lib: Make ctdbd_db_attach return 0/errno
[Samba.git] / source3 / smbd / trans2.c
blob58d18fbe98751c8adcdf26b083e3f7ac8d7395de
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 The canonical "check access" based on object handle or path function.
59 ********************************************************************/
61 NTSTATUS check_access(connection_struct *conn,
62 files_struct *fsp,
63 const struct smb_filename *smb_fname,
64 uint32_t access_mask)
66 if (fsp) {
67 if (!(fsp->access_mask & access_mask)) {
68 return NT_STATUS_ACCESS_DENIED;
70 } else {
71 NTSTATUS status = smbd_check_access_rights(conn,
72 smb_fname,
73 false,
74 access_mask);
75 if (!NT_STATUS_IS_OK(status)) {
76 return status;
79 return NT_STATUS_OK;
82 /********************************************************************
83 Roundup a value to the nearest allocation roundup size boundary.
84 Only do this for Windows clients.
85 ********************************************************************/
87 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
89 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
91 /* Only roundup for Windows clients. */
92 enum remote_arch_types ra_type = get_remote_arch();
93 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
94 val = SMB_ROUNDUP(val,rval);
96 return val;
99 /********************************************************************
100 Create a 64 bit FileIndex. If the file is on the same device as
101 the root of the share, just return the 64-bit inode. If it isn't,
102 mangle as we used to do.
103 ********************************************************************/
105 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
107 uint64_t file_index;
108 if (conn->base_share_dev == psbuf->st_ex_dev) {
109 return (uint64_t)psbuf->st_ex_ino;
111 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
112 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
113 return file_index;
116 /****************************************************************************
117 Utility functions for dealing with extended attributes.
118 ****************************************************************************/
120 /****************************************************************************
121 Refuse to allow clients to overwrite our private xattrs.
122 ****************************************************************************/
124 bool samba_private_attr_name(const char *unix_ea_name)
126 static const char * const prohibited_ea_names[] = {
127 SAMBA_POSIX_INHERITANCE_EA_NAME,
128 SAMBA_XATTR_DOS_ATTRIB,
129 SAMBA_XATTR_MARKER,
130 XATTR_NTACL_NAME,
131 NULL
134 int i;
136 for (i = 0; prohibited_ea_names[i]; i++) {
137 if (strequal( prohibited_ea_names[i], unix_ea_name))
138 return true;
140 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
141 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
142 return true;
144 return false;
147 /****************************************************************************
148 Get one EA value. Fill in a struct ea_struct.
149 ****************************************************************************/
151 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
152 files_struct *fsp, const char *fname,
153 const char *ea_name, struct ea_struct *pea)
155 /* Get the value of this xattr. Max size is 64k. */
156 size_t attr_size = 256;
157 char *val = NULL;
158 ssize_t sizeret;
160 again:
162 val = talloc_realloc(mem_ctx, val, char, attr_size);
163 if (!val) {
164 return NT_STATUS_NO_MEMORY;
167 if (fsp && fsp->fh->fd != -1) {
168 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
169 } else {
170 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
173 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
174 attr_size = 65536;
175 goto again;
178 if (sizeret == -1) {
179 return map_nt_error_from_unix(errno);
182 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
183 dump_data(10, (uint8_t *)val, sizeret);
185 pea->flags = 0;
186 if (strnequal(ea_name, "user.", 5)) {
187 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
188 } else {
189 pea->name = talloc_strdup(mem_ctx, ea_name);
191 if (pea->name == NULL) {
192 TALLOC_FREE(val);
193 return NT_STATUS_NO_MEMORY;
195 pea->value.data = (unsigned char *)val;
196 pea->value.length = (size_t)sizeret;
197 return NT_STATUS_OK;
200 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
201 files_struct *fsp, const char *fname,
202 char ***pnames, size_t *pnum_names)
204 /* Get a list of all xattrs. Max namesize is 64k. */
205 size_t ea_namelist_size = 1024;
206 char *ea_namelist = NULL;
208 char *p;
209 char **names, **tmp;
210 size_t num_names;
211 ssize_t sizeret = -1;
213 if (!lp_ea_support(SNUM(conn))) {
214 if (pnames) {
215 *pnames = NULL;
217 *pnum_names = 0;
218 return NT_STATUS_OK;
222 * TALLOC the result early to get the talloc hierarchy right.
225 names = talloc_array(mem_ctx, char *, 1);
226 if (names == NULL) {
227 DEBUG(0, ("talloc failed\n"));
228 return NT_STATUS_NO_MEMORY;
231 while (ea_namelist_size <= 65536) {
233 ea_namelist = talloc_realloc(
234 names, ea_namelist, char, ea_namelist_size);
235 if (ea_namelist == NULL) {
236 DEBUG(0, ("talloc failed\n"));
237 TALLOC_FREE(names);
238 return NT_STATUS_NO_MEMORY;
241 if (fsp && fsp->fh->fd != -1) {
242 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
243 ea_namelist_size);
244 } else {
245 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
246 ea_namelist_size);
249 if ((sizeret == -1) && (errno == ERANGE)) {
250 ea_namelist_size *= 2;
252 else {
253 break;
257 if (sizeret == -1) {
258 TALLOC_FREE(names);
259 return map_nt_error_from_unix(errno);
262 DEBUG(10, ("%s: ea_namelist size = %u\n",
263 __func__, (unsigned int)sizeret));
265 if (sizeret == 0) {
266 TALLOC_FREE(names);
267 if (pnames) {
268 *pnames = NULL;
270 *pnum_names = 0;
271 return NT_STATUS_OK;
275 * Ensure the result is 0-terminated
278 if (ea_namelist[sizeret-1] != '\0') {
279 TALLOC_FREE(names);
280 return NT_STATUS_INTERNAL_ERROR;
284 * count the names
286 num_names = 0;
288 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
289 num_names += 1;
292 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
293 if (tmp == NULL) {
294 DEBUG(0, ("talloc failed\n"));
295 TALLOC_FREE(names);
296 return NT_STATUS_NO_MEMORY;
299 names = tmp;
300 num_names = 0;
302 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
303 names[num_names++] = p;
306 if (pnames) {
307 *pnames = names;
308 } else {
309 TALLOC_FREE(names);
311 *pnum_names = num_names;
312 return NT_STATUS_OK;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
320 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
322 /* Get a list of all xattrs. Max namesize is 64k. */
323 size_t i, num_names;
324 char **names;
325 struct ea_list *ea_list_head = NULL;
326 NTSTATUS status;
328 *pea_total_len = 0;
329 *ea_list = NULL;
331 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
332 &names, &num_names);
334 if (!NT_STATUS_IS_OK(status)) {
335 return status;
338 if (num_names == 0) {
339 *ea_list = NULL;
340 return NT_STATUS_OK;
343 for (i=0; i<num_names; i++) {
344 struct ea_list *listp;
345 fstring dos_ea_name;
347 if (strnequal(names[i], "system.", 7)
348 || samba_private_attr_name(names[i]))
349 continue;
352 * Filter out any underlying POSIX EA names
353 * that a Windows client can't handle.
355 if (!lp_posix_pathnames() &&
356 is_invalid_windows_ea_name(names[i])) {
357 continue;
360 listp = talloc(mem_ctx, struct ea_list);
361 if (listp == NULL) {
362 return NT_STATUS_NO_MEMORY;
365 status = get_ea_value(listp, conn, fsp,
366 fname, names[i],
367 &listp->ea);
369 if (!NT_STATUS_IS_OK(status)) {
370 TALLOC_FREE(listp);
371 return status;
374 if (listp->ea.value.length == 0) {
376 * We can never return a zero length EA.
377 * Windows reports the EA's as corrupted.
379 TALLOC_FREE(listp);
380 continue;
383 push_ascii_fstring(dos_ea_name, listp->ea.name);
385 *pea_total_len +=
386 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
388 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
389 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
390 (unsigned int)listp->ea.value.length));
392 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
396 /* Add on 4 for total length. */
397 if (*pea_total_len) {
398 *pea_total_len += 4;
401 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
402 (unsigned int)*pea_total_len));
404 *ea_list = ea_list_head;
405 return NT_STATUS_OK;
408 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
409 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
411 *pea_total_len = 0;
412 *ea_list = NULL;
414 if (!lp_ea_support(SNUM(conn))) {
415 return NT_STATUS_OK;
418 if (is_ntfs_stream_smb_fname(smb_fname)) {
419 return NT_STATUS_INVALID_PARAMETER;
422 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
425 /****************************************************************************
426 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
427 that was filled.
428 ****************************************************************************/
430 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
431 connection_struct *conn, struct ea_list *ea_list)
433 unsigned int ret_data_size = 4;
434 char *p = pdata;
436 SMB_ASSERT(total_data_size >= 4);
438 if (!lp_ea_support(SNUM(conn))) {
439 SIVAL(pdata,4,0);
440 return 4;
443 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
444 size_t dos_namelen;
445 fstring dos_ea_name;
446 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
447 dos_namelen = strlen(dos_ea_name);
448 if (dos_namelen > 255 || dos_namelen == 0) {
449 break;
451 if (ea_list->ea.value.length > 65535) {
452 break;
454 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
455 break;
458 /* We know we have room. */
459 SCVAL(p,0,ea_list->ea.flags);
460 SCVAL(p,1,dos_namelen);
461 SSVAL(p,2,ea_list->ea.value.length);
462 strlcpy(p+4, dos_ea_name, dos_namelen+1);
463 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
465 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
469 ret_data_size = PTR_DIFF(p, pdata);
470 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
471 SIVAL(pdata,0,ret_data_size);
472 return ret_data_size;
475 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
476 char *pdata,
477 unsigned int total_data_size,
478 unsigned int *ret_data_size,
479 connection_struct *conn,
480 struct ea_list *ea_list)
482 uint8_t *p = (uint8_t *)pdata;
483 uint8_t *last_start = NULL;
484 bool do_store_data = (pdata != NULL);
486 *ret_data_size = 0;
488 if (!lp_ea_support(SNUM(conn))) {
489 return NT_STATUS_NO_EAS_ON_FILE;
492 for (; ea_list; ea_list = ea_list->next) {
493 size_t dos_namelen;
494 fstring dos_ea_name;
495 size_t this_size;
496 size_t pad = 0;
498 if (last_start != NULL && do_store_data) {
499 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
501 last_start = p;
503 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
504 dos_namelen = strlen(dos_ea_name);
505 if (dos_namelen > 255 || dos_namelen == 0) {
506 return NT_STATUS_INTERNAL_ERROR;
508 if (ea_list->ea.value.length > 65535) {
509 return NT_STATUS_INTERNAL_ERROR;
512 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
514 if (ea_list->next) {
515 pad = (4 - (this_size % 4)) % 4;
516 this_size += pad;
519 if (do_store_data) {
520 if (this_size > total_data_size) {
521 return NT_STATUS_INFO_LENGTH_MISMATCH;
524 /* We know we have room. */
525 SIVAL(p, 0x00, 0); /* next offset */
526 SCVAL(p, 0x04, ea_list->ea.flags);
527 SCVAL(p, 0x05, dos_namelen);
528 SSVAL(p, 0x06, ea_list->ea.value.length);
529 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
530 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
531 if (pad) {
532 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
533 '\0',
534 pad);
536 total_data_size -= this_size;
539 p += this_size;
542 *ret_data_size = PTR_DIFF(p, pdata);
543 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
544 return NT_STATUS_OK;
547 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
549 size_t total_ea_len = 0;
550 TALLOC_CTX *mem_ctx;
551 struct ea_list *ea_list = NULL;
553 if (!lp_ea_support(SNUM(conn))) {
554 return 0;
556 mem_ctx = talloc_stackframe();
558 /* If this is a stream fsp, then we need to instead find the
559 * estimated ea len from the main file, not the stream
560 * (streams cannot have EAs), but the estimate isn't just 0 in
561 * this case! */
562 if (is_ntfs_stream_smb_fname(smb_fname)) {
563 fsp = NULL;
565 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
566 if(conn->sconn->using_smb2) {
567 NTSTATUS status;
568 unsigned int ret_data_size;
570 * We're going to be using fill_ea_chained_buffer() to
571 * marshall EA's - this size is significantly larger
572 * than the SMB1 buffer. Re-calculate the size without
573 * marshalling.
575 status = fill_ea_chained_buffer(mem_ctx,
576 NULL,
578 &ret_data_size,
579 conn,
580 ea_list);
581 if (!NT_STATUS_IS_OK(status)) {
582 ret_data_size = 0;
584 total_ea_len = ret_data_size;
586 TALLOC_FREE(mem_ctx);
587 return total_ea_len;
590 /****************************************************************************
591 Ensure the EA name is case insensitive by matching any existing EA name.
592 ****************************************************************************/
594 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
596 size_t total_ea_len;
597 TALLOC_CTX *mem_ctx = talloc_tos();
598 struct ea_list *ea_list;
599 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
600 if (!NT_STATUS_IS_OK(status)) {
601 return;
604 for (; ea_list; ea_list = ea_list->next) {
605 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
606 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
607 &unix_ea_name[5], ea_list->ea.name));
608 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
609 break;
614 /****************************************************************************
615 Set or delete an extended attribute.
616 ****************************************************************************/
618 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
619 const struct smb_filename *smb_fname, struct ea_list *ea_list)
621 NTSTATUS status;
622 char *fname = NULL;
624 if (!lp_ea_support(SNUM(conn))) {
625 return NT_STATUS_EAS_NOT_SUPPORTED;
628 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
629 if (!NT_STATUS_IS_OK(status)) {
630 return status;
633 /* Setting EAs on streams isn't supported. */
634 if (is_ntfs_stream_smb_fname(smb_fname)) {
635 return NT_STATUS_INVALID_PARAMETER;
639 * Filter out invalid Windows EA names - before
640 * we set *any* of them.
643 if (ea_list_has_invalid_name(ea_list)) {
644 return STATUS_INVALID_EA_NAME;
647 fname = smb_fname->base_name;
649 for (;ea_list; ea_list = ea_list->next) {
650 int ret;
651 fstring unix_ea_name;
653 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
654 fstrcat(unix_ea_name, ea_list->ea.name);
656 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
658 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
660 if (samba_private_attr_name(unix_ea_name)) {
661 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
662 return NT_STATUS_ACCESS_DENIED;
665 if (ea_list->ea.value.length == 0) {
666 /* Remove the attribute. */
667 if (fsp && (fsp->fh->fd != -1)) {
668 DEBUG(10,("set_ea: deleting ea name %s on "
669 "file %s by file descriptor.\n",
670 unix_ea_name, fsp_str_dbg(fsp)));
671 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
672 } else {
673 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
674 unix_ea_name, fname));
675 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
677 #ifdef ENOATTR
678 /* Removing a non existent attribute always succeeds. */
679 if (ret == -1 && errno == ENOATTR) {
680 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
681 unix_ea_name));
682 ret = 0;
684 #endif
685 } else {
686 if (fsp && (fsp->fh->fd != -1)) {
687 DEBUG(10,("set_ea: setting ea name %s on file "
688 "%s by file descriptor.\n",
689 unix_ea_name, fsp_str_dbg(fsp)));
690 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
691 ea_list->ea.value.data, ea_list->ea.value.length, 0);
692 } else {
693 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
694 unix_ea_name, fname));
695 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
700 if (ret == -1) {
701 #ifdef ENOTSUP
702 if (errno == ENOTSUP) {
703 return NT_STATUS_EAS_NOT_SUPPORTED;
705 #endif
706 return map_nt_error_from_unix(errno);
710 return NT_STATUS_OK;
712 /****************************************************************************
713 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
718 struct ea_list *ea_list_head = NULL;
719 size_t converted_size, offset = 0;
721 while (offset + 2 < data_size) {
722 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
723 unsigned int namelen = CVAL(pdata,offset);
725 offset++; /* Go past the namelen byte. */
727 /* integer wrap paranioa. */
728 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
729 (offset > data_size) || (namelen > data_size) ||
730 (offset + namelen >= data_size)) {
731 break;
733 /* Ensure the name is null terminated. */
734 if (pdata[offset + namelen] != '\0') {
735 return NULL;
737 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
738 &converted_size)) {
739 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
740 "failed: %s", strerror(errno)));
742 if (!eal->ea.name) {
743 return NULL;
746 offset += (namelen + 1); /* Go past the name + terminating zero. */
747 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
748 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
751 return ea_list_head;
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
760 struct ea_list *ea_list_head = NULL;
761 size_t offset = 0;
762 size_t bytes_used = 0;
764 while (offset < data_size) {
765 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
767 if (!eal) {
768 return NULL;
771 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
772 offset += bytes_used;
775 return ea_list_head;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list *ealist)
784 fstring dos_ea_name;
785 struct ea_list *listp;
786 size_t ret = 0;
788 for (listp = ealist; listp; listp = listp->next) {
789 push_ascii_fstring(dos_ea_name, listp->ea.name);
790 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
792 /* Add on 4 for total length. */
793 if (ret) {
794 ret += 4;
797 return ret;
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
808 struct ea_list *nlistp, *flistp;
810 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
811 for (flistp = file_list; flistp; flistp = flistp->next) {
812 if (strequal(nlistp->ea.name, flistp->ea.name)) {
813 break;
817 if (flistp) {
818 /* Copy the data from this entry. */
819 nlistp->ea.flags = flistp->ea.flags;
820 nlistp->ea.value = flistp->ea.value;
821 } else {
822 /* Null entry. */
823 nlistp->ea.flags = 0;
824 ZERO_STRUCT(nlistp->ea.value);
828 *total_ea_len = ea_list_size(name_list);
829 return name_list;
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct *conn,
840 struct smb_request *req,
841 NTSTATUS status,
842 const char *params,
843 int paramsize,
844 const char *pdata,
845 int datasize,
846 int max_data_bytes)
848 /* As we are using a protocol > LANMAN1 then the max_send
849 variable must have been set in the sessetupX call.
850 This takes precedence over the max_xmit field in the
851 global struct. These different max_xmit variables should
852 be merged as this is now too confusing */
854 int data_to_send = datasize;
855 int params_to_send = paramsize;
856 int useable_space;
857 const char *pp = params;
858 const char *pd = pdata;
859 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
860 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
861 int data_alignment_offset = 0;
862 bool overflow = False;
863 struct smbXsrv_connection *xconn = req->xconn;
864 int max_send = xconn->smb1.sessions.max_send;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
869 for OS/2. */
871 if (max_data_bytes > 0 && datasize > max_data_bytes) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes, datasize ));
874 datasize = data_to_send = max_data_bytes;
875 overflow = True;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send == 0 && data_to_send == 0) {
881 reply_outbuf(req, 10, 0);
882 if (NT_STATUS_V(status)) {
883 uint8_t eclass;
884 uint32_t ecode;
885 ntstatus_to_dos(status, &eclass, &ecode);
886 error_packet_set((char *)req->outbuf,
887 eclass, ecode, status,
888 __LINE__,__FILE__);
890 show_msg((char *)req->outbuf);
891 if (!srv_send_smb(xconn,
892 (char *)req->outbuf,
893 true, req->seqnum+1,
894 IS_CONN_ENCRYPTED(conn),
895 &req->pcd)) {
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req->outbuf);
899 return;
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send % 4) != 0) && (data_to_send != 0))
907 data_alignment_offset = 4 - (params_to_send % 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space = max_send - (smb_size
914 + 2 * 10 /* wct */
915 + alignment_offset
916 + data_alignment_offset);
918 if (useable_space < 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send || data_to_send) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime = params_to_send + data_to_send;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime = MIN(total_sent_thistime, useable_space);
939 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
940 + data_alignment_offset);
942 /* Set total params and data to be sent */
943 SSVAL(req->outbuf,smb_tprcnt,paramsize);
944 SSVAL(req->outbuf,smb_tdrcnt,datasize);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime = MIN(params_to_send,useable_space);
951 data_sent_thistime = useable_space - params_sent_thistime;
952 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
954 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req->outbuf,smb_proff,
962 ((smb_buf(req->outbuf)+alignment_offset)
963 - smb_base(req->outbuf)));
965 if(params_sent_thistime == 0)
966 SSVAL(req->outbuf,smb_prdisp,0);
967 else
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req->outbuf,smb_prdisp,pp - params);
971 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
972 if(data_sent_thistime == 0) {
973 SSVAL(req->outbuf,smb_droff,0);
974 SSVAL(req->outbuf,smb_drdisp, 0);
975 } else {
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req->outbuf, smb_droff,
979 ((smb_buf(req->outbuf)+alignment_offset)
980 - smb_base(req->outbuf))
981 + params_sent_thistime + data_alignment_offset);
982 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
985 /* Initialize the padding for alignment */
987 if (alignment_offset != 0) {
988 memset(smb_buf(req->outbuf), 0, alignment_offset);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime) {
994 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
995 params_sent_thistime);
998 /* Copy in the data bytes */
999 if(data_sent_thistime) {
1000 if (data_alignment_offset != 0) {
1001 memset((smb_buf(req->outbuf)+alignment_offset+
1002 params_sent_thistime), 0,
1003 data_alignment_offset);
1005 memcpy(smb_buf(req->outbuf)+alignment_offset
1006 +params_sent_thistime+data_alignment_offset,
1007 pd,data_sent_thistime);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime, data_sent_thistime, useable_space));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send, data_to_send, paramsize, datasize));
1015 if (overflow) {
1016 error_packet_set((char *)req->outbuf,
1017 ERRDOS,ERRbufferoverflow,
1018 STATUS_BUFFER_OVERFLOW,
1019 __LINE__,__FILE__);
1020 } else if (NT_STATUS_V(status)) {
1021 uint8_t eclass;
1022 uint32_t ecode;
1023 ntstatus_to_dos(status, &eclass, &ecode);
1024 error_packet_set((char *)req->outbuf,
1025 eclass, ecode, status,
1026 __LINE__,__FILE__);
1029 /* Send the packet */
1030 show_msg((char *)req->outbuf);
1031 if (!srv_send_smb(xconn,
1032 (char *)req->outbuf,
1033 true, req->seqnum+1,
1034 IS_CONN_ENCRYPTED(conn),
1035 &req->pcd))
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req->outbuf);
1040 pp += params_sent_thistime;
1041 pd += data_sent_thistime;
1043 params_to_send -= params_sent_thistime;
1044 data_to_send -= data_sent_thistime;
1046 /* Sanity check */
1047 if(params_to_send < 0 || data_to_send < 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send, data_to_send));
1050 return;
1054 return;
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct *conn,
1062 struct smb_request *req,
1063 char **pparams, int total_params,
1064 char **ppdata, int total_data,
1065 unsigned int max_data_bytes)
1067 struct smb_filename *smb_fname = NULL;
1068 char *params = *pparams;
1069 char *pdata = *ppdata;
1070 int deny_mode;
1071 int32_t open_attr;
1072 bool oplock_request;
1073 #if 0
1074 bool return_additional_info;
1075 int16 open_sattr;
1076 time_t open_time;
1077 #endif
1078 int open_ofun;
1079 uint32_t open_size;
1080 char *pname;
1081 char *fname = NULL;
1082 off_t size=0;
1083 int fattr=0,mtime=0;
1084 SMB_INO_T inode = 0;
1085 int smb_action = 0;
1086 files_struct *fsp;
1087 struct ea_list *ea_list = NULL;
1088 uint16_t flags = 0;
1089 NTSTATUS status;
1090 uint32_t access_mask;
1091 uint32_t share_mode;
1092 uint32_t create_disposition;
1093 uint32_t create_options = 0;
1094 uint32_t private_flags = 0;
1095 TALLOC_CTX *ctx = talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params < 29) {
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1103 goto out;
1106 flags = SVAL(params, 0);
1107 deny_mode = SVAL(params, 2);
1108 open_attr = SVAL(params,6);
1109 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1110 if (oplock_request) {
1111 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1114 #if 0
1115 return_additional_info = BITSETW(params,0);
1116 open_sattr = SVAL(params, 4);
1117 open_time = make_unix_date3(params+8);
1118 #endif
1119 open_ofun = SVAL(params,12);
1120 open_size = IVAL(params,14);
1121 pname = &params[28];
1123 if (IS_IPC(conn)) {
1124 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1125 goto out;
1128 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1129 total_params - 28, STR_TERMINATE,
1130 &status);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 reply_nterror(req, status);
1133 goto out;
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1138 (unsigned int)open_ofun, open_size));
1140 status = filename_convert(ctx,
1141 conn,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1143 fname,
1145 NULL,
1146 &smb_fname);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req,
1150 NT_STATUS_PATH_NOT_COVERED,
1151 ERRSRV, ERRbadpath);
1152 goto out;
1154 reply_nterror(req, status);
1155 goto out;
1158 if (open_ofun == 0) {
1159 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1160 goto out;
1163 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1164 open_ofun,
1165 &access_mask, &share_mode,
1166 &create_disposition,
1167 &create_options,
1168 &private_flags)) {
1169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1170 goto out;
1173 /* Any data in this call is an EA list. */
1174 if (total_data && (total_data != 4)) {
1175 if (total_data < 10) {
1176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1177 goto out;
1180 if (IVAL(pdata,0) > total_data) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata,0), (unsigned int)total_data));
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1184 goto out;
1187 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1188 total_data - 4);
1189 if (!ea_list) {
1190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1191 goto out;
1194 if (!lp_ea_support(SNUM(conn))) {
1195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1196 goto out;
1199 if (ea_list_has_invalid_name(ea_list)) {
1200 int param_len = 30;
1201 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1202 if(*pparams == NULL ) {
1203 reply_nterror(req, NT_STATUS_NO_MEMORY);
1204 goto out;
1206 params = *pparams;
1207 memset(params, '\0', param_len);
1208 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1209 params, param_len, NULL, 0, max_data_bytes);
1210 goto out;
1214 status = SMB_VFS_CREATE_FILE(
1215 conn, /* conn */
1216 req, /* req */
1217 0, /* root_dir_fid */
1218 smb_fname, /* fname */
1219 access_mask, /* access_mask */
1220 share_mode, /* share_access */
1221 create_disposition, /* create_disposition*/
1222 create_options, /* create_options */
1223 open_attr, /* file_attributes */
1224 oplock_request, /* oplock_request */
1225 NULL, /* lease */
1226 open_size, /* allocation_size */
1227 private_flags,
1228 NULL, /* sd */
1229 ea_list, /* ea_list */
1230 &fsp, /* result */
1231 &smb_action, /* psbuf */
1232 NULL, NULL); /* create context */
1234 if (!NT_STATUS_IS_OK(status)) {
1235 if (open_was_deferred(req->xconn, req->mid)) {
1236 /* We have re-scheduled this call. */
1237 goto out;
1239 reply_openerror(req, status);
1240 goto out;
1243 size = get_file_size_stat(&smb_fname->st);
1244 fattr = dos_mode(conn, smb_fname);
1245 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1246 inode = smb_fname->st.st_ex_ino;
1247 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1248 close_file(req, fsp, ERROR_CLOSE);
1249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1250 goto out;
1253 /* Realloc the size of parameters and data we will return */
1254 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1255 if(*pparams == NULL ) {
1256 reply_nterror(req, NT_STATUS_NO_MEMORY);
1257 goto out;
1259 params = *pparams;
1261 SSVAL(params,0,fsp->fnum);
1262 SSVAL(params,2,fattr);
1263 srv_put_dos_date2(params,4, mtime);
1264 SIVAL(params,8, (uint32_t)size);
1265 SSVAL(params,12,deny_mode);
1266 SSVAL(params,14,0); /* open_type - file or directory. */
1267 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1269 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1270 smb_action |= EXTENDED_OPLOCK_GRANTED;
1273 SSVAL(params,18,smb_action);
1276 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1278 SIVAL(params,20,inode);
1279 SSVAL(params,24,0); /* Padding. */
1280 if (flags & 8) {
1281 uint32_t ea_size = estimate_ea_size(conn, fsp,
1282 smb_fname);
1283 SIVAL(params, 26, ea_size);
1284 } else {
1285 SIVAL(params, 26, 0);
1288 /* Send the required number of replies */
1289 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1290 out:
1291 TALLOC_FREE(smb_fname);
1294 /*********************************************************
1295 Routine to check if a given string matches exactly.
1296 as a special case a mask of "." does NOT match. That
1297 is required for correct wildcard semantics
1298 Case can be significant or not.
1299 **********************************************************/
1301 static bool exact_match(bool has_wild,
1302 bool case_sensitive,
1303 const char *str,
1304 const char *mask)
1306 if (mask[0] == '.' && mask[1] == 0) {
1307 return false;
1310 if (has_wild) {
1311 return false;
1314 if (case_sensitive) {
1315 return strcmp(str,mask)==0;
1316 } else {
1317 return strcasecmp_m(str,mask) == 0;
1321 /****************************************************************************
1322 Return the filetype for UNIX extensions.
1323 ****************************************************************************/
1325 static uint32_t unix_filetype(mode_t mode)
1327 if(S_ISREG(mode))
1328 return UNIX_TYPE_FILE;
1329 else if(S_ISDIR(mode))
1330 return UNIX_TYPE_DIR;
1331 #ifdef S_ISLNK
1332 else if(S_ISLNK(mode))
1333 return UNIX_TYPE_SYMLINK;
1334 #endif
1335 #ifdef S_ISCHR
1336 else if(S_ISCHR(mode))
1337 return UNIX_TYPE_CHARDEV;
1338 #endif
1339 #ifdef S_ISBLK
1340 else if(S_ISBLK(mode))
1341 return UNIX_TYPE_BLKDEV;
1342 #endif
1343 #ifdef S_ISFIFO
1344 else if(S_ISFIFO(mode))
1345 return UNIX_TYPE_FIFO;
1346 #endif
1347 #ifdef S_ISSOCK
1348 else if(S_ISSOCK(mode))
1349 return UNIX_TYPE_SOCKET;
1350 #endif
1352 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1353 return UNIX_TYPE_UNKNOWN;
1356 /****************************************************************************
1357 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1358 ****************************************************************************/
1360 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1362 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1363 const SMB_STRUCT_STAT *psbuf,
1364 uint32_t perms,
1365 enum perm_type ptype,
1366 mode_t *ret_perms)
1368 mode_t ret = 0;
1370 if (perms == SMB_MODE_NO_CHANGE) {
1371 if (!VALID_STAT(*psbuf)) {
1372 return NT_STATUS_INVALID_PARAMETER;
1373 } else {
1374 *ret_perms = psbuf->st_ex_mode;
1375 return NT_STATUS_OK;
1379 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1380 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1381 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1382 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1383 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1384 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1385 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1386 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1387 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1388 #ifdef S_ISVTX
1389 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1390 #endif
1391 #ifdef S_ISGID
1392 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1393 #endif
1394 #ifdef S_ISUID
1395 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1396 #endif
1398 if (ptype == PERM_NEW_FILE) {
1400 * "create mask"/"force create mode" are
1401 * only applied to new files, not existing ones.
1403 ret &= lp_create_mask(SNUM(conn));
1404 /* Add in force bits */
1405 ret |= lp_force_create_mode(SNUM(conn));
1406 } else if (ptype == PERM_NEW_DIR) {
1408 * "directory mask"/"force directory mode" are
1409 * only applied to new directories, not existing ones.
1411 ret &= lp_directory_mask(SNUM(conn));
1412 /* Add in force bits */
1413 ret |= lp_force_directory_mode(SNUM(conn));
1416 *ret_perms = ret;
1417 return NT_STATUS_OK;
1420 /****************************************************************************
1421 Needed to show the msdfs symlinks as directories. Modifies psbuf
1422 to be a directory if it's a msdfs link.
1423 ****************************************************************************/
1425 static bool check_msdfs_link(connection_struct *conn,
1426 const char *pathname,
1427 SMB_STRUCT_STAT *psbuf)
1429 int saved_errno = errno;
1430 if(lp_host_msdfs() &&
1431 lp_msdfs_root(SNUM(conn)) &&
1432 is_msdfs_link(conn, pathname, psbuf)) {
1434 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1435 "as a directory\n",
1436 pathname));
1437 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1438 errno = saved_errno;
1439 return true;
1441 errno = saved_errno;
1442 return false;
1446 /****************************************************************************
1447 Get a level dependent lanman2 dir entry.
1448 ****************************************************************************/
1450 struct smbd_dirptr_lanman2_state {
1451 connection_struct *conn;
1452 uint32_t info_level;
1453 bool check_mangled_names;
1454 bool has_wild;
1455 bool got_exact_match;
1458 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1459 void *private_data,
1460 const char *dname,
1461 const char *mask,
1462 char **_fname)
1464 struct smbd_dirptr_lanman2_state *state =
1465 (struct smbd_dirptr_lanman2_state *)private_data;
1466 bool ok;
1467 char mangled_name[13]; /* mangled 8.3 name. */
1468 bool got_match;
1469 const char *fname;
1471 /* Mangle fname if it's an illegal name. */
1472 if (mangle_must_mangle(dname, state->conn->params)) {
1474 * Slow path - ensure we can push the original name as UCS2. If
1475 * not, then just don't return this name.
1477 NTSTATUS status;
1478 size_t ret_len = 0;
1479 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1480 uint8_t *tmp = talloc_array(talloc_tos(),
1481 uint8_t,
1482 len);
1484 status = srvstr_push(NULL,
1485 FLAGS2_UNICODE_STRINGS,
1486 tmp,
1487 dname,
1488 len,
1489 STR_TERMINATE,
1490 &ret_len);
1492 TALLOC_FREE(tmp);
1494 if (!NT_STATUS_IS_OK(status)) {
1495 return false;
1498 ok = name_to_8_3(dname, mangled_name,
1499 true, state->conn->params);
1500 if (!ok) {
1501 return false;
1503 fname = mangled_name;
1504 } else {
1505 fname = dname;
1508 got_match = exact_match(state->has_wild,
1509 state->conn->case_sensitive,
1510 fname, mask);
1511 state->got_exact_match = got_match;
1512 if (!got_match) {
1513 got_match = mask_match(fname, mask,
1514 state->conn->case_sensitive);
1517 if(!got_match && state->check_mangled_names &&
1518 !mangle_is_8_3(fname, false, state->conn->params)) {
1520 * It turns out that NT matches wildcards against
1521 * both long *and* short names. This may explain some
1522 * of the wildcard wierdness from old DOS clients
1523 * that some people have been seeing.... JRA.
1525 /* Force the mangling into 8.3. */
1526 ok = name_to_8_3(fname, mangled_name,
1527 false, state->conn->params);
1528 if (!ok) {
1529 return false;
1532 got_match = exact_match(state->has_wild,
1533 state->conn->case_sensitive,
1534 mangled_name, mask);
1535 state->got_exact_match = got_match;
1536 if (!got_match) {
1537 got_match = mask_match(mangled_name, mask,
1538 state->conn->case_sensitive);
1542 if (!got_match) {
1543 return false;
1546 *_fname = talloc_strdup(ctx, fname);
1547 if (*_fname == NULL) {
1548 return false;
1551 return true;
1554 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1555 void *private_data,
1556 struct smb_filename *smb_fname,
1557 uint32_t *_mode)
1559 struct smbd_dirptr_lanman2_state *state =
1560 (struct smbd_dirptr_lanman2_state *)private_data;
1561 bool ms_dfs_link = false;
1562 uint32_t mode = 0;
1564 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1565 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1566 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1567 "Couldn't lstat [%s] (%s)\n",
1568 smb_fname_str_dbg(smb_fname),
1569 strerror(errno)));
1570 return false;
1572 } else if (!VALID_STAT(smb_fname->st) &&
1573 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1574 /* Needed to show the msdfs symlinks as
1575 * directories */
1577 ms_dfs_link = check_msdfs_link(state->conn,
1578 smb_fname->base_name,
1579 &smb_fname->st);
1580 if (!ms_dfs_link) {
1581 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1582 "Couldn't stat [%s] (%s)\n",
1583 smb_fname_str_dbg(smb_fname),
1584 strerror(errno)));
1585 return false;
1589 if (ms_dfs_link) {
1590 mode = dos_mode_msdfs(state->conn, smb_fname);
1591 } else {
1592 mode = dos_mode(state->conn, smb_fname);
1595 *_mode = mode;
1596 return true;
1599 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1600 connection_struct *conn,
1601 uint16_t flags2,
1602 uint32_t info_level,
1603 struct ea_list *name_list,
1604 bool check_mangled_names,
1605 bool requires_resume_key,
1606 uint32_t mode,
1607 const char *fname,
1608 const struct smb_filename *smb_fname,
1609 int space_remaining,
1610 uint8_t align,
1611 bool do_pad,
1612 char *base_data,
1613 char **ppdata,
1614 char *end_data,
1615 uint64_t *last_entry_off)
1617 char *p, *q, *pdata = *ppdata;
1618 uint32_t reskey=0;
1619 uint64_t file_size = 0;
1620 uint64_t allocation_size = 0;
1621 uint64_t file_index = 0;
1622 size_t len = 0;
1623 struct timespec mdate_ts = {0};
1624 struct timespec adate_ts = {0};
1625 struct timespec cdate_ts = {0};
1626 struct timespec create_date_ts = {0};
1627 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1628 char *nameptr;
1629 char *last_entry_ptr;
1630 bool was_8_3;
1631 int off;
1632 int pad = 0;
1633 NTSTATUS status;
1634 struct readdir_attr_data *readdir_attr_data = NULL;
1636 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1637 file_size = get_file_size_stat(&smb_fname->st);
1639 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1641 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1644 return status;
1648 file_index = get_FileIndex(conn, &smb_fname->st);
1650 mdate_ts = smb_fname->st.st_ex_mtime;
1651 adate_ts = smb_fname->st.st_ex_atime;
1652 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1653 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1655 if (lp_dos_filetime_resolution(SNUM(conn))) {
1656 dos_filetime_timespec(&create_date_ts);
1657 dos_filetime_timespec(&mdate_ts);
1658 dos_filetime_timespec(&adate_ts);
1659 dos_filetime_timespec(&cdate_ts);
1662 create_date = convert_timespec_to_time_t(create_date_ts);
1663 mdate = convert_timespec_to_time_t(mdate_ts);
1664 adate = convert_timespec_to_time_t(adate_ts);
1666 /* align the record */
1667 SMB_ASSERT(align >= 1);
1669 off = (int)PTR_DIFF(pdata, base_data);
1670 pad = (off + (align-1)) & ~(align-1);
1671 pad -= off;
1673 if (pad && pad > space_remaining) {
1674 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1675 "for padding (wanted %u, had %d)\n",
1676 (unsigned int)pad,
1677 space_remaining ));
1678 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1681 off += pad;
1682 /* initialize padding to 0 */
1683 if (pad) {
1684 memset(pdata, 0, pad);
1686 space_remaining -= pad;
1688 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1689 space_remaining ));
1691 pdata += pad;
1692 p = pdata;
1693 last_entry_ptr = p;
1695 pad = 0;
1696 off = 0;
1698 switch (info_level) {
1699 case SMB_FIND_INFO_STANDARD:
1700 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1701 if(requires_resume_key) {
1702 SIVAL(p,0,reskey);
1703 p += 4;
1705 srv_put_dos_date2(p,0,create_date);
1706 srv_put_dos_date2(p,4,adate);
1707 srv_put_dos_date2(p,8,mdate);
1708 SIVAL(p,12,(uint32_t)file_size);
1709 SIVAL(p,16,(uint32_t)allocation_size);
1710 SSVAL(p,20,mode);
1711 p += 23;
1712 nameptr = p;
1713 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1714 p += ucs2_align(base_data, p, 0);
1716 status = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE, &len);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 return status;
1722 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1723 if (len > 2) {
1724 SCVAL(nameptr, -1, len - 2);
1725 } else {
1726 SCVAL(nameptr, -1, 0);
1728 } else {
1729 if (len > 1) {
1730 SCVAL(nameptr, -1, len - 1);
1731 } else {
1732 SCVAL(nameptr, -1, 0);
1735 p += len;
1736 break;
1738 case SMB_FIND_EA_SIZE:
1739 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1740 if (requires_resume_key) {
1741 SIVAL(p,0,reskey);
1742 p += 4;
1744 srv_put_dos_date2(p,0,create_date);
1745 srv_put_dos_date2(p,4,adate);
1746 srv_put_dos_date2(p,8,mdate);
1747 SIVAL(p,12,(uint32_t)file_size);
1748 SIVAL(p,16,(uint32_t)allocation_size);
1749 SSVAL(p,20,mode);
1751 unsigned int ea_size = estimate_ea_size(conn, NULL,
1752 smb_fname);
1753 SIVAL(p,22,ea_size); /* Extended attributes */
1755 p += 27;
1756 nameptr = p - 1;
1757 status = srvstr_push(base_data, flags2,
1758 p, fname, PTR_DIFF(end_data, p),
1759 STR_TERMINATE | STR_NOALIGN, &len);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 return status;
1763 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1764 if (len > 2) {
1765 len -= 2;
1766 } else {
1767 len = 0;
1769 } else {
1770 if (len > 1) {
1771 len -= 1;
1772 } else {
1773 len = 0;
1776 SCVAL(nameptr,0,len);
1777 p += len;
1778 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1779 break;
1781 case SMB_FIND_EA_LIST:
1783 struct ea_list *file_list = NULL;
1784 size_t ea_len = 0;
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1787 if (!name_list) {
1788 return NT_STATUS_INVALID_PARAMETER;
1790 if (requires_resume_key) {
1791 SIVAL(p,0,reskey);
1792 p += 4;
1794 srv_put_dos_date2(p,0,create_date);
1795 srv_put_dos_date2(p,4,adate);
1796 srv_put_dos_date2(p,8,mdate);
1797 SIVAL(p,12,(uint32_t)file_size);
1798 SIVAL(p,16,(uint32_t)allocation_size);
1799 SSVAL(p,20,mode);
1800 p += 22; /* p now points to the EA area. */
1802 status = get_ea_list_from_file(ctx, conn, NULL,
1803 smb_fname,
1804 &ea_len, &file_list);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 file_list = NULL;
1808 name_list = ea_list_union(name_list, file_list, &ea_len);
1810 /* We need to determine if this entry will fit in the space available. */
1811 /* Max string size is 255 bytes. */
1812 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1813 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1814 "(wanted %u, had %d)\n",
1815 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1816 space_remaining ));
1817 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1820 /* Push the ea_data followed by the name. */
1821 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1822 nameptr = p;
1823 status = srvstr_push(base_data, flags2,
1824 p + 1, fname, PTR_DIFF(end_data, p+1),
1825 STR_TERMINATE | STR_NOALIGN, &len);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 return status;
1829 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1830 if (len > 2) {
1831 len -= 2;
1832 } else {
1833 len = 0;
1835 } else {
1836 if (len > 1) {
1837 len -= 1;
1838 } else {
1839 len = 0;
1842 SCVAL(nameptr,0,len);
1843 p += len + 1;
1844 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1845 break;
1848 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1850 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1851 p += 4;
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1854 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,mode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1861 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1862 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1863 } else {
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1868 p += 4;
1869 /* Clear the short name buffer. This is
1870 * IMPORTANT as not doing so will trigger
1871 * a Win2k client bug. JRA.
1873 if (!was_8_3 && check_mangled_names) {
1874 char mangled_name[13]; /* mangled 8.3 name. */
1875 if (!name_to_8_3(fname,mangled_name,True,
1876 conn->params)) {
1877 /* Error - mangle failed ! */
1878 memset(mangled_name,'\0',12);
1880 mangled_name[12] = 0;
1881 status = srvstr_push(base_data, flags2,
1882 p+2, mangled_name, 24,
1883 STR_UPPER|STR_UNICODE, &len);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 return status;
1887 if (len < 24) {
1888 memset(p + 2 + len,'\0',24 - len);
1890 SSVAL(p, 0, len);
1891 } else {
1892 memset(p,'\0',26);
1894 p += 2 + 24;
1895 status = srvstr_push(base_data, flags2, p,
1896 fname, PTR_DIFF(end_data, p),
1897 STR_TERMINATE_ASCII, &len);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 return status;
1901 SIVAL(q,0,len);
1902 p += len;
1904 len = PTR_DIFF(p, pdata);
1905 pad = (len + (align-1)) & ~(align-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1911 SIVAL(pdata,0,pad);
1913 * set padding to zero
1915 if (do_pad) {
1916 memset(p, 0, pad - len);
1917 p = pdata + pad;
1918 } else {
1919 p = pdata + len;
1921 break;
1923 case SMB_FIND_FILE_DIRECTORY_INFO:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1925 p += 4;
1926 SIVAL(p,0,reskey); p += 4;
1927 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1930 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1931 SOFF_T(p,0,file_size); p += 8;
1932 SOFF_T(p,0,allocation_size); p += 8;
1933 SIVAL(p,0,mode); p += 4;
1934 status = srvstr_push(base_data, flags2,
1935 p + 4, fname, PTR_DIFF(end_data, p+4),
1936 STR_TERMINATE_ASCII, &len);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 return status;
1940 SIVAL(p,0,len);
1941 p += 4 + len;
1943 len = PTR_DIFF(p, pdata);
1944 pad = (len + (align-1)) & ~(align-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1950 SIVAL(pdata,0,pad);
1952 * set padding to zero
1954 if (do_pad) {
1955 memset(p, 0, pad - len);
1956 p = pdata + pad;
1957 } else {
1958 p = pdata + len;
1960 break;
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1964 p += 4;
1965 SIVAL(p,0,reskey); p += 4;
1966 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1967 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1968 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1969 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1970 SOFF_T(p,0,file_size); p += 8;
1971 SOFF_T(p,0,allocation_size); p += 8;
1972 SIVAL(p,0,mode); p += 4;
1973 q = p; p += 4; /* q is placeholder for name length. */
1975 unsigned int ea_size = estimate_ea_size(conn, NULL,
1976 smb_fname);
1977 SIVAL(p,0,ea_size); /* Extended attributes */
1978 p +=4;
1980 status = srvstr_push(base_data, flags2, p,
1981 fname, PTR_DIFF(end_data, p),
1982 STR_TERMINATE_ASCII, &len);
1983 if (!NT_STATUS_IS_OK(status)) {
1984 return status;
1986 SIVAL(q, 0, len);
1987 p += len;
1989 len = PTR_DIFF(p, pdata);
1990 pad = (len + (align-1)) & ~(align-1);
1992 * offset to the next entry, the caller
1993 * will overwrite it for the last entry
1994 * that's why we always include the padding
1996 SIVAL(pdata,0,pad);
1998 * set padding to zero
2000 if (do_pad) {
2001 memset(p, 0, pad - len);
2002 p = pdata + pad;
2003 } else {
2004 p = pdata + len;
2006 break;
2008 case SMB_FIND_FILE_NAMES_INFO:
2009 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2010 p += 4;
2011 SIVAL(p,0,reskey); p += 4;
2012 p += 4;
2013 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2014 acl on a dir (tridge) */
2015 status = srvstr_push(base_data, flags2, p,
2016 fname, PTR_DIFF(end_data, p),
2017 STR_TERMINATE_ASCII, &len);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 return status;
2021 SIVAL(p, -4, len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2044 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2045 p += 4;
2046 SIVAL(p,0,reskey); p += 4;
2047 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2049 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2051 SOFF_T(p,0,file_size); p += 8;
2052 SOFF_T(p,0,allocation_size); p += 8;
2053 SIVAL(p,0,mode); p += 4;
2054 q = p; p += 4; /* q is placeholder for name length. */
2055 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2056 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2057 } else {
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2059 smb_fname);
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2062 p += 4;
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 status = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII, &len);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 return status;
2071 SIVAL(q, 0, len);
2072 p += len;
2074 len = PTR_DIFF(p, pdata);
2075 pad = (len + (align-1)) & ~(align-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2081 SIVAL(pdata,0,pad);
2083 * set padding to zero
2085 if (do_pad) {
2086 memset(p, 0, pad - len);
2087 p = pdata + pad;
2088 } else {
2089 p = pdata + len;
2091 break;
2093 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2095 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2096 p += 4;
2097 SIVAL(p,0,reskey); p += 4;
2098 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2099 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2100 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2101 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2102 SOFF_T(p,0,file_size); p += 8;
2103 SOFF_T(p,0,allocation_size); p += 8;
2104 SIVAL(p,0,mode); p += 4;
2105 q = p; p += 4; /* q is placeholder for name length */
2106 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2107 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2108 } else if (readdir_attr_data &&
2109 readdir_attr_data->type == RDATTR_AAPL) {
2111 * OS X specific SMB2 extension negotiated via
2112 * AAPL create context: return max_access in
2113 * ea_size field.
2115 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2116 } else {
2117 unsigned int ea_size = estimate_ea_size(conn, NULL,
2118 smb_fname);
2119 SIVAL(p,0,ea_size); /* Extended attributes */
2121 p += 4;
2123 if (readdir_attr_data &&
2124 readdir_attr_data->type == RDATTR_AAPL) {
2126 * OS X specific SMB2 extension negotiated via
2127 * AAPL create context: return resource fork
2128 * length and compressed FinderInfo in
2129 * shortname field.
2131 * According to documentation short_name_len
2132 * should be 0, but on the wire behaviour
2133 * shows its set to 24 by clients.
2135 SSVAL(p, 0, 24);
2137 /* Resourefork length */
2138 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2140 /* Compressed FinderInfo */
2141 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2142 } else if (!was_8_3 && check_mangled_names) {
2143 char mangled_name[13]; /* mangled 8.3 name. */
2144 if (!name_to_8_3(fname,mangled_name,True,
2145 conn->params)) {
2146 /* Error - mangle failed ! */
2147 memset(mangled_name,'\0',12);
2149 mangled_name[12] = 0;
2150 status = srvstr_push(base_data, flags2,
2151 p+2, mangled_name, 24,
2152 STR_UPPER|STR_UNICODE, &len);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 return status;
2156 SSVAL(p, 0, len);
2157 if (len < 24) {
2158 memset(p + 2 + len,'\0',24 - len);
2160 SSVAL(p, 0, len);
2161 } else {
2162 /* Clear the short name buffer. This is
2163 * IMPORTANT as not doing so will trigger
2164 * a Win2k client bug. JRA.
2166 memset(p,'\0',26);
2168 p += 26;
2170 /* Reserved ? */
2171 if (readdir_attr_data &&
2172 readdir_attr_data->type == RDATTR_AAPL) {
2174 * OS X specific SMB2 extension negotiated via
2175 * AAPL create context: return UNIX mode in
2176 * reserved field.
2178 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2179 SSVAL(p, 0, aapl_mode);
2180 } else {
2181 SSVAL(p, 0, 0);
2183 p += 2;
2185 SBVAL(p,0,file_index); p += 8;
2186 status = srvstr_push(base_data, flags2, p,
2187 fname, PTR_DIFF(end_data, p),
2188 STR_TERMINATE_ASCII, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return status;
2192 SIVAL(q,0,len);
2193 p += len;
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2202 SIVAL(pdata,0,pad);
2204 * set padding to zero
2206 if (do_pad) {
2207 memset(p, 0, pad - len);
2208 p = pdata + pad;
2209 } else {
2210 p = pdata + len;
2212 break;
2214 /* CIFS UNIX Extension. */
2216 case SMB_FIND_FILE_UNIX:
2217 case SMB_FIND_FILE_UNIX_INFO2:
2218 p+= 4;
2219 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2221 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (info_level == SMB_FIND_FILE_UNIX) {
2224 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2225 p = store_file_unix_basic(conn, p,
2226 NULL, &smb_fname->st);
2227 status = srvstr_push(base_data, flags2, p,
2228 fname, PTR_DIFF(end_data, p),
2229 STR_TERMINATE, &len);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 return status;
2233 } else {
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2235 p = store_file_unix_basic_info2(conn, p,
2236 NULL, &smb_fname->st);
2237 nameptr = p;
2238 p += 4;
2239 status = srvstr_push(base_data, flags2, p, fname,
2240 PTR_DIFF(end_data, p), 0, &len);
2241 if (!NT_STATUS_IS_OK(status)) {
2242 return status;
2244 SIVAL(nameptr, 0, len);
2247 p += len;
2249 len = PTR_DIFF(p, pdata);
2250 pad = (len + (align-1)) & ~(align-1);
2252 * offset to the next entry, the caller
2253 * will overwrite it for the last entry
2254 * that's why we always include the padding
2256 SIVAL(pdata,0,pad);
2258 * set padding to zero
2260 if (do_pad) {
2261 memset(p, 0, pad - len);
2262 p = pdata + pad;
2263 } else {
2264 p = pdata + len;
2266 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2268 break;
2270 default:
2271 return NT_STATUS_INVALID_LEVEL;
2274 if (PTR_DIFF(p,pdata) > space_remaining) {
2275 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2276 "(wanted %u, had %d)\n",
2277 (unsigned int)PTR_DIFF(p,pdata),
2278 space_remaining ));
2279 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2282 /* Setup the last entry pointer, as an offset from base_data */
2283 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2284 /* Advance the data pointer to the next slot */
2285 *ppdata = p;
2287 return NT_STATUS_OK;
2290 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2291 connection_struct *conn,
2292 struct dptr_struct *dirptr,
2293 uint16_t flags2,
2294 const char *path_mask,
2295 uint32_t dirtype,
2296 int info_level,
2297 int requires_resume_key,
2298 bool dont_descend,
2299 bool ask_sharemode,
2300 uint8_t align,
2301 bool do_pad,
2302 char **ppdata,
2303 char *base_data,
2304 char *end_data,
2305 int space_remaining,
2306 bool *got_exact_match,
2307 int *_last_entry_off,
2308 struct ea_list *name_list)
2310 const char *p;
2311 const char *mask = NULL;
2312 long prev_dirpos = 0;
2313 uint32_t mode = 0;
2314 char *fname = NULL;
2315 struct smb_filename *smb_fname = NULL;
2316 struct smbd_dirptr_lanman2_state state;
2317 bool ok;
2318 uint64_t last_entry_off = 0;
2319 NTSTATUS status;
2321 ZERO_STRUCT(state);
2322 state.conn = conn;
2323 state.info_level = info_level;
2324 state.check_mangled_names = lp_mangled_names(conn->params);
2325 state.has_wild = dptr_has_wild(dirptr);
2326 state.got_exact_match = false;
2328 *got_exact_match = false;
2330 p = strrchr_m(path_mask,'/');
2331 if(p != NULL) {
2332 if(p[1] == '\0') {
2333 mask = "*.*";
2334 } else {
2335 mask = p+1;
2337 } else {
2338 mask = path_mask;
2341 ok = smbd_dirptr_get_entry(ctx,
2342 dirptr,
2343 mask,
2344 dirtype,
2345 dont_descend,
2346 ask_sharemode,
2347 smbd_dirptr_lanman2_match_fn,
2348 smbd_dirptr_lanman2_mode_fn,
2349 &state,
2350 &fname,
2351 &smb_fname,
2352 &mode,
2353 &prev_dirpos);
2354 if (!ok) {
2355 return NT_STATUS_END_OF_FILE;
2358 *got_exact_match = state.got_exact_match;
2360 status = smbd_marshall_dir_entry(ctx,
2361 conn,
2362 flags2,
2363 info_level,
2364 name_list,
2365 state.check_mangled_names,
2366 requires_resume_key,
2367 mode,
2368 fname,
2369 smb_fname,
2370 space_remaining,
2371 align,
2372 do_pad,
2373 base_data,
2374 ppdata,
2375 end_data,
2376 &last_entry_off);
2377 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2378 DEBUG(1,("Conversion error: illegal character: %s\n",
2379 smb_fname_str_dbg(smb_fname)));
2381 TALLOC_FREE(fname);
2382 TALLOC_FREE(smb_fname);
2383 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2384 dptr_SeekDir(dirptr, prev_dirpos);
2385 return status;
2387 if (!NT_STATUS_IS_OK(status)) {
2388 return status;
2391 *_last_entry_off = last_entry_off;
2392 return NT_STATUS_OK;
2395 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2396 connection_struct *conn,
2397 struct dptr_struct *dirptr,
2398 uint16_t flags2,
2399 const char *path_mask,
2400 uint32_t dirtype,
2401 int info_level,
2402 bool requires_resume_key,
2403 bool dont_descend,
2404 bool ask_sharemode,
2405 char **ppdata,
2406 char *base_data,
2407 char *end_data,
2408 int space_remaining,
2409 bool *got_exact_match,
2410 int *last_entry_off,
2411 struct ea_list *name_list)
2413 uint8_t align = 4;
2414 const bool do_pad = true;
2416 if (info_level >= 1 && info_level <= 3) {
2417 /* No alignment on earlier info levels. */
2418 align = 1;
2421 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2422 path_mask, dirtype, info_level,
2423 requires_resume_key, dont_descend, ask_sharemode,
2424 align, do_pad,
2425 ppdata, base_data, end_data,
2426 space_remaining,
2427 got_exact_match,
2428 last_entry_off, name_list);
2431 /****************************************************************************
2432 Reply to a TRANS2_FINDFIRST.
2433 ****************************************************************************/
2435 static void call_trans2findfirst(connection_struct *conn,
2436 struct smb_request *req,
2437 char **pparams, int total_params,
2438 char **ppdata, int total_data,
2439 unsigned int max_data_bytes)
2441 /* We must be careful here that we don't return more than the
2442 allowed number of data bytes. If this means returning fewer than
2443 maxentries then so be it. We assume that the redirector has
2444 enough room for the fixed number of parameter bytes it has
2445 requested. */
2446 struct smb_filename *smb_dname = NULL;
2447 char *params = *pparams;
2448 char *pdata = *ppdata;
2449 char *data_end;
2450 uint32_t dirtype;
2451 int maxentries;
2452 uint16_t findfirst_flags;
2453 bool close_after_first;
2454 bool close_if_end;
2455 bool requires_resume_key;
2456 int info_level;
2457 char *directory = NULL;
2458 char *mask = NULL;
2459 char *p;
2460 int last_entry_off=0;
2461 int dptr_num = -1;
2462 int numentries = 0;
2463 int i;
2464 bool finished = False;
2465 bool dont_descend = False;
2466 bool out_of_space = False;
2467 int space_remaining;
2468 bool mask_contains_wcard = False;
2469 struct ea_list *ea_list = NULL;
2470 NTSTATUS ntstatus = NT_STATUS_OK;
2471 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2472 TALLOC_CTX *ctx = talloc_tos();
2473 struct dptr_struct *dirptr = NULL;
2474 struct smbd_server_connection *sconn = req->sconn;
2475 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2476 bool backup_priv = false;
2477 bool as_root = false;
2479 if (total_params < 13) {
2480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2481 goto out;
2484 dirtype = SVAL(params,0);
2485 maxentries = SVAL(params,2);
2486 findfirst_flags = SVAL(params,4);
2487 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2488 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2489 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2490 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2491 security_token_has_privilege(get_current_nttok(conn),
2492 SEC_PRIV_BACKUP));
2494 info_level = SVAL(params,6);
2496 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2497 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2498 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2499 (int)backup_priv,
2500 info_level, max_data_bytes));
2502 if (!maxentries) {
2503 /* W2K3 seems to treat zero as 1. */
2504 maxentries = 1;
2507 switch (info_level) {
2508 case SMB_FIND_INFO_STANDARD:
2509 case SMB_FIND_EA_SIZE:
2510 case SMB_FIND_EA_LIST:
2511 case SMB_FIND_FILE_DIRECTORY_INFO:
2512 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2513 case SMB_FIND_FILE_NAMES_INFO:
2514 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2515 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2516 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2517 break;
2518 case SMB_FIND_FILE_UNIX:
2519 case SMB_FIND_FILE_UNIX_INFO2:
2520 /* Always use filesystem for UNIX mtime query. */
2521 ask_sharemode = false;
2522 if (!lp_unix_extensions()) {
2523 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2524 goto out;
2526 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2527 break;
2528 default:
2529 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2530 goto out;
2533 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2534 params+12, total_params - 12,
2535 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2536 if (!NT_STATUS_IS_OK(ntstatus)) {
2537 reply_nterror(req, ntstatus);
2538 goto out;
2541 if (backup_priv) {
2542 become_root();
2543 as_root = true;
2544 ntstatus = filename_convert_with_privilege(ctx,
2545 conn,
2546 req,
2547 directory,
2548 ucf_flags,
2549 &mask_contains_wcard,
2550 &smb_dname);
2551 } else {
2552 ntstatus = filename_convert(ctx, conn,
2553 req->flags2 & FLAGS2_DFS_PATHNAMES,
2554 directory,
2555 ucf_flags,
2556 &mask_contains_wcard,
2557 &smb_dname);
2560 if (!NT_STATUS_IS_OK(ntstatus)) {
2561 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2562 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2563 ERRSRV, ERRbadpath);
2564 goto out;
2566 reply_nterror(req, ntstatus);
2567 goto out;
2570 mask = smb_dname->original_lcomp;
2572 directory = smb_dname->base_name;
2574 p = strrchr_m(directory,'/');
2575 if(p == NULL) {
2576 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2577 if((directory[0] == '.') && (directory[1] == '\0')) {
2578 mask = talloc_strdup(ctx,"*");
2579 if (!mask) {
2580 reply_nterror(req, NT_STATUS_NO_MEMORY);
2581 goto out;
2583 mask_contains_wcard = True;
2585 } else {
2586 *p = 0;
2589 if (p == NULL || p == directory) {
2590 /* Ensure we don't have a directory name of "". */
2591 directory = talloc_strdup(talloc_tos(), ".");
2592 if (!directory) {
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2594 goto out;
2598 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2600 if (info_level == SMB_FIND_EA_LIST) {
2601 uint32_t ea_size;
2603 if (total_data < 4) {
2604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2605 goto out;
2608 ea_size = IVAL(pdata,0);
2609 if (ea_size != total_data) {
2610 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2611 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2613 goto out;
2616 if (!lp_ea_support(SNUM(conn))) {
2617 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2618 goto out;
2621 /* Pull out the list of names. */
2622 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2623 if (!ea_list) {
2624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 goto out;
2629 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2631 goto out;
2634 *ppdata = (char *)SMB_REALLOC(
2635 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2636 if(*ppdata == NULL ) {
2637 reply_nterror(req, NT_STATUS_NO_MEMORY);
2638 goto out;
2640 pdata = *ppdata;
2641 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2643 /* Realloc the params space */
2644 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2645 if (*pparams == NULL) {
2646 reply_nterror(req, NT_STATUS_NO_MEMORY);
2647 goto out;
2649 params = *pparams;
2651 /* Save the wildcard match and attribs we are using on this directory -
2652 needed as lanman2 assumes these are being saved between calls */
2654 ntstatus = dptr_create(conn,
2655 req,
2656 NULL, /* fsp */
2657 directory,
2658 False,
2659 True,
2660 req->smbpid,
2661 mask,
2662 mask_contains_wcard,
2663 dirtype,
2664 &dirptr);
2666 if (!NT_STATUS_IS_OK(ntstatus)) {
2667 reply_nterror(req, ntstatus);
2668 goto out;
2671 if (backup_priv) {
2672 /* Remember this in case we have
2673 to do a findnext. */
2674 dptr_set_priv(dirptr);
2677 dptr_num = dptr_dnum(dirptr);
2678 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2680 /* Initialize per TRANS2_FIND_FIRST operation data */
2681 dptr_init_search_op(dirptr);
2683 /* We don't need to check for VOL here as this is returned by
2684 a different TRANS2 call. */
2686 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2687 directory,lp_dont_descend(ctx, SNUM(conn))));
2688 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2689 dont_descend = True;
2691 p = pdata;
2692 space_remaining = max_data_bytes;
2693 out_of_space = False;
2695 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2696 bool got_exact_match = False;
2698 /* this is a heuristic to avoid seeking the dirptr except when
2699 absolutely necessary. It allows for a filename of about 40 chars */
2700 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2701 out_of_space = True;
2702 finished = False;
2703 } else {
2704 ntstatus = get_lanman2_dir_entry(ctx,
2705 conn,
2706 dirptr,
2707 req->flags2,
2708 mask,dirtype,info_level,
2709 requires_resume_key,dont_descend,
2710 ask_sharemode,
2711 &p,pdata,data_end,
2712 space_remaining,
2713 &got_exact_match,
2714 &last_entry_off, ea_list);
2715 if (NT_STATUS_EQUAL(ntstatus,
2716 NT_STATUS_ILLEGAL_CHARACTER)) {
2718 * Bad character conversion on name. Ignore this
2719 * entry.
2721 continue;
2723 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2724 out_of_space = true;
2725 } else {
2726 finished = !NT_STATUS_IS_OK(ntstatus);
2730 if (!finished && !out_of_space)
2731 numentries++;
2734 * As an optimisation if we know we aren't looking
2735 * for a wildcard name (ie. the name matches the wildcard exactly)
2736 * then we can finish on any (first) match.
2737 * This speeds up large directory searches. JRA.
2740 if(got_exact_match)
2741 finished = True;
2743 /* Ensure space_remaining never goes -ve. */
2744 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2745 space_remaining = 0;
2746 out_of_space = true;
2747 } else {
2748 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2752 /* Check if we can close the dirptr */
2753 if(close_after_first || (finished && close_if_end)) {
2754 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2755 dptr_close(sconn, &dptr_num);
2759 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2760 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2761 * the protocol level is less than NT1. Tested with smbclient. JRA.
2762 * This should fix the OS/2 client bug #2335.
2765 if(numentries == 0) {
2766 dptr_close(sconn, &dptr_num);
2767 if (get_Protocol() < PROTOCOL_NT1) {
2768 reply_force_doserror(req, ERRDOS, ERRnofiles);
2769 goto out;
2770 } else {
2771 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2772 ERRDOS, ERRbadfile);
2773 goto out;
2777 /* At this point pdata points to numentries directory entries. */
2779 /* Set up the return parameter block */
2780 SSVAL(params,0,dptr_num);
2781 SSVAL(params,2,numentries);
2782 SSVAL(params,4,finished);
2783 SSVAL(params,6,0); /* Never an EA error */
2784 SSVAL(params,8,last_entry_off);
2786 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2787 max_data_bytes);
2789 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2790 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2791 if (!directory) {
2792 reply_nterror(req, NT_STATUS_NO_MEMORY);
2796 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2797 smb_fn_name(req->cmd),
2798 mask, directory, dirtype, numentries ) );
2801 * Force a name mangle here to ensure that the
2802 * mask as an 8.3 name is top of the mangled cache.
2803 * The reasons for this are subtle. Don't remove
2804 * this code unless you know what you are doing
2805 * (see PR#13758). JRA.
2808 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2809 char mangled_name[13];
2810 name_to_8_3(mask, mangled_name, True, conn->params);
2812 out:
2814 if (as_root) {
2815 unbecome_root();
2818 TALLOC_FREE(smb_dname);
2819 return;
2822 /****************************************************************************
2823 Reply to a TRANS2_FINDNEXT.
2824 ****************************************************************************/
2826 static void call_trans2findnext(connection_struct *conn,
2827 struct smb_request *req,
2828 char **pparams, int total_params,
2829 char **ppdata, int total_data,
2830 unsigned int max_data_bytes)
2832 /* We must be careful here that we don't return more than the
2833 allowed number of data bytes. If this means returning fewer than
2834 maxentries then so be it. We assume that the redirector has
2835 enough room for the fixed number of parameter bytes it has
2836 requested. */
2837 char *params = *pparams;
2838 char *pdata = *ppdata;
2839 char *data_end;
2840 int dptr_num;
2841 int maxentries;
2842 uint16_t info_level;
2843 uint32_t resume_key;
2844 uint16_t findnext_flags;
2845 bool close_after_request;
2846 bool close_if_end;
2847 bool requires_resume_key;
2848 bool continue_bit;
2849 bool mask_contains_wcard = False;
2850 char *resume_name = NULL;
2851 const char *mask = NULL;
2852 const char *directory = NULL;
2853 char *p = NULL;
2854 uint16_t dirtype;
2855 int numentries = 0;
2856 int i, last_entry_off=0;
2857 bool finished = False;
2858 bool dont_descend = False;
2859 bool out_of_space = False;
2860 int space_remaining;
2861 struct ea_list *ea_list = NULL;
2862 NTSTATUS ntstatus = NT_STATUS_OK;
2863 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2864 TALLOC_CTX *ctx = talloc_tos();
2865 struct dptr_struct *dirptr;
2866 struct smbd_server_connection *sconn = req->sconn;
2867 bool backup_priv = false;
2868 bool as_root = false;
2870 if (total_params < 13) {
2871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2872 return;
2875 dptr_num = SVAL(params,0);
2876 maxentries = SVAL(params,2);
2877 info_level = SVAL(params,4);
2878 resume_key = IVAL(params,6);
2879 findnext_flags = SVAL(params,10);
2880 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2881 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2882 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2883 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2885 if (!continue_bit) {
2886 /* We only need resume_name if continue_bit is zero. */
2887 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2888 params+12,
2889 total_params - 12, STR_TERMINATE, &ntstatus,
2890 &mask_contains_wcard);
2891 if (!NT_STATUS_IS_OK(ntstatus)) {
2892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2893 complain (it thinks we're asking for the directory above the shared
2894 path or an invalid name). Catch this as the resume name is only compared, never used in
2895 a file access. JRA. */
2896 srvstr_pull_talloc(ctx, params, req->flags2,
2897 &resume_name, params+12,
2898 total_params - 12,
2899 STR_TERMINATE);
2901 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2902 reply_nterror(req, ntstatus);
2903 return;
2908 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2909 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2910 resume_key = %d resume name = %s continue=%d level = %d\n",
2911 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2912 requires_resume_key, resume_key,
2913 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2915 if (!maxentries) {
2916 /* W2K3 seems to treat zero as 1. */
2917 maxentries = 1;
2920 switch (info_level) {
2921 case SMB_FIND_INFO_STANDARD:
2922 case SMB_FIND_EA_SIZE:
2923 case SMB_FIND_EA_LIST:
2924 case SMB_FIND_FILE_DIRECTORY_INFO:
2925 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2926 case SMB_FIND_FILE_NAMES_INFO:
2927 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2929 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2930 break;
2931 case SMB_FIND_FILE_UNIX:
2932 case SMB_FIND_FILE_UNIX_INFO2:
2933 /* Always use filesystem for UNIX mtime query. */
2934 ask_sharemode = false;
2935 if (!lp_unix_extensions()) {
2936 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2937 return;
2939 break;
2940 default:
2941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2942 return;
2945 if (info_level == SMB_FIND_EA_LIST) {
2946 uint32_t ea_size;
2948 if (total_data < 4) {
2949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2950 return;
2953 ea_size = IVAL(pdata,0);
2954 if (ea_size != total_data) {
2955 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2956 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2958 return;
2961 if (!lp_ea_support(SNUM(conn))) {
2962 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2963 return;
2966 /* Pull out the list of names. */
2967 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2968 if (!ea_list) {
2969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2970 return;
2974 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2976 return;
2979 *ppdata = (char *)SMB_REALLOC(
2980 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2981 if(*ppdata == NULL) {
2982 reply_nterror(req, NT_STATUS_NO_MEMORY);
2983 return;
2986 pdata = *ppdata;
2987 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2989 /* Realloc the params space */
2990 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2991 if(*pparams == NULL ) {
2992 reply_nterror(req, NT_STATUS_NO_MEMORY);
2993 return;
2996 params = *pparams;
2998 /* Check that the dptr is valid */
2999 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3000 reply_nterror(req, STATUS_NO_MORE_FILES);
3001 return;
3004 directory = dptr_path(sconn, dptr_num);
3006 /* Get the wildcard mask from the dptr */
3007 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3008 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3009 reply_nterror(req, STATUS_NO_MORE_FILES);
3010 return;
3013 /* Get the attr mask from the dptr */
3014 dirtype = dptr_attr(sconn, dptr_num);
3016 backup_priv = dptr_get_priv(dirptr);
3018 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3019 "backup_priv = %d\n",
3020 dptr_num, mask, dirtype,
3021 (long)dirptr,
3022 dptr_TellDir(dirptr),
3023 (int)backup_priv));
3025 /* Initialize per TRANS2_FIND_NEXT operation data */
3026 dptr_init_search_op(dirptr);
3028 /* We don't need to check for VOL here as this is returned by
3029 a different TRANS2 call. */
3031 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3032 directory,lp_dont_descend(ctx, SNUM(conn))));
3033 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3034 dont_descend = True;
3036 p = pdata;
3037 space_remaining = max_data_bytes;
3038 out_of_space = False;
3040 if (backup_priv) {
3041 become_root();
3042 as_root = true;
3046 * Seek to the correct position. We no longer use the resume key but
3047 * depend on the last file name instead.
3050 if(!continue_bit && resume_name && *resume_name) {
3051 SMB_STRUCT_STAT st;
3053 long current_pos = 0;
3055 * Remember, name_to_8_3 is called by
3056 * get_lanman2_dir_entry(), so the resume name
3057 * could be mangled. Ensure we check the unmangled name.
3060 if (mangle_is_mangled(resume_name, conn->params)) {
3061 char *new_resume_name = NULL;
3062 mangle_lookup_name_from_8_3(ctx,
3063 resume_name,
3064 &new_resume_name,
3065 conn->params);
3066 if (new_resume_name) {
3067 resume_name = new_resume_name;
3072 * Fix for NT redirector problem triggered by resume key indexes
3073 * changing between directory scans. We now return a resume key of 0
3074 * and instead look for the filename to continue from (also given
3075 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3076 * findfirst/findnext (as is usual) then the directory pointer
3077 * should already be at the correct place.
3080 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3081 } /* end if resume_name && !continue_bit */
3083 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3084 bool got_exact_match = False;
3086 /* this is a heuristic to avoid seeking the dirptr except when
3087 absolutely necessary. It allows for a filename of about 40 chars */
3088 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3089 out_of_space = True;
3090 finished = False;
3091 } else {
3092 ntstatus = get_lanman2_dir_entry(ctx,
3093 conn,
3094 dirptr,
3095 req->flags2,
3096 mask,dirtype,info_level,
3097 requires_resume_key,dont_descend,
3098 ask_sharemode,
3099 &p,pdata,data_end,
3100 space_remaining,
3101 &got_exact_match,
3102 &last_entry_off, ea_list);
3103 if (NT_STATUS_EQUAL(ntstatus,
3104 NT_STATUS_ILLEGAL_CHARACTER)) {
3106 * Bad character conversion on name. Ignore this
3107 * entry.
3109 continue;
3111 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3112 out_of_space = true;
3113 } else {
3114 finished = !NT_STATUS_IS_OK(ntstatus);
3118 if (!finished && !out_of_space)
3119 numentries++;
3122 * As an optimisation if we know we aren't looking
3123 * for a wildcard name (ie. the name matches the wildcard exactly)
3124 * then we can finish on any (first) match.
3125 * This speeds up large directory searches. JRA.
3128 if(got_exact_match)
3129 finished = True;
3131 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3134 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3135 smb_fn_name(req->cmd),
3136 mask, directory, dirtype, numentries ) );
3138 /* Check if we can close the dirptr */
3139 if(close_after_request || (finished && close_if_end)) {
3140 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3141 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3144 if (as_root) {
3145 unbecome_root();
3148 /* Set up the return parameter block */
3149 SSVAL(params,0,numentries);
3150 SSVAL(params,2,finished);
3151 SSVAL(params,4,0); /* Never an EA error */
3152 SSVAL(params,6,last_entry_off);
3154 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3155 max_data_bytes);
3157 return;
3160 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3162 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3163 return objid;
3166 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3168 SMB_ASSERT(extended_info != NULL);
3170 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3171 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3172 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3173 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3174 #ifdef SAMBA_VERSION_REVISION
3175 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3176 #endif
3177 extended_info->samba_subversion = 0;
3178 #ifdef SAMBA_VERSION_RC_RELEASE
3179 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3180 #else
3181 #ifdef SAMBA_VERSION_PRE_RELEASE
3182 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3183 #endif
3184 #endif
3185 #ifdef SAMBA_VERSION_VENDOR_PATCH
3186 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3187 #endif
3188 extended_info->samba_gitcommitdate = 0;
3189 #ifdef SAMBA_VERSION_COMMIT_TIME
3190 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3191 #endif
3193 memset(extended_info->samba_version_string, 0,
3194 sizeof(extended_info->samba_version_string));
3196 snprintf (extended_info->samba_version_string,
3197 sizeof(extended_info->samba_version_string),
3198 "%s", samba_version_string());
3201 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3202 connection_struct *conn,
3203 TALLOC_CTX *mem_ctx,
3204 uint16_t info_level,
3205 uint16_t flags2,
3206 unsigned int max_data_bytes,
3207 size_t *fixed_portion,
3208 struct smb_filename *fname,
3209 char **ppdata,
3210 int *ret_data_len)
3212 char *pdata, *end_data;
3213 int data_len = 0;
3214 size_t len = 0;
3215 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3216 int snum = SNUM(conn);
3217 const char *fstype = lp_fstype(SNUM(conn));
3218 const char *filename = NULL;
3219 const uint64_t bytes_per_sector = 512;
3220 uint32_t additional_flags = 0;
3221 struct smb_filename smb_fname;
3222 SMB_STRUCT_STAT st;
3223 NTSTATUS status = NT_STATUS_OK;
3224 uint64_t df_ret;
3226 if (fname == NULL || fname->base_name == NULL) {
3227 filename = ".";
3228 } else {
3229 filename = fname->base_name;
3232 if (IS_IPC(conn)) {
3233 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3234 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3235 "info level (0x%x) on IPC$.\n",
3236 (unsigned int)info_level));
3237 return NT_STATUS_ACCESS_DENIED;
3241 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3243 ZERO_STRUCT(smb_fname);
3244 smb_fname.base_name = discard_const_p(char, filename);
3246 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3247 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3248 return map_nt_error_from_unix(errno);
3251 st = smb_fname.st;
3253 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3254 return NT_STATUS_INVALID_PARAMETER;
3257 *ppdata = (char *)SMB_REALLOC(
3258 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3259 if (*ppdata == NULL) {
3260 return NT_STATUS_NO_MEMORY;
3263 pdata = *ppdata;
3264 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3265 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3267 *fixed_portion = 0;
3269 switch (info_level) {
3270 case SMB_INFO_ALLOCATION:
3272 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3273 data_len = 18;
3274 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3275 &dsize);
3276 if (df_ret == (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno);
3280 block_size = lp_block_size(snum);
3281 if (bsize < block_size) {
3282 uint64_t factor = block_size/bsize;
3283 bsize = block_size;
3284 dsize /= factor;
3285 dfree /= factor;
3287 if (bsize > block_size) {
3288 uint64_t factor = bsize/block_size;
3289 bsize = block_size;
3290 dsize *= factor;
3291 dfree *= factor;
3293 sectors_per_unit = bsize/bytes_per_sector;
3295 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3296 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3297 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3299 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3300 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3301 SIVAL(pdata,l1_cUnit,dsize);
3302 SIVAL(pdata,l1_cUnitAvail,dfree);
3303 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3304 break;
3307 case SMB_INFO_VOLUME:
3308 /* Return volume name */
3310 * Add volume serial number - hash of a combination of
3311 * the called hostname and the service name.
3313 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3315 * Win2k3 and previous mess this up by sending a name length
3316 * one byte short. I believe only older clients (OS/2 Win9x) use
3317 * this call so try fixing this by adding a terminating null to
3318 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3320 status = srvstr_push(
3321 pdata, flags2,
3322 pdata+l2_vol_szVolLabel, vname,
3323 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3324 STR_NOALIGN|STR_TERMINATE, &len);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 return status;
3328 SCVAL(pdata,l2_vol_cch,len);
3329 data_len = l2_vol_szVolLabel + len;
3330 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3331 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3332 (unsigned)len, vname));
3333 break;
3335 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3336 case SMB_FS_ATTRIBUTE_INFORMATION:
3338 additional_flags = 0;
3339 #if defined(HAVE_SYS_QUOTAS)
3340 additional_flags |= FILE_VOLUME_QUOTAS;
3341 #endif
3343 if(lp_nt_acl_support(SNUM(conn))) {
3344 additional_flags |= FILE_PERSISTENT_ACLS;
3347 /* Capabilities are filled in at connection time through STATVFS call */
3348 additional_flags |= conn->fs_capabilities;
3349 additional_flags |= lp_parm_int(conn->params->service,
3350 "share", "fake_fscaps",
3353 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3354 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3355 additional_flags); /* FS ATTRIBUTES */
3357 SIVAL(pdata,4,255); /* Max filename component length */
3358 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3359 and will think we can't do long filenames */
3360 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3361 PTR_DIFF(end_data, pdata+12),
3362 STR_UNICODE, &len);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 return status;
3366 SIVAL(pdata,8,len);
3367 data_len = 12 + len;
3368 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3369 /* the client only requested a portion of the
3370 file system name */
3371 data_len = max_data_bytes;
3372 status = STATUS_BUFFER_OVERFLOW;
3374 *fixed_portion = 16;
3375 break;
3377 case SMB_QUERY_FS_LABEL_INFO:
3378 case SMB_FS_LABEL_INFORMATION:
3379 status = srvstr_push(pdata, flags2, pdata+4, vname,
3380 PTR_DIFF(end_data, pdata+4), 0, &len);
3381 if (!NT_STATUS_IS_OK(status)) {
3382 return status;
3384 data_len = 4 + len;
3385 SIVAL(pdata,0,len);
3386 break;
3388 case SMB_QUERY_FS_VOLUME_INFO:
3389 case SMB_FS_VOLUME_INFORMATION:
3392 * Add volume serial number - hash of a combination of
3393 * the called hostname and the service name.
3395 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3396 (str_checksum(get_local_machine_name())<<16));
3398 /* Max label len is 32 characters. */
3399 status = srvstr_push(pdata, flags2, pdata+18, vname,
3400 PTR_DIFF(end_data, pdata+18),
3401 STR_UNICODE, &len);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 return status;
3405 SIVAL(pdata,12,len);
3406 data_len = 18+len;
3408 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3409 (int)strlen(vname),vname,
3410 lp_servicename(talloc_tos(), snum)));
3411 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3412 /* the client only requested a portion of the
3413 volume label */
3414 data_len = max_data_bytes;
3415 status = STATUS_BUFFER_OVERFLOW;
3417 *fixed_portion = 24;
3418 break;
3420 case SMB_QUERY_FS_SIZE_INFO:
3421 case SMB_FS_SIZE_INFORMATION:
3423 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3424 data_len = 24;
3425 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3426 &dsize);
3427 if (df_ret == (uint64_t)-1) {
3428 return map_nt_error_from_unix(errno);
3430 block_size = lp_block_size(snum);
3431 if (bsize < block_size) {
3432 uint64_t factor = block_size/bsize;
3433 bsize = block_size;
3434 dsize /= factor;
3435 dfree /= factor;
3437 if (bsize > block_size) {
3438 uint64_t factor = bsize/block_size;
3439 bsize = block_size;
3440 dsize *= factor;
3441 dfree *= factor;
3443 sectors_per_unit = bsize/bytes_per_sector;
3444 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3446 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3447 SBIG_UINT(pdata,0,dsize);
3448 SBIG_UINT(pdata,8,dfree);
3449 SIVAL(pdata,16,sectors_per_unit);
3450 SIVAL(pdata,20,bytes_per_sector);
3451 *fixed_portion = 24;
3452 break;
3455 case SMB_FS_FULL_SIZE_INFORMATION:
3457 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3458 data_len = 32;
3459 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3460 &dsize);
3461 if (df_ret == (uint64_t)-1) {
3462 return map_nt_error_from_unix(errno);
3464 block_size = lp_block_size(snum);
3465 if (bsize < block_size) {
3466 uint64_t factor = block_size/bsize;
3467 bsize = block_size;
3468 dsize /= factor;
3469 dfree /= factor;
3471 if (bsize > block_size) {
3472 uint64_t factor = bsize/block_size;
3473 bsize = block_size;
3474 dsize *= factor;
3475 dfree *= factor;
3477 sectors_per_unit = bsize/bytes_per_sector;
3478 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3479 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3480 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3481 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3482 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3483 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3484 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3485 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3486 *fixed_portion = 32;
3487 break;
3490 case SMB_QUERY_FS_DEVICE_INFO:
3491 case SMB_FS_DEVICE_INFORMATION:
3493 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3495 if (!CAN_WRITE(conn)) {
3496 characteristics |= FILE_READ_ONLY_DEVICE;
3498 data_len = 8;
3499 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3500 SIVAL(pdata,4,characteristics);
3501 *fixed_portion = 8;
3502 break;
3505 #ifdef HAVE_SYS_QUOTAS
3506 case SMB_FS_QUOTA_INFORMATION:
3508 * what we have to send --metze:
3510 * Unknown1: 24 NULL bytes
3511 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3512 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3513 * Quota Flags: 2 byte :
3514 * Unknown3: 6 NULL bytes
3516 * 48 bytes total
3518 * details for Quota Flags:
3520 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3521 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3522 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3523 * 0x0001 Enable Quotas: enable quota for this fs
3527 /* we need to fake up a fsp here,
3528 * because its not send in this call
3530 files_struct fsp;
3531 SMB_NTQUOTA_STRUCT quotas;
3533 ZERO_STRUCT(fsp);
3534 ZERO_STRUCT(quotas);
3536 fsp.conn = conn;
3537 fsp.fnum = FNUM_FIELD_INVALID;
3539 /* access check */
3540 if (get_current_uid(conn) != 0) {
3541 DEBUG(0,("get_user_quota: access_denied "
3542 "service [%s] user [%s]\n",
3543 lp_servicename(talloc_tos(), SNUM(conn)),
3544 conn->session_info->unix_info->unix_name));
3545 return NT_STATUS_ACCESS_DENIED;
3548 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3549 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3550 return map_nt_error_from_unix(errno);
3553 data_len = 48;
3555 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3556 lp_servicename(talloc_tos(), SNUM(conn))));
3558 /* Unknown1 24 NULL bytes*/
3559 SBIG_UINT(pdata,0,(uint64_t)0);
3560 SBIG_UINT(pdata,8,(uint64_t)0);
3561 SBIG_UINT(pdata,16,(uint64_t)0);
3563 /* Default Soft Quota 8 bytes */
3564 SBIG_UINT(pdata,24,quotas.softlim);
3566 /* Default Hard Quota 8 bytes */
3567 SBIG_UINT(pdata,32,quotas.hardlim);
3569 /* Quota flag 2 bytes */
3570 SSVAL(pdata,40,quotas.qflags);
3572 /* Unknown3 6 NULL bytes */
3573 SSVAL(pdata,42,0);
3574 SIVAL(pdata,44,0);
3576 break;
3578 #endif /* HAVE_SYS_QUOTAS */
3579 case SMB_FS_OBJECTID_INFORMATION:
3581 unsigned char objid[16];
3582 struct smb_extended_info extended_info;
3583 memcpy(pdata,create_volume_objectid(conn, objid),16);
3584 samba_extended_info_version (&extended_info);
3585 SIVAL(pdata,16,extended_info.samba_magic);
3586 SIVAL(pdata,20,extended_info.samba_version);
3587 SIVAL(pdata,24,extended_info.samba_subversion);
3588 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3589 memcpy(pdata+36,extended_info.samba_version_string,28);
3590 data_len = 64;
3591 break;
3594 case SMB_FS_SECTOR_SIZE_INFORMATION:
3596 data_len = 28;
3598 * These values match a physical Windows Server 2012
3599 * share backed by NTFS atop spinning rust.
3601 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3602 /* logical_bytes_per_sector */
3603 SIVAL(pdata, 0, bytes_per_sector);
3604 /* phys_bytes_per_sector_atomic */
3605 SIVAL(pdata, 4, bytes_per_sector);
3606 /* phys_bytes_per_sector_perf */
3607 SIVAL(pdata, 8, bytes_per_sector);
3608 /* fs_effective_phys_bytes_per_sector_atomic */
3609 SIVAL(pdata, 12, bytes_per_sector);
3610 /* flags */
3611 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3612 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3613 /* byte_off_sector_align */
3614 SIVAL(pdata, 20, 0);
3615 /* byte_off_partition_align */
3616 SIVAL(pdata, 24, 0);
3617 *fixed_portion = 28;
3618 break;
3623 * Query the version and capabilities of the CIFS UNIX extensions
3624 * in use.
3627 case SMB_QUERY_CIFS_UNIX_INFO:
3629 bool large_write = lp_min_receive_file_size() &&
3630 !srv_is_signing_active(xconn);
3631 bool large_read = !srv_is_signing_active(xconn);
3632 int encrypt_caps = 0;
3634 if (!lp_unix_extensions()) {
3635 return NT_STATUS_INVALID_LEVEL;
3638 switch (conn->encrypt_level) {
3639 case SMB_SIGNING_OFF:
3640 encrypt_caps = 0;
3641 break;
3642 case SMB_SIGNING_DESIRED:
3643 case SMB_SIGNING_IF_REQUIRED:
3644 case SMB_SIGNING_DEFAULT:
3645 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3646 break;
3647 case SMB_SIGNING_REQUIRED:
3648 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3649 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3650 large_write = false;
3651 large_read = false;
3652 break;
3655 data_len = 12;
3656 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3657 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3659 /* We have POSIX ACLs, pathname, encryption,
3660 * large read/write, and locking capability. */
3662 SBIG_UINT(pdata,4,((uint64_t)(
3663 CIFS_UNIX_POSIX_ACLS_CAP|
3664 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3665 CIFS_UNIX_FCNTL_LOCKS_CAP|
3666 CIFS_UNIX_EXTATTR_CAP|
3667 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3668 encrypt_caps|
3669 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3670 (large_write ?
3671 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3672 break;
3675 case SMB_QUERY_POSIX_FS_INFO:
3677 int rc;
3678 vfs_statvfs_struct svfs;
3680 if (!lp_unix_extensions()) {
3681 return NT_STATUS_INVALID_LEVEL;
3684 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3686 if (!rc) {
3687 data_len = 56;
3688 SIVAL(pdata,0,svfs.OptimalTransferSize);
3689 SIVAL(pdata,4,svfs.BlockSize);
3690 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3691 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3692 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3693 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3694 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3695 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3696 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3697 #ifdef EOPNOTSUPP
3698 } else if (rc == EOPNOTSUPP) {
3699 return NT_STATUS_INVALID_LEVEL;
3700 #endif /* EOPNOTSUPP */
3701 } else {
3702 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3703 return NT_STATUS_DOS(ERRSRV, ERRerror);
3705 break;
3708 case SMB_QUERY_POSIX_WHOAMI:
3710 uint32_t flags = 0;
3711 uint32_t sid_bytes;
3712 int i;
3714 if (!lp_unix_extensions()) {
3715 return NT_STATUS_INVALID_LEVEL;
3718 if (max_data_bytes < 40) {
3719 return NT_STATUS_BUFFER_TOO_SMALL;
3722 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3723 flags |= SMB_WHOAMI_GUEST;
3726 /* NOTE: 8 bytes for UID/GID, irrespective of native
3727 * platform size. This matches
3728 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3730 data_len = 4 /* flags */
3731 + 4 /* flag mask */
3732 + 8 /* uid */
3733 + 8 /* gid */
3734 + 4 /* ngroups */
3735 + 4 /* num_sids */
3736 + 4 /* SID bytes */
3737 + 4 /* pad/reserved */
3738 + (conn->session_info->unix_token->ngroups * 8)
3739 /* groups list */
3740 + (conn->session_info->security_token->num_sids *
3741 SID_MAX_SIZE)
3742 /* SID list */;
3744 SIVAL(pdata, 0, flags);
3745 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3746 SBIG_UINT(pdata, 8,
3747 (uint64_t)conn->session_info->unix_token->uid);
3748 SBIG_UINT(pdata, 16,
3749 (uint64_t)conn->session_info->unix_token->gid);
3752 if (data_len >= max_data_bytes) {
3753 /* Potential overflow, skip the GIDs and SIDs. */
3755 SIVAL(pdata, 24, 0); /* num_groups */
3756 SIVAL(pdata, 28, 0); /* num_sids */
3757 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3758 SIVAL(pdata, 36, 0); /* reserved */
3760 data_len = 40;
3761 break;
3764 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3765 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3767 /* We walk the SID list twice, but this call is fairly
3768 * infrequent, and I don't expect that it's performance
3769 * sensitive -- jpeach
3771 for (i = 0, sid_bytes = 0;
3772 i < conn->session_info->security_token->num_sids; ++i) {
3773 sid_bytes += ndr_size_dom_sid(
3774 &conn->session_info->security_token->sids[i],
3778 /* SID list byte count */
3779 SIVAL(pdata, 32, sid_bytes);
3781 /* 4 bytes pad/reserved - must be zero */
3782 SIVAL(pdata, 36, 0);
3783 data_len = 40;
3785 /* GID list */
3786 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3787 SBIG_UINT(pdata, data_len,
3788 (uint64_t)conn->session_info->unix_token->groups[i]);
3789 data_len += 8;
3792 /* SID list */
3793 for (i = 0;
3794 i < conn->session_info->security_token->num_sids; ++i) {
3795 int sid_len = ndr_size_dom_sid(
3796 &conn->session_info->security_token->sids[i],
3799 sid_linearize((uint8_t *)(pdata + data_len),
3800 sid_len,
3801 &conn->session_info->security_token->sids[i]);
3802 data_len += sid_len;
3805 break;
3808 case SMB_MAC_QUERY_FS_INFO:
3810 * Thursby MAC extension... ONLY on NTFS filesystems
3811 * once we do streams then we don't need this
3813 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3814 data_len = 88;
3815 SIVAL(pdata,84,0x100); /* Don't support mac... */
3816 break;
3818 /* drop through */
3819 default:
3820 return NT_STATUS_INVALID_LEVEL;
3823 *ret_data_len = data_len;
3824 return status;
3827 /****************************************************************************
3828 Reply to a TRANS2_QFSINFO (query filesystem info).
3829 ****************************************************************************/
3831 static void call_trans2qfsinfo(connection_struct *conn,
3832 struct smb_request *req,
3833 char **pparams, int total_params,
3834 char **ppdata, int total_data,
3835 unsigned int max_data_bytes)
3837 char *params = *pparams;
3838 uint16_t info_level;
3839 int data_len = 0;
3840 size_t fixed_portion;
3841 NTSTATUS status;
3843 if (total_params < 2) {
3844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3845 return;
3848 info_level = SVAL(params,0);
3850 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3851 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3852 DEBUG(0,("call_trans2qfsinfo: encryption required "
3853 "and info level 0x%x sent.\n",
3854 (unsigned int)info_level));
3855 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3856 return;
3860 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3862 status = smbd_do_qfsinfo(req->xconn, conn, req,
3863 info_level,
3864 req->flags2,
3865 max_data_bytes,
3866 &fixed_portion,
3867 NULL,
3868 ppdata, &data_len);
3869 if (!NT_STATUS_IS_OK(status)) {
3870 reply_nterror(req, status);
3871 return;
3874 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3875 max_data_bytes);
3877 DEBUG( 4, ( "%s info_level = %d\n",
3878 smb_fn_name(req->cmd), info_level) );
3880 return;
3883 /****************************************************************************
3884 Reply to a TRANS2_SETFSINFO (set filesystem info).
3885 ****************************************************************************/
3887 static void call_trans2setfsinfo(connection_struct *conn,
3888 struct smb_request *req,
3889 char **pparams, int total_params,
3890 char **ppdata, int total_data,
3891 unsigned int max_data_bytes)
3893 struct smbXsrv_connection *xconn = req->xconn;
3894 char *pdata = *ppdata;
3895 char *params = *pparams;
3896 uint16_t info_level;
3898 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3899 lp_servicename(talloc_tos(), SNUM(conn))));
3901 /* */
3902 if (total_params < 4) {
3903 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3904 total_params));
3905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3906 return;
3909 info_level = SVAL(params,2);
3911 if (IS_IPC(conn)) {
3912 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3913 info_level != SMB_SET_CIFS_UNIX_INFO) {
3914 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3915 "info level (0x%x) on IPC$.\n",
3916 (unsigned int)info_level));
3917 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3918 return;
3922 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3923 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3924 DEBUG(0,("call_trans2setfsinfo: encryption required "
3925 "and info level 0x%x sent.\n",
3926 (unsigned int)info_level));
3927 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3928 return;
3932 switch(info_level) {
3933 case SMB_SET_CIFS_UNIX_INFO:
3934 if (!lp_unix_extensions()) {
3935 DEBUG(2,("call_trans2setfsinfo: "
3936 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3937 "unix extensions off\n"));
3938 reply_nterror(req,
3939 NT_STATUS_INVALID_LEVEL);
3940 return;
3943 /* There should be 12 bytes of capabilities set. */
3944 if (total_data < 12) {
3945 reply_nterror(
3946 req,
3947 NT_STATUS_INVALID_PARAMETER);
3948 return;
3950 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3951 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3952 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3953 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3954 /* Just print these values for now. */
3955 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3956 "major = %u, minor = %u cap_low = 0x%x, "
3957 "cap_high = 0x%xn",
3958 (unsigned int)xconn->
3959 smb1.unix_info.client_major,
3960 (unsigned int)xconn->
3961 smb1.unix_info.client_minor,
3962 (unsigned int)xconn->
3963 smb1.unix_info.client_cap_low,
3964 (unsigned int)xconn->
3965 smb1.unix_info.client_cap_high));
3967 /* Here is where we must switch to posix pathname processing... */
3968 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3969 lp_set_posix_pathnames();
3970 mangle_change_to_posix();
3973 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3974 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3975 /* Client that knows how to do posix locks,
3976 * but not posix open/mkdir operations. Set a
3977 * default type for read/write checks. */
3979 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3982 break;
3984 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3986 NTSTATUS status;
3987 size_t param_len = 0;
3988 size_t data_len = total_data;
3990 if (!lp_unix_extensions()) {
3991 reply_nterror(
3992 req,
3993 NT_STATUS_INVALID_LEVEL);
3994 return;
3997 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3998 reply_nterror(
3999 req,
4000 NT_STATUS_NOT_SUPPORTED);
4001 return;
4004 if (xconn->smb1.echo_handler.trusted_fde) {
4005 DEBUG( 2,("call_trans2setfsinfo: "
4006 "request transport encryption disabled"
4007 "with 'fork echo handler = yes'\n"));
4008 reply_nterror(
4009 req,
4010 NT_STATUS_NOT_SUPPORTED);
4011 return;
4014 DEBUG( 4,("call_trans2setfsinfo: "
4015 "request transport encryption.\n"));
4017 status = srv_request_encryption_setup(conn,
4018 (unsigned char **)ppdata,
4019 &data_len,
4020 (unsigned char **)pparams,
4021 &param_len);
4023 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4024 !NT_STATUS_IS_OK(status)) {
4025 reply_nterror(req, status);
4026 return;
4029 send_trans2_replies(conn, req,
4030 NT_STATUS_OK,
4031 *pparams,
4032 param_len,
4033 *ppdata,
4034 data_len,
4035 max_data_bytes);
4037 if (NT_STATUS_IS_OK(status)) {
4038 /* Server-side transport
4039 * encryption is now *on*. */
4040 status = srv_encryption_start(conn);
4041 if (!NT_STATUS_IS_OK(status)) {
4042 char *reason = talloc_asprintf(talloc_tos(),
4043 "Failure in setting "
4044 "up encrypted transport: %s",
4045 nt_errstr(status));
4046 exit_server_cleanly(reason);
4049 return;
4052 case SMB_FS_QUOTA_INFORMATION:
4054 files_struct *fsp = NULL;
4055 SMB_NTQUOTA_STRUCT quotas;
4057 ZERO_STRUCT(quotas);
4059 /* access check */
4060 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4061 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4062 lp_servicename(talloc_tos(), SNUM(conn)),
4063 conn->session_info->unix_info->unix_name));
4064 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4065 return;
4068 /* note: normally there're 48 bytes,
4069 * but we didn't use the last 6 bytes for now
4070 * --metze
4072 fsp = file_fsp(req, SVAL(params,0));
4074 if (!check_fsp_ntquota_handle(conn, req,
4075 fsp)) {
4076 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4077 reply_nterror(
4078 req, NT_STATUS_INVALID_HANDLE);
4079 return;
4082 if (total_data < 42) {
4083 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4084 total_data));
4085 reply_nterror(
4086 req,
4087 NT_STATUS_INVALID_PARAMETER);
4088 return;
4091 /* unknown_1 24 NULL bytes in pdata*/
4093 /* the soft quotas 8 bytes (uint64_t)*/
4094 quotas.softlim = BVAL(pdata,24);
4096 /* the hard quotas 8 bytes (uint64_t)*/
4097 quotas.hardlim = BVAL(pdata,32);
4099 /* quota_flags 2 bytes **/
4100 quotas.qflags = SVAL(pdata,40);
4102 /* unknown_2 6 NULL bytes follow*/
4104 /* now set the quotas */
4105 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4106 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4107 reply_nterror(req, map_nt_error_from_unix(errno));
4108 return;
4111 break;
4113 default:
4114 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4115 info_level));
4116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4117 return;
4118 break;
4122 * sending this reply works fine,
4123 * but I'm not sure it's the same
4124 * like windows do...
4125 * --metze
4127 reply_outbuf(req, 10, 0);
4130 #if defined(HAVE_POSIX_ACLS)
4131 /****************************************************************************
4132 Utility function to count the number of entries in a POSIX acl.
4133 ****************************************************************************/
4135 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4137 unsigned int ace_count = 0;
4138 int entry_id = SMB_ACL_FIRST_ENTRY;
4139 SMB_ACL_ENTRY_T entry;
4141 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4142 /* get_next... */
4143 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4144 entry_id = SMB_ACL_NEXT_ENTRY;
4146 ace_count++;
4148 return ace_count;
4151 /****************************************************************************
4152 Utility function to marshall a POSIX acl into wire format.
4153 ****************************************************************************/
4155 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4157 int entry_id = SMB_ACL_FIRST_ENTRY;
4158 SMB_ACL_ENTRY_T entry;
4160 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4161 SMB_ACL_TAG_T tagtype;
4162 SMB_ACL_PERMSET_T permset;
4163 unsigned char perms = 0;
4164 unsigned int own_grp;
4166 /* get_next... */
4167 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4168 entry_id = SMB_ACL_NEXT_ENTRY;
4171 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4172 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4173 return False;
4176 if (sys_acl_get_permset(entry, &permset) == -1) {
4177 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4178 return False;
4181 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4182 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4183 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4185 SCVAL(pdata,1,perms);
4187 switch (tagtype) {
4188 case SMB_ACL_USER_OBJ:
4189 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4190 own_grp = (unsigned int)pst->st_ex_uid;
4191 SIVAL(pdata,2,own_grp);
4192 SIVAL(pdata,6,0);
4193 break;
4194 case SMB_ACL_USER:
4196 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4197 if (!puid) {
4198 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4199 return False;
4201 own_grp = (unsigned int)*puid;
4202 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4203 SIVAL(pdata,2,own_grp);
4204 SIVAL(pdata,6,0);
4205 break;
4207 case SMB_ACL_GROUP_OBJ:
4208 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4209 own_grp = (unsigned int)pst->st_ex_gid;
4210 SIVAL(pdata,2,own_grp);
4211 SIVAL(pdata,6,0);
4212 break;
4213 case SMB_ACL_GROUP:
4215 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4216 if (!pgid) {
4217 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4218 return False;
4220 own_grp = (unsigned int)*pgid;
4221 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4222 SIVAL(pdata,2,own_grp);
4223 SIVAL(pdata,6,0);
4224 break;
4226 case SMB_ACL_MASK:
4227 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4228 SIVAL(pdata,2,0xFFFFFFFF);
4229 SIVAL(pdata,6,0xFFFFFFFF);
4230 break;
4231 case SMB_ACL_OTHER:
4232 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4233 SIVAL(pdata,2,0xFFFFFFFF);
4234 SIVAL(pdata,6,0xFFFFFFFF);
4235 break;
4236 default:
4237 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4238 return False;
4240 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4243 return True;
4245 #endif
4247 /****************************************************************************
4248 Store the FILE_UNIX_BASIC info.
4249 ****************************************************************************/
4251 static char *store_file_unix_basic(connection_struct *conn,
4252 char *pdata,
4253 files_struct *fsp,
4254 const SMB_STRUCT_STAT *psbuf)
4256 uint64_t file_index = get_FileIndex(conn, psbuf);
4257 dev_t devno;
4259 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4260 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4262 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4263 pdata += 8;
4265 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4266 pdata += 8;
4268 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4269 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4270 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4271 pdata += 24;
4273 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4274 SIVAL(pdata,4,0);
4275 pdata += 8;
4277 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4278 SIVAL(pdata,4,0);
4279 pdata += 8;
4281 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4282 pdata += 4;
4284 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4285 devno = psbuf->st_ex_rdev;
4286 } else {
4287 devno = psbuf->st_ex_dev;
4290 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4291 SIVAL(pdata,4,0);
4292 pdata += 8;
4294 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4295 SIVAL(pdata,4,0);
4296 pdata += 8;
4298 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4299 pdata += 8;
4301 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4302 SIVAL(pdata,4,0);
4303 pdata += 8;
4305 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4306 SIVAL(pdata,4,0);
4307 pdata += 8;
4309 return pdata;
4312 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4313 * the chflags(2) (or equivalent) flags.
4315 * XXX: this really should be behind the VFS interface. To do this, we would
4316 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4317 * Each VFS module could then implement its own mapping as appropriate for the
4318 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4320 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4321 info2_flags_map[] =
4323 #ifdef UF_NODUMP
4324 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4325 #endif
4327 #ifdef UF_IMMUTABLE
4328 { UF_IMMUTABLE, EXT_IMMUTABLE },
4329 #endif
4331 #ifdef UF_APPEND
4332 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4333 #endif
4335 #ifdef UF_HIDDEN
4336 { UF_HIDDEN, EXT_HIDDEN },
4337 #endif
4339 /* Do not remove. We need to guarantee that this array has at least one
4340 * entry to build on HP-UX.
4342 { 0, 0 }
4346 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4347 uint32_t *smb_fflags, uint32_t *smb_fmask)
4349 int i;
4351 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4352 *smb_fmask |= info2_flags_map[i].smb_fflag;
4353 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4354 *smb_fflags |= info2_flags_map[i].smb_fflag;
4359 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4360 const uint32_t smb_fflags,
4361 const uint32_t smb_fmask,
4362 int *stat_fflags)
4364 uint32_t max_fmask = 0;
4365 int i;
4367 *stat_fflags = psbuf->st_ex_flags;
4369 /* For each flags requested in smb_fmask, check the state of the
4370 * corresponding flag in smb_fflags and set or clear the matching
4371 * stat flag.
4374 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4375 max_fmask |= info2_flags_map[i].smb_fflag;
4376 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4377 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4378 *stat_fflags |= info2_flags_map[i].stat_fflag;
4379 } else {
4380 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4385 /* If smb_fmask is asking to set any bits that are not supported by
4386 * our flag mappings, we should fail.
4388 if ((smb_fmask & max_fmask) != smb_fmask) {
4389 return False;
4392 return True;
4396 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4397 * of file flags and birth (create) time.
4399 static char *store_file_unix_basic_info2(connection_struct *conn,
4400 char *pdata,
4401 files_struct *fsp,
4402 const SMB_STRUCT_STAT *psbuf)
4404 uint32_t file_flags = 0;
4405 uint32_t flags_mask = 0;
4407 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4409 /* Create (birth) time 64 bit */
4410 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4411 pdata += 8;
4413 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4414 SIVAL(pdata, 0, file_flags); /* flags */
4415 SIVAL(pdata, 4, flags_mask); /* mask */
4416 pdata += 8;
4418 return pdata;
4421 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4422 const struct stream_struct *streams,
4423 char *data,
4424 unsigned int max_data_bytes,
4425 unsigned int *data_size)
4427 unsigned int i;
4428 unsigned int ofs = 0;
4430 if (max_data_bytes < 32) {
4431 return NT_STATUS_INFO_LENGTH_MISMATCH;
4434 for (i = 0; i < num_streams; i++) {
4435 unsigned int next_offset;
4436 size_t namelen;
4437 smb_ucs2_t *namebuf;
4439 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4440 streams[i].name, &namelen) ||
4441 namelen <= 2)
4443 return NT_STATUS_INVALID_PARAMETER;
4447 * name_buf is now null-terminated, we need to marshall as not
4448 * terminated
4451 namelen -= 2;
4454 * We cannot overflow ...
4456 if ((ofs + 24 + namelen) > max_data_bytes) {
4457 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4458 i));
4459 TALLOC_FREE(namebuf);
4460 return STATUS_BUFFER_OVERFLOW;
4463 SIVAL(data, ofs+4, namelen);
4464 SOFF_T(data, ofs+8, streams[i].size);
4465 SOFF_T(data, ofs+16, streams[i].alloc_size);
4466 memcpy(data+ofs+24, namebuf, namelen);
4467 TALLOC_FREE(namebuf);
4469 next_offset = ofs + 24 + namelen;
4471 if (i == num_streams-1) {
4472 SIVAL(data, ofs, 0);
4474 else {
4475 unsigned int align = ndr_align_size(next_offset, 8);
4477 if ((next_offset + align) > max_data_bytes) {
4478 DEBUG(10, ("refusing to overflow align "
4479 "reply at stream %u\n",
4480 i));
4481 TALLOC_FREE(namebuf);
4482 return STATUS_BUFFER_OVERFLOW;
4485 memset(data+next_offset, 0, align);
4486 next_offset += align;
4488 SIVAL(data, ofs, next_offset - ofs);
4489 ofs = next_offset;
4492 ofs = next_offset;
4495 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4497 *data_size = ofs;
4499 return NT_STATUS_OK;
4502 /****************************************************************************
4503 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4504 ****************************************************************************/
4506 static void call_trans2qpipeinfo(connection_struct *conn,
4507 struct smb_request *req,
4508 unsigned int tran_call,
4509 char **pparams, int total_params,
4510 char **ppdata, int total_data,
4511 unsigned int max_data_bytes)
4513 char *params = *pparams;
4514 char *pdata = *ppdata;
4515 unsigned int data_size = 0;
4516 unsigned int param_size = 2;
4517 uint16_t info_level;
4518 files_struct *fsp;
4520 if (!params) {
4521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4522 return;
4525 if (total_params < 4) {
4526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4527 return;
4530 fsp = file_fsp(req, SVAL(params,0));
4531 if (!fsp_is_np(fsp)) {
4532 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4533 return;
4536 info_level = SVAL(params,2);
4538 *pparams = (char *)SMB_REALLOC(*pparams,2);
4539 if (*pparams == NULL) {
4540 reply_nterror(req, NT_STATUS_NO_MEMORY);
4541 return;
4543 params = *pparams;
4544 SSVAL(params,0,0);
4545 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4547 return;
4549 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4550 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4551 if (*ppdata == NULL ) {
4552 reply_nterror(req, NT_STATUS_NO_MEMORY);
4553 return;
4555 pdata = *ppdata;
4557 switch (info_level) {
4558 case SMB_FILE_STANDARD_INFORMATION:
4559 memset(pdata,0,24);
4560 SOFF_T(pdata,0,4096LL);
4561 SIVAL(pdata,16,1);
4562 SIVAL(pdata,20,1);
4563 data_size = 24;
4564 break;
4566 default:
4567 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4568 return;
4571 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4572 max_data_bytes);
4574 return;
4577 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4578 TALLOC_CTX *mem_ctx,
4579 uint16_t info_level,
4580 files_struct *fsp,
4581 struct smb_filename *smb_fname,
4582 bool delete_pending,
4583 struct timespec write_time_ts,
4584 struct ea_list *ea_list,
4585 int lock_data_count,
4586 char *lock_data,
4587 uint16_t flags2,
4588 unsigned int max_data_bytes,
4589 size_t *fixed_portion,
4590 char **ppdata,
4591 unsigned int *pdata_size)
4593 char *pdata = *ppdata;
4594 char *dstart, *dend;
4595 unsigned int data_size;
4596 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4597 time_t create_time, mtime, atime, c_time;
4598 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4599 char *p;
4600 char *base_name;
4601 char *dos_fname;
4602 int mode;
4603 int nlink;
4604 NTSTATUS status;
4605 uint64_t file_size = 0;
4606 uint64_t pos = 0;
4607 uint64_t allocation_size = 0;
4608 uint64_t file_index = 0;
4609 uint32_t access_mask = 0;
4610 size_t len = 0;
4612 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4613 return NT_STATUS_INVALID_LEVEL;
4616 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4617 smb_fname_str_dbg(smb_fname),
4618 fsp_fnum_dbg(fsp),
4619 info_level, max_data_bytes));
4621 mode = dos_mode(conn, smb_fname);
4622 nlink = psbuf->st_ex_nlink;
4624 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4625 nlink = 1;
4628 if ((nlink > 0) && delete_pending) {
4629 nlink -= 1;
4632 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4633 return NT_STATUS_INVALID_PARAMETER;
4636 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4637 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4638 if (*ppdata == NULL) {
4639 return NT_STATUS_NO_MEMORY;
4641 pdata = *ppdata;
4642 dstart = pdata;
4643 dend = dstart + data_size - 1;
4645 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4646 update_stat_ex_mtime(psbuf, write_time_ts);
4649 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4650 mtime_ts = psbuf->st_ex_mtime;
4651 atime_ts = psbuf->st_ex_atime;
4652 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4654 if (lp_dos_filetime_resolution(SNUM(conn))) {
4655 dos_filetime_timespec(&create_time_ts);
4656 dos_filetime_timespec(&mtime_ts);
4657 dos_filetime_timespec(&atime_ts);
4658 dos_filetime_timespec(&ctime_ts);
4661 create_time = convert_timespec_to_time_t(create_time_ts);
4662 mtime = convert_timespec_to_time_t(mtime_ts);
4663 atime = convert_timespec_to_time_t(atime_ts);
4664 c_time = convert_timespec_to_time_t(ctime_ts);
4666 p = strrchr_m(smb_fname->base_name,'/');
4667 if (!p)
4668 base_name = smb_fname->base_name;
4669 else
4670 base_name = p+1;
4672 /* NT expects the name to be in an exact form of the *full*
4673 filename. See the trans2 torture test */
4674 if (ISDOT(base_name)) {
4675 dos_fname = talloc_strdup(mem_ctx, "\\");
4676 if (!dos_fname) {
4677 return NT_STATUS_NO_MEMORY;
4679 } else {
4680 dos_fname = talloc_asprintf(mem_ctx,
4681 "\\%s",
4682 smb_fname->base_name);
4683 if (!dos_fname) {
4684 return NT_STATUS_NO_MEMORY;
4686 if (is_ntfs_stream_smb_fname(smb_fname)) {
4687 dos_fname = talloc_asprintf(dos_fname, "%s",
4688 smb_fname->stream_name);
4689 if (!dos_fname) {
4690 return NT_STATUS_NO_MEMORY;
4694 string_replace(dos_fname, '/', '\\');
4697 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4699 if (!fsp) {
4700 /* Do we have this path open ? */
4701 files_struct *fsp1;
4702 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4703 fsp1 = file_find_di_first(conn->sconn, fileid);
4704 if (fsp1 && fsp1->initial_allocation_size) {
4705 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4709 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4710 file_size = get_file_size_stat(psbuf);
4713 if (fsp) {
4714 pos = fsp->fh->position_information;
4717 if (fsp) {
4718 access_mask = fsp->access_mask;
4719 } else {
4720 /* GENERIC_EXECUTE mapping from Windows */
4721 access_mask = 0x12019F;
4724 /* This should be an index number - looks like
4725 dev/ino to me :-)
4727 I think this causes us to fail the IFSKIT
4728 BasicFileInformationTest. -tpot */
4729 file_index = get_FileIndex(conn, psbuf);
4731 *fixed_portion = 0;
4733 switch (info_level) {
4734 case SMB_INFO_STANDARD:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4736 data_size = 22;
4737 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4738 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4739 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4740 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4741 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4742 SSVAL(pdata,l1_attrFile,mode);
4743 break;
4745 case SMB_INFO_QUERY_EA_SIZE:
4747 unsigned int ea_size =
4748 estimate_ea_size(conn, fsp,
4749 smb_fname);
4750 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4751 data_size = 26;
4752 srv_put_dos_date2(pdata,0,create_time);
4753 srv_put_dos_date2(pdata,4,atime);
4754 srv_put_dos_date2(pdata,8,mtime); /* write time */
4755 SIVAL(pdata,12,(uint32_t)file_size);
4756 SIVAL(pdata,16,(uint32_t)allocation_size);
4757 SSVAL(pdata,20,mode);
4758 SIVAL(pdata,22,ea_size);
4759 break;
4762 case SMB_INFO_IS_NAME_VALID:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4764 if (fsp) {
4765 /* os/2 needs this ? really ?*/
4766 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4768 /* This is only reached for qpathinfo */
4769 data_size = 0;
4770 break;
4772 case SMB_INFO_QUERY_EAS_FROM_LIST:
4774 size_t total_ea_len = 0;
4775 struct ea_list *ea_file_list = NULL;
4776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4778 status =
4779 get_ea_list_from_file(mem_ctx, conn, fsp,
4780 smb_fname,
4781 &total_ea_len, &ea_file_list);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 return status;
4786 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4788 if (!ea_list || (total_ea_len > data_size)) {
4789 data_size = 4;
4790 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4791 break;
4794 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4795 break;
4798 case SMB_INFO_QUERY_ALL_EAS:
4800 /* We have data_size bytes to put EA's into. */
4801 size_t total_ea_len = 0;
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4804 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4805 smb_fname,
4806 &total_ea_len, &ea_list);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 return status;
4811 if (!ea_list || (total_ea_len > data_size)) {
4812 data_size = 4;
4813 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4814 break;
4817 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4818 break;
4821 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4823 /* This is FileFullEaInformation - 0xF which maps to
4824 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4826 /* We have data_size bytes to put EA's into. */
4827 size_t total_ea_len = 0;
4828 struct ea_list *ea_file_list = NULL;
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4832 /*TODO: add filtering and index handling */
4834 status =
4835 get_ea_list_from_file(mem_ctx, conn, fsp,
4836 smb_fname,
4837 &total_ea_len, &ea_file_list);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 return status;
4841 if (!ea_file_list) {
4842 return NT_STATUS_NO_EAS_ON_FILE;
4845 status = fill_ea_chained_buffer(mem_ctx,
4846 pdata,
4847 data_size,
4848 &data_size,
4849 conn, ea_file_list);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 return status;
4853 break;
4856 case SMB_FILE_BASIC_INFORMATION:
4857 case SMB_QUERY_FILE_BASIC_INFO:
4859 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4860 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4861 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4862 } else {
4863 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4864 data_size = 40;
4865 SIVAL(pdata,36,0);
4867 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4868 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4869 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4870 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4871 SIVAL(pdata,32,mode);
4873 DEBUG(5,("SMB_QFBI - "));
4874 DEBUG(5,("create: %s ", ctime(&create_time)));
4875 DEBUG(5,("access: %s ", ctime(&atime)));
4876 DEBUG(5,("write: %s ", ctime(&mtime)));
4877 DEBUG(5,("change: %s ", ctime(&c_time)));
4878 DEBUG(5,("mode: %x\n", mode));
4879 *fixed_portion = data_size;
4880 break;
4882 case SMB_FILE_STANDARD_INFORMATION:
4883 case SMB_QUERY_FILE_STANDARD_INFO:
4885 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4886 data_size = 24;
4887 SOFF_T(pdata,0,allocation_size);
4888 SOFF_T(pdata,8,file_size);
4889 SIVAL(pdata,16,nlink);
4890 SCVAL(pdata,20,delete_pending?1:0);
4891 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4892 SSVAL(pdata,22,0); /* Padding. */
4893 *fixed_portion = 24;
4894 break;
4896 case SMB_FILE_EA_INFORMATION:
4897 case SMB_QUERY_FILE_EA_INFO:
4899 unsigned int ea_size =
4900 estimate_ea_size(conn, fsp, smb_fname);
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4902 data_size = 4;
4903 *fixed_portion = 4;
4904 SIVAL(pdata,0,ea_size);
4905 break;
4908 /* Get the 8.3 name - used if NT SMB was negotiated. */
4909 case SMB_QUERY_FILE_ALT_NAME_INFO:
4910 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4912 char mangled_name[13];
4913 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4914 if (!name_to_8_3(base_name,mangled_name,
4915 True,conn->params)) {
4916 return NT_STATUS_NO_MEMORY;
4918 status = srvstr_push(dstart, flags2,
4919 pdata+4, mangled_name,
4920 PTR_DIFF(dend, pdata+4),
4921 STR_UNICODE, &len);
4922 if (!NT_STATUS_IS_OK(status)) {
4923 return status;
4925 data_size = 4 + len;
4926 SIVAL(pdata,0,len);
4927 *fixed_portion = 8;
4928 break;
4931 case SMB_QUERY_FILE_NAME_INFO:
4934 this must be *exactly* right for ACLs on mapped drives to work
4936 status = srvstr_push(dstart, flags2,
4937 pdata+4, dos_fname,
4938 PTR_DIFF(dend, pdata+4),
4939 STR_UNICODE, &len);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 return status;
4943 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4944 data_size = 4 + len;
4945 SIVAL(pdata,0,len);
4946 break;
4949 case SMB_FILE_ALLOCATION_INFORMATION:
4950 case SMB_QUERY_FILE_ALLOCATION_INFO:
4951 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4952 data_size = 8;
4953 SOFF_T(pdata,0,allocation_size);
4954 break;
4956 case SMB_FILE_END_OF_FILE_INFORMATION:
4957 case SMB_QUERY_FILE_END_OF_FILEINFO:
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4959 data_size = 8;
4960 SOFF_T(pdata,0,file_size);
4961 break;
4963 case SMB_QUERY_FILE_ALL_INFO:
4964 case SMB_FILE_ALL_INFORMATION:
4966 unsigned int ea_size =
4967 estimate_ea_size(conn, fsp, smb_fname);
4968 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4969 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4970 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4971 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4972 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4973 SIVAL(pdata,32,mode);
4974 SIVAL(pdata,36,0); /* padding. */
4975 pdata += 40;
4976 SOFF_T(pdata,0,allocation_size);
4977 SOFF_T(pdata,8,file_size);
4978 SIVAL(pdata,16,nlink);
4979 SCVAL(pdata,20,delete_pending);
4980 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4981 SSVAL(pdata,22,0);
4982 pdata += 24;
4983 SIVAL(pdata,0,ea_size);
4984 pdata += 4; /* EA info */
4985 status = srvstr_push(dstart, flags2,
4986 pdata+4, dos_fname,
4987 PTR_DIFF(dend, pdata+4),
4988 STR_UNICODE, &len);
4989 if (!NT_STATUS_IS_OK(status)) {
4990 return status;
4992 SIVAL(pdata,0,len);
4993 pdata += 4 + len;
4994 data_size = PTR_DIFF(pdata,(*ppdata));
4995 *fixed_portion = 10;
4996 break;
4999 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5001 unsigned int ea_size =
5002 estimate_ea_size(conn, fsp, smb_fname);
5003 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5004 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5005 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5006 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5007 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5008 SIVAL(pdata, 0x20, mode);
5009 SIVAL(pdata, 0x24, 0); /* padding. */
5010 SBVAL(pdata, 0x28, allocation_size);
5011 SBVAL(pdata, 0x30, file_size);
5012 SIVAL(pdata, 0x38, nlink);
5013 SCVAL(pdata, 0x3C, delete_pending);
5014 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5015 SSVAL(pdata, 0x3E, 0); /* padding */
5016 SBVAL(pdata, 0x40, file_index);
5017 SIVAL(pdata, 0x48, ea_size);
5018 SIVAL(pdata, 0x4C, access_mask);
5019 SBVAL(pdata, 0x50, pos);
5020 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5021 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5023 pdata += 0x60;
5025 status = srvstr_push(dstart, flags2,
5026 pdata+4, dos_fname,
5027 PTR_DIFF(dend, pdata+4),
5028 STR_UNICODE, &len);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 return status;
5032 SIVAL(pdata,0,len);
5033 pdata += 4 + len;
5034 data_size = PTR_DIFF(pdata,(*ppdata));
5035 *fixed_portion = 104;
5036 break;
5038 case SMB_FILE_INTERNAL_INFORMATION:
5040 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5041 SBVAL(pdata, 0, file_index);
5042 data_size = 8;
5043 *fixed_portion = 8;
5044 break;
5046 case SMB_FILE_ACCESS_INFORMATION:
5047 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5048 SIVAL(pdata, 0, access_mask);
5049 data_size = 4;
5050 *fixed_portion = 4;
5051 break;
5053 case SMB_FILE_NAME_INFORMATION:
5054 /* Pathname with leading '\'. */
5056 size_t byte_len;
5057 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5058 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5059 SIVAL(pdata,0,byte_len);
5060 data_size = 4 + byte_len;
5061 break;
5064 case SMB_FILE_DISPOSITION_INFORMATION:
5065 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5066 data_size = 1;
5067 SCVAL(pdata,0,delete_pending);
5068 *fixed_portion = 1;
5069 break;
5071 case SMB_FILE_POSITION_INFORMATION:
5072 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5073 data_size = 8;
5074 SOFF_T(pdata,0,pos);
5075 *fixed_portion = 8;
5076 break;
5078 case SMB_FILE_MODE_INFORMATION:
5079 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5080 SIVAL(pdata,0,mode);
5081 data_size = 4;
5082 *fixed_portion = 4;
5083 break;
5085 case SMB_FILE_ALIGNMENT_INFORMATION:
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5087 SIVAL(pdata,0,0); /* No alignment needed. */
5088 data_size = 4;
5089 *fixed_portion = 4;
5090 break;
5093 * NT4 server just returns "invalid query" to this - if we try
5094 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5095 * want this. JRA.
5097 /* The first statement above is false - verified using Thursby
5098 * client against NT4 -- gcolley.
5100 case SMB_QUERY_FILE_STREAM_INFO:
5101 case SMB_FILE_STREAM_INFORMATION: {
5102 unsigned int num_streams = 0;
5103 struct stream_struct *streams = NULL;
5105 DEBUG(10,("smbd_do_qfilepathinfo: "
5106 "SMB_FILE_STREAM_INFORMATION\n"));
5108 if (is_ntfs_stream_smb_fname(smb_fname)) {
5109 return NT_STATUS_INVALID_PARAMETER;
5112 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5113 talloc_tos(), &num_streams, &streams);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 DEBUG(10, ("could not get stream info: %s\n",
5117 nt_errstr(status)));
5118 return status;
5121 status = marshall_stream_info(num_streams, streams,
5122 pdata, max_data_bytes,
5123 &data_size);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 DEBUG(10, ("marshall_stream_info failed: %s\n",
5127 nt_errstr(status)));
5128 TALLOC_FREE(streams);
5129 return status;
5132 TALLOC_FREE(streams);
5134 *fixed_portion = 32;
5136 break;
5138 case SMB_QUERY_COMPRESSION_INFO:
5139 case SMB_FILE_COMPRESSION_INFORMATION:
5140 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5141 SOFF_T(pdata,0,file_size);
5142 SIVAL(pdata,8,0); /* ??? */
5143 SIVAL(pdata,12,0); /* ??? */
5144 data_size = 16;
5145 *fixed_portion = 16;
5146 break;
5148 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5149 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5150 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5151 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5152 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5153 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5154 SOFF_T(pdata,32,allocation_size);
5155 SOFF_T(pdata,40,file_size);
5156 SIVAL(pdata,48,mode);
5157 SIVAL(pdata,52,0); /* ??? */
5158 data_size = 56;
5159 *fixed_portion = 56;
5160 break;
5162 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5164 SIVAL(pdata,0,mode);
5165 SIVAL(pdata,4,0);
5166 data_size = 8;
5167 *fixed_portion = 8;
5168 break;
5171 * CIFS UNIX Extensions.
5174 case SMB_QUERY_FILE_UNIX_BASIC:
5176 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5177 data_size = PTR_DIFF(pdata,(*ppdata));
5179 DEBUG(4,("smbd_do_qfilepathinfo: "
5180 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5181 dump_data(4, (uint8_t *)(*ppdata), data_size);
5183 break;
5185 case SMB_QUERY_FILE_UNIX_INFO2:
5187 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5188 data_size = PTR_DIFF(pdata,(*ppdata));
5191 int i;
5192 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5194 for (i=0; i<100; i++)
5195 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5196 DEBUG(4,("\n"));
5199 break;
5201 case SMB_QUERY_FILE_UNIX_LINK:
5203 int link_len = 0;
5204 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5206 if (!buffer) {
5207 return NT_STATUS_NO_MEMORY;
5210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5211 #ifdef S_ISLNK
5212 if(!S_ISLNK(psbuf->st_ex_mode)) {
5213 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5215 #else
5216 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5217 #endif
5218 link_len = SMB_VFS_READLINK(conn,
5219 smb_fname->base_name,
5220 buffer, PATH_MAX);
5221 if (link_len == -1) {
5222 return map_nt_error_from_unix(errno);
5224 buffer[link_len] = 0;
5225 status = srvstr_push(dstart, flags2,
5226 pdata, buffer,
5227 PTR_DIFF(dend, pdata),
5228 STR_TERMINATE, &len);
5229 if (!NT_STATUS_IS_OK(status)) {
5230 return status;
5232 pdata += len;
5233 data_size = PTR_DIFF(pdata,(*ppdata));
5235 break;
5238 #if defined(HAVE_POSIX_ACLS)
5239 case SMB_QUERY_POSIX_ACL:
5241 SMB_ACL_T file_acl = NULL;
5242 SMB_ACL_T def_acl = NULL;
5243 uint16_t num_file_acls = 0;
5244 uint16_t num_def_acls = 0;
5246 if (fsp && fsp->fh->fd != -1) {
5247 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5248 talloc_tos());
5249 } else {
5250 file_acl =
5251 SMB_VFS_SYS_ACL_GET_FILE(conn,
5252 smb_fname->base_name,
5253 SMB_ACL_TYPE_ACCESS,
5254 talloc_tos());
5257 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5258 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5259 "not implemented on "
5260 "filesystem containing %s\n",
5261 smb_fname->base_name));
5262 return NT_STATUS_NOT_IMPLEMENTED;
5265 if (S_ISDIR(psbuf->st_ex_mode)) {
5266 if (fsp && fsp->is_directory) {
5267 def_acl =
5268 SMB_VFS_SYS_ACL_GET_FILE(
5269 conn,
5270 fsp->fsp_name->base_name,
5271 SMB_ACL_TYPE_DEFAULT,
5272 talloc_tos());
5273 } else {
5274 def_acl =
5275 SMB_VFS_SYS_ACL_GET_FILE(
5276 conn,
5277 smb_fname->base_name,
5278 SMB_ACL_TYPE_DEFAULT,
5279 talloc_tos());
5281 def_acl = free_empty_sys_acl(conn, def_acl);
5284 num_file_acls = count_acl_entries(conn, file_acl);
5285 num_def_acls = count_acl_entries(conn, def_acl);
5287 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5288 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5289 data_size,
5290 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5291 SMB_POSIX_ACL_HEADER_SIZE) ));
5292 if (file_acl) {
5293 TALLOC_FREE(file_acl);
5295 if (def_acl) {
5296 TALLOC_FREE(def_acl);
5298 return NT_STATUS_BUFFER_TOO_SMALL;
5301 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5302 SSVAL(pdata,2,num_file_acls);
5303 SSVAL(pdata,4,num_def_acls);
5304 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5305 if (file_acl) {
5306 TALLOC_FREE(file_acl);
5308 if (def_acl) {
5309 TALLOC_FREE(def_acl);
5311 return NT_STATUS_INTERNAL_ERROR;
5313 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5314 if (file_acl) {
5315 TALLOC_FREE(file_acl);
5317 if (def_acl) {
5318 TALLOC_FREE(def_acl);
5320 return NT_STATUS_INTERNAL_ERROR;
5323 if (file_acl) {
5324 TALLOC_FREE(file_acl);
5326 if (def_acl) {
5327 TALLOC_FREE(def_acl);
5329 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5330 break;
5332 #endif
5335 case SMB_QUERY_POSIX_LOCK:
5337 uint64_t count;
5338 uint64_t offset;
5339 uint64_t smblctx;
5340 enum brl_type lock_type;
5342 /* We need an open file with a real fd for this. */
5343 if (!fsp || fsp->fh->fd == -1) {
5344 return NT_STATUS_INVALID_LEVEL;
5347 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5348 return NT_STATUS_INVALID_PARAMETER;
5351 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5352 case POSIX_LOCK_TYPE_READ:
5353 lock_type = READ_LOCK;
5354 break;
5355 case POSIX_LOCK_TYPE_WRITE:
5356 lock_type = WRITE_LOCK;
5357 break;
5358 case POSIX_LOCK_TYPE_UNLOCK:
5359 default:
5360 /* There's no point in asking for an unlock... */
5361 return NT_STATUS_INVALID_PARAMETER;
5364 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5365 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5366 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5368 status = query_lock(fsp,
5369 &smblctx,
5370 &count,
5371 &offset,
5372 &lock_type,
5373 POSIX_LOCK);
5375 if (ERROR_WAS_LOCK_DENIED(status)) {
5376 /* Here we need to report who has it locked... */
5377 data_size = POSIX_LOCK_DATA_SIZE;
5379 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5380 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5381 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5382 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5383 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5385 } else if (NT_STATUS_IS_OK(status)) {
5386 /* For success we just return a copy of what we sent
5387 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5388 data_size = POSIX_LOCK_DATA_SIZE;
5389 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5390 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5391 } else {
5392 return status;
5394 break;
5397 default:
5398 return NT_STATUS_INVALID_LEVEL;
5401 *pdata_size = data_size;
5402 return NT_STATUS_OK;
5405 /****************************************************************************
5406 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5407 file name or file id).
5408 ****************************************************************************/
5410 static void call_trans2qfilepathinfo(connection_struct *conn,
5411 struct smb_request *req,
5412 unsigned int tran_call,
5413 char **pparams, int total_params,
5414 char **ppdata, int total_data,
5415 unsigned int max_data_bytes)
5417 char *params = *pparams;
5418 char *pdata = *ppdata;
5419 uint16_t info_level;
5420 unsigned int data_size = 0;
5421 unsigned int param_size = 2;
5422 struct smb_filename *smb_fname = NULL;
5423 bool delete_pending = False;
5424 struct timespec write_time_ts;
5425 files_struct *fsp = NULL;
5426 struct file_id fileid;
5427 struct ea_list *ea_list = NULL;
5428 int lock_data_count = 0;
5429 char *lock_data = NULL;
5430 size_t fixed_portion;
5431 NTSTATUS status = NT_STATUS_OK;
5433 if (!params) {
5434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5435 return;
5438 ZERO_STRUCT(write_time_ts);
5440 if (tran_call == TRANSACT2_QFILEINFO) {
5441 if (total_params < 4) {
5442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5443 return;
5446 if (IS_IPC(conn)) {
5447 call_trans2qpipeinfo(conn, req, tran_call,
5448 pparams, total_params,
5449 ppdata, total_data,
5450 max_data_bytes);
5451 return;
5454 fsp = file_fsp(req, SVAL(params,0));
5455 info_level = SVAL(params,2);
5457 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5459 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5460 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5461 return;
5464 /* Initial check for valid fsp ptr. */
5465 if (!check_fsp_open(conn, req, fsp)) {
5466 return;
5469 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5470 if (smb_fname == NULL) {
5471 reply_nterror(req, NT_STATUS_NO_MEMORY);
5472 return;
5475 if(fsp->fake_file_handle) {
5477 * This is actually for the QUOTA_FAKE_FILE --metze
5480 /* We know this name is ok, it's already passed the checks. */
5482 } else if(fsp->fh->fd == -1) {
5484 * This is actually a QFILEINFO on a directory
5485 * handle (returned from an NT SMB). NT5.0 seems
5486 * to do this call. JRA.
5489 if (INFO_LEVEL_IS_UNIX(info_level)) {
5490 /* Always do lstat for UNIX calls. */
5491 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5492 DEBUG(3,("call_trans2qfilepathinfo: "
5493 "SMB_VFS_LSTAT of %s failed "
5494 "(%s)\n",
5495 smb_fname_str_dbg(smb_fname),
5496 strerror(errno)));
5497 reply_nterror(req,
5498 map_nt_error_from_unix(errno));
5499 return;
5501 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5502 DEBUG(3,("call_trans2qfilepathinfo: "
5503 "SMB_VFS_STAT of %s failed (%s)\n",
5504 smb_fname_str_dbg(smb_fname),
5505 strerror(errno)));
5506 reply_nterror(req,
5507 map_nt_error_from_unix(errno));
5508 return;
5511 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5512 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5513 } else {
5515 * Original code - this is an open file.
5517 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5518 DEBUG(3, ("fstat of %s failed (%s)\n",
5519 fsp_fnum_dbg(fsp), strerror(errno)));
5520 reply_nterror(req,
5521 map_nt_error_from_unix(errno));
5522 return;
5524 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5525 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5528 } else {
5529 uint32_t name_hash;
5530 char *fname = NULL;
5531 uint32_t ucf_flags = 0;
5533 /* qpathinfo */
5534 if (total_params < 7) {
5535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5536 return;
5539 info_level = SVAL(params,0);
5541 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5543 if (INFO_LEVEL_IS_UNIX(info_level)) {
5544 if (!lp_unix_extensions()) {
5545 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5546 return;
5548 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5549 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5550 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5551 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5555 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5556 total_params - 6,
5557 STR_TERMINATE, &status);
5558 if (!NT_STATUS_IS_OK(status)) {
5559 reply_nterror(req, status);
5560 return;
5563 status = filename_convert(req,
5564 conn,
5565 req->flags2 & FLAGS2_DFS_PATHNAMES,
5566 fname,
5567 ucf_flags,
5568 NULL,
5569 &smb_fname);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5572 reply_botherror(req,
5573 NT_STATUS_PATH_NOT_COVERED,
5574 ERRSRV, ERRbadpath);
5575 return;
5577 reply_nterror(req, status);
5578 return;
5581 /* If this is a stream, check if there is a delete_pending. */
5582 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5583 && is_ntfs_stream_smb_fname(smb_fname)) {
5584 struct smb_filename *smb_fname_base;
5586 /* Create an smb_filename with stream_name == NULL. */
5587 smb_fname_base = synthetic_smb_fname(
5588 talloc_tos(), smb_fname->base_name,
5589 NULL, NULL);
5590 if (smb_fname_base == NULL) {
5591 reply_nterror(req, NT_STATUS_NO_MEMORY);
5592 return;
5595 if (INFO_LEVEL_IS_UNIX(info_level)) {
5596 /* Always do lstat for UNIX calls. */
5597 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5598 DEBUG(3,("call_trans2qfilepathinfo: "
5599 "SMB_VFS_LSTAT of %s failed "
5600 "(%s)\n",
5601 smb_fname_str_dbg(smb_fname_base),
5602 strerror(errno)));
5603 TALLOC_FREE(smb_fname_base);
5604 reply_nterror(req,
5605 map_nt_error_from_unix(errno));
5606 return;
5608 } else {
5609 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5610 DEBUG(3,("call_trans2qfilepathinfo: "
5611 "fileinfo of %s failed "
5612 "(%s)\n",
5613 smb_fname_str_dbg(smb_fname_base),
5614 strerror(errno)));
5615 TALLOC_FREE(smb_fname_base);
5616 reply_nterror(req,
5617 map_nt_error_from_unix(errno));
5618 return;
5622 status = file_name_hash(conn,
5623 smb_fname_str_dbg(smb_fname_base),
5624 &name_hash);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 TALLOC_FREE(smb_fname_base);
5627 reply_nterror(req, status);
5628 return;
5631 fileid = vfs_file_id_from_sbuf(conn,
5632 &smb_fname_base->st);
5633 TALLOC_FREE(smb_fname_base);
5634 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5635 if (delete_pending) {
5636 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5637 return;
5641 if (INFO_LEVEL_IS_UNIX(info_level)) {
5642 /* Always do lstat for UNIX calls. */
5643 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5644 DEBUG(3,("call_trans2qfilepathinfo: "
5645 "SMB_VFS_LSTAT of %s failed (%s)\n",
5646 smb_fname_str_dbg(smb_fname),
5647 strerror(errno)));
5648 reply_nterror(req,
5649 map_nt_error_from_unix(errno));
5650 return;
5653 } else {
5654 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5655 DEBUG(3,("call_trans2qfilepathinfo: "
5656 "SMB_VFS_STAT of %s failed (%s)\n",
5657 smb_fname_str_dbg(smb_fname),
5658 strerror(errno)));
5659 reply_nterror(req,
5660 map_nt_error_from_unix(errno));
5661 return;
5665 status = file_name_hash(conn,
5666 smb_fname_str_dbg(smb_fname),
5667 &name_hash);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 reply_nterror(req, status);
5670 return;
5673 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5674 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5675 if (delete_pending) {
5676 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5677 return;
5681 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5682 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5683 fsp_fnum_dbg(fsp),
5684 info_level,tran_call,total_data));
5686 /* Pull out any data sent here before we realloc. */
5687 switch (info_level) {
5688 case SMB_INFO_QUERY_EAS_FROM_LIST:
5690 /* Pull any EA list from the data portion. */
5691 uint32_t ea_size;
5693 if (total_data < 4) {
5694 reply_nterror(
5695 req, NT_STATUS_INVALID_PARAMETER);
5696 return;
5698 ea_size = IVAL(pdata,0);
5700 if (total_data > 0 && ea_size != total_data) {
5701 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5702 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5703 reply_nterror(
5704 req, NT_STATUS_INVALID_PARAMETER);
5705 return;
5708 if (!lp_ea_support(SNUM(conn))) {
5709 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5710 return;
5713 /* Pull out the list of names. */
5714 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5715 if (!ea_list) {
5716 reply_nterror(
5717 req, NT_STATUS_INVALID_PARAMETER);
5718 return;
5720 break;
5723 case SMB_QUERY_POSIX_LOCK:
5725 if (fsp == NULL || fsp->fh->fd == -1) {
5726 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5727 return;
5730 if (total_data != POSIX_LOCK_DATA_SIZE) {
5731 reply_nterror(
5732 req, NT_STATUS_INVALID_PARAMETER);
5733 return;
5736 /* Copy the lock range data. */
5737 lock_data = (char *)talloc_memdup(
5738 req, pdata, total_data);
5739 if (!lock_data) {
5740 reply_nterror(req, NT_STATUS_NO_MEMORY);
5741 return;
5743 lock_data_count = total_data;
5745 default:
5746 break;
5749 *pparams = (char *)SMB_REALLOC(*pparams,2);
5750 if (*pparams == NULL) {
5751 reply_nterror(req, NT_STATUS_NO_MEMORY);
5752 return;
5754 params = *pparams;
5755 SSVAL(params,0,0);
5758 * draft-leach-cifs-v1-spec-02.txt
5759 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5760 * says:
5762 * The requested information is placed in the Data portion of the
5763 * transaction response. For the information levels greater than 0x100,
5764 * the transaction response has 1 parameter word which should be
5765 * ignored by the client.
5767 * However Windows only follows this rule for the IS_NAME_VALID call.
5769 switch (info_level) {
5770 case SMB_INFO_IS_NAME_VALID:
5771 param_size = 0;
5772 break;
5775 if ((info_level & 0xFF00) == 0xFF00) {
5777 * We use levels that start with 0xFF00
5778 * internally to represent SMB2 specific levels
5780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5781 return;
5784 status = smbd_do_qfilepathinfo(conn, req, info_level,
5785 fsp, smb_fname,
5786 delete_pending, write_time_ts,
5787 ea_list,
5788 lock_data_count, lock_data,
5789 req->flags2, max_data_bytes,
5790 &fixed_portion,
5791 ppdata, &data_size);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 reply_nterror(req, status);
5794 return;
5796 if (fixed_portion > max_data_bytes) {
5797 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5798 return;
5801 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5802 max_data_bytes);
5804 return;
5807 /****************************************************************************
5808 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5809 code.
5810 ****************************************************************************/
5812 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5813 connection_struct *conn,
5814 struct smb_request *req,
5815 bool overwrite_if_exists,
5816 const struct smb_filename *smb_fname_old,
5817 struct smb_filename *smb_fname_new)
5819 NTSTATUS status = NT_STATUS_OK;
5821 /* source must already exist. */
5822 if (!VALID_STAT(smb_fname_old->st)) {
5823 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5826 if (VALID_STAT(smb_fname_new->st)) {
5827 if (overwrite_if_exists) {
5828 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5829 return NT_STATUS_FILE_IS_A_DIRECTORY;
5831 status = unlink_internals(conn,
5832 req,
5833 FILE_ATTRIBUTE_NORMAL,
5834 smb_fname_new,
5835 false);
5836 if (!NT_STATUS_IS_OK(status)) {
5837 return status;
5839 } else {
5840 /* Disallow if newname already exists. */
5841 return NT_STATUS_OBJECT_NAME_COLLISION;
5845 /* No links from a directory. */
5846 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5847 return NT_STATUS_FILE_IS_A_DIRECTORY;
5850 /* Setting a hardlink to/from a stream isn't currently supported. */
5851 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5852 is_ntfs_stream_smb_fname(smb_fname_new)) {
5853 return NT_STATUS_INVALID_PARAMETER;
5856 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5857 smb_fname_old->base_name, smb_fname_new->base_name));
5859 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5860 smb_fname_new->base_name) != 0) {
5861 status = map_nt_error_from_unix(errno);
5862 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5863 nt_errstr(status), smb_fname_old->base_name,
5864 smb_fname_new->base_name));
5866 return status;
5869 /****************************************************************************
5870 Deal with setting the time from any of the setfilepathinfo functions.
5871 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5872 calling this function.
5873 ****************************************************************************/
5875 NTSTATUS smb_set_file_time(connection_struct *conn,
5876 files_struct *fsp,
5877 const struct smb_filename *smb_fname,
5878 struct smb_file_time *ft,
5879 bool setting_write_time)
5881 struct smb_filename smb_fname_base;
5882 uint32_t action =
5883 FILE_NOTIFY_CHANGE_LAST_ACCESS
5884 |FILE_NOTIFY_CHANGE_LAST_WRITE
5885 |FILE_NOTIFY_CHANGE_CREATION;
5887 if (!VALID_STAT(smb_fname->st)) {
5888 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5891 /* get some defaults (no modifications) if any info is zero or -1. */
5892 if (null_timespec(ft->create_time)) {
5893 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5896 if (null_timespec(ft->atime)) {
5897 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5900 if (null_timespec(ft->mtime)) {
5901 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5904 if (!setting_write_time) {
5905 /* ft->mtime comes from change time, not write time. */
5906 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5909 /* Ensure the resolution is the correct for
5910 * what we can store on this filesystem. */
5912 round_timespec(conn->ts_res, &ft->create_time);
5913 round_timespec(conn->ts_res, &ft->ctime);
5914 round_timespec(conn->ts_res, &ft->atime);
5915 round_timespec(conn->ts_res, &ft->mtime);
5917 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5918 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5919 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5920 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5921 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5922 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5923 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5924 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5926 if (setting_write_time) {
5928 * This was a Windows setfileinfo on an open file.
5929 * NT does this a lot. We also need to
5930 * set the time here, as it can be read by
5931 * FindFirst/FindNext and with the patch for bug #2045
5932 * in smbd/fileio.c it ensures that this timestamp is
5933 * kept sticky even after a write. We save the request
5934 * away and will set it on file close and after a write. JRA.
5937 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5938 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5940 if (fsp != NULL) {
5941 if (fsp->base_fsp) {
5942 set_sticky_write_time_fsp(fsp->base_fsp,
5943 ft->mtime);
5944 } else {
5945 set_sticky_write_time_fsp(fsp, ft->mtime);
5947 } else {
5948 set_sticky_write_time_path(
5949 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5950 ft->mtime);
5954 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5956 /* Always call ntimes on the base, even if a stream was passed in. */
5957 smb_fname_base = *smb_fname;
5958 smb_fname_base.stream_name = NULL;
5960 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5961 return map_nt_error_from_unix(errno);
5964 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5965 smb_fname->base_name);
5966 return NT_STATUS_OK;
5969 /****************************************************************************
5970 Deal with setting the dosmode from any of the setfilepathinfo functions.
5971 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5972 done before calling this function.
5973 ****************************************************************************/
5975 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5976 const struct smb_filename *smb_fname,
5977 uint32_t dosmode)
5979 struct smb_filename *smb_fname_base;
5980 NTSTATUS status;
5982 if (!VALID_STAT(smb_fname->st)) {
5983 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5986 /* Always operate on the base_name, even if a stream was passed in. */
5987 smb_fname_base = synthetic_smb_fname(
5988 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5989 if (smb_fname_base == NULL) {
5990 return NT_STATUS_NO_MEMORY;
5993 if (dosmode) {
5994 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5995 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5996 } else {
5997 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6001 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6003 /* check the mode isn't different, before changing it */
6004 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6005 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6006 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6007 (unsigned int)dosmode));
6009 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6010 false)) {
6011 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6012 "%s failed (%s)\n",
6013 smb_fname_str_dbg(smb_fname_base),
6014 strerror(errno)));
6015 status = map_nt_error_from_unix(errno);
6016 goto out;
6019 status = NT_STATUS_OK;
6020 out:
6021 TALLOC_FREE(smb_fname_base);
6022 return status;
6025 /****************************************************************************
6026 Deal with setting the size from any of the setfilepathinfo functions.
6027 ****************************************************************************/
6029 static NTSTATUS smb_set_file_size(connection_struct *conn,
6030 struct smb_request *req,
6031 files_struct *fsp,
6032 const struct smb_filename *smb_fname,
6033 const SMB_STRUCT_STAT *psbuf,
6034 off_t size,
6035 bool fail_after_createfile)
6037 NTSTATUS status = NT_STATUS_OK;
6038 struct smb_filename *smb_fname_tmp = NULL;
6039 files_struct *new_fsp = NULL;
6041 if (!VALID_STAT(*psbuf)) {
6042 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6045 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6047 if (size == get_file_size_stat(psbuf)) {
6048 return NT_STATUS_OK;
6051 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6052 smb_fname_str_dbg(smb_fname), (double)size));
6054 if (fsp && fsp->fh->fd != -1) {
6055 /* Handle based call. */
6056 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6057 return NT_STATUS_ACCESS_DENIED;
6060 if (vfs_set_filelen(fsp, size) == -1) {
6061 return map_nt_error_from_unix(errno);
6063 trigger_write_time_update_immediate(fsp);
6064 return NT_STATUS_OK;
6067 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6068 if (smb_fname_tmp == NULL) {
6069 return NT_STATUS_NO_MEMORY;
6072 smb_fname_tmp->st = *psbuf;
6074 status = SMB_VFS_CREATE_FILE(
6075 conn, /* conn */
6076 req, /* req */
6077 0, /* root_dir_fid */
6078 smb_fname_tmp, /* fname */
6079 FILE_WRITE_DATA, /* access_mask */
6080 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6081 FILE_SHARE_DELETE),
6082 FILE_OPEN, /* create_disposition*/
6083 0, /* create_options */
6084 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6085 0, /* oplock_request */
6086 NULL, /* lease */
6087 0, /* allocation_size */
6088 0, /* private_flags */
6089 NULL, /* sd */
6090 NULL, /* ea_list */
6091 &new_fsp, /* result */
6092 NULL, /* pinfo */
6093 NULL, NULL); /* create context */
6095 TALLOC_FREE(smb_fname_tmp);
6097 if (!NT_STATUS_IS_OK(status)) {
6098 /* NB. We check for open_was_deferred in the caller. */
6099 return status;
6102 /* See RAW-SFILEINFO-END-OF-FILE */
6103 if (fail_after_createfile) {
6104 close_file(req, new_fsp,NORMAL_CLOSE);
6105 return NT_STATUS_INVALID_LEVEL;
6108 if (vfs_set_filelen(new_fsp, size) == -1) {
6109 status = map_nt_error_from_unix(errno);
6110 close_file(req, new_fsp,NORMAL_CLOSE);
6111 return status;
6114 trigger_write_time_update_immediate(new_fsp);
6115 close_file(req, new_fsp,NORMAL_CLOSE);
6116 return NT_STATUS_OK;
6119 /****************************************************************************
6120 Deal with SMB_INFO_SET_EA.
6121 ****************************************************************************/
6123 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6124 const char *pdata,
6125 int total_data,
6126 files_struct *fsp,
6127 const struct smb_filename *smb_fname)
6129 struct ea_list *ea_list = NULL;
6130 TALLOC_CTX *ctx = NULL;
6131 NTSTATUS status = NT_STATUS_OK;
6133 if (total_data < 10) {
6135 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6136 length. They seem to have no effect. Bug #3212. JRA */
6138 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6139 /* We're done. We only get EA info in this call. */
6140 return NT_STATUS_OK;
6143 return NT_STATUS_INVALID_PARAMETER;
6146 if (IVAL(pdata,0) > total_data) {
6147 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6148 IVAL(pdata,0), (unsigned int)total_data));
6149 return NT_STATUS_INVALID_PARAMETER;
6152 ctx = talloc_tos();
6153 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6154 if (!ea_list) {
6155 return NT_STATUS_INVALID_PARAMETER;
6158 status = set_ea(conn, fsp, smb_fname, ea_list);
6160 return status;
6163 /****************************************************************************
6164 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6165 ****************************************************************************/
6167 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6168 const char *pdata,
6169 int total_data,
6170 files_struct *fsp)
6172 struct ea_list *ea_list = NULL;
6173 NTSTATUS status;
6175 if (!fsp) {
6176 return NT_STATUS_INVALID_HANDLE;
6179 if (!lp_ea_support(SNUM(conn))) {
6180 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6181 "EA's not supported.\n",
6182 (unsigned int)total_data));
6183 return NT_STATUS_EAS_NOT_SUPPORTED;
6186 if (total_data < 10) {
6187 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6188 "too small.\n",
6189 (unsigned int)total_data));
6190 return NT_STATUS_INVALID_PARAMETER;
6193 ea_list = read_nttrans_ea_list(talloc_tos(),
6194 pdata,
6195 total_data);
6197 if (!ea_list) {
6198 return NT_STATUS_INVALID_PARAMETER;
6201 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6203 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6204 smb_fname_str_dbg(fsp->fsp_name),
6205 nt_errstr(status) ));
6207 return status;
6211 /****************************************************************************
6212 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6213 ****************************************************************************/
6215 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6216 const char *pdata,
6217 int total_data,
6218 files_struct *fsp,
6219 struct smb_filename *smb_fname)
6221 NTSTATUS status = NT_STATUS_OK;
6222 bool delete_on_close;
6223 uint32_t dosmode = 0;
6225 if (total_data < 1) {
6226 return NT_STATUS_INVALID_PARAMETER;
6229 if (fsp == NULL) {
6230 return NT_STATUS_INVALID_HANDLE;
6233 delete_on_close = (CVAL(pdata,0) ? True : False);
6234 dosmode = dos_mode(conn, smb_fname);
6236 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6237 "delete_on_close = %u\n",
6238 smb_fname_str_dbg(smb_fname),
6239 (unsigned int)dosmode,
6240 (unsigned int)delete_on_close ));
6242 if (delete_on_close) {
6243 status = can_set_delete_on_close(fsp, dosmode);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 return status;
6249 /* The set is across all open files on this dev/inode pair. */
6250 if (!set_delete_on_close(fsp, delete_on_close,
6251 conn->session_info->security_token,
6252 conn->session_info->unix_token)) {
6253 return NT_STATUS_ACCESS_DENIED;
6255 return NT_STATUS_OK;
6258 /****************************************************************************
6259 Deal with SMB_FILE_POSITION_INFORMATION.
6260 ****************************************************************************/
6262 static NTSTATUS smb_file_position_information(connection_struct *conn,
6263 const char *pdata,
6264 int total_data,
6265 files_struct *fsp)
6267 uint64_t position_information;
6269 if (total_data < 8) {
6270 return NT_STATUS_INVALID_PARAMETER;
6273 if (fsp == NULL) {
6274 /* Ignore on pathname based set. */
6275 return NT_STATUS_OK;
6278 position_information = (uint64_t)IVAL(pdata,0);
6279 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6281 DEBUG(10,("smb_file_position_information: Set file position "
6282 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6283 (double)position_information));
6284 fsp->fh->position_information = position_information;
6285 return NT_STATUS_OK;
6288 /****************************************************************************
6289 Deal with SMB_FILE_MODE_INFORMATION.
6290 ****************************************************************************/
6292 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6293 const char *pdata,
6294 int total_data)
6296 uint32_t mode;
6298 if (total_data < 4) {
6299 return NT_STATUS_INVALID_PARAMETER;
6301 mode = IVAL(pdata,0);
6302 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6303 return NT_STATUS_INVALID_PARAMETER;
6305 return NT_STATUS_OK;
6308 /****************************************************************************
6309 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6310 ****************************************************************************/
6312 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6313 struct smb_request *req,
6314 const char *pdata,
6315 int total_data,
6316 const struct smb_filename *smb_fname)
6318 char *link_target = NULL;
6319 const char *newname = smb_fname->base_name;
6320 TALLOC_CTX *ctx = talloc_tos();
6322 /* Set a symbolic link. */
6323 /* Don't allow this if follow links is false. */
6325 if (total_data == 0) {
6326 return NT_STATUS_INVALID_PARAMETER;
6329 if (!lp_follow_symlinks(SNUM(conn))) {
6330 return NT_STATUS_ACCESS_DENIED;
6333 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6334 total_data, STR_TERMINATE);
6336 if (!link_target) {
6337 return NT_STATUS_INVALID_PARAMETER;
6340 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6341 newname, link_target ));
6343 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6344 return map_nt_error_from_unix(errno);
6347 return NT_STATUS_OK;
6350 /****************************************************************************
6351 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6352 ****************************************************************************/
6354 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6355 struct smb_request *req,
6356 const char *pdata, int total_data,
6357 struct smb_filename *smb_fname_new)
6359 char *oldname = NULL;
6360 struct smb_filename *smb_fname_old = NULL;
6361 TALLOC_CTX *ctx = talloc_tos();
6362 NTSTATUS status = NT_STATUS_OK;
6364 /* Set a hard link. */
6365 if (total_data == 0) {
6366 return NT_STATUS_INVALID_PARAMETER;
6369 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6370 total_data, STR_TERMINATE, &status);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 return status;
6375 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6376 smb_fname_str_dbg(smb_fname_new), oldname));
6378 status = filename_convert(ctx,
6379 conn,
6380 req->flags2 & FLAGS2_DFS_PATHNAMES,
6381 oldname,
6383 NULL,
6384 &smb_fname_old);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 return status;
6389 return hardlink_internals(ctx, conn, req, false,
6390 smb_fname_old, smb_fname_new);
6393 /****************************************************************************
6394 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6395 ****************************************************************************/
6397 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6398 struct smb_request *req,
6399 const char *pdata,
6400 int total_data,
6401 files_struct *fsp,
6402 struct smb_filename *smb_fname_src)
6404 bool overwrite;
6405 uint32_t len;
6406 char *newname = NULL;
6407 struct smb_filename *smb_fname_dst = NULL;
6408 NTSTATUS status = NT_STATUS_OK;
6409 TALLOC_CTX *ctx = talloc_tos();
6411 if (!fsp) {
6412 return NT_STATUS_INVALID_HANDLE;
6415 if (total_data < 20) {
6416 return NT_STATUS_INVALID_PARAMETER;
6419 overwrite = (CVAL(pdata,0) ? True : False);
6420 len = IVAL(pdata,16);
6422 if (len > (total_data - 20) || (len == 0)) {
6423 return NT_STATUS_INVALID_PARAMETER;
6426 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6427 &pdata[20], len, STR_TERMINATE,
6428 &status);
6429 if (!NT_STATUS_IS_OK(status)) {
6430 return status;
6433 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6434 newname));
6436 status = filename_convert(ctx,
6437 conn,
6438 req->flags2 & FLAGS2_DFS_PATHNAMES,
6439 newname,
6440 UCF_SAVE_LCOMP,
6441 NULL,
6442 &smb_fname_dst);
6443 if (!NT_STATUS_IS_OK(status)) {
6444 return status;
6447 if (fsp->base_fsp) {
6448 /* newname must be a stream name. */
6449 if (newname[0] != ':') {
6450 return NT_STATUS_NOT_SUPPORTED;
6453 /* Create an smb_fname to call rename_internals_fsp() with. */
6454 smb_fname_dst = synthetic_smb_fname(
6455 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6456 newname, NULL);
6457 if (smb_fname_dst == NULL) {
6458 status = NT_STATUS_NO_MEMORY;
6459 goto out;
6463 * Set the original last component, since
6464 * rename_internals_fsp() requires it.
6466 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6467 newname);
6468 if (smb_fname_dst->original_lcomp == NULL) {
6469 status = NT_STATUS_NO_MEMORY;
6470 goto out;
6475 DEBUG(10,("smb2_file_rename_information: "
6476 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6477 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6478 smb_fname_str_dbg(smb_fname_dst)));
6479 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6480 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6481 overwrite);
6483 out:
6484 TALLOC_FREE(smb_fname_dst);
6485 return status;
6488 static NTSTATUS smb_file_link_information(connection_struct *conn,
6489 struct smb_request *req,
6490 const char *pdata,
6491 int total_data,
6492 files_struct *fsp,
6493 struct smb_filename *smb_fname_src)
6495 bool overwrite;
6496 uint32_t len;
6497 char *newname = NULL;
6498 struct smb_filename *smb_fname_dst = NULL;
6499 NTSTATUS status = NT_STATUS_OK;
6500 TALLOC_CTX *ctx = talloc_tos();
6502 if (!fsp) {
6503 return NT_STATUS_INVALID_HANDLE;
6506 if (total_data < 20) {
6507 return NT_STATUS_INVALID_PARAMETER;
6510 overwrite = (CVAL(pdata,0) ? true : false);
6511 len = IVAL(pdata,16);
6513 if (len > (total_data - 20) || (len == 0)) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6518 &pdata[20], len, STR_TERMINATE,
6519 &status);
6520 if (!NT_STATUS_IS_OK(status)) {
6521 return status;
6524 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6525 newname));
6527 status = filename_convert(ctx,
6528 conn,
6529 req->flags2 & FLAGS2_DFS_PATHNAMES,
6530 newname,
6531 UCF_SAVE_LCOMP,
6532 NULL,
6533 &smb_fname_dst);
6534 if (!NT_STATUS_IS_OK(status)) {
6535 return status;
6538 if (fsp->base_fsp) {
6539 /* No stream names. */
6540 return NT_STATUS_NOT_SUPPORTED;
6543 DEBUG(10,("smb_file_link_information: "
6544 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6545 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6546 smb_fname_str_dbg(smb_fname_dst)));
6547 status = hardlink_internals(ctx,
6548 conn,
6549 req,
6550 overwrite,
6551 fsp->fsp_name,
6552 smb_fname_dst);
6554 TALLOC_FREE(smb_fname_dst);
6555 return status;
6558 /****************************************************************************
6559 Deal with SMB_FILE_RENAME_INFORMATION.
6560 ****************************************************************************/
6562 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6563 struct smb_request *req,
6564 const char *pdata,
6565 int total_data,
6566 files_struct *fsp,
6567 struct smb_filename *smb_fname_src)
6569 bool overwrite;
6570 uint32_t root_fid;
6571 uint32_t len;
6572 char *newname = NULL;
6573 struct smb_filename *smb_fname_dst = NULL;
6574 bool dest_has_wcard = False;
6575 NTSTATUS status = NT_STATUS_OK;
6576 char *p;
6577 TALLOC_CTX *ctx = talloc_tos();
6579 if (total_data < 13) {
6580 return NT_STATUS_INVALID_PARAMETER;
6583 overwrite = (CVAL(pdata,0) ? True : False);
6584 root_fid = IVAL(pdata,4);
6585 len = IVAL(pdata,8);
6587 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6588 return NT_STATUS_INVALID_PARAMETER;
6591 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6592 len, 0, &status,
6593 &dest_has_wcard);
6594 if (!NT_STATUS_IS_OK(status)) {
6595 return status;
6598 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6599 newname));
6601 status = resolve_dfspath_wcard(ctx, conn,
6602 req->flags2 & FLAGS2_DFS_PATHNAMES,
6603 newname,
6604 true,
6605 !conn->sconn->using_smb2,
6606 &newname,
6607 &dest_has_wcard);
6608 if (!NT_STATUS_IS_OK(status)) {
6609 return status;
6612 /* Check the new name has no '/' characters. */
6613 if (strchr_m(newname, '/')) {
6614 return NT_STATUS_NOT_SUPPORTED;
6617 if (fsp && fsp->base_fsp) {
6618 /* newname must be a stream name. */
6619 if (newname[0] != ':') {
6620 return NT_STATUS_NOT_SUPPORTED;
6623 /* Create an smb_fname to call rename_internals_fsp() with. */
6624 smb_fname_dst = synthetic_smb_fname(
6625 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6626 newname, NULL);
6627 if (smb_fname_dst == NULL) {
6628 status = NT_STATUS_NO_MEMORY;
6629 goto out;
6633 * Set the original last component, since
6634 * rename_internals_fsp() requires it.
6636 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6637 newname);
6638 if (smb_fname_dst->original_lcomp == NULL) {
6639 status = NT_STATUS_NO_MEMORY;
6640 goto out;
6643 } else {
6645 * Build up an smb_fname_dst based on the filename passed in.
6646 * We basically just strip off the last component, and put on
6647 * the newname instead.
6649 char *base_name = NULL;
6651 /* newname must *not* be a stream name. */
6652 if (newname[0] == ':') {
6653 return NT_STATUS_NOT_SUPPORTED;
6657 * Strip off the last component (filename) of the path passed
6658 * in.
6660 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6661 if (!base_name) {
6662 return NT_STATUS_NO_MEMORY;
6664 p = strrchr_m(base_name, '/');
6665 if (p) {
6666 p[1] = '\0';
6667 } else {
6668 base_name = talloc_strdup(ctx, "");
6669 if (!base_name) {
6670 return NT_STATUS_NO_MEMORY;
6673 /* Append the new name. */
6674 base_name = talloc_asprintf_append(base_name,
6675 "%s",
6676 newname);
6677 if (!base_name) {
6678 return NT_STATUS_NO_MEMORY;
6681 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6682 (UCF_SAVE_LCOMP |
6683 (dest_has_wcard ?
6684 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6685 0)));
6687 /* If an error we expect this to be
6688 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6690 if (!NT_STATUS_IS_OK(status)) {
6691 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6692 status)) {
6693 goto out;
6695 /* Create an smb_fname to call rename_internals_fsp() */
6696 smb_fname_dst = synthetic_smb_fname(
6697 ctx, base_name, NULL, NULL);
6698 if (smb_fname_dst == NULL) {
6699 status = NT_STATUS_NO_MEMORY;
6700 goto out;
6705 if (fsp) {
6706 DEBUG(10,("smb_file_rename_information: "
6707 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6708 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6709 smb_fname_str_dbg(smb_fname_dst)));
6710 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6711 overwrite);
6712 } else {
6713 DEBUG(10,("smb_file_rename_information: "
6714 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6715 smb_fname_str_dbg(smb_fname_src),
6716 smb_fname_str_dbg(smb_fname_dst)));
6717 status = rename_internals(ctx, conn, req, smb_fname_src,
6718 smb_fname_dst, 0, overwrite, false,
6719 dest_has_wcard,
6720 FILE_WRITE_ATTRIBUTES);
6722 out:
6723 TALLOC_FREE(smb_fname_dst);
6724 return status;
6727 /****************************************************************************
6728 Deal with SMB_SET_POSIX_ACL.
6729 ****************************************************************************/
6731 #if defined(HAVE_POSIX_ACLS)
6732 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6733 const char *pdata,
6734 int total_data,
6735 files_struct *fsp,
6736 const struct smb_filename *smb_fname)
6738 uint16_t posix_acl_version;
6739 uint16_t num_file_acls;
6740 uint16_t num_def_acls;
6741 bool valid_file_acls = True;
6742 bool valid_def_acls = True;
6744 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6745 return NT_STATUS_INVALID_PARAMETER;
6747 posix_acl_version = SVAL(pdata,0);
6748 num_file_acls = SVAL(pdata,2);
6749 num_def_acls = SVAL(pdata,4);
6751 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6752 valid_file_acls = False;
6753 num_file_acls = 0;
6756 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6757 valid_def_acls = False;
6758 num_def_acls = 0;
6761 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6762 return NT_STATUS_INVALID_PARAMETER;
6765 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6766 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6767 return NT_STATUS_INVALID_PARAMETER;
6770 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6771 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6772 (unsigned int)num_file_acls,
6773 (unsigned int)num_def_acls));
6775 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6776 smb_fname->base_name, num_file_acls,
6777 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6778 return map_nt_error_from_unix(errno);
6781 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6782 smb_fname->base_name, &smb_fname->st, num_def_acls,
6783 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6784 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6785 return map_nt_error_from_unix(errno);
6787 return NT_STATUS_OK;
6789 #endif
6791 /****************************************************************************
6792 Deal with SMB_SET_POSIX_LOCK.
6793 ****************************************************************************/
6795 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6796 struct smb_request *req,
6797 const char *pdata,
6798 int total_data,
6799 files_struct *fsp)
6801 uint64_t count;
6802 uint64_t offset;
6803 uint64_t smblctx;
6804 bool blocking_lock = False;
6805 enum brl_type lock_type;
6807 NTSTATUS status = NT_STATUS_OK;
6809 if (fsp == NULL || fsp->fh->fd == -1) {
6810 return NT_STATUS_INVALID_HANDLE;
6813 if (total_data != POSIX_LOCK_DATA_SIZE) {
6814 return NT_STATUS_INVALID_PARAMETER;
6817 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6818 case POSIX_LOCK_TYPE_READ:
6819 lock_type = READ_LOCK;
6820 break;
6821 case POSIX_LOCK_TYPE_WRITE:
6822 /* Return the right POSIX-mappable error code for files opened read-only. */
6823 if (!fsp->can_write) {
6824 return NT_STATUS_INVALID_HANDLE;
6826 lock_type = WRITE_LOCK;
6827 break;
6828 case POSIX_LOCK_TYPE_UNLOCK:
6829 lock_type = UNLOCK_LOCK;
6830 break;
6831 default:
6832 return NT_STATUS_INVALID_PARAMETER;
6835 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6836 blocking_lock = False;
6837 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6838 blocking_lock = True;
6839 } else {
6840 return NT_STATUS_INVALID_PARAMETER;
6843 if (!lp_blocking_locks(SNUM(conn))) {
6844 blocking_lock = False;
6847 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6848 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6849 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6850 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6851 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6853 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6854 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6855 fsp_str_dbg(fsp),
6856 (unsigned int)lock_type,
6857 (unsigned long long)smblctx,
6858 (double)count,
6859 (double)offset ));
6861 if (lock_type == UNLOCK_LOCK) {
6862 status = do_unlock(req->sconn->msg_ctx,
6863 fsp,
6864 smblctx,
6865 count,
6866 offset,
6867 POSIX_LOCK);
6868 } else {
6869 uint64_t block_smblctx;
6871 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6872 fsp,
6873 smblctx,
6874 count,
6875 offset,
6876 lock_type,
6877 POSIX_LOCK,
6878 blocking_lock,
6879 &status,
6880 &block_smblctx);
6882 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6884 * A blocking lock was requested. Package up
6885 * this smb into a queued request and push it
6886 * onto the blocking lock queue.
6888 if(push_blocking_lock_request(br_lck,
6889 req,
6890 fsp,
6891 -1, /* infinite timeout. */
6893 smblctx,
6894 lock_type,
6895 POSIX_LOCK,
6896 offset,
6897 count,
6898 block_smblctx)) {
6899 TALLOC_FREE(br_lck);
6900 return status;
6903 TALLOC_FREE(br_lck);
6906 return status;
6909 /****************************************************************************
6910 Deal with SMB_SET_FILE_BASIC_INFO.
6911 ****************************************************************************/
6913 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6914 const char *pdata,
6915 int total_data,
6916 files_struct *fsp,
6917 const struct smb_filename *smb_fname)
6919 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6920 struct smb_file_time ft;
6921 uint32_t dosmode = 0;
6922 NTSTATUS status = NT_STATUS_OK;
6924 ZERO_STRUCT(ft);
6926 if (total_data < 36) {
6927 return NT_STATUS_INVALID_PARAMETER;
6930 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 return status;
6935 /* Set the attributes */
6936 dosmode = IVAL(pdata,32);
6937 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 return status;
6942 /* create time */
6943 ft.create_time = interpret_long_date(pdata);
6945 /* access time */
6946 ft.atime = interpret_long_date(pdata+8);
6948 /* write time. */
6949 ft.mtime = interpret_long_date(pdata+16);
6951 /* change time. */
6952 ft.ctime = interpret_long_date(pdata+24);
6954 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6955 smb_fname_str_dbg(smb_fname)));
6957 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6958 true);
6961 /****************************************************************************
6962 Deal with SMB_INFO_STANDARD.
6963 ****************************************************************************/
6965 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6966 const char *pdata,
6967 int total_data,
6968 files_struct *fsp,
6969 const struct smb_filename *smb_fname)
6971 NTSTATUS status;
6972 struct smb_file_time ft;
6974 ZERO_STRUCT(ft);
6976 if (total_data < 12) {
6977 return NT_STATUS_INVALID_PARAMETER;
6980 /* create time */
6981 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6982 /* access time */
6983 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6984 /* write time */
6985 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6987 DEBUG(10,("smb_set_info_standard: file %s\n",
6988 smb_fname_str_dbg(smb_fname)));
6990 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6991 if (!NT_STATUS_IS_OK(status)) {
6992 return status;
6995 return smb_set_file_time(conn,
6996 fsp,
6997 smb_fname,
6998 &ft,
6999 true);
7002 /****************************************************************************
7003 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7004 ****************************************************************************/
7006 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7007 struct smb_request *req,
7008 const char *pdata,
7009 int total_data,
7010 files_struct *fsp,
7011 struct smb_filename *smb_fname)
7013 uint64_t allocation_size = 0;
7014 NTSTATUS status = NT_STATUS_OK;
7015 files_struct *new_fsp = NULL;
7017 if (!VALID_STAT(smb_fname->st)) {
7018 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7021 if (total_data < 8) {
7022 return NT_STATUS_INVALID_PARAMETER;
7025 allocation_size = (uint64_t)IVAL(pdata,0);
7026 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7027 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7028 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7029 (double)allocation_size));
7031 if (allocation_size) {
7032 allocation_size = smb_roundup(conn, allocation_size);
7035 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7036 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7037 (double)allocation_size));
7039 if (fsp && fsp->fh->fd != -1) {
7040 /* Open file handle. */
7041 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7042 return NT_STATUS_ACCESS_DENIED;
7045 /* Only change if needed. */
7046 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7047 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7048 return map_nt_error_from_unix(errno);
7051 /* But always update the time. */
7053 * This is equivalent to a write. Ensure it's seen immediately
7054 * if there are no pending writes.
7056 trigger_write_time_update_immediate(fsp);
7057 return NT_STATUS_OK;
7060 /* Pathname or stat or directory file. */
7061 status = SMB_VFS_CREATE_FILE(
7062 conn, /* conn */
7063 req, /* req */
7064 0, /* root_dir_fid */
7065 smb_fname, /* fname */
7066 FILE_WRITE_DATA, /* access_mask */
7067 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7068 FILE_SHARE_DELETE),
7069 FILE_OPEN, /* create_disposition*/
7070 0, /* create_options */
7071 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7072 0, /* oplock_request */
7073 NULL, /* lease */
7074 0, /* allocation_size */
7075 0, /* private_flags */
7076 NULL, /* sd */
7077 NULL, /* ea_list */
7078 &new_fsp, /* result */
7079 NULL, /* pinfo */
7080 NULL, NULL); /* create context */
7082 if (!NT_STATUS_IS_OK(status)) {
7083 /* NB. We check for open_was_deferred in the caller. */
7084 return status;
7087 /* Only change if needed. */
7088 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7089 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7090 status = map_nt_error_from_unix(errno);
7091 close_file(req, new_fsp, NORMAL_CLOSE);
7092 return status;
7096 /* Changing the allocation size should set the last mod time. */
7098 * This is equivalent to a write. Ensure it's seen immediately
7099 * if there are no pending writes.
7101 trigger_write_time_update_immediate(new_fsp);
7102 close_file(req, new_fsp, NORMAL_CLOSE);
7103 return NT_STATUS_OK;
7106 /****************************************************************************
7107 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7108 ****************************************************************************/
7110 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7111 struct smb_request *req,
7112 const char *pdata,
7113 int total_data,
7114 files_struct *fsp,
7115 const struct smb_filename *smb_fname,
7116 bool fail_after_createfile)
7118 off_t size;
7120 if (total_data < 8) {
7121 return NT_STATUS_INVALID_PARAMETER;
7124 size = IVAL(pdata,0);
7125 size |= (((off_t)IVAL(pdata,4)) << 32);
7126 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7127 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7128 (double)size));
7130 return smb_set_file_size(conn, req,
7131 fsp,
7132 smb_fname,
7133 &smb_fname->st,
7134 size,
7135 fail_after_createfile);
7138 /****************************************************************************
7139 Allow a UNIX info mknod.
7140 ****************************************************************************/
7142 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7143 const char *pdata,
7144 int total_data,
7145 const struct smb_filename *smb_fname)
7147 uint32_t file_type = IVAL(pdata,56);
7148 #if defined(HAVE_MAKEDEV)
7149 uint32_t dev_major = IVAL(pdata,60);
7150 uint32_t dev_minor = IVAL(pdata,68);
7151 #endif
7152 SMB_DEV_T dev = (SMB_DEV_T)0;
7153 uint32_t raw_unixmode = IVAL(pdata,84);
7154 NTSTATUS status;
7155 mode_t unixmode;
7157 if (total_data < 100) {
7158 return NT_STATUS_INVALID_PARAMETER;
7161 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7162 PERM_NEW_FILE, &unixmode);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 return status;
7167 #if defined(HAVE_MAKEDEV)
7168 dev = makedev(dev_major, dev_minor);
7169 #endif
7171 switch (file_type) {
7172 #if defined(S_IFIFO)
7173 case UNIX_TYPE_FIFO:
7174 unixmode |= S_IFIFO;
7175 break;
7176 #endif
7177 #if defined(S_IFSOCK)
7178 case UNIX_TYPE_SOCKET:
7179 unixmode |= S_IFSOCK;
7180 break;
7181 #endif
7182 #if defined(S_IFCHR)
7183 case UNIX_TYPE_CHARDEV:
7184 unixmode |= S_IFCHR;
7185 break;
7186 #endif
7187 #if defined(S_IFBLK)
7188 case UNIX_TYPE_BLKDEV:
7189 unixmode |= S_IFBLK;
7190 break;
7191 #endif
7192 default:
7193 return NT_STATUS_INVALID_PARAMETER;
7196 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7197 "%.0f mode 0%o for file %s\n", (double)dev,
7198 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7200 /* Ok - do the mknod. */
7201 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7202 return map_nt_error_from_unix(errno);
7205 /* If any of the other "set" calls fail we
7206 * don't want to end up with a half-constructed mknod.
7209 if (lp_inherit_permissions(SNUM(conn))) {
7210 char *parent;
7211 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7212 &parent, NULL)) {
7213 return NT_STATUS_NO_MEMORY;
7215 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7216 unixmode);
7217 TALLOC_FREE(parent);
7220 return NT_STATUS_OK;
7223 /****************************************************************************
7224 Deal with SMB_SET_FILE_UNIX_BASIC.
7225 ****************************************************************************/
7227 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7228 struct smb_request *req,
7229 const char *pdata,
7230 int total_data,
7231 files_struct *fsp,
7232 const struct smb_filename *smb_fname)
7234 struct smb_file_time ft;
7235 uint32_t raw_unixmode;
7236 mode_t unixmode;
7237 off_t size = 0;
7238 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7239 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7240 NTSTATUS status = NT_STATUS_OK;
7241 bool delete_on_fail = False;
7242 enum perm_type ptype;
7243 files_struct *all_fsps = NULL;
7244 bool modify_mtime = true;
7245 struct file_id id;
7246 struct smb_filename *smb_fname_tmp = NULL;
7247 SMB_STRUCT_STAT sbuf;
7249 ZERO_STRUCT(ft);
7251 if (total_data < 100) {
7252 return NT_STATUS_INVALID_PARAMETER;
7255 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7256 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7257 size=IVAL(pdata,0); /* first 8 Bytes are size */
7258 size |= (((off_t)IVAL(pdata,4)) << 32);
7261 ft.atime = interpret_long_date(pdata+24); /* access_time */
7262 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7263 set_owner = (uid_t)IVAL(pdata,40);
7264 set_grp = (gid_t)IVAL(pdata,48);
7265 raw_unixmode = IVAL(pdata,84);
7267 if (VALID_STAT(smb_fname->st)) {
7268 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7269 ptype = PERM_EXISTING_DIR;
7270 } else {
7271 ptype = PERM_EXISTING_FILE;
7273 } else {
7274 ptype = PERM_NEW_FILE;
7277 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7278 ptype, &unixmode);
7279 if (!NT_STATUS_IS_OK(status)) {
7280 return status;
7283 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7284 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7285 smb_fname_str_dbg(smb_fname), (double)size,
7286 (unsigned int)set_owner, (unsigned int)set_grp,
7287 (int)raw_unixmode));
7289 sbuf = smb_fname->st;
7291 if (!VALID_STAT(sbuf)) {
7293 * The only valid use of this is to create character and block
7294 * devices, and named pipes. This is deprecated (IMHO) and
7295 * a new info level should be used for mknod. JRA.
7298 status = smb_unix_mknod(conn,
7299 pdata,
7300 total_data,
7301 smb_fname);
7302 if (!NT_STATUS_IS_OK(status)) {
7303 return status;
7306 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7307 if (smb_fname_tmp == NULL) {
7308 return NT_STATUS_NO_MEMORY;
7311 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7312 status = map_nt_error_from_unix(errno);
7313 TALLOC_FREE(smb_fname_tmp);
7314 SMB_VFS_UNLINK(conn, smb_fname);
7315 return status;
7318 sbuf = smb_fname_tmp->st;
7319 smb_fname = smb_fname_tmp;
7321 /* Ensure we don't try and change anything else. */
7322 raw_unixmode = SMB_MODE_NO_CHANGE;
7323 size = get_file_size_stat(&sbuf);
7324 ft.atime = sbuf.st_ex_atime;
7325 ft.mtime = sbuf.st_ex_mtime;
7327 * We continue here as we might want to change the
7328 * owner uid/gid.
7330 delete_on_fail = True;
7333 #if 1
7334 /* Horrible backwards compatibility hack as an old server bug
7335 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7336 * */
7338 if (!size) {
7339 size = get_file_size_stat(&sbuf);
7341 #endif
7344 * Deal with the UNIX specific mode set.
7347 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7348 int ret;
7350 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7351 "setting mode 0%o for file %s\n",
7352 (unsigned int)unixmode,
7353 smb_fname_str_dbg(smb_fname)));
7354 if (fsp && fsp->fh->fd != -1) {
7355 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7356 } else {
7357 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7359 if (ret != 0) {
7360 return map_nt_error_from_unix(errno);
7365 * Deal with the UNIX specific uid set.
7368 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7369 (sbuf.st_ex_uid != set_owner)) {
7370 int ret;
7372 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7373 "changing owner %u for path %s\n",
7374 (unsigned int)set_owner,
7375 smb_fname_str_dbg(smb_fname)));
7377 if (fsp && fsp->fh->fd != -1) {
7378 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7379 } else {
7381 * UNIX extensions calls must always operate
7382 * on symlinks.
7384 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7385 set_owner, (gid_t)-1);
7388 if (ret != 0) {
7389 status = map_nt_error_from_unix(errno);
7390 if (delete_on_fail) {
7391 SMB_VFS_UNLINK(conn, smb_fname);
7393 return status;
7398 * Deal with the UNIX specific gid set.
7401 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7402 (sbuf.st_ex_gid != set_grp)) {
7403 int ret;
7405 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7406 "changing group %u for file %s\n",
7407 (unsigned int)set_owner,
7408 smb_fname_str_dbg(smb_fname)));
7409 if (fsp && fsp->fh->fd != -1) {
7410 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7411 } else {
7413 * UNIX extensions calls must always operate
7414 * on symlinks.
7416 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7417 set_grp);
7419 if (ret != 0) {
7420 status = map_nt_error_from_unix(errno);
7421 if (delete_on_fail) {
7422 SMB_VFS_UNLINK(conn, smb_fname);
7424 return status;
7428 /* Deal with any size changes. */
7430 status = smb_set_file_size(conn, req,
7431 fsp,
7432 smb_fname,
7433 &sbuf,
7434 size,
7435 false);
7436 if (!NT_STATUS_IS_OK(status)) {
7437 return status;
7440 /* Deal with any time changes. */
7441 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7442 /* No change, don't cancel anything. */
7443 return status;
7446 id = vfs_file_id_from_sbuf(conn, &sbuf);
7447 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7448 all_fsps = file_find_di_next(all_fsps)) {
7450 * We're setting the time explicitly for UNIX.
7451 * Cancel any pending changes over all handles.
7453 all_fsps->update_write_time_on_close = false;
7454 TALLOC_FREE(all_fsps->update_write_time_event);
7458 * Override the "setting_write_time"
7459 * parameter here as it almost does what
7460 * we need. Just remember if we modified
7461 * mtime and send the notify ourselves.
7463 if (null_timespec(ft.mtime)) {
7464 modify_mtime = false;
7467 status = smb_set_file_time(conn,
7468 fsp,
7469 smb_fname,
7470 &ft,
7471 false);
7472 if (modify_mtime) {
7473 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7474 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7476 return status;
7479 /****************************************************************************
7480 Deal with SMB_SET_FILE_UNIX_INFO2.
7481 ****************************************************************************/
7483 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7484 struct smb_request *req,
7485 const char *pdata,
7486 int total_data,
7487 files_struct *fsp,
7488 const struct smb_filename *smb_fname)
7490 NTSTATUS status;
7491 uint32_t smb_fflags;
7492 uint32_t smb_fmask;
7494 if (total_data < 116) {
7495 return NT_STATUS_INVALID_PARAMETER;
7498 /* Start by setting all the fields that are common between UNIX_BASIC
7499 * and UNIX_INFO2.
7501 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7502 fsp, smb_fname);
7503 if (!NT_STATUS_IS_OK(status)) {
7504 return status;
7507 smb_fflags = IVAL(pdata, 108);
7508 smb_fmask = IVAL(pdata, 112);
7510 /* NB: We should only attempt to alter the file flags if the client
7511 * sends a non-zero mask.
7513 if (smb_fmask != 0) {
7514 int stat_fflags = 0;
7516 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7517 smb_fmask, &stat_fflags)) {
7518 /* Client asked to alter a flag we don't understand. */
7519 return NT_STATUS_INVALID_PARAMETER;
7522 if (fsp && fsp->fh->fd != -1) {
7523 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7524 return NT_STATUS_NOT_SUPPORTED;
7525 } else {
7526 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7527 stat_fflags) != 0) {
7528 return map_nt_error_from_unix(errno);
7533 /* XXX: need to add support for changing the create_time here. You
7534 * can do this for paths on Darwin with setattrlist(2). The right way
7535 * to hook this up is probably by extending the VFS utimes interface.
7538 return NT_STATUS_OK;
7541 /****************************************************************************
7542 Create a directory with POSIX semantics.
7543 ****************************************************************************/
7545 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7546 struct smb_request *req,
7547 char **ppdata,
7548 int total_data,
7549 struct smb_filename *smb_fname,
7550 int *pdata_return_size)
7552 NTSTATUS status = NT_STATUS_OK;
7553 uint32_t raw_unixmode = 0;
7554 uint32_t mod_unixmode = 0;
7555 mode_t unixmode = (mode_t)0;
7556 files_struct *fsp = NULL;
7557 uint16_t info_level_return = 0;
7558 int info;
7559 char *pdata = *ppdata;
7561 if (total_data < 18) {
7562 return NT_STATUS_INVALID_PARAMETER;
7565 raw_unixmode = IVAL(pdata,8);
7566 /* Next 4 bytes are not yet defined. */
7568 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7569 PERM_NEW_DIR, &unixmode);
7570 if (!NT_STATUS_IS_OK(status)) {
7571 return status;
7574 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7576 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7577 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7579 status = SMB_VFS_CREATE_FILE(
7580 conn, /* conn */
7581 req, /* req */
7582 0, /* root_dir_fid */
7583 smb_fname, /* fname */
7584 FILE_READ_ATTRIBUTES, /* access_mask */
7585 FILE_SHARE_NONE, /* share_access */
7586 FILE_CREATE, /* create_disposition*/
7587 FILE_DIRECTORY_FILE, /* create_options */
7588 mod_unixmode, /* file_attributes */
7589 0, /* oplock_request */
7590 NULL, /* lease */
7591 0, /* allocation_size */
7592 0, /* private_flags */
7593 NULL, /* sd */
7594 NULL, /* ea_list */
7595 &fsp, /* result */
7596 &info, /* pinfo */
7597 NULL, NULL); /* create context */
7599 if (NT_STATUS_IS_OK(status)) {
7600 close_file(req, fsp, NORMAL_CLOSE);
7603 info_level_return = SVAL(pdata,16);
7605 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7606 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7607 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7608 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7609 } else {
7610 *pdata_return_size = 12;
7613 /* Realloc the data size */
7614 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7615 if (*ppdata == NULL) {
7616 *pdata_return_size = 0;
7617 return NT_STATUS_NO_MEMORY;
7619 pdata = *ppdata;
7621 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7622 SSVAL(pdata,2,0); /* No fnum. */
7623 SIVAL(pdata,4,info); /* Was directory created. */
7625 switch (info_level_return) {
7626 case SMB_QUERY_FILE_UNIX_BASIC:
7627 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7628 SSVAL(pdata,10,0); /* Padding. */
7629 store_file_unix_basic(conn, pdata + 12, fsp,
7630 &smb_fname->st);
7631 break;
7632 case SMB_QUERY_FILE_UNIX_INFO2:
7633 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7634 SSVAL(pdata,10,0); /* Padding. */
7635 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7636 &smb_fname->st);
7637 break;
7638 default:
7639 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7640 SSVAL(pdata,10,0); /* Padding. */
7641 break;
7644 return status;
7647 /****************************************************************************
7648 Open/Create a file with POSIX semantics.
7649 ****************************************************************************/
7651 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7652 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7654 static NTSTATUS smb_posix_open(connection_struct *conn,
7655 struct smb_request *req,
7656 char **ppdata,
7657 int total_data,
7658 struct smb_filename *smb_fname,
7659 int *pdata_return_size)
7661 bool extended_oplock_granted = False;
7662 char *pdata = *ppdata;
7663 uint32_t flags = 0;
7664 uint32_t wire_open_mode = 0;
7665 uint32_t raw_unixmode = 0;
7666 uint32_t mod_unixmode = 0;
7667 uint32_t create_disp = 0;
7668 uint32_t access_mask = 0;
7669 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7670 NTSTATUS status = NT_STATUS_OK;
7671 mode_t unixmode = (mode_t)0;
7672 files_struct *fsp = NULL;
7673 int oplock_request = 0;
7674 int info = 0;
7675 uint16_t info_level_return = 0;
7677 if (total_data < 18) {
7678 return NT_STATUS_INVALID_PARAMETER;
7681 flags = IVAL(pdata,0);
7682 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7683 if (oplock_request) {
7684 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7687 wire_open_mode = IVAL(pdata,4);
7689 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7690 return smb_posix_mkdir(conn, req,
7691 ppdata,
7692 total_data,
7693 smb_fname,
7694 pdata_return_size);
7697 switch (wire_open_mode & SMB_ACCMODE) {
7698 case SMB_O_RDONLY:
7699 access_mask = SMB_O_RDONLY_MAPPING;
7700 break;
7701 case SMB_O_WRONLY:
7702 access_mask = SMB_O_WRONLY_MAPPING;
7703 break;
7704 case SMB_O_RDWR:
7705 access_mask = (SMB_O_RDONLY_MAPPING|
7706 SMB_O_WRONLY_MAPPING);
7707 break;
7708 default:
7709 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7710 (unsigned int)wire_open_mode ));
7711 return NT_STATUS_INVALID_PARAMETER;
7714 wire_open_mode &= ~SMB_ACCMODE;
7716 /* First take care of O_CREAT|O_EXCL interactions. */
7717 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7718 case (SMB_O_CREAT | SMB_O_EXCL):
7719 /* File exists fail. File not exist create. */
7720 create_disp = FILE_CREATE;
7721 break;
7722 case SMB_O_CREAT:
7723 /* File exists open. File not exist create. */
7724 create_disp = FILE_OPEN_IF;
7725 break;
7726 case SMB_O_EXCL:
7727 /* O_EXCL on its own without O_CREAT is undefined.
7728 We deliberately ignore it as some versions of
7729 Linux CIFSFS can send a bare O_EXCL on the
7730 wire which other filesystems in the kernel
7731 ignore. See bug 9519 for details. */
7733 /* Fallthrough. */
7735 case 0:
7736 /* File exists open. File not exist fail. */
7737 create_disp = FILE_OPEN;
7738 break;
7739 default:
7740 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7741 (unsigned int)wire_open_mode ));
7742 return NT_STATUS_INVALID_PARAMETER;
7745 /* Next factor in the effects of O_TRUNC. */
7746 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7748 if (wire_open_mode & SMB_O_TRUNC) {
7749 switch (create_disp) {
7750 case FILE_CREATE:
7751 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7752 /* Leave create_disp alone as
7753 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7755 /* File exists fail. File not exist create. */
7756 break;
7757 case FILE_OPEN_IF:
7758 /* SMB_O_CREAT | SMB_O_TRUNC */
7759 /* File exists overwrite. File not exist create. */
7760 create_disp = FILE_OVERWRITE_IF;
7761 break;
7762 case FILE_OPEN:
7763 /* SMB_O_TRUNC */
7764 /* File exists overwrite. File not exist fail. */
7765 create_disp = FILE_OVERWRITE;
7766 break;
7767 default:
7768 /* Cannot get here. */
7769 smb_panic("smb_posix_open: logic error");
7770 return NT_STATUS_INVALID_PARAMETER;
7774 raw_unixmode = IVAL(pdata,8);
7775 /* Next 4 bytes are not yet defined. */
7777 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7778 (VALID_STAT(smb_fname->st) ?
7779 PERM_EXISTING_FILE : PERM_NEW_FILE),
7780 &unixmode);
7782 if (!NT_STATUS_IS_OK(status)) {
7783 return status;
7786 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7788 if (wire_open_mode & SMB_O_SYNC) {
7789 create_options |= FILE_WRITE_THROUGH;
7791 if (wire_open_mode & SMB_O_APPEND) {
7792 access_mask |= FILE_APPEND_DATA;
7794 if (wire_open_mode & SMB_O_DIRECT) {
7795 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7798 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7799 VALID_STAT_OF_DIR(smb_fname->st)) {
7800 if (access_mask != SMB_O_RDONLY_MAPPING) {
7801 return NT_STATUS_FILE_IS_A_DIRECTORY;
7803 create_options &= ~FILE_NON_DIRECTORY_FILE;
7804 create_options |= FILE_DIRECTORY_FILE;
7807 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7808 smb_fname_str_dbg(smb_fname),
7809 (unsigned int)wire_open_mode,
7810 (unsigned int)unixmode ));
7812 status = SMB_VFS_CREATE_FILE(
7813 conn, /* conn */
7814 req, /* req */
7815 0, /* root_dir_fid */
7816 smb_fname, /* fname */
7817 access_mask, /* access_mask */
7818 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7819 FILE_SHARE_DELETE),
7820 create_disp, /* create_disposition*/
7821 create_options, /* create_options */
7822 mod_unixmode, /* file_attributes */
7823 oplock_request, /* oplock_request */
7824 NULL, /* lease */
7825 0, /* allocation_size */
7826 0, /* private_flags */
7827 NULL, /* sd */
7828 NULL, /* ea_list */
7829 &fsp, /* result */
7830 &info, /* pinfo */
7831 NULL, NULL); /* create context */
7833 if (!NT_STATUS_IS_OK(status)) {
7834 return status;
7837 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7838 extended_oplock_granted = True;
7841 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7842 extended_oplock_granted = True;
7845 info_level_return = SVAL(pdata,16);
7847 /* Allocate the correct return size. */
7849 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7850 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7851 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7852 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7853 } else {
7854 *pdata_return_size = 12;
7857 /* Realloc the data size */
7858 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7859 if (*ppdata == NULL) {
7860 close_file(req, fsp, ERROR_CLOSE);
7861 *pdata_return_size = 0;
7862 return NT_STATUS_NO_MEMORY;
7864 pdata = *ppdata;
7866 if (extended_oplock_granted) {
7867 if (flags & REQUEST_BATCH_OPLOCK) {
7868 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7869 } else {
7870 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7872 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7873 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7874 } else {
7875 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7878 SSVAL(pdata,2,fsp->fnum);
7879 SIVAL(pdata,4,info); /* Was file created etc. */
7881 switch (info_level_return) {
7882 case SMB_QUERY_FILE_UNIX_BASIC:
7883 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7884 SSVAL(pdata,10,0); /* padding. */
7885 store_file_unix_basic(conn, pdata + 12, fsp,
7886 &smb_fname->st);
7887 break;
7888 case SMB_QUERY_FILE_UNIX_INFO2:
7889 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7890 SSVAL(pdata,10,0); /* padding. */
7891 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7892 &smb_fname->st);
7893 break;
7894 default:
7895 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7896 SSVAL(pdata,10,0); /* padding. */
7897 break;
7899 return NT_STATUS_OK;
7902 /****************************************************************************
7903 Delete a file with POSIX semantics.
7904 ****************************************************************************/
7906 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7907 struct smb_request *req,
7908 const char *pdata,
7909 int total_data,
7910 struct smb_filename *smb_fname)
7912 NTSTATUS status = NT_STATUS_OK;
7913 files_struct *fsp = NULL;
7914 uint16_t flags = 0;
7915 char del = 1;
7916 int info = 0;
7917 int create_options = 0;
7918 int i;
7919 struct share_mode_lock *lck = NULL;
7921 if (total_data < 2) {
7922 return NT_STATUS_INVALID_PARAMETER;
7925 flags = SVAL(pdata,0);
7927 if (!VALID_STAT(smb_fname->st)) {
7928 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7931 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7932 !VALID_STAT_OF_DIR(smb_fname->st)) {
7933 return NT_STATUS_NOT_A_DIRECTORY;
7936 DEBUG(10,("smb_posix_unlink: %s %s\n",
7937 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7938 smb_fname_str_dbg(smb_fname)));
7940 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7941 create_options |= FILE_DIRECTORY_FILE;
7944 status = SMB_VFS_CREATE_FILE(
7945 conn, /* conn */
7946 req, /* req */
7947 0, /* root_dir_fid */
7948 smb_fname, /* fname */
7949 DELETE_ACCESS, /* access_mask */
7950 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7951 FILE_SHARE_DELETE),
7952 FILE_OPEN, /* create_disposition*/
7953 create_options, /* create_options */
7954 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7955 0, /* oplock_request */
7956 NULL, /* lease */
7957 0, /* allocation_size */
7958 0, /* private_flags */
7959 NULL, /* sd */
7960 NULL, /* ea_list */
7961 &fsp, /* result */
7962 &info, /* pinfo */
7963 NULL, NULL); /* create context */
7965 if (!NT_STATUS_IS_OK(status)) {
7966 return status;
7970 * Don't lie to client. If we can't really delete due to
7971 * non-POSIX opens return SHARING_VIOLATION.
7974 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7975 if (lck == NULL) {
7976 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7977 "lock for file %s\n", fsp_str_dbg(fsp)));
7978 close_file(req, fsp, NORMAL_CLOSE);
7979 return NT_STATUS_INVALID_PARAMETER;
7983 * See if others still have the file open. If this is the case, then
7984 * don't delete. If all opens are POSIX delete we can set the delete
7985 * on close disposition.
7987 for (i=0; i<lck->data->num_share_modes; i++) {
7988 struct share_mode_entry *e = &lck->data->share_modes[i];
7989 if (is_valid_share_mode_entry(e)) {
7990 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7991 continue;
7993 if (share_mode_stale_pid(lck->data, i)) {
7994 continue;
7996 /* Fail with sharing violation. */
7997 TALLOC_FREE(lck);
7998 close_file(req, fsp, NORMAL_CLOSE);
7999 return NT_STATUS_SHARING_VIOLATION;
8004 * Set the delete on close.
8006 status = smb_set_file_disposition_info(conn,
8007 &del,
8009 fsp,
8010 smb_fname);
8012 TALLOC_FREE(lck);
8014 if (!NT_STATUS_IS_OK(status)) {
8015 close_file(req, fsp, NORMAL_CLOSE);
8016 return status;
8018 return close_file(req, fsp, NORMAL_CLOSE);
8021 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8022 struct smb_request *req,
8023 TALLOC_CTX *mem_ctx,
8024 uint16_t info_level,
8025 files_struct *fsp,
8026 struct smb_filename *smb_fname,
8027 char **ppdata, int total_data,
8028 int *ret_data_size)
8030 char *pdata = *ppdata;
8031 NTSTATUS status = NT_STATUS_OK;
8032 int data_return_size = 0;
8034 *ret_data_size = 0;
8036 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8037 return NT_STATUS_INVALID_LEVEL;
8040 if (!CAN_WRITE(conn)) {
8041 /* Allow POSIX opens. The open path will deny
8042 * any non-readonly opens. */
8043 if (info_level != SMB_POSIX_PATH_OPEN) {
8044 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8048 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8049 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8050 fsp_fnum_dbg(fsp),
8051 info_level, total_data));
8053 switch (info_level) {
8055 case SMB_INFO_STANDARD:
8057 status = smb_set_info_standard(conn,
8058 pdata,
8059 total_data,
8060 fsp,
8061 smb_fname);
8062 break;
8065 case SMB_INFO_SET_EA:
8067 status = smb_info_set_ea(conn,
8068 pdata,
8069 total_data,
8070 fsp,
8071 smb_fname);
8072 break;
8075 case SMB_SET_FILE_BASIC_INFO:
8076 case SMB_FILE_BASIC_INFORMATION:
8078 status = smb_set_file_basic_info(conn,
8079 pdata,
8080 total_data,
8081 fsp,
8082 smb_fname);
8083 break;
8086 case SMB_FILE_ALLOCATION_INFORMATION:
8087 case SMB_SET_FILE_ALLOCATION_INFO:
8089 status = smb_set_file_allocation_info(conn, req,
8090 pdata,
8091 total_data,
8092 fsp,
8093 smb_fname);
8094 break;
8097 case SMB_FILE_END_OF_FILE_INFORMATION:
8098 case SMB_SET_FILE_END_OF_FILE_INFO:
8101 * XP/Win7 both fail after the createfile with
8102 * SMB_SET_FILE_END_OF_FILE_INFO but not
8103 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8104 * The level is known here, so pass it down
8105 * appropriately.
8107 bool should_fail =
8108 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8110 status = smb_set_file_end_of_file_info(conn, req,
8111 pdata,
8112 total_data,
8113 fsp,
8114 smb_fname,
8115 should_fail);
8116 break;
8119 case SMB_FILE_DISPOSITION_INFORMATION:
8120 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8122 #if 0
8123 /* JRA - We used to just ignore this on a path ?
8124 * Shouldn't this be invalid level on a pathname
8125 * based call ?
8127 if (tran_call != TRANSACT2_SETFILEINFO) {
8128 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8130 #endif
8131 status = smb_set_file_disposition_info(conn,
8132 pdata,
8133 total_data,
8134 fsp,
8135 smb_fname);
8136 break;
8139 case SMB_FILE_POSITION_INFORMATION:
8141 status = smb_file_position_information(conn,
8142 pdata,
8143 total_data,
8144 fsp);
8145 break;
8148 case SMB_FILE_FULL_EA_INFORMATION:
8150 status = smb_set_file_full_ea_info(conn,
8151 pdata,
8152 total_data,
8153 fsp);
8154 break;
8157 /* From tridge Samba4 :
8158 * MODE_INFORMATION in setfileinfo (I have no
8159 * idea what "mode information" on a file is - it takes a value of 0,
8160 * 2, 4 or 6. What could it be?).
8163 case SMB_FILE_MODE_INFORMATION:
8165 status = smb_file_mode_information(conn,
8166 pdata,
8167 total_data);
8168 break;
8172 * CIFS UNIX extensions.
8175 case SMB_SET_FILE_UNIX_BASIC:
8177 status = smb_set_file_unix_basic(conn, req,
8178 pdata,
8179 total_data,
8180 fsp,
8181 smb_fname);
8182 break;
8185 case SMB_SET_FILE_UNIX_INFO2:
8187 status = smb_set_file_unix_info2(conn, req,
8188 pdata,
8189 total_data,
8190 fsp,
8191 smb_fname);
8192 break;
8195 case SMB_SET_FILE_UNIX_LINK:
8197 if (fsp) {
8198 /* We must have a pathname for this. */
8199 return NT_STATUS_INVALID_LEVEL;
8201 status = smb_set_file_unix_link(conn, req, pdata,
8202 total_data, smb_fname);
8203 break;
8206 case SMB_SET_FILE_UNIX_HLINK:
8208 if (fsp) {
8209 /* We must have a pathname for this. */
8210 return NT_STATUS_INVALID_LEVEL;
8212 status = smb_set_file_unix_hlink(conn, req,
8213 pdata, total_data,
8214 smb_fname);
8215 break;
8218 case SMB_FILE_RENAME_INFORMATION:
8220 status = smb_file_rename_information(conn, req,
8221 pdata, total_data,
8222 fsp, smb_fname);
8223 break;
8226 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8228 /* SMB2 rename information. */
8229 status = smb2_file_rename_information(conn, req,
8230 pdata, total_data,
8231 fsp, smb_fname);
8232 break;
8235 case SMB_FILE_LINK_INFORMATION:
8237 status = smb_file_link_information(conn, req,
8238 pdata, total_data,
8239 fsp, smb_fname);
8240 break;
8243 #if defined(HAVE_POSIX_ACLS)
8244 case SMB_SET_POSIX_ACL:
8246 status = smb_set_posix_acl(conn,
8247 pdata,
8248 total_data,
8249 fsp,
8250 smb_fname);
8251 break;
8253 #endif
8255 case SMB_SET_POSIX_LOCK:
8257 if (!fsp) {
8258 return NT_STATUS_INVALID_LEVEL;
8260 status = smb_set_posix_lock(conn, req,
8261 pdata, total_data, fsp);
8262 break;
8265 case SMB_POSIX_PATH_OPEN:
8267 if (fsp) {
8268 /* We must have a pathname for this. */
8269 return NT_STATUS_INVALID_LEVEL;
8272 status = smb_posix_open(conn, req,
8273 ppdata,
8274 total_data,
8275 smb_fname,
8276 &data_return_size);
8277 break;
8280 case SMB_POSIX_PATH_UNLINK:
8282 if (fsp) {
8283 /* We must have a pathname for this. */
8284 return NT_STATUS_INVALID_LEVEL;
8287 status = smb_posix_unlink(conn, req,
8288 pdata,
8289 total_data,
8290 smb_fname);
8291 break;
8294 default:
8295 return NT_STATUS_INVALID_LEVEL;
8298 if (!NT_STATUS_IS_OK(status)) {
8299 return status;
8302 *ret_data_size = data_return_size;
8303 return NT_STATUS_OK;
8306 /****************************************************************************
8307 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8308 ****************************************************************************/
8310 static void call_trans2setfilepathinfo(connection_struct *conn,
8311 struct smb_request *req,
8312 unsigned int tran_call,
8313 char **pparams, int total_params,
8314 char **ppdata, int total_data,
8315 unsigned int max_data_bytes)
8317 char *params = *pparams;
8318 char *pdata = *ppdata;
8319 uint16_t info_level;
8320 struct smb_filename *smb_fname = NULL;
8321 files_struct *fsp = NULL;
8322 NTSTATUS status = NT_STATUS_OK;
8323 int data_return_size = 0;
8325 if (!params) {
8326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8327 return;
8330 if (tran_call == TRANSACT2_SETFILEINFO) {
8331 if (total_params < 4) {
8332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8333 return;
8336 fsp = file_fsp(req, SVAL(params,0));
8337 /* Basic check for non-null fsp. */
8338 if (!check_fsp_open(conn, req, fsp)) {
8339 return;
8341 info_level = SVAL(params,2);
8343 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8344 if (smb_fname == NULL) {
8345 reply_nterror(req, NT_STATUS_NO_MEMORY);
8346 return;
8349 if(fsp->fh->fd == -1) {
8351 * This is actually a SETFILEINFO on a directory
8352 * handle (returned from an NT SMB). NT5.0 seems
8353 * to do this call. JRA.
8355 if (INFO_LEVEL_IS_UNIX(info_level)) {
8356 /* Always do lstat for UNIX calls. */
8357 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8358 DEBUG(3,("call_trans2setfilepathinfo: "
8359 "SMB_VFS_LSTAT of %s failed "
8360 "(%s)\n",
8361 smb_fname_str_dbg(smb_fname),
8362 strerror(errno)));
8363 reply_nterror(req, map_nt_error_from_unix(errno));
8364 return;
8366 } else {
8367 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8368 DEBUG(3,("call_trans2setfilepathinfo: "
8369 "fileinfo of %s failed (%s)\n",
8370 smb_fname_str_dbg(smb_fname),
8371 strerror(errno)));
8372 reply_nterror(req, map_nt_error_from_unix(errno));
8373 return;
8376 } else if (fsp->print_file) {
8378 * Doing a DELETE_ON_CLOSE should cancel a print job.
8380 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8381 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8383 DEBUG(3,("call_trans2setfilepathinfo: "
8384 "Cancelling print job (%s)\n",
8385 fsp_str_dbg(fsp)));
8387 SSVAL(params,0,0);
8388 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8389 *ppdata, 0,
8390 max_data_bytes);
8391 return;
8392 } else {
8393 reply_nterror(req,
8394 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8395 return;
8397 } else {
8399 * Original code - this is an open file.
8401 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8402 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8403 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8404 strerror(errno)));
8405 reply_nterror(req, map_nt_error_from_unix(errno));
8406 return;
8409 } else {
8410 char *fname = NULL;
8411 uint32_t ucf_flags = 0;
8413 /* set path info */
8414 if (total_params < 7) {
8415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8416 return;
8419 info_level = SVAL(params,0);
8420 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8421 total_params - 6, STR_TERMINATE,
8422 &status);
8423 if (!NT_STATUS_IS_OK(status)) {
8424 reply_nterror(req, status);
8425 return;
8428 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8429 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8430 info_level == SMB_FILE_RENAME_INFORMATION ||
8431 info_level == SMB_POSIX_PATH_UNLINK) {
8432 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8435 status = filename_convert(req, conn,
8436 req->flags2 & FLAGS2_DFS_PATHNAMES,
8437 fname,
8438 ucf_flags,
8439 NULL,
8440 &smb_fname);
8441 if (!NT_STATUS_IS_OK(status)) {
8442 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8443 reply_botherror(req,
8444 NT_STATUS_PATH_NOT_COVERED,
8445 ERRSRV, ERRbadpath);
8446 return;
8448 reply_nterror(req, status);
8449 return;
8452 if (INFO_LEVEL_IS_UNIX(info_level)) {
8454 * For CIFS UNIX extensions the target name may not exist.
8457 /* Always do lstat for UNIX calls. */
8458 SMB_VFS_LSTAT(conn, smb_fname);
8460 } else if (!VALID_STAT(smb_fname->st) &&
8461 SMB_VFS_STAT(conn, smb_fname)) {
8462 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8463 "%s failed (%s)\n",
8464 smb_fname_str_dbg(smb_fname),
8465 strerror(errno)));
8466 reply_nterror(req, map_nt_error_from_unix(errno));
8467 return;
8471 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8472 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8473 fsp_fnum_dbg(fsp),
8474 info_level,total_data));
8476 /* Realloc the parameter size */
8477 *pparams = (char *)SMB_REALLOC(*pparams,2);
8478 if (*pparams == NULL) {
8479 reply_nterror(req, NT_STATUS_NO_MEMORY);
8480 return;
8482 params = *pparams;
8484 SSVAL(params,0,0);
8486 status = smbd_do_setfilepathinfo(conn, req, req,
8487 info_level,
8488 fsp,
8489 smb_fname,
8490 ppdata, total_data,
8491 &data_return_size);
8492 if (!NT_STATUS_IS_OK(status)) {
8493 if (open_was_deferred(req->xconn, req->mid)) {
8494 /* We have re-scheduled this call. */
8495 return;
8497 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8498 /* We have re-scheduled this call. */
8499 return;
8501 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8502 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8503 ERRSRV, ERRbadpath);
8504 return;
8506 if (info_level == SMB_POSIX_PATH_OPEN) {
8507 reply_openerror(req, status);
8508 return;
8512 * Invalid EA name needs to return 2 param bytes,
8513 * not a zero-length error packet.
8515 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8516 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8517 max_data_bytes);
8518 } else {
8519 reply_nterror(req, status);
8521 return;
8524 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8525 max_data_bytes);
8527 return;
8530 /****************************************************************************
8531 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8532 ****************************************************************************/
8534 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8535 char **pparams, int total_params,
8536 char **ppdata, int total_data,
8537 unsigned int max_data_bytes)
8539 struct smb_filename *smb_dname = NULL;
8540 char *params = *pparams;
8541 char *pdata = *ppdata;
8542 char *directory = NULL;
8543 NTSTATUS status = NT_STATUS_OK;
8544 struct ea_list *ea_list = NULL;
8545 TALLOC_CTX *ctx = talloc_tos();
8547 if (!CAN_WRITE(conn)) {
8548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8549 return;
8552 if (total_params < 5) {
8553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8554 return;
8557 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8558 total_params - 4, STR_TERMINATE,
8559 &status);
8560 if (!NT_STATUS_IS_OK(status)) {
8561 reply_nterror(req, status);
8562 return;
8565 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8567 status = filename_convert(ctx,
8568 conn,
8569 req->flags2 & FLAGS2_DFS_PATHNAMES,
8570 directory,
8572 NULL,
8573 &smb_dname);
8575 if (!NT_STATUS_IS_OK(status)) {
8576 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8577 reply_botherror(req,
8578 NT_STATUS_PATH_NOT_COVERED,
8579 ERRSRV, ERRbadpath);
8580 return;
8582 reply_nterror(req, status);
8583 return;
8587 * OS/2 workplace shell seems to send SET_EA requests of "null"
8588 * length (4 bytes containing IVAL 4).
8589 * They seem to have no effect. Bug #3212. JRA.
8592 if (total_data && (total_data != 4)) {
8593 /* Any data in this call is an EA list. */
8594 if (total_data < 10) {
8595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8596 goto out;
8599 if (IVAL(pdata,0) > total_data) {
8600 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8601 IVAL(pdata,0), (unsigned int)total_data));
8602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8603 goto out;
8606 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8607 total_data - 4);
8608 if (!ea_list) {
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610 goto out;
8613 if (!lp_ea_support(SNUM(conn))) {
8614 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8615 goto out;
8618 /* If total_data == 4 Windows doesn't care what values
8619 * are placed in that field, it just ignores them.
8620 * The System i QNTC IBM SMB client puts bad values here,
8621 * so ignore them. */
8623 status = create_directory(conn, req, smb_dname);
8625 if (!NT_STATUS_IS_OK(status)) {
8626 reply_nterror(req, status);
8627 goto out;
8630 /* Try and set any given EA. */
8631 if (ea_list) {
8632 status = set_ea(conn, NULL, smb_dname, ea_list);
8633 if (!NT_STATUS_IS_OK(status)) {
8634 reply_nterror(req, status);
8635 goto out;
8639 /* Realloc the parameter and data sizes */
8640 *pparams = (char *)SMB_REALLOC(*pparams,2);
8641 if(*pparams == NULL) {
8642 reply_nterror(req, NT_STATUS_NO_MEMORY);
8643 goto out;
8645 params = *pparams;
8647 SSVAL(params,0,0);
8649 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8651 out:
8652 TALLOC_FREE(smb_dname);
8653 return;
8656 /****************************************************************************
8657 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8658 We don't actually do this - we just send a null response.
8659 ****************************************************************************/
8661 static void call_trans2findnotifyfirst(connection_struct *conn,
8662 struct smb_request *req,
8663 char **pparams, int total_params,
8664 char **ppdata, int total_data,
8665 unsigned int max_data_bytes)
8667 char *params = *pparams;
8668 uint16_t info_level;
8670 if (total_params < 6) {
8671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8672 return;
8675 info_level = SVAL(params,4);
8676 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8678 switch (info_level) {
8679 case 1:
8680 case 2:
8681 break;
8682 default:
8683 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8684 return;
8687 /* Realloc the parameter and data sizes */
8688 *pparams = (char *)SMB_REALLOC(*pparams,6);
8689 if (*pparams == NULL) {
8690 reply_nterror(req, NT_STATUS_NO_MEMORY);
8691 return;
8693 params = *pparams;
8695 SSVAL(params,0,fnf_handle);
8696 SSVAL(params,2,0); /* No changes */
8697 SSVAL(params,4,0); /* No EA errors */
8699 fnf_handle++;
8701 if(fnf_handle == 0)
8702 fnf_handle = 257;
8704 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8706 return;
8709 /****************************************************************************
8710 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8711 changes). Currently this does nothing.
8712 ****************************************************************************/
8714 static void call_trans2findnotifynext(connection_struct *conn,
8715 struct smb_request *req,
8716 char **pparams, int total_params,
8717 char **ppdata, int total_data,
8718 unsigned int max_data_bytes)
8720 char *params = *pparams;
8722 DEBUG(3,("call_trans2findnotifynext\n"));
8724 /* Realloc the parameter and data sizes */
8725 *pparams = (char *)SMB_REALLOC(*pparams,4);
8726 if (*pparams == NULL) {
8727 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 return;
8730 params = *pparams;
8732 SSVAL(params,0,0); /* No changes */
8733 SSVAL(params,2,0); /* No EA errors */
8735 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8737 return;
8740 /****************************************************************************
8741 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8742 ****************************************************************************/
8744 static void call_trans2getdfsreferral(connection_struct *conn,
8745 struct smb_request *req,
8746 char **pparams, int total_params,
8747 char **ppdata, int total_data,
8748 unsigned int max_data_bytes)
8750 char *params = *pparams;
8751 char *pathname = NULL;
8752 int reply_size = 0;
8753 int max_referral_level;
8754 NTSTATUS status = NT_STATUS_OK;
8755 TALLOC_CTX *ctx = talloc_tos();
8757 DEBUG(10,("call_trans2getdfsreferral\n"));
8759 if (total_params < 3) {
8760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8761 return;
8764 max_referral_level = SVAL(params,0);
8766 if(!lp_host_msdfs()) {
8767 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8768 return;
8771 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8772 total_params - 2, STR_TERMINATE);
8773 if (!pathname) {
8774 reply_nterror(req, NT_STATUS_NOT_FOUND);
8775 return;
8777 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8778 ppdata,&status)) < 0) {
8779 reply_nterror(req, status);
8780 return;
8783 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8784 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8785 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8787 return;
8790 #define LMCAT_SPL 0x53
8791 #define LMFUNC_GETJOBID 0x60
8793 /****************************************************************************
8794 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8795 ****************************************************************************/
8797 static void call_trans2ioctl(connection_struct *conn,
8798 struct smb_request *req,
8799 char **pparams, int total_params,
8800 char **ppdata, int total_data,
8801 unsigned int max_data_bytes)
8803 char *pdata = *ppdata;
8804 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8805 NTSTATUS status;
8806 size_t len = 0;
8808 /* check for an invalid fid before proceeding */
8810 if (!fsp) {
8811 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8812 return;
8815 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8816 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8817 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8818 if (*ppdata == NULL) {
8819 reply_nterror(req, NT_STATUS_NO_MEMORY);
8820 return;
8822 pdata = *ppdata;
8824 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8825 CAN ACCEPT THIS IN UNICODE. JRA. */
8827 /* Job number */
8828 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8830 status = srvstr_push(pdata, req->flags2, pdata + 2,
8831 lp_netbios_name(), 15,
8832 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8833 if (!NT_STATUS_IS_OK(status)) {
8834 reply_nterror(req, status);
8835 return;
8837 status = srvstr_push(pdata, req->flags2, pdata+18,
8838 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8839 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8840 if (!NT_STATUS_IS_OK(status)) {
8841 reply_nterror(req, status);
8842 return;
8844 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8845 max_data_bytes);
8846 return;
8849 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8850 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8853 /****************************************************************************
8854 Reply to a SMBfindclose (stop trans2 directory search).
8855 ****************************************************************************/
8857 void reply_findclose(struct smb_request *req)
8859 int dptr_num;
8860 struct smbd_server_connection *sconn = req->sconn;
8862 START_PROFILE(SMBfindclose);
8864 if (req->wct < 1) {
8865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8866 END_PROFILE(SMBfindclose);
8867 return;
8870 dptr_num = SVALS(req->vwv+0, 0);
8872 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8874 dptr_close(sconn, &dptr_num);
8876 reply_outbuf(req, 0, 0);
8878 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8880 END_PROFILE(SMBfindclose);
8881 return;
8884 /****************************************************************************
8885 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8886 ****************************************************************************/
8888 void reply_findnclose(struct smb_request *req)
8890 int dptr_num;
8892 START_PROFILE(SMBfindnclose);
8894 if (req->wct < 1) {
8895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8896 END_PROFILE(SMBfindnclose);
8897 return;
8900 dptr_num = SVAL(req->vwv+0, 0);
8902 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8904 /* We never give out valid handles for a
8905 findnotifyfirst - so any dptr_num is ok here.
8906 Just ignore it. */
8908 reply_outbuf(req, 0, 0);
8910 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8912 END_PROFILE(SMBfindnclose);
8913 return;
8916 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8917 struct trans_state *state)
8919 if (get_Protocol() >= PROTOCOL_NT1) {
8920 req->flags2 |= 0x40; /* IS_LONG_NAME */
8921 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8924 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8925 if (state->call != TRANSACT2_QFSINFO &&
8926 state->call != TRANSACT2_SETFSINFO) {
8927 DEBUG(0,("handle_trans2: encryption required "
8928 "with call 0x%x\n",
8929 (unsigned int)state->call));
8930 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8931 return;
8935 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8937 /* Now we must call the relevant TRANS2 function */
8938 switch(state->call) {
8939 case TRANSACT2_OPEN:
8941 START_PROFILE(Trans2_open);
8942 call_trans2open(conn, req,
8943 &state->param, state->total_param,
8944 &state->data, state->total_data,
8945 state->max_data_return);
8946 END_PROFILE(Trans2_open);
8947 break;
8950 case TRANSACT2_FINDFIRST:
8952 START_PROFILE(Trans2_findfirst);
8953 call_trans2findfirst(conn, req,
8954 &state->param, state->total_param,
8955 &state->data, state->total_data,
8956 state->max_data_return);
8957 END_PROFILE(Trans2_findfirst);
8958 break;
8961 case TRANSACT2_FINDNEXT:
8963 START_PROFILE(Trans2_findnext);
8964 call_trans2findnext(conn, req,
8965 &state->param, state->total_param,
8966 &state->data, state->total_data,
8967 state->max_data_return);
8968 END_PROFILE(Trans2_findnext);
8969 break;
8972 case TRANSACT2_QFSINFO:
8974 START_PROFILE(Trans2_qfsinfo);
8975 call_trans2qfsinfo(conn, req,
8976 &state->param, state->total_param,
8977 &state->data, state->total_data,
8978 state->max_data_return);
8979 END_PROFILE(Trans2_qfsinfo);
8980 break;
8983 case TRANSACT2_SETFSINFO:
8985 START_PROFILE(Trans2_setfsinfo);
8986 call_trans2setfsinfo(conn, req,
8987 &state->param, state->total_param,
8988 &state->data, state->total_data,
8989 state->max_data_return);
8990 END_PROFILE(Trans2_setfsinfo);
8991 break;
8994 case TRANSACT2_QPATHINFO:
8995 case TRANSACT2_QFILEINFO:
8997 START_PROFILE(Trans2_qpathinfo);
8998 call_trans2qfilepathinfo(conn, req, state->call,
8999 &state->param, state->total_param,
9000 &state->data, state->total_data,
9001 state->max_data_return);
9002 END_PROFILE(Trans2_qpathinfo);
9003 break;
9006 case TRANSACT2_SETPATHINFO:
9007 case TRANSACT2_SETFILEINFO:
9009 START_PROFILE(Trans2_setpathinfo);
9010 call_trans2setfilepathinfo(conn, req, state->call,
9011 &state->param, state->total_param,
9012 &state->data, state->total_data,
9013 state->max_data_return);
9014 END_PROFILE(Trans2_setpathinfo);
9015 break;
9018 case TRANSACT2_FINDNOTIFYFIRST:
9020 START_PROFILE(Trans2_findnotifyfirst);
9021 call_trans2findnotifyfirst(conn, req,
9022 &state->param, state->total_param,
9023 &state->data, state->total_data,
9024 state->max_data_return);
9025 END_PROFILE(Trans2_findnotifyfirst);
9026 break;
9029 case TRANSACT2_FINDNOTIFYNEXT:
9031 START_PROFILE(Trans2_findnotifynext);
9032 call_trans2findnotifynext(conn, req,
9033 &state->param, state->total_param,
9034 &state->data, state->total_data,
9035 state->max_data_return);
9036 END_PROFILE(Trans2_findnotifynext);
9037 break;
9040 case TRANSACT2_MKDIR:
9042 START_PROFILE(Trans2_mkdir);
9043 call_trans2mkdir(conn, req,
9044 &state->param, state->total_param,
9045 &state->data, state->total_data,
9046 state->max_data_return);
9047 END_PROFILE(Trans2_mkdir);
9048 break;
9051 case TRANSACT2_GET_DFS_REFERRAL:
9053 START_PROFILE(Trans2_get_dfs_referral);
9054 call_trans2getdfsreferral(conn, req,
9055 &state->param, state->total_param,
9056 &state->data, state->total_data,
9057 state->max_data_return);
9058 END_PROFILE(Trans2_get_dfs_referral);
9059 break;
9062 case TRANSACT2_IOCTL:
9064 START_PROFILE(Trans2_ioctl);
9065 call_trans2ioctl(conn, req,
9066 &state->param, state->total_param,
9067 &state->data, state->total_data,
9068 state->max_data_return);
9069 END_PROFILE(Trans2_ioctl);
9070 break;
9073 default:
9074 /* Error in request */
9075 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9076 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9080 /****************************************************************************
9081 Reply to a SMBtrans2.
9082 ****************************************************************************/
9084 void reply_trans2(struct smb_request *req)
9086 connection_struct *conn = req->conn;
9087 unsigned int dsoff;
9088 unsigned int dscnt;
9089 unsigned int psoff;
9090 unsigned int pscnt;
9091 unsigned int tran_call;
9092 struct trans_state *state;
9093 NTSTATUS result;
9095 START_PROFILE(SMBtrans2);
9097 if (req->wct < 14) {
9098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9099 END_PROFILE(SMBtrans2);
9100 return;
9103 dsoff = SVAL(req->vwv+12, 0);
9104 dscnt = SVAL(req->vwv+11, 0);
9105 psoff = SVAL(req->vwv+10, 0);
9106 pscnt = SVAL(req->vwv+9, 0);
9107 tran_call = SVAL(req->vwv+14, 0);
9109 result = allow_new_trans(conn->pending_trans, req->mid);
9110 if (!NT_STATUS_IS_OK(result)) {
9111 DEBUG(2, ("Got invalid trans2 request: %s\n",
9112 nt_errstr(result)));
9113 reply_nterror(req, result);
9114 END_PROFILE(SMBtrans2);
9115 return;
9118 if (IS_IPC(conn)) {
9119 switch (tran_call) {
9120 /* List the allowed trans2 calls on IPC$ */
9121 case TRANSACT2_OPEN:
9122 case TRANSACT2_GET_DFS_REFERRAL:
9123 case TRANSACT2_QFILEINFO:
9124 case TRANSACT2_QFSINFO:
9125 case TRANSACT2_SETFSINFO:
9126 break;
9127 default:
9128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9129 END_PROFILE(SMBtrans2);
9130 return;
9134 if ((state = talloc(conn, struct trans_state)) == NULL) {
9135 DEBUG(0, ("talloc failed\n"));
9136 reply_nterror(req, NT_STATUS_NO_MEMORY);
9137 END_PROFILE(SMBtrans2);
9138 return;
9141 state->cmd = SMBtrans2;
9143 state->mid = req->mid;
9144 state->vuid = req->vuid;
9145 state->setup_count = SVAL(req->vwv+13, 0);
9146 state->setup = NULL;
9147 state->total_param = SVAL(req->vwv+0, 0);
9148 state->param = NULL;
9149 state->total_data = SVAL(req->vwv+1, 0);
9150 state->data = NULL;
9151 state->max_param_return = SVAL(req->vwv+2, 0);
9152 state->max_data_return = SVAL(req->vwv+3, 0);
9153 state->max_setup_return = SVAL(req->vwv+4, 0);
9154 state->close_on_completion = BITSETW(req->vwv+5, 0);
9155 state->one_way = BITSETW(req->vwv+5, 1);
9157 state->call = tran_call;
9159 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9160 is so as a sanity check */
9161 if (state->setup_count != 1) {
9163 * Need to have rc=0 for ioctl to get job id for OS/2.
9164 * Network printing will fail if function is not successful.
9165 * Similar function in reply.c will be used if protocol
9166 * is LANMAN1.0 instead of LM1.2X002.
9167 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9168 * outbuf doesn't have to be set(only job id is used).
9170 if ( (state->setup_count == 4)
9171 && (tran_call == TRANSACT2_IOCTL)
9172 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9173 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9174 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9175 } else {
9176 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9177 DEBUG(2,("Transaction is %d\n",tran_call));
9178 TALLOC_FREE(state);
9179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9180 END_PROFILE(SMBtrans2);
9181 return;
9185 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9186 goto bad_param;
9188 if (state->total_data) {
9190 if (trans_oob(state->total_data, 0, dscnt)
9191 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9192 goto bad_param;
9195 /* Can't use talloc here, the core routines do realloc on the
9196 * params and data. */
9197 state->data = (char *)SMB_MALLOC(state->total_data);
9198 if (state->data == NULL) {
9199 DEBUG(0,("reply_trans2: data malloc fail for %u "
9200 "bytes !\n", (unsigned int)state->total_data));
9201 TALLOC_FREE(state);
9202 reply_nterror(req, NT_STATUS_NO_MEMORY);
9203 END_PROFILE(SMBtrans2);
9204 return;
9207 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9210 if (state->total_param) {
9212 if (trans_oob(state->total_param, 0, pscnt)
9213 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9214 goto bad_param;
9217 /* Can't use talloc here, the core routines do realloc on the
9218 * params and data. */
9219 state->param = (char *)SMB_MALLOC(state->total_param);
9220 if (state->param == NULL) {
9221 DEBUG(0,("reply_trans: param malloc fail for %u "
9222 "bytes !\n", (unsigned int)state->total_param));
9223 SAFE_FREE(state->data);
9224 TALLOC_FREE(state);
9225 reply_nterror(req, NT_STATUS_NO_MEMORY);
9226 END_PROFILE(SMBtrans2);
9227 return;
9230 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9233 state->received_data = dscnt;
9234 state->received_param = pscnt;
9236 if ((state->received_param == state->total_param) &&
9237 (state->received_data == state->total_data)) {
9239 handle_trans2(conn, req, state);
9241 SAFE_FREE(state->data);
9242 SAFE_FREE(state->param);
9243 TALLOC_FREE(state);
9244 END_PROFILE(SMBtrans2);
9245 return;
9248 DLIST_ADD(conn->pending_trans, state);
9250 /* We need to send an interim response then receive the rest
9251 of the parameter/data bytes */
9252 reply_outbuf(req, 0, 0);
9253 show_msg((char *)req->outbuf);
9254 END_PROFILE(SMBtrans2);
9255 return;
9257 bad_param:
9259 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9260 SAFE_FREE(state->data);
9261 SAFE_FREE(state->param);
9262 TALLOC_FREE(state);
9263 END_PROFILE(SMBtrans2);
9264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9268 /****************************************************************************
9269 Reply to a SMBtranss2
9270 ****************************************************************************/
9272 void reply_transs2(struct smb_request *req)
9274 connection_struct *conn = req->conn;
9275 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9276 struct trans_state *state;
9278 START_PROFILE(SMBtranss2);
9280 show_msg((const char *)req->inbuf);
9282 /* Windows clients expect all replies to
9283 a transact secondary (SMBtranss2 0x33)
9284 to have a command code of transact
9285 (SMBtrans2 0x32). See bug #8989
9286 and also [MS-CIFS] section 2.2.4.47.2
9287 for details.
9289 req->cmd = SMBtrans2;
9291 if (req->wct < 8) {
9292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9293 END_PROFILE(SMBtranss2);
9294 return;
9297 for (state = conn->pending_trans; state != NULL;
9298 state = state->next) {
9299 if (state->mid == req->mid) {
9300 break;
9304 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 END_PROFILE(SMBtranss2);
9307 return;
9310 /* Revise state->total_param and state->total_data in case they have
9311 changed downwards */
9313 if (SVAL(req->vwv+0, 0) < state->total_param)
9314 state->total_param = SVAL(req->vwv+0, 0);
9315 if (SVAL(req->vwv+1, 0) < state->total_data)
9316 state->total_data = SVAL(req->vwv+1, 0);
9318 pcnt = SVAL(req->vwv+2, 0);
9319 poff = SVAL(req->vwv+3, 0);
9320 pdisp = SVAL(req->vwv+4, 0);
9322 dcnt = SVAL(req->vwv+5, 0);
9323 doff = SVAL(req->vwv+6, 0);
9324 ddisp = SVAL(req->vwv+7, 0);
9326 state->received_param += pcnt;
9327 state->received_data += dcnt;
9329 if ((state->received_data > state->total_data) ||
9330 (state->received_param > state->total_param))
9331 goto bad_param;
9333 if (pcnt) {
9334 if (trans_oob(state->total_param, pdisp, pcnt)
9335 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9336 goto bad_param;
9338 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9341 if (dcnt) {
9342 if (trans_oob(state->total_data, ddisp, dcnt)
9343 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9344 goto bad_param;
9346 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9349 if ((state->received_param < state->total_param) ||
9350 (state->received_data < state->total_data)) {
9351 END_PROFILE(SMBtranss2);
9352 return;
9355 handle_trans2(conn, req, state);
9357 DLIST_REMOVE(conn->pending_trans, state);
9358 SAFE_FREE(state->data);
9359 SAFE_FREE(state->param);
9360 TALLOC_FREE(state);
9362 END_PROFILE(SMBtranss2);
9363 return;
9365 bad_param:
9367 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9368 DLIST_REMOVE(conn->pending_trans, state);
9369 SAFE_FREE(state->data);
9370 SAFE_FREE(state->param);
9371 TALLOC_FREE(state);
9372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9373 END_PROFILE(SMBtranss2);
9374 return;