docs: Fix typo in man smb.conf.
[Samba.git] / source3 / smbd / trans2.c
blobf58aacf4f344590f2ecb960740b33c5b951576e4
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
53 char *pdata,
54 files_struct *fsp,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
65 SMB_STRUCT_STAT sbuf;
66 const SMB_STRUCT_STAT *pst = NULL;
68 if (fsp) {
69 pst = &fsp->fsp_name->st;
70 } else {
71 pst = &smb_fname->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
76 smb_fname,
77 &sbuf);
78 if (ret == -1) {
79 return map_nt_error_from_unix(errno);
81 pst = &sbuf;
84 if (S_ISLNK(pst->st_ex_mode)) {
85 return NT_STATUS_ACCESS_DENIED;
87 return NT_STATUS_OK;
90 NTSTATUS check_access_fsp(const struct files_struct *fsp,
91 uint32_t access_mask)
93 if (!(fsp->access_mask & access_mask)) {
94 return NT_STATUS_ACCESS_DENIED;
96 return NT_STATUS_OK;
99 /********************************************************************
100 The canonical "check access" based on object handle or path function.
101 ********************************************************************/
103 NTSTATUS check_access(connection_struct *conn,
104 files_struct *fsp,
105 const struct smb_filename *smb_fname,
106 uint32_t access_mask)
108 NTSTATUS status;
110 if (fsp) {
111 status = check_access_fsp(fsp, access_mask);
112 } else {
113 status = smbd_check_access_rights(conn, smb_fname,
114 false, access_mask);
117 return status;
120 /********************************************************************
121 Roundup a value to the nearest allocation roundup size boundary.
122 Only do this for Windows clients.
123 ********************************************************************/
125 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
127 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
129 /* Only roundup for Windows clients. */
130 enum remote_arch_types ra_type = get_remote_arch();
131 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
132 val = SMB_ROUNDUP(val,rval);
134 return val;
137 /********************************************************************
138 Create a 64 bit FileIndex. If the file is on the same device as
139 the root of the share, just return the 64-bit inode. If it isn't,
140 mangle as we used to do.
141 ********************************************************************/
143 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
145 uint64_t file_index;
146 if (conn->base_share_dev == psbuf->st_ex_dev) {
147 return (uint64_t)psbuf->st_ex_ino;
149 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
150 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
151 return file_index;
154 /****************************************************************************
155 Utility functions for dealing with extended attributes.
156 ****************************************************************************/
158 /****************************************************************************
159 Refuse to allow clients to overwrite our private xattrs.
160 ****************************************************************************/
162 bool samba_private_attr_name(const char *unix_ea_name)
164 static const char * const prohibited_ea_names[] = {
165 SAMBA_POSIX_INHERITANCE_EA_NAME,
166 SAMBA_XATTR_DOS_ATTRIB,
167 SAMBA_XATTR_MARKER,
168 XATTR_NTACL_NAME,
169 NULL
172 int i;
174 for (i = 0; prohibited_ea_names[i]; i++) {
175 if (strequal( prohibited_ea_names[i], unix_ea_name))
176 return true;
178 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
179 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
180 return true;
182 return false;
185 /****************************************************************************
186 Get one EA value. Fill in a struct ea_struct.
187 ****************************************************************************/
189 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
190 files_struct *fsp, const char *fname,
191 const char *ea_name, struct ea_struct *pea)
193 /* Get the value of this xattr. Max size is 64k. */
194 size_t attr_size = 256;
195 char *val = NULL;
196 ssize_t sizeret;
198 again:
200 val = talloc_realloc(mem_ctx, val, char, attr_size);
201 if (!val) {
202 return NT_STATUS_NO_MEMORY;
205 if (fsp && fsp->fh->fd != -1) {
206 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
207 } else {
208 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
211 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
212 attr_size = 65536;
213 goto again;
216 if (sizeret == -1) {
217 return map_nt_error_from_unix(errno);
220 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
221 dump_data(10, (uint8_t *)val, sizeret);
223 pea->flags = 0;
224 if (strnequal(ea_name, "user.", 5)) {
225 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
226 } else {
227 pea->name = talloc_strdup(mem_ctx, ea_name);
229 if (pea->name == NULL) {
230 TALLOC_FREE(val);
231 return NT_STATUS_NO_MEMORY;
233 pea->value.data = (unsigned char *)val;
234 pea->value.length = (size_t)sizeret;
235 return NT_STATUS_OK;
238 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
239 connection_struct *conn,
240 files_struct *fsp,
241 const struct smb_filename *smb_fname,
242 char ***pnames,
243 size_t *pnum_names)
245 char smallbuf[1024];
246 /* Get a list of all xattrs. Max namesize is 64k. */
247 size_t ea_namelist_size = 1024;
248 char *ea_namelist = smallbuf;
249 char *to_free = NULL;
251 char *p;
252 char **names;
253 size_t num_names;
254 ssize_t sizeret = -1;
255 NTSTATUS status;
257 if (pnames) {
258 *pnames = NULL;
260 *pnum_names = 0;
262 if (!lp_ea_support(SNUM(conn))) {
263 return NT_STATUS_OK;
266 status = refuse_symlink(conn, fsp, smb_fname);
267 if (!NT_STATUS_IS_OK(status)) {
269 * Just return no EA's on a symlink.
271 return NT_STATUS_OK;
274 if (fsp && fsp->fh->fd != -1) {
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
276 ea_namelist_size);
277 } else {
278 sizeret = SMB_VFS_LISTXATTR(conn,
279 smb_fname->base_name,
280 ea_namelist,
281 ea_namelist_size);
284 if ((sizeret == -1) && (errno == ERANGE)) {
285 ea_namelist_size = 65536;
286 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
287 if (ea_namelist == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 to_free = ea_namelist;
292 if (fsp && fsp->fh->fd != -1) {
293 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
294 ea_namelist_size);
295 } else {
296 sizeret = SMB_VFS_LISTXATTR(conn,
297 smb_fname->base_name,
298 ea_namelist,
299 ea_namelist_size);
303 if (sizeret == -1) {
304 status = map_nt_error_from_unix(errno);
305 TALLOC_FREE(to_free);
306 return status;
309 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
311 if (sizeret == 0) {
312 TALLOC_FREE(to_free);
313 return NT_STATUS_OK;
317 * Ensure the result is 0-terminated
320 if (ea_namelist[sizeret-1] != '\0') {
321 TALLOC_FREE(to_free);
322 return NT_STATUS_INTERNAL_ERROR;
326 * count the names
328 num_names = 0;
330 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
331 num_names += 1;
334 *pnum_names = num_names;
336 if (pnames == NULL) {
337 TALLOC_FREE(to_free);
338 return NT_STATUS_OK;
341 names = talloc_array(mem_ctx, char *, num_names);
342 if (names == NULL) {
343 DEBUG(0, ("talloc failed\n"));
344 TALLOC_FREE(to_free);
345 return NT_STATUS_NO_MEMORY;
348 if (ea_namelist == smallbuf) {
349 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
350 if (ea_namelist == NULL) {
351 TALLOC_FREE(names);
352 return NT_STATUS_NO_MEMORY;
354 } else {
355 talloc_steal(names, ea_namelist);
357 ea_namelist = talloc_realloc(names, ea_namelist, char,
358 sizeret);
359 if (ea_namelist == NULL) {
360 TALLOC_FREE(names);
361 return NT_STATUS_NO_MEMORY;
365 num_names = 0;
367 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
368 names[num_names++] = p;
371 *pnames = names;
373 return NT_STATUS_OK;
376 /****************************************************************************
377 Return a linked list of the total EA's. Plus the total size
378 ****************************************************************************/
380 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
381 connection_struct *conn,
382 files_struct *fsp,
383 const struct smb_filename *smb_fname,
384 size_t *pea_total_len,
385 struct ea_list **ea_list)
387 /* Get a list of all xattrs. Max namesize is 64k. */
388 size_t i, num_names;
389 char **names;
390 struct ea_list *ea_list_head = NULL;
391 bool posix_pathnames = false;
392 NTSTATUS status;
394 *pea_total_len = 0;
395 *ea_list = NULL;
397 if (fsp) {
398 posix_pathnames =
399 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
400 } else {
401 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
404 status = get_ea_names_from_file(talloc_tos(),
405 conn,
406 fsp,
407 smb_fname,
408 &names,
409 &num_names);
411 if (!NT_STATUS_IS_OK(status)) {
412 return status;
415 if (num_names == 0) {
416 *ea_list = NULL;
417 return NT_STATUS_OK;
420 for (i=0; i<num_names; i++) {
421 struct ea_list *listp;
422 fstring dos_ea_name;
424 if (strnequal(names[i], "system.", 7)
425 || samba_private_attr_name(names[i]))
426 continue;
429 * Filter out any underlying POSIX EA names
430 * that a Windows client can't handle.
432 if (!posix_pathnames &&
433 is_invalid_windows_ea_name(names[i])) {
434 continue;
437 listp = talloc(mem_ctx, struct ea_list);
438 if (listp == NULL) {
439 return NT_STATUS_NO_MEMORY;
442 status = get_ea_value(listp,
443 conn,
444 fsp,
445 smb_fname->base_name,
446 names[i],
447 &listp->ea);
449 if (!NT_STATUS_IS_OK(status)) {
450 TALLOC_FREE(listp);
451 return status;
454 if (listp->ea.value.length == 0) {
456 * We can never return a zero length EA.
457 * Windows reports the EA's as corrupted.
459 TALLOC_FREE(listp);
460 continue;
463 push_ascii_fstring(dos_ea_name, listp->ea.name);
465 *pea_total_len +=
466 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
468 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
469 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
470 (unsigned int)listp->ea.value.length));
472 DLIST_ADD_END(ea_list_head, listp);
476 /* Add on 4 for total length. */
477 if (*pea_total_len) {
478 *pea_total_len += 4;
481 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
482 (unsigned int)*pea_total_len));
484 *ea_list = ea_list_head;
485 return NT_STATUS_OK;
488 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
489 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
491 *pea_total_len = 0;
492 *ea_list = NULL;
494 if (!lp_ea_support(SNUM(conn))) {
495 return NT_STATUS_OK;
498 if (is_ntfs_stream_smb_fname(smb_fname)) {
499 return NT_STATUS_INVALID_PARAMETER;
502 return get_ea_list_from_file_path(mem_ctx,
503 conn,
504 fsp,
505 smb_fname,
506 pea_total_len,
507 ea_list);
510 /****************************************************************************
511 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
512 that was filled.
513 ****************************************************************************/
515 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
516 connection_struct *conn, struct ea_list *ea_list)
518 unsigned int ret_data_size = 4;
519 char *p = pdata;
521 SMB_ASSERT(total_data_size >= 4);
523 if (!lp_ea_support(SNUM(conn))) {
524 SIVAL(pdata,4,0);
525 return 4;
528 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
529 size_t dos_namelen;
530 fstring dos_ea_name;
531 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
532 dos_namelen = strlen(dos_ea_name);
533 if (dos_namelen > 255 || dos_namelen == 0) {
534 break;
536 if (ea_list->ea.value.length > 65535) {
537 break;
539 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
540 break;
543 /* We know we have room. */
544 SCVAL(p,0,ea_list->ea.flags);
545 SCVAL(p,1,dos_namelen);
546 SSVAL(p,2,ea_list->ea.value.length);
547 strlcpy(p+4, dos_ea_name, dos_namelen+1);
548 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
550 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
551 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
554 ret_data_size = PTR_DIFF(p, pdata);
555 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
556 SIVAL(pdata,0,ret_data_size);
557 return ret_data_size;
560 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
561 char *pdata,
562 unsigned int total_data_size,
563 unsigned int *ret_data_size,
564 connection_struct *conn,
565 struct ea_list *ea_list)
567 uint8_t *p = (uint8_t *)pdata;
568 uint8_t *last_start = NULL;
569 bool do_store_data = (pdata != NULL);
571 *ret_data_size = 0;
573 if (!lp_ea_support(SNUM(conn))) {
574 return NT_STATUS_NO_EAS_ON_FILE;
577 for (; ea_list; ea_list = ea_list->next) {
578 size_t dos_namelen;
579 fstring dos_ea_name;
580 size_t this_size;
581 size_t pad = 0;
583 if (last_start != NULL && do_store_data) {
584 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
586 last_start = p;
588 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
589 dos_namelen = strlen(dos_ea_name);
590 if (dos_namelen > 255 || dos_namelen == 0) {
591 return NT_STATUS_INTERNAL_ERROR;
593 if (ea_list->ea.value.length > 65535) {
594 return NT_STATUS_INTERNAL_ERROR;
597 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
599 if (ea_list->next) {
600 pad = (4 - (this_size % 4)) % 4;
601 this_size += pad;
604 if (do_store_data) {
605 if (this_size > total_data_size) {
606 return NT_STATUS_INFO_LENGTH_MISMATCH;
609 /* We know we have room. */
610 SIVAL(p, 0x00, 0); /* next offset */
611 SCVAL(p, 0x04, ea_list->ea.flags);
612 SCVAL(p, 0x05, dos_namelen);
613 SSVAL(p, 0x06, ea_list->ea.value.length);
614 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
615 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
616 if (pad) {
617 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
618 '\0',
619 pad);
621 total_data_size -= this_size;
624 p += this_size;
627 *ret_data_size = PTR_DIFF(p, pdata);
628 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
629 return NT_STATUS_OK;
632 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
634 size_t total_ea_len = 0;
635 TALLOC_CTX *mem_ctx;
636 struct ea_list *ea_list = NULL;
638 if (!lp_ea_support(SNUM(conn))) {
639 return 0;
641 mem_ctx = talloc_stackframe();
643 /* If this is a stream fsp, then we need to instead find the
644 * estimated ea len from the main file, not the stream
645 * (streams cannot have EAs), but the estimate isn't just 0 in
646 * this case! */
647 if (is_ntfs_stream_smb_fname(smb_fname)) {
648 fsp = NULL;
650 (void)get_ea_list_from_file_path(mem_ctx,
651 conn,
652 fsp,
653 smb_fname,
654 &total_ea_len,
655 &ea_list);
656 if(conn->sconn->using_smb2) {
657 NTSTATUS status;
658 unsigned int ret_data_size;
660 * We're going to be using fill_ea_chained_buffer() to
661 * marshall EA's - this size is significantly larger
662 * than the SMB1 buffer. Re-calculate the size without
663 * marshalling.
665 status = fill_ea_chained_buffer(mem_ctx,
666 NULL,
668 &ret_data_size,
669 conn,
670 ea_list);
671 if (!NT_STATUS_IS_OK(status)) {
672 ret_data_size = 0;
674 total_ea_len = ret_data_size;
676 TALLOC_FREE(mem_ctx);
677 return total_ea_len;
680 /****************************************************************************
681 Ensure the EA name is case insensitive by matching any existing EA name.
682 ****************************************************************************/
684 static void canonicalize_ea_name(connection_struct *conn,
685 files_struct *fsp,
686 const struct smb_filename *smb_fname,
687 fstring unix_ea_name)
689 size_t total_ea_len;
690 TALLOC_CTX *mem_ctx = talloc_tos();
691 struct ea_list *ea_list;
692 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
693 conn,
694 fsp,
695 smb_fname,
696 &total_ea_len,
697 &ea_list);
698 if (!NT_STATUS_IS_OK(status)) {
699 return;
702 for (; ea_list; ea_list = ea_list->next) {
703 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
704 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
705 &unix_ea_name[5], ea_list->ea.name));
706 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
707 break;
712 /****************************************************************************
713 Set or delete an extended attribute.
714 ****************************************************************************/
716 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
717 const struct smb_filename *smb_fname, struct ea_list *ea_list)
719 NTSTATUS status;
720 bool posix_pathnames = false;
722 if (!lp_ea_support(SNUM(conn))) {
723 return NT_STATUS_EAS_NOT_SUPPORTED;
726 if (fsp) {
727 posix_pathnames =
728 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
729 } else {
730 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
733 status = refuse_symlink(conn, fsp, smb_fname);
734 if (!NT_STATUS_IS_OK(status)) {
735 return status;
738 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
739 if (!NT_STATUS_IS_OK(status)) {
740 return status;
743 /* Setting EAs on streams isn't supported. */
744 if (is_ntfs_stream_smb_fname(smb_fname)) {
745 return NT_STATUS_INVALID_PARAMETER;
749 * Filter out invalid Windows EA names - before
750 * we set *any* of them.
753 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
754 return STATUS_INVALID_EA_NAME;
757 for (;ea_list; ea_list = ea_list->next) {
758 int ret;
759 fstring unix_ea_name;
761 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
762 fstrcat(unix_ea_name, ea_list->ea.name);
764 canonicalize_ea_name(conn,
765 fsp,
766 smb_fname,
767 unix_ea_name);
769 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
771 if (samba_private_attr_name(unix_ea_name)) {
772 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
773 return NT_STATUS_ACCESS_DENIED;
776 if (ea_list->ea.value.length == 0) {
777 /* Remove the attribute. */
778 if (fsp && (fsp->fh->fd != -1)) {
779 DEBUG(10,("set_ea: deleting ea name %s on "
780 "file %s by file descriptor.\n",
781 unix_ea_name, fsp_str_dbg(fsp)));
782 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
783 } else {
784 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
785 unix_ea_name, smb_fname->base_name));
786 ret = SMB_VFS_REMOVEXATTR(conn,
787 smb_fname->base_name,
788 unix_ea_name);
790 #ifdef ENOATTR
791 /* Removing a non existent attribute always succeeds. */
792 if (ret == -1 && errno == ENOATTR) {
793 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
794 unix_ea_name));
795 ret = 0;
797 #endif
798 } else {
799 if (fsp && (fsp->fh->fd != -1)) {
800 DEBUG(10,("set_ea: setting ea name %s on file "
801 "%s by file descriptor.\n",
802 unix_ea_name, fsp_str_dbg(fsp)));
803 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
804 ea_list->ea.value.data, ea_list->ea.value.length, 0);
805 } else {
806 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
807 unix_ea_name, smb_fname->base_name));
808 ret = SMB_VFS_SETXATTR(conn,
809 smb_fname->base_name,
810 unix_ea_name,
811 ea_list->ea.value.data,
812 ea_list->ea.value.length,
817 if (ret == -1) {
818 #ifdef ENOTSUP
819 if (errno == ENOTSUP) {
820 return NT_STATUS_EAS_NOT_SUPPORTED;
822 #endif
823 return map_nt_error_from_unix(errno);
827 return NT_STATUS_OK;
829 /****************************************************************************
830 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
831 ****************************************************************************/
833 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
835 struct ea_list *ea_list_head = NULL;
836 size_t converted_size, offset = 0;
838 while (offset + 2 < data_size) {
839 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
840 unsigned int namelen = CVAL(pdata,offset);
842 offset++; /* Go past the namelen byte. */
844 /* integer wrap paranioa. */
845 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
846 (offset > data_size) || (namelen > data_size) ||
847 (offset + namelen >= data_size)) {
848 break;
850 /* Ensure the name is null terminated. */
851 if (pdata[offset + namelen] != '\0') {
852 return NULL;
854 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
855 &converted_size)) {
856 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
857 "failed: %s", strerror(errno)));
859 if (!eal->ea.name) {
860 return NULL;
863 offset += (namelen + 1); /* Go past the name + terminating zero. */
864 DLIST_ADD_END(ea_list_head, eal);
865 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
868 return ea_list_head;
871 /****************************************************************************
872 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
873 ****************************************************************************/
875 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
877 struct ea_list *ea_list_head = NULL;
878 size_t offset = 0;
879 size_t bytes_used = 0;
881 while (offset < data_size) {
882 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
884 if (!eal) {
885 return NULL;
888 DLIST_ADD_END(ea_list_head, eal);
889 offset += bytes_used;
892 return ea_list_head;
895 /****************************************************************************
896 Count the total EA size needed.
897 ****************************************************************************/
899 static size_t ea_list_size(struct ea_list *ealist)
901 fstring dos_ea_name;
902 struct ea_list *listp;
903 size_t ret = 0;
905 for (listp = ealist; listp; listp = listp->next) {
906 push_ascii_fstring(dos_ea_name, listp->ea.name);
907 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
909 /* Add on 4 for total length. */
910 if (ret) {
911 ret += 4;
914 return ret;
917 /****************************************************************************
918 Return a union of EA's from a file list and a list of names.
919 The TALLOC context for the two lists *MUST* be identical as we steal
920 memory from one list to add to another. JRA.
921 ****************************************************************************/
923 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
925 struct ea_list *nlistp, *flistp;
927 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
928 for (flistp = file_list; flistp; flistp = flistp->next) {
929 if (strequal(nlistp->ea.name, flistp->ea.name)) {
930 break;
934 if (flistp) {
935 /* Copy the data from this entry. */
936 nlistp->ea.flags = flistp->ea.flags;
937 nlistp->ea.value = flistp->ea.value;
938 } else {
939 /* Null entry. */
940 nlistp->ea.flags = 0;
941 ZERO_STRUCT(nlistp->ea.value);
945 *total_ea_len = ea_list_size(name_list);
946 return name_list;
949 /****************************************************************************
950 Send the required number of replies back.
951 We assume all fields other than the data fields are
952 set correctly for the type of call.
953 HACK ! Always assumes smb_setup field is zero.
954 ****************************************************************************/
956 void send_trans2_replies(connection_struct *conn,
957 struct smb_request *req,
958 NTSTATUS status,
959 const char *params,
960 int paramsize,
961 const char *pdata,
962 int datasize,
963 int max_data_bytes)
965 /* As we are using a protocol > LANMAN1 then the max_send
966 variable must have been set in the sessetupX call.
967 This takes precedence over the max_xmit field in the
968 global struct. These different max_xmit variables should
969 be merged as this is now too confusing */
971 int data_to_send = datasize;
972 int params_to_send = paramsize;
973 int useable_space;
974 const char *pp = params;
975 const char *pd = pdata;
976 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
977 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
978 int data_alignment_offset = 0;
979 bool overflow = False;
980 struct smbXsrv_connection *xconn = req->xconn;
981 int max_send = xconn->smb1.sessions.max_send;
983 /* Modify the data_to_send and datasize and set the error if
984 we're trying to send more than max_data_bytes. We still send
985 the part of the packet(s) that fit. Strange, but needed
986 for OS/2. */
988 if (max_data_bytes > 0 && datasize > max_data_bytes) {
989 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
990 max_data_bytes, datasize ));
991 datasize = data_to_send = max_data_bytes;
992 overflow = True;
995 /* If there genuinely are no parameters or data to send just send the empty packet */
997 if(params_to_send == 0 && data_to_send == 0) {
998 reply_outbuf(req, 10, 0);
999 if (NT_STATUS_V(status)) {
1000 uint8_t eclass;
1001 uint32_t ecode;
1002 ntstatus_to_dos(status, &eclass, &ecode);
1003 error_packet_set((char *)req->outbuf,
1004 eclass, ecode, status,
1005 __LINE__,__FILE__);
1007 show_msg((char *)req->outbuf);
1008 if (!srv_send_smb(xconn,
1009 (char *)req->outbuf,
1010 true, req->seqnum+1,
1011 IS_CONN_ENCRYPTED(conn),
1012 &req->pcd)) {
1013 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1015 TALLOC_FREE(req->outbuf);
1016 return;
1019 /* When sending params and data ensure that both are nicely aligned */
1020 /* Only do this alignment when there is also data to send - else
1021 can cause NT redirector problems. */
1023 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1024 data_alignment_offset = 4 - (params_to_send % 4);
1026 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1027 /* The alignment_offset is to align the param bytes on an even byte
1028 boundary. NT 4.0 Beta needs this to work correctly. */
1030 useable_space = max_send - (smb_size
1031 + 2 * 10 /* wct */
1032 + alignment_offset
1033 + data_alignment_offset);
1035 if (useable_space < 0) {
1036 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1037 "= %d!!!", useable_space));
1038 exit_server_cleanly("send_trans2_replies: Not enough space");
1041 while (params_to_send || data_to_send) {
1042 /* Calculate whether we will totally or partially fill this packet */
1044 total_sent_thistime = params_to_send + data_to_send;
1046 /* We can never send more than useable_space */
1048 * Note that 'useable_space' does not include the alignment offsets,
1049 * but we must include the alignment offsets in the calculation of
1050 * the length of the data we send over the wire, as the alignment offsets
1051 * are sent here. Fix from Marc_Jacobsen@hp.com.
1054 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1056 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1057 + data_alignment_offset);
1059 /* Set total params and data to be sent */
1060 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1061 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1063 /* Calculate how many parameters and data we can fit into
1064 * this packet. Parameters get precedence
1067 params_sent_thistime = MIN(params_to_send,useable_space);
1068 data_sent_thistime = useable_space - params_sent_thistime;
1069 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1071 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1073 /* smb_proff is the offset from the start of the SMB header to the
1074 parameter bytes, however the first 4 bytes of outbuf are
1075 the Netbios over TCP header. Thus use smb_base() to subtract
1076 them from the calculation */
1078 SSVAL(req->outbuf,smb_proff,
1079 ((smb_buf(req->outbuf)+alignment_offset)
1080 - smb_base(req->outbuf)));
1082 if(params_sent_thistime == 0)
1083 SSVAL(req->outbuf,smb_prdisp,0);
1084 else
1085 /* Absolute displacement of param bytes sent in this packet */
1086 SSVAL(req->outbuf,smb_prdisp,pp - params);
1088 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1089 if(data_sent_thistime == 0) {
1090 SSVAL(req->outbuf,smb_droff,0);
1091 SSVAL(req->outbuf,smb_drdisp, 0);
1092 } else {
1093 /* The offset of the data bytes is the offset of the
1094 parameter bytes plus the number of parameters being sent this time */
1095 SSVAL(req->outbuf, smb_droff,
1096 ((smb_buf(req->outbuf)+alignment_offset)
1097 - smb_base(req->outbuf))
1098 + params_sent_thistime + data_alignment_offset);
1099 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1102 /* Initialize the padding for alignment */
1104 if (alignment_offset != 0) {
1105 memset(smb_buf(req->outbuf), 0, alignment_offset);
1108 /* Copy the param bytes into the packet */
1110 if(params_sent_thistime) {
1111 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1112 params_sent_thistime);
1115 /* Copy in the data bytes */
1116 if(data_sent_thistime) {
1117 if (data_alignment_offset != 0) {
1118 memset((smb_buf(req->outbuf)+alignment_offset+
1119 params_sent_thistime), 0,
1120 data_alignment_offset);
1122 memcpy(smb_buf(req->outbuf)+alignment_offset
1123 +params_sent_thistime+data_alignment_offset,
1124 pd,data_sent_thistime);
1127 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1128 params_sent_thistime, data_sent_thistime, useable_space));
1129 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1130 params_to_send, data_to_send, paramsize, datasize));
1132 if (overflow) {
1133 error_packet_set((char *)req->outbuf,
1134 ERRDOS,ERRbufferoverflow,
1135 STATUS_BUFFER_OVERFLOW,
1136 __LINE__,__FILE__);
1137 } else if (NT_STATUS_V(status)) {
1138 uint8_t eclass;
1139 uint32_t ecode;
1140 ntstatus_to_dos(status, &eclass, &ecode);
1141 error_packet_set((char *)req->outbuf,
1142 eclass, ecode, status,
1143 __LINE__,__FILE__);
1146 /* Send the packet */
1147 show_msg((char *)req->outbuf);
1148 if (!srv_send_smb(xconn,
1149 (char *)req->outbuf,
1150 true, req->seqnum+1,
1151 IS_CONN_ENCRYPTED(conn),
1152 &req->pcd))
1153 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1155 TALLOC_FREE(req->outbuf);
1157 pp += params_sent_thistime;
1158 pd += data_sent_thistime;
1160 params_to_send -= params_sent_thistime;
1161 data_to_send -= data_sent_thistime;
1163 /* Sanity check */
1164 if(params_to_send < 0 || data_to_send < 0) {
1165 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1166 params_to_send, data_to_send));
1167 return;
1171 return;
1174 /****************************************************************************
1175 Reply to a TRANSACT2_OPEN.
1176 ****************************************************************************/
1178 static void call_trans2open(connection_struct *conn,
1179 struct smb_request *req,
1180 char **pparams, int total_params,
1181 char **ppdata, int total_data,
1182 unsigned int max_data_bytes)
1184 struct smb_filename *smb_fname = NULL;
1185 char *params = *pparams;
1186 char *pdata = *ppdata;
1187 int deny_mode;
1188 int32_t open_attr;
1189 bool oplock_request;
1190 #if 0
1191 bool return_additional_info;
1192 int16 open_sattr;
1193 time_t open_time;
1194 #endif
1195 int open_ofun;
1196 uint32_t open_size;
1197 char *pname;
1198 char *fname = NULL;
1199 off_t size=0;
1200 int fattr=0,mtime=0;
1201 SMB_INO_T inode = 0;
1202 int smb_action = 0;
1203 files_struct *fsp;
1204 struct ea_list *ea_list = NULL;
1205 uint16_t flags = 0;
1206 NTSTATUS status;
1207 uint32_t access_mask;
1208 uint32_t share_mode;
1209 uint32_t create_disposition;
1210 uint32_t create_options = 0;
1211 uint32_t private_flags = 0;
1212 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1213 TALLOC_CTX *ctx = talloc_tos();
1216 * Ensure we have enough parameters to perform the operation.
1219 if (total_params < 29) {
1220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1221 goto out;
1224 flags = SVAL(params, 0);
1225 deny_mode = SVAL(params, 2);
1226 open_attr = SVAL(params,6);
1227 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1228 if (oplock_request) {
1229 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1232 #if 0
1233 return_additional_info = BITSETW(params,0);
1234 open_sattr = SVAL(params, 4);
1235 open_time = make_unix_date3(params+8);
1236 #endif
1237 open_ofun = SVAL(params,12);
1238 open_size = IVAL(params,14);
1239 pname = &params[28];
1241 if (IS_IPC(conn)) {
1242 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1243 goto out;
1246 if (req->posix_pathnames) {
1247 srvstr_get_path_posix(ctx,
1248 params,
1249 req->flags2,
1250 &fname,
1251 pname,
1252 total_params - 28,
1253 STR_TERMINATE,
1254 &status);
1255 } else {
1256 srvstr_get_path(ctx,
1257 params,
1258 req->flags2,
1259 &fname,
1260 pname,
1261 total_params - 28,
1262 STR_TERMINATE,
1263 &status);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1267 goto out;
1270 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1271 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1272 (unsigned int)open_ofun, open_size));
1274 status = filename_convert(ctx,
1275 conn,
1276 req->flags2 & FLAGS2_DFS_PATHNAMES,
1277 fname,
1278 ucf_flags,
1279 NULL,
1280 &smb_fname);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1283 reply_botherror(req,
1284 NT_STATUS_PATH_NOT_COVERED,
1285 ERRSRV, ERRbadpath);
1286 goto out;
1288 reply_nterror(req, status);
1289 goto out;
1292 if (open_ofun == 0) {
1293 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1294 goto out;
1297 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1298 open_ofun,
1299 &access_mask, &share_mode,
1300 &create_disposition,
1301 &create_options,
1302 &private_flags)) {
1303 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1304 goto out;
1307 /* Any data in this call is an EA list. */
1308 if (total_data && (total_data != 4)) {
1309 if (total_data < 10) {
1310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1311 goto out;
1314 if (IVAL(pdata,0) > total_data) {
1315 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1316 IVAL(pdata,0), (unsigned int)total_data));
1317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1318 goto out;
1321 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1322 total_data - 4);
1323 if (!ea_list) {
1324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1325 goto out;
1328 if (!lp_ea_support(SNUM(conn))) {
1329 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1330 goto out;
1333 if (!req->posix_pathnames &&
1334 ea_list_has_invalid_name(ea_list)) {
1335 int param_len = 30;
1336 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1337 if(*pparams == NULL ) {
1338 reply_nterror(req, NT_STATUS_NO_MEMORY);
1339 goto out;
1341 params = *pparams;
1342 memset(params, '\0', param_len);
1343 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1344 params, param_len, NULL, 0, max_data_bytes);
1345 goto out;
1349 status = SMB_VFS_CREATE_FILE(
1350 conn, /* conn */
1351 req, /* req */
1352 0, /* root_dir_fid */
1353 smb_fname, /* fname */
1354 access_mask, /* access_mask */
1355 share_mode, /* share_access */
1356 create_disposition, /* create_disposition*/
1357 create_options, /* create_options */
1358 open_attr, /* file_attributes */
1359 oplock_request, /* oplock_request */
1360 NULL, /* lease */
1361 open_size, /* allocation_size */
1362 private_flags,
1363 NULL, /* sd */
1364 ea_list, /* ea_list */
1365 &fsp, /* result */
1366 &smb_action, /* psbuf */
1367 NULL, NULL); /* create context */
1369 if (!NT_STATUS_IS_OK(status)) {
1370 if (open_was_deferred(req->xconn, req->mid)) {
1371 /* We have re-scheduled this call. */
1372 goto out;
1374 reply_openerror(req, status);
1375 goto out;
1378 size = get_file_size_stat(&smb_fname->st);
1379 fattr = dos_mode(conn, smb_fname);
1380 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1381 inode = smb_fname->st.st_ex_ino;
1382 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1383 close_file(req, fsp, ERROR_CLOSE);
1384 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1385 goto out;
1388 /* Realloc the size of parameters and data we will return */
1389 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1390 if(*pparams == NULL ) {
1391 reply_nterror(req, NT_STATUS_NO_MEMORY);
1392 goto out;
1394 params = *pparams;
1396 SSVAL(params,0,fsp->fnum);
1397 SSVAL(params,2,fattr);
1398 srv_put_dos_date2(params,4, mtime);
1399 SIVAL(params,8, (uint32_t)size);
1400 SSVAL(params,12,deny_mode);
1401 SSVAL(params,14,0); /* open_type - file or directory. */
1402 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1404 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1405 smb_action |= EXTENDED_OPLOCK_GRANTED;
1408 SSVAL(params,18,smb_action);
1411 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1413 SIVAL(params,20,inode);
1414 SSVAL(params,24,0); /* Padding. */
1415 if (flags & 8) {
1416 uint32_t ea_size = estimate_ea_size(conn, fsp,
1417 smb_fname);
1418 SIVAL(params, 26, ea_size);
1419 } else {
1420 SIVAL(params, 26, 0);
1423 /* Send the required number of replies */
1424 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1425 out:
1426 TALLOC_FREE(smb_fname);
1429 /*********************************************************
1430 Routine to check if a given string matches exactly.
1431 as a special case a mask of "." does NOT match. That
1432 is required for correct wildcard semantics
1433 Case can be significant or not.
1434 **********************************************************/
1436 static bool exact_match(bool has_wild,
1437 bool case_sensitive,
1438 const char *str,
1439 const char *mask)
1441 if (mask[0] == '.' && mask[1] == 0) {
1442 return false;
1445 if (has_wild) {
1446 return false;
1449 if (case_sensitive) {
1450 return strcmp(str,mask)==0;
1451 } else {
1452 return strcasecmp_m(str,mask) == 0;
1456 /****************************************************************************
1457 Return the filetype for UNIX extensions.
1458 ****************************************************************************/
1460 static uint32_t unix_filetype(mode_t mode)
1462 if(S_ISREG(mode))
1463 return UNIX_TYPE_FILE;
1464 else if(S_ISDIR(mode))
1465 return UNIX_TYPE_DIR;
1466 #ifdef S_ISLNK
1467 else if(S_ISLNK(mode))
1468 return UNIX_TYPE_SYMLINK;
1469 #endif
1470 #ifdef S_ISCHR
1471 else if(S_ISCHR(mode))
1472 return UNIX_TYPE_CHARDEV;
1473 #endif
1474 #ifdef S_ISBLK
1475 else if(S_ISBLK(mode))
1476 return UNIX_TYPE_BLKDEV;
1477 #endif
1478 #ifdef S_ISFIFO
1479 else if(S_ISFIFO(mode))
1480 return UNIX_TYPE_FIFO;
1481 #endif
1482 #ifdef S_ISSOCK
1483 else if(S_ISSOCK(mode))
1484 return UNIX_TYPE_SOCKET;
1485 #endif
1487 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1488 return UNIX_TYPE_UNKNOWN;
1491 /****************************************************************************
1492 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1493 ****************************************************************************/
1495 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1497 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1498 const SMB_STRUCT_STAT *psbuf,
1499 uint32_t perms,
1500 enum perm_type ptype,
1501 mode_t *ret_perms)
1503 mode_t ret = 0;
1505 if (perms == SMB_MODE_NO_CHANGE) {
1506 if (!VALID_STAT(*psbuf)) {
1507 return NT_STATUS_INVALID_PARAMETER;
1508 } else {
1509 *ret_perms = psbuf->st_ex_mode;
1510 return NT_STATUS_OK;
1514 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1515 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1516 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1517 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1518 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1519 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1520 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1521 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1522 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1523 #ifdef S_ISVTX
1524 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1525 #endif
1526 #ifdef S_ISGID
1527 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1528 #endif
1529 #ifdef S_ISUID
1530 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1531 #endif
1533 if (ptype == PERM_NEW_FILE) {
1535 * "create mask"/"force create mode" are
1536 * only applied to new files, not existing ones.
1538 ret &= lp_create_mask(SNUM(conn));
1539 /* Add in force bits */
1540 ret |= lp_force_create_mode(SNUM(conn));
1541 } else if (ptype == PERM_NEW_DIR) {
1543 * "directory mask"/"force directory mode" are
1544 * only applied to new directories, not existing ones.
1546 ret &= lp_directory_mask(SNUM(conn));
1547 /* Add in force bits */
1548 ret |= lp_force_directory_mode(SNUM(conn));
1551 *ret_perms = ret;
1552 return NT_STATUS_OK;
1555 /****************************************************************************
1556 Needed to show the msdfs symlinks as directories. Modifies psbuf
1557 to be a directory if it's a msdfs link.
1558 ****************************************************************************/
1560 static bool check_msdfs_link(connection_struct *conn,
1561 const char *pathname,
1562 SMB_STRUCT_STAT *psbuf)
1564 int saved_errno = errno;
1565 if(lp_host_msdfs() &&
1566 lp_msdfs_root(SNUM(conn)) &&
1567 is_msdfs_link(conn, pathname, psbuf)) {
1569 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1570 "as a directory\n",
1571 pathname));
1572 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1573 errno = saved_errno;
1574 return true;
1576 errno = saved_errno;
1577 return false;
1581 /****************************************************************************
1582 Get a level dependent lanman2 dir entry.
1583 ****************************************************************************/
1585 struct smbd_dirptr_lanman2_state {
1586 connection_struct *conn;
1587 uint32_t info_level;
1588 bool check_mangled_names;
1589 bool has_wild;
1590 bool got_exact_match;
1593 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1594 void *private_data,
1595 const char *dname,
1596 const char *mask,
1597 char **_fname)
1599 struct smbd_dirptr_lanman2_state *state =
1600 (struct smbd_dirptr_lanman2_state *)private_data;
1601 bool ok;
1602 char mangled_name[13]; /* mangled 8.3 name. */
1603 bool got_match;
1604 const char *fname;
1606 /* Mangle fname if it's an illegal name. */
1607 if (mangle_must_mangle(dname, state->conn->params)) {
1609 * Slow path - ensure we can push the original name as UCS2. If
1610 * not, then just don't return this name.
1612 NTSTATUS status;
1613 size_t ret_len = 0;
1614 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1615 uint8_t *tmp = talloc_array(talloc_tos(),
1616 uint8_t,
1617 len);
1619 status = srvstr_push(NULL,
1620 FLAGS2_UNICODE_STRINGS,
1621 tmp,
1622 dname,
1623 len,
1624 STR_TERMINATE,
1625 &ret_len);
1627 TALLOC_FREE(tmp);
1629 if (!NT_STATUS_IS_OK(status)) {
1630 return false;
1633 ok = name_to_8_3(dname, mangled_name,
1634 true, state->conn->params);
1635 if (!ok) {
1636 return false;
1638 fname = mangled_name;
1639 } else {
1640 fname = dname;
1643 got_match = exact_match(state->has_wild,
1644 state->conn->case_sensitive,
1645 fname, mask);
1646 state->got_exact_match = got_match;
1647 if (!got_match) {
1648 got_match = mask_match(fname, mask,
1649 state->conn->case_sensitive);
1652 if(!got_match && state->check_mangled_names &&
1653 !mangle_is_8_3(fname, false, state->conn->params)) {
1655 * It turns out that NT matches wildcards against
1656 * both long *and* short names. This may explain some
1657 * of the wildcard wierdness from old DOS clients
1658 * that some people have been seeing.... JRA.
1660 /* Force the mangling into 8.3. */
1661 ok = name_to_8_3(fname, mangled_name,
1662 false, state->conn->params);
1663 if (!ok) {
1664 return false;
1667 got_match = exact_match(state->has_wild,
1668 state->conn->case_sensitive,
1669 mangled_name, mask);
1670 state->got_exact_match = got_match;
1671 if (!got_match) {
1672 got_match = mask_match(mangled_name, mask,
1673 state->conn->case_sensitive);
1677 if (!got_match) {
1678 return false;
1681 *_fname = talloc_strdup(ctx, fname);
1682 if (*_fname == NULL) {
1683 return false;
1686 return true;
1689 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1690 void *private_data,
1691 struct smb_filename *smb_fname,
1692 uint32_t *_mode)
1694 struct smbd_dirptr_lanman2_state *state =
1695 (struct smbd_dirptr_lanman2_state *)private_data;
1696 bool ms_dfs_link = false;
1697 uint32_t mode = 0;
1699 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1700 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1701 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1702 "Couldn't lstat [%s] (%s)\n",
1703 smb_fname_str_dbg(smb_fname),
1704 strerror(errno)));
1705 return false;
1707 } else if (!VALID_STAT(smb_fname->st) &&
1708 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1709 /* Needed to show the msdfs symlinks as
1710 * directories */
1712 ms_dfs_link = check_msdfs_link(state->conn,
1713 smb_fname->base_name,
1714 &smb_fname->st);
1715 if (!ms_dfs_link) {
1716 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1717 "Couldn't stat [%s] (%s)\n",
1718 smb_fname_str_dbg(smb_fname),
1719 strerror(errno)));
1720 return false;
1724 if (ms_dfs_link) {
1725 mode = dos_mode_msdfs(state->conn, smb_fname);
1726 } else {
1727 mode = dos_mode(state->conn, smb_fname);
1730 *_mode = mode;
1731 return true;
1734 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1735 connection_struct *conn,
1736 uint16_t flags2,
1737 uint32_t info_level,
1738 struct ea_list *name_list,
1739 bool check_mangled_names,
1740 bool requires_resume_key,
1741 uint32_t mode,
1742 const char *fname,
1743 const struct smb_filename *smb_fname,
1744 int space_remaining,
1745 uint8_t align,
1746 bool do_pad,
1747 char *base_data,
1748 char **ppdata,
1749 char *end_data,
1750 uint64_t *last_entry_off)
1752 char *p, *q, *pdata = *ppdata;
1753 uint32_t reskey=0;
1754 uint64_t file_size = 0;
1755 uint64_t allocation_size = 0;
1756 uint64_t file_index = 0;
1757 size_t len = 0;
1758 struct timespec mdate_ts = {0};
1759 struct timespec adate_ts = {0};
1760 struct timespec cdate_ts = {0};
1761 struct timespec create_date_ts = {0};
1762 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1763 char *nameptr;
1764 char *last_entry_ptr;
1765 bool was_8_3;
1766 int off;
1767 int pad = 0;
1768 NTSTATUS status;
1769 struct readdir_attr_data *readdir_attr_data = NULL;
1771 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1772 file_size = get_file_size_stat(&smb_fname->st);
1774 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1776 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1779 return status;
1783 file_index = get_FileIndex(conn, &smb_fname->st);
1785 mdate_ts = smb_fname->st.st_ex_mtime;
1786 adate_ts = smb_fname->st.st_ex_atime;
1787 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1788 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1790 if (lp_dos_filetime_resolution(SNUM(conn))) {
1791 dos_filetime_timespec(&create_date_ts);
1792 dos_filetime_timespec(&mdate_ts);
1793 dos_filetime_timespec(&adate_ts);
1794 dos_filetime_timespec(&cdate_ts);
1797 create_date = convert_timespec_to_time_t(create_date_ts);
1798 mdate = convert_timespec_to_time_t(mdate_ts);
1799 adate = convert_timespec_to_time_t(adate_ts);
1801 /* align the record */
1802 SMB_ASSERT(align >= 1);
1804 off = (int)PTR_DIFF(pdata, base_data);
1805 pad = (off + (align-1)) & ~(align-1);
1806 pad -= off;
1808 if (pad && pad > space_remaining) {
1809 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1810 "for padding (wanted %u, had %d)\n",
1811 (unsigned int)pad,
1812 space_remaining ));
1813 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1816 off += pad;
1817 /* initialize padding to 0 */
1818 if (pad) {
1819 memset(pdata, 0, pad);
1821 space_remaining -= pad;
1823 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1824 space_remaining ));
1826 pdata += pad;
1827 p = pdata;
1828 last_entry_ptr = p;
1830 pad = 0;
1831 off = 0;
1833 switch (info_level) {
1834 case SMB_FIND_INFO_STANDARD:
1835 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1836 if(requires_resume_key) {
1837 SIVAL(p,0,reskey);
1838 p += 4;
1840 srv_put_dos_date2(p,0,create_date);
1841 srv_put_dos_date2(p,4,adate);
1842 srv_put_dos_date2(p,8,mdate);
1843 SIVAL(p,12,(uint32_t)file_size);
1844 SIVAL(p,16,(uint32_t)allocation_size);
1845 SSVAL(p,20,mode);
1846 p += 23;
1847 nameptr = p;
1848 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1849 p += ucs2_align(base_data, p, 0);
1851 status = srvstr_push(base_data, flags2, p,
1852 fname, PTR_DIFF(end_data, p),
1853 STR_TERMINATE, &len);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 return status;
1857 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1858 if (len > 2) {
1859 SCVAL(nameptr, -1, len - 2);
1860 } else {
1861 SCVAL(nameptr, -1, 0);
1863 } else {
1864 if (len > 1) {
1865 SCVAL(nameptr, -1, len - 1);
1866 } else {
1867 SCVAL(nameptr, -1, 0);
1870 p += len;
1871 break;
1873 case SMB_FIND_EA_SIZE:
1874 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1875 if (requires_resume_key) {
1876 SIVAL(p,0,reskey);
1877 p += 4;
1879 srv_put_dos_date2(p,0,create_date);
1880 srv_put_dos_date2(p,4,adate);
1881 srv_put_dos_date2(p,8,mdate);
1882 SIVAL(p,12,(uint32_t)file_size);
1883 SIVAL(p,16,(uint32_t)allocation_size);
1884 SSVAL(p,20,mode);
1886 unsigned int ea_size = estimate_ea_size(conn, NULL,
1887 smb_fname);
1888 SIVAL(p,22,ea_size); /* Extended attributes */
1890 p += 27;
1891 nameptr = p - 1;
1892 status = srvstr_push(base_data, flags2,
1893 p, fname, PTR_DIFF(end_data, p),
1894 STR_TERMINATE | STR_NOALIGN, &len);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 return status;
1898 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1899 if (len > 2) {
1900 len -= 2;
1901 } else {
1902 len = 0;
1904 } else {
1905 if (len > 1) {
1906 len -= 1;
1907 } else {
1908 len = 0;
1911 SCVAL(nameptr,0,len);
1912 p += len;
1913 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1914 break;
1916 case SMB_FIND_EA_LIST:
1918 struct ea_list *file_list = NULL;
1919 size_t ea_len = 0;
1921 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1922 if (!name_list) {
1923 return NT_STATUS_INVALID_PARAMETER;
1925 if (requires_resume_key) {
1926 SIVAL(p,0,reskey);
1927 p += 4;
1929 srv_put_dos_date2(p,0,create_date);
1930 srv_put_dos_date2(p,4,adate);
1931 srv_put_dos_date2(p,8,mdate);
1932 SIVAL(p,12,(uint32_t)file_size);
1933 SIVAL(p,16,(uint32_t)allocation_size);
1934 SSVAL(p,20,mode);
1935 p += 22; /* p now points to the EA area. */
1937 status = get_ea_list_from_file(ctx, conn, NULL,
1938 smb_fname,
1939 &ea_len, &file_list);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 file_list = NULL;
1943 name_list = ea_list_union(name_list, file_list, &ea_len);
1945 /* We need to determine if this entry will fit in the space available. */
1946 /* Max string size is 255 bytes. */
1947 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1948 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1949 "(wanted %u, had %d)\n",
1950 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1951 space_remaining ));
1952 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1955 /* Push the ea_data followed by the name. */
1956 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1957 nameptr = p;
1958 status = srvstr_push(base_data, flags2,
1959 p + 1, fname, PTR_DIFF(end_data, p+1),
1960 STR_TERMINATE | STR_NOALIGN, &len);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return status;
1964 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1965 if (len > 2) {
1966 len -= 2;
1967 } else {
1968 len = 0;
1970 } else {
1971 if (len > 1) {
1972 len -= 1;
1973 } else {
1974 len = 0;
1977 SCVAL(nameptr,0,len);
1978 p += len + 1;
1979 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1980 break;
1983 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1985 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1986 p += 4;
1987 SIVAL(p,0,reskey); p += 4;
1988 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1989 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1990 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1991 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1992 SOFF_T(p,0,file_size); p += 8;
1993 SOFF_T(p,0,allocation_size); p += 8;
1994 SIVAL(p,0,mode); p += 4;
1995 q = p; p += 4; /* q is placeholder for name length. */
1996 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1997 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1998 } else {
1999 unsigned int ea_size = estimate_ea_size(conn, NULL,
2000 smb_fname);
2001 SIVAL(p,0,ea_size); /* Extended attributes */
2003 p += 4;
2004 /* Clear the short name buffer. This is
2005 * IMPORTANT as not doing so will trigger
2006 * a Win2k client bug. JRA.
2008 if (!was_8_3 && check_mangled_names) {
2009 char mangled_name[13]; /* mangled 8.3 name. */
2010 if (!name_to_8_3(fname,mangled_name,True,
2011 conn->params)) {
2012 /* Error - mangle failed ! */
2013 memset(mangled_name,'\0',12);
2015 mangled_name[12] = 0;
2016 status = srvstr_push(base_data, flags2,
2017 p+2, mangled_name, 24,
2018 STR_UPPER|STR_UNICODE, &len);
2019 if (!NT_STATUS_IS_OK(status)) {
2020 return status;
2022 if (len < 24) {
2023 memset(p + 2 + len,'\0',24 - len);
2025 SSVAL(p, 0, len);
2026 } else {
2027 memset(p,'\0',26);
2029 p += 2 + 24;
2030 status = srvstr_push(base_data, flags2, p,
2031 fname, PTR_DIFF(end_data, p),
2032 STR_TERMINATE_ASCII, &len);
2033 if (!NT_STATUS_IS_OK(status)) {
2034 return status;
2036 SIVAL(q,0,len);
2037 p += len;
2039 len = PTR_DIFF(p, pdata);
2040 pad = (len + (align-1)) & ~(align-1);
2042 * offset to the next entry, the caller
2043 * will overwrite it for the last entry
2044 * that's why we always include the padding
2046 SIVAL(pdata,0,pad);
2048 * set padding to zero
2050 if (do_pad) {
2051 memset(p, 0, pad - len);
2052 p = pdata + pad;
2053 } else {
2054 p = pdata + len;
2056 break;
2058 case SMB_FIND_FILE_DIRECTORY_INFO:
2059 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2060 p += 4;
2061 SIVAL(p,0,reskey); p += 4;
2062 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2063 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2064 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2065 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2066 SOFF_T(p,0,file_size); p += 8;
2067 SOFF_T(p,0,allocation_size); p += 8;
2068 SIVAL(p,0,mode); p += 4;
2069 status = srvstr_push(base_data, flags2,
2070 p + 4, fname, PTR_DIFF(end_data, p+4),
2071 STR_TERMINATE_ASCII, &len);
2072 if (!NT_STATUS_IS_OK(status)) {
2073 return status;
2075 SIVAL(p,0,len);
2076 p += 4 + len;
2078 len = PTR_DIFF(p, pdata);
2079 pad = (len + (align-1)) & ~(align-1);
2081 * offset to the next entry, the caller
2082 * will overwrite it for the last entry
2083 * that's why we always include the padding
2085 SIVAL(pdata,0,pad);
2087 * set padding to zero
2089 if (do_pad) {
2090 memset(p, 0, pad - len);
2091 p = pdata + pad;
2092 } else {
2093 p = pdata + len;
2095 break;
2097 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2098 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2099 p += 4;
2100 SIVAL(p,0,reskey); p += 4;
2101 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2102 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2103 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2105 SOFF_T(p,0,file_size); p += 8;
2106 SOFF_T(p,0,allocation_size); p += 8;
2107 SIVAL(p,0,mode); p += 4;
2108 q = p; p += 4; /* q is placeholder for name length. */
2110 unsigned int ea_size = estimate_ea_size(conn, NULL,
2111 smb_fname);
2112 SIVAL(p,0,ea_size); /* Extended attributes */
2113 p +=4;
2115 status = srvstr_push(base_data, flags2, p,
2116 fname, PTR_DIFF(end_data, p),
2117 STR_TERMINATE_ASCII, &len);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 return status;
2121 SIVAL(q, 0, len);
2122 p += len;
2124 len = PTR_DIFF(p, pdata);
2125 pad = (len + (align-1)) & ~(align-1);
2127 * offset to the next entry, the caller
2128 * will overwrite it for the last entry
2129 * that's why we always include the padding
2131 SIVAL(pdata,0,pad);
2133 * set padding to zero
2135 if (do_pad) {
2136 memset(p, 0, pad - len);
2137 p = pdata + pad;
2138 } else {
2139 p = pdata + len;
2141 break;
2143 case SMB_FIND_FILE_NAMES_INFO:
2144 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2145 p += 4;
2146 SIVAL(p,0,reskey); p += 4;
2147 p += 4;
2148 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2149 acl on a dir (tridge) */
2150 status = srvstr_push(base_data, flags2, p,
2151 fname, PTR_DIFF(end_data, p),
2152 STR_TERMINATE_ASCII, &len);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 return status;
2156 SIVAL(p, -4, len);
2157 p += len;
2159 len = PTR_DIFF(p, pdata);
2160 pad = (len + (align-1)) & ~(align-1);
2162 * offset to the next entry, the caller
2163 * will overwrite it for the last entry
2164 * that's why we always include the padding
2166 SIVAL(pdata,0,pad);
2168 * set padding to zero
2170 if (do_pad) {
2171 memset(p, 0, pad - len);
2172 p = pdata + pad;
2173 } else {
2174 p = pdata + len;
2176 break;
2178 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2179 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2180 p += 4;
2181 SIVAL(p,0,reskey); p += 4;
2182 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2183 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2184 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2185 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2186 SOFF_T(p,0,file_size); p += 8;
2187 SOFF_T(p,0,allocation_size); p += 8;
2188 SIVAL(p,0,mode); p += 4;
2189 q = p; p += 4; /* q is placeholder for name length. */
2190 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2191 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2192 } else {
2193 unsigned int ea_size = estimate_ea_size(conn, NULL,
2194 smb_fname);
2195 SIVAL(p,0,ea_size); /* Extended attributes */
2197 p += 4;
2198 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2199 SBVAL(p,0,file_index); p += 8;
2200 status = srvstr_push(base_data, flags2, p,
2201 fname, PTR_DIFF(end_data, p),
2202 STR_TERMINATE_ASCII, &len);
2203 if (!NT_STATUS_IS_OK(status)) {
2204 return status;
2206 SIVAL(q, 0, len);
2207 p += len;
2209 len = PTR_DIFF(p, pdata);
2210 pad = (len + (align-1)) & ~(align-1);
2212 * offset to the next entry, the caller
2213 * will overwrite it for the last entry
2214 * that's why we always include the padding
2216 SIVAL(pdata,0,pad);
2218 * set padding to zero
2220 if (do_pad) {
2221 memset(p, 0, pad - len);
2222 p = pdata + pad;
2223 } else {
2224 p = pdata + len;
2226 break;
2228 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2229 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2230 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2231 p += 4;
2232 SIVAL(p,0,reskey); p += 4;
2233 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2234 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2235 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2236 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2237 SOFF_T(p,0,file_size); p += 8;
2238 SOFF_T(p,0,allocation_size); p += 8;
2239 SIVAL(p,0,mode); p += 4;
2240 q = p; p += 4; /* q is placeholder for name length */
2241 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2242 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2243 } else if (readdir_attr_data &&
2244 readdir_attr_data->type == RDATTR_AAPL) {
2246 * OS X specific SMB2 extension negotiated via
2247 * AAPL create context: return max_access in
2248 * ea_size field.
2250 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2251 } else {
2252 unsigned int ea_size = estimate_ea_size(conn, NULL,
2253 smb_fname);
2254 SIVAL(p,0,ea_size); /* Extended attributes */
2256 p += 4;
2258 if (readdir_attr_data &&
2259 readdir_attr_data->type == RDATTR_AAPL) {
2261 * OS X specific SMB2 extension negotiated via
2262 * AAPL create context: return resource fork
2263 * length and compressed FinderInfo in
2264 * shortname field.
2266 * According to documentation short_name_len
2267 * should be 0, but on the wire behaviour
2268 * shows its set to 24 by clients.
2270 SSVAL(p, 0, 24);
2272 /* Resourefork length */
2273 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2275 /* Compressed FinderInfo */
2276 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2277 } else if (!was_8_3 && check_mangled_names) {
2278 char mangled_name[13]; /* mangled 8.3 name. */
2279 if (!name_to_8_3(fname,mangled_name,True,
2280 conn->params)) {
2281 /* Error - mangle failed ! */
2282 memset(mangled_name,'\0',12);
2284 mangled_name[12] = 0;
2285 status = srvstr_push(base_data, flags2,
2286 p+2, mangled_name, 24,
2287 STR_UPPER|STR_UNICODE, &len);
2288 if (!NT_STATUS_IS_OK(status)) {
2289 return status;
2291 SSVAL(p, 0, len);
2292 if (len < 24) {
2293 memset(p + 2 + len,'\0',24 - len);
2295 SSVAL(p, 0, len);
2296 } else {
2297 /* Clear the short name buffer. This is
2298 * IMPORTANT as not doing so will trigger
2299 * a Win2k client bug. JRA.
2301 memset(p,'\0',26);
2303 p += 26;
2305 /* Reserved ? */
2306 if (readdir_attr_data &&
2307 readdir_attr_data->type == RDATTR_AAPL) {
2309 * OS X specific SMB2 extension negotiated via
2310 * AAPL create context: return UNIX mode in
2311 * reserved field.
2313 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2314 SSVAL(p, 0, aapl_mode);
2315 } else {
2316 SSVAL(p, 0, 0);
2318 p += 2;
2320 SBVAL(p,0,file_index); p += 8;
2321 status = srvstr_push(base_data, flags2, p,
2322 fname, PTR_DIFF(end_data, p),
2323 STR_TERMINATE_ASCII, &len);
2324 if (!NT_STATUS_IS_OK(status)) {
2325 return status;
2327 SIVAL(q,0,len);
2328 p += len;
2330 len = PTR_DIFF(p, pdata);
2331 pad = (len + (align-1)) & ~(align-1);
2333 * offset to the next entry, the caller
2334 * will overwrite it for the last entry
2335 * that's why we always include the padding
2337 SIVAL(pdata,0,pad);
2339 * set padding to zero
2341 if (do_pad) {
2342 memset(p, 0, pad - len);
2343 p = pdata + pad;
2344 } else {
2345 p = pdata + len;
2347 break;
2349 /* CIFS UNIX Extension. */
2351 case SMB_FIND_FILE_UNIX:
2352 case SMB_FIND_FILE_UNIX_INFO2:
2353 p+= 4;
2354 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2356 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2358 if (info_level == SMB_FIND_FILE_UNIX) {
2359 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2360 p = store_file_unix_basic(conn, p,
2361 NULL, &smb_fname->st);
2362 status = srvstr_push(base_data, flags2, p,
2363 fname, PTR_DIFF(end_data, p),
2364 STR_TERMINATE, &len);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 return status;
2368 } else {
2369 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2370 p = store_file_unix_basic_info2(conn, p,
2371 NULL, &smb_fname->st);
2372 nameptr = p;
2373 p += 4;
2374 status = srvstr_push(base_data, flags2, p, fname,
2375 PTR_DIFF(end_data, p), 0, &len);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 return status;
2379 SIVAL(nameptr, 0, len);
2382 p += len;
2384 len = PTR_DIFF(p, pdata);
2385 pad = (len + (align-1)) & ~(align-1);
2387 * offset to the next entry, the caller
2388 * will overwrite it for the last entry
2389 * that's why we always include the padding
2391 SIVAL(pdata,0,pad);
2393 * set padding to zero
2395 if (do_pad) {
2396 memset(p, 0, pad - len);
2397 p = pdata + pad;
2398 } else {
2399 p = pdata + len;
2401 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2403 break;
2405 default:
2406 return NT_STATUS_INVALID_LEVEL;
2409 if (PTR_DIFF(p,pdata) > space_remaining) {
2410 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2411 "(wanted %u, had %d)\n",
2412 (unsigned int)PTR_DIFF(p,pdata),
2413 space_remaining ));
2414 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2417 /* Setup the last entry pointer, as an offset from base_data */
2418 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2419 /* Advance the data pointer to the next slot */
2420 *ppdata = p;
2422 return NT_STATUS_OK;
2425 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2426 connection_struct *conn,
2427 struct dptr_struct *dirptr,
2428 uint16_t flags2,
2429 const char *path_mask,
2430 uint32_t dirtype,
2431 int info_level,
2432 int requires_resume_key,
2433 bool dont_descend,
2434 bool ask_sharemode,
2435 uint8_t align,
2436 bool do_pad,
2437 char **ppdata,
2438 char *base_data,
2439 char *end_data,
2440 int space_remaining,
2441 bool *got_exact_match,
2442 int *_last_entry_off,
2443 struct ea_list *name_list)
2445 const char *p;
2446 const char *mask = NULL;
2447 long prev_dirpos = 0;
2448 uint32_t mode = 0;
2449 char *fname = NULL;
2450 struct smb_filename *smb_fname = NULL;
2451 struct smbd_dirptr_lanman2_state state;
2452 bool ok;
2453 uint64_t last_entry_off = 0;
2454 NTSTATUS status;
2455 enum mangled_names_options mangled_names;
2456 bool marshall_with_83_names;
2458 mangled_names = lp_mangled_names(conn->params);
2460 ZERO_STRUCT(state);
2461 state.conn = conn;
2462 state.info_level = info_level;
2463 if (mangled_names != MANGLED_NAMES_NO) {
2464 state.check_mangled_names = true;
2466 state.has_wild = dptr_has_wild(dirptr);
2467 state.got_exact_match = false;
2469 *got_exact_match = false;
2471 p = strrchr_m(path_mask,'/');
2472 if(p != NULL) {
2473 if(p[1] == '\0') {
2474 mask = "*.*";
2475 } else {
2476 mask = p+1;
2478 } else {
2479 mask = path_mask;
2482 ok = smbd_dirptr_get_entry(ctx,
2483 dirptr,
2484 mask,
2485 dirtype,
2486 dont_descend,
2487 ask_sharemode,
2488 smbd_dirptr_lanman2_match_fn,
2489 smbd_dirptr_lanman2_mode_fn,
2490 &state,
2491 &fname,
2492 &smb_fname,
2493 &mode,
2494 &prev_dirpos);
2495 if (!ok) {
2496 return NT_STATUS_END_OF_FILE;
2499 *got_exact_match = state.got_exact_match;
2501 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2503 status = smbd_marshall_dir_entry(ctx,
2504 conn,
2505 flags2,
2506 info_level,
2507 name_list,
2508 marshall_with_83_names,
2509 requires_resume_key,
2510 mode,
2511 fname,
2512 smb_fname,
2513 space_remaining,
2514 align,
2515 do_pad,
2516 base_data,
2517 ppdata,
2518 end_data,
2519 &last_entry_off);
2520 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2521 DEBUG(1,("Conversion error: illegal character: %s\n",
2522 smb_fname_str_dbg(smb_fname)));
2524 TALLOC_FREE(fname);
2525 TALLOC_FREE(smb_fname);
2526 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2527 dptr_SeekDir(dirptr, prev_dirpos);
2528 return status;
2530 if (!NT_STATUS_IS_OK(status)) {
2531 return status;
2534 *_last_entry_off = last_entry_off;
2535 return NT_STATUS_OK;
2538 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2539 connection_struct *conn,
2540 struct dptr_struct *dirptr,
2541 uint16_t flags2,
2542 const char *path_mask,
2543 uint32_t dirtype,
2544 int info_level,
2545 bool requires_resume_key,
2546 bool dont_descend,
2547 bool ask_sharemode,
2548 char **ppdata,
2549 char *base_data,
2550 char *end_data,
2551 int space_remaining,
2552 bool *got_exact_match,
2553 int *last_entry_off,
2554 struct ea_list *name_list)
2556 uint8_t align = 4;
2557 const bool do_pad = true;
2559 if (info_level >= 1 && info_level <= 3) {
2560 /* No alignment on earlier info levels. */
2561 align = 1;
2564 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2565 path_mask, dirtype, info_level,
2566 requires_resume_key, dont_descend, ask_sharemode,
2567 align, do_pad,
2568 ppdata, base_data, end_data,
2569 space_remaining,
2570 got_exact_match,
2571 last_entry_off, name_list);
2574 /****************************************************************************
2575 Reply to a TRANS2_FINDFIRST.
2576 ****************************************************************************/
2578 static void call_trans2findfirst(connection_struct *conn,
2579 struct smb_request *req,
2580 char **pparams, int total_params,
2581 char **ppdata, int total_data,
2582 unsigned int max_data_bytes)
2584 /* We must be careful here that we don't return more than the
2585 allowed number of data bytes. If this means returning fewer than
2586 maxentries then so be it. We assume that the redirector has
2587 enough room for the fixed number of parameter bytes it has
2588 requested. */
2589 struct smb_filename *smb_dname = NULL;
2590 char *params = *pparams;
2591 char *pdata = *ppdata;
2592 char *data_end;
2593 uint32_t dirtype;
2594 int maxentries;
2595 uint16_t findfirst_flags;
2596 bool close_after_first;
2597 bool close_if_end;
2598 bool requires_resume_key;
2599 int info_level;
2600 char *directory = NULL;
2601 char *mask = NULL;
2602 char *p;
2603 int last_entry_off=0;
2604 int dptr_num = -1;
2605 int numentries = 0;
2606 int i;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 bool mask_contains_wcard = False;
2612 struct ea_list *ea_list = NULL;
2613 NTSTATUS ntstatus = NT_STATUS_OK;
2614 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2615 struct dptr_struct *dirptr = NULL;
2616 struct smbd_server_connection *sconn = req->sconn;
2617 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2618 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2619 bool backup_priv = false;
2620 bool as_root = false;
2622 if (total_params < 13) {
2623 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2624 goto out;
2627 dirtype = SVAL(params,0);
2628 maxentries = SVAL(params,2);
2629 findfirst_flags = SVAL(params,4);
2630 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2631 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2632 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2633 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2634 security_token_has_privilege(get_current_nttok(conn),
2635 SEC_PRIV_BACKUP));
2637 info_level = SVAL(params,6);
2639 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2640 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2641 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2642 (int)backup_priv,
2643 info_level, max_data_bytes));
2645 if (!maxentries) {
2646 /* W2K3 seems to treat zero as 1. */
2647 maxentries = 1;
2650 switch (info_level) {
2651 case SMB_FIND_INFO_STANDARD:
2652 case SMB_FIND_EA_SIZE:
2653 case SMB_FIND_EA_LIST:
2654 case SMB_FIND_FILE_DIRECTORY_INFO:
2655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2656 case SMB_FIND_FILE_NAMES_INFO:
2657 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2658 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2659 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2660 break;
2661 case SMB_FIND_FILE_UNIX:
2662 case SMB_FIND_FILE_UNIX_INFO2:
2663 /* Always use filesystem for UNIX mtime query. */
2664 ask_sharemode = false;
2665 if (!lp_unix_extensions()) {
2666 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2667 goto out;
2669 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2670 break;
2671 default:
2672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2673 goto out;
2676 if (req->posix_pathnames) {
2677 srvstr_get_path_wcard_posix(talloc_tos(),
2678 params,
2679 req->flags2,
2680 &directory,
2681 params+12,
2682 total_params - 12,
2683 STR_TERMINATE,
2684 &ntstatus,
2685 &mask_contains_wcard);
2686 } else {
2687 srvstr_get_path_wcard(talloc_tos(),
2688 params,
2689 req->flags2,
2690 &directory,
2691 params+12,
2692 total_params - 12,
2693 STR_TERMINATE,
2694 &ntstatus,
2695 &mask_contains_wcard);
2697 if (!NT_STATUS_IS_OK(ntstatus)) {
2698 reply_nterror(req, ntstatus);
2699 goto out;
2702 if (backup_priv) {
2703 become_root();
2704 as_root = true;
2705 ntstatus = filename_convert_with_privilege(talloc_tos(),
2706 conn,
2707 req,
2708 directory,
2709 ucf_flags,
2710 &mask_contains_wcard,
2711 &smb_dname);
2712 } else {
2713 ntstatus = filename_convert(talloc_tos(), conn,
2714 req->flags2 & FLAGS2_DFS_PATHNAMES,
2715 directory,
2716 ucf_flags,
2717 &mask_contains_wcard,
2718 &smb_dname);
2721 if (!NT_STATUS_IS_OK(ntstatus)) {
2722 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2723 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2724 ERRSRV, ERRbadpath);
2725 goto out;
2727 reply_nterror(req, ntstatus);
2728 goto out;
2731 mask = smb_dname->original_lcomp;
2733 directory = smb_dname->base_name;
2735 p = strrchr_m(directory,'/');
2736 if(p == NULL) {
2737 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2738 if((directory[0] == '.') && (directory[1] == '\0')) {
2739 mask = talloc_strdup(talloc_tos(),"*");
2740 if (!mask) {
2741 reply_nterror(req, NT_STATUS_NO_MEMORY);
2742 goto out;
2744 mask_contains_wcard = True;
2746 } else {
2747 *p = 0;
2750 if (p == NULL || p == directory) {
2751 /* Ensure we don't have a directory name of "". */
2752 directory = talloc_strdup(talloc_tos(), ".");
2753 if (!directory) {
2754 reply_nterror(req, NT_STATUS_NO_MEMORY);
2755 goto out;
2757 /* Ensure smb_dname->base_name matches. */
2758 smb_dname->base_name = directory;
2761 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2763 if (info_level == SMB_FIND_EA_LIST) {
2764 uint32_t ea_size;
2766 if (total_data < 4) {
2767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2768 goto out;
2771 ea_size = IVAL(pdata,0);
2772 if (ea_size != total_data) {
2773 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2774 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2776 goto out;
2779 if (!lp_ea_support(SNUM(conn))) {
2780 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2781 goto out;
2784 /* Pull out the list of names. */
2785 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2786 if (!ea_list) {
2787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2788 goto out;
2792 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 goto out;
2797 *ppdata = (char *)SMB_REALLOC(
2798 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2799 if(*ppdata == NULL ) {
2800 reply_nterror(req, NT_STATUS_NO_MEMORY);
2801 goto out;
2803 pdata = *ppdata;
2804 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2806 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2807 * error.
2809 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2810 /* Realloc the params space */
2811 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2812 if (*pparams == NULL) {
2813 reply_nterror(req, NT_STATUS_NO_MEMORY);
2814 goto out;
2816 params = *pparams;
2818 /* Save the wildcard match and attribs we are using on this directory -
2819 needed as lanman2 assumes these are being saved between calls */
2821 ntstatus = dptr_create(conn,
2822 req,
2823 NULL, /* fsp */
2824 smb_dname,
2825 False,
2826 True,
2827 req->smbpid,
2828 mask,
2829 mask_contains_wcard,
2830 dirtype,
2831 &dirptr);
2833 if (!NT_STATUS_IS_OK(ntstatus)) {
2834 reply_nterror(req, ntstatus);
2835 goto out;
2838 if (backup_priv) {
2839 /* Remember this in case we have
2840 to do a findnext. */
2841 dptr_set_priv(dirptr);
2844 dptr_num = dptr_dnum(dirptr);
2845 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2847 /* Initialize per TRANS2_FIND_FIRST operation data */
2848 dptr_init_search_op(dirptr);
2850 /* We don't need to check for VOL here as this is returned by
2851 a different TRANS2 call. */
2853 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2854 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2855 if (in_list(directory,
2856 lp_dont_descend(talloc_tos(), SNUM(conn)),
2857 conn->case_sensitive)) {
2858 dont_descend = True;
2861 p = pdata;
2862 space_remaining = max_data_bytes;
2863 out_of_space = False;
2865 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2866 bool got_exact_match = False;
2868 /* this is a heuristic to avoid seeking the dirptr except when
2869 absolutely necessary. It allows for a filename of about 40 chars */
2870 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2871 out_of_space = True;
2872 finished = False;
2873 } else {
2874 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2875 conn,
2876 dirptr,
2877 req->flags2,
2878 mask,dirtype,info_level,
2879 requires_resume_key,dont_descend,
2880 ask_sharemode,
2881 &p,pdata,data_end,
2882 space_remaining,
2883 &got_exact_match,
2884 &last_entry_off, ea_list);
2885 if (NT_STATUS_EQUAL(ntstatus,
2886 NT_STATUS_ILLEGAL_CHARACTER)) {
2888 * Bad character conversion on name. Ignore this
2889 * entry.
2891 continue;
2893 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2894 out_of_space = true;
2895 } else {
2896 finished = !NT_STATUS_IS_OK(ntstatus);
2900 if (!finished && !out_of_space)
2901 numentries++;
2904 * As an optimisation if we know we aren't looking
2905 * for a wildcard name (ie. the name matches the wildcard exactly)
2906 * then we can finish on any (first) match.
2907 * This speeds up large directory searches. JRA.
2910 if(got_exact_match)
2911 finished = True;
2913 /* Ensure space_remaining never goes -ve. */
2914 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2915 space_remaining = 0;
2916 out_of_space = true;
2917 } else {
2918 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2922 /* Check if we can close the dirptr */
2923 if(close_after_first || (finished && close_if_end)) {
2924 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2925 dptr_close(sconn, &dptr_num);
2929 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2930 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2931 * the protocol level is less than NT1. Tested with smbclient. JRA.
2932 * This should fix the OS/2 client bug #2335.
2935 if(numentries == 0) {
2936 dptr_close(sconn, &dptr_num);
2937 if (get_Protocol() < PROTOCOL_NT1) {
2938 reply_force_doserror(req, ERRDOS, ERRnofiles);
2939 goto out;
2940 } else {
2941 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2942 ERRDOS, ERRbadfile);
2943 goto out;
2947 /* At this point pdata points to numentries directory entries. */
2949 /* Set up the return parameter block */
2950 SSVAL(params,0,dptr_num);
2951 SSVAL(params,2,numentries);
2952 SSVAL(params,4,finished);
2953 SSVAL(params,6,0); /* Never an EA error */
2954 SSVAL(params,8,last_entry_off);
2956 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2957 max_data_bytes);
2959 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2960 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2961 if (!directory) {
2962 reply_nterror(req, NT_STATUS_NO_MEMORY);
2966 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2967 smb_fn_name(req->cmd),
2968 mask, directory, dirtype, numentries ) );
2971 * Force a name mangle here to ensure that the
2972 * mask as an 8.3 name is top of the mangled cache.
2973 * The reasons for this are subtle. Don't remove
2974 * this code unless you know what you are doing
2975 * (see PR#13758). JRA.
2978 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2979 char mangled_name[13];
2980 name_to_8_3(mask, mangled_name, True, conn->params);
2982 out:
2984 if (as_root) {
2985 unbecome_root();
2988 TALLOC_FREE(smb_dname);
2989 return;
2992 /****************************************************************************
2993 Reply to a TRANS2_FINDNEXT.
2994 ****************************************************************************/
2996 static void call_trans2findnext(connection_struct *conn,
2997 struct smb_request *req,
2998 char **pparams, int total_params,
2999 char **ppdata, int total_data,
3000 unsigned int max_data_bytes)
3002 /* We must be careful here that we don't return more than the
3003 allowed number of data bytes. If this means returning fewer than
3004 maxentries then so be it. We assume that the redirector has
3005 enough room for the fixed number of parameter bytes it has
3006 requested. */
3007 char *params = *pparams;
3008 char *pdata = *ppdata;
3009 char *data_end;
3010 int dptr_num;
3011 int maxentries;
3012 uint16_t info_level;
3013 uint32_t resume_key;
3014 uint16_t findnext_flags;
3015 bool close_after_request;
3016 bool close_if_end;
3017 bool requires_resume_key;
3018 bool continue_bit;
3019 bool mask_contains_wcard = False;
3020 char *resume_name = NULL;
3021 const char *mask = NULL;
3022 const char *directory = NULL;
3023 char *p = NULL;
3024 uint16_t dirtype;
3025 int numentries = 0;
3026 int i, last_entry_off=0;
3027 bool finished = False;
3028 bool dont_descend = False;
3029 bool out_of_space = False;
3030 int space_remaining;
3031 struct ea_list *ea_list = NULL;
3032 NTSTATUS ntstatus = NT_STATUS_OK;
3033 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3034 TALLOC_CTX *ctx = talloc_tos();
3035 struct dptr_struct *dirptr;
3036 struct smbd_server_connection *sconn = req->sconn;
3037 bool backup_priv = false;
3038 bool as_root = false;
3040 if (total_params < 13) {
3041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3042 return;
3045 dptr_num = SVAL(params,0);
3046 maxentries = SVAL(params,2);
3047 info_level = SVAL(params,4);
3048 resume_key = IVAL(params,6);
3049 findnext_flags = SVAL(params,10);
3050 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3051 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3052 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3053 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3055 if (!continue_bit) {
3056 /* We only need resume_name if continue_bit is zero. */
3057 if (req->posix_pathnames) {
3058 srvstr_get_path_wcard_posix(ctx,
3059 params,
3060 req->flags2,
3061 &resume_name,
3062 params+12,
3063 total_params - 12,
3064 STR_TERMINATE,
3065 &ntstatus,
3066 &mask_contains_wcard);
3067 } else {
3068 srvstr_get_path_wcard(ctx,
3069 params,
3070 req->flags2,
3071 &resume_name,
3072 params+12,
3073 total_params - 12,
3074 STR_TERMINATE,
3075 &ntstatus,
3076 &mask_contains_wcard);
3078 if (!NT_STATUS_IS_OK(ntstatus)) {
3079 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3080 complain (it thinks we're asking for the directory above the shared
3081 path or an invalid name). Catch this as the resume name is only compared, never used in
3082 a file access. JRA. */
3083 srvstr_pull_talloc(ctx, params, req->flags2,
3084 &resume_name, params+12,
3085 total_params - 12,
3086 STR_TERMINATE);
3088 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3089 reply_nterror(req, ntstatus);
3090 return;
3095 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3096 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3097 resume_key = %d resume name = %s continue=%d level = %d\n",
3098 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3099 requires_resume_key, resume_key,
3100 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3102 if (!maxentries) {
3103 /* W2K3 seems to treat zero as 1. */
3104 maxentries = 1;
3107 switch (info_level) {
3108 case SMB_FIND_INFO_STANDARD:
3109 case SMB_FIND_EA_SIZE:
3110 case SMB_FIND_EA_LIST:
3111 case SMB_FIND_FILE_DIRECTORY_INFO:
3112 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3113 case SMB_FIND_FILE_NAMES_INFO:
3114 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3115 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3116 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3117 break;
3118 case SMB_FIND_FILE_UNIX:
3119 case SMB_FIND_FILE_UNIX_INFO2:
3120 /* Always use filesystem for UNIX mtime query. */
3121 ask_sharemode = false;
3122 if (!lp_unix_extensions()) {
3123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3124 return;
3126 break;
3127 default:
3128 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3129 return;
3132 if (info_level == SMB_FIND_EA_LIST) {
3133 uint32_t ea_size;
3135 if (total_data < 4) {
3136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3137 return;
3140 ea_size = IVAL(pdata,0);
3141 if (ea_size != total_data) {
3142 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3143 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3145 return;
3148 if (!lp_ea_support(SNUM(conn))) {
3149 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3150 return;
3153 /* Pull out the list of names. */
3154 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3155 if (!ea_list) {
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 return;
3161 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3163 return;
3166 *ppdata = (char *)SMB_REALLOC(
3167 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3168 if(*ppdata == NULL) {
3169 reply_nterror(req, NT_STATUS_NO_MEMORY);
3170 return;
3173 pdata = *ppdata;
3174 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3177 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3178 * error.
3180 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3181 /* Realloc the params space */
3182 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3183 if(*pparams == NULL ) {
3184 reply_nterror(req, NT_STATUS_NO_MEMORY);
3185 return;
3188 params = *pparams;
3190 /* Check that the dptr is valid */
3191 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3192 reply_nterror(req, STATUS_NO_MORE_FILES);
3193 return;
3196 directory = dptr_path(sconn, dptr_num);
3198 /* Get the wildcard mask from the dptr */
3199 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3200 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3201 reply_nterror(req, STATUS_NO_MORE_FILES);
3202 return;
3205 /* Get the attr mask from the dptr */
3206 dirtype = dptr_attr(sconn, dptr_num);
3208 backup_priv = dptr_get_priv(dirptr);
3210 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3211 "backup_priv = %d\n",
3212 dptr_num, mask, dirtype,
3213 (long)dirptr,
3214 dptr_TellDir(dirptr),
3215 (int)backup_priv));
3217 /* Initialize per TRANS2_FIND_NEXT operation data */
3218 dptr_init_search_op(dirptr);
3220 /* We don't need to check for VOL here as this is returned by
3221 a different TRANS2 call. */
3223 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3224 directory,lp_dont_descend(ctx, SNUM(conn))));
3225 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3226 dont_descend = True;
3228 p = pdata;
3229 space_remaining = max_data_bytes;
3230 out_of_space = False;
3232 if (backup_priv) {
3233 become_root();
3234 as_root = true;
3238 * Seek to the correct position. We no longer use the resume key but
3239 * depend on the last file name instead.
3242 if(!continue_bit && resume_name && *resume_name) {
3243 SMB_STRUCT_STAT st;
3245 long current_pos = 0;
3247 * Remember, name_to_8_3 is called by
3248 * get_lanman2_dir_entry(), so the resume name
3249 * could be mangled. Ensure we check the unmangled name.
3252 if (mangle_is_mangled(resume_name, conn->params)) {
3253 char *new_resume_name = NULL;
3254 mangle_lookup_name_from_8_3(ctx,
3255 resume_name,
3256 &new_resume_name,
3257 conn->params);
3258 if (new_resume_name) {
3259 resume_name = new_resume_name;
3264 * Fix for NT redirector problem triggered by resume key indexes
3265 * changing between directory scans. We now return a resume key of 0
3266 * and instead look for the filename to continue from (also given
3267 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3268 * findfirst/findnext (as is usual) then the directory pointer
3269 * should already be at the correct place.
3272 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3273 } /* end if resume_name && !continue_bit */
3275 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3276 bool got_exact_match = False;
3278 /* this is a heuristic to avoid seeking the dirptr except when
3279 absolutely necessary. It allows for a filename of about 40 chars */
3280 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3281 out_of_space = True;
3282 finished = False;
3283 } else {
3284 ntstatus = get_lanman2_dir_entry(ctx,
3285 conn,
3286 dirptr,
3287 req->flags2,
3288 mask,dirtype,info_level,
3289 requires_resume_key,dont_descend,
3290 ask_sharemode,
3291 &p,pdata,data_end,
3292 space_remaining,
3293 &got_exact_match,
3294 &last_entry_off, ea_list);
3295 if (NT_STATUS_EQUAL(ntstatus,
3296 NT_STATUS_ILLEGAL_CHARACTER)) {
3298 * Bad character conversion on name. Ignore this
3299 * entry.
3301 continue;
3303 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3304 out_of_space = true;
3305 } else {
3306 finished = !NT_STATUS_IS_OK(ntstatus);
3310 if (!finished && !out_of_space)
3311 numentries++;
3314 * As an optimisation if we know we aren't looking
3315 * for a wildcard name (ie. the name matches the wildcard exactly)
3316 * then we can finish on any (first) match.
3317 * This speeds up large directory searches. JRA.
3320 if(got_exact_match)
3321 finished = True;
3323 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3326 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3327 smb_fn_name(req->cmd),
3328 mask, directory, dirtype, numentries ) );
3330 /* Check if we can close the dirptr */
3331 if(close_after_request || (finished && close_if_end)) {
3332 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3333 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3336 if (as_root) {
3337 unbecome_root();
3340 /* Set up the return parameter block */
3341 SSVAL(params,0,numentries);
3342 SSVAL(params,2,finished);
3343 SSVAL(params,4,0); /* Never an EA error */
3344 SSVAL(params,6,last_entry_off);
3346 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3347 max_data_bytes);
3349 return;
3352 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3354 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3355 return objid;
3358 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3360 SMB_ASSERT(extended_info != NULL);
3362 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3363 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3364 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3365 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3366 #ifdef SAMBA_VERSION_REVISION
3367 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3368 #endif
3369 extended_info->samba_subversion = 0;
3370 #ifdef SAMBA_VERSION_RC_RELEASE
3371 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3372 #else
3373 #ifdef SAMBA_VERSION_PRE_RELEASE
3374 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3375 #endif
3376 #endif
3377 #ifdef SAMBA_VERSION_VENDOR_PATCH
3378 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3379 #endif
3380 extended_info->samba_gitcommitdate = 0;
3381 #ifdef SAMBA_VERSION_COMMIT_TIME
3382 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3383 #endif
3385 memset(extended_info->samba_version_string, 0,
3386 sizeof(extended_info->samba_version_string));
3388 snprintf (extended_info->samba_version_string,
3389 sizeof(extended_info->samba_version_string),
3390 "%s", samba_version_string());
3393 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3394 connection_struct *conn,
3395 TALLOC_CTX *mem_ctx,
3396 uint16_t info_level,
3397 uint16_t flags2,
3398 unsigned int max_data_bytes,
3399 size_t *fixed_portion,
3400 struct smb_filename *fname,
3401 char **ppdata,
3402 int *ret_data_len)
3404 char *pdata, *end_data;
3405 int data_len = 0;
3406 size_t len = 0;
3407 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3408 int snum = SNUM(conn);
3409 const char *fstype = lp_fstype(SNUM(conn));
3410 const char *filename = NULL;
3411 const uint64_t bytes_per_sector = 512;
3412 uint32_t additional_flags = 0;
3413 struct smb_filename smb_fname;
3414 SMB_STRUCT_STAT st;
3415 NTSTATUS status = NT_STATUS_OK;
3416 uint64_t df_ret;
3418 if (fname == NULL || fname->base_name == NULL) {
3419 filename = ".";
3420 } else {
3421 filename = fname->base_name;
3424 if (IS_IPC(conn)) {
3425 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3426 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3427 "info level (0x%x) on IPC$.\n",
3428 (unsigned int)info_level));
3429 return NT_STATUS_ACCESS_DENIED;
3433 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3435 ZERO_STRUCT(smb_fname);
3436 smb_fname.base_name = discard_const_p(char, filename);
3438 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3439 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3440 return map_nt_error_from_unix(errno);
3443 st = smb_fname.st;
3445 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3446 return NT_STATUS_INVALID_PARAMETER;
3449 *ppdata = (char *)SMB_REALLOC(
3450 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3451 if (*ppdata == NULL) {
3452 return NT_STATUS_NO_MEMORY;
3455 pdata = *ppdata;
3456 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3457 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3459 *fixed_portion = 0;
3461 switch (info_level) {
3462 case SMB_INFO_ALLOCATION:
3464 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3465 data_len = 18;
3466 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3467 &dfree, &dsize);
3468 if (df_ret == (uint64_t)-1) {
3469 return map_nt_error_from_unix(errno);
3472 block_size = lp_block_size(snum);
3473 if (bsize < block_size) {
3474 uint64_t factor = block_size/bsize;
3475 bsize = block_size;
3476 dsize /= factor;
3477 dfree /= factor;
3479 if (bsize > block_size) {
3480 uint64_t factor = bsize/block_size;
3481 bsize = block_size;
3482 dsize *= factor;
3483 dfree *= factor;
3485 sectors_per_unit = bsize/bytes_per_sector;
3487 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3488 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3489 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3491 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3492 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3493 SIVAL(pdata,l1_cUnit,dsize);
3494 SIVAL(pdata,l1_cUnitAvail,dfree);
3495 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3496 break;
3499 case SMB_INFO_VOLUME:
3500 /* Return volume name */
3502 * Add volume serial number - hash of a combination of
3503 * the called hostname and the service name.
3505 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3507 * Win2k3 and previous mess this up by sending a name length
3508 * one byte short. I believe only older clients (OS/2 Win9x) use
3509 * this call so try fixing this by adding a terminating null to
3510 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3512 status = srvstr_push(
3513 pdata, flags2,
3514 pdata+l2_vol_szVolLabel, vname,
3515 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3516 STR_NOALIGN|STR_TERMINATE, &len);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 return status;
3520 SCVAL(pdata,l2_vol_cch,len);
3521 data_len = l2_vol_szVolLabel + len;
3522 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3523 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3524 (unsigned)len, vname));
3525 break;
3527 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3528 case SMB_FS_ATTRIBUTE_INFORMATION:
3530 additional_flags = 0;
3531 #if defined(HAVE_SYS_QUOTAS)
3532 additional_flags |= FILE_VOLUME_QUOTAS;
3533 #endif
3535 if(lp_nt_acl_support(SNUM(conn))) {
3536 additional_flags |= FILE_PERSISTENT_ACLS;
3539 /* Capabilities are filled in at connection time through STATVFS call */
3540 additional_flags |= conn->fs_capabilities;
3541 additional_flags |= lp_parm_int(conn->params->service,
3542 "share", "fake_fscaps",
3545 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3546 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3547 additional_flags); /* FS ATTRIBUTES */
3549 SIVAL(pdata,4,255); /* Max filename component length */
3550 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3551 and will think we can't do long filenames */
3552 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3553 PTR_DIFF(end_data, pdata+12),
3554 STR_UNICODE, &len);
3555 if (!NT_STATUS_IS_OK(status)) {
3556 return status;
3558 SIVAL(pdata,8,len);
3559 data_len = 12 + len;
3560 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3561 /* the client only requested a portion of the
3562 file system name */
3563 data_len = max_data_bytes;
3564 status = STATUS_BUFFER_OVERFLOW;
3566 *fixed_portion = 16;
3567 break;
3569 case SMB_QUERY_FS_LABEL_INFO:
3570 case SMB_FS_LABEL_INFORMATION:
3571 status = srvstr_push(pdata, flags2, pdata+4, vname,
3572 PTR_DIFF(end_data, pdata+4), 0, &len);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 return status;
3576 data_len = 4 + len;
3577 SIVAL(pdata,0,len);
3578 break;
3580 case SMB_QUERY_FS_VOLUME_INFO:
3581 case SMB_FS_VOLUME_INFORMATION:
3584 * Add volume serial number - hash of a combination of
3585 * the called hostname and the service name.
3587 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3588 (str_checksum(get_local_machine_name())<<16));
3590 /* Max label len is 32 characters. */
3591 status = srvstr_push(pdata, flags2, pdata+18, vname,
3592 PTR_DIFF(end_data, pdata+18),
3593 STR_UNICODE, &len);
3594 if (!NT_STATUS_IS_OK(status)) {
3595 return status;
3597 SIVAL(pdata,12,len);
3598 data_len = 18+len;
3600 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3601 (int)strlen(vname),vname,
3602 lp_servicename(talloc_tos(), snum)));
3603 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3604 /* the client only requested a portion of the
3605 volume label */
3606 data_len = max_data_bytes;
3607 status = STATUS_BUFFER_OVERFLOW;
3609 *fixed_portion = 24;
3610 break;
3612 case SMB_QUERY_FS_SIZE_INFO:
3613 case SMB_FS_SIZE_INFORMATION:
3615 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3616 data_len = 24;
3617 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3618 &dfree, &dsize);
3619 if (df_ret == (uint64_t)-1) {
3620 return map_nt_error_from_unix(errno);
3622 block_size = lp_block_size(snum);
3623 if (bsize < block_size) {
3624 uint64_t factor = block_size/bsize;
3625 bsize = block_size;
3626 dsize /= factor;
3627 dfree /= factor;
3629 if (bsize > block_size) {
3630 uint64_t factor = bsize/block_size;
3631 bsize = block_size;
3632 dsize *= factor;
3633 dfree *= factor;
3635 sectors_per_unit = bsize/bytes_per_sector;
3636 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3637 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3638 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3639 SBIG_UINT(pdata,0,dsize);
3640 SBIG_UINT(pdata,8,dfree);
3641 SIVAL(pdata,16,sectors_per_unit);
3642 SIVAL(pdata,20,bytes_per_sector);
3643 *fixed_portion = 24;
3644 break;
3647 case SMB_FS_FULL_SIZE_INFORMATION:
3649 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3650 data_len = 32;
3651 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3652 &dfree, &dsize);
3653 if (df_ret == (uint64_t)-1) {
3654 return map_nt_error_from_unix(errno);
3656 block_size = lp_block_size(snum);
3657 if (bsize < block_size) {
3658 uint64_t factor = block_size/bsize;
3659 bsize = block_size;
3660 dsize /= factor;
3661 dfree /= factor;
3663 if (bsize > block_size) {
3664 uint64_t factor = bsize/block_size;
3665 bsize = block_size;
3666 dsize *= factor;
3667 dfree *= factor;
3669 sectors_per_unit = bsize/bytes_per_sector;
3670 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3671 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3672 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3673 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3674 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3675 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3676 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3677 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3678 *fixed_portion = 32;
3679 break;
3682 case SMB_QUERY_FS_DEVICE_INFO:
3683 case SMB_FS_DEVICE_INFORMATION:
3685 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3687 if (!CAN_WRITE(conn)) {
3688 characteristics |= FILE_READ_ONLY_DEVICE;
3690 data_len = 8;
3691 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3692 SIVAL(pdata,4,characteristics);
3693 *fixed_portion = 8;
3694 break;
3697 #ifdef HAVE_SYS_QUOTAS
3698 case SMB_FS_QUOTA_INFORMATION:
3700 * what we have to send --metze:
3702 * Unknown1: 24 NULL bytes
3703 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3704 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3705 * Quota Flags: 2 byte :
3706 * Unknown3: 6 NULL bytes
3708 * 48 bytes total
3710 * details for Quota Flags:
3712 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3713 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3714 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3715 * 0x0001 Enable Quotas: enable quota for this fs
3719 /* we need to fake up a fsp here,
3720 * because its not send in this call
3722 files_struct fsp;
3723 SMB_NTQUOTA_STRUCT quotas;
3725 ZERO_STRUCT(fsp);
3726 ZERO_STRUCT(quotas);
3728 fsp.conn = conn;
3729 fsp.fnum = FNUM_FIELD_INVALID;
3731 /* access check */
3732 if (get_current_uid(conn) != 0) {
3733 DEBUG(0,("get_user_quota: access_denied "
3734 "service [%s] user [%s]\n",
3735 lp_servicename(talloc_tos(), SNUM(conn)),
3736 conn->session_info->unix_info->unix_name));
3737 return NT_STATUS_ACCESS_DENIED;
3740 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3741 NULL, &quotas);
3742 if (!NT_STATUS_IS_OK(status)) {
3743 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3744 return status;
3747 data_len = 48;
3749 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3750 lp_servicename(talloc_tos(), SNUM(conn))));
3752 /* Unknown1 24 NULL bytes*/
3753 SBIG_UINT(pdata,0,(uint64_t)0);
3754 SBIG_UINT(pdata,8,(uint64_t)0);
3755 SBIG_UINT(pdata,16,(uint64_t)0);
3757 /* Default Soft Quota 8 bytes */
3758 SBIG_UINT(pdata,24,quotas.softlim);
3760 /* Default Hard Quota 8 bytes */
3761 SBIG_UINT(pdata,32,quotas.hardlim);
3763 /* Quota flag 2 bytes */
3764 SSVAL(pdata,40,quotas.qflags);
3766 /* Unknown3 6 NULL bytes */
3767 SSVAL(pdata,42,0);
3768 SIVAL(pdata,44,0);
3770 break;
3772 #endif /* HAVE_SYS_QUOTAS */
3773 case SMB_FS_OBJECTID_INFORMATION:
3775 unsigned char objid[16];
3776 struct smb_extended_info extended_info;
3777 memcpy(pdata,create_volume_objectid(conn, objid),16);
3778 samba_extended_info_version (&extended_info);
3779 SIVAL(pdata,16,extended_info.samba_magic);
3780 SIVAL(pdata,20,extended_info.samba_version);
3781 SIVAL(pdata,24,extended_info.samba_subversion);
3782 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3783 memcpy(pdata+36,extended_info.samba_version_string,28);
3784 data_len = 64;
3785 break;
3788 case SMB_FS_SECTOR_SIZE_INFORMATION:
3790 data_len = 28;
3792 * These values match a physical Windows Server 2012
3793 * share backed by NTFS atop spinning rust.
3795 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3796 /* logical_bytes_per_sector */
3797 SIVAL(pdata, 0, bytes_per_sector);
3798 /* phys_bytes_per_sector_atomic */
3799 SIVAL(pdata, 4, bytes_per_sector);
3800 /* phys_bytes_per_sector_perf */
3801 SIVAL(pdata, 8, bytes_per_sector);
3802 /* fs_effective_phys_bytes_per_sector_atomic */
3803 SIVAL(pdata, 12, bytes_per_sector);
3804 /* flags */
3805 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3806 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3807 /* byte_off_sector_align */
3808 SIVAL(pdata, 20, 0);
3809 /* byte_off_partition_align */
3810 SIVAL(pdata, 24, 0);
3811 *fixed_portion = 28;
3812 break;
3817 * Query the version and capabilities of the CIFS UNIX extensions
3818 * in use.
3821 case SMB_QUERY_CIFS_UNIX_INFO:
3823 bool large_write = lp_min_receive_file_size() &&
3824 !srv_is_signing_active(xconn);
3825 bool large_read = !srv_is_signing_active(xconn);
3826 int encrypt_caps = 0;
3828 if (!lp_unix_extensions()) {
3829 return NT_STATUS_INVALID_LEVEL;
3832 switch (conn->encrypt_level) {
3833 case SMB_SIGNING_OFF:
3834 encrypt_caps = 0;
3835 break;
3836 case SMB_SIGNING_DESIRED:
3837 case SMB_SIGNING_IF_REQUIRED:
3838 case SMB_SIGNING_DEFAULT:
3839 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3840 break;
3841 case SMB_SIGNING_REQUIRED:
3842 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3843 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3844 large_write = false;
3845 large_read = false;
3846 break;
3849 data_len = 12;
3850 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3851 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3853 /* We have POSIX ACLs, pathname, encryption,
3854 * large read/write, and locking capability. */
3856 SBIG_UINT(pdata,4,((uint64_t)(
3857 CIFS_UNIX_POSIX_ACLS_CAP|
3858 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3859 CIFS_UNIX_FCNTL_LOCKS_CAP|
3860 CIFS_UNIX_EXTATTR_CAP|
3861 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3862 encrypt_caps|
3863 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3864 (large_write ?
3865 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3866 break;
3869 case SMB_QUERY_POSIX_FS_INFO:
3871 int rc;
3872 vfs_statvfs_struct svfs;
3874 if (!lp_unix_extensions()) {
3875 return NT_STATUS_INVALID_LEVEL;
3878 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3880 if (!rc) {
3881 data_len = 56;
3882 SIVAL(pdata,0,svfs.OptimalTransferSize);
3883 SIVAL(pdata,4,svfs.BlockSize);
3884 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3885 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3886 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3887 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3888 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3889 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3890 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3891 #ifdef EOPNOTSUPP
3892 } else if (rc == EOPNOTSUPP) {
3893 return NT_STATUS_INVALID_LEVEL;
3894 #endif /* EOPNOTSUPP */
3895 } else {
3896 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3897 return NT_STATUS_DOS(ERRSRV, ERRerror);
3899 break;
3902 case SMB_QUERY_POSIX_WHOAMI:
3904 uint32_t flags = 0;
3905 uint32_t sid_bytes;
3906 int i;
3908 if (!lp_unix_extensions()) {
3909 return NT_STATUS_INVALID_LEVEL;
3912 if (max_data_bytes < 40) {
3913 return NT_STATUS_BUFFER_TOO_SMALL;
3916 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3917 flags |= SMB_WHOAMI_GUEST;
3920 /* NOTE: 8 bytes for UID/GID, irrespective of native
3921 * platform size. This matches
3922 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3924 data_len = 4 /* flags */
3925 + 4 /* flag mask */
3926 + 8 /* uid */
3927 + 8 /* gid */
3928 + 4 /* ngroups */
3929 + 4 /* num_sids */
3930 + 4 /* SID bytes */
3931 + 4 /* pad/reserved */
3932 + (conn->session_info->unix_token->ngroups * 8)
3933 /* groups list */
3934 + (conn->session_info->security_token->num_sids *
3935 SID_MAX_SIZE)
3936 /* SID list */;
3938 SIVAL(pdata, 0, flags);
3939 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3940 SBIG_UINT(pdata, 8,
3941 (uint64_t)conn->session_info->unix_token->uid);
3942 SBIG_UINT(pdata, 16,
3943 (uint64_t)conn->session_info->unix_token->gid);
3946 if (data_len >= max_data_bytes) {
3947 /* Potential overflow, skip the GIDs and SIDs. */
3949 SIVAL(pdata, 24, 0); /* num_groups */
3950 SIVAL(pdata, 28, 0); /* num_sids */
3951 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3952 SIVAL(pdata, 36, 0); /* reserved */
3954 data_len = 40;
3955 break;
3958 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3959 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3961 /* We walk the SID list twice, but this call is fairly
3962 * infrequent, and I don't expect that it's performance
3963 * sensitive -- jpeach
3965 for (i = 0, sid_bytes = 0;
3966 i < conn->session_info->security_token->num_sids; ++i) {
3967 sid_bytes += ndr_size_dom_sid(
3968 &conn->session_info->security_token->sids[i],
3972 /* SID list byte count */
3973 SIVAL(pdata, 32, sid_bytes);
3975 /* 4 bytes pad/reserved - must be zero */
3976 SIVAL(pdata, 36, 0);
3977 data_len = 40;
3979 /* GID list */
3980 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3981 SBIG_UINT(pdata, data_len,
3982 (uint64_t)conn->session_info->unix_token->groups[i]);
3983 data_len += 8;
3986 /* SID list */
3987 for (i = 0;
3988 i < conn->session_info->security_token->num_sids; ++i) {
3989 int sid_len = ndr_size_dom_sid(
3990 &conn->session_info->security_token->sids[i],
3993 sid_linearize((uint8_t *)(pdata + data_len),
3994 sid_len,
3995 &conn->session_info->security_token->sids[i]);
3996 data_len += sid_len;
3999 break;
4002 case SMB_MAC_QUERY_FS_INFO:
4004 * Thursby MAC extension... ONLY on NTFS filesystems
4005 * once we do streams then we don't need this
4007 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4008 data_len = 88;
4009 SIVAL(pdata,84,0x100); /* Don't support mac... */
4010 break;
4012 /* drop through */
4013 default:
4014 return NT_STATUS_INVALID_LEVEL;
4017 *ret_data_len = data_len;
4018 return status;
4021 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4022 struct smb_request *req,
4023 files_struct *fsp,
4024 const DATA_BLOB *qdata)
4026 NTSTATUS status;
4027 SMB_NTQUOTA_STRUCT quotas;
4029 ZERO_STRUCT(quotas);
4031 /* access check */
4032 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4033 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4034 lp_servicename(talloc_tos(), SNUM(conn)),
4035 conn->session_info->unix_info->unix_name));
4036 return NT_STATUS_ACCESS_DENIED;
4039 if (!check_fsp_ntquota_handle(conn, req,
4040 fsp)) {
4041 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4042 return NT_STATUS_INVALID_HANDLE;
4045 /* note: normally there're 48 bytes,
4046 * but we didn't use the last 6 bytes for now
4047 * --metze
4049 if (qdata->length < 42) {
4050 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4051 (unsigned int)qdata->length));
4052 return NT_STATUS_INVALID_PARAMETER;
4055 /* unknown_1 24 NULL bytes in pdata*/
4057 /* the soft quotas 8 bytes (uint64_t)*/
4058 quotas.softlim = BVAL(qdata->data,24);
4060 /* the hard quotas 8 bytes (uint64_t)*/
4061 quotas.hardlim = BVAL(qdata->data,32);
4063 /* quota_flags 2 bytes **/
4064 quotas.qflags = SVAL(qdata->data,40);
4066 /* unknown_2 6 NULL bytes follow*/
4068 /* now set the quotas */
4069 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4070 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4071 lp_servicename(talloc_tos(), SNUM(conn))));
4072 status = map_nt_error_from_unix(errno);
4073 } else {
4074 status = NT_STATUS_OK;
4076 return status;
4079 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4080 struct smb_request *req,
4081 TALLOC_CTX *mem_ctx,
4082 uint16_t info_level,
4083 files_struct *fsp,
4084 const DATA_BLOB *pdata)
4086 switch (info_level) {
4087 case SMB_FS_QUOTA_INFORMATION:
4089 return smb_set_fsquota(conn,
4090 req,
4091 fsp,
4092 pdata);
4095 default:
4096 break;
4098 return NT_STATUS_INVALID_LEVEL;
4101 /****************************************************************************
4102 Reply to a TRANS2_QFSINFO (query filesystem info).
4103 ****************************************************************************/
4105 static void call_trans2qfsinfo(connection_struct *conn,
4106 struct smb_request *req,
4107 char **pparams, int total_params,
4108 char **ppdata, int total_data,
4109 unsigned int max_data_bytes)
4111 char *params = *pparams;
4112 uint16_t info_level;
4113 int data_len = 0;
4114 size_t fixed_portion;
4115 NTSTATUS status;
4117 if (total_params < 2) {
4118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4119 return;
4122 info_level = SVAL(params,0);
4124 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4125 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4126 DEBUG(0,("call_trans2qfsinfo: encryption required "
4127 "and info level 0x%x sent.\n",
4128 (unsigned int)info_level));
4129 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4130 return;
4134 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4136 status = smbd_do_qfsinfo(req->xconn, conn, req,
4137 info_level,
4138 req->flags2,
4139 max_data_bytes,
4140 &fixed_portion,
4141 NULL,
4142 ppdata, &data_len);
4143 if (!NT_STATUS_IS_OK(status)) {
4144 reply_nterror(req, status);
4145 return;
4148 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4149 max_data_bytes);
4151 DEBUG( 4, ( "%s info_level = %d\n",
4152 smb_fn_name(req->cmd), info_level) );
4154 return;
4157 /****************************************************************************
4158 Reply to a TRANS2_SETFSINFO (set filesystem info).
4159 ****************************************************************************/
4161 static void call_trans2setfsinfo(connection_struct *conn,
4162 struct smb_request *req,
4163 char **pparams, int total_params,
4164 char **ppdata, int total_data,
4165 unsigned int max_data_bytes)
4167 struct smbXsrv_connection *xconn = req->xconn;
4168 char *pdata = *ppdata;
4169 char *params = *pparams;
4170 uint16_t info_level;
4172 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4173 lp_servicename(talloc_tos(), SNUM(conn))));
4175 /* */
4176 if (total_params < 4) {
4177 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4178 total_params));
4179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4180 return;
4183 info_level = SVAL(params,2);
4185 if (IS_IPC(conn)) {
4186 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4187 info_level != SMB_SET_CIFS_UNIX_INFO) {
4188 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4189 "info level (0x%x) on IPC$.\n",
4190 (unsigned int)info_level));
4191 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4192 return;
4196 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4197 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4198 DEBUG(0,("call_trans2setfsinfo: encryption required "
4199 "and info level 0x%x sent.\n",
4200 (unsigned int)info_level));
4201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4202 return;
4206 switch(info_level) {
4207 case SMB_SET_CIFS_UNIX_INFO:
4208 if (!lp_unix_extensions()) {
4209 DEBUG(2,("call_trans2setfsinfo: "
4210 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4211 "unix extensions off\n"));
4212 reply_nterror(req,
4213 NT_STATUS_INVALID_LEVEL);
4214 return;
4217 /* There should be 12 bytes of capabilities set. */
4218 if (total_data < 12) {
4219 reply_nterror(
4220 req,
4221 NT_STATUS_INVALID_PARAMETER);
4222 return;
4224 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4225 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4226 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4227 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4228 /* Just print these values for now. */
4229 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4230 "major = %u, minor = %u cap_low = 0x%x, "
4231 "cap_high = 0x%xn",
4232 (unsigned int)xconn->
4233 smb1.unix_info.client_major,
4234 (unsigned int)xconn->
4235 smb1.unix_info.client_minor,
4236 (unsigned int)xconn->
4237 smb1.unix_info.client_cap_low,
4238 (unsigned int)xconn->
4239 smb1.unix_info.client_cap_high));
4241 /* Here is where we must switch to posix pathname processing... */
4242 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4243 lp_set_posix_pathnames();
4244 mangle_change_to_posix();
4247 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4248 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4249 /* Client that knows how to do posix locks,
4250 * but not posix open/mkdir operations. Set a
4251 * default type for read/write checks. */
4253 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4256 break;
4258 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4260 NTSTATUS status;
4261 size_t param_len = 0;
4262 size_t data_len = total_data;
4264 if (!lp_unix_extensions()) {
4265 reply_nterror(
4266 req,
4267 NT_STATUS_INVALID_LEVEL);
4268 return;
4271 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4272 reply_nterror(
4273 req,
4274 NT_STATUS_NOT_SUPPORTED);
4275 return;
4278 if (xconn->smb1.echo_handler.trusted_fde) {
4279 DEBUG( 2,("call_trans2setfsinfo: "
4280 "request transport encryption disabled"
4281 "with 'fork echo handler = yes'\n"));
4282 reply_nterror(
4283 req,
4284 NT_STATUS_NOT_SUPPORTED);
4285 return;
4288 DEBUG( 4,("call_trans2setfsinfo: "
4289 "request transport encryption.\n"));
4291 status = srv_request_encryption_setup(conn,
4292 (unsigned char **)ppdata,
4293 &data_len,
4294 (unsigned char **)pparams,
4295 &param_len);
4297 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4298 !NT_STATUS_IS_OK(status)) {
4299 reply_nterror(req, status);
4300 return;
4303 send_trans2_replies(conn, req,
4304 NT_STATUS_OK,
4305 *pparams,
4306 param_len,
4307 *ppdata,
4308 data_len,
4309 max_data_bytes);
4311 if (NT_STATUS_IS_OK(status)) {
4312 /* Server-side transport
4313 * encryption is now *on*. */
4314 status = srv_encryption_start(conn);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 char *reason = talloc_asprintf(talloc_tos(),
4317 "Failure in setting "
4318 "up encrypted transport: %s",
4319 nt_errstr(status));
4320 exit_server_cleanly(reason);
4323 return;
4326 case SMB_FS_QUOTA_INFORMATION:
4328 NTSTATUS status;
4329 DATA_BLOB qdata = {
4330 .data = (uint8_t *)pdata,
4331 .length = total_data
4333 files_struct *fsp = NULL;
4334 fsp = file_fsp(req, SVAL(params,0));
4336 status = smb_set_fsquota(conn,
4337 req,
4338 fsp,
4339 &qdata);
4340 if (!NT_STATUS_IS_OK(status)) {
4341 reply_nterror(req, status);
4342 return;
4344 break;
4346 default:
4347 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4348 info_level));
4349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4350 return;
4351 break;
4355 * sending this reply works fine,
4356 * but I'm not sure it's the same
4357 * like windows do...
4358 * --metze
4360 reply_outbuf(req, 10, 0);
4363 #if defined(HAVE_POSIX_ACLS)
4364 /****************************************************************************
4365 Utility function to count the number of entries in a POSIX acl.
4366 ****************************************************************************/
4368 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4370 unsigned int ace_count = 0;
4371 int entry_id = SMB_ACL_FIRST_ENTRY;
4372 SMB_ACL_ENTRY_T entry;
4374 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4375 /* get_next... */
4376 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4377 entry_id = SMB_ACL_NEXT_ENTRY;
4379 ace_count++;
4381 return ace_count;
4384 /****************************************************************************
4385 Utility function to marshall a POSIX acl into wire format.
4386 ****************************************************************************/
4388 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4390 int entry_id = SMB_ACL_FIRST_ENTRY;
4391 SMB_ACL_ENTRY_T entry;
4393 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4394 SMB_ACL_TAG_T tagtype;
4395 SMB_ACL_PERMSET_T permset;
4396 unsigned char perms = 0;
4397 unsigned int own_grp;
4399 /* get_next... */
4400 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4401 entry_id = SMB_ACL_NEXT_ENTRY;
4404 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4405 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4406 return False;
4409 if (sys_acl_get_permset(entry, &permset) == -1) {
4410 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4411 return False;
4414 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4415 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4416 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4418 SCVAL(pdata,1,perms);
4420 switch (tagtype) {
4421 case SMB_ACL_USER_OBJ:
4422 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4423 own_grp = (unsigned int)pst->st_ex_uid;
4424 SIVAL(pdata,2,own_grp);
4425 SIVAL(pdata,6,0);
4426 break;
4427 case SMB_ACL_USER:
4429 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4430 if (!puid) {
4431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4432 return False;
4434 own_grp = (unsigned int)*puid;
4435 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4436 SIVAL(pdata,2,own_grp);
4437 SIVAL(pdata,6,0);
4438 break;
4440 case SMB_ACL_GROUP_OBJ:
4441 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4442 own_grp = (unsigned int)pst->st_ex_gid;
4443 SIVAL(pdata,2,own_grp);
4444 SIVAL(pdata,6,0);
4445 break;
4446 case SMB_ACL_GROUP:
4448 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4449 if (!pgid) {
4450 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4451 return False;
4453 own_grp = (unsigned int)*pgid;
4454 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4455 SIVAL(pdata,2,own_grp);
4456 SIVAL(pdata,6,0);
4457 break;
4459 case SMB_ACL_MASK:
4460 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4461 SIVAL(pdata,2,0xFFFFFFFF);
4462 SIVAL(pdata,6,0xFFFFFFFF);
4463 break;
4464 case SMB_ACL_OTHER:
4465 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4466 SIVAL(pdata,2,0xFFFFFFFF);
4467 SIVAL(pdata,6,0xFFFFFFFF);
4468 break;
4469 default:
4470 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4471 return False;
4473 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4476 return True;
4478 #endif
4480 /****************************************************************************
4481 Store the FILE_UNIX_BASIC info.
4482 ****************************************************************************/
4484 static char *store_file_unix_basic(connection_struct *conn,
4485 char *pdata,
4486 files_struct *fsp,
4487 const SMB_STRUCT_STAT *psbuf)
4489 uint64_t file_index = get_FileIndex(conn, psbuf);
4490 dev_t devno;
4492 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4493 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4495 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4496 pdata += 8;
4498 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4499 pdata += 8;
4501 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4502 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4503 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4504 pdata += 24;
4506 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4507 SIVAL(pdata,4,0);
4508 pdata += 8;
4510 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4511 SIVAL(pdata,4,0);
4512 pdata += 8;
4514 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4515 pdata += 4;
4517 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4518 devno = psbuf->st_ex_rdev;
4519 } else {
4520 devno = psbuf->st_ex_dev;
4523 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4524 SIVAL(pdata,4,0);
4525 pdata += 8;
4527 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4528 SIVAL(pdata,4,0);
4529 pdata += 8;
4531 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4532 pdata += 8;
4534 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4535 SIVAL(pdata,4,0);
4536 pdata += 8;
4538 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4539 SIVAL(pdata,4,0);
4540 pdata += 8;
4542 return pdata;
4545 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4546 * the chflags(2) (or equivalent) flags.
4548 * XXX: this really should be behind the VFS interface. To do this, we would
4549 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4550 * Each VFS module could then implement its own mapping as appropriate for the
4551 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4553 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4554 info2_flags_map[] =
4556 #ifdef UF_NODUMP
4557 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4558 #endif
4560 #ifdef UF_IMMUTABLE
4561 { UF_IMMUTABLE, EXT_IMMUTABLE },
4562 #endif
4564 #ifdef UF_APPEND
4565 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4566 #endif
4568 #ifdef UF_HIDDEN
4569 { UF_HIDDEN, EXT_HIDDEN },
4570 #endif
4572 /* Do not remove. We need to guarantee that this array has at least one
4573 * entry to build on HP-UX.
4575 { 0, 0 }
4579 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4580 uint32_t *smb_fflags, uint32_t *smb_fmask)
4582 int i;
4584 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4585 *smb_fmask |= info2_flags_map[i].smb_fflag;
4586 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4587 *smb_fflags |= info2_flags_map[i].smb_fflag;
4592 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4593 const uint32_t smb_fflags,
4594 const uint32_t smb_fmask,
4595 int *stat_fflags)
4597 uint32_t max_fmask = 0;
4598 int i;
4600 *stat_fflags = psbuf->st_ex_flags;
4602 /* For each flags requested in smb_fmask, check the state of the
4603 * corresponding flag in smb_fflags and set or clear the matching
4604 * stat flag.
4607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4608 max_fmask |= info2_flags_map[i].smb_fflag;
4609 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4610 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4611 *stat_fflags |= info2_flags_map[i].stat_fflag;
4612 } else {
4613 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4618 /* If smb_fmask is asking to set any bits that are not supported by
4619 * our flag mappings, we should fail.
4621 if ((smb_fmask & max_fmask) != smb_fmask) {
4622 return False;
4625 return True;
4629 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4630 * of file flags and birth (create) time.
4632 static char *store_file_unix_basic_info2(connection_struct *conn,
4633 char *pdata,
4634 files_struct *fsp,
4635 const SMB_STRUCT_STAT *psbuf)
4637 uint32_t file_flags = 0;
4638 uint32_t flags_mask = 0;
4640 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4642 /* Create (birth) time 64 bit */
4643 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4644 pdata += 8;
4646 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4647 SIVAL(pdata, 0, file_flags); /* flags */
4648 SIVAL(pdata, 4, flags_mask); /* mask */
4649 pdata += 8;
4651 return pdata;
4654 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4655 const struct stream_struct *streams,
4656 char *data,
4657 unsigned int max_data_bytes,
4658 unsigned int *data_size)
4660 unsigned int i;
4661 unsigned int ofs = 0;
4663 if (max_data_bytes < 32) {
4664 return NT_STATUS_INFO_LENGTH_MISMATCH;
4667 for (i = 0; i < num_streams; i++) {
4668 unsigned int next_offset;
4669 size_t namelen;
4670 smb_ucs2_t *namebuf;
4672 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4673 streams[i].name, &namelen) ||
4674 namelen <= 2)
4676 return NT_STATUS_INVALID_PARAMETER;
4680 * name_buf is now null-terminated, we need to marshall as not
4681 * terminated
4684 namelen -= 2;
4687 * We cannot overflow ...
4689 if ((ofs + 24 + namelen) > max_data_bytes) {
4690 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4691 i));
4692 TALLOC_FREE(namebuf);
4693 return STATUS_BUFFER_OVERFLOW;
4696 SIVAL(data, ofs+4, namelen);
4697 SOFF_T(data, ofs+8, streams[i].size);
4698 SOFF_T(data, ofs+16, streams[i].alloc_size);
4699 memcpy(data+ofs+24, namebuf, namelen);
4700 TALLOC_FREE(namebuf);
4702 next_offset = ofs + 24 + namelen;
4704 if (i == num_streams-1) {
4705 SIVAL(data, ofs, 0);
4707 else {
4708 unsigned int align = ndr_align_size(next_offset, 8);
4710 if ((next_offset + align) > max_data_bytes) {
4711 DEBUG(10, ("refusing to overflow align "
4712 "reply at stream %u\n",
4713 i));
4714 TALLOC_FREE(namebuf);
4715 return STATUS_BUFFER_OVERFLOW;
4718 memset(data+next_offset, 0, align);
4719 next_offset += align;
4721 SIVAL(data, ofs, next_offset - ofs);
4722 ofs = next_offset;
4725 ofs = next_offset;
4728 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4730 *data_size = ofs;
4732 return NT_STATUS_OK;
4735 /****************************************************************************
4736 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4737 ****************************************************************************/
4739 static void call_trans2qpipeinfo(connection_struct *conn,
4740 struct smb_request *req,
4741 unsigned int tran_call,
4742 char **pparams, int total_params,
4743 char **ppdata, int total_data,
4744 unsigned int max_data_bytes)
4746 char *params = *pparams;
4747 char *pdata = *ppdata;
4748 unsigned int data_size = 0;
4749 unsigned int param_size = 2;
4750 uint16_t info_level;
4751 files_struct *fsp;
4753 if (!params) {
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4755 return;
4758 if (total_params < 4) {
4759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760 return;
4763 fsp = file_fsp(req, SVAL(params,0));
4764 if (!fsp_is_np(fsp)) {
4765 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4766 return;
4769 info_level = SVAL(params,2);
4771 *pparams = (char *)SMB_REALLOC(*pparams,2);
4772 if (*pparams == NULL) {
4773 reply_nterror(req, NT_STATUS_NO_MEMORY);
4774 return;
4776 params = *pparams;
4777 SSVAL(params,0,0);
4778 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4780 return;
4782 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4783 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4784 if (*ppdata == NULL ) {
4785 reply_nterror(req, NT_STATUS_NO_MEMORY);
4786 return;
4788 pdata = *ppdata;
4790 switch (info_level) {
4791 case SMB_FILE_STANDARD_INFORMATION:
4792 memset(pdata,0,24);
4793 SOFF_T(pdata,0,4096LL);
4794 SIVAL(pdata,16,1);
4795 SIVAL(pdata,20,1);
4796 data_size = 24;
4797 break;
4799 default:
4800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4801 return;
4804 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4805 max_data_bytes);
4807 return;
4810 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4811 TALLOC_CTX *mem_ctx,
4812 uint16_t info_level,
4813 files_struct *fsp,
4814 struct smb_filename *smb_fname,
4815 bool delete_pending,
4816 struct timespec write_time_ts,
4817 struct ea_list *ea_list,
4818 int lock_data_count,
4819 char *lock_data,
4820 uint16_t flags2,
4821 unsigned int max_data_bytes,
4822 size_t *fixed_portion,
4823 char **ppdata,
4824 unsigned int *pdata_size)
4826 char *pdata = *ppdata;
4827 char *dstart, *dend;
4828 unsigned int data_size;
4829 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4830 time_t create_time, mtime, atime, c_time;
4831 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4832 char *p;
4833 char *base_name;
4834 char *dos_fname;
4835 int mode;
4836 int nlink;
4837 NTSTATUS status;
4838 uint64_t file_size = 0;
4839 uint64_t pos = 0;
4840 uint64_t allocation_size = 0;
4841 uint64_t file_index = 0;
4842 uint32_t access_mask = 0;
4843 size_t len = 0;
4845 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4846 return NT_STATUS_INVALID_LEVEL;
4849 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4850 smb_fname_str_dbg(smb_fname),
4851 fsp_fnum_dbg(fsp),
4852 info_level, max_data_bytes));
4854 mode = dos_mode(conn, smb_fname);
4855 nlink = psbuf->st_ex_nlink;
4857 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4858 nlink = 1;
4861 if ((nlink > 0) && delete_pending) {
4862 nlink -= 1;
4865 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4866 return NT_STATUS_INVALID_PARAMETER;
4869 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4870 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4871 if (*ppdata == NULL) {
4872 return NT_STATUS_NO_MEMORY;
4874 pdata = *ppdata;
4875 dstart = pdata;
4876 dend = dstart + data_size - 1;
4878 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4879 update_stat_ex_mtime(psbuf, write_time_ts);
4882 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4883 mtime_ts = psbuf->st_ex_mtime;
4884 atime_ts = psbuf->st_ex_atime;
4885 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4887 if (lp_dos_filetime_resolution(SNUM(conn))) {
4888 dos_filetime_timespec(&create_time_ts);
4889 dos_filetime_timespec(&mtime_ts);
4890 dos_filetime_timespec(&atime_ts);
4891 dos_filetime_timespec(&ctime_ts);
4894 create_time = convert_timespec_to_time_t(create_time_ts);
4895 mtime = convert_timespec_to_time_t(mtime_ts);
4896 atime = convert_timespec_to_time_t(atime_ts);
4897 c_time = convert_timespec_to_time_t(ctime_ts);
4899 p = strrchr_m(smb_fname->base_name,'/');
4900 if (!p)
4901 base_name = smb_fname->base_name;
4902 else
4903 base_name = p+1;
4905 /* NT expects the name to be in an exact form of the *full*
4906 filename. See the trans2 torture test */
4907 if (ISDOT(base_name)) {
4908 dos_fname = talloc_strdup(mem_ctx, "\\");
4909 if (!dos_fname) {
4910 return NT_STATUS_NO_MEMORY;
4912 } else {
4913 dos_fname = talloc_asprintf(mem_ctx,
4914 "\\%s",
4915 smb_fname->base_name);
4916 if (!dos_fname) {
4917 return NT_STATUS_NO_MEMORY;
4919 if (is_ntfs_stream_smb_fname(smb_fname)) {
4920 dos_fname = talloc_asprintf(dos_fname, "%s",
4921 smb_fname->stream_name);
4922 if (!dos_fname) {
4923 return NT_STATUS_NO_MEMORY;
4927 string_replace(dos_fname, '/', '\\');
4930 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4932 if (!fsp) {
4933 /* Do we have this path open ? */
4934 files_struct *fsp1;
4935 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4936 fsp1 = file_find_di_first(conn->sconn, fileid);
4937 if (fsp1 && fsp1->initial_allocation_size) {
4938 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4942 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4943 file_size = get_file_size_stat(psbuf);
4946 if (fsp) {
4947 pos = fsp->fh->position_information;
4950 if (fsp) {
4951 access_mask = fsp->access_mask;
4952 } else {
4953 /* GENERIC_EXECUTE mapping from Windows */
4954 access_mask = 0x12019F;
4957 /* This should be an index number - looks like
4958 dev/ino to me :-)
4960 I think this causes us to fail the IFSKIT
4961 BasicFileInformationTest. -tpot */
4962 file_index = get_FileIndex(conn, psbuf);
4964 *fixed_portion = 0;
4966 switch (info_level) {
4967 case SMB_INFO_STANDARD:
4968 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4969 data_size = 22;
4970 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4971 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4972 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4973 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4974 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4975 SSVAL(pdata,l1_attrFile,mode);
4976 break;
4978 case SMB_INFO_QUERY_EA_SIZE:
4980 unsigned int ea_size =
4981 estimate_ea_size(conn, fsp,
4982 smb_fname);
4983 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4984 data_size = 26;
4985 srv_put_dos_date2(pdata,0,create_time);
4986 srv_put_dos_date2(pdata,4,atime);
4987 srv_put_dos_date2(pdata,8,mtime); /* write time */
4988 SIVAL(pdata,12,(uint32_t)file_size);
4989 SIVAL(pdata,16,(uint32_t)allocation_size);
4990 SSVAL(pdata,20,mode);
4991 SIVAL(pdata,22,ea_size);
4992 break;
4995 case SMB_INFO_IS_NAME_VALID:
4996 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4997 if (fsp) {
4998 /* os/2 needs this ? really ?*/
4999 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5001 /* This is only reached for qpathinfo */
5002 data_size = 0;
5003 break;
5005 case SMB_INFO_QUERY_EAS_FROM_LIST:
5007 size_t total_ea_len = 0;
5008 struct ea_list *ea_file_list = NULL;
5009 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5011 status =
5012 get_ea_list_from_file(mem_ctx, conn, fsp,
5013 smb_fname,
5014 &total_ea_len, &ea_file_list);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 return status;
5019 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5021 if (!ea_list || (total_ea_len > data_size)) {
5022 data_size = 4;
5023 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5024 break;
5027 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5028 break;
5031 case SMB_INFO_QUERY_ALL_EAS:
5033 /* We have data_size bytes to put EA's into. */
5034 size_t total_ea_len = 0;
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5037 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5038 smb_fname,
5039 &total_ea_len, &ea_list);
5040 if (!NT_STATUS_IS_OK(status)) {
5041 return status;
5044 if (!ea_list || (total_ea_len > data_size)) {
5045 data_size = 4;
5046 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5047 break;
5050 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5051 break;
5054 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5056 /* This is FileFullEaInformation - 0xF which maps to
5057 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5059 /* We have data_size bytes to put EA's into. */
5060 size_t total_ea_len = 0;
5061 struct ea_list *ea_file_list = NULL;
5063 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5065 /*TODO: add filtering and index handling */
5067 status =
5068 get_ea_list_from_file(mem_ctx, conn, fsp,
5069 smb_fname,
5070 &total_ea_len, &ea_file_list);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 return status;
5074 if (!ea_file_list) {
5075 return NT_STATUS_NO_EAS_ON_FILE;
5078 status = fill_ea_chained_buffer(mem_ctx,
5079 pdata,
5080 data_size,
5081 &data_size,
5082 conn, ea_file_list);
5083 if (!NT_STATUS_IS_OK(status)) {
5084 return status;
5086 break;
5089 case SMB_FILE_BASIC_INFORMATION:
5090 case SMB_QUERY_FILE_BASIC_INFO:
5092 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5094 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5095 } else {
5096 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5097 data_size = 40;
5098 SIVAL(pdata,36,0);
5100 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5101 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5102 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5103 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5104 SIVAL(pdata,32,mode);
5106 DEBUG(5,("SMB_QFBI - "));
5107 DEBUG(5,("create: %s ", ctime(&create_time)));
5108 DEBUG(5,("access: %s ", ctime(&atime)));
5109 DEBUG(5,("write: %s ", ctime(&mtime)));
5110 DEBUG(5,("change: %s ", ctime(&c_time)));
5111 DEBUG(5,("mode: %x\n", mode));
5112 *fixed_portion = data_size;
5113 break;
5115 case SMB_FILE_STANDARD_INFORMATION:
5116 case SMB_QUERY_FILE_STANDARD_INFO:
5118 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5119 data_size = 24;
5120 SOFF_T(pdata,0,allocation_size);
5121 SOFF_T(pdata,8,file_size);
5122 SIVAL(pdata,16,nlink);
5123 SCVAL(pdata,20,delete_pending?1:0);
5124 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5125 SSVAL(pdata,22,0); /* Padding. */
5126 *fixed_portion = 24;
5127 break;
5129 case SMB_FILE_EA_INFORMATION:
5130 case SMB_QUERY_FILE_EA_INFO:
5132 unsigned int ea_size =
5133 estimate_ea_size(conn, fsp, smb_fname);
5134 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5135 data_size = 4;
5136 *fixed_portion = 4;
5137 SIVAL(pdata,0,ea_size);
5138 break;
5141 /* Get the 8.3 name - used if NT SMB was negotiated. */
5142 case SMB_QUERY_FILE_ALT_NAME_INFO:
5143 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5145 char mangled_name[13];
5146 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5147 if (!name_to_8_3(base_name,mangled_name,
5148 True,conn->params)) {
5149 return NT_STATUS_NO_MEMORY;
5151 status = srvstr_push(dstart, flags2,
5152 pdata+4, mangled_name,
5153 PTR_DIFF(dend, pdata+4),
5154 STR_UNICODE, &len);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 return status;
5158 data_size = 4 + len;
5159 SIVAL(pdata,0,len);
5160 *fixed_portion = 8;
5161 break;
5164 case SMB_QUERY_FILE_NAME_INFO:
5167 this must be *exactly* right for ACLs on mapped drives to work
5169 status = srvstr_push(dstart, flags2,
5170 pdata+4, dos_fname,
5171 PTR_DIFF(dend, pdata+4),
5172 STR_UNICODE, &len);
5173 if (!NT_STATUS_IS_OK(status)) {
5174 return status;
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5177 data_size = 4 + len;
5178 SIVAL(pdata,0,len);
5179 break;
5182 case SMB_FILE_ALLOCATION_INFORMATION:
5183 case SMB_QUERY_FILE_ALLOCATION_INFO:
5184 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5185 data_size = 8;
5186 SOFF_T(pdata,0,allocation_size);
5187 break;
5189 case SMB_FILE_END_OF_FILE_INFORMATION:
5190 case SMB_QUERY_FILE_END_OF_FILEINFO:
5191 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5192 data_size = 8;
5193 SOFF_T(pdata,0,file_size);
5194 break;
5196 case SMB_QUERY_FILE_ALL_INFO:
5197 case SMB_FILE_ALL_INFORMATION:
5199 unsigned int ea_size =
5200 estimate_ea_size(conn, fsp, smb_fname);
5201 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5202 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5203 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5204 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5205 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5206 SIVAL(pdata,32,mode);
5207 SIVAL(pdata,36,0); /* padding. */
5208 pdata += 40;
5209 SOFF_T(pdata,0,allocation_size);
5210 SOFF_T(pdata,8,file_size);
5211 SIVAL(pdata,16,nlink);
5212 SCVAL(pdata,20,delete_pending);
5213 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5214 SSVAL(pdata,22,0);
5215 pdata += 24;
5216 SIVAL(pdata,0,ea_size);
5217 pdata += 4; /* EA info */
5218 status = srvstr_push(dstart, flags2,
5219 pdata+4, dos_fname,
5220 PTR_DIFF(dend, pdata+4),
5221 STR_UNICODE, &len);
5222 if (!NT_STATUS_IS_OK(status)) {
5223 return status;
5225 SIVAL(pdata,0,len);
5226 pdata += 4 + len;
5227 data_size = PTR_DIFF(pdata,(*ppdata));
5228 *fixed_portion = 10;
5229 break;
5232 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5234 unsigned int ea_size =
5235 estimate_ea_size(conn, fsp, smb_fname);
5236 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5237 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5238 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5239 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5240 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5241 SIVAL(pdata, 0x20, mode);
5242 SIVAL(pdata, 0x24, 0); /* padding. */
5243 SBVAL(pdata, 0x28, allocation_size);
5244 SBVAL(pdata, 0x30, file_size);
5245 SIVAL(pdata, 0x38, nlink);
5246 SCVAL(pdata, 0x3C, delete_pending);
5247 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5248 SSVAL(pdata, 0x3E, 0); /* padding */
5249 SBVAL(pdata, 0x40, file_index);
5250 SIVAL(pdata, 0x48, ea_size);
5251 SIVAL(pdata, 0x4C, access_mask);
5252 SBVAL(pdata, 0x50, pos);
5253 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5254 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5256 pdata += 0x60;
5258 status = srvstr_push(dstart, flags2,
5259 pdata+4, dos_fname,
5260 PTR_DIFF(dend, pdata+4),
5261 STR_UNICODE, &len);
5262 if (!NT_STATUS_IS_OK(status)) {
5263 return status;
5265 SIVAL(pdata,0,len);
5266 pdata += 4 + len;
5267 data_size = PTR_DIFF(pdata,(*ppdata));
5268 *fixed_portion = 104;
5269 break;
5271 case SMB_FILE_INTERNAL_INFORMATION:
5273 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5274 SBVAL(pdata, 0, file_index);
5275 data_size = 8;
5276 *fixed_portion = 8;
5277 break;
5279 case SMB_FILE_ACCESS_INFORMATION:
5280 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5281 SIVAL(pdata, 0, access_mask);
5282 data_size = 4;
5283 *fixed_portion = 4;
5284 break;
5286 case SMB_FILE_NAME_INFORMATION:
5287 /* Pathname with leading '\'. */
5289 size_t byte_len;
5290 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5291 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5292 SIVAL(pdata,0,byte_len);
5293 data_size = 4 + byte_len;
5294 break;
5297 case SMB_FILE_DISPOSITION_INFORMATION:
5298 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5299 data_size = 1;
5300 SCVAL(pdata,0,delete_pending);
5301 *fixed_portion = 1;
5302 break;
5304 case SMB_FILE_POSITION_INFORMATION:
5305 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5306 data_size = 8;
5307 SOFF_T(pdata,0,pos);
5308 *fixed_portion = 8;
5309 break;
5311 case SMB_FILE_MODE_INFORMATION:
5312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5313 SIVAL(pdata,0,mode);
5314 data_size = 4;
5315 *fixed_portion = 4;
5316 break;
5318 case SMB_FILE_ALIGNMENT_INFORMATION:
5319 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5320 SIVAL(pdata,0,0); /* No alignment needed. */
5321 data_size = 4;
5322 *fixed_portion = 4;
5323 break;
5326 * NT4 server just returns "invalid query" to this - if we try
5327 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5328 * want this. JRA.
5330 /* The first statement above is false - verified using Thursby
5331 * client against NT4 -- gcolley.
5333 case SMB_QUERY_FILE_STREAM_INFO:
5334 case SMB_FILE_STREAM_INFORMATION: {
5335 unsigned int num_streams = 0;
5336 struct stream_struct *streams = NULL;
5338 DEBUG(10,("smbd_do_qfilepathinfo: "
5339 "SMB_FILE_STREAM_INFORMATION\n"));
5341 if (is_ntfs_stream_smb_fname(smb_fname)) {
5342 return NT_STATUS_INVALID_PARAMETER;
5345 status = vfs_streaminfo(conn,
5346 fsp,
5347 smb_fname,
5348 talloc_tos(),
5349 &num_streams,
5350 &streams);
5352 if (!NT_STATUS_IS_OK(status)) {
5353 DEBUG(10, ("could not get stream info: %s\n",
5354 nt_errstr(status)));
5355 return status;
5358 status = marshall_stream_info(num_streams, streams,
5359 pdata, max_data_bytes,
5360 &data_size);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 DEBUG(10, ("marshall_stream_info failed: %s\n",
5364 nt_errstr(status)));
5365 TALLOC_FREE(streams);
5366 return status;
5369 TALLOC_FREE(streams);
5371 *fixed_portion = 32;
5373 break;
5375 case SMB_QUERY_COMPRESSION_INFO:
5376 case SMB_FILE_COMPRESSION_INFORMATION:
5377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5378 SOFF_T(pdata,0,file_size);
5379 SIVAL(pdata,8,0); /* ??? */
5380 SIVAL(pdata,12,0); /* ??? */
5381 data_size = 16;
5382 *fixed_portion = 16;
5383 break;
5385 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5386 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5387 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5388 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5389 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5390 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5391 SOFF_T(pdata,32,allocation_size);
5392 SOFF_T(pdata,40,file_size);
5393 SIVAL(pdata,48,mode);
5394 SIVAL(pdata,52,0); /* ??? */
5395 data_size = 56;
5396 *fixed_portion = 56;
5397 break;
5399 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5401 SIVAL(pdata,0,mode);
5402 SIVAL(pdata,4,0);
5403 data_size = 8;
5404 *fixed_portion = 8;
5405 break;
5408 * CIFS UNIX Extensions.
5411 case SMB_QUERY_FILE_UNIX_BASIC:
5413 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5414 data_size = PTR_DIFF(pdata,(*ppdata));
5416 DEBUG(4,("smbd_do_qfilepathinfo: "
5417 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5418 dump_data(4, (uint8_t *)(*ppdata), data_size);
5420 break;
5422 case SMB_QUERY_FILE_UNIX_INFO2:
5424 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5425 data_size = PTR_DIFF(pdata,(*ppdata));
5428 int i;
5429 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5431 for (i=0; i<100; i++)
5432 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5433 DEBUG(4,("\n"));
5436 break;
5438 case SMB_QUERY_FILE_UNIX_LINK:
5440 int link_len = 0;
5441 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5443 if (!buffer) {
5444 return NT_STATUS_NO_MEMORY;
5447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5448 #ifdef S_ISLNK
5449 if(!S_ISLNK(psbuf->st_ex_mode)) {
5450 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5452 #else
5453 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5454 #endif
5455 link_len = SMB_VFS_READLINK(conn,
5456 smb_fname->base_name,
5457 buffer, PATH_MAX);
5458 if (link_len == -1) {
5459 return map_nt_error_from_unix(errno);
5461 buffer[link_len] = 0;
5462 status = srvstr_push(dstart, flags2,
5463 pdata, buffer,
5464 PTR_DIFF(dend, pdata),
5465 STR_TERMINATE, &len);
5466 if (!NT_STATUS_IS_OK(status)) {
5467 return status;
5469 pdata += len;
5470 data_size = PTR_DIFF(pdata,(*ppdata));
5472 break;
5475 #if defined(HAVE_POSIX_ACLS)
5476 case SMB_QUERY_POSIX_ACL:
5478 SMB_ACL_T file_acl = NULL;
5479 SMB_ACL_T def_acl = NULL;
5480 uint16_t num_file_acls = 0;
5481 uint16_t num_def_acls = 0;
5483 status = refuse_symlink(conn,
5484 fsp,
5485 smb_fname);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 return status;
5490 if (fsp && fsp->fh->fd != -1) {
5491 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5492 talloc_tos());
5493 } else {
5494 file_acl =
5495 SMB_VFS_SYS_ACL_GET_FILE(conn,
5496 smb_fname->base_name,
5497 SMB_ACL_TYPE_ACCESS,
5498 talloc_tos());
5501 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5502 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5503 "not implemented on "
5504 "filesystem containing %s\n",
5505 smb_fname->base_name));
5506 return NT_STATUS_NOT_IMPLEMENTED;
5509 if (S_ISDIR(psbuf->st_ex_mode)) {
5510 if (fsp && fsp->is_directory) {
5511 def_acl =
5512 SMB_VFS_SYS_ACL_GET_FILE(
5513 conn,
5514 fsp->fsp_name->base_name,
5515 SMB_ACL_TYPE_DEFAULT,
5516 talloc_tos());
5517 } else {
5518 def_acl =
5519 SMB_VFS_SYS_ACL_GET_FILE(
5520 conn,
5521 smb_fname->base_name,
5522 SMB_ACL_TYPE_DEFAULT,
5523 talloc_tos());
5525 def_acl = free_empty_sys_acl(conn, def_acl);
5528 num_file_acls = count_acl_entries(conn, file_acl);
5529 num_def_acls = count_acl_entries(conn, def_acl);
5531 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5532 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5533 data_size,
5534 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5535 SMB_POSIX_ACL_HEADER_SIZE) ));
5536 if (file_acl) {
5537 TALLOC_FREE(file_acl);
5539 if (def_acl) {
5540 TALLOC_FREE(def_acl);
5542 return NT_STATUS_BUFFER_TOO_SMALL;
5545 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5546 SSVAL(pdata,2,num_file_acls);
5547 SSVAL(pdata,4,num_def_acls);
5548 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5549 if (file_acl) {
5550 TALLOC_FREE(file_acl);
5552 if (def_acl) {
5553 TALLOC_FREE(def_acl);
5555 return NT_STATUS_INTERNAL_ERROR;
5557 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5558 if (file_acl) {
5559 TALLOC_FREE(file_acl);
5561 if (def_acl) {
5562 TALLOC_FREE(def_acl);
5564 return NT_STATUS_INTERNAL_ERROR;
5567 if (file_acl) {
5568 TALLOC_FREE(file_acl);
5570 if (def_acl) {
5571 TALLOC_FREE(def_acl);
5573 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5574 break;
5576 #endif
5579 case SMB_QUERY_POSIX_LOCK:
5581 uint64_t count;
5582 uint64_t offset;
5583 uint64_t smblctx;
5584 enum brl_type lock_type;
5586 /* We need an open file with a real fd for this. */
5587 if (!fsp || fsp->fh->fd == -1) {
5588 return NT_STATUS_INVALID_LEVEL;
5591 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5592 return NT_STATUS_INVALID_PARAMETER;
5595 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5596 case POSIX_LOCK_TYPE_READ:
5597 lock_type = READ_LOCK;
5598 break;
5599 case POSIX_LOCK_TYPE_WRITE:
5600 lock_type = WRITE_LOCK;
5601 break;
5602 case POSIX_LOCK_TYPE_UNLOCK:
5603 default:
5604 /* There's no point in asking for an unlock... */
5605 return NT_STATUS_INVALID_PARAMETER;
5608 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5609 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5610 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5612 status = query_lock(fsp,
5613 &smblctx,
5614 &count,
5615 &offset,
5616 &lock_type,
5617 POSIX_LOCK);
5619 if (ERROR_WAS_LOCK_DENIED(status)) {
5620 /* Here we need to report who has it locked... */
5621 data_size = POSIX_LOCK_DATA_SIZE;
5623 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5624 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5625 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5626 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5627 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5629 } else if (NT_STATUS_IS_OK(status)) {
5630 /* For success we just return a copy of what we sent
5631 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5632 data_size = POSIX_LOCK_DATA_SIZE;
5633 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5634 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5635 } else {
5636 return status;
5638 break;
5641 default:
5642 return NT_STATUS_INVALID_LEVEL;
5645 *pdata_size = data_size;
5646 return NT_STATUS_OK;
5649 /****************************************************************************
5650 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5651 file name or file id).
5652 ****************************************************************************/
5654 static void call_trans2qfilepathinfo(connection_struct *conn,
5655 struct smb_request *req,
5656 unsigned int tran_call,
5657 char **pparams, int total_params,
5658 char **ppdata, int total_data,
5659 unsigned int max_data_bytes)
5661 char *params = *pparams;
5662 char *pdata = *ppdata;
5663 uint16_t info_level;
5664 unsigned int data_size = 0;
5665 unsigned int param_size = 2;
5666 struct smb_filename *smb_fname = NULL;
5667 bool delete_pending = False;
5668 struct timespec write_time_ts;
5669 files_struct *fsp = NULL;
5670 struct file_id fileid;
5671 struct ea_list *ea_list = NULL;
5672 int lock_data_count = 0;
5673 char *lock_data = NULL;
5674 size_t fixed_portion;
5675 NTSTATUS status = NT_STATUS_OK;
5677 if (!params) {
5678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5679 return;
5682 ZERO_STRUCT(write_time_ts);
5684 if (tran_call == TRANSACT2_QFILEINFO) {
5685 if (total_params < 4) {
5686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5687 return;
5690 if (IS_IPC(conn)) {
5691 call_trans2qpipeinfo(conn, req, tran_call,
5692 pparams, total_params,
5693 ppdata, total_data,
5694 max_data_bytes);
5695 return;
5698 fsp = file_fsp(req, SVAL(params,0));
5699 info_level = SVAL(params,2);
5701 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5703 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5704 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5705 return;
5708 /* Initial check for valid fsp ptr. */
5709 if (!check_fsp_open(conn, req, fsp)) {
5710 return;
5713 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5714 if (smb_fname == NULL) {
5715 reply_nterror(req, NT_STATUS_NO_MEMORY);
5716 return;
5719 if(fsp->fake_file_handle) {
5721 * This is actually for the QUOTA_FAKE_FILE --metze
5724 /* We know this name is ok, it's already passed the checks. */
5726 } else if(fsp->fh->fd == -1) {
5728 * This is actually a QFILEINFO on a directory
5729 * handle (returned from an NT SMB). NT5.0 seems
5730 * to do this call. JRA.
5733 if (INFO_LEVEL_IS_UNIX(info_level)) {
5734 /* Always do lstat for UNIX calls. */
5735 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5736 DEBUG(3,("call_trans2qfilepathinfo: "
5737 "SMB_VFS_LSTAT of %s failed "
5738 "(%s)\n",
5739 smb_fname_str_dbg(smb_fname),
5740 strerror(errno)));
5741 reply_nterror(req,
5742 map_nt_error_from_unix(errno));
5743 return;
5745 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5746 DEBUG(3,("call_trans2qfilepathinfo: "
5747 "SMB_VFS_STAT of %s failed (%s)\n",
5748 smb_fname_str_dbg(smb_fname),
5749 strerror(errno)));
5750 reply_nterror(req,
5751 map_nt_error_from_unix(errno));
5752 return;
5755 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5756 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5757 } else {
5759 * Original code - this is an open file.
5761 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5762 DEBUG(3, ("fstat of %s failed (%s)\n",
5763 fsp_fnum_dbg(fsp), strerror(errno)));
5764 reply_nterror(req,
5765 map_nt_error_from_unix(errno));
5766 return;
5768 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5769 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5772 } else {
5773 uint32_t name_hash;
5774 char *fname = NULL;
5775 uint32_t ucf_flags = (req->posix_pathnames ?
5776 UCF_POSIX_PATHNAMES : 0);
5778 /* qpathinfo */
5779 if (total_params < 7) {
5780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5781 return;
5784 info_level = SVAL(params,0);
5786 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5788 if (INFO_LEVEL_IS_UNIX(info_level)) {
5789 if (!lp_unix_extensions()) {
5790 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5791 return;
5793 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5794 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5795 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5796 req->posix_pathnames) {
5797 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5801 if (req->posix_pathnames) {
5802 srvstr_get_path_posix(req,
5803 params,
5804 req->flags2,
5805 &fname,
5806 &params[6],
5807 total_params - 6,
5808 STR_TERMINATE,
5809 &status);
5810 } else {
5811 srvstr_get_path(req,
5812 params,
5813 req->flags2,
5814 &fname,
5815 &params[6],
5816 total_params - 6,
5817 STR_TERMINATE,
5818 &status);
5820 if (!NT_STATUS_IS_OK(status)) {
5821 reply_nterror(req, status);
5822 return;
5825 status = filename_convert(req,
5826 conn,
5827 req->flags2 & FLAGS2_DFS_PATHNAMES,
5828 fname,
5829 ucf_flags,
5830 NULL,
5831 &smb_fname);
5832 if (!NT_STATUS_IS_OK(status)) {
5833 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5834 reply_botherror(req,
5835 NT_STATUS_PATH_NOT_COVERED,
5836 ERRSRV, ERRbadpath);
5837 return;
5839 reply_nterror(req, status);
5840 return;
5843 /* If this is a stream, check if there is a delete_pending. */
5844 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5845 && is_ntfs_stream_smb_fname(smb_fname)) {
5846 struct smb_filename *smb_fname_base;
5848 /* Create an smb_filename with stream_name == NULL. */
5849 smb_fname_base = synthetic_smb_fname(
5850 talloc_tos(),
5851 smb_fname->base_name,
5852 NULL,
5853 NULL,
5854 smb_fname->flags);
5855 if (smb_fname_base == NULL) {
5856 reply_nterror(req, NT_STATUS_NO_MEMORY);
5857 return;
5860 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5861 /* Always do lstat for UNIX calls. */
5862 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5863 DEBUG(3,("call_trans2qfilepathinfo: "
5864 "SMB_VFS_LSTAT of %s failed "
5865 "(%s)\n",
5866 smb_fname_str_dbg(smb_fname_base),
5867 strerror(errno)));
5868 TALLOC_FREE(smb_fname_base);
5869 reply_nterror(req,
5870 map_nt_error_from_unix(errno));
5871 return;
5873 } else {
5874 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5875 DEBUG(3,("call_trans2qfilepathinfo: "
5876 "fileinfo of %s failed "
5877 "(%s)\n",
5878 smb_fname_str_dbg(smb_fname_base),
5879 strerror(errno)));
5880 TALLOC_FREE(smb_fname_base);
5881 reply_nterror(req,
5882 map_nt_error_from_unix(errno));
5883 return;
5887 status = file_name_hash(conn,
5888 smb_fname_str_dbg(smb_fname_base),
5889 &name_hash);
5890 if (!NT_STATUS_IS_OK(status)) {
5891 TALLOC_FREE(smb_fname_base);
5892 reply_nterror(req, status);
5893 return;
5896 fileid = vfs_file_id_from_sbuf(conn,
5897 &smb_fname_base->st);
5898 TALLOC_FREE(smb_fname_base);
5899 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5900 if (delete_pending) {
5901 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5902 return;
5906 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5907 /* Always do lstat for UNIX calls. */
5908 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5909 DEBUG(3,("call_trans2qfilepathinfo: "
5910 "SMB_VFS_LSTAT of %s failed (%s)\n",
5911 smb_fname_str_dbg(smb_fname),
5912 strerror(errno)));
5913 reply_nterror(req,
5914 map_nt_error_from_unix(errno));
5915 return;
5918 } else {
5919 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5920 DEBUG(3,("call_trans2qfilepathinfo: "
5921 "SMB_VFS_STAT of %s failed (%s)\n",
5922 smb_fname_str_dbg(smb_fname),
5923 strerror(errno)));
5924 reply_nterror(req,
5925 map_nt_error_from_unix(errno));
5926 return;
5930 status = file_name_hash(conn,
5931 smb_fname_str_dbg(smb_fname),
5932 &name_hash);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 reply_nterror(req, status);
5935 return;
5938 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5939 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5940 if (delete_pending) {
5941 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5942 return;
5946 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5947 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5948 fsp_fnum_dbg(fsp),
5949 info_level,tran_call,total_data));
5951 /* Pull out any data sent here before we realloc. */
5952 switch (info_level) {
5953 case SMB_INFO_QUERY_EAS_FROM_LIST:
5955 /* Pull any EA list from the data portion. */
5956 uint32_t ea_size;
5958 if (total_data < 4) {
5959 reply_nterror(
5960 req, NT_STATUS_INVALID_PARAMETER);
5961 return;
5963 ea_size = IVAL(pdata,0);
5965 if (total_data > 0 && ea_size != total_data) {
5966 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5967 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5968 reply_nterror(
5969 req, NT_STATUS_INVALID_PARAMETER);
5970 return;
5973 if (!lp_ea_support(SNUM(conn))) {
5974 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5975 return;
5978 /* Pull out the list of names. */
5979 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5980 if (!ea_list) {
5981 reply_nterror(
5982 req, NT_STATUS_INVALID_PARAMETER);
5983 return;
5985 break;
5988 case SMB_QUERY_POSIX_LOCK:
5990 if (fsp == NULL || fsp->fh->fd == -1) {
5991 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5992 return;
5995 if (total_data != POSIX_LOCK_DATA_SIZE) {
5996 reply_nterror(
5997 req, NT_STATUS_INVALID_PARAMETER);
5998 return;
6001 /* Copy the lock range data. */
6002 lock_data = (char *)talloc_memdup(
6003 req, pdata, total_data);
6004 if (!lock_data) {
6005 reply_nterror(req, NT_STATUS_NO_MEMORY);
6006 return;
6008 lock_data_count = total_data;
6010 default:
6011 break;
6014 *pparams = (char *)SMB_REALLOC(*pparams,2);
6015 if (*pparams == NULL) {
6016 reply_nterror(req, NT_STATUS_NO_MEMORY);
6017 return;
6019 params = *pparams;
6020 SSVAL(params,0,0);
6023 * draft-leach-cifs-v1-spec-02.txt
6024 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6025 * says:
6027 * The requested information is placed in the Data portion of the
6028 * transaction response. For the information levels greater than 0x100,
6029 * the transaction response has 1 parameter word which should be
6030 * ignored by the client.
6032 * However Windows only follows this rule for the IS_NAME_VALID call.
6034 switch (info_level) {
6035 case SMB_INFO_IS_NAME_VALID:
6036 param_size = 0;
6037 break;
6040 if ((info_level & 0xFF00) == 0xFF00) {
6042 * We use levels that start with 0xFF00
6043 * internally to represent SMB2 specific levels
6045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6046 return;
6049 status = smbd_do_qfilepathinfo(conn, req, info_level,
6050 fsp, smb_fname,
6051 delete_pending, write_time_ts,
6052 ea_list,
6053 lock_data_count, lock_data,
6054 req->flags2, max_data_bytes,
6055 &fixed_portion,
6056 ppdata, &data_size);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 reply_nterror(req, status);
6059 return;
6061 if (fixed_portion > max_data_bytes) {
6062 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6063 return;
6066 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6067 max_data_bytes);
6069 return;
6072 /****************************************************************************
6073 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6074 code.
6075 ****************************************************************************/
6077 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6078 connection_struct *conn,
6079 struct smb_request *req,
6080 bool overwrite_if_exists,
6081 const struct smb_filename *smb_fname_old,
6082 struct smb_filename *smb_fname_new)
6084 NTSTATUS status = NT_STATUS_OK;
6086 /* source must already exist. */
6087 if (!VALID_STAT(smb_fname_old->st)) {
6088 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6091 if (VALID_STAT(smb_fname_new->st)) {
6092 if (overwrite_if_exists) {
6093 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6094 return NT_STATUS_FILE_IS_A_DIRECTORY;
6096 status = unlink_internals(conn,
6097 req,
6098 FILE_ATTRIBUTE_NORMAL,
6099 smb_fname_new,
6100 false);
6101 if (!NT_STATUS_IS_OK(status)) {
6102 return status;
6104 } else {
6105 /* Disallow if newname already exists. */
6106 return NT_STATUS_OBJECT_NAME_COLLISION;
6110 /* No links from a directory. */
6111 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6112 return NT_STATUS_FILE_IS_A_DIRECTORY;
6115 /* Setting a hardlink to/from a stream isn't currently supported. */
6116 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6117 is_ntfs_stream_smb_fname(smb_fname_new)) {
6118 return NT_STATUS_INVALID_PARAMETER;
6121 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6122 smb_fname_old->base_name, smb_fname_new->base_name));
6124 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6125 smb_fname_new->base_name) != 0) {
6126 status = map_nt_error_from_unix(errno);
6127 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6128 nt_errstr(status), smb_fname_old->base_name,
6129 smb_fname_new->base_name));
6131 return status;
6134 /****************************************************************************
6135 Deal with setting the time from any of the setfilepathinfo functions.
6136 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6137 calling this function.
6138 ****************************************************************************/
6140 NTSTATUS smb_set_file_time(connection_struct *conn,
6141 files_struct *fsp,
6142 const struct smb_filename *smb_fname,
6143 struct smb_file_time *ft,
6144 bool setting_write_time)
6146 struct smb_filename smb_fname_base;
6147 uint32_t action =
6148 FILE_NOTIFY_CHANGE_LAST_ACCESS
6149 |FILE_NOTIFY_CHANGE_LAST_WRITE
6150 |FILE_NOTIFY_CHANGE_CREATION;
6152 if (!VALID_STAT(smb_fname->st)) {
6153 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6156 /* get some defaults (no modifications) if any info is zero or -1. */
6157 if (null_timespec(ft->create_time)) {
6158 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6161 if (null_timespec(ft->atime)) {
6162 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6165 if (null_timespec(ft->mtime)) {
6166 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6169 if (!setting_write_time) {
6170 /* ft->mtime comes from change time, not write time. */
6171 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6174 /* Ensure the resolution is the correct for
6175 * what we can store on this filesystem. */
6177 round_timespec(conn->ts_res, &ft->create_time);
6178 round_timespec(conn->ts_res, &ft->ctime);
6179 round_timespec(conn->ts_res, &ft->atime);
6180 round_timespec(conn->ts_res, &ft->mtime);
6182 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6183 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6184 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6185 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6186 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6187 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6188 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6189 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6191 if (setting_write_time) {
6193 * This was a Windows setfileinfo on an open file.
6194 * NT does this a lot. We also need to
6195 * set the time here, as it can be read by
6196 * FindFirst/FindNext and with the patch for bug #2045
6197 * in smbd/fileio.c it ensures that this timestamp is
6198 * kept sticky even after a write. We save the request
6199 * away and will set it on file close and after a write. JRA.
6202 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6203 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6205 if (fsp != NULL) {
6206 if (fsp->base_fsp) {
6207 set_sticky_write_time_fsp(fsp->base_fsp,
6208 ft->mtime);
6209 } else {
6210 set_sticky_write_time_fsp(fsp, ft->mtime);
6212 } else {
6213 set_sticky_write_time_path(
6214 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6215 ft->mtime);
6219 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6221 /* Always call ntimes on the base, even if a stream was passed in. */
6222 smb_fname_base = *smb_fname;
6223 smb_fname_base.stream_name = NULL;
6225 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6226 return map_nt_error_from_unix(errno);
6229 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6230 smb_fname->base_name);
6231 return NT_STATUS_OK;
6234 /****************************************************************************
6235 Deal with setting the dosmode from any of the setfilepathinfo functions.
6236 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6237 done before calling this function.
6238 ****************************************************************************/
6240 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6241 const struct smb_filename *smb_fname,
6242 uint32_t dosmode)
6244 struct smb_filename *smb_fname_base;
6245 NTSTATUS status;
6247 if (!VALID_STAT(smb_fname->st)) {
6248 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6251 /* Always operate on the base_name, even if a stream was passed in. */
6252 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6253 smb_fname->base_name,
6254 NULL,
6255 &smb_fname->st,
6256 smb_fname->flags);
6257 if (smb_fname_base == NULL) {
6258 return NT_STATUS_NO_MEMORY;
6261 if (dosmode) {
6262 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6263 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6264 } else {
6265 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6269 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6271 /* check the mode isn't different, before changing it */
6272 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6273 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6274 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6275 (unsigned int)dosmode));
6277 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6278 false)) {
6279 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6280 "%s failed (%s)\n",
6281 smb_fname_str_dbg(smb_fname_base),
6282 strerror(errno)));
6283 status = map_nt_error_from_unix(errno);
6284 goto out;
6287 status = NT_STATUS_OK;
6288 out:
6289 TALLOC_FREE(smb_fname_base);
6290 return status;
6293 /****************************************************************************
6294 Deal with setting the size from any of the setfilepathinfo functions.
6295 ****************************************************************************/
6297 static NTSTATUS smb_set_file_size(connection_struct *conn,
6298 struct smb_request *req,
6299 files_struct *fsp,
6300 const struct smb_filename *smb_fname,
6301 const SMB_STRUCT_STAT *psbuf,
6302 off_t size,
6303 bool fail_after_createfile)
6305 NTSTATUS status = NT_STATUS_OK;
6306 struct smb_filename *smb_fname_tmp = NULL;
6307 files_struct *new_fsp = NULL;
6309 if (!VALID_STAT(*psbuf)) {
6310 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6313 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6315 if (size == get_file_size_stat(psbuf)) {
6316 return NT_STATUS_OK;
6319 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6320 smb_fname_str_dbg(smb_fname), (double)size));
6322 if (fsp && fsp->fh->fd != -1) {
6323 /* Handle based call. */
6324 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6325 return NT_STATUS_ACCESS_DENIED;
6328 if (vfs_set_filelen(fsp, size) == -1) {
6329 return map_nt_error_from_unix(errno);
6331 trigger_write_time_update_immediate(fsp);
6332 return NT_STATUS_OK;
6335 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6336 if (smb_fname_tmp == NULL) {
6337 return NT_STATUS_NO_MEMORY;
6340 smb_fname_tmp->st = *psbuf;
6342 status = SMB_VFS_CREATE_FILE(
6343 conn, /* conn */
6344 req, /* req */
6345 0, /* root_dir_fid */
6346 smb_fname_tmp, /* fname */
6347 FILE_WRITE_DATA, /* access_mask */
6348 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6349 FILE_SHARE_DELETE),
6350 FILE_OPEN, /* create_disposition*/
6351 0, /* create_options */
6352 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6353 0, /* oplock_request */
6354 NULL, /* lease */
6355 0, /* allocation_size */
6356 0, /* private_flags */
6357 NULL, /* sd */
6358 NULL, /* ea_list */
6359 &new_fsp, /* result */
6360 NULL, /* pinfo */
6361 NULL, NULL); /* create context */
6363 TALLOC_FREE(smb_fname_tmp);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 /* NB. We check for open_was_deferred in the caller. */
6367 return status;
6370 /* See RAW-SFILEINFO-END-OF-FILE */
6371 if (fail_after_createfile) {
6372 close_file(req, new_fsp,NORMAL_CLOSE);
6373 return NT_STATUS_INVALID_LEVEL;
6376 if (vfs_set_filelen(new_fsp, size) == -1) {
6377 status = map_nt_error_from_unix(errno);
6378 close_file(req, new_fsp,NORMAL_CLOSE);
6379 return status;
6382 trigger_write_time_update_immediate(new_fsp);
6383 close_file(req, new_fsp,NORMAL_CLOSE);
6384 return NT_STATUS_OK;
6387 /****************************************************************************
6388 Deal with SMB_INFO_SET_EA.
6389 ****************************************************************************/
6391 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6392 const char *pdata,
6393 int total_data,
6394 files_struct *fsp,
6395 const struct smb_filename *smb_fname)
6397 struct ea_list *ea_list = NULL;
6398 TALLOC_CTX *ctx = NULL;
6399 NTSTATUS status = NT_STATUS_OK;
6401 if (total_data < 10) {
6403 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6404 length. They seem to have no effect. Bug #3212. JRA */
6406 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6407 /* We're done. We only get EA info in this call. */
6408 return NT_STATUS_OK;
6411 return NT_STATUS_INVALID_PARAMETER;
6414 if (IVAL(pdata,0) > total_data) {
6415 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6416 IVAL(pdata,0), (unsigned int)total_data));
6417 return NT_STATUS_INVALID_PARAMETER;
6420 ctx = talloc_tos();
6421 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6422 if (!ea_list) {
6423 return NT_STATUS_INVALID_PARAMETER;
6426 status = set_ea(conn, fsp, smb_fname, ea_list);
6428 return status;
6431 /****************************************************************************
6432 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6433 ****************************************************************************/
6435 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6436 const char *pdata,
6437 int total_data,
6438 files_struct *fsp)
6440 struct ea_list *ea_list = NULL;
6441 NTSTATUS status;
6443 if (!fsp) {
6444 return NT_STATUS_INVALID_HANDLE;
6447 if (!lp_ea_support(SNUM(conn))) {
6448 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6449 "EA's not supported.\n",
6450 (unsigned int)total_data));
6451 return NT_STATUS_EAS_NOT_SUPPORTED;
6454 if (total_data < 10) {
6455 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6456 "too small.\n",
6457 (unsigned int)total_data));
6458 return NT_STATUS_INVALID_PARAMETER;
6461 ea_list = read_nttrans_ea_list(talloc_tos(),
6462 pdata,
6463 total_data);
6465 if (!ea_list) {
6466 return NT_STATUS_INVALID_PARAMETER;
6469 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6471 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6472 smb_fname_str_dbg(fsp->fsp_name),
6473 nt_errstr(status) ));
6475 return status;
6479 /****************************************************************************
6480 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6481 ****************************************************************************/
6483 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6484 const char *pdata,
6485 int total_data,
6486 files_struct *fsp,
6487 struct smb_filename *smb_fname)
6489 NTSTATUS status = NT_STATUS_OK;
6490 bool delete_on_close;
6491 uint32_t dosmode = 0;
6493 if (total_data < 1) {
6494 return NT_STATUS_INVALID_PARAMETER;
6497 if (fsp == NULL) {
6498 return NT_STATUS_INVALID_HANDLE;
6501 delete_on_close = (CVAL(pdata,0) ? True : False);
6502 dosmode = dos_mode(conn, smb_fname);
6504 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6505 "delete_on_close = %u\n",
6506 smb_fname_str_dbg(smb_fname),
6507 (unsigned int)dosmode,
6508 (unsigned int)delete_on_close ));
6510 if (delete_on_close) {
6511 status = can_set_delete_on_close(fsp, dosmode);
6512 if (!NT_STATUS_IS_OK(status)) {
6513 return status;
6517 /* The set is across all open files on this dev/inode pair. */
6518 if (!set_delete_on_close(fsp, delete_on_close,
6519 conn->session_info->security_token,
6520 conn->session_info->unix_token)) {
6521 return NT_STATUS_ACCESS_DENIED;
6523 return NT_STATUS_OK;
6526 /****************************************************************************
6527 Deal with SMB_FILE_POSITION_INFORMATION.
6528 ****************************************************************************/
6530 static NTSTATUS smb_file_position_information(connection_struct *conn,
6531 const char *pdata,
6532 int total_data,
6533 files_struct *fsp)
6535 uint64_t position_information;
6537 if (total_data < 8) {
6538 return NT_STATUS_INVALID_PARAMETER;
6541 if (fsp == NULL) {
6542 /* Ignore on pathname based set. */
6543 return NT_STATUS_OK;
6546 position_information = (uint64_t)IVAL(pdata,0);
6547 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6549 DEBUG(10,("smb_file_position_information: Set file position "
6550 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6551 (double)position_information));
6552 fsp->fh->position_information = position_information;
6553 return NT_STATUS_OK;
6556 /****************************************************************************
6557 Deal with SMB_FILE_MODE_INFORMATION.
6558 ****************************************************************************/
6560 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6561 const char *pdata,
6562 int total_data)
6564 uint32_t mode;
6566 if (total_data < 4) {
6567 return NT_STATUS_INVALID_PARAMETER;
6569 mode = IVAL(pdata,0);
6570 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6571 return NT_STATUS_INVALID_PARAMETER;
6573 return NT_STATUS_OK;
6576 /****************************************************************************
6577 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6578 ****************************************************************************/
6580 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6581 struct smb_request *req,
6582 const char *pdata,
6583 int total_data,
6584 const struct smb_filename *smb_fname)
6586 char *link_target = NULL;
6587 const char *newname = smb_fname->base_name;
6588 TALLOC_CTX *ctx = talloc_tos();
6590 /* Set a symbolic link. */
6591 /* Don't allow this if follow links is false. */
6593 if (total_data == 0) {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 if (!lp_follow_symlinks(SNUM(conn))) {
6598 return NT_STATUS_ACCESS_DENIED;
6601 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6602 total_data, STR_TERMINATE);
6604 if (!link_target) {
6605 return NT_STATUS_INVALID_PARAMETER;
6608 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6609 newname, link_target ));
6611 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6612 return map_nt_error_from_unix(errno);
6615 return NT_STATUS_OK;
6618 /****************************************************************************
6619 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6620 ****************************************************************************/
6622 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6623 struct smb_request *req,
6624 const char *pdata, int total_data,
6625 struct smb_filename *smb_fname_new)
6627 char *oldname = NULL;
6628 struct smb_filename *smb_fname_old = NULL;
6629 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6630 TALLOC_CTX *ctx = talloc_tos();
6631 NTSTATUS status = NT_STATUS_OK;
6633 /* Set a hard link. */
6634 if (total_data == 0) {
6635 return NT_STATUS_INVALID_PARAMETER;
6638 if (req->posix_pathnames) {
6639 srvstr_get_path_posix(ctx,
6640 pdata,
6641 req->flags2,
6642 &oldname,
6643 pdata,
6644 total_data,
6645 STR_TERMINATE,
6646 &status);
6647 } else {
6648 srvstr_get_path(ctx,
6649 pdata,
6650 req->flags2,
6651 &oldname,
6652 pdata,
6653 total_data,
6654 STR_TERMINATE,
6655 &status);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 return status;
6661 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6662 smb_fname_str_dbg(smb_fname_new), oldname));
6664 status = filename_convert(ctx,
6665 conn,
6666 req->flags2 & FLAGS2_DFS_PATHNAMES,
6667 oldname,
6668 ucf_flags,
6669 NULL,
6670 &smb_fname_old);
6671 if (!NT_STATUS_IS_OK(status)) {
6672 return status;
6675 return hardlink_internals(ctx, conn, req, false,
6676 smb_fname_old, smb_fname_new);
6679 /****************************************************************************
6680 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6681 ****************************************************************************/
6683 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6684 struct smb_request *req,
6685 const char *pdata,
6686 int total_data,
6687 files_struct *fsp,
6688 struct smb_filename *smb_fname_src)
6690 bool overwrite;
6691 uint32_t len;
6692 char *newname = NULL;
6693 struct smb_filename *smb_fname_dst = NULL;
6694 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6695 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6696 NTSTATUS status = NT_STATUS_OK;
6697 TALLOC_CTX *ctx = talloc_tos();
6699 if (!fsp) {
6700 return NT_STATUS_INVALID_HANDLE;
6703 if (total_data < 20) {
6704 return NT_STATUS_INVALID_PARAMETER;
6707 overwrite = (CVAL(pdata,0) ? True : False);
6708 len = IVAL(pdata,16);
6710 if (len > (total_data - 20) || (len == 0)) {
6711 return NT_STATUS_INVALID_PARAMETER;
6714 if (req->posix_pathnames) {
6715 srvstr_get_path_posix(ctx,
6716 pdata,
6717 req->flags2,
6718 &newname,
6719 &pdata[20],
6720 len,
6721 STR_TERMINATE,
6722 &status);
6723 } else {
6724 srvstr_get_path(ctx,
6725 pdata,
6726 req->flags2,
6727 &newname,
6728 &pdata[20],
6729 len,
6730 STR_TERMINATE,
6731 &status);
6733 if (!NT_STATUS_IS_OK(status)) {
6734 return status;
6737 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6738 newname));
6740 status = filename_convert(ctx,
6741 conn,
6742 req->flags2 & FLAGS2_DFS_PATHNAMES,
6743 newname,
6744 ucf_flags,
6745 NULL,
6746 &smb_fname_dst);
6747 if (!NT_STATUS_IS_OK(status)) {
6748 return status;
6751 if (fsp->base_fsp) {
6752 /* newname must be a stream name. */
6753 if (newname[0] != ':') {
6754 return NT_STATUS_NOT_SUPPORTED;
6757 /* Create an smb_fname to call rename_internals_fsp() with. */
6758 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6759 fsp->base_fsp->fsp_name->base_name,
6760 newname,
6761 NULL,
6762 fsp->base_fsp->fsp_name->flags);
6763 if (smb_fname_dst == NULL) {
6764 status = NT_STATUS_NO_MEMORY;
6765 goto out;
6769 * Set the original last component, since
6770 * rename_internals_fsp() requires it.
6772 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6773 newname);
6774 if (smb_fname_dst->original_lcomp == NULL) {
6775 status = NT_STATUS_NO_MEMORY;
6776 goto out;
6781 DEBUG(10,("smb2_file_rename_information: "
6782 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6783 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6784 smb_fname_str_dbg(smb_fname_dst)));
6785 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6786 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6787 overwrite);
6789 out:
6790 TALLOC_FREE(smb_fname_dst);
6791 return status;
6794 static NTSTATUS smb_file_link_information(connection_struct *conn,
6795 struct smb_request *req,
6796 const char *pdata,
6797 int total_data,
6798 files_struct *fsp,
6799 struct smb_filename *smb_fname_src)
6801 bool overwrite;
6802 uint32_t len;
6803 char *newname = NULL;
6804 struct smb_filename *smb_fname_dst = NULL;
6805 NTSTATUS status = NT_STATUS_OK;
6806 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6807 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6808 TALLOC_CTX *ctx = talloc_tos();
6810 if (!fsp) {
6811 return NT_STATUS_INVALID_HANDLE;
6814 if (total_data < 20) {
6815 return NT_STATUS_INVALID_PARAMETER;
6818 overwrite = (CVAL(pdata,0) ? true : false);
6819 len = IVAL(pdata,16);
6821 if (len > (total_data - 20) || (len == 0)) {
6822 return NT_STATUS_INVALID_PARAMETER;
6825 if (req->posix_pathnames) {
6826 srvstr_get_path_posix(ctx,
6827 pdata,
6828 req->flags2,
6829 &newname,
6830 &pdata[20],
6831 len,
6832 STR_TERMINATE,
6833 &status);
6834 } else {
6835 srvstr_get_path(ctx,
6836 pdata,
6837 req->flags2,
6838 &newname,
6839 &pdata[20],
6840 len,
6841 STR_TERMINATE,
6842 &status);
6844 if (!NT_STATUS_IS_OK(status)) {
6845 return status;
6848 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6849 newname));
6851 status = filename_convert(ctx,
6852 conn,
6853 req->flags2 & FLAGS2_DFS_PATHNAMES,
6854 newname,
6855 ucf_flags,
6856 NULL,
6857 &smb_fname_dst);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 return status;
6862 if (fsp->base_fsp) {
6863 /* No stream names. */
6864 return NT_STATUS_NOT_SUPPORTED;
6867 DEBUG(10,("smb_file_link_information: "
6868 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6869 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6870 smb_fname_str_dbg(smb_fname_dst)));
6871 status = hardlink_internals(ctx,
6872 conn,
6873 req,
6874 overwrite,
6875 fsp->fsp_name,
6876 smb_fname_dst);
6878 TALLOC_FREE(smb_fname_dst);
6879 return status;
6882 /****************************************************************************
6883 Deal with SMB_FILE_RENAME_INFORMATION.
6884 ****************************************************************************/
6886 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6887 struct smb_request *req,
6888 const char *pdata,
6889 int total_data,
6890 files_struct *fsp,
6891 struct smb_filename *smb_fname_src)
6893 bool overwrite;
6894 uint32_t root_fid;
6895 uint32_t len;
6896 char *newname = NULL;
6897 struct smb_filename *smb_fname_dst = NULL;
6898 bool dest_has_wcard = False;
6899 NTSTATUS status = NT_STATUS_OK;
6900 char *p;
6901 TALLOC_CTX *ctx = talloc_tos();
6903 if (total_data < 13) {
6904 return NT_STATUS_INVALID_PARAMETER;
6907 overwrite = (CVAL(pdata,0) ? True : False);
6908 root_fid = IVAL(pdata,4);
6909 len = IVAL(pdata,8);
6911 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6912 return NT_STATUS_INVALID_PARAMETER;
6915 if (req->posix_pathnames) {
6916 srvstr_get_path_wcard_posix(ctx,
6917 pdata,
6918 req->flags2,
6919 &newname,
6920 &pdata[12],
6921 len,
6923 &status,
6924 &dest_has_wcard);
6925 } else {
6926 srvstr_get_path_wcard(ctx,
6927 pdata,
6928 req->flags2,
6929 &newname,
6930 &pdata[12],
6931 len,
6933 &status,
6934 &dest_has_wcard);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 return status;
6940 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6941 newname));
6943 status = resolve_dfspath_wcard(ctx, conn,
6944 req->flags2 & FLAGS2_DFS_PATHNAMES,
6945 newname,
6946 UCF_COND_ALLOW_WCARD_LCOMP,
6947 !conn->sconn->using_smb2,
6948 &newname,
6949 &dest_has_wcard);
6950 if (!NT_STATUS_IS_OK(status)) {
6951 return status;
6954 /* Check the new name has no '/' characters. */
6955 if (strchr_m(newname, '/')) {
6956 return NT_STATUS_NOT_SUPPORTED;
6959 if (fsp && fsp->base_fsp) {
6960 /* newname must be a stream name. */
6961 if (newname[0] != ':') {
6962 return NT_STATUS_NOT_SUPPORTED;
6965 /* Create an smb_fname to call rename_internals_fsp() with. */
6966 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6967 fsp->base_fsp->fsp_name->base_name,
6968 newname,
6969 NULL,
6970 fsp->base_fsp->fsp_name->flags);
6971 if (smb_fname_dst == NULL) {
6972 status = NT_STATUS_NO_MEMORY;
6973 goto out;
6977 * Set the original last component, since
6978 * rename_internals_fsp() requires it.
6980 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6981 newname);
6982 if (smb_fname_dst->original_lcomp == NULL) {
6983 status = NT_STATUS_NO_MEMORY;
6984 goto out;
6987 } else {
6989 * Build up an smb_fname_dst based on the filename passed in.
6990 * We basically just strip off the last component, and put on
6991 * the newname instead.
6993 char *base_name = NULL;
6995 /* newname must *not* be a stream name. */
6996 if (newname[0] == ':') {
6997 return NT_STATUS_NOT_SUPPORTED;
7001 * Strip off the last component (filename) of the path passed
7002 * in.
7004 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7005 if (!base_name) {
7006 return NT_STATUS_NO_MEMORY;
7008 p = strrchr_m(base_name, '/');
7009 if (p) {
7010 p[1] = '\0';
7011 } else {
7012 base_name = talloc_strdup(ctx, "");
7013 if (!base_name) {
7014 return NT_STATUS_NO_MEMORY;
7017 /* Append the new name. */
7018 base_name = talloc_asprintf_append(base_name,
7019 "%s",
7020 newname);
7021 if (!base_name) {
7022 return NT_STATUS_NO_MEMORY;
7025 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7026 (UCF_SAVE_LCOMP |
7027 (dest_has_wcard ?
7028 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
7029 0)));
7031 /* If an error we expect this to be
7032 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7034 if (!NT_STATUS_IS_OK(status)) {
7035 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7036 status)) {
7037 goto out;
7039 /* Create an smb_fname to call rename_internals_fsp() */
7040 smb_fname_dst = synthetic_smb_fname(ctx,
7041 base_name,
7042 NULL,
7043 NULL,
7044 smb_fname_src->flags);
7045 if (smb_fname_dst == NULL) {
7046 status = NT_STATUS_NO_MEMORY;
7047 goto out;
7052 if (fsp) {
7053 DEBUG(10,("smb_file_rename_information: "
7054 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7055 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7056 smb_fname_str_dbg(smb_fname_dst)));
7057 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7058 overwrite);
7059 } else {
7060 DEBUG(10,("smb_file_rename_information: "
7061 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7062 smb_fname_str_dbg(smb_fname_src),
7063 smb_fname_str_dbg(smb_fname_dst)));
7064 status = rename_internals(ctx, conn, req, smb_fname_src,
7065 smb_fname_dst, 0, overwrite, false,
7066 dest_has_wcard,
7067 FILE_WRITE_ATTRIBUTES);
7069 out:
7070 TALLOC_FREE(smb_fname_dst);
7071 return status;
7074 /****************************************************************************
7075 Deal with SMB_SET_POSIX_ACL.
7076 ****************************************************************************/
7078 #if defined(HAVE_POSIX_ACLS)
7079 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7080 const char *pdata,
7081 int total_data,
7082 files_struct *fsp,
7083 const struct smb_filename *smb_fname)
7085 uint16_t posix_acl_version;
7086 uint16_t num_file_acls;
7087 uint16_t num_def_acls;
7088 bool valid_file_acls = True;
7089 bool valid_def_acls = True;
7090 NTSTATUS status;
7092 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7093 return NT_STATUS_INVALID_PARAMETER;
7095 posix_acl_version = SVAL(pdata,0);
7096 num_file_acls = SVAL(pdata,2);
7097 num_def_acls = SVAL(pdata,4);
7099 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7100 valid_file_acls = False;
7101 num_file_acls = 0;
7104 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7105 valid_def_acls = False;
7106 num_def_acls = 0;
7109 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7110 return NT_STATUS_INVALID_PARAMETER;
7113 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7114 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7115 return NT_STATUS_INVALID_PARAMETER;
7118 status = refuse_symlink(conn, fsp, smb_fname);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 return status;
7123 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7124 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7125 (unsigned int)num_file_acls,
7126 (unsigned int)num_def_acls));
7128 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7129 smb_fname->base_name, num_file_acls,
7130 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7131 return map_nt_error_from_unix(errno);
7134 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7135 smb_fname->base_name, &smb_fname->st, num_def_acls,
7136 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7137 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7138 return map_nt_error_from_unix(errno);
7140 return NT_STATUS_OK;
7142 #endif
7144 /****************************************************************************
7145 Deal with SMB_SET_POSIX_LOCK.
7146 ****************************************************************************/
7148 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7149 struct smb_request *req,
7150 const char *pdata,
7151 int total_data,
7152 files_struct *fsp)
7154 uint64_t count;
7155 uint64_t offset;
7156 uint64_t smblctx;
7157 bool blocking_lock = False;
7158 enum brl_type lock_type;
7160 NTSTATUS status = NT_STATUS_OK;
7162 if (fsp == NULL || fsp->fh->fd == -1) {
7163 return NT_STATUS_INVALID_HANDLE;
7166 if (total_data != POSIX_LOCK_DATA_SIZE) {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7171 case POSIX_LOCK_TYPE_READ:
7172 lock_type = READ_LOCK;
7173 break;
7174 case POSIX_LOCK_TYPE_WRITE:
7175 /* Return the right POSIX-mappable error code for files opened read-only. */
7176 if (!fsp->can_write) {
7177 return NT_STATUS_INVALID_HANDLE;
7179 lock_type = WRITE_LOCK;
7180 break;
7181 case POSIX_LOCK_TYPE_UNLOCK:
7182 lock_type = UNLOCK_LOCK;
7183 break;
7184 default:
7185 return NT_STATUS_INVALID_PARAMETER;
7188 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7189 blocking_lock = False;
7190 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7191 blocking_lock = True;
7192 } else {
7193 return NT_STATUS_INVALID_PARAMETER;
7196 if (!lp_blocking_locks(SNUM(conn))) {
7197 blocking_lock = False;
7200 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7201 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7202 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7203 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7204 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7206 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7207 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7208 fsp_str_dbg(fsp),
7209 (unsigned int)lock_type,
7210 (unsigned long long)smblctx,
7211 (double)count,
7212 (double)offset ));
7214 if (lock_type == UNLOCK_LOCK) {
7215 status = do_unlock(req->sconn->msg_ctx,
7216 fsp,
7217 smblctx,
7218 count,
7219 offset,
7220 POSIX_LOCK);
7221 } else {
7222 uint64_t block_smblctx;
7224 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7225 fsp,
7226 smblctx,
7227 count,
7228 offset,
7229 lock_type,
7230 POSIX_LOCK,
7231 blocking_lock,
7232 &status,
7233 &block_smblctx);
7235 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7237 * A blocking lock was requested. Package up
7238 * this smb into a queued request and push it
7239 * onto the blocking lock queue.
7241 if(push_blocking_lock_request(br_lck,
7242 req,
7243 fsp,
7244 -1, /* infinite timeout. */
7246 smblctx,
7247 lock_type,
7248 POSIX_LOCK,
7249 offset,
7250 count,
7251 block_smblctx)) {
7252 TALLOC_FREE(br_lck);
7253 return status;
7256 TALLOC_FREE(br_lck);
7259 return status;
7262 /****************************************************************************
7263 Deal with SMB_SET_FILE_BASIC_INFO.
7264 ****************************************************************************/
7266 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7267 const char *pdata,
7268 int total_data,
7269 files_struct *fsp,
7270 const struct smb_filename *smb_fname)
7272 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7273 struct smb_file_time ft;
7274 uint32_t dosmode = 0;
7275 NTSTATUS status = NT_STATUS_OK;
7277 ZERO_STRUCT(ft);
7279 if (total_data < 36) {
7280 return NT_STATUS_INVALID_PARAMETER;
7283 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7284 if (!NT_STATUS_IS_OK(status)) {
7285 return status;
7288 /* Set the attributes */
7289 dosmode = IVAL(pdata,32);
7290 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7291 if (!NT_STATUS_IS_OK(status)) {
7292 return status;
7295 /* create time */
7296 ft.create_time = interpret_long_date(pdata);
7298 /* access time */
7299 ft.atime = interpret_long_date(pdata+8);
7301 /* write time. */
7302 ft.mtime = interpret_long_date(pdata+16);
7304 /* change time. */
7305 ft.ctime = interpret_long_date(pdata+24);
7307 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7308 smb_fname_str_dbg(smb_fname)));
7310 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7311 true);
7314 /****************************************************************************
7315 Deal with SMB_INFO_STANDARD.
7316 ****************************************************************************/
7318 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7319 const char *pdata,
7320 int total_data,
7321 files_struct *fsp,
7322 const struct smb_filename *smb_fname)
7324 NTSTATUS status;
7325 struct smb_file_time ft;
7327 ZERO_STRUCT(ft);
7329 if (total_data < 12) {
7330 return NT_STATUS_INVALID_PARAMETER;
7333 /* create time */
7334 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7335 /* access time */
7336 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7337 /* write time */
7338 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7340 DEBUG(10,("smb_set_info_standard: file %s\n",
7341 smb_fname_str_dbg(smb_fname)));
7343 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7344 if (!NT_STATUS_IS_OK(status)) {
7345 return status;
7348 return smb_set_file_time(conn,
7349 fsp,
7350 smb_fname,
7351 &ft,
7352 true);
7355 /****************************************************************************
7356 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7357 ****************************************************************************/
7359 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7360 struct smb_request *req,
7361 const char *pdata,
7362 int total_data,
7363 files_struct *fsp,
7364 struct smb_filename *smb_fname)
7366 uint64_t allocation_size = 0;
7367 NTSTATUS status = NT_STATUS_OK;
7368 files_struct *new_fsp = NULL;
7370 if (!VALID_STAT(smb_fname->st)) {
7371 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7374 if (total_data < 8) {
7375 return NT_STATUS_INVALID_PARAMETER;
7378 allocation_size = (uint64_t)IVAL(pdata,0);
7379 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7380 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7381 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7382 (double)allocation_size));
7384 if (allocation_size) {
7385 allocation_size = smb_roundup(conn, allocation_size);
7388 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7389 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7390 (double)allocation_size));
7392 if (fsp && fsp->fh->fd != -1) {
7393 /* Open file handle. */
7394 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7395 return NT_STATUS_ACCESS_DENIED;
7398 /* Only change if needed. */
7399 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7400 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7401 return map_nt_error_from_unix(errno);
7404 /* But always update the time. */
7406 * This is equivalent to a write. Ensure it's seen immediately
7407 * if there are no pending writes.
7409 trigger_write_time_update_immediate(fsp);
7410 return NT_STATUS_OK;
7413 /* Pathname or stat or directory file. */
7414 status = SMB_VFS_CREATE_FILE(
7415 conn, /* conn */
7416 req, /* req */
7417 0, /* root_dir_fid */
7418 smb_fname, /* fname */
7419 FILE_WRITE_DATA, /* access_mask */
7420 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7421 FILE_SHARE_DELETE),
7422 FILE_OPEN, /* create_disposition*/
7423 0, /* create_options */
7424 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7425 0, /* oplock_request */
7426 NULL, /* lease */
7427 0, /* allocation_size */
7428 0, /* private_flags */
7429 NULL, /* sd */
7430 NULL, /* ea_list */
7431 &new_fsp, /* result */
7432 NULL, /* pinfo */
7433 NULL, NULL); /* create context */
7435 if (!NT_STATUS_IS_OK(status)) {
7436 /* NB. We check for open_was_deferred in the caller. */
7437 return status;
7440 /* Only change if needed. */
7441 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7442 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7443 status = map_nt_error_from_unix(errno);
7444 close_file(req, new_fsp, NORMAL_CLOSE);
7445 return status;
7449 /* Changing the allocation size should set the last mod time. */
7451 * This is equivalent to a write. Ensure it's seen immediately
7452 * if there are no pending writes.
7454 trigger_write_time_update_immediate(new_fsp);
7455 close_file(req, new_fsp, NORMAL_CLOSE);
7456 return NT_STATUS_OK;
7459 /****************************************************************************
7460 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7461 ****************************************************************************/
7463 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7464 struct smb_request *req,
7465 const char *pdata,
7466 int total_data,
7467 files_struct *fsp,
7468 const struct smb_filename *smb_fname,
7469 bool fail_after_createfile)
7471 off_t size;
7473 if (total_data < 8) {
7474 return NT_STATUS_INVALID_PARAMETER;
7477 size = IVAL(pdata,0);
7478 size |= (((off_t)IVAL(pdata,4)) << 32);
7479 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7480 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7481 (double)size));
7483 return smb_set_file_size(conn, req,
7484 fsp,
7485 smb_fname,
7486 &smb_fname->st,
7487 size,
7488 fail_after_createfile);
7491 /****************************************************************************
7492 Allow a UNIX info mknod.
7493 ****************************************************************************/
7495 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7496 const char *pdata,
7497 int total_data,
7498 const struct smb_filename *smb_fname)
7500 uint32_t file_type = IVAL(pdata,56);
7501 #if defined(HAVE_MAKEDEV)
7502 uint32_t dev_major = IVAL(pdata,60);
7503 uint32_t dev_minor = IVAL(pdata,68);
7504 #endif
7505 SMB_DEV_T dev = (SMB_DEV_T)0;
7506 uint32_t raw_unixmode = IVAL(pdata,84);
7507 NTSTATUS status;
7508 mode_t unixmode;
7510 if (total_data < 100) {
7511 return NT_STATUS_INVALID_PARAMETER;
7514 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7515 PERM_NEW_FILE, &unixmode);
7516 if (!NT_STATUS_IS_OK(status)) {
7517 return status;
7520 #if defined(HAVE_MAKEDEV)
7521 dev = makedev(dev_major, dev_minor);
7522 #endif
7524 switch (file_type) {
7525 #if defined(S_IFIFO)
7526 case UNIX_TYPE_FIFO:
7527 unixmode |= S_IFIFO;
7528 break;
7529 #endif
7530 #if defined(S_IFSOCK)
7531 case UNIX_TYPE_SOCKET:
7532 unixmode |= S_IFSOCK;
7533 break;
7534 #endif
7535 #if defined(S_IFCHR)
7536 case UNIX_TYPE_CHARDEV:
7537 unixmode |= S_IFCHR;
7538 break;
7539 #endif
7540 #if defined(S_IFBLK)
7541 case UNIX_TYPE_BLKDEV:
7542 unixmode |= S_IFBLK;
7543 break;
7544 #endif
7545 default:
7546 return NT_STATUS_INVALID_PARAMETER;
7549 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7550 "%.0f mode 0%o for file %s\n", (double)dev,
7551 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7553 /* Ok - do the mknod. */
7554 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7555 return map_nt_error_from_unix(errno);
7558 /* If any of the other "set" calls fail we
7559 * don't want to end up with a half-constructed mknod.
7562 if (lp_inherit_permissions(SNUM(conn))) {
7563 char *parent;
7564 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7565 &parent, NULL)) {
7566 return NT_STATUS_NO_MEMORY;
7568 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7569 unixmode);
7570 TALLOC_FREE(parent);
7573 return NT_STATUS_OK;
7576 /****************************************************************************
7577 Deal with SMB_SET_FILE_UNIX_BASIC.
7578 ****************************************************************************/
7580 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7581 struct smb_request *req,
7582 const char *pdata,
7583 int total_data,
7584 files_struct *fsp,
7585 const struct smb_filename *smb_fname)
7587 struct smb_file_time ft;
7588 uint32_t raw_unixmode;
7589 mode_t unixmode;
7590 off_t size = 0;
7591 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7592 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7593 NTSTATUS status = NT_STATUS_OK;
7594 bool delete_on_fail = False;
7595 enum perm_type ptype;
7596 files_struct *all_fsps = NULL;
7597 bool modify_mtime = true;
7598 struct file_id id;
7599 struct smb_filename *smb_fname_tmp = NULL;
7600 SMB_STRUCT_STAT sbuf;
7602 ZERO_STRUCT(ft);
7604 if (total_data < 100) {
7605 return NT_STATUS_INVALID_PARAMETER;
7608 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7609 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7610 size=IVAL(pdata,0); /* first 8 Bytes are size */
7611 size |= (((off_t)IVAL(pdata,4)) << 32);
7614 ft.atime = interpret_long_date(pdata+24); /* access_time */
7615 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7616 set_owner = (uid_t)IVAL(pdata,40);
7617 set_grp = (gid_t)IVAL(pdata,48);
7618 raw_unixmode = IVAL(pdata,84);
7620 if (VALID_STAT(smb_fname->st)) {
7621 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7622 ptype = PERM_EXISTING_DIR;
7623 } else {
7624 ptype = PERM_EXISTING_FILE;
7626 } else {
7627 ptype = PERM_NEW_FILE;
7630 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7631 ptype, &unixmode);
7632 if (!NT_STATUS_IS_OK(status)) {
7633 return status;
7636 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7637 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7638 smb_fname_str_dbg(smb_fname), (double)size,
7639 (unsigned int)set_owner, (unsigned int)set_grp,
7640 (int)raw_unixmode));
7642 sbuf = smb_fname->st;
7644 if (!VALID_STAT(sbuf)) {
7646 * The only valid use of this is to create character and block
7647 * devices, and named pipes. This is deprecated (IMHO) and
7648 * a new info level should be used for mknod. JRA.
7651 status = smb_unix_mknod(conn,
7652 pdata,
7653 total_data,
7654 smb_fname);
7655 if (!NT_STATUS_IS_OK(status)) {
7656 return status;
7659 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7660 if (smb_fname_tmp == NULL) {
7661 return NT_STATUS_NO_MEMORY;
7664 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7665 status = map_nt_error_from_unix(errno);
7666 TALLOC_FREE(smb_fname_tmp);
7667 SMB_VFS_UNLINK(conn, smb_fname);
7668 return status;
7671 sbuf = smb_fname_tmp->st;
7672 smb_fname = smb_fname_tmp;
7674 /* Ensure we don't try and change anything else. */
7675 raw_unixmode = SMB_MODE_NO_CHANGE;
7676 size = get_file_size_stat(&sbuf);
7677 ft.atime = sbuf.st_ex_atime;
7678 ft.mtime = sbuf.st_ex_mtime;
7680 * We continue here as we might want to change the
7681 * owner uid/gid.
7683 delete_on_fail = True;
7686 #if 1
7687 /* Horrible backwards compatibility hack as an old server bug
7688 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7689 * */
7691 if (!size) {
7692 size = get_file_size_stat(&sbuf);
7694 #endif
7697 * Deal with the UNIX specific mode set.
7700 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7701 int ret;
7703 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7704 "setting mode 0%o for file %s\n",
7705 (unsigned int)unixmode,
7706 smb_fname_str_dbg(smb_fname)));
7707 if (fsp && fsp->fh->fd != -1) {
7708 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7709 } else {
7710 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7712 if (ret != 0) {
7713 return map_nt_error_from_unix(errno);
7718 * Deal with the UNIX specific uid set.
7721 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7722 (sbuf.st_ex_uid != set_owner)) {
7723 int ret;
7725 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7726 "changing owner %u for path %s\n",
7727 (unsigned int)set_owner,
7728 smb_fname_str_dbg(smb_fname)));
7730 if (fsp && fsp->fh->fd != -1) {
7731 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7732 } else {
7734 * UNIX extensions calls must always operate
7735 * on symlinks.
7737 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7738 set_owner, (gid_t)-1);
7741 if (ret != 0) {
7742 status = map_nt_error_from_unix(errno);
7743 if (delete_on_fail) {
7744 SMB_VFS_UNLINK(conn, smb_fname);
7746 return status;
7751 * Deal with the UNIX specific gid set.
7754 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7755 (sbuf.st_ex_gid != set_grp)) {
7756 int ret;
7758 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7759 "changing group %u for file %s\n",
7760 (unsigned int)set_owner,
7761 smb_fname_str_dbg(smb_fname)));
7762 if (fsp && fsp->fh->fd != -1) {
7763 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7764 } else {
7766 * UNIX extensions calls must always operate
7767 * on symlinks.
7769 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7770 set_grp);
7772 if (ret != 0) {
7773 status = map_nt_error_from_unix(errno);
7774 if (delete_on_fail) {
7775 SMB_VFS_UNLINK(conn, smb_fname);
7777 return status;
7781 /* Deal with any size changes. */
7783 status = smb_set_file_size(conn, req,
7784 fsp,
7785 smb_fname,
7786 &sbuf,
7787 size,
7788 false);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 return status;
7793 /* Deal with any time changes. */
7794 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7795 /* No change, don't cancel anything. */
7796 return status;
7799 id = vfs_file_id_from_sbuf(conn, &sbuf);
7800 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7801 all_fsps = file_find_di_next(all_fsps)) {
7803 * We're setting the time explicitly for UNIX.
7804 * Cancel any pending changes over all handles.
7806 all_fsps->update_write_time_on_close = false;
7807 TALLOC_FREE(all_fsps->update_write_time_event);
7811 * Override the "setting_write_time"
7812 * parameter here as it almost does what
7813 * we need. Just remember if we modified
7814 * mtime and send the notify ourselves.
7816 if (null_timespec(ft.mtime)) {
7817 modify_mtime = false;
7820 status = smb_set_file_time(conn,
7821 fsp,
7822 smb_fname,
7823 &ft,
7824 false);
7825 if (modify_mtime) {
7826 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7827 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7829 return status;
7832 /****************************************************************************
7833 Deal with SMB_SET_FILE_UNIX_INFO2.
7834 ****************************************************************************/
7836 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7837 struct smb_request *req,
7838 const char *pdata,
7839 int total_data,
7840 files_struct *fsp,
7841 const struct smb_filename *smb_fname)
7843 NTSTATUS status;
7844 uint32_t smb_fflags;
7845 uint32_t smb_fmask;
7847 if (total_data < 116) {
7848 return NT_STATUS_INVALID_PARAMETER;
7851 /* Start by setting all the fields that are common between UNIX_BASIC
7852 * and UNIX_INFO2.
7854 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7855 fsp, smb_fname);
7856 if (!NT_STATUS_IS_OK(status)) {
7857 return status;
7860 smb_fflags = IVAL(pdata, 108);
7861 smb_fmask = IVAL(pdata, 112);
7863 /* NB: We should only attempt to alter the file flags if the client
7864 * sends a non-zero mask.
7866 if (smb_fmask != 0) {
7867 int stat_fflags = 0;
7869 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7870 smb_fmask, &stat_fflags)) {
7871 /* Client asked to alter a flag we don't understand. */
7872 return NT_STATUS_INVALID_PARAMETER;
7875 if (fsp && fsp->fh->fd != -1) {
7876 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7877 return NT_STATUS_NOT_SUPPORTED;
7878 } else {
7879 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7880 stat_fflags) != 0) {
7881 return map_nt_error_from_unix(errno);
7886 /* XXX: need to add support for changing the create_time here. You
7887 * can do this for paths on Darwin with setattrlist(2). The right way
7888 * to hook this up is probably by extending the VFS utimes interface.
7891 return NT_STATUS_OK;
7894 /****************************************************************************
7895 Create a directory with POSIX semantics.
7896 ****************************************************************************/
7898 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7899 struct smb_request *req,
7900 char **ppdata,
7901 int total_data,
7902 struct smb_filename *smb_fname,
7903 int *pdata_return_size)
7905 NTSTATUS status = NT_STATUS_OK;
7906 uint32_t raw_unixmode = 0;
7907 uint32_t mod_unixmode = 0;
7908 mode_t unixmode = (mode_t)0;
7909 files_struct *fsp = NULL;
7910 uint16_t info_level_return = 0;
7911 int info;
7912 char *pdata = *ppdata;
7914 if (total_data < 18) {
7915 return NT_STATUS_INVALID_PARAMETER;
7918 raw_unixmode = IVAL(pdata,8);
7919 /* Next 4 bytes are not yet defined. */
7921 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7922 PERM_NEW_DIR, &unixmode);
7923 if (!NT_STATUS_IS_OK(status)) {
7924 return status;
7927 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7929 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7930 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7932 status = SMB_VFS_CREATE_FILE(
7933 conn, /* conn */
7934 req, /* req */
7935 0, /* root_dir_fid */
7936 smb_fname, /* fname */
7937 FILE_READ_ATTRIBUTES, /* access_mask */
7938 FILE_SHARE_NONE, /* share_access */
7939 FILE_CREATE, /* create_disposition*/
7940 FILE_DIRECTORY_FILE, /* create_options */
7941 mod_unixmode, /* file_attributes */
7942 0, /* oplock_request */
7943 NULL, /* lease */
7944 0, /* allocation_size */
7945 0, /* private_flags */
7946 NULL, /* sd */
7947 NULL, /* ea_list */
7948 &fsp, /* result */
7949 &info, /* pinfo */
7950 NULL, NULL); /* create context */
7952 if (NT_STATUS_IS_OK(status)) {
7953 close_file(req, fsp, NORMAL_CLOSE);
7956 info_level_return = SVAL(pdata,16);
7958 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7959 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7960 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7961 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7962 } else {
7963 *pdata_return_size = 12;
7966 /* Realloc the data size */
7967 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7968 if (*ppdata == NULL) {
7969 *pdata_return_size = 0;
7970 return NT_STATUS_NO_MEMORY;
7972 pdata = *ppdata;
7974 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7975 SSVAL(pdata,2,0); /* No fnum. */
7976 SIVAL(pdata,4,info); /* Was directory created. */
7978 switch (info_level_return) {
7979 case SMB_QUERY_FILE_UNIX_BASIC:
7980 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7981 SSVAL(pdata,10,0); /* Padding. */
7982 store_file_unix_basic(conn, pdata + 12, fsp,
7983 &smb_fname->st);
7984 break;
7985 case SMB_QUERY_FILE_UNIX_INFO2:
7986 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7987 SSVAL(pdata,10,0); /* Padding. */
7988 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7989 &smb_fname->st);
7990 break;
7991 default:
7992 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7993 SSVAL(pdata,10,0); /* Padding. */
7994 break;
7997 return status;
8000 /****************************************************************************
8001 Open/Create a file with POSIX semantics.
8002 ****************************************************************************/
8004 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8005 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8007 static NTSTATUS smb_posix_open(connection_struct *conn,
8008 struct smb_request *req,
8009 char **ppdata,
8010 int total_data,
8011 struct smb_filename *smb_fname,
8012 int *pdata_return_size)
8014 bool extended_oplock_granted = False;
8015 char *pdata = *ppdata;
8016 uint32_t flags = 0;
8017 uint32_t wire_open_mode = 0;
8018 uint32_t raw_unixmode = 0;
8019 uint32_t mod_unixmode = 0;
8020 uint32_t create_disp = 0;
8021 uint32_t access_mask = 0;
8022 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8023 NTSTATUS status = NT_STATUS_OK;
8024 mode_t unixmode = (mode_t)0;
8025 files_struct *fsp = NULL;
8026 int oplock_request = 0;
8027 int info = 0;
8028 uint16_t info_level_return = 0;
8030 if (total_data < 18) {
8031 return NT_STATUS_INVALID_PARAMETER;
8034 flags = IVAL(pdata,0);
8035 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8036 if (oplock_request) {
8037 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8040 wire_open_mode = IVAL(pdata,4);
8042 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8043 return smb_posix_mkdir(conn, req,
8044 ppdata,
8045 total_data,
8046 smb_fname,
8047 pdata_return_size);
8050 switch (wire_open_mode & SMB_ACCMODE) {
8051 case SMB_O_RDONLY:
8052 access_mask = SMB_O_RDONLY_MAPPING;
8053 break;
8054 case SMB_O_WRONLY:
8055 access_mask = SMB_O_WRONLY_MAPPING;
8056 break;
8057 case SMB_O_RDWR:
8058 access_mask = (SMB_O_RDONLY_MAPPING|
8059 SMB_O_WRONLY_MAPPING);
8060 break;
8061 default:
8062 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8063 (unsigned int)wire_open_mode ));
8064 return NT_STATUS_INVALID_PARAMETER;
8067 wire_open_mode &= ~SMB_ACCMODE;
8069 /* First take care of O_CREAT|O_EXCL interactions. */
8070 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8071 case (SMB_O_CREAT | SMB_O_EXCL):
8072 /* File exists fail. File not exist create. */
8073 create_disp = FILE_CREATE;
8074 break;
8075 case SMB_O_CREAT:
8076 /* File exists open. File not exist create. */
8077 create_disp = FILE_OPEN_IF;
8078 break;
8079 case SMB_O_EXCL:
8080 /* O_EXCL on its own without O_CREAT is undefined.
8081 We deliberately ignore it as some versions of
8082 Linux CIFSFS can send a bare O_EXCL on the
8083 wire which other filesystems in the kernel
8084 ignore. See bug 9519 for details. */
8086 /* Fallthrough. */
8088 case 0:
8089 /* File exists open. File not exist fail. */
8090 create_disp = FILE_OPEN;
8091 break;
8092 default:
8093 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8094 (unsigned int)wire_open_mode ));
8095 return NT_STATUS_INVALID_PARAMETER;
8098 /* Next factor in the effects of O_TRUNC. */
8099 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8101 if (wire_open_mode & SMB_O_TRUNC) {
8102 switch (create_disp) {
8103 case FILE_CREATE:
8104 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8105 /* Leave create_disp alone as
8106 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8108 /* File exists fail. File not exist create. */
8109 break;
8110 case FILE_OPEN_IF:
8111 /* SMB_O_CREAT | SMB_O_TRUNC */
8112 /* File exists overwrite. File not exist create. */
8113 create_disp = FILE_OVERWRITE_IF;
8114 break;
8115 case FILE_OPEN:
8116 /* SMB_O_TRUNC */
8117 /* File exists overwrite. File not exist fail. */
8118 create_disp = FILE_OVERWRITE;
8119 break;
8120 default:
8121 /* Cannot get here. */
8122 smb_panic("smb_posix_open: logic error");
8123 return NT_STATUS_INVALID_PARAMETER;
8127 raw_unixmode = IVAL(pdata,8);
8128 /* Next 4 bytes are not yet defined. */
8130 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8131 (VALID_STAT(smb_fname->st) ?
8132 PERM_EXISTING_FILE : PERM_NEW_FILE),
8133 &unixmode);
8135 if (!NT_STATUS_IS_OK(status)) {
8136 return status;
8139 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8141 if (wire_open_mode & SMB_O_SYNC) {
8142 create_options |= FILE_WRITE_THROUGH;
8144 if (wire_open_mode & SMB_O_APPEND) {
8145 access_mask |= FILE_APPEND_DATA;
8147 if (wire_open_mode & SMB_O_DIRECT) {
8148 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8151 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8152 VALID_STAT_OF_DIR(smb_fname->st)) {
8153 if (access_mask != SMB_O_RDONLY_MAPPING) {
8154 return NT_STATUS_FILE_IS_A_DIRECTORY;
8156 create_options &= ~FILE_NON_DIRECTORY_FILE;
8157 create_options |= FILE_DIRECTORY_FILE;
8160 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8161 smb_fname_str_dbg(smb_fname),
8162 (unsigned int)wire_open_mode,
8163 (unsigned int)unixmode ));
8165 status = SMB_VFS_CREATE_FILE(
8166 conn, /* conn */
8167 req, /* req */
8168 0, /* root_dir_fid */
8169 smb_fname, /* fname */
8170 access_mask, /* access_mask */
8171 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8172 FILE_SHARE_DELETE),
8173 create_disp, /* create_disposition*/
8174 create_options, /* create_options */
8175 mod_unixmode, /* file_attributes */
8176 oplock_request, /* oplock_request */
8177 NULL, /* lease */
8178 0, /* allocation_size */
8179 0, /* private_flags */
8180 NULL, /* sd */
8181 NULL, /* ea_list */
8182 &fsp, /* result */
8183 &info, /* pinfo */
8184 NULL, NULL); /* create context */
8186 if (!NT_STATUS_IS_OK(status)) {
8187 return status;
8190 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8191 extended_oplock_granted = True;
8194 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8195 extended_oplock_granted = True;
8198 info_level_return = SVAL(pdata,16);
8200 /* Allocate the correct return size. */
8202 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8203 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8204 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8205 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8206 } else {
8207 *pdata_return_size = 12;
8210 /* Realloc the data size */
8211 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8212 if (*ppdata == NULL) {
8213 close_file(req, fsp, ERROR_CLOSE);
8214 *pdata_return_size = 0;
8215 return NT_STATUS_NO_MEMORY;
8217 pdata = *ppdata;
8219 if (extended_oplock_granted) {
8220 if (flags & REQUEST_BATCH_OPLOCK) {
8221 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8222 } else {
8223 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8225 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8226 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8227 } else {
8228 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8231 SSVAL(pdata,2,fsp->fnum);
8232 SIVAL(pdata,4,info); /* Was file created etc. */
8234 switch (info_level_return) {
8235 case SMB_QUERY_FILE_UNIX_BASIC:
8236 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8237 SSVAL(pdata,10,0); /* padding. */
8238 store_file_unix_basic(conn, pdata + 12, fsp,
8239 &smb_fname->st);
8240 break;
8241 case SMB_QUERY_FILE_UNIX_INFO2:
8242 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8243 SSVAL(pdata,10,0); /* padding. */
8244 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8245 &smb_fname->st);
8246 break;
8247 default:
8248 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8249 SSVAL(pdata,10,0); /* padding. */
8250 break;
8252 return NT_STATUS_OK;
8255 /****************************************************************************
8256 Delete a file with POSIX semantics.
8257 ****************************************************************************/
8259 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8260 struct smb_request *req,
8261 const char *pdata,
8262 int total_data,
8263 struct smb_filename *smb_fname)
8265 NTSTATUS status = NT_STATUS_OK;
8266 files_struct *fsp = NULL;
8267 uint16_t flags = 0;
8268 char del = 1;
8269 int info = 0;
8270 int create_options = 0;
8271 int i;
8272 struct share_mode_lock *lck = NULL;
8274 if (total_data < 2) {
8275 return NT_STATUS_INVALID_PARAMETER;
8278 flags = SVAL(pdata,0);
8280 if (!VALID_STAT(smb_fname->st)) {
8281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8284 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8285 !VALID_STAT_OF_DIR(smb_fname->st)) {
8286 return NT_STATUS_NOT_A_DIRECTORY;
8289 DEBUG(10,("smb_posix_unlink: %s %s\n",
8290 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8291 smb_fname_str_dbg(smb_fname)));
8293 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8294 create_options |= FILE_DIRECTORY_FILE;
8297 status = SMB_VFS_CREATE_FILE(
8298 conn, /* conn */
8299 req, /* req */
8300 0, /* root_dir_fid */
8301 smb_fname, /* fname */
8302 DELETE_ACCESS, /* access_mask */
8303 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8304 FILE_SHARE_DELETE),
8305 FILE_OPEN, /* create_disposition*/
8306 create_options, /* create_options */
8307 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8308 0, /* oplock_request */
8309 NULL, /* lease */
8310 0, /* allocation_size */
8311 0, /* private_flags */
8312 NULL, /* sd */
8313 NULL, /* ea_list */
8314 &fsp, /* result */
8315 &info, /* pinfo */
8316 NULL, NULL); /* create context */
8318 if (!NT_STATUS_IS_OK(status)) {
8319 return status;
8323 * Don't lie to client. If we can't really delete due to
8324 * non-POSIX opens return SHARING_VIOLATION.
8327 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8328 if (lck == NULL) {
8329 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8330 "lock for file %s\n", fsp_str_dbg(fsp)));
8331 close_file(req, fsp, NORMAL_CLOSE);
8332 return NT_STATUS_INVALID_PARAMETER;
8336 * See if others still have the file open. If this is the case, then
8337 * don't delete. If all opens are POSIX delete we can set the delete
8338 * on close disposition.
8340 for (i=0; i<lck->data->num_share_modes; i++) {
8341 struct share_mode_entry *e = &lck->data->share_modes[i];
8342 if (is_valid_share_mode_entry(e)) {
8343 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8344 continue;
8346 if (share_mode_stale_pid(lck->data, i)) {
8347 continue;
8349 /* Fail with sharing violation. */
8350 TALLOC_FREE(lck);
8351 close_file(req, fsp, NORMAL_CLOSE);
8352 return NT_STATUS_SHARING_VIOLATION;
8357 * Set the delete on close.
8359 status = smb_set_file_disposition_info(conn,
8360 &del,
8362 fsp,
8363 smb_fname);
8365 TALLOC_FREE(lck);
8367 if (!NT_STATUS_IS_OK(status)) {
8368 close_file(req, fsp, NORMAL_CLOSE);
8369 return status;
8371 return close_file(req, fsp, NORMAL_CLOSE);
8374 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8375 struct smb_request *req,
8376 TALLOC_CTX *mem_ctx,
8377 uint16_t info_level,
8378 files_struct *fsp,
8379 struct smb_filename *smb_fname,
8380 char **ppdata, int total_data,
8381 int *ret_data_size)
8383 char *pdata = *ppdata;
8384 NTSTATUS status = NT_STATUS_OK;
8385 int data_return_size = 0;
8387 *ret_data_size = 0;
8389 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8390 return NT_STATUS_INVALID_LEVEL;
8393 if (!CAN_WRITE(conn)) {
8394 /* Allow POSIX opens. The open path will deny
8395 * any non-readonly opens. */
8396 if (info_level != SMB_POSIX_PATH_OPEN) {
8397 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8401 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8402 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8403 fsp_fnum_dbg(fsp),
8404 info_level, total_data));
8406 switch (info_level) {
8408 case SMB_INFO_STANDARD:
8410 status = smb_set_info_standard(conn,
8411 pdata,
8412 total_data,
8413 fsp,
8414 smb_fname);
8415 break;
8418 case SMB_INFO_SET_EA:
8420 status = smb_info_set_ea(conn,
8421 pdata,
8422 total_data,
8423 fsp,
8424 smb_fname);
8425 break;
8428 case SMB_SET_FILE_BASIC_INFO:
8429 case SMB_FILE_BASIC_INFORMATION:
8431 status = smb_set_file_basic_info(conn,
8432 pdata,
8433 total_data,
8434 fsp,
8435 smb_fname);
8436 break;
8439 case SMB_FILE_ALLOCATION_INFORMATION:
8440 case SMB_SET_FILE_ALLOCATION_INFO:
8442 status = smb_set_file_allocation_info(conn, req,
8443 pdata,
8444 total_data,
8445 fsp,
8446 smb_fname);
8447 break;
8450 case SMB_FILE_END_OF_FILE_INFORMATION:
8451 case SMB_SET_FILE_END_OF_FILE_INFO:
8454 * XP/Win7 both fail after the createfile with
8455 * SMB_SET_FILE_END_OF_FILE_INFO but not
8456 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8457 * The level is known here, so pass it down
8458 * appropriately.
8460 bool should_fail =
8461 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8463 status = smb_set_file_end_of_file_info(conn, req,
8464 pdata,
8465 total_data,
8466 fsp,
8467 smb_fname,
8468 should_fail);
8469 break;
8472 case SMB_FILE_DISPOSITION_INFORMATION:
8473 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8475 #if 0
8476 /* JRA - We used to just ignore this on a path ?
8477 * Shouldn't this be invalid level on a pathname
8478 * based call ?
8480 if (tran_call != TRANSACT2_SETFILEINFO) {
8481 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8483 #endif
8484 status = smb_set_file_disposition_info(conn,
8485 pdata,
8486 total_data,
8487 fsp,
8488 smb_fname);
8489 break;
8492 case SMB_FILE_POSITION_INFORMATION:
8494 status = smb_file_position_information(conn,
8495 pdata,
8496 total_data,
8497 fsp);
8498 break;
8501 case SMB_FILE_FULL_EA_INFORMATION:
8503 status = smb_set_file_full_ea_info(conn,
8504 pdata,
8505 total_data,
8506 fsp);
8507 break;
8510 /* From tridge Samba4 :
8511 * MODE_INFORMATION in setfileinfo (I have no
8512 * idea what "mode information" on a file is - it takes a value of 0,
8513 * 2, 4 or 6. What could it be?).
8516 case SMB_FILE_MODE_INFORMATION:
8518 status = smb_file_mode_information(conn,
8519 pdata,
8520 total_data);
8521 break;
8525 * CIFS UNIX extensions.
8528 case SMB_SET_FILE_UNIX_BASIC:
8530 status = smb_set_file_unix_basic(conn, req,
8531 pdata,
8532 total_data,
8533 fsp,
8534 smb_fname);
8535 break;
8538 case SMB_SET_FILE_UNIX_INFO2:
8540 status = smb_set_file_unix_info2(conn, req,
8541 pdata,
8542 total_data,
8543 fsp,
8544 smb_fname);
8545 break;
8548 case SMB_SET_FILE_UNIX_LINK:
8550 if (fsp) {
8551 /* We must have a pathname for this. */
8552 return NT_STATUS_INVALID_LEVEL;
8554 status = smb_set_file_unix_link(conn, req, pdata,
8555 total_data, smb_fname);
8556 break;
8559 case SMB_SET_FILE_UNIX_HLINK:
8561 if (fsp) {
8562 /* We must have a pathname for this. */
8563 return NT_STATUS_INVALID_LEVEL;
8565 status = smb_set_file_unix_hlink(conn, req,
8566 pdata, total_data,
8567 smb_fname);
8568 break;
8571 case SMB_FILE_RENAME_INFORMATION:
8573 status = smb_file_rename_information(conn, req,
8574 pdata, total_data,
8575 fsp, smb_fname);
8576 break;
8579 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8581 /* SMB2 rename information. */
8582 status = smb2_file_rename_information(conn, req,
8583 pdata, total_data,
8584 fsp, smb_fname);
8585 break;
8588 case SMB_FILE_LINK_INFORMATION:
8590 status = smb_file_link_information(conn, req,
8591 pdata, total_data,
8592 fsp, smb_fname);
8593 break;
8596 #if defined(HAVE_POSIX_ACLS)
8597 case SMB_SET_POSIX_ACL:
8599 status = smb_set_posix_acl(conn,
8600 pdata,
8601 total_data,
8602 fsp,
8603 smb_fname);
8604 break;
8606 #endif
8608 case SMB_SET_POSIX_LOCK:
8610 if (!fsp) {
8611 return NT_STATUS_INVALID_LEVEL;
8613 status = smb_set_posix_lock(conn, req,
8614 pdata, total_data, fsp);
8615 break;
8618 case SMB_POSIX_PATH_OPEN:
8620 if (fsp) {
8621 /* We must have a pathname for this. */
8622 return NT_STATUS_INVALID_LEVEL;
8625 status = smb_posix_open(conn, req,
8626 ppdata,
8627 total_data,
8628 smb_fname,
8629 &data_return_size);
8630 break;
8633 case SMB_POSIX_PATH_UNLINK:
8635 if (fsp) {
8636 /* We must have a pathname for this. */
8637 return NT_STATUS_INVALID_LEVEL;
8640 status = smb_posix_unlink(conn, req,
8641 pdata,
8642 total_data,
8643 smb_fname);
8644 break;
8647 default:
8648 return NT_STATUS_INVALID_LEVEL;
8651 if (!NT_STATUS_IS_OK(status)) {
8652 return status;
8655 *ret_data_size = data_return_size;
8656 return NT_STATUS_OK;
8659 /****************************************************************************
8660 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8661 ****************************************************************************/
8663 static void call_trans2setfilepathinfo(connection_struct *conn,
8664 struct smb_request *req,
8665 unsigned int tran_call,
8666 char **pparams, int total_params,
8667 char **ppdata, int total_data,
8668 unsigned int max_data_bytes)
8670 char *params = *pparams;
8671 char *pdata = *ppdata;
8672 uint16_t info_level;
8673 struct smb_filename *smb_fname = NULL;
8674 files_struct *fsp = NULL;
8675 NTSTATUS status = NT_STATUS_OK;
8676 int data_return_size = 0;
8678 if (!params) {
8679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8680 return;
8683 if (tran_call == TRANSACT2_SETFILEINFO) {
8684 if (total_params < 4) {
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686 return;
8689 fsp = file_fsp(req, SVAL(params,0));
8690 /* Basic check for non-null fsp. */
8691 if (!check_fsp_open(conn, req, fsp)) {
8692 return;
8694 info_level = SVAL(params,2);
8696 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8697 if (smb_fname == NULL) {
8698 reply_nterror(req, NT_STATUS_NO_MEMORY);
8699 return;
8702 if(fsp->fh->fd == -1) {
8704 * This is actually a SETFILEINFO on a directory
8705 * handle (returned from an NT SMB). NT5.0 seems
8706 * to do this call. JRA.
8708 if (INFO_LEVEL_IS_UNIX(info_level)) {
8709 /* Always do lstat for UNIX calls. */
8710 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8711 DEBUG(3,("call_trans2setfilepathinfo: "
8712 "SMB_VFS_LSTAT of %s failed "
8713 "(%s)\n",
8714 smb_fname_str_dbg(smb_fname),
8715 strerror(errno)));
8716 reply_nterror(req, map_nt_error_from_unix(errno));
8717 return;
8719 } else {
8720 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8721 DEBUG(3,("call_trans2setfilepathinfo: "
8722 "fileinfo of %s failed (%s)\n",
8723 smb_fname_str_dbg(smb_fname),
8724 strerror(errno)));
8725 reply_nterror(req, map_nt_error_from_unix(errno));
8726 return;
8729 } else if (fsp->print_file) {
8731 * Doing a DELETE_ON_CLOSE should cancel a print job.
8733 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8734 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8736 DEBUG(3,("call_trans2setfilepathinfo: "
8737 "Cancelling print job (%s)\n",
8738 fsp_str_dbg(fsp)));
8740 SSVAL(params,0,0);
8741 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8742 *ppdata, 0,
8743 max_data_bytes);
8744 return;
8745 } else {
8746 reply_nterror(req,
8747 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8748 return;
8750 } else {
8752 * Original code - this is an open file.
8754 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8755 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8756 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8757 strerror(errno)));
8758 reply_nterror(req, map_nt_error_from_unix(errno));
8759 return;
8762 } else {
8763 char *fname = NULL;
8764 uint32_t ucf_flags = (req->posix_pathnames ?
8765 UCF_POSIX_PATHNAMES : 0);
8767 /* set path info */
8768 if (total_params < 7) {
8769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8770 return;
8773 info_level = SVAL(params,0);
8774 if (req->posix_pathnames) {
8775 srvstr_get_path_posix(req,
8776 params,
8777 req->flags2,
8778 &fname,
8779 &params[6],
8780 total_params - 6,
8781 STR_TERMINATE,
8782 &status);
8783 } else {
8784 srvstr_get_path(req,
8785 params,
8786 req->flags2,
8787 &fname,
8788 &params[6],
8789 total_params - 6,
8790 STR_TERMINATE,
8791 &status);
8793 if (!NT_STATUS_IS_OK(status)) {
8794 reply_nterror(req, status);
8795 return;
8798 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8799 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8800 info_level == SMB_FILE_RENAME_INFORMATION ||
8801 info_level == SMB_POSIX_PATH_UNLINK) {
8802 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8805 status = filename_convert(req, conn,
8806 req->flags2 & FLAGS2_DFS_PATHNAMES,
8807 fname,
8808 ucf_flags,
8809 NULL,
8810 &smb_fname);
8811 if (!NT_STATUS_IS_OK(status)) {
8812 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8813 reply_botherror(req,
8814 NT_STATUS_PATH_NOT_COVERED,
8815 ERRSRV, ERRbadpath);
8816 return;
8818 reply_nterror(req, status);
8819 return;
8822 if (INFO_LEVEL_IS_UNIX(info_level)) {
8824 * For CIFS UNIX extensions the target name may not exist.
8827 /* Always do lstat for UNIX calls. */
8828 SMB_VFS_LSTAT(conn, smb_fname);
8830 } else if (!VALID_STAT(smb_fname->st) &&
8831 SMB_VFS_STAT(conn, smb_fname)) {
8832 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8833 "%s failed (%s)\n",
8834 smb_fname_str_dbg(smb_fname),
8835 strerror(errno)));
8836 reply_nterror(req, map_nt_error_from_unix(errno));
8837 return;
8841 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8842 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8843 fsp_fnum_dbg(fsp),
8844 info_level,total_data));
8846 /* Realloc the parameter size */
8847 *pparams = (char *)SMB_REALLOC(*pparams,2);
8848 if (*pparams == NULL) {
8849 reply_nterror(req, NT_STATUS_NO_MEMORY);
8850 return;
8852 params = *pparams;
8854 SSVAL(params,0,0);
8856 status = smbd_do_setfilepathinfo(conn, req, req,
8857 info_level,
8858 fsp,
8859 smb_fname,
8860 ppdata, total_data,
8861 &data_return_size);
8862 if (!NT_STATUS_IS_OK(status)) {
8863 if (open_was_deferred(req->xconn, req->mid)) {
8864 /* We have re-scheduled this call. */
8865 return;
8867 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8868 /* We have re-scheduled this call. */
8869 return;
8871 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8872 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8873 ERRSRV, ERRbadpath);
8874 return;
8876 if (info_level == SMB_POSIX_PATH_OPEN) {
8877 reply_openerror(req, status);
8878 return;
8882 * Invalid EA name needs to return 2 param bytes,
8883 * not a zero-length error packet.
8885 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8886 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8887 max_data_bytes);
8888 } else {
8889 reply_nterror(req, status);
8891 return;
8894 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8895 max_data_bytes);
8897 return;
8900 /****************************************************************************
8901 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8902 ****************************************************************************/
8904 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8905 char **pparams, int total_params,
8906 char **ppdata, int total_data,
8907 unsigned int max_data_bytes)
8909 struct smb_filename *smb_dname = NULL;
8910 char *params = *pparams;
8911 char *pdata = *ppdata;
8912 char *directory = NULL;
8913 NTSTATUS status = NT_STATUS_OK;
8914 struct ea_list *ea_list = NULL;
8915 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8916 TALLOC_CTX *ctx = talloc_tos();
8918 if (!CAN_WRITE(conn)) {
8919 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8920 return;
8923 if (total_params < 5) {
8924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8925 return;
8928 if (req->posix_pathnames) {
8929 srvstr_get_path_posix(ctx,
8930 params,
8931 req->flags2,
8932 &directory,
8933 &params[4],
8934 total_params - 4,
8935 STR_TERMINATE,
8936 &status);
8937 } else {
8938 srvstr_get_path(ctx,
8939 params,
8940 req->flags2,
8941 &directory,
8942 &params[4],
8943 total_params - 4,
8944 STR_TERMINATE,
8945 &status);
8947 if (!NT_STATUS_IS_OK(status)) {
8948 reply_nterror(req, status);
8949 return;
8952 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8954 status = filename_convert(ctx,
8955 conn,
8956 req->flags2 & FLAGS2_DFS_PATHNAMES,
8957 directory,
8958 ucf_flags,
8959 NULL,
8960 &smb_dname);
8962 if (!NT_STATUS_IS_OK(status)) {
8963 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8964 reply_botherror(req,
8965 NT_STATUS_PATH_NOT_COVERED,
8966 ERRSRV, ERRbadpath);
8967 return;
8969 reply_nterror(req, status);
8970 return;
8974 * OS/2 workplace shell seems to send SET_EA requests of "null"
8975 * length (4 bytes containing IVAL 4).
8976 * They seem to have no effect. Bug #3212. JRA.
8979 if (total_data && (total_data != 4)) {
8980 /* Any data in this call is an EA list. */
8981 if (total_data < 10) {
8982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8983 goto out;
8986 if (IVAL(pdata,0) > total_data) {
8987 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8988 IVAL(pdata,0), (unsigned int)total_data));
8989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8990 goto out;
8993 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8994 total_data - 4);
8995 if (!ea_list) {
8996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8997 goto out;
9000 if (!lp_ea_support(SNUM(conn))) {
9001 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9002 goto out;
9005 /* If total_data == 4 Windows doesn't care what values
9006 * are placed in that field, it just ignores them.
9007 * The System i QNTC IBM SMB client puts bad values here,
9008 * so ignore them. */
9010 status = create_directory(conn, req, smb_dname);
9012 if (!NT_STATUS_IS_OK(status)) {
9013 reply_nterror(req, status);
9014 goto out;
9017 /* Try and set any given EA. */
9018 if (ea_list) {
9019 status = set_ea(conn, NULL, smb_dname, ea_list);
9020 if (!NT_STATUS_IS_OK(status)) {
9021 reply_nterror(req, status);
9022 goto out;
9026 /* Realloc the parameter and data sizes */
9027 *pparams = (char *)SMB_REALLOC(*pparams,2);
9028 if(*pparams == NULL) {
9029 reply_nterror(req, NT_STATUS_NO_MEMORY);
9030 goto out;
9032 params = *pparams;
9034 SSVAL(params,0,0);
9036 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9038 out:
9039 TALLOC_FREE(smb_dname);
9040 return;
9043 /****************************************************************************
9044 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9045 We don't actually do this - we just send a null response.
9046 ****************************************************************************/
9048 static void call_trans2findnotifyfirst(connection_struct *conn,
9049 struct smb_request *req,
9050 char **pparams, int total_params,
9051 char **ppdata, int total_data,
9052 unsigned int max_data_bytes)
9054 char *params = *pparams;
9055 uint16_t info_level;
9057 if (total_params < 6) {
9058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9059 return;
9062 info_level = SVAL(params,4);
9063 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9065 switch (info_level) {
9066 case 1:
9067 case 2:
9068 break;
9069 default:
9070 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9071 return;
9074 /* Realloc the parameter and data sizes */
9075 *pparams = (char *)SMB_REALLOC(*pparams,6);
9076 if (*pparams == NULL) {
9077 reply_nterror(req, NT_STATUS_NO_MEMORY);
9078 return;
9080 params = *pparams;
9082 SSVAL(params,0,fnf_handle);
9083 SSVAL(params,2,0); /* No changes */
9084 SSVAL(params,4,0); /* No EA errors */
9086 fnf_handle++;
9088 if(fnf_handle == 0)
9089 fnf_handle = 257;
9091 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9093 return;
9096 /****************************************************************************
9097 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9098 changes). Currently this does nothing.
9099 ****************************************************************************/
9101 static void call_trans2findnotifynext(connection_struct *conn,
9102 struct smb_request *req,
9103 char **pparams, int total_params,
9104 char **ppdata, int total_data,
9105 unsigned int max_data_bytes)
9107 char *params = *pparams;
9109 DEBUG(3,("call_trans2findnotifynext\n"));
9111 /* Realloc the parameter and data sizes */
9112 *pparams = (char *)SMB_REALLOC(*pparams,4);
9113 if (*pparams == NULL) {
9114 reply_nterror(req, NT_STATUS_NO_MEMORY);
9115 return;
9117 params = *pparams;
9119 SSVAL(params,0,0); /* No changes */
9120 SSVAL(params,2,0); /* No EA errors */
9122 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9124 return;
9127 /****************************************************************************
9128 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9129 ****************************************************************************/
9131 static void call_trans2getdfsreferral(connection_struct *conn,
9132 struct smb_request *req,
9133 char **pparams, int total_params,
9134 char **ppdata, int total_data,
9135 unsigned int max_data_bytes)
9137 char *params = *pparams;
9138 char *pathname = NULL;
9139 int reply_size = 0;
9140 int max_referral_level;
9141 NTSTATUS status = NT_STATUS_OK;
9142 TALLOC_CTX *ctx = talloc_tos();
9144 DEBUG(10,("call_trans2getdfsreferral\n"));
9146 if (total_params < 3) {
9147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9148 return;
9151 max_referral_level = SVAL(params,0);
9153 if(!lp_host_msdfs()) {
9154 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9155 return;
9158 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9159 total_params - 2, STR_TERMINATE);
9160 if (!pathname) {
9161 reply_nterror(req, NT_STATUS_NOT_FOUND);
9162 return;
9164 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9165 ppdata,&status)) < 0) {
9166 reply_nterror(req, status);
9167 return;
9170 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9171 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9172 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9174 return;
9177 #define LMCAT_SPL 0x53
9178 #define LMFUNC_GETJOBID 0x60
9180 /****************************************************************************
9181 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9182 ****************************************************************************/
9184 static void call_trans2ioctl(connection_struct *conn,
9185 struct smb_request *req,
9186 char **pparams, int total_params,
9187 char **ppdata, int total_data,
9188 unsigned int max_data_bytes)
9190 char *pdata = *ppdata;
9191 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9192 NTSTATUS status;
9193 size_t len = 0;
9195 /* check for an invalid fid before proceeding */
9197 if (!fsp) {
9198 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9199 return;
9202 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9203 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9204 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9205 if (*ppdata == NULL) {
9206 reply_nterror(req, NT_STATUS_NO_MEMORY);
9207 return;
9209 pdata = *ppdata;
9211 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9212 CAN ACCEPT THIS IN UNICODE. JRA. */
9214 /* Job number */
9215 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9217 status = srvstr_push(pdata, req->flags2, pdata + 2,
9218 lp_netbios_name(), 15,
9219 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9220 if (!NT_STATUS_IS_OK(status)) {
9221 reply_nterror(req, status);
9222 return;
9224 status = srvstr_push(pdata, req->flags2, pdata+18,
9225 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9226 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9227 if (!NT_STATUS_IS_OK(status)) {
9228 reply_nterror(req, status);
9229 return;
9231 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9232 max_data_bytes);
9233 return;
9236 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9237 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9240 /****************************************************************************
9241 Reply to a SMBfindclose (stop trans2 directory search).
9242 ****************************************************************************/
9244 void reply_findclose(struct smb_request *req)
9246 int dptr_num;
9247 struct smbd_server_connection *sconn = req->sconn;
9249 START_PROFILE(SMBfindclose);
9251 if (req->wct < 1) {
9252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9253 END_PROFILE(SMBfindclose);
9254 return;
9257 dptr_num = SVALS(req->vwv+0, 0);
9259 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9261 dptr_close(sconn, &dptr_num);
9263 reply_outbuf(req, 0, 0);
9265 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9267 END_PROFILE(SMBfindclose);
9268 return;
9271 /****************************************************************************
9272 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9273 ****************************************************************************/
9275 void reply_findnclose(struct smb_request *req)
9277 int dptr_num;
9279 START_PROFILE(SMBfindnclose);
9281 if (req->wct < 1) {
9282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9283 END_PROFILE(SMBfindnclose);
9284 return;
9287 dptr_num = SVAL(req->vwv+0, 0);
9289 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9291 /* We never give out valid handles for a
9292 findnotifyfirst - so any dptr_num is ok here.
9293 Just ignore it. */
9295 reply_outbuf(req, 0, 0);
9297 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9299 END_PROFILE(SMBfindnclose);
9300 return;
9303 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9304 struct trans_state *state)
9306 if (get_Protocol() >= PROTOCOL_NT1) {
9307 req->flags2 |= 0x40; /* IS_LONG_NAME */
9308 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9311 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9312 if (state->call != TRANSACT2_QFSINFO &&
9313 state->call != TRANSACT2_SETFSINFO) {
9314 DEBUG(0,("handle_trans2: encryption required "
9315 "with call 0x%x\n",
9316 (unsigned int)state->call));
9317 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9318 return;
9322 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9324 /* Now we must call the relevant TRANS2 function */
9325 switch(state->call) {
9326 case TRANSACT2_OPEN:
9328 START_PROFILE(Trans2_open);
9329 call_trans2open(conn, req,
9330 &state->param, state->total_param,
9331 &state->data, state->total_data,
9332 state->max_data_return);
9333 END_PROFILE(Trans2_open);
9334 break;
9337 case TRANSACT2_FINDFIRST:
9339 START_PROFILE(Trans2_findfirst);
9340 call_trans2findfirst(conn, req,
9341 &state->param, state->total_param,
9342 &state->data, state->total_data,
9343 state->max_data_return);
9344 END_PROFILE(Trans2_findfirst);
9345 break;
9348 case TRANSACT2_FINDNEXT:
9350 START_PROFILE(Trans2_findnext);
9351 call_trans2findnext(conn, req,
9352 &state->param, state->total_param,
9353 &state->data, state->total_data,
9354 state->max_data_return);
9355 END_PROFILE(Trans2_findnext);
9356 break;
9359 case TRANSACT2_QFSINFO:
9361 START_PROFILE(Trans2_qfsinfo);
9362 call_trans2qfsinfo(conn, req,
9363 &state->param, state->total_param,
9364 &state->data, state->total_data,
9365 state->max_data_return);
9366 END_PROFILE(Trans2_qfsinfo);
9367 break;
9370 case TRANSACT2_SETFSINFO:
9372 START_PROFILE(Trans2_setfsinfo);
9373 call_trans2setfsinfo(conn, req,
9374 &state->param, state->total_param,
9375 &state->data, state->total_data,
9376 state->max_data_return);
9377 END_PROFILE(Trans2_setfsinfo);
9378 break;
9381 case TRANSACT2_QPATHINFO:
9382 case TRANSACT2_QFILEINFO:
9384 START_PROFILE(Trans2_qpathinfo);
9385 call_trans2qfilepathinfo(conn, req, state->call,
9386 &state->param, state->total_param,
9387 &state->data, state->total_data,
9388 state->max_data_return);
9389 END_PROFILE(Trans2_qpathinfo);
9390 break;
9393 case TRANSACT2_SETPATHINFO:
9394 case TRANSACT2_SETFILEINFO:
9396 START_PROFILE(Trans2_setpathinfo);
9397 call_trans2setfilepathinfo(conn, req, state->call,
9398 &state->param, state->total_param,
9399 &state->data, state->total_data,
9400 state->max_data_return);
9401 END_PROFILE(Trans2_setpathinfo);
9402 break;
9405 case TRANSACT2_FINDNOTIFYFIRST:
9407 START_PROFILE(Trans2_findnotifyfirst);
9408 call_trans2findnotifyfirst(conn, req,
9409 &state->param, state->total_param,
9410 &state->data, state->total_data,
9411 state->max_data_return);
9412 END_PROFILE(Trans2_findnotifyfirst);
9413 break;
9416 case TRANSACT2_FINDNOTIFYNEXT:
9418 START_PROFILE(Trans2_findnotifynext);
9419 call_trans2findnotifynext(conn, req,
9420 &state->param, state->total_param,
9421 &state->data, state->total_data,
9422 state->max_data_return);
9423 END_PROFILE(Trans2_findnotifynext);
9424 break;
9427 case TRANSACT2_MKDIR:
9429 START_PROFILE(Trans2_mkdir);
9430 call_trans2mkdir(conn, req,
9431 &state->param, state->total_param,
9432 &state->data, state->total_data,
9433 state->max_data_return);
9434 END_PROFILE(Trans2_mkdir);
9435 break;
9438 case TRANSACT2_GET_DFS_REFERRAL:
9440 START_PROFILE(Trans2_get_dfs_referral);
9441 call_trans2getdfsreferral(conn, req,
9442 &state->param, state->total_param,
9443 &state->data, state->total_data,
9444 state->max_data_return);
9445 END_PROFILE(Trans2_get_dfs_referral);
9446 break;
9449 case TRANSACT2_IOCTL:
9451 START_PROFILE(Trans2_ioctl);
9452 call_trans2ioctl(conn, req,
9453 &state->param, state->total_param,
9454 &state->data, state->total_data,
9455 state->max_data_return);
9456 END_PROFILE(Trans2_ioctl);
9457 break;
9460 default:
9461 /* Error in request */
9462 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9463 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9467 /****************************************************************************
9468 Reply to a SMBtrans2.
9469 ****************************************************************************/
9471 void reply_trans2(struct smb_request *req)
9473 connection_struct *conn = req->conn;
9474 unsigned int dsoff;
9475 unsigned int dscnt;
9476 unsigned int psoff;
9477 unsigned int pscnt;
9478 unsigned int tran_call;
9479 struct trans_state *state;
9480 NTSTATUS result;
9482 START_PROFILE(SMBtrans2);
9484 if (req->wct < 14) {
9485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9486 END_PROFILE(SMBtrans2);
9487 return;
9490 dsoff = SVAL(req->vwv+12, 0);
9491 dscnt = SVAL(req->vwv+11, 0);
9492 psoff = SVAL(req->vwv+10, 0);
9493 pscnt = SVAL(req->vwv+9, 0);
9494 tran_call = SVAL(req->vwv+14, 0);
9496 result = allow_new_trans(conn->pending_trans, req->mid);
9497 if (!NT_STATUS_IS_OK(result)) {
9498 DEBUG(2, ("Got invalid trans2 request: %s\n",
9499 nt_errstr(result)));
9500 reply_nterror(req, result);
9501 END_PROFILE(SMBtrans2);
9502 return;
9505 if (IS_IPC(conn)) {
9506 switch (tran_call) {
9507 /* List the allowed trans2 calls on IPC$ */
9508 case TRANSACT2_OPEN:
9509 case TRANSACT2_GET_DFS_REFERRAL:
9510 case TRANSACT2_QFILEINFO:
9511 case TRANSACT2_QFSINFO:
9512 case TRANSACT2_SETFSINFO:
9513 break;
9514 default:
9515 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9516 END_PROFILE(SMBtrans2);
9517 return;
9521 if ((state = talloc(conn, struct trans_state)) == NULL) {
9522 DEBUG(0, ("talloc failed\n"));
9523 reply_nterror(req, NT_STATUS_NO_MEMORY);
9524 END_PROFILE(SMBtrans2);
9525 return;
9528 state->cmd = SMBtrans2;
9530 state->mid = req->mid;
9531 state->vuid = req->vuid;
9532 state->setup_count = SVAL(req->vwv+13, 0);
9533 state->setup = NULL;
9534 state->total_param = SVAL(req->vwv+0, 0);
9535 state->param = NULL;
9536 state->total_data = SVAL(req->vwv+1, 0);
9537 state->data = NULL;
9538 state->max_param_return = SVAL(req->vwv+2, 0);
9539 state->max_data_return = SVAL(req->vwv+3, 0);
9540 state->max_setup_return = SVAL(req->vwv+4, 0);
9541 state->close_on_completion = BITSETW(req->vwv+5, 0);
9542 state->one_way = BITSETW(req->vwv+5, 1);
9544 state->call = tran_call;
9546 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9547 is so as a sanity check */
9548 if (state->setup_count != 1) {
9550 * Need to have rc=0 for ioctl to get job id for OS/2.
9551 * Network printing will fail if function is not successful.
9552 * Similar function in reply.c will be used if protocol
9553 * is LANMAN1.0 instead of LM1.2X002.
9554 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9555 * outbuf doesn't have to be set(only job id is used).
9557 if ( (state->setup_count == 4)
9558 && (tran_call == TRANSACT2_IOCTL)
9559 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9560 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9561 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9562 } else {
9563 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9564 DEBUG(2,("Transaction is %d\n",tran_call));
9565 TALLOC_FREE(state);
9566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9567 END_PROFILE(SMBtrans2);
9568 return;
9572 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9573 goto bad_param;
9575 if (state->total_data) {
9577 if (trans_oob(state->total_data, 0, dscnt)
9578 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9579 goto bad_param;
9582 /* Can't use talloc here, the core routines do realloc on the
9583 * params and data. */
9584 state->data = (char *)SMB_MALLOC(state->total_data);
9585 if (state->data == NULL) {
9586 DEBUG(0,("reply_trans2: data malloc fail for %u "
9587 "bytes !\n", (unsigned int)state->total_data));
9588 TALLOC_FREE(state);
9589 reply_nterror(req, NT_STATUS_NO_MEMORY);
9590 END_PROFILE(SMBtrans2);
9591 return;
9594 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9597 if (state->total_param) {
9599 if (trans_oob(state->total_param, 0, pscnt)
9600 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9601 goto bad_param;
9604 /* Can't use talloc here, the core routines do realloc on the
9605 * params and data. */
9606 state->param = (char *)SMB_MALLOC(state->total_param);
9607 if (state->param == NULL) {
9608 DEBUG(0,("reply_trans: param malloc fail for %u "
9609 "bytes !\n", (unsigned int)state->total_param));
9610 SAFE_FREE(state->data);
9611 TALLOC_FREE(state);
9612 reply_nterror(req, NT_STATUS_NO_MEMORY);
9613 END_PROFILE(SMBtrans2);
9614 return;
9617 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9620 state->received_data = dscnt;
9621 state->received_param = pscnt;
9623 if ((state->received_param == state->total_param) &&
9624 (state->received_data == state->total_data)) {
9626 handle_trans2(conn, req, state);
9628 SAFE_FREE(state->data);
9629 SAFE_FREE(state->param);
9630 TALLOC_FREE(state);
9631 END_PROFILE(SMBtrans2);
9632 return;
9635 DLIST_ADD(conn->pending_trans, state);
9637 /* We need to send an interim response then receive the rest
9638 of the parameter/data bytes */
9639 reply_outbuf(req, 0, 0);
9640 show_msg((char *)req->outbuf);
9641 END_PROFILE(SMBtrans2);
9642 return;
9644 bad_param:
9646 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9647 SAFE_FREE(state->data);
9648 SAFE_FREE(state->param);
9649 TALLOC_FREE(state);
9650 END_PROFILE(SMBtrans2);
9651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9655 /****************************************************************************
9656 Reply to a SMBtranss2
9657 ****************************************************************************/
9659 void reply_transs2(struct smb_request *req)
9661 connection_struct *conn = req->conn;
9662 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9663 struct trans_state *state;
9665 START_PROFILE(SMBtranss2);
9667 show_msg((const char *)req->inbuf);
9669 /* Windows clients expect all replies to
9670 a transact secondary (SMBtranss2 0x33)
9671 to have a command code of transact
9672 (SMBtrans2 0x32). See bug #8989
9673 and also [MS-CIFS] section 2.2.4.47.2
9674 for details.
9676 req->cmd = SMBtrans2;
9678 if (req->wct < 8) {
9679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9680 END_PROFILE(SMBtranss2);
9681 return;
9684 for (state = conn->pending_trans; state != NULL;
9685 state = state->next) {
9686 if (state->mid == req->mid) {
9687 break;
9691 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9693 END_PROFILE(SMBtranss2);
9694 return;
9697 /* Revise state->total_param and state->total_data in case they have
9698 changed downwards */
9700 if (SVAL(req->vwv+0, 0) < state->total_param)
9701 state->total_param = SVAL(req->vwv+0, 0);
9702 if (SVAL(req->vwv+1, 0) < state->total_data)
9703 state->total_data = SVAL(req->vwv+1, 0);
9705 pcnt = SVAL(req->vwv+2, 0);
9706 poff = SVAL(req->vwv+3, 0);
9707 pdisp = SVAL(req->vwv+4, 0);
9709 dcnt = SVAL(req->vwv+5, 0);
9710 doff = SVAL(req->vwv+6, 0);
9711 ddisp = SVAL(req->vwv+7, 0);
9713 state->received_param += pcnt;
9714 state->received_data += dcnt;
9716 if ((state->received_data > state->total_data) ||
9717 (state->received_param > state->total_param))
9718 goto bad_param;
9720 if (pcnt) {
9721 if (trans_oob(state->total_param, pdisp, pcnt)
9722 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9723 goto bad_param;
9725 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9728 if (dcnt) {
9729 if (trans_oob(state->total_data, ddisp, dcnt)
9730 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9731 goto bad_param;
9733 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9736 if ((state->received_param < state->total_param) ||
9737 (state->received_data < state->total_data)) {
9738 END_PROFILE(SMBtranss2);
9739 return;
9742 handle_trans2(conn, req, state);
9744 DLIST_REMOVE(conn->pending_trans, state);
9745 SAFE_FREE(state->data);
9746 SAFE_FREE(state->param);
9747 TALLOC_FREE(state);
9749 END_PROFILE(SMBtranss2);
9750 return;
9752 bad_param:
9754 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9755 DLIST_REMOVE(conn->pending_trans, state);
9756 SAFE_FREE(state->data);
9757 SAFE_FREE(state->param);
9758 TALLOC_FREE(state);
9759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9760 END_PROFILE(SMBtranss2);
9761 return;