s3-vfs: add vfs_btrfs module
[Samba/gbeck.git] / source3 / smbd / trans2.c
blobfae9e1ff9dcf4a698df869f32daecedbd8f03a72
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 "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
327 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
328 &names, &num_names);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (num_names == 0) {
335 *ea_list = NULL;
336 return NT_STATUS_OK;
339 for (i=0; i<num_names; i++) {
340 struct ea_list *listp;
341 fstring dos_ea_name;
343 if (strnequal(names[i], "system.", 7)
344 || samba_private_attr_name(names[i]))
345 continue;
347 listp = talloc(mem_ctx, struct ea_list);
348 if (listp == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 status = get_ea_value(mem_ctx, conn, fsp,
353 fname, names[i],
354 &listp->ea);
356 if (!NT_STATUS_IS_OK(status)) {
357 return status;
360 push_ascii_fstring(dos_ea_name, listp->ea.name);
362 *pea_total_len +=
363 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
365 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
366 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
367 (unsigned int)listp->ea.value.length));
369 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
373 /* Add on 4 for total length. */
374 if (*pea_total_len) {
375 *pea_total_len += 4;
378 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
379 (unsigned int)*pea_total_len));
381 *ea_list = ea_list_head;
382 return NT_STATUS_OK;
385 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
386 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
388 *pea_total_len = 0;
389 *ea_list = NULL;
391 if (!lp_ea_support(SNUM(conn))) {
392 return NT_STATUS_OK;
395 if (is_ntfs_stream_smb_fname(smb_fname)) {
396 return NT_STATUS_INVALID_PARAMETER;
399 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
402 /****************************************************************************
403 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
404 that was filled.
405 ****************************************************************************/
407 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
408 connection_struct *conn, struct ea_list *ea_list)
410 unsigned int ret_data_size = 4;
411 char *p = pdata;
413 SMB_ASSERT(total_data_size >= 4);
415 if (!lp_ea_support(SNUM(conn))) {
416 SIVAL(pdata,4,0);
417 return 4;
420 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
421 size_t dos_namelen;
422 fstring dos_ea_name;
423 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
424 dos_namelen = strlen(dos_ea_name);
425 if (dos_namelen > 255 || dos_namelen == 0) {
426 break;
428 if (ea_list->ea.value.length > 65535) {
429 break;
431 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
432 break;
435 /* We know we have room. */
436 SCVAL(p,0,ea_list->ea.flags);
437 SCVAL(p,1,dos_namelen);
438 SSVAL(p,2,ea_list->ea.value.length);
439 strlcpy(p+4, dos_ea_name, dos_namelen+1);
440 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
442 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
443 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
446 ret_data_size = PTR_DIFF(p, pdata);
447 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
448 SIVAL(pdata,0,ret_data_size);
449 return ret_data_size;
452 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
453 char *pdata,
454 unsigned int total_data_size,
455 unsigned int *ret_data_size,
456 connection_struct *conn,
457 struct ea_list *ea_list)
459 uint8_t *p = (uint8_t *)pdata;
460 uint8_t *last_start = NULL;
462 *ret_data_size = 0;
464 if (!lp_ea_support(SNUM(conn))) {
465 return NT_STATUS_NO_EAS_ON_FILE;
468 for (; ea_list; ea_list = ea_list->next) {
469 size_t dos_namelen;
470 fstring dos_ea_name;
471 size_t this_size;
473 if (last_start) {
474 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
476 last_start = p;
478 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
479 dos_namelen = strlen(dos_ea_name);
480 if (dos_namelen > 255 || dos_namelen == 0) {
481 return NT_STATUS_INTERNAL_ERROR;
483 if (ea_list->ea.value.length > 65535) {
484 return NT_STATUS_INTERNAL_ERROR;
487 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
489 if (ea_list->next) {
490 size_t pad = 4 - (this_size % 4);
491 this_size += pad;
494 if (this_size > total_data_size) {
495 return NT_STATUS_INFO_LENGTH_MISMATCH;
498 /* We know we have room. */
499 SIVAL(p, 0x00, 0); /* next offset */
500 SCVAL(p, 0x04, ea_list->ea.flags);
501 SCVAL(p, 0x05, dos_namelen);
502 SSVAL(p, 0x06, ea_list->ea.value.length);
503 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
504 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
506 total_data_size -= this_size;
507 p += this_size;
510 *ret_data_size = PTR_DIFF(p, pdata);
511 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
512 return NT_STATUS_OK;
515 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
517 size_t total_ea_len = 0;
518 TALLOC_CTX *mem_ctx;
519 struct ea_list *ea_list;
521 if (!lp_ea_support(SNUM(conn))) {
522 return 0;
524 mem_ctx = talloc_stackframe();
526 /* If this is a stream fsp, then we need to instead find the
527 * estimated ea len from the main file, not the stream
528 * (streams cannot have EAs), but the estimate isn't just 0 in
529 * this case! */
530 if (is_ntfs_stream_smb_fname(smb_fname)) {
531 fsp = NULL;
533 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
534 TALLOC_FREE(mem_ctx);
535 return total_ea_len;
538 /****************************************************************************
539 Ensure the EA name is case insensitive by matching any existing EA name.
540 ****************************************************************************/
542 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
544 size_t total_ea_len;
545 TALLOC_CTX *mem_ctx = talloc_tos();
546 struct ea_list *ea_list;
547 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
548 if (!NT_STATUS_IS_OK(status)) {
549 return;
552 for (; ea_list; ea_list = ea_list->next) {
553 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
554 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
555 &unix_ea_name[5], ea_list->ea.name));
556 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
557 break;
562 /****************************************************************************
563 Set or delete an extended attribute.
564 ****************************************************************************/
566 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
567 const struct smb_filename *smb_fname, struct ea_list *ea_list)
569 NTSTATUS status;
570 char *fname = NULL;
572 if (!lp_ea_support(SNUM(conn))) {
573 return NT_STATUS_EAS_NOT_SUPPORTED;
576 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
577 if (!NT_STATUS_IS_OK(status)) {
578 return status;
581 /* Setting EAs on streams isn't supported. */
582 if (is_ntfs_stream_smb_fname(smb_fname)) {
583 return NT_STATUS_INVALID_PARAMETER;
586 fname = smb_fname->base_name;
588 for (;ea_list; ea_list = ea_list->next) {
589 int ret;
590 fstring unix_ea_name;
592 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
593 fstrcat(unix_ea_name, ea_list->ea.name);
595 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
597 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
599 if (samba_private_attr_name(unix_ea_name)) {
600 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
601 return NT_STATUS_ACCESS_DENIED;
604 if (ea_list->ea.value.length == 0) {
605 /* Remove the attribute. */
606 if (fsp && (fsp->fh->fd != -1)) {
607 DEBUG(10,("set_ea: deleting ea name %s on "
608 "file %s by file descriptor.\n",
609 unix_ea_name, fsp_str_dbg(fsp)));
610 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
611 } else {
612 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
613 unix_ea_name, fname));
614 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
616 #ifdef ENOATTR
617 /* Removing a non existent attribute always succeeds. */
618 if (ret == -1 && errno == ENOATTR) {
619 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
620 unix_ea_name));
621 ret = 0;
623 #endif
624 } else {
625 if (fsp && (fsp->fh->fd != -1)) {
626 DEBUG(10,("set_ea: setting ea name %s on file "
627 "%s by file descriptor.\n",
628 unix_ea_name, fsp_str_dbg(fsp)));
629 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
630 ea_list->ea.value.data, ea_list->ea.value.length, 0);
631 } else {
632 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
633 unix_ea_name, fname));
634 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
635 ea_list->ea.value.data, ea_list->ea.value.length, 0);
639 if (ret == -1) {
640 #ifdef ENOTSUP
641 if (errno == ENOTSUP) {
642 return NT_STATUS_EAS_NOT_SUPPORTED;
644 #endif
645 return map_nt_error_from_unix(errno);
649 return NT_STATUS_OK;
651 /****************************************************************************
652 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
653 ****************************************************************************/
655 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
657 struct ea_list *ea_list_head = NULL;
658 size_t converted_size, offset = 0;
660 while (offset + 2 < data_size) {
661 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
662 unsigned int namelen = CVAL(pdata,offset);
664 offset++; /* Go past the namelen byte. */
666 /* integer wrap paranioa. */
667 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
668 (offset > data_size) || (namelen > data_size) ||
669 (offset + namelen >= data_size)) {
670 break;
672 /* Ensure the name is null terminated. */
673 if (pdata[offset + namelen] != '\0') {
674 return NULL;
676 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
677 &converted_size)) {
678 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
679 "failed: %s", strerror(errno)));
681 if (!eal->ea.name) {
682 return NULL;
685 offset += (namelen + 1); /* Go past the name + terminating zero. */
686 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
687 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
690 return ea_list_head;
693 /****************************************************************************
694 Read one EA list entry from the buffer.
695 ****************************************************************************/
697 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
699 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
700 uint16 val_len;
701 unsigned int namelen;
702 size_t converted_size;
704 if (!eal) {
705 return NULL;
708 if (data_size < 6) {
709 return NULL;
712 eal->ea.flags = CVAL(pdata,0);
713 namelen = CVAL(pdata,1);
714 val_len = SVAL(pdata,2);
716 if (4 + namelen + 1 + val_len > data_size) {
717 return NULL;
720 /* Ensure the name is null terminated. */
721 if (pdata[namelen + 4] != '\0') {
722 return NULL;
724 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
725 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
726 strerror(errno)));
728 if (!eal->ea.name) {
729 return NULL;
732 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
733 if (!eal->ea.value.data) {
734 return NULL;
737 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
739 /* Ensure we're null terminated just in case we print the value. */
740 eal->ea.value.data[val_len] = '\0';
741 /* But don't count the null. */
742 eal->ea.value.length--;
744 if (pbytes_used) {
745 *pbytes_used = 4 + namelen + 1 + val_len;
748 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
749 dump_data(10, eal->ea.value.data, eal->ea.value.length);
751 return eal;
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 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 show_msg((char *)req->outbuf);
882 if (!srv_send_smb(sconn,
883 (char *)req->outbuf,
884 true, req->seqnum+1,
885 IS_CONN_ENCRYPTED(conn),
886 &req->pcd)) {
887 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
889 TALLOC_FREE(req->outbuf);
890 return;
893 /* When sending params and data ensure that both are nicely aligned */
894 /* Only do this alignment when there is also data to send - else
895 can cause NT redirector problems. */
897 if (((params_to_send % 4) != 0) && (data_to_send != 0))
898 data_alignment_offset = 4 - (params_to_send % 4);
900 /* Space is bufsize minus Netbios over TCP header minus SMB header */
901 /* The alignment_offset is to align the param bytes on an even byte
902 boundary. NT 4.0 Beta needs this to work correctly. */
904 useable_space = max_send - (smb_size
905 + 2 * 10 /* wct */
906 + alignment_offset
907 + data_alignment_offset);
909 if (useable_space < 0) {
910 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
911 "= %d!!!", useable_space));
912 exit_server_cleanly("send_trans2_replies: Not enough space");
915 while (params_to_send || data_to_send) {
916 /* Calculate whether we will totally or partially fill this packet */
918 total_sent_thistime = params_to_send + data_to_send;
920 /* We can never send more than useable_space */
922 * Note that 'useable_space' does not include the alignment offsets,
923 * but we must include the alignment offsets in the calculation of
924 * the length of the data we send over the wire, as the alignment offsets
925 * are sent here. Fix from Marc_Jacobsen@hp.com.
928 total_sent_thistime = MIN(total_sent_thistime, useable_space);
930 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
931 + data_alignment_offset);
933 /* Set total params and data to be sent */
934 SSVAL(req->outbuf,smb_tprcnt,paramsize);
935 SSVAL(req->outbuf,smb_tdrcnt,datasize);
937 /* Calculate how many parameters and data we can fit into
938 * this packet. Parameters get precedence
941 params_sent_thistime = MIN(params_to_send,useable_space);
942 data_sent_thistime = useable_space - params_sent_thistime;
943 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
945 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
947 /* smb_proff is the offset from the start of the SMB header to the
948 parameter bytes, however the first 4 bytes of outbuf are
949 the Netbios over TCP header. Thus use smb_base() to subtract
950 them from the calculation */
952 SSVAL(req->outbuf,smb_proff,
953 ((smb_buf(req->outbuf)+alignment_offset)
954 - smb_base(req->outbuf)));
956 if(params_sent_thistime == 0)
957 SSVAL(req->outbuf,smb_prdisp,0);
958 else
959 /* Absolute displacement of param bytes sent in this packet */
960 SSVAL(req->outbuf,smb_prdisp,pp - params);
962 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
963 if(data_sent_thistime == 0) {
964 SSVAL(req->outbuf,smb_droff,0);
965 SSVAL(req->outbuf,smb_drdisp, 0);
966 } else {
967 /* The offset of the data bytes is the offset of the
968 parameter bytes plus the number of parameters being sent this time */
969 SSVAL(req->outbuf, smb_droff,
970 ((smb_buf(req->outbuf)+alignment_offset)
971 - smb_base(req->outbuf))
972 + params_sent_thistime + data_alignment_offset);
973 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
976 /* Initialize the padding for alignment */
978 if (alignment_offset != 0) {
979 memset(smb_buf(req->outbuf), 0, alignment_offset);
982 /* Copy the param bytes into the packet */
984 if(params_sent_thistime) {
985 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
986 params_sent_thistime);
989 /* Copy in the data bytes */
990 if(data_sent_thistime) {
991 if (data_alignment_offset != 0) {
992 memset((smb_buf(req->outbuf)+alignment_offset+
993 params_sent_thistime), 0,
994 data_alignment_offset);
996 memcpy(smb_buf(req->outbuf)+alignment_offset
997 +params_sent_thistime+data_alignment_offset,
998 pd,data_sent_thistime);
1001 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1002 params_sent_thistime, data_sent_thistime, useable_space));
1003 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1004 params_to_send, data_to_send, paramsize, datasize));
1006 if (overflow) {
1007 error_packet_set((char *)req->outbuf,
1008 ERRDOS,ERRbufferoverflow,
1009 STATUS_BUFFER_OVERFLOW,
1010 __LINE__,__FILE__);
1013 /* Send the packet */
1014 show_msg((char *)req->outbuf);
1015 if (!srv_send_smb(sconn,
1016 (char *)req->outbuf,
1017 true, req->seqnum+1,
1018 IS_CONN_ENCRYPTED(conn),
1019 &req->pcd))
1020 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1022 TALLOC_FREE(req->outbuf);
1024 pp += params_sent_thistime;
1025 pd += data_sent_thistime;
1027 params_to_send -= params_sent_thistime;
1028 data_to_send -= data_sent_thistime;
1030 /* Sanity check */
1031 if(params_to_send < 0 || data_to_send < 0) {
1032 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1033 params_to_send, data_to_send));
1034 return;
1038 return;
1041 /****************************************************************************
1042 Reply to a TRANSACT2_OPEN.
1043 ****************************************************************************/
1045 static void call_trans2open(connection_struct *conn,
1046 struct smb_request *req,
1047 char **pparams, int total_params,
1048 char **ppdata, int total_data,
1049 unsigned int max_data_bytes)
1051 struct smb_filename *smb_fname = NULL;
1052 char *params = *pparams;
1053 char *pdata = *ppdata;
1054 int deny_mode;
1055 int32 open_attr;
1056 bool oplock_request;
1057 #if 0
1058 bool return_additional_info;
1059 int16 open_sattr;
1060 time_t open_time;
1061 #endif
1062 int open_ofun;
1063 uint32 open_size;
1064 char *pname;
1065 char *fname = NULL;
1066 off_t size=0;
1067 int fattr=0,mtime=0;
1068 SMB_INO_T inode = 0;
1069 int smb_action = 0;
1070 files_struct *fsp;
1071 struct ea_list *ea_list = NULL;
1072 uint16 flags = 0;
1073 NTSTATUS status;
1074 uint32 access_mask;
1075 uint32 share_mode;
1076 uint32 create_disposition;
1077 uint32 create_options = 0;
1078 uint32_t private_flags = 0;
1079 TALLOC_CTX *ctx = talloc_tos();
1082 * Ensure we have enough parameters to perform the operation.
1085 if (total_params < 29) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1090 flags = SVAL(params, 0);
1091 deny_mode = SVAL(params, 2);
1092 open_attr = SVAL(params,6);
1093 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1094 if (oplock_request) {
1095 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1098 #if 0
1099 return_additional_info = BITSETW(params,0);
1100 open_sattr = SVAL(params, 4);
1101 open_time = make_unix_date3(params+8);
1102 #endif
1103 open_ofun = SVAL(params,12);
1104 open_size = IVAL(params,14);
1105 pname = &params[28];
1107 if (IS_IPC(conn)) {
1108 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1109 goto out;
1112 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1113 total_params - 28, STR_TERMINATE,
1114 &status);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 goto out;
1120 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1121 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1122 (unsigned int)open_ofun, open_size));
1124 status = filename_convert(ctx,
1125 conn,
1126 req->flags2 & FLAGS2_DFS_PATHNAMES,
1127 fname,
1129 NULL,
1130 &smb_fname);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1133 reply_botherror(req,
1134 NT_STATUS_PATH_NOT_COVERED,
1135 ERRSRV, ERRbadpath);
1136 goto out;
1138 reply_nterror(req, status);
1139 goto out;
1142 if (open_ofun == 0) {
1143 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1144 goto out;
1147 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1148 open_ofun,
1149 &access_mask, &share_mode,
1150 &create_disposition,
1151 &create_options,
1152 &private_flags)) {
1153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1154 goto out;
1157 /* Any data in this call is an EA list. */
1158 if (total_data && (total_data != 4)) {
1159 if (total_data < 10) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 goto out;
1164 if (IVAL(pdata,0) > total_data) {
1165 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1166 IVAL(pdata,0), (unsigned int)total_data));
1167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1168 goto out;
1171 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1172 total_data - 4);
1173 if (!ea_list) {
1174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 goto out;
1178 if (!lp_ea_support(SNUM(conn))) {
1179 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1180 goto out;
1184 status = SMB_VFS_CREATE_FILE(
1185 conn, /* conn */
1186 req, /* req */
1187 0, /* root_dir_fid */
1188 smb_fname, /* fname */
1189 access_mask, /* access_mask */
1190 share_mode, /* share_access */
1191 create_disposition, /* create_disposition*/
1192 create_options, /* create_options */
1193 open_attr, /* file_attributes */
1194 oplock_request, /* oplock_request */
1195 open_size, /* allocation_size */
1196 private_flags,
1197 NULL, /* sd */
1198 ea_list, /* ea_list */
1199 &fsp, /* result */
1200 &smb_action); /* psbuf */
1202 if (!NT_STATUS_IS_OK(status)) {
1203 if (open_was_deferred(req->sconn, req->mid)) {
1204 /* We have re-scheduled this call. */
1205 goto out;
1207 reply_openerror(req, status);
1208 goto out;
1211 size = get_file_size_stat(&smb_fname->st);
1212 fattr = dos_mode(conn, smb_fname);
1213 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1214 inode = smb_fname->st.st_ex_ino;
1215 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1216 close_file(req, fsp, ERROR_CLOSE);
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 goto out;
1221 /* Realloc the size of parameters and data we will return */
1222 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1223 if(*pparams == NULL ) {
1224 reply_nterror(req, NT_STATUS_NO_MEMORY);
1225 goto out;
1227 params = *pparams;
1229 SSVAL(params,0,fsp->fnum);
1230 SSVAL(params,2,fattr);
1231 srv_put_dos_date2(params,4, mtime);
1232 SIVAL(params,8, (uint32)size);
1233 SSVAL(params,12,deny_mode);
1234 SSVAL(params,14,0); /* open_type - file or directory. */
1235 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1237 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1238 smb_action |= EXTENDED_OPLOCK_GRANTED;
1241 SSVAL(params,18,smb_action);
1244 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1246 SIVAL(params,20,inode);
1247 SSVAL(params,24,0); /* Padding. */
1248 if (flags & 8) {
1249 uint32 ea_size = estimate_ea_size(conn, fsp,
1250 smb_fname);
1251 SIVAL(params, 26, ea_size);
1252 } else {
1253 SIVAL(params, 26, 0);
1256 /* Send the required number of replies */
1257 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1258 out:
1259 TALLOC_FREE(smb_fname);
1262 /*********************************************************
1263 Routine to check if a given string matches exactly.
1264 as a special case a mask of "." does NOT match. That
1265 is required for correct wildcard semantics
1266 Case can be significant or not.
1267 **********************************************************/
1269 static bool exact_match(bool has_wild,
1270 bool case_sensitive,
1271 const char *str,
1272 const char *mask)
1274 if (mask[0] == '.' && mask[1] == 0) {
1275 return false;
1278 if (has_wild) {
1279 return false;
1282 if (case_sensitive) {
1283 return strcmp(str,mask)==0;
1284 } else {
1285 return strcasecmp_m(str,mask) == 0;
1289 /****************************************************************************
1290 Return the filetype for UNIX extensions.
1291 ****************************************************************************/
1293 static uint32 unix_filetype(mode_t mode)
1295 if(S_ISREG(mode))
1296 return UNIX_TYPE_FILE;
1297 else if(S_ISDIR(mode))
1298 return UNIX_TYPE_DIR;
1299 #ifdef S_ISLNK
1300 else if(S_ISLNK(mode))
1301 return UNIX_TYPE_SYMLINK;
1302 #endif
1303 #ifdef S_ISCHR
1304 else if(S_ISCHR(mode))
1305 return UNIX_TYPE_CHARDEV;
1306 #endif
1307 #ifdef S_ISBLK
1308 else if(S_ISBLK(mode))
1309 return UNIX_TYPE_BLKDEV;
1310 #endif
1311 #ifdef S_ISFIFO
1312 else if(S_ISFIFO(mode))
1313 return UNIX_TYPE_FIFO;
1314 #endif
1315 #ifdef S_ISSOCK
1316 else if(S_ISSOCK(mode))
1317 return UNIX_TYPE_SOCKET;
1318 #endif
1320 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1321 return UNIX_TYPE_UNKNOWN;
1324 /****************************************************************************
1325 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1326 ****************************************************************************/
1328 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1330 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1331 const SMB_STRUCT_STAT *psbuf,
1332 uint32 perms,
1333 enum perm_type ptype,
1334 mode_t *ret_perms)
1336 mode_t ret = 0;
1338 if (perms == SMB_MODE_NO_CHANGE) {
1339 if (!VALID_STAT(*psbuf)) {
1340 return NT_STATUS_INVALID_PARAMETER;
1341 } else {
1342 *ret_perms = psbuf->st_ex_mode;
1343 return NT_STATUS_OK;
1347 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1348 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1349 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1350 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1351 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1352 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1353 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1354 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1355 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1356 #ifdef S_ISVTX
1357 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1358 #endif
1359 #ifdef S_ISGID
1360 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1361 #endif
1362 #ifdef S_ISUID
1363 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1364 #endif
1366 switch (ptype) {
1367 case PERM_NEW_FILE:
1368 case PERM_EXISTING_FILE:
1369 /* Apply mode mask */
1370 ret &= lp_create_mask(SNUM(conn));
1371 /* Add in force bits */
1372 ret |= lp_force_create_mode(SNUM(conn));
1373 break;
1374 case PERM_NEW_DIR:
1375 case PERM_EXISTING_DIR:
1376 ret &= lp_dir_mask(SNUM(conn));
1377 /* Add in force bits */
1378 ret |= lp_force_dir_mode(SNUM(conn));
1379 break;
1382 *ret_perms = ret;
1383 return NT_STATUS_OK;
1386 /****************************************************************************
1387 Needed to show the msdfs symlinks as directories. Modifies psbuf
1388 to be a directory if it's a msdfs link.
1389 ****************************************************************************/
1391 static bool check_msdfs_link(connection_struct *conn,
1392 const char *pathname,
1393 SMB_STRUCT_STAT *psbuf)
1395 int saved_errno = errno;
1396 if(lp_host_msdfs() &&
1397 lp_msdfs_root(SNUM(conn)) &&
1398 is_msdfs_link(conn, pathname, psbuf)) {
1400 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1401 "as a directory\n",
1402 pathname));
1403 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1404 errno = saved_errno;
1405 return true;
1407 errno = saved_errno;
1408 return false;
1412 /****************************************************************************
1413 Get a level dependent lanman2 dir entry.
1414 ****************************************************************************/
1416 struct smbd_dirptr_lanman2_state {
1417 connection_struct *conn;
1418 uint32_t info_level;
1419 bool check_mangled_names;
1420 bool has_wild;
1421 bool got_exact_match;
1424 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1425 void *private_data,
1426 const char *dname,
1427 const char *mask,
1428 char **_fname)
1430 struct smbd_dirptr_lanman2_state *state =
1431 (struct smbd_dirptr_lanman2_state *)private_data;
1432 bool ok;
1433 char mangled_name[13]; /* mangled 8.3 name. */
1434 bool got_match;
1435 const char *fname;
1437 /* Mangle fname if it's an illegal name. */
1438 if (mangle_must_mangle(dname, state->conn->params)) {
1439 ok = name_to_8_3(dname, mangled_name,
1440 true, state->conn->params);
1441 if (!ok) {
1442 return false;
1444 fname = mangled_name;
1445 } else {
1446 fname = dname;
1449 got_match = exact_match(state->has_wild,
1450 state->conn->case_sensitive,
1451 fname, mask);
1452 state->got_exact_match = got_match;
1453 if (!got_match) {
1454 got_match = mask_match(fname, mask,
1455 state->conn->case_sensitive);
1458 if(!got_match && state->check_mangled_names &&
1459 !mangle_is_8_3(fname, false, state->conn->params)) {
1461 * It turns out that NT matches wildcards against
1462 * both long *and* short names. This may explain some
1463 * of the wildcard wierdness from old DOS clients
1464 * that some people have been seeing.... JRA.
1466 /* Force the mangling into 8.3. */
1467 ok = name_to_8_3(fname, mangled_name,
1468 false, state->conn->params);
1469 if (!ok) {
1470 return false;
1473 got_match = exact_match(state->has_wild,
1474 state->conn->case_sensitive,
1475 mangled_name, mask);
1476 state->got_exact_match = got_match;
1477 if (!got_match) {
1478 got_match = mask_match(mangled_name, mask,
1479 state->conn->case_sensitive);
1483 if (!got_match) {
1484 return false;
1487 *_fname = talloc_strdup(ctx, fname);
1488 if (*_fname == NULL) {
1489 return false;
1492 return true;
1495 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1496 void *private_data,
1497 struct smb_filename *smb_fname,
1498 uint32_t *_mode)
1500 struct smbd_dirptr_lanman2_state *state =
1501 (struct smbd_dirptr_lanman2_state *)private_data;
1502 bool ms_dfs_link = false;
1503 uint32_t mode = 0;
1505 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1506 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1507 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1508 "Couldn't lstat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname),
1510 strerror(errno)));
1511 return false;
1513 } else if (!VALID_STAT(smb_fname->st) &&
1514 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1515 /* Needed to show the msdfs symlinks as
1516 * directories */
1518 ms_dfs_link = check_msdfs_link(state->conn,
1519 smb_fname->base_name,
1520 &smb_fname->st);
1521 if (!ms_dfs_link) {
1522 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1523 "Couldn't stat [%s] (%s)\n",
1524 smb_fname_str_dbg(smb_fname),
1525 strerror(errno)));
1526 return false;
1530 if (ms_dfs_link) {
1531 mode = dos_mode_msdfs(state->conn, smb_fname);
1532 } else {
1533 mode = dos_mode(state->conn, smb_fname);
1536 *_mode = mode;
1537 return true;
1540 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1541 connection_struct *conn,
1542 uint16_t flags2,
1543 uint32_t info_level,
1544 struct ea_list *name_list,
1545 bool check_mangled_names,
1546 bool requires_resume_key,
1547 uint32_t mode,
1548 const char *fname,
1549 const struct smb_filename *smb_fname,
1550 int space_remaining,
1551 uint8_t align,
1552 bool do_pad,
1553 char *base_data,
1554 char **ppdata,
1555 char *end_data,
1556 bool *out_of_space,
1557 uint64_t *last_entry_off)
1559 char *p, *q, *pdata = *ppdata;
1560 uint32_t reskey=0;
1561 uint64_t file_size = 0;
1562 uint64_t allocation_size = 0;
1563 uint64_t file_index = 0;
1564 uint32_t len;
1565 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1566 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1567 char *nameptr;
1568 char *last_entry_ptr;
1569 bool was_8_3;
1570 int off;
1571 int pad = 0;
1573 *out_of_space = false;
1575 ZERO_STRUCT(mdate_ts);
1576 ZERO_STRUCT(adate_ts);
1577 ZERO_STRUCT(create_date_ts);
1578 ZERO_STRUCT(cdate_ts);
1580 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1581 file_size = get_file_size_stat(&smb_fname->st);
1583 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1585 file_index = get_FileIndex(conn, &smb_fname->st);
1587 mdate_ts = smb_fname->st.st_ex_mtime;
1588 adate_ts = smb_fname->st.st_ex_atime;
1589 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1590 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1592 if (lp_dos_filetime_resolution(SNUM(conn))) {
1593 dos_filetime_timespec(&create_date_ts);
1594 dos_filetime_timespec(&mdate_ts);
1595 dos_filetime_timespec(&adate_ts);
1596 dos_filetime_timespec(&cdate_ts);
1599 create_date = convert_timespec_to_time_t(create_date_ts);
1600 mdate = convert_timespec_to_time_t(mdate_ts);
1601 adate = convert_timespec_to_time_t(adate_ts);
1603 /* align the record */
1604 SMB_ASSERT(align >= 1);
1606 off = (int)PTR_DIFF(pdata, base_data);
1607 pad = (off + (align-1)) & ~(align-1);
1608 pad -= off;
1610 if (pad && pad > space_remaining) {
1611 *out_of_space = true;
1612 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1613 "for padding (wanted %u, had %d)\n",
1614 (unsigned int)pad,
1615 space_remaining ));
1616 return false; /* Not finished - just out of space */
1619 off += pad;
1620 /* initialize padding to 0 */
1621 if (pad) {
1622 memset(pdata, 0, pad);
1624 space_remaining -= pad;
1626 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1627 space_remaining ));
1629 pdata += pad;
1630 p = pdata;
1631 last_entry_ptr = p;
1633 pad = 0;
1634 off = 0;
1636 switch (info_level) {
1637 case SMB_FIND_INFO_STANDARD:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1639 if(requires_resume_key) {
1640 SIVAL(p,0,reskey);
1641 p += 4;
1643 srv_put_dos_date2(p,0,create_date);
1644 srv_put_dos_date2(p,4,adate);
1645 srv_put_dos_date2(p,8,mdate);
1646 SIVAL(p,12,(uint32)file_size);
1647 SIVAL(p,16,(uint32)allocation_size);
1648 SSVAL(p,20,mode);
1649 p += 23;
1650 nameptr = p;
1651 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1652 p += ucs2_align(base_data, p, 0);
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE);
1657 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 if (len > 2) {
1659 SCVAL(nameptr, -1, len - 2);
1660 } else {
1661 SCVAL(nameptr, -1, 0);
1663 } else {
1664 if (len > 1) {
1665 SCVAL(nameptr, -1, len - 1);
1666 } else {
1667 SCVAL(nameptr, -1, 0);
1670 p += len;
1671 break;
1673 case SMB_FIND_EA_SIZE:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1675 if (requires_resume_key) {
1676 SIVAL(p,0,reskey);
1677 p += 4;
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1684 SSVAL(p,20,mode);
1686 unsigned int ea_size = estimate_ea_size(conn, NULL,
1687 smb_fname);
1688 SIVAL(p,22,ea_size); /* Extended attributes */
1690 p += 27;
1691 nameptr = p - 1;
1692 len = srvstr_push(base_data, flags2,
1693 p, fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE | STR_NOALIGN);
1695 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1696 if (len > 2) {
1697 len -= 2;
1698 } else {
1699 len = 0;
1701 } else {
1702 if (len > 1) {
1703 len -= 1;
1704 } else {
1705 len = 0;
1708 SCVAL(nameptr,0,len);
1709 p += len;
1710 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1711 break;
1713 case SMB_FIND_EA_LIST:
1715 struct ea_list *file_list = NULL;
1716 size_t ea_len = 0;
1717 NTSTATUS status;
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1720 if (!name_list) {
1721 return false;
1723 if (requires_resume_key) {
1724 SIVAL(p,0,reskey);
1725 p += 4;
1727 srv_put_dos_date2(p,0,create_date);
1728 srv_put_dos_date2(p,4,adate);
1729 srv_put_dos_date2(p,8,mdate);
1730 SIVAL(p,12,(uint32)file_size);
1731 SIVAL(p,16,(uint32)allocation_size);
1732 SSVAL(p,20,mode);
1733 p += 22; /* p now points to the EA area. */
1735 status = get_ea_list_from_file(ctx, conn, NULL,
1736 smb_fname,
1737 &ea_len, &file_list);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 file_list = NULL;
1741 name_list = ea_list_union(name_list, file_list, &ea_len);
1743 /* We need to determine if this entry will fit in the space available. */
1744 /* Max string size is 255 bytes. */
1745 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1746 *out_of_space = true;
1747 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1748 "(wanted %u, had %d)\n",
1749 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1750 space_remaining ));
1751 return False; /* Not finished - just out of space */
1754 /* Push the ea_data followed by the name. */
1755 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1756 nameptr = p;
1757 len = srvstr_push(base_data, flags2,
1758 p + 1, fname, PTR_DIFF(end_data, p+1),
1759 STR_TERMINATE | STR_NOALIGN);
1760 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1761 if (len > 2) {
1762 len -= 2;
1763 } else {
1764 len = 0;
1766 } else {
1767 if (len > 1) {
1768 len -= 1;
1769 } else {
1770 len = 0;
1773 SCVAL(nameptr,0,len);
1774 p += len + 1;
1775 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1776 break;
1779 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1781 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1782 p += 4;
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,mode); p += 4;
1791 q = p; p += 4; /* q is placeholder for name length. */
1793 unsigned int ea_size = estimate_ea_size(conn, NULL,
1794 smb_fname);
1795 SIVAL(p,0,ea_size); /* Extended attributes */
1796 p += 4;
1798 /* Clear the short name buffer. This is
1799 * IMPORTANT as not doing so will trigger
1800 * a Win2k client bug. JRA.
1802 if (!was_8_3 && check_mangled_names) {
1803 char mangled_name[13]; /* mangled 8.3 name. */
1804 if (!name_to_8_3(fname,mangled_name,True,
1805 conn->params)) {
1806 /* Error - mangle failed ! */
1807 memset(mangled_name,'\0',12);
1809 mangled_name[12] = 0;
1810 len = srvstr_push(base_data, flags2,
1811 p+2, mangled_name, 24,
1812 STR_UPPER|STR_UNICODE);
1813 if (len < 24) {
1814 memset(p + 2 + len,'\0',24 - len);
1816 SSVAL(p, 0, len);
1817 } else {
1818 memset(p,'\0',26);
1820 p += 2 + 24;
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE_ASCII);
1824 SIVAL(q,0,len);
1825 p += len;
1827 len = PTR_DIFF(p, pdata);
1828 pad = (len + (align-1)) & ~(align-1);
1830 * offset to the next entry, the caller
1831 * will overwrite it for the last entry
1832 * that's why we always include the padding
1834 SIVAL(pdata,0,pad);
1836 * set padding to zero
1838 if (do_pad) {
1839 memset(p, 0, pad - len);
1840 p = pdata + pad;
1841 } else {
1842 p = pdata + len;
1844 break;
1846 case SMB_FIND_FILE_DIRECTORY_INFO:
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1848 p += 4;
1849 SIVAL(p,0,reskey); p += 4;
1850 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1851 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1852 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1853 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1854 SOFF_T(p,0,file_size); p += 8;
1855 SOFF_T(p,0,allocation_size); p += 8;
1856 SIVAL(p,0,mode); p += 4;
1857 len = srvstr_push(base_data, flags2,
1858 p + 4, fname, PTR_DIFF(end_data, p+4),
1859 STR_TERMINATE_ASCII);
1860 SIVAL(p,0,len);
1861 p += 4 + len;
1863 len = PTR_DIFF(p, pdata);
1864 pad = (len + (align-1)) & ~(align-1);
1866 * offset to the next entry, the caller
1867 * will overwrite it for the last entry
1868 * that's why we always include the padding
1870 SIVAL(pdata,0,pad);
1872 * set padding to zero
1874 if (do_pad) {
1875 memset(p, 0, pad - len);
1876 p = pdata + pad;
1877 } else {
1878 p = pdata + len;
1880 break;
1882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1883 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1884 p += 4;
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1888 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1889 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,mode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length. */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL,
1896 smb_fname);
1897 SIVAL(p,0,ea_size); /* Extended attributes */
1898 p +=4;
1900 len = srvstr_push(base_data, flags2, p,
1901 fname, PTR_DIFF(end_data, p),
1902 STR_TERMINATE_ASCII);
1903 SIVAL(q, 0, len);
1904 p += len;
1906 len = PTR_DIFF(p, pdata);
1907 pad = (len + (align-1)) & ~(align-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1913 SIVAL(pdata,0,pad);
1915 * set padding to zero
1917 if (do_pad) {
1918 memset(p, 0, pad - len);
1919 p = pdata + pad;
1920 } else {
1921 p = pdata + len;
1923 break;
1925 case SMB_FIND_FILE_NAMES_INFO:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1927 p += 4;
1928 SIVAL(p,0,reskey); p += 4;
1929 p += 4;
1930 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1931 acl on a dir (tridge) */
1932 len = srvstr_push(base_data, flags2, p,
1933 fname, PTR_DIFF(end_data, p),
1934 STR_TERMINATE_ASCII);
1935 SIVAL(p, -4, len);
1936 p += len;
1938 len = PTR_DIFF(p, pdata);
1939 pad = (len + (align-1)) & ~(align-1);
1941 * offset to the next entry, the caller
1942 * will overwrite it for the last entry
1943 * that's why we always include the padding
1945 SIVAL(pdata,0,pad);
1947 * set padding to zero
1949 if (do_pad) {
1950 memset(p, 0, pad - len);
1951 p = pdata + pad;
1952 } else {
1953 p = pdata + len;
1955 break;
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1958 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1959 p += 4;
1960 SIVAL(p,0,reskey); p += 4;
1961 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1962 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1963 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1964 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1965 SOFF_T(p,0,file_size); p += 8;
1966 SOFF_T(p,0,allocation_size); p += 8;
1967 SIVAL(p,0,mode); p += 4;
1968 q = p; p += 4; /* q is placeholder for name length. */
1970 unsigned int ea_size = estimate_ea_size(conn, NULL,
1971 smb_fname);
1972 SIVAL(p,0,ea_size); /* Extended attributes */
1973 p +=4;
1975 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1976 SBVAL(p,0,file_index); p += 8;
1977 len = srvstr_push(base_data, flags2, p,
1978 fname, PTR_DIFF(end_data, p),
1979 STR_TERMINATE_ASCII);
1980 SIVAL(q, 0, len);
1981 p += len;
1983 len = PTR_DIFF(p, pdata);
1984 pad = (len + (align-1)) & ~(align-1);
1986 * offset to the next entry, the caller
1987 * will overwrite it for the last entry
1988 * that's why we always include the padding
1990 SIVAL(pdata,0,pad);
1992 * set padding to zero
1994 if (do_pad) {
1995 memset(p, 0, pad - len);
1996 p = pdata + pad;
1997 } else {
1998 p = pdata + len;
2000 break;
2002 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 p += 4;
2006 SIVAL(p,0,reskey); p += 4;
2007 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2010 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2011 SOFF_T(p,0,file_size); p += 8;
2012 SOFF_T(p,0,allocation_size); p += 8;
2013 SIVAL(p,0,mode); p += 4;
2014 q = p; p += 4; /* q is placeholder for name length */
2016 unsigned int ea_size = estimate_ea_size(conn, NULL,
2017 smb_fname);
2018 SIVAL(p,0,ea_size); /* Extended attributes */
2019 p +=4;
2021 /* Clear the short name buffer. This is
2022 * IMPORTANT as not doing so will trigger
2023 * a Win2k client bug. JRA.
2025 if (!was_8_3 && check_mangled_names) {
2026 char mangled_name[13]; /* mangled 8.3 name. */
2027 if (!name_to_8_3(fname,mangled_name,True,
2028 conn->params)) {
2029 /* Error - mangle failed ! */
2030 memset(mangled_name,'\0',12);
2032 mangled_name[12] = 0;
2033 len = srvstr_push(base_data, flags2,
2034 p+2, mangled_name, 24,
2035 STR_UPPER|STR_UNICODE);
2036 SSVAL(p, 0, len);
2037 if (len < 24) {
2038 memset(p + 2 + len,'\0',24 - len);
2040 SSVAL(p, 0, len);
2041 } else {
2042 memset(p,'\0',26);
2044 p += 26;
2045 SSVAL(p,0,0); p += 2; /* Reserved ? */
2046 SBVAL(p,0,file_index); p += 8;
2047 len = srvstr_push(base_data, flags2, p,
2048 fname, PTR_DIFF(end_data, p),
2049 STR_TERMINATE_ASCII);
2050 SIVAL(q,0,len);
2051 p += len;
2053 len = PTR_DIFF(p, pdata);
2054 pad = (len + (align-1)) & ~(align-1);
2056 * offset to the next entry, the caller
2057 * will overwrite it for the last entry
2058 * that's why we always include the padding
2060 SIVAL(pdata,0,pad);
2062 * set padding to zero
2064 if (do_pad) {
2065 memset(p, 0, pad - len);
2066 p = pdata + pad;
2067 } else {
2068 p = pdata + len;
2070 break;
2072 /* CIFS UNIX Extension. */
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 p+= 4;
2077 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2079 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2081 if (info_level == SMB_FIND_FILE_UNIX) {
2082 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2083 p = store_file_unix_basic(conn, p,
2084 NULL, &smb_fname->st);
2085 len = srvstr_push(base_data, flags2, p,
2086 fname, PTR_DIFF(end_data, p),
2087 STR_TERMINATE);
2088 } else {
2089 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2090 p = store_file_unix_basic_info2(conn, p,
2091 NULL, &smb_fname->st);
2092 nameptr = p;
2093 p += 4;
2094 len = srvstr_push(base_data, flags2, p, fname,
2095 PTR_DIFF(end_data, p), 0);
2096 SIVAL(nameptr, 0, len);
2099 p += len;
2101 len = PTR_DIFF(p, pdata);
2102 pad = (len + (align-1)) & ~(align-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2108 SIVAL(pdata,0,pad);
2110 * set padding to zero
2112 if (do_pad) {
2113 memset(p, 0, pad - len);
2114 p = pdata + pad;
2115 } else {
2116 p = pdata + len;
2118 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2120 break;
2122 default:
2123 return false;
2126 if (PTR_DIFF(p,pdata) > space_remaining) {
2127 *out_of_space = true;
2128 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2129 "(wanted %u, had %d)\n",
2130 (unsigned int)PTR_DIFF(p,pdata),
2131 space_remaining ));
2132 return false; /* Not finished - just out of space */
2135 /* Setup the last entry pointer, as an offset from base_data */
2136 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2137 /* Advance the data pointer to the next slot */
2138 *ppdata = p;
2140 return true;
2143 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2144 connection_struct *conn,
2145 struct dptr_struct *dirptr,
2146 uint16 flags2,
2147 const char *path_mask,
2148 uint32 dirtype,
2149 int info_level,
2150 int requires_resume_key,
2151 bool dont_descend,
2152 bool ask_sharemode,
2153 uint8_t align,
2154 bool do_pad,
2155 char **ppdata,
2156 char *base_data,
2157 char *end_data,
2158 int space_remaining,
2159 bool *out_of_space,
2160 bool *got_exact_match,
2161 int *_last_entry_off,
2162 struct ea_list *name_list)
2164 const char *p;
2165 const char *mask = NULL;
2166 long prev_dirpos = 0;
2167 uint32_t mode = 0;
2168 char *fname = NULL;
2169 struct smb_filename *smb_fname = NULL;
2170 struct smbd_dirptr_lanman2_state state;
2171 bool ok;
2172 uint64_t last_entry_off = 0;
2174 ZERO_STRUCT(state);
2175 state.conn = conn;
2176 state.info_level = info_level;
2177 state.check_mangled_names = lp_manglednames(conn->params);
2178 state.has_wild = dptr_has_wild(dirptr);
2179 state.got_exact_match = false;
2181 *out_of_space = false;
2182 *got_exact_match = false;
2184 p = strrchr_m(path_mask,'/');
2185 if(p != NULL) {
2186 if(p[1] == '\0') {
2187 mask = "*.*";
2188 } else {
2189 mask = p+1;
2191 } else {
2192 mask = path_mask;
2195 ok = smbd_dirptr_get_entry(ctx,
2196 dirptr,
2197 mask,
2198 dirtype,
2199 dont_descend,
2200 ask_sharemode,
2201 smbd_dirptr_lanman2_match_fn,
2202 smbd_dirptr_lanman2_mode_fn,
2203 &state,
2204 &fname,
2205 &smb_fname,
2206 &mode,
2207 &prev_dirpos);
2208 if (!ok) {
2209 return false;
2212 *got_exact_match = state.got_exact_match;
2214 ok = smbd_marshall_dir_entry(ctx,
2215 conn,
2216 flags2,
2217 info_level,
2218 name_list,
2219 state.check_mangled_names,
2220 requires_resume_key,
2221 mode,
2222 fname,
2223 smb_fname,
2224 space_remaining,
2225 align,
2226 do_pad,
2227 base_data,
2228 ppdata,
2229 end_data,
2230 out_of_space,
2231 &last_entry_off);
2232 TALLOC_FREE(fname);
2233 TALLOC_FREE(smb_fname);
2234 if (*out_of_space) {
2235 dptr_SeekDir(dirptr, prev_dirpos);
2236 return false;
2238 if (!ok) {
2239 return false;
2242 *_last_entry_off = last_entry_off;
2243 return true;
2246 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2247 connection_struct *conn,
2248 struct dptr_struct *dirptr,
2249 uint16 flags2,
2250 const char *path_mask,
2251 uint32 dirtype,
2252 int info_level,
2253 bool requires_resume_key,
2254 bool dont_descend,
2255 bool ask_sharemode,
2256 char **ppdata,
2257 char *base_data,
2258 char *end_data,
2259 int space_remaining,
2260 bool *out_of_space,
2261 bool *got_exact_match,
2262 int *last_entry_off,
2263 struct ea_list *name_list)
2265 uint8_t align = 4;
2266 const bool do_pad = true;
2268 if (info_level >= 1 && info_level <= 3) {
2269 /* No alignment on earlier info levels. */
2270 align = 1;
2273 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2274 path_mask, dirtype, info_level,
2275 requires_resume_key, dont_descend, ask_sharemode,
2276 align, do_pad,
2277 ppdata, base_data, end_data,
2278 space_remaining,
2279 out_of_space, got_exact_match,
2280 last_entry_off, name_list);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDFIRST.
2285 ****************************************************************************/
2287 static void call_trans2findfirst(connection_struct *conn,
2288 struct smb_request *req,
2289 char **pparams, int total_params,
2290 char **ppdata, int total_data,
2291 unsigned int max_data_bytes)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2297 requested. */
2298 struct smb_filename *smb_dname = NULL;
2299 char *params = *pparams;
2300 char *pdata = *ppdata;
2301 char *data_end;
2302 uint32 dirtype;
2303 int maxentries;
2304 uint16 findfirst_flags;
2305 bool close_after_first;
2306 bool close_if_end;
2307 bool requires_resume_key;
2308 int info_level;
2309 char *directory = NULL;
2310 char *mask = NULL;
2311 char *p;
2312 int last_entry_off=0;
2313 int dptr_num = -1;
2314 int numentries = 0;
2315 int i;
2316 bool finished = False;
2317 bool dont_descend = False;
2318 bool out_of_space = False;
2319 int space_remaining;
2320 bool mask_contains_wcard = False;
2321 struct ea_list *ea_list = NULL;
2322 NTSTATUS ntstatus = NT_STATUS_OK;
2323 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX *ctx = talloc_tos();
2325 struct dptr_struct *dirptr = NULL;
2326 struct smbd_server_connection *sconn = req->sconn;
2327 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2328 bool backup_priv = false;
2330 if (total_params < 13) {
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 goto out;
2335 dirtype = SVAL(params,0);
2336 maxentries = SVAL(params,2);
2337 findfirst_flags = SVAL(params,4);
2338 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2339 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2340 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2341 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2342 security_token_has_privilege(get_current_nttok(conn),
2343 SEC_PRIV_BACKUP));
2345 info_level = SVAL(params,6);
2347 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2348 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2349 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2350 (int)backup_priv,
2351 info_level, max_data_bytes));
2353 if (!maxentries) {
2354 /* W2K3 seems to treat zero as 1. */
2355 maxentries = 1;
2358 switch (info_level) {
2359 case SMB_FIND_INFO_STANDARD:
2360 case SMB_FIND_EA_SIZE:
2361 case SMB_FIND_EA_LIST:
2362 case SMB_FIND_FILE_DIRECTORY_INFO:
2363 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2364 case SMB_FIND_FILE_NAMES_INFO:
2365 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2366 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2367 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2368 break;
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2371 /* Always use filesystem for UNIX mtime query. */
2372 ask_sharemode = false;
2373 if (!lp_unix_extensions()) {
2374 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2375 goto out;
2377 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2378 break;
2379 default:
2380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2381 goto out;
2384 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2385 params+12, total_params - 12,
2386 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2387 if (!NT_STATUS_IS_OK(ntstatus)) {
2388 reply_nterror(req, ntstatus);
2389 goto out;
2392 if (backup_priv) {
2393 become_root();
2394 ntstatus = filename_convert_with_privilege(ctx,
2395 conn,
2396 req,
2397 directory,
2398 ucf_flags,
2399 &mask_contains_wcard,
2400 &smb_dname);
2401 } else {
2402 ntstatus = filename_convert(ctx, conn,
2403 req->flags2 & FLAGS2_DFS_PATHNAMES,
2404 directory,
2405 ucf_flags,
2406 &mask_contains_wcard,
2407 &smb_dname);
2410 if (!NT_STATUS_IS_OK(ntstatus)) {
2411 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2412 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2413 ERRSRV, ERRbadpath);
2414 goto out;
2416 reply_nterror(req, ntstatus);
2417 goto out;
2420 mask = smb_dname->original_lcomp;
2422 directory = smb_dname->base_name;
2424 p = strrchr_m(directory,'/');
2425 if(p == NULL) {
2426 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2427 if((directory[0] == '.') && (directory[1] == '\0')) {
2428 mask = talloc_strdup(ctx,"*");
2429 if (!mask) {
2430 reply_nterror(req, NT_STATUS_NO_MEMORY);
2431 goto out;
2433 mask_contains_wcard = True;
2435 } else {
2436 *p = 0;
2439 if (p == NULL || p == directory) {
2440 /* Ensure we don't have a directory name of "". */
2441 directory = talloc_strdup(talloc_tos(), ".");
2442 if (!directory) {
2443 reply_nterror(req, NT_STATUS_NO_MEMORY);
2444 goto out;
2448 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2450 if (info_level == SMB_FIND_EA_LIST) {
2451 uint32 ea_size;
2453 if (total_data < 4) {
2454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2455 goto out;
2458 ea_size = IVAL(pdata,0);
2459 if (ea_size != total_data) {
2460 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2461 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2463 goto out;
2466 if (!lp_ea_support(SNUM(conn))) {
2467 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2468 goto out;
2471 /* Pull out the list of names. */
2472 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2473 if (!ea_list) {
2474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2475 goto out;
2479 *ppdata = (char *)SMB_REALLOC(
2480 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2481 if(*ppdata == NULL ) {
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 goto out;
2485 pdata = *ppdata;
2486 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2488 /* Realloc the params space */
2489 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2490 if (*pparams == NULL) {
2491 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 goto out;
2494 params = *pparams;
2496 /* Save the wildcard match and attribs we are using on this directory -
2497 needed as lanman2 assumes these are being saved between calls */
2499 ntstatus = dptr_create(conn,
2500 req,
2501 NULL, /* fsp */
2502 directory,
2503 False,
2504 True,
2505 req->smbpid,
2506 mask,
2507 mask_contains_wcard,
2508 dirtype,
2509 &dirptr);
2511 if (!NT_STATUS_IS_OK(ntstatus)) {
2512 reply_nterror(req, ntstatus);
2513 goto out;
2516 if (backup_priv) {
2517 /* Remember this in case we have
2518 to do a findnext. */
2519 dptr_set_priv(dirptr);
2522 dptr_num = dptr_dnum(dirptr);
2523 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2525 /* Initialize per TRANS2_FIND_FIRST operation data */
2526 dptr_init_search_op(dirptr);
2528 /* We don't need to check for VOL here as this is returned by
2529 a different TRANS2 call. */
2531 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2532 directory,lp_dontdescend(ctx, SNUM(conn))));
2533 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2534 dont_descend = True;
2536 p = pdata;
2537 space_remaining = max_data_bytes;
2538 out_of_space = False;
2540 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2541 bool got_exact_match = False;
2543 /* this is a heuristic to avoid seeking the dirptr except when
2544 absolutely necessary. It allows for a filename of about 40 chars */
2545 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2546 out_of_space = True;
2547 finished = False;
2548 } else {
2549 finished = !get_lanman2_dir_entry(ctx,
2550 conn,
2551 dirptr,
2552 req->flags2,
2553 mask,dirtype,info_level,
2554 requires_resume_key,dont_descend,
2555 ask_sharemode,
2556 &p,pdata,data_end,
2557 space_remaining, &out_of_space,
2558 &got_exact_match,
2559 &last_entry_off, ea_list);
2562 if (finished && out_of_space)
2563 finished = False;
2565 if (!finished && !out_of_space)
2566 numentries++;
2569 * As an optimisation if we know we aren't looking
2570 * for a wildcard name (ie. the name matches the wildcard exactly)
2571 * then we can finish on any (first) match.
2572 * This speeds up large directory searches. JRA.
2575 if(got_exact_match)
2576 finished = True;
2578 /* Ensure space_remaining never goes -ve. */
2579 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2580 space_remaining = 0;
2581 out_of_space = true;
2582 } else {
2583 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2587 /* Check if we can close the dirptr */
2588 if(close_after_first || (finished && close_if_end)) {
2589 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2590 dptr_close(sconn, &dptr_num);
2594 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2595 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2596 * the protocol level is less than NT1. Tested with smbclient. JRA.
2597 * This should fix the OS/2 client bug #2335.
2600 if(numentries == 0) {
2601 dptr_close(sconn, &dptr_num);
2602 if (get_Protocol() < PROTOCOL_NT1) {
2603 reply_force_doserror(req, ERRDOS, ERRnofiles);
2604 goto out;
2605 } else {
2606 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2607 ERRDOS, ERRbadfile);
2608 goto out;
2612 /* At this point pdata points to numentries directory entries. */
2614 /* Set up the return parameter block */
2615 SSVAL(params,0,dptr_num);
2616 SSVAL(params,2,numentries);
2617 SSVAL(params,4,finished);
2618 SSVAL(params,6,0); /* Never an EA error */
2619 SSVAL(params,8,last_entry_off);
2621 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2622 max_data_bytes);
2624 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2625 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2626 if (!directory) {
2627 reply_nterror(req, NT_STATUS_NO_MEMORY);
2631 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2632 smb_fn_name(req->cmd),
2633 mask, directory, dirtype, numentries ) );
2636 * Force a name mangle here to ensure that the
2637 * mask as an 8.3 name is top of the mangled cache.
2638 * The reasons for this are subtle. Don't remove
2639 * this code unless you know what you are doing
2640 * (see PR#13758). JRA.
2643 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2644 char mangled_name[13];
2645 name_to_8_3(mask, mangled_name, True, conn->params);
2647 out:
2649 if (backup_priv) {
2650 unbecome_root();
2653 TALLOC_FREE(smb_dname);
2654 return;
2657 /****************************************************************************
2658 Reply to a TRANS2_FINDNEXT.
2659 ****************************************************************************/
2661 static void call_trans2findnext(connection_struct *conn,
2662 struct smb_request *req,
2663 char **pparams, int total_params,
2664 char **ppdata, int total_data,
2665 unsigned int max_data_bytes)
2667 /* We must be careful here that we don't return more than the
2668 allowed number of data bytes. If this means returning fewer than
2669 maxentries then so be it. We assume that the redirector has
2670 enough room for the fixed number of parameter bytes it has
2671 requested. */
2672 char *params = *pparams;
2673 char *pdata = *ppdata;
2674 char *data_end;
2675 int dptr_num;
2676 int maxentries;
2677 uint16 info_level;
2678 uint32 resume_key;
2679 uint16 findnext_flags;
2680 bool close_after_request;
2681 bool close_if_end;
2682 bool requires_resume_key;
2683 bool continue_bit;
2684 bool mask_contains_wcard = False;
2685 char *resume_name = NULL;
2686 const char *mask = NULL;
2687 const char *directory = NULL;
2688 char *p = NULL;
2689 uint16 dirtype;
2690 int numentries = 0;
2691 int i, last_entry_off=0;
2692 bool finished = False;
2693 bool dont_descend = False;
2694 bool out_of_space = False;
2695 int space_remaining;
2696 struct ea_list *ea_list = NULL;
2697 NTSTATUS ntstatus = NT_STATUS_OK;
2698 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2699 TALLOC_CTX *ctx = talloc_tos();
2700 struct dptr_struct *dirptr;
2701 struct smbd_server_connection *sconn = req->sconn;
2702 bool backup_priv = false;
2704 if (total_params < 13) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2709 dptr_num = SVAL(params,0);
2710 maxentries = SVAL(params,2);
2711 info_level = SVAL(params,4);
2712 resume_key = IVAL(params,6);
2713 findnext_flags = SVAL(params,10);
2714 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2715 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2716 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2717 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2719 if (!continue_bit) {
2720 /* We only need resume_name if continue_bit is zero. */
2721 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2722 params+12,
2723 total_params - 12, STR_TERMINATE, &ntstatus,
2724 &mask_contains_wcard);
2725 if (!NT_STATUS_IS_OK(ntstatus)) {
2726 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2727 complain (it thinks we're asking for the directory above the shared
2728 path or an invalid name). Catch this as the resume name is only compared, never used in
2729 a file access. JRA. */
2730 srvstr_pull_talloc(ctx, params, req->flags2,
2731 &resume_name, params+12,
2732 total_params - 12,
2733 STR_TERMINATE);
2735 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2736 reply_nterror(req, ntstatus);
2737 return;
2742 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2743 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2744 resume_key = %d resume name = %s continue=%d level = %d\n",
2745 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2746 requires_resume_key, resume_key,
2747 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2749 if (!maxentries) {
2750 /* W2K3 seems to treat zero as 1. */
2751 maxentries = 1;
2754 switch (info_level) {
2755 case SMB_FIND_INFO_STANDARD:
2756 case SMB_FIND_EA_SIZE:
2757 case SMB_FIND_EA_LIST:
2758 case SMB_FIND_FILE_DIRECTORY_INFO:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2760 case SMB_FIND_FILE_NAMES_INFO:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2764 break;
2765 case SMB_FIND_FILE_UNIX:
2766 case SMB_FIND_FILE_UNIX_INFO2:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode = false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2771 return;
2773 break;
2774 default:
2775 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2776 return;
2779 if (info_level == SMB_FIND_EA_LIST) {
2780 uint32 ea_size;
2782 if (total_data < 4) {
2783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2784 return;
2787 ea_size = IVAL(pdata,0);
2788 if (ea_size != total_data) {
2789 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2790 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2792 return;
2795 if (!lp_ea_support(SNUM(conn))) {
2796 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2797 return;
2800 /* Pull out the list of names. */
2801 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2802 if (!ea_list) {
2803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2804 return;
2808 *ppdata = (char *)SMB_REALLOC(
2809 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2810 if(*ppdata == NULL) {
2811 reply_nterror(req, NT_STATUS_NO_MEMORY);
2812 return;
2815 pdata = *ppdata;
2816 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2818 /* Realloc the params space */
2819 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2820 if(*pparams == NULL ) {
2821 reply_nterror(req, NT_STATUS_NO_MEMORY);
2822 return;
2825 params = *pparams;
2827 /* Check that the dptr is valid */
2828 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2829 reply_nterror(req, STATUS_NO_MORE_FILES);
2830 return;
2833 directory = dptr_path(sconn, dptr_num);
2835 /* Get the wildcard mask from the dptr */
2836 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2837 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2838 reply_nterror(req, STATUS_NO_MORE_FILES);
2839 return;
2842 /* Get the attr mask from the dptr */
2843 dirtype = dptr_attr(sconn, dptr_num);
2845 backup_priv = dptr_get_priv(dirptr);
2847 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2848 "backup_priv = %d\n",
2849 dptr_num, mask, dirtype,
2850 (long)dirptr,
2851 dptr_TellDir(dirptr),
2852 (int)backup_priv));
2854 /* Initialize per TRANS2_FIND_NEXT operation data */
2855 dptr_init_search_op(dirptr);
2857 /* We don't need to check for VOL here as this is returned by
2858 a different TRANS2 call. */
2860 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2861 directory,lp_dontdescend(ctx, SNUM(conn))));
2862 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2863 dont_descend = True;
2865 p = pdata;
2866 space_remaining = max_data_bytes;
2867 out_of_space = False;
2869 if (backup_priv) {
2870 become_root();
2874 * Seek to the correct position. We no longer use the resume key but
2875 * depend on the last file name instead.
2878 if(!continue_bit && resume_name && *resume_name) {
2879 SMB_STRUCT_STAT st;
2881 long current_pos = 0;
2883 * Remember, name_to_8_3 is called by
2884 * get_lanman2_dir_entry(), so the resume name
2885 * could be mangled. Ensure we check the unmangled name.
2888 if (mangle_is_mangled(resume_name, conn->params)) {
2889 char *new_resume_name = NULL;
2890 mangle_lookup_name_from_8_3(ctx,
2891 resume_name,
2892 &new_resume_name,
2893 conn->params);
2894 if (new_resume_name) {
2895 resume_name = new_resume_name;
2900 * Fix for NT redirector problem triggered by resume key indexes
2901 * changing between directory scans. We now return a resume key of 0
2902 * and instead look for the filename to continue from (also given
2903 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2904 * findfirst/findnext (as is usual) then the directory pointer
2905 * should already be at the correct place.
2908 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2909 } /* end if resume_name && !continue_bit */
2911 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2912 bool got_exact_match = False;
2914 /* this is a heuristic to avoid seeking the dirptr except when
2915 absolutely necessary. It allows for a filename of about 40 chars */
2916 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2917 out_of_space = True;
2918 finished = False;
2919 } else {
2920 finished = !get_lanman2_dir_entry(ctx,
2921 conn,
2922 dirptr,
2923 req->flags2,
2924 mask,dirtype,info_level,
2925 requires_resume_key,dont_descend,
2926 ask_sharemode,
2927 &p,pdata,data_end,
2928 space_remaining, &out_of_space,
2929 &got_exact_match,
2930 &last_entry_off, ea_list);
2933 if (finished && out_of_space)
2934 finished = False;
2936 if (!finished && !out_of_space)
2937 numentries++;
2940 * As an optimisation if we know we aren't looking
2941 * for a wildcard name (ie. the name matches the wildcard exactly)
2942 * then we can finish on any (first) match.
2943 * This speeds up large directory searches. JRA.
2946 if(got_exact_match)
2947 finished = True;
2949 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2952 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2953 smb_fn_name(req->cmd),
2954 mask, directory, dirtype, numentries ) );
2956 /* Check if we can close the dirptr */
2957 if(close_after_request || (finished && close_if_end)) {
2958 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2959 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2962 if (backup_priv) {
2963 unbecome_root();
2966 /* Set up the return parameter block */
2967 SSVAL(params,0,numentries);
2968 SSVAL(params,2,finished);
2969 SSVAL(params,4,0); /* Never an EA error */
2970 SSVAL(params,6,last_entry_off);
2972 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2973 max_data_bytes);
2975 return;
2978 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2980 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2981 return objid;
2984 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2986 SMB_ASSERT(extended_info != NULL);
2988 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2989 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2990 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2991 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2992 #ifdef SAMBA_VERSION_REVISION
2993 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2994 #endif
2995 extended_info->samba_subversion = 0;
2996 #ifdef SAMBA_VERSION_RC_RELEASE
2997 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2998 #else
2999 #ifdef SAMBA_VERSION_PRE_RELEASE
3000 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3001 #endif
3002 #endif
3003 #ifdef SAMBA_VERSION_VENDOR_PATCH
3004 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3005 #endif
3006 extended_info->samba_gitcommitdate = 0;
3007 #ifdef SAMBA_VERSION_COMMIT_TIME
3008 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3009 #endif
3011 memset(extended_info->samba_version_string, 0,
3012 sizeof(extended_info->samba_version_string));
3014 snprintf (extended_info->samba_version_string,
3015 sizeof(extended_info->samba_version_string),
3016 "%s", samba_version_string());
3019 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3020 TALLOC_CTX *mem_ctx,
3021 uint16_t info_level,
3022 uint16_t flags2,
3023 unsigned int max_data_bytes,
3024 struct smb_filename *fname,
3025 char **ppdata,
3026 int *ret_data_len)
3028 char *pdata, *end_data;
3029 int data_len = 0, len;
3030 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3031 int snum = SNUM(conn);
3032 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3033 char *filename = NULL;
3034 uint32 additional_flags = 0;
3035 struct smb_filename smb_fname;
3036 SMB_STRUCT_STAT st;
3038 if (fname == NULL || fname->base_name == NULL) {
3039 filename = ".";
3040 } else {
3041 filename = fname->base_name;
3044 if (IS_IPC(conn)) {
3045 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3046 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3047 "info level (0x%x) on IPC$.\n",
3048 (unsigned int)info_level));
3049 return NT_STATUS_ACCESS_DENIED;
3053 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3055 ZERO_STRUCT(smb_fname);
3056 smb_fname.base_name = discard_const_p(char, filename);
3058 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3059 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3060 return map_nt_error_from_unix(errno);
3063 st = smb_fname.st;
3065 *ppdata = (char *)SMB_REALLOC(
3066 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3067 if (*ppdata == NULL) {
3068 return NT_STATUS_NO_MEMORY;
3071 pdata = *ppdata;
3072 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3073 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3075 switch (info_level) {
3076 case SMB_INFO_ALLOCATION:
3078 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3079 data_len = 18;
3080 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3081 return map_nt_error_from_unix(errno);
3084 block_size = lp_block_size(snum);
3085 if (bsize < block_size) {
3086 uint64_t factor = block_size/bsize;
3087 bsize = block_size;
3088 dsize /= factor;
3089 dfree /= factor;
3091 if (bsize > block_size) {
3092 uint64_t factor = bsize/block_size;
3093 bsize = block_size;
3094 dsize *= factor;
3095 dfree *= factor;
3097 bytes_per_sector = 512;
3098 sectors_per_unit = bsize/bytes_per_sector;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3102 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3104 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3105 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3106 SIVAL(pdata,l1_cUnit,dsize);
3107 SIVAL(pdata,l1_cUnitAvail,dfree);
3108 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3109 break;
3112 case SMB_INFO_VOLUME:
3113 /* Return volume name */
3115 * Add volume serial number - hash of a combination of
3116 * the called hostname and the service name.
3118 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3120 * Win2k3 and previous mess this up by sending a name length
3121 * one byte short. I believe only older clients (OS/2 Win9x) use
3122 * this call so try fixing this by adding a terminating null to
3123 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3125 len = srvstr_push(
3126 pdata, flags2,
3127 pdata+l2_vol_szVolLabel, vname,
3128 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3129 STR_NOALIGN|STR_TERMINATE);
3130 SCVAL(pdata,l2_vol_cch,len);
3131 data_len = l2_vol_szVolLabel + len;
3132 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3133 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3134 len, vname));
3135 break;
3137 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3138 case SMB_FS_ATTRIBUTE_INFORMATION:
3140 additional_flags = 0;
3141 #if defined(HAVE_SYS_QUOTAS)
3142 additional_flags |= FILE_VOLUME_QUOTAS;
3143 #endif
3145 if(lp_nt_acl_support(SNUM(conn))) {
3146 additional_flags |= FILE_PERSISTENT_ACLS;
3149 /* Capabilities are filled in at connection time through STATVFS call */
3150 additional_flags |= conn->fs_capabilities;
3151 additional_flags |= lp_parm_int(conn->params->service,
3152 "share", "fake_fscaps",
3155 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3156 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3157 additional_flags); /* FS ATTRIBUTES */
3159 SIVAL(pdata,4,255); /* Max filename component length */
3160 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3161 and will think we can't do long filenames */
3162 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3163 PTR_DIFF(end_data, pdata+12),
3164 STR_UNICODE);
3165 SIVAL(pdata,8,len);
3166 data_len = 12 + len;
3167 break;
3169 case SMB_QUERY_FS_LABEL_INFO:
3170 case SMB_FS_LABEL_INFORMATION:
3171 len = srvstr_push(pdata, flags2, pdata+4, vname,
3172 PTR_DIFF(end_data, pdata+4), 0);
3173 data_len = 4 + len;
3174 SIVAL(pdata,0,len);
3175 break;
3177 case SMB_QUERY_FS_VOLUME_INFO:
3178 case SMB_FS_VOLUME_INFORMATION:
3181 * Add volume serial number - hash of a combination of
3182 * the called hostname and the service name.
3184 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3185 (str_checksum(get_local_machine_name())<<16));
3187 /* Max label len is 32 characters. */
3188 len = srvstr_push(pdata, flags2, pdata+18, vname,
3189 PTR_DIFF(end_data, pdata+18),
3190 STR_UNICODE);
3191 SIVAL(pdata,12,len);
3192 data_len = 18+len;
3194 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3195 (int)strlen(vname),vname,
3196 lp_servicename(talloc_tos(), snum)));
3197 break;
3199 case SMB_QUERY_FS_SIZE_INFO:
3200 case SMB_FS_SIZE_INFORMATION:
3202 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3203 data_len = 24;
3204 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3205 return map_nt_error_from_unix(errno);
3207 block_size = lp_block_size(snum);
3208 if (bsize < block_size) {
3209 uint64_t factor = block_size/bsize;
3210 bsize = block_size;
3211 dsize /= factor;
3212 dfree /= factor;
3214 if (bsize > block_size) {
3215 uint64_t factor = bsize/block_size;
3216 bsize = block_size;
3217 dsize *= factor;
3218 dfree *= factor;
3220 bytes_per_sector = 512;
3221 sectors_per_unit = bsize/bytes_per_sector;
3222 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3224 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3225 SBIG_UINT(pdata,0,dsize);
3226 SBIG_UINT(pdata,8,dfree);
3227 SIVAL(pdata,16,sectors_per_unit);
3228 SIVAL(pdata,20,bytes_per_sector);
3229 break;
3232 case SMB_FS_FULL_SIZE_INFORMATION:
3234 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3235 data_len = 32;
3236 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3237 return map_nt_error_from_unix(errno);
3239 block_size = lp_block_size(snum);
3240 if (bsize < block_size) {
3241 uint64_t factor = block_size/bsize;
3242 bsize = block_size;
3243 dsize /= factor;
3244 dfree /= factor;
3246 if (bsize > block_size) {
3247 uint64_t factor = bsize/block_size;
3248 bsize = block_size;
3249 dsize *= factor;
3250 dfree *= factor;
3252 bytes_per_sector = 512;
3253 sectors_per_unit = bsize/bytes_per_sector;
3254 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3255 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3256 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3257 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3258 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3259 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3260 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3261 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3262 break;
3265 case SMB_QUERY_FS_DEVICE_INFO:
3266 case SMB_FS_DEVICE_INFORMATION:
3268 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3270 if (!CAN_WRITE(conn)) {
3271 characteristics |= FILE_READ_ONLY_DEVICE;
3273 data_len = 8;
3274 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3275 SIVAL(pdata,4,characteristics);
3276 break;
3279 #ifdef HAVE_SYS_QUOTAS
3280 case SMB_FS_QUOTA_INFORMATION:
3282 * what we have to send --metze:
3284 * Unknown1: 24 NULL bytes
3285 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3286 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3287 * Quota Flags: 2 byte :
3288 * Unknown3: 6 NULL bytes
3290 * 48 bytes total
3292 * details for Quota Flags:
3294 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3295 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3296 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3297 * 0x0001 Enable Quotas: enable quota for this fs
3301 /* we need to fake up a fsp here,
3302 * because its not send in this call
3304 files_struct fsp;
3305 SMB_NTQUOTA_STRUCT quotas;
3307 ZERO_STRUCT(fsp);
3308 ZERO_STRUCT(quotas);
3310 fsp.conn = conn;
3311 fsp.fnum = FNUM_FIELD_INVALID;
3313 /* access check */
3314 if (get_current_uid(conn) != 0) {
3315 DEBUG(0,("set_user_quota: access_denied "
3316 "service [%s] user [%s]\n",
3317 lp_servicename(talloc_tos(), SNUM(conn)),
3318 conn->session_info->unix_info->unix_name));
3319 return NT_STATUS_ACCESS_DENIED;
3322 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3323 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3324 return map_nt_error_from_unix(errno);
3327 data_len = 48;
3329 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3330 lp_servicename(talloc_tos(), SNUM(conn))));
3332 /* Unknown1 24 NULL bytes*/
3333 SBIG_UINT(pdata,0,(uint64_t)0);
3334 SBIG_UINT(pdata,8,(uint64_t)0);
3335 SBIG_UINT(pdata,16,(uint64_t)0);
3337 /* Default Soft Quota 8 bytes */
3338 SBIG_UINT(pdata,24,quotas.softlim);
3340 /* Default Hard Quota 8 bytes */
3341 SBIG_UINT(pdata,32,quotas.hardlim);
3343 /* Quota flag 2 bytes */
3344 SSVAL(pdata,40,quotas.qflags);
3346 /* Unknown3 6 NULL bytes */
3347 SSVAL(pdata,42,0);
3348 SIVAL(pdata,44,0);
3350 break;
3352 #endif /* HAVE_SYS_QUOTAS */
3353 case SMB_FS_OBJECTID_INFORMATION:
3355 unsigned char objid[16];
3356 struct smb_extended_info extended_info;
3357 memcpy(pdata,create_volume_objectid(conn, objid),16);
3358 samba_extended_info_version (&extended_info);
3359 SIVAL(pdata,16,extended_info.samba_magic);
3360 SIVAL(pdata,20,extended_info.samba_version);
3361 SIVAL(pdata,24,extended_info.samba_subversion);
3362 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3363 memcpy(pdata+36,extended_info.samba_version_string,28);
3364 data_len = 64;
3365 break;
3369 * Query the version and capabilities of the CIFS UNIX extensions
3370 * in use.
3373 case SMB_QUERY_CIFS_UNIX_INFO:
3375 bool large_write = lp_min_receive_file_size() &&
3376 !srv_is_signing_active(conn->sconn);
3377 bool large_read = !srv_is_signing_active(conn->sconn);
3378 int encrypt_caps = 0;
3380 if (!lp_unix_extensions()) {
3381 return NT_STATUS_INVALID_LEVEL;
3384 switch (conn->encrypt_level) {
3385 case SMB_SIGNING_OFF:
3386 encrypt_caps = 0;
3387 break;
3388 case SMB_SIGNING_IF_REQUIRED:
3389 case SMB_SIGNING_DEFAULT:
3390 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3391 break;
3392 case SMB_SIGNING_REQUIRED:
3393 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3394 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3395 large_write = false;
3396 large_read = false;
3397 break;
3400 data_len = 12;
3401 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3402 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3404 /* We have POSIX ACLs, pathname, encryption,
3405 * large read/write, and locking capability. */
3407 SBIG_UINT(pdata,4,((uint64_t)(
3408 CIFS_UNIX_POSIX_ACLS_CAP|
3409 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3410 CIFS_UNIX_FCNTL_LOCKS_CAP|
3411 CIFS_UNIX_EXTATTR_CAP|
3412 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3413 encrypt_caps|
3414 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3415 (large_write ?
3416 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3417 break;
3420 case SMB_QUERY_POSIX_FS_INFO:
3422 int rc;
3423 vfs_statvfs_struct svfs;
3425 if (!lp_unix_extensions()) {
3426 return NT_STATUS_INVALID_LEVEL;
3429 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3431 if (!rc) {
3432 data_len = 56;
3433 SIVAL(pdata,0,svfs.OptimalTransferSize);
3434 SIVAL(pdata,4,svfs.BlockSize);
3435 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3436 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3437 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3438 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3439 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3440 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3441 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3442 #ifdef EOPNOTSUPP
3443 } else if (rc == EOPNOTSUPP) {
3444 return NT_STATUS_INVALID_LEVEL;
3445 #endif /* EOPNOTSUPP */
3446 } else {
3447 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3448 return NT_STATUS_DOS(ERRSRV, ERRerror);
3450 break;
3453 case SMB_QUERY_POSIX_WHOAMI:
3455 uint32_t flags = 0;
3456 uint32_t sid_bytes;
3457 int i;
3459 if (!lp_unix_extensions()) {
3460 return NT_STATUS_INVALID_LEVEL;
3463 if (max_data_bytes < 40) {
3464 return NT_STATUS_BUFFER_TOO_SMALL;
3467 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3468 flags |= SMB_WHOAMI_GUEST;
3471 /* NOTE: 8 bytes for UID/GID, irrespective of native
3472 * platform size. This matches
3473 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3475 data_len = 4 /* flags */
3476 + 4 /* flag mask */
3477 + 8 /* uid */
3478 + 8 /* gid */
3479 + 4 /* ngroups */
3480 + 4 /* num_sids */
3481 + 4 /* SID bytes */
3482 + 4 /* pad/reserved */
3483 + (conn->session_info->unix_token->ngroups * 8)
3484 /* groups list */
3485 + (conn->session_info->security_token->num_sids *
3486 SID_MAX_SIZE)
3487 /* SID list */;
3489 SIVAL(pdata, 0, flags);
3490 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3491 SBIG_UINT(pdata, 8,
3492 (uint64_t)conn->session_info->unix_token->uid);
3493 SBIG_UINT(pdata, 16,
3494 (uint64_t)conn->session_info->unix_token->gid);
3497 if (data_len >= max_data_bytes) {
3498 /* Potential overflow, skip the GIDs and SIDs. */
3500 SIVAL(pdata, 24, 0); /* num_groups */
3501 SIVAL(pdata, 28, 0); /* num_sids */
3502 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3503 SIVAL(pdata, 36, 0); /* reserved */
3505 data_len = 40;
3506 break;
3509 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3510 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3512 /* We walk the SID list twice, but this call is fairly
3513 * infrequent, and I don't expect that it's performance
3514 * sensitive -- jpeach
3516 for (i = 0, sid_bytes = 0;
3517 i < conn->session_info->security_token->num_sids; ++i) {
3518 sid_bytes += ndr_size_dom_sid(
3519 &conn->session_info->security_token->sids[i],
3523 /* SID list byte count */
3524 SIVAL(pdata, 32, sid_bytes);
3526 /* 4 bytes pad/reserved - must be zero */
3527 SIVAL(pdata, 36, 0);
3528 data_len = 40;
3530 /* GID list */
3531 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3532 SBIG_UINT(pdata, data_len,
3533 (uint64_t)conn->session_info->unix_token->groups[i]);
3534 data_len += 8;
3537 /* SID list */
3538 for (i = 0;
3539 i < conn->session_info->security_token->num_sids; ++i) {
3540 int sid_len = ndr_size_dom_sid(
3541 &conn->session_info->security_token->sids[i],
3544 sid_linearize(pdata + data_len, sid_len,
3545 &conn->session_info->security_token->sids[i]);
3546 data_len += sid_len;
3549 break;
3552 case SMB_MAC_QUERY_FS_INFO:
3554 * Thursby MAC extension... ONLY on NTFS filesystems
3555 * once we do streams then we don't need this
3557 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3558 data_len = 88;
3559 SIVAL(pdata,84,0x100); /* Don't support mac... */
3560 break;
3562 /* drop through */
3563 default:
3564 return NT_STATUS_INVALID_LEVEL;
3567 *ret_data_len = data_len;
3568 return NT_STATUS_OK;
3571 /****************************************************************************
3572 Reply to a TRANS2_QFSINFO (query filesystem info).
3573 ****************************************************************************/
3575 static void call_trans2qfsinfo(connection_struct *conn,
3576 struct smb_request *req,
3577 char **pparams, int total_params,
3578 char **ppdata, int total_data,
3579 unsigned int max_data_bytes)
3581 char *params = *pparams;
3582 uint16_t info_level;
3583 int data_len = 0;
3584 NTSTATUS status;
3586 if (total_params < 2) {
3587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3588 return;
3591 info_level = SVAL(params,0);
3593 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3594 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3595 DEBUG(0,("call_trans2qfsinfo: encryption required "
3596 "and info level 0x%x sent.\n",
3597 (unsigned int)info_level));
3598 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3599 return;
3603 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3605 status = smbd_do_qfsinfo(conn, req,
3606 info_level,
3607 req->flags2,
3608 max_data_bytes,
3609 NULL,
3610 ppdata, &data_len);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 reply_nterror(req, status);
3613 return;
3616 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3617 max_data_bytes);
3619 DEBUG( 4, ( "%s info_level = %d\n",
3620 smb_fn_name(req->cmd), info_level) );
3622 return;
3625 /****************************************************************************
3626 Reply to a TRANS2_SETFSINFO (set filesystem info).
3627 ****************************************************************************/
3629 static void call_trans2setfsinfo(connection_struct *conn,
3630 struct smb_request *req,
3631 char **pparams, int total_params,
3632 char **ppdata, int total_data,
3633 unsigned int max_data_bytes)
3635 struct smbd_server_connection *sconn = req->sconn;
3636 char *pdata = *ppdata;
3637 char *params = *pparams;
3638 uint16 info_level;
3640 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3641 lp_servicename(talloc_tos(), SNUM(conn))));
3643 /* */
3644 if (total_params < 4) {
3645 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3646 total_params));
3647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3648 return;
3651 info_level = SVAL(params,2);
3653 if (IS_IPC(conn)) {
3654 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3655 info_level != SMB_SET_CIFS_UNIX_INFO) {
3656 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3657 "info level (0x%x) on IPC$.\n",
3658 (unsigned int)info_level));
3659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3660 return;
3664 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3665 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3666 DEBUG(0,("call_trans2setfsinfo: encryption required "
3667 "and info level 0x%x sent.\n",
3668 (unsigned int)info_level));
3669 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3670 return;
3674 switch(info_level) {
3675 case SMB_SET_CIFS_UNIX_INFO:
3676 if (!lp_unix_extensions()) {
3677 DEBUG(2,("call_trans2setfsinfo: "
3678 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3679 "unix extensions off\n"));
3680 reply_nterror(req,
3681 NT_STATUS_INVALID_LEVEL);
3682 return;
3685 /* There should be 12 bytes of capabilities set. */
3686 if (total_data < 12) {
3687 reply_nterror(
3688 req,
3689 NT_STATUS_INVALID_PARAMETER);
3690 return;
3692 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3693 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3694 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3695 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3696 /* Just print these values for now. */
3697 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3698 "major = %u, minor = %u cap_low = 0x%x, "
3699 "cap_high = 0x%xn",
3700 (unsigned int)sconn->
3701 smb1.unix_info.client_major,
3702 (unsigned int)sconn->
3703 smb1.unix_info.client_minor,
3704 (unsigned int)sconn->
3705 smb1.unix_info.client_cap_low,
3706 (unsigned int)sconn->
3707 smb1.unix_info.client_cap_high));
3709 /* Here is where we must switch to posix pathname processing... */
3710 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3711 lp_set_posix_pathnames();
3712 mangle_change_to_posix();
3715 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3716 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3717 /* Client that knows how to do posix locks,
3718 * but not posix open/mkdir operations. Set a
3719 * default type for read/write checks. */
3721 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3724 break;
3726 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3728 NTSTATUS status;
3729 size_t param_len = 0;
3730 size_t data_len = total_data;
3732 if (!lp_unix_extensions()) {
3733 reply_nterror(
3734 req,
3735 NT_STATUS_INVALID_LEVEL);
3736 return;
3739 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3740 reply_nterror(
3741 req,
3742 NT_STATUS_NOT_SUPPORTED);
3743 return;
3746 if (req->sconn->smb1.echo_handler.trusted_fde) {
3747 DEBUG( 2,("call_trans2setfsinfo: "
3748 "request transport encryption disabled"
3749 "with 'fork echo handler = yes'\n"));
3750 reply_nterror(
3751 req,
3752 NT_STATUS_NOT_SUPPORTED);
3753 return;
3756 DEBUG( 4,("call_trans2setfsinfo: "
3757 "request transport encryption.\n"));
3759 status = srv_request_encryption_setup(conn,
3760 (unsigned char **)ppdata,
3761 &data_len,
3762 (unsigned char **)pparams,
3763 &param_len);
3765 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3766 !NT_STATUS_IS_OK(status)) {
3767 reply_nterror(req, status);
3768 return;
3771 send_trans2_replies(conn, req,
3772 *pparams,
3773 param_len,
3774 *ppdata,
3775 data_len,
3776 max_data_bytes);
3778 if (NT_STATUS_IS_OK(status)) {
3779 /* Server-side transport
3780 * encryption is now *on*. */
3781 status = srv_encryption_start(conn);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 char *reason = talloc_asprintf(talloc_tos(),
3784 "Failure in setting "
3785 "up encrypted transport: %s",
3786 nt_errstr(status));
3787 exit_server_cleanly(reason);
3790 return;
3793 case SMB_FS_QUOTA_INFORMATION:
3795 files_struct *fsp = NULL;
3796 SMB_NTQUOTA_STRUCT quotas;
3798 ZERO_STRUCT(quotas);
3800 /* access check */
3801 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3802 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3803 lp_servicename(talloc_tos(), SNUM(conn)),
3804 conn->session_info->unix_info->unix_name));
3805 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3806 return;
3809 /* note: normaly there're 48 bytes,
3810 * but we didn't use the last 6 bytes for now
3811 * --metze
3813 fsp = file_fsp(req, SVAL(params,0));
3815 if (!check_fsp_ntquota_handle(conn, req,
3816 fsp)) {
3817 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3818 reply_nterror(
3819 req, NT_STATUS_INVALID_HANDLE);
3820 return;
3823 if (total_data < 42) {
3824 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3825 total_data));
3826 reply_nterror(
3827 req,
3828 NT_STATUS_INVALID_PARAMETER);
3829 return;
3832 /* unknown_1 24 NULL bytes in pdata*/
3834 /* the soft quotas 8 bytes (uint64_t)*/
3835 quotas.softlim = BVAL(pdata,24);
3837 /* the hard quotas 8 bytes (uint64_t)*/
3838 quotas.hardlim = BVAL(pdata,32);
3840 /* quota_flags 2 bytes **/
3841 quotas.qflags = SVAL(pdata,40);
3843 /* unknown_2 6 NULL bytes follow*/
3845 /* now set the quotas */
3846 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3847 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3848 reply_nterror(req, map_nt_error_from_unix(errno));
3849 return;
3852 break;
3854 default:
3855 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3856 info_level));
3857 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3858 return;
3859 break;
3863 * sending this reply works fine,
3864 * but I'm not sure it's the same
3865 * like windows do...
3866 * --metze
3868 reply_outbuf(req, 10, 0);
3871 #if defined(HAVE_POSIX_ACLS)
3872 /****************************************************************************
3873 Utility function to count the number of entries in a POSIX acl.
3874 ****************************************************************************/
3876 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3878 unsigned int ace_count = 0;
3879 int entry_id = SMB_ACL_FIRST_ENTRY;
3880 SMB_ACL_ENTRY_T entry;
3882 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3883 /* get_next... */
3884 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3885 entry_id = SMB_ACL_NEXT_ENTRY;
3887 ace_count++;
3889 return ace_count;
3892 /****************************************************************************
3893 Utility function to marshall a POSIX acl into wire format.
3894 ****************************************************************************/
3896 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3898 int entry_id = SMB_ACL_FIRST_ENTRY;
3899 SMB_ACL_ENTRY_T entry;
3901 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3902 SMB_ACL_TAG_T tagtype;
3903 SMB_ACL_PERMSET_T permset;
3904 unsigned char perms = 0;
3905 unsigned int own_grp;
3907 /* get_next... */
3908 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3909 entry_id = SMB_ACL_NEXT_ENTRY;
3912 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3914 return False;
3917 if (sys_acl_get_permset(entry, &permset) == -1) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3919 return False;
3922 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3923 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3924 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3926 SCVAL(pdata,1,perms);
3928 switch (tagtype) {
3929 case SMB_ACL_USER_OBJ:
3930 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3931 own_grp = (unsigned int)pst->st_ex_uid;
3932 SIVAL(pdata,2,own_grp);
3933 SIVAL(pdata,6,0);
3934 break;
3935 case SMB_ACL_USER:
3937 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3938 if (!puid) {
3939 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3940 return False;
3942 own_grp = (unsigned int)*puid;
3943 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3944 SIVAL(pdata,2,own_grp);
3945 SIVAL(pdata,6,0);
3946 break;
3948 case SMB_ACL_GROUP_OBJ:
3949 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3950 own_grp = (unsigned int)pst->st_ex_gid;
3951 SIVAL(pdata,2,own_grp);
3952 SIVAL(pdata,6,0);
3953 break;
3954 case SMB_ACL_GROUP:
3956 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3957 if (!pgid) {
3958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3959 return False;
3961 own_grp = (unsigned int)*pgid;
3962 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3963 SIVAL(pdata,2,own_grp);
3964 SIVAL(pdata,6,0);
3965 break;
3967 case SMB_ACL_MASK:
3968 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3969 SIVAL(pdata,2,0xFFFFFFFF);
3970 SIVAL(pdata,6,0xFFFFFFFF);
3971 break;
3972 case SMB_ACL_OTHER:
3973 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3974 SIVAL(pdata,2,0xFFFFFFFF);
3975 SIVAL(pdata,6,0xFFFFFFFF);
3976 break;
3977 default:
3978 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3979 return False;
3981 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3984 return True;
3986 #endif
3988 /****************************************************************************
3989 Store the FILE_UNIX_BASIC info.
3990 ****************************************************************************/
3992 static char *store_file_unix_basic(connection_struct *conn,
3993 char *pdata,
3994 files_struct *fsp,
3995 const SMB_STRUCT_STAT *psbuf)
3997 uint64_t file_index = get_FileIndex(conn, psbuf);
3998 dev_t devno;
4000 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4001 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4003 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4004 pdata += 8;
4006 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4007 pdata += 8;
4009 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4012 pdata += 24;
4014 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4015 SIVAL(pdata,4,0);
4016 pdata += 8;
4018 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4019 SIVAL(pdata,4,0);
4020 pdata += 8;
4022 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4023 pdata += 4;
4025 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4026 devno = psbuf->st_ex_rdev;
4027 } else {
4028 devno = psbuf->st_ex_dev;
4031 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4032 SIVAL(pdata,4,0);
4033 pdata += 8;
4035 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4036 SIVAL(pdata,4,0);
4037 pdata += 8;
4039 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4040 pdata += 8;
4042 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4043 SIVAL(pdata,4,0);
4044 pdata += 8;
4046 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4047 SIVAL(pdata,4,0);
4048 pdata += 8;
4050 return pdata;
4053 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4054 * the chflags(2) (or equivalent) flags.
4056 * XXX: this really should be behind the VFS interface. To do this, we would
4057 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4058 * Each VFS module could then implement its own mapping as appropriate for the
4059 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4061 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4062 info2_flags_map[] =
4064 #ifdef UF_NODUMP
4065 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4066 #endif
4068 #ifdef UF_IMMUTABLE
4069 { UF_IMMUTABLE, EXT_IMMUTABLE },
4070 #endif
4072 #ifdef UF_APPEND
4073 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4074 #endif
4076 #ifdef UF_HIDDEN
4077 { UF_HIDDEN, EXT_HIDDEN },
4078 #endif
4080 /* Do not remove. We need to guarantee that this array has at least one
4081 * entry to build on HP-UX.
4083 { 0, 0 }
4087 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4088 uint32 *smb_fflags, uint32 *smb_fmask)
4090 int i;
4092 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4093 *smb_fmask |= info2_flags_map[i].smb_fflag;
4094 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4095 *smb_fflags |= info2_flags_map[i].smb_fflag;
4100 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4101 const uint32 smb_fflags,
4102 const uint32 smb_fmask,
4103 int *stat_fflags)
4105 uint32 max_fmask = 0;
4106 int i;
4108 *stat_fflags = psbuf->st_ex_flags;
4110 /* For each flags requested in smb_fmask, check the state of the
4111 * corresponding flag in smb_fflags and set or clear the matching
4112 * stat flag.
4115 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4116 max_fmask |= info2_flags_map[i].smb_fflag;
4117 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4118 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4119 *stat_fflags |= info2_flags_map[i].stat_fflag;
4120 } else {
4121 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4126 /* If smb_fmask is asking to set any bits that are not supported by
4127 * our flag mappings, we should fail.
4129 if ((smb_fmask & max_fmask) != smb_fmask) {
4130 return False;
4133 return True;
4137 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4138 * of file flags and birth (create) time.
4140 static char *store_file_unix_basic_info2(connection_struct *conn,
4141 char *pdata,
4142 files_struct *fsp,
4143 const SMB_STRUCT_STAT *psbuf)
4145 uint32 file_flags = 0;
4146 uint32 flags_mask = 0;
4148 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4150 /* Create (birth) time 64 bit */
4151 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4152 pdata += 8;
4154 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4155 SIVAL(pdata, 0, file_flags); /* flags */
4156 SIVAL(pdata, 4, flags_mask); /* mask */
4157 pdata += 8;
4159 return pdata;
4162 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4163 const struct stream_struct *streams,
4164 char *data,
4165 unsigned int max_data_bytes,
4166 unsigned int *data_size)
4168 unsigned int i;
4169 unsigned int ofs = 0;
4171 for (i = 0; i < num_streams; i++) {
4172 unsigned int next_offset;
4173 size_t namelen;
4174 smb_ucs2_t *namebuf;
4176 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4177 streams[i].name, &namelen) ||
4178 namelen <= 2)
4180 return NT_STATUS_INVALID_PARAMETER;
4184 * name_buf is now null-terminated, we need to marshall as not
4185 * terminated
4188 namelen -= 2;
4191 * We cannot overflow ...
4193 if ((ofs + 24 + namelen) > max_data_bytes) {
4194 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4195 i));
4196 TALLOC_FREE(namebuf);
4197 return STATUS_BUFFER_OVERFLOW;
4200 SIVAL(data, ofs+4, namelen);
4201 SOFF_T(data, ofs+8, streams[i].size);
4202 SOFF_T(data, ofs+16, streams[i].alloc_size);
4203 memcpy(data+ofs+24, namebuf, namelen);
4204 TALLOC_FREE(namebuf);
4206 next_offset = ofs + 24 + namelen;
4208 if (i == num_streams-1) {
4209 SIVAL(data, ofs, 0);
4211 else {
4212 unsigned int align = ndr_align_size(next_offset, 8);
4214 if ((next_offset + align) > max_data_bytes) {
4215 DEBUG(10, ("refusing to overflow align "
4216 "reply at stream %u\n",
4217 i));
4218 TALLOC_FREE(namebuf);
4219 return STATUS_BUFFER_OVERFLOW;
4222 memset(data+next_offset, 0, align);
4223 next_offset += align;
4225 SIVAL(data, ofs, next_offset - ofs);
4226 ofs = next_offset;
4229 ofs = next_offset;
4232 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4234 *data_size = ofs;
4236 return NT_STATUS_OK;
4239 /****************************************************************************
4240 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4241 ****************************************************************************/
4243 static void call_trans2qpipeinfo(connection_struct *conn,
4244 struct smb_request *req,
4245 unsigned int tran_call,
4246 char **pparams, int total_params,
4247 char **ppdata, int total_data,
4248 unsigned int max_data_bytes)
4250 char *params = *pparams;
4251 char *pdata = *ppdata;
4252 unsigned int data_size = 0;
4253 unsigned int param_size = 2;
4254 uint16 info_level;
4255 files_struct *fsp;
4257 if (!params) {
4258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4259 return;
4262 if (total_params < 4) {
4263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4264 return;
4267 fsp = file_fsp(req, SVAL(params,0));
4268 if (!fsp_is_np(fsp)) {
4269 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4270 return;
4273 info_level = SVAL(params,2);
4275 *pparams = (char *)SMB_REALLOC(*pparams,2);
4276 if (*pparams == NULL) {
4277 reply_nterror(req, NT_STATUS_NO_MEMORY);
4278 return;
4280 params = *pparams;
4281 SSVAL(params,0,0);
4282 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4283 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4284 if (*ppdata == NULL ) {
4285 reply_nterror(req, NT_STATUS_NO_MEMORY);
4286 return;
4288 pdata = *ppdata;
4290 switch (info_level) {
4291 case SMB_FILE_STANDARD_INFORMATION:
4292 memset(pdata,0,24);
4293 SOFF_T(pdata,0,4096LL);
4294 SIVAL(pdata,16,1);
4295 SIVAL(pdata,20,1);
4296 data_size = 24;
4297 break;
4299 default:
4300 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4301 return;
4304 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4305 max_data_bytes);
4307 return;
4310 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4311 TALLOC_CTX *mem_ctx,
4312 uint16_t info_level,
4313 files_struct *fsp,
4314 struct smb_filename *smb_fname,
4315 bool delete_pending,
4316 struct timespec write_time_ts,
4317 struct ea_list *ea_list,
4318 int lock_data_count,
4319 char *lock_data,
4320 uint16_t flags2,
4321 unsigned int max_data_bytes,
4322 char **ppdata,
4323 unsigned int *pdata_size)
4325 char *pdata = *ppdata;
4326 char *dstart, *dend;
4327 unsigned int data_size;
4328 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4329 time_t create_time, mtime, atime, c_time;
4330 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4331 char *p;
4332 char *base_name;
4333 char *dos_fname;
4334 int mode;
4335 int nlink;
4336 NTSTATUS status;
4337 uint64_t file_size = 0;
4338 uint64_t pos = 0;
4339 uint64_t allocation_size = 0;
4340 uint64_t file_index = 0;
4341 uint32_t access_mask = 0;
4343 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4344 return NT_STATUS_INVALID_LEVEL;
4347 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4348 smb_fname_str_dbg(smb_fname),
4349 fsp_fnum_dbg(fsp),
4350 info_level, max_data_bytes));
4352 mode = dos_mode(conn, smb_fname);
4353 nlink = psbuf->st_ex_nlink;
4355 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4356 nlink = 1;
4359 if ((nlink > 0) && delete_pending) {
4360 nlink -= 1;
4363 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4364 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4365 if (*ppdata == NULL) {
4366 return NT_STATUS_NO_MEMORY;
4368 pdata = *ppdata;
4369 dstart = pdata;
4370 dend = dstart + data_size - 1;
4372 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4373 update_stat_ex_mtime(psbuf, write_time_ts);
4376 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4377 mtime_ts = psbuf->st_ex_mtime;
4378 atime_ts = psbuf->st_ex_atime;
4379 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4381 if (lp_dos_filetime_resolution(SNUM(conn))) {
4382 dos_filetime_timespec(&create_time_ts);
4383 dos_filetime_timespec(&mtime_ts);
4384 dos_filetime_timespec(&atime_ts);
4385 dos_filetime_timespec(&ctime_ts);
4388 create_time = convert_timespec_to_time_t(create_time_ts);
4389 mtime = convert_timespec_to_time_t(mtime_ts);
4390 atime = convert_timespec_to_time_t(atime_ts);
4391 c_time = convert_timespec_to_time_t(ctime_ts);
4393 p = strrchr_m(smb_fname->base_name,'/');
4394 if (!p)
4395 base_name = smb_fname->base_name;
4396 else
4397 base_name = p+1;
4399 /* NT expects the name to be in an exact form of the *full*
4400 filename. See the trans2 torture test */
4401 if (ISDOT(base_name)) {
4402 dos_fname = talloc_strdup(mem_ctx, "\\");
4403 if (!dos_fname) {
4404 return NT_STATUS_NO_MEMORY;
4406 } else {
4407 dos_fname = talloc_asprintf(mem_ctx,
4408 "\\%s",
4409 smb_fname->base_name);
4410 if (!dos_fname) {
4411 return NT_STATUS_NO_MEMORY;
4413 if (is_ntfs_stream_smb_fname(smb_fname)) {
4414 dos_fname = talloc_asprintf(dos_fname, "%s",
4415 smb_fname->stream_name);
4416 if (!dos_fname) {
4417 return NT_STATUS_NO_MEMORY;
4421 string_replace(dos_fname, '/', '\\');
4424 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4426 if (!fsp) {
4427 /* Do we have this path open ? */
4428 files_struct *fsp1;
4429 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4430 fsp1 = file_find_di_first(conn->sconn, fileid);
4431 if (fsp1 && fsp1->initial_allocation_size) {
4432 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4436 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4437 file_size = get_file_size_stat(psbuf);
4440 if (fsp) {
4441 pos = fsp->fh->position_information;
4444 if (fsp) {
4445 access_mask = fsp->access_mask;
4446 } else {
4447 /* GENERIC_EXECUTE mapping from Windows */
4448 access_mask = 0x12019F;
4451 /* This should be an index number - looks like
4452 dev/ino to me :-)
4454 I think this causes us to fail the IFSKIT
4455 BasicFileInformationTest. -tpot */
4456 file_index = get_FileIndex(conn, psbuf);
4458 switch (info_level) {
4459 case SMB_INFO_STANDARD:
4460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4461 data_size = 22;
4462 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4463 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4464 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4465 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4466 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4467 SSVAL(pdata,l1_attrFile,mode);
4468 break;
4470 case SMB_INFO_QUERY_EA_SIZE:
4472 unsigned int ea_size =
4473 estimate_ea_size(conn, fsp,
4474 smb_fname);
4475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4476 data_size = 26;
4477 srv_put_dos_date2(pdata,0,create_time);
4478 srv_put_dos_date2(pdata,4,atime);
4479 srv_put_dos_date2(pdata,8,mtime); /* write time */
4480 SIVAL(pdata,12,(uint32)file_size);
4481 SIVAL(pdata,16,(uint32)allocation_size);
4482 SSVAL(pdata,20,mode);
4483 SIVAL(pdata,22,ea_size);
4484 break;
4487 case SMB_INFO_IS_NAME_VALID:
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4489 if (fsp) {
4490 /* os/2 needs this ? really ?*/
4491 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4493 /* This is only reached for qpathinfo */
4494 data_size = 0;
4495 break;
4497 case SMB_INFO_QUERY_EAS_FROM_LIST:
4499 size_t total_ea_len = 0;
4500 struct ea_list *ea_file_list = NULL;
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4503 status =
4504 get_ea_list_from_file(mem_ctx, conn, fsp,
4505 smb_fname,
4506 &total_ea_len, &ea_file_list);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 return status;
4511 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4513 if (!ea_list || (total_ea_len > data_size)) {
4514 data_size = 4;
4515 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4516 break;
4519 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4520 break;
4523 case SMB_INFO_QUERY_ALL_EAS:
4525 /* We have data_size bytes to put EA's into. */
4526 size_t total_ea_len = 0;
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4529 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4530 smb_fname,
4531 &total_ea_len, &ea_list);
4532 if (!NT_STATUS_IS_OK(status)) {
4533 return status;
4536 if (!ea_list || (total_ea_len > data_size)) {
4537 data_size = 4;
4538 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4539 break;
4542 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4543 break;
4546 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4548 /* This is FileFullEaInformation - 0xF which maps to
4549 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4551 /* We have data_size bytes to put EA's into. */
4552 size_t total_ea_len = 0;
4553 struct ea_list *ea_file_list = NULL;
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4557 /*TODO: add filtering and index handling */
4559 status =
4560 get_ea_list_from_file(mem_ctx, conn, fsp,
4561 smb_fname,
4562 &total_ea_len, &ea_file_list);
4563 if (!NT_STATUS_IS_OK(status)) {
4564 return status;
4566 if (!ea_file_list) {
4567 return NT_STATUS_NO_EAS_ON_FILE;
4570 status = fill_ea_chained_buffer(mem_ctx,
4571 pdata,
4572 data_size,
4573 &data_size,
4574 conn, ea_file_list);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 return status;
4578 break;
4581 case SMB_FILE_BASIC_INFORMATION:
4582 case SMB_QUERY_FILE_BASIC_INFO:
4584 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4586 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4587 } else {
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4589 data_size = 40;
4590 SIVAL(pdata,36,0);
4592 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4593 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4594 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4595 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4596 SIVAL(pdata,32,mode);
4598 DEBUG(5,("SMB_QFBI - "));
4599 DEBUG(5,("create: %s ", ctime(&create_time)));
4600 DEBUG(5,("access: %s ", ctime(&atime)));
4601 DEBUG(5,("write: %s ", ctime(&mtime)));
4602 DEBUG(5,("change: %s ", ctime(&c_time)));
4603 DEBUG(5,("mode: %x\n", mode));
4604 break;
4606 case SMB_FILE_STANDARD_INFORMATION:
4607 case SMB_QUERY_FILE_STANDARD_INFO:
4609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4610 data_size = 24;
4611 SOFF_T(pdata,0,allocation_size);
4612 SOFF_T(pdata,8,file_size);
4613 SIVAL(pdata,16,nlink);
4614 SCVAL(pdata,20,delete_pending?1:0);
4615 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4616 SSVAL(pdata,22,0); /* Padding. */
4617 break;
4619 case SMB_FILE_EA_INFORMATION:
4620 case SMB_QUERY_FILE_EA_INFO:
4622 unsigned int ea_size =
4623 estimate_ea_size(conn, fsp, smb_fname);
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4625 data_size = 4;
4626 SIVAL(pdata,0,ea_size);
4627 break;
4630 /* Get the 8.3 name - used if NT SMB was negotiated. */
4631 case SMB_QUERY_FILE_ALT_NAME_INFO:
4632 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4634 int len;
4635 char mangled_name[13];
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4637 if (!name_to_8_3(base_name,mangled_name,
4638 True,conn->params)) {
4639 return NT_STATUS_NO_MEMORY;
4641 len = srvstr_push(dstart, flags2,
4642 pdata+4, mangled_name,
4643 PTR_DIFF(dend, pdata+4),
4644 STR_UNICODE);
4645 data_size = 4 + len;
4646 SIVAL(pdata,0,len);
4647 break;
4650 case SMB_QUERY_FILE_NAME_INFO:
4652 int len;
4654 this must be *exactly* right for ACLs on mapped drives to work
4656 len = srvstr_push(dstart, flags2,
4657 pdata+4, dos_fname,
4658 PTR_DIFF(dend, pdata+4),
4659 STR_UNICODE);
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4661 data_size = 4 + len;
4662 SIVAL(pdata,0,len);
4663 break;
4666 case SMB_FILE_ALLOCATION_INFORMATION:
4667 case SMB_QUERY_FILE_ALLOCATION_INFO:
4668 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4669 data_size = 8;
4670 SOFF_T(pdata,0,allocation_size);
4671 break;
4673 case SMB_FILE_END_OF_FILE_INFORMATION:
4674 case SMB_QUERY_FILE_END_OF_FILEINFO:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4676 data_size = 8;
4677 SOFF_T(pdata,0,file_size);
4678 break;
4680 case SMB_QUERY_FILE_ALL_INFO:
4681 case SMB_FILE_ALL_INFORMATION:
4683 int len;
4684 unsigned int ea_size =
4685 estimate_ea_size(conn, fsp, smb_fname);
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4687 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4688 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4689 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4690 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4691 SIVAL(pdata,32,mode);
4692 SIVAL(pdata,36,0); /* padding. */
4693 pdata += 40;
4694 SOFF_T(pdata,0,allocation_size);
4695 SOFF_T(pdata,8,file_size);
4696 SIVAL(pdata,16,nlink);
4697 SCVAL(pdata,20,delete_pending);
4698 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4699 SSVAL(pdata,22,0);
4700 pdata += 24;
4701 SIVAL(pdata,0,ea_size);
4702 pdata += 4; /* EA info */
4703 len = srvstr_push(dstart, flags2,
4704 pdata+4, dos_fname,
4705 PTR_DIFF(dend, pdata+4),
4706 STR_UNICODE);
4707 SIVAL(pdata,0,len);
4708 pdata += 4 + len;
4709 data_size = PTR_DIFF(pdata,(*ppdata));
4710 break;
4713 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4715 int len;
4716 unsigned int ea_size =
4717 estimate_ea_size(conn, fsp, smb_fname);
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4719 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4722 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4723 SIVAL(pdata, 0x20, mode);
4724 SIVAL(pdata, 0x24, 0); /* padding. */
4725 SBVAL(pdata, 0x28, allocation_size);
4726 SBVAL(pdata, 0x30, file_size);
4727 SIVAL(pdata, 0x38, nlink);
4728 SCVAL(pdata, 0x3C, delete_pending);
4729 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4730 SSVAL(pdata, 0x3E, 0); /* padding */
4731 SBVAL(pdata, 0x40, file_index);
4732 SIVAL(pdata, 0x48, ea_size);
4733 SIVAL(pdata, 0x4C, access_mask);
4734 SBVAL(pdata, 0x50, pos);
4735 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4736 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4738 pdata += 0x60;
4740 len = srvstr_push(dstart, flags2,
4741 pdata+4, dos_fname,
4742 PTR_DIFF(dend, pdata+4),
4743 STR_UNICODE);
4744 SIVAL(pdata,0,len);
4745 pdata += 4 + len;
4746 data_size = PTR_DIFF(pdata,(*ppdata));
4747 break;
4749 case SMB_FILE_INTERNAL_INFORMATION:
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4752 SBVAL(pdata, 0, file_index);
4753 data_size = 8;
4754 break;
4756 case SMB_FILE_ACCESS_INFORMATION:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4758 SIVAL(pdata, 0, access_mask);
4759 data_size = 4;
4760 break;
4762 case SMB_FILE_NAME_INFORMATION:
4763 /* Pathname with leading '\'. */
4765 size_t byte_len;
4766 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4767 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4768 SIVAL(pdata,0,byte_len);
4769 data_size = 4 + byte_len;
4770 break;
4773 case SMB_FILE_DISPOSITION_INFORMATION:
4774 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4775 data_size = 1;
4776 SCVAL(pdata,0,delete_pending);
4777 break;
4779 case SMB_FILE_POSITION_INFORMATION:
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4781 data_size = 8;
4782 SOFF_T(pdata,0,pos);
4783 break;
4785 case SMB_FILE_MODE_INFORMATION:
4786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4787 SIVAL(pdata,0,mode);
4788 data_size = 4;
4789 break;
4791 case SMB_FILE_ALIGNMENT_INFORMATION:
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4793 SIVAL(pdata,0,0); /* No alignment needed. */
4794 data_size = 4;
4795 break;
4798 * NT4 server just returns "invalid query" to this - if we try
4799 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4800 * want this. JRA.
4802 /* The first statement above is false - verified using Thursby
4803 * client against NT4 -- gcolley.
4805 case SMB_QUERY_FILE_STREAM_INFO:
4806 case SMB_FILE_STREAM_INFORMATION: {
4807 unsigned int num_streams = 0;
4808 struct stream_struct *streams = NULL;
4810 DEBUG(10,("smbd_do_qfilepathinfo: "
4811 "SMB_FILE_STREAM_INFORMATION\n"));
4813 if (is_ntfs_stream_smb_fname(smb_fname)) {
4814 return NT_STATUS_INVALID_PARAMETER;
4817 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4818 talloc_tos(), &num_streams, &streams);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 DEBUG(10, ("could not get stream info: %s\n",
4822 nt_errstr(status)));
4823 return status;
4826 status = marshall_stream_info(num_streams, streams,
4827 pdata, max_data_bytes,
4828 &data_size);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 DEBUG(10, ("marshall_stream_info failed: %s\n",
4832 nt_errstr(status)));
4833 TALLOC_FREE(streams);
4834 return status;
4837 TALLOC_FREE(streams);
4839 break;
4841 case SMB_QUERY_COMPRESSION_INFO:
4842 case SMB_FILE_COMPRESSION_INFORMATION:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4844 SOFF_T(pdata,0,file_size);
4845 SIVAL(pdata,8,0); /* ??? */
4846 SIVAL(pdata,12,0); /* ??? */
4847 data_size = 16;
4848 break;
4850 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4851 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4852 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4853 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4854 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4855 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4856 SOFF_T(pdata,32,allocation_size);
4857 SOFF_T(pdata,40,file_size);
4858 SIVAL(pdata,48,mode);
4859 SIVAL(pdata,52,0); /* ??? */
4860 data_size = 56;
4861 break;
4863 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4865 SIVAL(pdata,0,mode);
4866 SIVAL(pdata,4,0);
4867 data_size = 8;
4868 break;
4871 * CIFS UNIX Extensions.
4874 case SMB_QUERY_FILE_UNIX_BASIC:
4876 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4877 data_size = PTR_DIFF(pdata,(*ppdata));
4879 DEBUG(4,("smbd_do_qfilepathinfo: "
4880 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4881 dump_data(4, (uint8_t *)(*ppdata), data_size);
4883 break;
4885 case SMB_QUERY_FILE_UNIX_INFO2:
4887 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4888 data_size = PTR_DIFF(pdata,(*ppdata));
4891 int i;
4892 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4894 for (i=0; i<100; i++)
4895 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4896 DEBUG(4,("\n"));
4899 break;
4901 case SMB_QUERY_FILE_UNIX_LINK:
4903 int len;
4904 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4906 if (!buffer) {
4907 return NT_STATUS_NO_MEMORY;
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4911 #ifdef S_ISLNK
4912 if(!S_ISLNK(psbuf->st_ex_mode)) {
4913 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4915 #else
4916 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4917 #endif
4918 len = SMB_VFS_READLINK(conn,
4919 smb_fname->base_name,
4920 buffer, PATH_MAX);
4921 if (len == -1) {
4922 return map_nt_error_from_unix(errno);
4924 buffer[len] = 0;
4925 len = srvstr_push(dstart, flags2,
4926 pdata, buffer,
4927 PTR_DIFF(dend, pdata),
4928 STR_TERMINATE);
4929 pdata += len;
4930 data_size = PTR_DIFF(pdata,(*ppdata));
4932 break;
4935 #if defined(HAVE_POSIX_ACLS)
4936 case SMB_QUERY_POSIX_ACL:
4938 SMB_ACL_T file_acl = NULL;
4939 SMB_ACL_T def_acl = NULL;
4940 uint16 num_file_acls = 0;
4941 uint16 num_def_acls = 0;
4943 if (fsp && fsp->fh->fd != -1) {
4944 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4945 talloc_tos());
4946 } else {
4947 file_acl =
4948 SMB_VFS_SYS_ACL_GET_FILE(conn,
4949 smb_fname->base_name,
4950 SMB_ACL_TYPE_ACCESS,
4951 talloc_tos());
4954 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4955 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4956 "not implemented on "
4957 "filesystem containing %s\n",
4958 smb_fname->base_name));
4959 return NT_STATUS_NOT_IMPLEMENTED;
4962 if (S_ISDIR(psbuf->st_ex_mode)) {
4963 if (fsp && fsp->is_directory) {
4964 def_acl =
4965 SMB_VFS_SYS_ACL_GET_FILE(
4966 conn,
4967 fsp->fsp_name->base_name,
4968 SMB_ACL_TYPE_DEFAULT,
4969 talloc_tos());
4970 } else {
4971 def_acl =
4972 SMB_VFS_SYS_ACL_GET_FILE(
4973 conn,
4974 smb_fname->base_name,
4975 SMB_ACL_TYPE_DEFAULT,
4976 talloc_tos());
4978 def_acl = free_empty_sys_acl(conn, def_acl);
4981 num_file_acls = count_acl_entries(conn, file_acl);
4982 num_def_acls = count_acl_entries(conn, def_acl);
4984 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4985 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4986 data_size,
4987 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4988 SMB_POSIX_ACL_HEADER_SIZE) ));
4989 if (file_acl) {
4990 TALLOC_FREE(file_acl);
4992 if (def_acl) {
4993 TALLOC_FREE(def_acl);
4995 return NT_STATUS_BUFFER_TOO_SMALL;
4998 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4999 SSVAL(pdata,2,num_file_acls);
5000 SSVAL(pdata,4,num_def_acls);
5001 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5002 if (file_acl) {
5003 TALLOC_FREE(file_acl);
5005 if (def_acl) {
5006 TALLOC_FREE(def_acl);
5008 return NT_STATUS_INTERNAL_ERROR;
5010 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5011 if (file_acl) {
5012 TALLOC_FREE(file_acl);
5014 if (def_acl) {
5015 TALLOC_FREE(def_acl);
5017 return NT_STATUS_INTERNAL_ERROR;
5020 if (file_acl) {
5021 TALLOC_FREE(file_acl);
5023 if (def_acl) {
5024 TALLOC_FREE(def_acl);
5026 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5027 break;
5029 #endif
5032 case SMB_QUERY_POSIX_LOCK:
5034 uint64_t count;
5035 uint64_t offset;
5036 uint64_t smblctx;
5037 enum brl_type lock_type;
5039 /* We need an open file with a real fd for this. */
5040 if (!fsp || fsp->fh->fd == -1) {
5041 return NT_STATUS_INVALID_LEVEL;
5044 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5045 return NT_STATUS_INVALID_PARAMETER;
5048 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5049 case POSIX_LOCK_TYPE_READ:
5050 lock_type = READ_LOCK;
5051 break;
5052 case POSIX_LOCK_TYPE_WRITE:
5053 lock_type = WRITE_LOCK;
5054 break;
5055 case POSIX_LOCK_TYPE_UNLOCK:
5056 default:
5057 /* There's no point in asking for an unlock... */
5058 return NT_STATUS_INVALID_PARAMETER;
5061 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5062 #if defined(HAVE_LONGLONG)
5063 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5064 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5065 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5066 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5067 #else /* HAVE_LONGLONG */
5068 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5069 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5070 #endif /* HAVE_LONGLONG */
5072 status = query_lock(fsp,
5073 &smblctx,
5074 &count,
5075 &offset,
5076 &lock_type,
5077 POSIX_LOCK);
5079 if (ERROR_WAS_LOCK_DENIED(status)) {
5080 /* Here we need to report who has it locked... */
5081 data_size = POSIX_LOCK_DATA_SIZE;
5083 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5084 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5085 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5086 #if defined(HAVE_LONGLONG)
5087 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5088 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5089 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5090 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5091 #else /* HAVE_LONGLONG */
5092 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5093 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5094 #endif /* HAVE_LONGLONG */
5096 } else if (NT_STATUS_IS_OK(status)) {
5097 /* For success we just return a copy of what we sent
5098 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5099 data_size = POSIX_LOCK_DATA_SIZE;
5100 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5101 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5102 } else {
5103 return status;
5105 break;
5108 default:
5109 return NT_STATUS_INVALID_LEVEL;
5112 *pdata_size = data_size;
5113 return NT_STATUS_OK;
5116 /****************************************************************************
5117 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5118 file name or file id).
5119 ****************************************************************************/
5121 static void call_trans2qfilepathinfo(connection_struct *conn,
5122 struct smb_request *req,
5123 unsigned int tran_call,
5124 char **pparams, int total_params,
5125 char **ppdata, int total_data,
5126 unsigned int max_data_bytes)
5128 char *params = *pparams;
5129 char *pdata = *ppdata;
5130 uint16 info_level;
5131 unsigned int data_size = 0;
5132 unsigned int param_size = 2;
5133 struct smb_filename *smb_fname = NULL;
5134 bool delete_pending = False;
5135 struct timespec write_time_ts;
5136 files_struct *fsp = NULL;
5137 struct file_id fileid;
5138 struct ea_list *ea_list = NULL;
5139 int lock_data_count = 0;
5140 char *lock_data = NULL;
5141 NTSTATUS status = NT_STATUS_OK;
5143 if (!params) {
5144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5145 return;
5148 ZERO_STRUCT(write_time_ts);
5150 if (tran_call == TRANSACT2_QFILEINFO) {
5151 if (total_params < 4) {
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 return;
5156 if (IS_IPC(conn)) {
5157 call_trans2qpipeinfo(conn, req, tran_call,
5158 pparams, total_params,
5159 ppdata, total_data,
5160 max_data_bytes);
5161 return;
5164 fsp = file_fsp(req, SVAL(params,0));
5165 info_level = SVAL(params,2);
5167 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5169 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5170 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5171 return;
5174 /* Initial check for valid fsp ptr. */
5175 if (!check_fsp_open(conn, req, fsp)) {
5176 return;
5179 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5180 &smb_fname);
5181 if (!NT_STATUS_IS_OK(status)) {
5182 reply_nterror(req, status);
5183 return;
5186 if(fsp->fake_file_handle) {
5188 * This is actually for the QUOTA_FAKE_FILE --metze
5191 /* We know this name is ok, it's already passed the checks. */
5193 } else if(fsp->fh->fd == -1) {
5195 * This is actually a QFILEINFO on a directory
5196 * handle (returned from an NT SMB). NT5.0 seems
5197 * to do this call. JRA.
5200 if (INFO_LEVEL_IS_UNIX(info_level)) {
5201 /* Always do lstat for UNIX calls. */
5202 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "SMB_VFS_LSTAT of %s failed "
5205 "(%s)\n",
5206 smb_fname_str_dbg(smb_fname),
5207 strerror(errno)));
5208 reply_nterror(req,
5209 map_nt_error_from_unix(errno));
5210 return;
5212 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5213 DEBUG(3,("call_trans2qfilepathinfo: "
5214 "SMB_VFS_STAT of %s failed (%s)\n",
5215 smb_fname_str_dbg(smb_fname),
5216 strerror(errno)));
5217 reply_nterror(req,
5218 map_nt_error_from_unix(errno));
5219 return;
5222 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5223 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5224 } else {
5226 * Original code - this is an open file.
5228 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5229 DEBUG(3, ("fstat of %s failed (%s)\n",
5230 fsp_fnum_dbg(fsp), strerror(errno)));
5231 reply_nterror(req,
5232 map_nt_error_from_unix(errno));
5233 return;
5235 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5236 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5239 } else {
5240 uint32_t name_hash;
5241 char *fname = NULL;
5242 uint32_t ucf_flags = 0;
5244 /* qpathinfo */
5245 if (total_params < 7) {
5246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5247 return;
5250 info_level = SVAL(params,0);
5252 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5254 if (INFO_LEVEL_IS_UNIX(info_level)) {
5255 if (!lp_unix_extensions()) {
5256 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5257 return;
5259 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5260 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5261 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5262 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5266 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5267 total_params - 6,
5268 STR_TERMINATE, &status);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 reply_nterror(req, status);
5271 return;
5274 status = filename_convert(req,
5275 conn,
5276 req->flags2 & FLAGS2_DFS_PATHNAMES,
5277 fname,
5278 ucf_flags,
5279 NULL,
5280 &smb_fname);
5281 if (!NT_STATUS_IS_OK(status)) {
5282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5283 reply_botherror(req,
5284 NT_STATUS_PATH_NOT_COVERED,
5285 ERRSRV, ERRbadpath);
5286 return;
5288 reply_nterror(req, status);
5289 return;
5292 /* If this is a stream, check if there is a delete_pending. */
5293 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5294 && is_ntfs_stream_smb_fname(smb_fname)) {
5295 struct smb_filename *smb_fname_base = NULL;
5297 /* Create an smb_filename with stream_name == NULL. */
5298 status =
5299 create_synthetic_smb_fname(talloc_tos(),
5300 smb_fname->base_name,
5301 NULL, NULL,
5302 &smb_fname_base);
5303 if (!NT_STATUS_IS_OK(status)) {
5304 reply_nterror(req, status);
5305 return;
5308 if (INFO_LEVEL_IS_UNIX(info_level)) {
5309 /* Always do lstat for UNIX calls. */
5310 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "SMB_VFS_LSTAT of %s failed "
5313 "(%s)\n",
5314 smb_fname_str_dbg(smb_fname_base),
5315 strerror(errno)));
5316 TALLOC_FREE(smb_fname_base);
5317 reply_nterror(req,
5318 map_nt_error_from_unix(errno));
5319 return;
5321 } else {
5322 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5323 DEBUG(3,("call_trans2qfilepathinfo: "
5324 "fileinfo of %s failed "
5325 "(%s)\n",
5326 smb_fname_str_dbg(smb_fname_base),
5327 strerror(errno)));
5328 TALLOC_FREE(smb_fname_base);
5329 reply_nterror(req,
5330 map_nt_error_from_unix(errno));
5331 return;
5335 status = file_name_hash(conn,
5336 smb_fname_str_dbg(smb_fname_base),
5337 &name_hash);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 TALLOC_FREE(smb_fname_base);
5340 reply_nterror(req, status);
5341 return;
5344 fileid = vfs_file_id_from_sbuf(conn,
5345 &smb_fname_base->st);
5346 TALLOC_FREE(smb_fname_base);
5347 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5348 if (delete_pending) {
5349 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5350 return;
5354 if (INFO_LEVEL_IS_UNIX(info_level)) {
5355 /* Always do lstat for UNIX calls. */
5356 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5357 DEBUG(3,("call_trans2qfilepathinfo: "
5358 "SMB_VFS_LSTAT of %s failed (%s)\n",
5359 smb_fname_str_dbg(smb_fname),
5360 strerror(errno)));
5361 reply_nterror(req,
5362 map_nt_error_from_unix(errno));
5363 return;
5366 } else {
5367 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5368 DEBUG(3,("call_trans2qfilepathinfo: "
5369 "SMB_VFS_STAT of %s failed (%s)\n",
5370 smb_fname_str_dbg(smb_fname),
5371 strerror(errno)));
5372 reply_nterror(req,
5373 map_nt_error_from_unix(errno));
5374 return;
5378 status = file_name_hash(conn,
5379 smb_fname_str_dbg(smb_fname),
5380 &name_hash);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 reply_nterror(req, status);
5383 return;
5386 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5387 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5388 if (delete_pending) {
5389 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5390 return;
5394 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5395 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5396 fsp_fnum_dbg(fsp),
5397 info_level,tran_call,total_data));
5399 /* Pull out any data sent here before we realloc. */
5400 switch (info_level) {
5401 case SMB_INFO_QUERY_EAS_FROM_LIST:
5403 /* Pull any EA list from the data portion. */
5404 uint32 ea_size;
5406 if (total_data < 4) {
5407 reply_nterror(
5408 req, NT_STATUS_INVALID_PARAMETER);
5409 return;
5411 ea_size = IVAL(pdata,0);
5413 if (total_data > 0 && ea_size != total_data) {
5414 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5415 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5416 reply_nterror(
5417 req, NT_STATUS_INVALID_PARAMETER);
5418 return;
5421 if (!lp_ea_support(SNUM(conn))) {
5422 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5423 return;
5426 /* Pull out the list of names. */
5427 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5428 if (!ea_list) {
5429 reply_nterror(
5430 req, NT_STATUS_INVALID_PARAMETER);
5431 return;
5433 break;
5436 case SMB_QUERY_POSIX_LOCK:
5438 if (fsp == NULL || fsp->fh->fd == -1) {
5439 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5440 return;
5443 if (total_data != POSIX_LOCK_DATA_SIZE) {
5444 reply_nterror(
5445 req, NT_STATUS_INVALID_PARAMETER);
5446 return;
5449 /* Copy the lock range data. */
5450 lock_data = (char *)talloc_memdup(
5451 req, pdata, total_data);
5452 if (!lock_data) {
5453 reply_nterror(req, NT_STATUS_NO_MEMORY);
5454 return;
5456 lock_data_count = total_data;
5458 default:
5459 break;
5462 *pparams = (char *)SMB_REALLOC(*pparams,2);
5463 if (*pparams == NULL) {
5464 reply_nterror(req, NT_STATUS_NO_MEMORY);
5465 return;
5467 params = *pparams;
5468 SSVAL(params,0,0);
5471 * draft-leach-cifs-v1-spec-02.txt
5472 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5473 * says:
5475 * The requested information is placed in the Data portion of the
5476 * transaction response. For the information levels greater than 0x100,
5477 * the transaction response has 1 parameter word which should be
5478 * ignored by the client.
5480 * However Windows only follows this rule for the IS_NAME_VALID call.
5482 switch (info_level) {
5483 case SMB_INFO_IS_NAME_VALID:
5484 param_size = 0;
5485 break;
5488 if ((info_level & 0xFF00) == 0xFF00) {
5490 * We use levels that start with 0xFF00
5491 * internally to represent SMB2 specific levels
5493 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5494 return;
5497 status = smbd_do_qfilepathinfo(conn, req, info_level,
5498 fsp, smb_fname,
5499 delete_pending, write_time_ts,
5500 ea_list,
5501 lock_data_count, lock_data,
5502 req->flags2, max_data_bytes,
5503 ppdata, &data_size);
5504 if (!NT_STATUS_IS_OK(status)) {
5505 reply_nterror(req, status);
5506 return;
5509 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5510 max_data_bytes);
5512 return;
5515 /****************************************************************************
5516 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5517 code.
5518 ****************************************************************************/
5520 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5521 connection_struct *conn,
5522 struct smb_request *req,
5523 bool overwrite_if_exists,
5524 const struct smb_filename *smb_fname_old,
5525 struct smb_filename *smb_fname_new)
5527 NTSTATUS status = NT_STATUS_OK;
5529 /* source must already exist. */
5530 if (!VALID_STAT(smb_fname_old->st)) {
5531 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5534 if (VALID_STAT(smb_fname_new->st)) {
5535 if (overwrite_if_exists) {
5536 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5537 return NT_STATUS_FILE_IS_A_DIRECTORY;
5539 status = unlink_internals(conn,
5540 req,
5541 FILE_ATTRIBUTE_NORMAL,
5542 smb_fname_new,
5543 false);
5544 if (!NT_STATUS_IS_OK(status)) {
5545 return status;
5547 } else {
5548 /* Disallow if newname already exists. */
5549 return NT_STATUS_OBJECT_NAME_COLLISION;
5553 /* No links from a directory. */
5554 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5555 return NT_STATUS_FILE_IS_A_DIRECTORY;
5558 /* Setting a hardlink to/from a stream isn't currently supported. */
5559 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5560 is_ntfs_stream_smb_fname(smb_fname_new)) {
5561 return NT_STATUS_INVALID_PARAMETER;
5564 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5565 smb_fname_old->base_name, smb_fname_new->base_name));
5567 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5568 smb_fname_new->base_name) != 0) {
5569 status = map_nt_error_from_unix(errno);
5570 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5571 nt_errstr(status), smb_fname_old->base_name,
5572 smb_fname_new->base_name));
5574 return status;
5577 /****************************************************************************
5578 Deal with setting the time from any of the setfilepathinfo functions.
5579 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5580 calling this function.
5581 ****************************************************************************/
5583 NTSTATUS smb_set_file_time(connection_struct *conn,
5584 files_struct *fsp,
5585 const struct smb_filename *smb_fname,
5586 struct smb_file_time *ft,
5587 bool setting_write_time)
5589 struct smb_filename smb_fname_base;
5590 uint32 action =
5591 FILE_NOTIFY_CHANGE_LAST_ACCESS
5592 |FILE_NOTIFY_CHANGE_LAST_WRITE
5593 |FILE_NOTIFY_CHANGE_CREATION;
5595 if (!VALID_STAT(smb_fname->st)) {
5596 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5599 /* get some defaults (no modifications) if any info is zero or -1. */
5600 if (null_timespec(ft->create_time)) {
5601 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5604 if (null_timespec(ft->atime)) {
5605 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5608 if (null_timespec(ft->mtime)) {
5609 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5612 if (!setting_write_time) {
5613 /* ft->mtime comes from change time, not write time. */
5614 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5617 /* Ensure the resolution is the correct for
5618 * what we can store on this filesystem. */
5620 round_timespec(conn->ts_res, &ft->create_time);
5621 round_timespec(conn->ts_res, &ft->ctime);
5622 round_timespec(conn->ts_res, &ft->atime);
5623 round_timespec(conn->ts_res, &ft->mtime);
5625 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5626 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5627 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5628 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5629 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5630 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5631 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5632 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5634 if (setting_write_time) {
5636 * This was a Windows setfileinfo on an open file.
5637 * NT does this a lot. We also need to
5638 * set the time here, as it can be read by
5639 * FindFirst/FindNext and with the patch for bug #2045
5640 * in smbd/fileio.c it ensures that this timestamp is
5641 * kept sticky even after a write. We save the request
5642 * away and will set it on file close and after a write. JRA.
5645 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5646 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5648 if (fsp != NULL) {
5649 if (fsp->base_fsp) {
5650 set_sticky_write_time_fsp(fsp->base_fsp,
5651 ft->mtime);
5652 } else {
5653 set_sticky_write_time_fsp(fsp, ft->mtime);
5655 } else {
5656 set_sticky_write_time_path(
5657 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5658 ft->mtime);
5662 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5664 /* Always call ntimes on the base, even if a stream was passed in. */
5665 smb_fname_base = *smb_fname;
5666 smb_fname_base.stream_name = NULL;
5668 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5669 return map_nt_error_from_unix(errno);
5672 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5673 smb_fname->base_name);
5674 return NT_STATUS_OK;
5677 /****************************************************************************
5678 Deal with setting the dosmode from any of the setfilepathinfo functions.
5679 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5680 done before calling this function.
5681 ****************************************************************************/
5683 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5684 const struct smb_filename *smb_fname,
5685 uint32 dosmode)
5687 struct smb_filename *smb_fname_base = NULL;
5688 NTSTATUS status;
5690 if (!VALID_STAT(smb_fname->st)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5694 /* Always operate on the base_name, even if a stream was passed in. */
5695 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5696 NULL, &smb_fname->st,
5697 &smb_fname_base);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 return status;
5702 if (dosmode) {
5703 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5704 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5705 } else {
5706 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5710 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5712 /* check the mode isn't different, before changing it */
5713 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5714 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5715 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5716 (unsigned int)dosmode));
5718 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5719 false)) {
5720 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5721 "%s failed (%s)\n",
5722 smb_fname_str_dbg(smb_fname_base),
5723 strerror(errno)));
5724 status = map_nt_error_from_unix(errno);
5725 goto out;
5728 status = NT_STATUS_OK;
5729 out:
5730 TALLOC_FREE(smb_fname_base);
5731 return status;
5734 /****************************************************************************
5735 Deal with setting the size from any of the setfilepathinfo functions.
5736 ****************************************************************************/
5738 static NTSTATUS smb_set_file_size(connection_struct *conn,
5739 struct smb_request *req,
5740 files_struct *fsp,
5741 const struct smb_filename *smb_fname,
5742 const SMB_STRUCT_STAT *psbuf,
5743 off_t size,
5744 bool fail_after_createfile)
5746 NTSTATUS status = NT_STATUS_OK;
5747 struct smb_filename *smb_fname_tmp = NULL;
5748 files_struct *new_fsp = NULL;
5750 if (!VALID_STAT(*psbuf)) {
5751 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5754 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5756 if (size == get_file_size_stat(psbuf)) {
5757 return NT_STATUS_OK;
5760 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5761 smb_fname_str_dbg(smb_fname), (double)size));
5763 if (fsp && fsp->fh->fd != -1) {
5764 /* Handle based call. */
5765 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5766 return NT_STATUS_ACCESS_DENIED;
5769 if (vfs_set_filelen(fsp, size) == -1) {
5770 return map_nt_error_from_unix(errno);
5772 trigger_write_time_update_immediate(fsp);
5773 return NT_STATUS_OK;
5776 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5777 if (!NT_STATUS_IS_OK(status)) {
5778 return status;
5781 smb_fname_tmp->st = *psbuf;
5783 status = SMB_VFS_CREATE_FILE(
5784 conn, /* conn */
5785 req, /* req */
5786 0, /* root_dir_fid */
5787 smb_fname_tmp, /* fname */
5788 FILE_WRITE_DATA, /* access_mask */
5789 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5790 FILE_SHARE_DELETE),
5791 FILE_OPEN, /* create_disposition*/
5792 0, /* create_options */
5793 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5794 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5795 0, /* allocation_size */
5796 0, /* private_flags */
5797 NULL, /* sd */
5798 NULL, /* ea_list */
5799 &new_fsp, /* result */
5800 NULL); /* pinfo */
5802 TALLOC_FREE(smb_fname_tmp);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 /* NB. We check for open_was_deferred in the caller. */
5806 return status;
5809 /* See RAW-SFILEINFO-END-OF-FILE */
5810 if (fail_after_createfile) {
5811 close_file(req, new_fsp,NORMAL_CLOSE);
5812 return NT_STATUS_INVALID_LEVEL;
5815 if (vfs_set_filelen(new_fsp, size) == -1) {
5816 status = map_nt_error_from_unix(errno);
5817 close_file(req, new_fsp,NORMAL_CLOSE);
5818 return status;
5821 trigger_write_time_update_immediate(new_fsp);
5822 close_file(req, new_fsp,NORMAL_CLOSE);
5823 return NT_STATUS_OK;
5826 /****************************************************************************
5827 Deal with SMB_INFO_SET_EA.
5828 ****************************************************************************/
5830 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5831 const char *pdata,
5832 int total_data,
5833 files_struct *fsp,
5834 const struct smb_filename *smb_fname)
5836 struct ea_list *ea_list = NULL;
5837 TALLOC_CTX *ctx = NULL;
5838 NTSTATUS status = NT_STATUS_OK;
5840 if (total_data < 10) {
5842 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5843 length. They seem to have no effect. Bug #3212. JRA */
5845 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5846 /* We're done. We only get EA info in this call. */
5847 return NT_STATUS_OK;
5850 return NT_STATUS_INVALID_PARAMETER;
5853 if (IVAL(pdata,0) > total_data) {
5854 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5855 IVAL(pdata,0), (unsigned int)total_data));
5856 return NT_STATUS_INVALID_PARAMETER;
5859 ctx = talloc_tos();
5860 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5861 if (!ea_list) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 status = set_ea(conn, fsp, smb_fname, ea_list);
5867 return status;
5870 /****************************************************************************
5871 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5872 ****************************************************************************/
5874 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5875 const char *pdata,
5876 int total_data,
5877 files_struct *fsp)
5879 struct ea_list *ea_list = NULL;
5880 NTSTATUS status;
5882 if (!fsp) {
5883 return NT_STATUS_INVALID_HANDLE;
5886 if (!lp_ea_support(SNUM(conn))) {
5887 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5888 "EA's not supported.\n",
5889 (unsigned int)total_data));
5890 return NT_STATUS_EAS_NOT_SUPPORTED;
5893 if (total_data < 10) {
5894 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5895 "too small.\n",
5896 (unsigned int)total_data));
5897 return NT_STATUS_INVALID_PARAMETER;
5900 ea_list = read_nttrans_ea_list(talloc_tos(),
5901 pdata,
5902 total_data);
5904 if (!ea_list) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5910 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5911 smb_fname_str_dbg(fsp->fsp_name),
5912 nt_errstr(status) ));
5914 return status;
5918 /****************************************************************************
5919 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5920 ****************************************************************************/
5922 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5923 const char *pdata,
5924 int total_data,
5925 files_struct *fsp,
5926 struct smb_filename *smb_fname)
5928 NTSTATUS status = NT_STATUS_OK;
5929 bool delete_on_close;
5930 uint32 dosmode = 0;
5932 if (total_data < 1) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 if (fsp == NULL) {
5937 return NT_STATUS_INVALID_HANDLE;
5940 delete_on_close = (CVAL(pdata,0) ? True : False);
5941 dosmode = dos_mode(conn, smb_fname);
5943 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5944 "delete_on_close = %u\n",
5945 smb_fname_str_dbg(smb_fname),
5946 (unsigned int)dosmode,
5947 (unsigned int)delete_on_close ));
5949 if (delete_on_close) {
5950 status = can_set_delete_on_close(fsp, dosmode);
5951 if (!NT_STATUS_IS_OK(status)) {
5952 return status;
5956 /* The set is across all open files on this dev/inode pair. */
5957 if (!set_delete_on_close(fsp, delete_on_close,
5958 conn->session_info->security_token,
5959 conn->session_info->unix_token)) {
5960 return NT_STATUS_ACCESS_DENIED;
5962 return NT_STATUS_OK;
5965 /****************************************************************************
5966 Deal with SMB_FILE_POSITION_INFORMATION.
5967 ****************************************************************************/
5969 static NTSTATUS smb_file_position_information(connection_struct *conn,
5970 const char *pdata,
5971 int total_data,
5972 files_struct *fsp)
5974 uint64_t position_information;
5976 if (total_data < 8) {
5977 return NT_STATUS_INVALID_PARAMETER;
5980 if (fsp == NULL) {
5981 /* Ignore on pathname based set. */
5982 return NT_STATUS_OK;
5985 position_information = (uint64_t)IVAL(pdata,0);
5986 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5988 DEBUG(10,("smb_file_position_information: Set file position "
5989 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5990 (double)position_information));
5991 fsp->fh->position_information = position_information;
5992 return NT_STATUS_OK;
5995 /****************************************************************************
5996 Deal with SMB_FILE_MODE_INFORMATION.
5997 ****************************************************************************/
5999 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6000 const char *pdata,
6001 int total_data)
6003 uint32 mode;
6005 if (total_data < 4) {
6006 return NT_STATUS_INVALID_PARAMETER;
6008 mode = IVAL(pdata,0);
6009 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6010 return NT_STATUS_INVALID_PARAMETER;
6012 return NT_STATUS_OK;
6015 /****************************************************************************
6016 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6017 ****************************************************************************/
6019 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6020 struct smb_request *req,
6021 const char *pdata,
6022 int total_data,
6023 const struct smb_filename *smb_fname)
6025 char *link_target = NULL;
6026 const char *newname = smb_fname->base_name;
6027 TALLOC_CTX *ctx = talloc_tos();
6029 /* Set a symbolic link. */
6030 /* Don't allow this if follow links is false. */
6032 if (total_data == 0) {
6033 return NT_STATUS_INVALID_PARAMETER;
6036 if (!lp_symlinks(SNUM(conn))) {
6037 return NT_STATUS_ACCESS_DENIED;
6040 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6041 total_data, STR_TERMINATE);
6043 if (!link_target) {
6044 return NT_STATUS_INVALID_PARAMETER;
6047 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6048 newname, link_target ));
6050 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6051 return map_nt_error_from_unix(errno);
6054 return NT_STATUS_OK;
6057 /****************************************************************************
6058 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6059 ****************************************************************************/
6061 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6062 struct smb_request *req,
6063 const char *pdata, int total_data,
6064 struct smb_filename *smb_fname_new)
6066 char *oldname = NULL;
6067 struct smb_filename *smb_fname_old = NULL;
6068 TALLOC_CTX *ctx = talloc_tos();
6069 NTSTATUS status = NT_STATUS_OK;
6071 /* Set a hard link. */
6072 if (total_data == 0) {
6073 return NT_STATUS_INVALID_PARAMETER;
6076 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6077 total_data, STR_TERMINATE, &status);
6078 if (!NT_STATUS_IS_OK(status)) {
6079 return status;
6082 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6083 smb_fname_str_dbg(smb_fname_new), oldname));
6085 status = filename_convert(ctx,
6086 conn,
6087 req->flags2 & FLAGS2_DFS_PATHNAMES,
6088 oldname,
6090 NULL,
6091 &smb_fname_old);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 return status;
6096 return hardlink_internals(ctx, conn, req, false,
6097 smb_fname_old, smb_fname_new);
6100 /****************************************************************************
6101 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6102 ****************************************************************************/
6104 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6105 struct smb_request *req,
6106 const char *pdata,
6107 int total_data,
6108 files_struct *fsp,
6109 struct smb_filename *smb_fname_src)
6111 bool overwrite;
6112 uint32_t len;
6113 char *newname = NULL;
6114 struct smb_filename *smb_fname_dst = NULL;
6115 NTSTATUS status = NT_STATUS_OK;
6116 TALLOC_CTX *ctx = talloc_tos();
6118 if (!fsp) {
6119 return NT_STATUS_INVALID_HANDLE;
6122 if (total_data < 20) {
6123 return NT_STATUS_INVALID_PARAMETER;
6126 overwrite = (CVAL(pdata,0) ? True : False);
6127 len = IVAL(pdata,16);
6129 if (len > (total_data - 20) || (len == 0)) {
6130 return NT_STATUS_INVALID_PARAMETER;
6133 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6134 &pdata[20], len, STR_TERMINATE,
6135 &status);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 return status;
6140 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6141 newname));
6143 status = filename_convert(ctx,
6144 conn,
6145 req->flags2 & FLAGS2_DFS_PATHNAMES,
6146 newname,
6147 UCF_SAVE_LCOMP,
6148 NULL,
6149 &smb_fname_dst);
6150 if (!NT_STATUS_IS_OK(status)) {
6151 return status;
6154 if (fsp->base_fsp) {
6155 /* newname must be a stream name. */
6156 if (newname[0] != ':') {
6157 return NT_STATUS_NOT_SUPPORTED;
6160 /* Create an smb_fname to call rename_internals_fsp() with. */
6161 status = create_synthetic_smb_fname(talloc_tos(),
6162 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6163 &smb_fname_dst);
6164 if (!NT_STATUS_IS_OK(status)) {
6165 goto out;
6169 * Set the original last component, since
6170 * rename_internals_fsp() requires it.
6172 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6173 newname);
6174 if (smb_fname_dst->original_lcomp == NULL) {
6175 status = NT_STATUS_NO_MEMORY;
6176 goto out;
6181 DEBUG(10,("smb2_file_rename_information: "
6182 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6183 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6184 smb_fname_str_dbg(smb_fname_dst)));
6185 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6186 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6187 overwrite);
6189 out:
6190 TALLOC_FREE(smb_fname_dst);
6191 return status;
6194 static NTSTATUS smb_file_link_information(connection_struct *conn,
6195 struct smb_request *req,
6196 const char *pdata,
6197 int total_data,
6198 files_struct *fsp,
6199 struct smb_filename *smb_fname_src)
6201 bool overwrite;
6202 uint32_t len;
6203 char *newname = NULL;
6204 struct smb_filename *smb_fname_dst = NULL;
6205 NTSTATUS status = NT_STATUS_OK;
6206 TALLOC_CTX *ctx = talloc_tos();
6208 if (!fsp) {
6209 return NT_STATUS_INVALID_HANDLE;
6212 if (total_data < 20) {
6213 return NT_STATUS_INVALID_PARAMETER;
6216 overwrite = (CVAL(pdata,0) ? true : false);
6217 len = IVAL(pdata,16);
6219 if (len > (total_data - 20) || (len == 0)) {
6220 return NT_STATUS_INVALID_PARAMETER;
6223 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6224 &pdata[20], len, STR_TERMINATE,
6225 &status);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 return status;
6230 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6231 newname));
6233 status = filename_convert(ctx,
6234 conn,
6235 req->flags2 & FLAGS2_DFS_PATHNAMES,
6236 newname,
6237 UCF_SAVE_LCOMP,
6238 NULL,
6239 &smb_fname_dst);
6240 if (!NT_STATUS_IS_OK(status)) {
6241 return status;
6244 if (fsp->base_fsp) {
6245 /* No stream names. */
6246 return NT_STATUS_NOT_SUPPORTED;
6249 DEBUG(10,("smb_file_link_information: "
6250 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6251 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6252 smb_fname_str_dbg(smb_fname_dst)));
6253 status = hardlink_internals(ctx,
6254 conn,
6255 req,
6256 overwrite,
6257 fsp->fsp_name,
6258 smb_fname_dst);
6260 TALLOC_FREE(smb_fname_dst);
6261 return status;
6264 /****************************************************************************
6265 Deal with SMB_FILE_RENAME_INFORMATION.
6266 ****************************************************************************/
6268 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6269 struct smb_request *req,
6270 const char *pdata,
6271 int total_data,
6272 files_struct *fsp,
6273 struct smb_filename *smb_fname_src)
6275 bool overwrite;
6276 uint32 root_fid;
6277 uint32 len;
6278 char *newname = NULL;
6279 struct smb_filename *smb_fname_dst = NULL;
6280 bool dest_has_wcard = False;
6281 NTSTATUS status = NT_STATUS_OK;
6282 char *p;
6283 TALLOC_CTX *ctx = talloc_tos();
6285 if (total_data < 13) {
6286 return NT_STATUS_INVALID_PARAMETER;
6289 overwrite = (CVAL(pdata,0) ? True : False);
6290 root_fid = IVAL(pdata,4);
6291 len = IVAL(pdata,8);
6293 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6294 return NT_STATUS_INVALID_PARAMETER;
6297 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6298 len, 0, &status,
6299 &dest_has_wcard);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 return status;
6304 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6305 newname));
6307 status = resolve_dfspath_wcard(ctx, conn,
6308 req->flags2 & FLAGS2_DFS_PATHNAMES,
6309 newname,
6310 true,
6311 !conn->sconn->using_smb2,
6312 &newname,
6313 &dest_has_wcard);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 return status;
6318 /* Check the new name has no '/' characters. */
6319 if (strchr_m(newname, '/')) {
6320 return NT_STATUS_NOT_SUPPORTED;
6323 if (fsp && fsp->base_fsp) {
6324 /* newname must be a stream name. */
6325 if (newname[0] != ':') {
6326 return NT_STATUS_NOT_SUPPORTED;
6329 /* Create an smb_fname to call rename_internals_fsp() with. */
6330 status = create_synthetic_smb_fname(talloc_tos(),
6331 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6332 &smb_fname_dst);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 goto out;
6338 * Set the original last component, since
6339 * rename_internals_fsp() requires it.
6341 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6342 newname);
6343 if (smb_fname_dst->original_lcomp == NULL) {
6344 status = NT_STATUS_NO_MEMORY;
6345 goto out;
6348 } else {
6350 * Build up an smb_fname_dst based on the filename passed in.
6351 * We basically just strip off the last component, and put on
6352 * the newname instead.
6354 char *base_name = NULL;
6356 /* newname must *not* be a stream name. */
6357 if (newname[0] == ':') {
6358 return NT_STATUS_NOT_SUPPORTED;
6362 * Strip off the last component (filename) of the path passed
6363 * in.
6365 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6366 if (!base_name) {
6367 return NT_STATUS_NO_MEMORY;
6369 p = strrchr_m(base_name, '/');
6370 if (p) {
6371 p[1] = '\0';
6372 } else {
6373 base_name = talloc_strdup(ctx, "");
6374 if (!base_name) {
6375 return NT_STATUS_NO_MEMORY;
6378 /* Append the new name. */
6379 base_name = talloc_asprintf_append(base_name,
6380 "%s",
6381 newname);
6382 if (!base_name) {
6383 return NT_STATUS_NO_MEMORY;
6386 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6387 (UCF_SAVE_LCOMP |
6388 (dest_has_wcard ?
6389 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6390 0)));
6392 /* If an error we expect this to be
6393 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6395 if (!NT_STATUS_IS_OK(status)) {
6396 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6397 status)) {
6398 goto out;
6400 /* Create an smb_fname to call rename_internals_fsp() */
6401 status = create_synthetic_smb_fname(ctx,
6402 base_name, NULL,
6403 NULL,
6404 &smb_fname_dst);
6405 if (!NT_STATUS_IS_OK(status)) {
6406 goto out;
6411 if (fsp) {
6412 DEBUG(10,("smb_file_rename_information: "
6413 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6414 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6415 smb_fname_str_dbg(smb_fname_dst)));
6416 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6417 overwrite);
6418 } else {
6419 DEBUG(10,("smb_file_rename_information: "
6420 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6421 smb_fname_str_dbg(smb_fname_src),
6422 smb_fname_str_dbg(smb_fname_dst)));
6423 status = rename_internals(ctx, conn, req, smb_fname_src,
6424 smb_fname_dst, 0, overwrite, false,
6425 dest_has_wcard,
6426 FILE_WRITE_ATTRIBUTES);
6428 out:
6429 TALLOC_FREE(smb_fname_dst);
6430 return status;
6433 /****************************************************************************
6434 Deal with SMB_SET_POSIX_ACL.
6435 ****************************************************************************/
6437 #if defined(HAVE_POSIX_ACLS)
6438 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6439 const char *pdata,
6440 int total_data,
6441 files_struct *fsp,
6442 const struct smb_filename *smb_fname)
6444 uint16 posix_acl_version;
6445 uint16 num_file_acls;
6446 uint16 num_def_acls;
6447 bool valid_file_acls = True;
6448 bool valid_def_acls = True;
6450 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6451 return NT_STATUS_INVALID_PARAMETER;
6453 posix_acl_version = SVAL(pdata,0);
6454 num_file_acls = SVAL(pdata,2);
6455 num_def_acls = SVAL(pdata,4);
6457 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6458 valid_file_acls = False;
6459 num_file_acls = 0;
6462 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6463 valid_def_acls = False;
6464 num_def_acls = 0;
6467 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6468 return NT_STATUS_INVALID_PARAMETER;
6471 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6472 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6473 return NT_STATUS_INVALID_PARAMETER;
6476 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6477 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6478 (unsigned int)num_file_acls,
6479 (unsigned int)num_def_acls));
6481 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6482 smb_fname->base_name, num_file_acls,
6483 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6484 return map_nt_error_from_unix(errno);
6487 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6488 smb_fname->base_name, &smb_fname->st, num_def_acls,
6489 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6490 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6491 return map_nt_error_from_unix(errno);
6493 return NT_STATUS_OK;
6495 #endif
6497 /****************************************************************************
6498 Deal with SMB_SET_POSIX_LOCK.
6499 ****************************************************************************/
6501 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6502 struct smb_request *req,
6503 const char *pdata,
6504 int total_data,
6505 files_struct *fsp)
6507 uint64_t count;
6508 uint64_t offset;
6509 uint64_t smblctx;
6510 bool blocking_lock = False;
6511 enum brl_type lock_type;
6513 NTSTATUS status = NT_STATUS_OK;
6515 if (fsp == NULL || fsp->fh->fd == -1) {
6516 return NT_STATUS_INVALID_HANDLE;
6519 if (total_data != POSIX_LOCK_DATA_SIZE) {
6520 return NT_STATUS_INVALID_PARAMETER;
6523 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6524 case POSIX_LOCK_TYPE_READ:
6525 lock_type = READ_LOCK;
6526 break;
6527 case POSIX_LOCK_TYPE_WRITE:
6528 /* Return the right POSIX-mappable error code for files opened read-only. */
6529 if (!fsp->can_write) {
6530 return NT_STATUS_INVALID_HANDLE;
6532 lock_type = WRITE_LOCK;
6533 break;
6534 case POSIX_LOCK_TYPE_UNLOCK:
6535 lock_type = UNLOCK_LOCK;
6536 break;
6537 default:
6538 return NT_STATUS_INVALID_PARAMETER;
6541 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6542 blocking_lock = False;
6543 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6544 blocking_lock = True;
6545 } else {
6546 return NT_STATUS_INVALID_PARAMETER;
6549 if (!lp_blocking_locks(SNUM(conn))) {
6550 blocking_lock = False;
6553 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6554 #if defined(HAVE_LONGLONG)
6555 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6556 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6557 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6558 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6559 #else /* HAVE_LONGLONG */
6560 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6561 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6562 #endif /* HAVE_LONGLONG */
6564 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6565 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6566 fsp_str_dbg(fsp),
6567 (unsigned int)lock_type,
6568 (unsigned long long)smblctx,
6569 (double)count,
6570 (double)offset ));
6572 if (lock_type == UNLOCK_LOCK) {
6573 status = do_unlock(req->sconn->msg_ctx,
6574 fsp,
6575 smblctx,
6576 count,
6577 offset,
6578 POSIX_LOCK);
6579 } else {
6580 uint64_t block_smblctx;
6582 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6583 fsp,
6584 smblctx,
6585 count,
6586 offset,
6587 lock_type,
6588 POSIX_LOCK,
6589 blocking_lock,
6590 &status,
6591 &block_smblctx,
6592 NULL);
6594 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6596 * A blocking lock was requested. Package up
6597 * this smb into a queued request and push it
6598 * onto the blocking lock queue.
6600 if(push_blocking_lock_request(br_lck,
6601 req,
6602 fsp,
6603 -1, /* infinite timeout. */
6605 smblctx,
6606 lock_type,
6607 POSIX_LOCK,
6608 offset,
6609 count,
6610 block_smblctx)) {
6611 TALLOC_FREE(br_lck);
6612 return status;
6615 TALLOC_FREE(br_lck);
6618 return status;
6621 /****************************************************************************
6622 Deal with SMB_SET_FILE_BASIC_INFO.
6623 ****************************************************************************/
6625 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6626 const char *pdata,
6627 int total_data,
6628 files_struct *fsp,
6629 const struct smb_filename *smb_fname)
6631 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6632 struct smb_file_time ft;
6633 uint32 dosmode = 0;
6634 NTSTATUS status = NT_STATUS_OK;
6636 ZERO_STRUCT(ft);
6638 if (total_data < 36) {
6639 return NT_STATUS_INVALID_PARAMETER;
6642 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6643 if (!NT_STATUS_IS_OK(status)) {
6644 return status;
6647 /* Set the attributes */
6648 dosmode = IVAL(pdata,32);
6649 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6650 if (!NT_STATUS_IS_OK(status)) {
6651 return status;
6654 /* create time */
6655 ft.create_time = interpret_long_date(pdata);
6657 /* access time */
6658 ft.atime = interpret_long_date(pdata+8);
6660 /* write time. */
6661 ft.mtime = interpret_long_date(pdata+16);
6663 /* change time. */
6664 ft.ctime = interpret_long_date(pdata+24);
6666 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6667 smb_fname_str_dbg(smb_fname)));
6669 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6670 true);
6673 /****************************************************************************
6674 Deal with SMB_INFO_STANDARD.
6675 ****************************************************************************/
6677 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6678 const char *pdata,
6679 int total_data,
6680 files_struct *fsp,
6681 const struct smb_filename *smb_fname)
6683 NTSTATUS status;
6684 struct smb_file_time ft;
6686 ZERO_STRUCT(ft);
6688 if (total_data < 12) {
6689 return NT_STATUS_INVALID_PARAMETER;
6692 /* create time */
6693 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6694 /* access time */
6695 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6696 /* write time */
6697 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6699 DEBUG(10,("smb_set_info_standard: file %s\n",
6700 smb_fname_str_dbg(smb_fname)));
6702 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6703 if (!NT_STATUS_IS_OK(status)) {
6704 return status;
6707 return smb_set_file_time(conn,
6708 fsp,
6709 smb_fname,
6710 &ft,
6711 true);
6714 /****************************************************************************
6715 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6716 ****************************************************************************/
6718 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6719 struct smb_request *req,
6720 const char *pdata,
6721 int total_data,
6722 files_struct *fsp,
6723 struct smb_filename *smb_fname)
6725 uint64_t allocation_size = 0;
6726 NTSTATUS status = NT_STATUS_OK;
6727 files_struct *new_fsp = NULL;
6729 if (!VALID_STAT(smb_fname->st)) {
6730 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6733 if (total_data < 8) {
6734 return NT_STATUS_INVALID_PARAMETER;
6737 allocation_size = (uint64_t)IVAL(pdata,0);
6738 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6739 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6740 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6741 (double)allocation_size));
6743 if (allocation_size) {
6744 allocation_size = smb_roundup(conn, allocation_size);
6747 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6748 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6749 (double)allocation_size));
6751 if (fsp && fsp->fh->fd != -1) {
6752 /* Open file handle. */
6753 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6754 return NT_STATUS_ACCESS_DENIED;
6757 /* Only change if needed. */
6758 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6759 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6760 return map_nt_error_from_unix(errno);
6763 /* But always update the time. */
6765 * This is equivalent to a write. Ensure it's seen immediately
6766 * if there are no pending writes.
6768 trigger_write_time_update_immediate(fsp);
6769 return NT_STATUS_OK;
6772 /* Pathname or stat or directory file. */
6773 status = SMB_VFS_CREATE_FILE(
6774 conn, /* conn */
6775 req, /* req */
6776 0, /* root_dir_fid */
6777 smb_fname, /* fname */
6778 FILE_WRITE_DATA, /* access_mask */
6779 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6780 FILE_SHARE_DELETE),
6781 FILE_OPEN, /* create_disposition*/
6782 0, /* create_options */
6783 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6784 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6785 0, /* allocation_size */
6786 0, /* private_flags */
6787 NULL, /* sd */
6788 NULL, /* ea_list */
6789 &new_fsp, /* result */
6790 NULL); /* pinfo */
6792 if (!NT_STATUS_IS_OK(status)) {
6793 /* NB. We check for open_was_deferred in the caller. */
6794 return status;
6797 /* Only change if needed. */
6798 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6799 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6800 status = map_nt_error_from_unix(errno);
6801 close_file(req, new_fsp, NORMAL_CLOSE);
6802 return status;
6806 /* Changing the allocation size should set the last mod time. */
6808 * This is equivalent to a write. Ensure it's seen immediately
6809 * if there are no pending writes.
6811 trigger_write_time_update_immediate(new_fsp);
6813 close_file(req, new_fsp, NORMAL_CLOSE);
6814 return NT_STATUS_OK;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6819 ****************************************************************************/
6821 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6822 struct smb_request *req,
6823 const char *pdata,
6824 int total_data,
6825 files_struct *fsp,
6826 const struct smb_filename *smb_fname,
6827 bool fail_after_createfile)
6829 off_t size;
6831 if (total_data < 8) {
6832 return NT_STATUS_INVALID_PARAMETER;
6835 size = IVAL(pdata,0);
6836 size |= (((off_t)IVAL(pdata,4)) << 32);
6837 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6838 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6839 (double)size));
6841 return smb_set_file_size(conn, req,
6842 fsp,
6843 smb_fname,
6844 &smb_fname->st,
6845 size,
6846 fail_after_createfile);
6849 /****************************************************************************
6850 Allow a UNIX info mknod.
6851 ****************************************************************************/
6853 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6854 const char *pdata,
6855 int total_data,
6856 const struct smb_filename *smb_fname)
6858 uint32 file_type = IVAL(pdata,56);
6859 #if defined(HAVE_MAKEDEV)
6860 uint32 dev_major = IVAL(pdata,60);
6861 uint32 dev_minor = IVAL(pdata,68);
6862 #endif
6863 SMB_DEV_T dev = (SMB_DEV_T)0;
6864 uint32 raw_unixmode = IVAL(pdata,84);
6865 NTSTATUS status;
6866 mode_t unixmode;
6868 if (total_data < 100) {
6869 return NT_STATUS_INVALID_PARAMETER;
6872 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6873 PERM_NEW_FILE, &unixmode);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 return status;
6878 #if defined(HAVE_MAKEDEV)
6879 dev = makedev(dev_major, dev_minor);
6880 #endif
6882 switch (file_type) {
6883 #if defined(S_IFIFO)
6884 case UNIX_TYPE_FIFO:
6885 unixmode |= S_IFIFO;
6886 break;
6887 #endif
6888 #if defined(S_IFSOCK)
6889 case UNIX_TYPE_SOCKET:
6890 unixmode |= S_IFSOCK;
6891 break;
6892 #endif
6893 #if defined(S_IFCHR)
6894 case UNIX_TYPE_CHARDEV:
6895 unixmode |= S_IFCHR;
6896 break;
6897 #endif
6898 #if defined(S_IFBLK)
6899 case UNIX_TYPE_BLKDEV:
6900 unixmode |= S_IFBLK;
6901 break;
6902 #endif
6903 default:
6904 return NT_STATUS_INVALID_PARAMETER;
6907 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6908 "%.0f mode 0%o for file %s\n", (double)dev,
6909 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6911 /* Ok - do the mknod. */
6912 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6913 return map_nt_error_from_unix(errno);
6916 /* If any of the other "set" calls fail we
6917 * don't want to end up with a half-constructed mknod.
6920 if (lp_inherit_perms(SNUM(conn))) {
6921 char *parent;
6922 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6923 &parent, NULL)) {
6924 return NT_STATUS_NO_MEMORY;
6926 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6927 unixmode);
6928 TALLOC_FREE(parent);
6931 return NT_STATUS_OK;
6934 /****************************************************************************
6935 Deal with SMB_SET_FILE_UNIX_BASIC.
6936 ****************************************************************************/
6938 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6939 struct smb_request *req,
6940 const char *pdata,
6941 int total_data,
6942 files_struct *fsp,
6943 const struct smb_filename *smb_fname)
6945 struct smb_file_time ft;
6946 uint32 raw_unixmode;
6947 mode_t unixmode;
6948 off_t size = 0;
6949 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6950 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6951 NTSTATUS status = NT_STATUS_OK;
6952 bool delete_on_fail = False;
6953 enum perm_type ptype;
6954 files_struct *all_fsps = NULL;
6955 bool modify_mtime = true;
6956 struct file_id id;
6957 struct smb_filename *smb_fname_tmp = NULL;
6958 SMB_STRUCT_STAT sbuf;
6960 ZERO_STRUCT(ft);
6962 if (total_data < 100) {
6963 return NT_STATUS_INVALID_PARAMETER;
6966 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6967 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6968 size=IVAL(pdata,0); /* first 8 Bytes are size */
6969 size |= (((off_t)IVAL(pdata,4)) << 32);
6972 ft.atime = interpret_long_date(pdata+24); /* access_time */
6973 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6974 set_owner = (uid_t)IVAL(pdata,40);
6975 set_grp = (gid_t)IVAL(pdata,48);
6976 raw_unixmode = IVAL(pdata,84);
6978 if (VALID_STAT(smb_fname->st)) {
6979 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6980 ptype = PERM_EXISTING_DIR;
6981 } else {
6982 ptype = PERM_EXISTING_FILE;
6984 } else {
6985 ptype = PERM_NEW_FILE;
6988 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6989 ptype, &unixmode);
6990 if (!NT_STATUS_IS_OK(status)) {
6991 return status;
6994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6995 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6996 smb_fname_str_dbg(smb_fname), (double)size,
6997 (unsigned int)set_owner, (unsigned int)set_grp,
6998 (int)raw_unixmode));
7000 sbuf = smb_fname->st;
7002 if (!VALID_STAT(sbuf)) {
7004 * The only valid use of this is to create character and block
7005 * devices, and named pipes. This is deprecated (IMHO) and
7006 * a new info level should be used for mknod. JRA.
7009 status = smb_unix_mknod(conn,
7010 pdata,
7011 total_data,
7012 smb_fname);
7013 if (!NT_STATUS_IS_OK(status)) {
7014 return status;
7017 status = copy_smb_filename(talloc_tos(), smb_fname,
7018 &smb_fname_tmp);
7019 if (!NT_STATUS_IS_OK(status)) {
7020 return status;
7023 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7024 status = map_nt_error_from_unix(errno);
7025 TALLOC_FREE(smb_fname_tmp);
7026 SMB_VFS_UNLINK(conn, smb_fname);
7027 return status;
7030 sbuf = smb_fname_tmp->st;
7031 smb_fname = smb_fname_tmp;
7033 /* Ensure we don't try and change anything else. */
7034 raw_unixmode = SMB_MODE_NO_CHANGE;
7035 size = get_file_size_stat(&sbuf);
7036 ft.atime = sbuf.st_ex_atime;
7037 ft.mtime = sbuf.st_ex_mtime;
7039 * We continue here as we might want to change the
7040 * owner uid/gid.
7042 delete_on_fail = True;
7045 #if 1
7046 /* Horrible backwards compatibility hack as an old server bug
7047 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7048 * */
7050 if (!size) {
7051 size = get_file_size_stat(&sbuf);
7053 #endif
7056 * Deal with the UNIX specific mode set.
7059 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7060 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7061 "setting mode 0%o for file %s\n",
7062 (unsigned int)unixmode,
7063 smb_fname_str_dbg(smb_fname)));
7064 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7065 return map_nt_error_from_unix(errno);
7070 * Deal with the UNIX specific uid set.
7073 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7074 (sbuf.st_ex_uid != set_owner)) {
7075 int ret;
7077 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7078 "changing owner %u for path %s\n",
7079 (unsigned int)set_owner,
7080 smb_fname_str_dbg(smb_fname)));
7082 if (S_ISLNK(sbuf.st_ex_mode)) {
7083 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7084 set_owner, (gid_t)-1);
7085 } else {
7086 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7087 set_owner, (gid_t)-1);
7090 if (ret != 0) {
7091 status = map_nt_error_from_unix(errno);
7092 if (delete_on_fail) {
7093 SMB_VFS_UNLINK(conn, smb_fname);
7095 return status;
7100 * Deal with the UNIX specific gid set.
7103 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7104 (sbuf.st_ex_gid != set_grp)) {
7105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7106 "changing group %u for file %s\n",
7107 (unsigned int)set_owner,
7108 smb_fname_str_dbg(smb_fname)));
7109 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7110 set_grp) != 0) {
7111 status = map_nt_error_from_unix(errno);
7112 if (delete_on_fail) {
7113 SMB_VFS_UNLINK(conn, smb_fname);
7115 return status;
7119 /* Deal with any size changes. */
7121 status = smb_set_file_size(conn, req,
7122 fsp,
7123 smb_fname,
7124 &sbuf,
7125 size,
7126 false);
7127 if (!NT_STATUS_IS_OK(status)) {
7128 return status;
7131 /* Deal with any time changes. */
7132 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7133 /* No change, don't cancel anything. */
7134 return status;
7137 id = vfs_file_id_from_sbuf(conn, &sbuf);
7138 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7139 all_fsps = file_find_di_next(all_fsps)) {
7141 * We're setting the time explicitly for UNIX.
7142 * Cancel any pending changes over all handles.
7144 all_fsps->update_write_time_on_close = false;
7145 TALLOC_FREE(all_fsps->update_write_time_event);
7149 * Override the "setting_write_time"
7150 * parameter here as it almost does what
7151 * we need. Just remember if we modified
7152 * mtime and send the notify ourselves.
7154 if (null_timespec(ft.mtime)) {
7155 modify_mtime = false;
7158 status = smb_set_file_time(conn,
7159 fsp,
7160 smb_fname,
7161 &ft,
7162 false);
7163 if (modify_mtime) {
7164 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7165 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7167 return status;
7170 /****************************************************************************
7171 Deal with SMB_SET_FILE_UNIX_INFO2.
7172 ****************************************************************************/
7174 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7175 struct smb_request *req,
7176 const char *pdata,
7177 int total_data,
7178 files_struct *fsp,
7179 const struct smb_filename *smb_fname)
7181 NTSTATUS status;
7182 uint32 smb_fflags;
7183 uint32 smb_fmask;
7185 if (total_data < 116) {
7186 return NT_STATUS_INVALID_PARAMETER;
7189 /* Start by setting all the fields that are common between UNIX_BASIC
7190 * and UNIX_INFO2.
7192 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7193 fsp, smb_fname);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 return status;
7198 smb_fflags = IVAL(pdata, 108);
7199 smb_fmask = IVAL(pdata, 112);
7201 /* NB: We should only attempt to alter the file flags if the client
7202 * sends a non-zero mask.
7204 if (smb_fmask != 0) {
7205 int stat_fflags = 0;
7207 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7208 smb_fmask, &stat_fflags)) {
7209 /* Client asked to alter a flag we don't understand. */
7210 return NT_STATUS_INVALID_PARAMETER;
7213 if (fsp && fsp->fh->fd != -1) {
7214 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7215 return NT_STATUS_NOT_SUPPORTED;
7216 } else {
7217 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7218 stat_fflags) != 0) {
7219 return map_nt_error_from_unix(errno);
7224 /* XXX: need to add support for changing the create_time here. You
7225 * can do this for paths on Darwin with setattrlist(2). The right way
7226 * to hook this up is probably by extending the VFS utimes interface.
7229 return NT_STATUS_OK;
7232 /****************************************************************************
7233 Create a directory with POSIX semantics.
7234 ****************************************************************************/
7236 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7237 struct smb_request *req,
7238 char **ppdata,
7239 int total_data,
7240 struct smb_filename *smb_fname,
7241 int *pdata_return_size)
7243 NTSTATUS status = NT_STATUS_OK;
7244 uint32 raw_unixmode = 0;
7245 uint32 mod_unixmode = 0;
7246 mode_t unixmode = (mode_t)0;
7247 files_struct *fsp = NULL;
7248 uint16 info_level_return = 0;
7249 int info;
7250 char *pdata = *ppdata;
7252 if (total_data < 18) {
7253 return NT_STATUS_INVALID_PARAMETER;
7256 raw_unixmode = IVAL(pdata,8);
7257 /* Next 4 bytes are not yet defined. */
7259 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7260 PERM_NEW_DIR, &unixmode);
7261 if (!NT_STATUS_IS_OK(status)) {
7262 return status;
7265 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7267 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7268 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7270 status = SMB_VFS_CREATE_FILE(
7271 conn, /* conn */
7272 req, /* req */
7273 0, /* root_dir_fid */
7274 smb_fname, /* fname */
7275 FILE_READ_ATTRIBUTES, /* access_mask */
7276 FILE_SHARE_NONE, /* share_access */
7277 FILE_CREATE, /* create_disposition*/
7278 FILE_DIRECTORY_FILE, /* create_options */
7279 mod_unixmode, /* file_attributes */
7280 0, /* oplock_request */
7281 0, /* allocation_size */
7282 0, /* private_flags */
7283 NULL, /* sd */
7284 NULL, /* ea_list */
7285 &fsp, /* result */
7286 &info); /* pinfo */
7288 if (NT_STATUS_IS_OK(status)) {
7289 close_file(req, fsp, NORMAL_CLOSE);
7292 info_level_return = SVAL(pdata,16);
7294 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7295 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7296 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7297 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7298 } else {
7299 *pdata_return_size = 12;
7302 /* Realloc the data size */
7303 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7304 if (*ppdata == NULL) {
7305 *pdata_return_size = 0;
7306 return NT_STATUS_NO_MEMORY;
7308 pdata = *ppdata;
7310 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7311 SSVAL(pdata,2,0); /* No fnum. */
7312 SIVAL(pdata,4,info); /* Was directory created. */
7314 switch (info_level_return) {
7315 case SMB_QUERY_FILE_UNIX_BASIC:
7316 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7317 SSVAL(pdata,10,0); /* Padding. */
7318 store_file_unix_basic(conn, pdata + 12, fsp,
7319 &smb_fname->st);
7320 break;
7321 case SMB_QUERY_FILE_UNIX_INFO2:
7322 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7323 SSVAL(pdata,10,0); /* Padding. */
7324 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7325 &smb_fname->st);
7326 break;
7327 default:
7328 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7329 SSVAL(pdata,10,0); /* Padding. */
7330 break;
7333 return status;
7336 /****************************************************************************
7337 Open/Create a file with POSIX semantics.
7338 ****************************************************************************/
7340 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7341 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7343 static NTSTATUS smb_posix_open(connection_struct *conn,
7344 struct smb_request *req,
7345 char **ppdata,
7346 int total_data,
7347 struct smb_filename *smb_fname,
7348 int *pdata_return_size)
7350 bool extended_oplock_granted = False;
7351 char *pdata = *ppdata;
7352 uint32 flags = 0;
7353 uint32 wire_open_mode = 0;
7354 uint32 raw_unixmode = 0;
7355 uint32 mod_unixmode = 0;
7356 uint32 create_disp = 0;
7357 uint32 access_mask = 0;
7358 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7359 NTSTATUS status = NT_STATUS_OK;
7360 mode_t unixmode = (mode_t)0;
7361 files_struct *fsp = NULL;
7362 int oplock_request = 0;
7363 int info = 0;
7364 uint16 info_level_return = 0;
7366 if (total_data < 18) {
7367 return NT_STATUS_INVALID_PARAMETER;
7370 flags = IVAL(pdata,0);
7371 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7372 if (oplock_request) {
7373 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7376 wire_open_mode = IVAL(pdata,4);
7378 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7379 return smb_posix_mkdir(conn, req,
7380 ppdata,
7381 total_data,
7382 smb_fname,
7383 pdata_return_size);
7386 switch (wire_open_mode & SMB_ACCMODE) {
7387 case SMB_O_RDONLY:
7388 access_mask = SMB_O_RDONLY_MAPPING;
7389 break;
7390 case SMB_O_WRONLY:
7391 access_mask = SMB_O_WRONLY_MAPPING;
7392 break;
7393 case SMB_O_RDWR:
7394 access_mask = (SMB_O_RDONLY_MAPPING|
7395 SMB_O_WRONLY_MAPPING);
7396 break;
7397 default:
7398 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7399 (unsigned int)wire_open_mode ));
7400 return NT_STATUS_INVALID_PARAMETER;
7403 wire_open_mode &= ~SMB_ACCMODE;
7405 /* First take care of O_CREAT|O_EXCL interactions. */
7406 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7407 case (SMB_O_CREAT | SMB_O_EXCL):
7408 /* File exists fail. File not exist create. */
7409 create_disp = FILE_CREATE;
7410 break;
7411 case SMB_O_CREAT:
7412 /* File exists open. File not exist create. */
7413 create_disp = FILE_OPEN_IF;
7414 break;
7415 case SMB_O_EXCL:
7416 /* O_EXCL on its own without O_CREAT is undefined.
7417 We deliberately ignore it as some versions of
7418 Linux CIFSFS can send a bare O_EXCL on the
7419 wire which other filesystems in the kernel
7420 ignore. See bug 9519 for details. */
7422 /* Fallthrough. */
7424 case 0:
7425 /* File exists open. File not exist fail. */
7426 create_disp = FILE_OPEN;
7427 break;
7428 default:
7429 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7430 (unsigned int)wire_open_mode ));
7431 return NT_STATUS_INVALID_PARAMETER;
7434 /* Next factor in the effects of O_TRUNC. */
7435 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7437 if (wire_open_mode & SMB_O_TRUNC) {
7438 switch (create_disp) {
7439 case FILE_CREATE:
7440 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7441 /* Leave create_disp alone as
7442 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7444 /* File exists fail. File not exist create. */
7445 break;
7446 case FILE_OPEN_IF:
7447 /* SMB_O_CREAT | SMB_O_TRUNC */
7448 /* File exists overwrite. File not exist create. */
7449 create_disp = FILE_OVERWRITE_IF;
7450 break;
7451 case FILE_OPEN:
7452 /* SMB_O_TRUNC */
7453 /* File exists overwrite. File not exist fail. */
7454 create_disp = FILE_OVERWRITE;
7455 break;
7456 default:
7457 /* Cannot get here. */
7458 smb_panic("smb_posix_open: logic error");
7459 return NT_STATUS_INVALID_PARAMETER;
7463 raw_unixmode = IVAL(pdata,8);
7464 /* Next 4 bytes are not yet defined. */
7466 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7467 (VALID_STAT(smb_fname->st) ?
7468 PERM_EXISTING_FILE : PERM_NEW_FILE),
7469 &unixmode);
7471 if (!NT_STATUS_IS_OK(status)) {
7472 return status;
7475 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7477 if (wire_open_mode & SMB_O_SYNC) {
7478 create_options |= FILE_WRITE_THROUGH;
7480 if (wire_open_mode & SMB_O_APPEND) {
7481 access_mask |= FILE_APPEND_DATA;
7483 if (wire_open_mode & SMB_O_DIRECT) {
7484 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7487 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7488 VALID_STAT_OF_DIR(smb_fname->st)) {
7489 if (access_mask != SMB_O_RDONLY_MAPPING) {
7490 return NT_STATUS_FILE_IS_A_DIRECTORY;
7492 create_options &= ~FILE_NON_DIRECTORY_FILE;
7493 create_options |= FILE_DIRECTORY_FILE;
7496 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7497 smb_fname_str_dbg(smb_fname),
7498 (unsigned int)wire_open_mode,
7499 (unsigned int)unixmode ));
7501 status = SMB_VFS_CREATE_FILE(
7502 conn, /* conn */
7503 req, /* req */
7504 0, /* root_dir_fid */
7505 smb_fname, /* fname */
7506 access_mask, /* access_mask */
7507 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7508 FILE_SHARE_DELETE),
7509 create_disp, /* create_disposition*/
7510 create_options, /* create_options */
7511 mod_unixmode, /* file_attributes */
7512 oplock_request, /* oplock_request */
7513 0, /* allocation_size */
7514 0, /* private_flags */
7515 NULL, /* sd */
7516 NULL, /* ea_list */
7517 &fsp, /* result */
7518 &info); /* pinfo */
7520 if (!NT_STATUS_IS_OK(status)) {
7521 return status;
7524 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7525 extended_oplock_granted = True;
7528 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7529 extended_oplock_granted = True;
7532 info_level_return = SVAL(pdata,16);
7534 /* Allocate the correct return size. */
7536 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7537 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7538 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7539 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7540 } else {
7541 *pdata_return_size = 12;
7544 /* Realloc the data size */
7545 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7546 if (*ppdata == NULL) {
7547 close_file(req, fsp, ERROR_CLOSE);
7548 *pdata_return_size = 0;
7549 return NT_STATUS_NO_MEMORY;
7551 pdata = *ppdata;
7553 if (extended_oplock_granted) {
7554 if (flags & REQUEST_BATCH_OPLOCK) {
7555 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7556 } else {
7557 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7559 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7560 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7561 } else {
7562 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7565 SSVAL(pdata,2,fsp->fnum);
7566 SIVAL(pdata,4,info); /* Was file created etc. */
7568 switch (info_level_return) {
7569 case SMB_QUERY_FILE_UNIX_BASIC:
7570 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7571 SSVAL(pdata,10,0); /* padding. */
7572 store_file_unix_basic(conn, pdata + 12, fsp,
7573 &smb_fname->st);
7574 break;
7575 case SMB_QUERY_FILE_UNIX_INFO2:
7576 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7577 SSVAL(pdata,10,0); /* padding. */
7578 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7579 &smb_fname->st);
7580 break;
7581 default:
7582 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7583 SSVAL(pdata,10,0); /* padding. */
7584 break;
7586 return NT_STATUS_OK;
7589 /****************************************************************************
7590 Delete a file with POSIX semantics.
7591 ****************************************************************************/
7593 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7594 struct smb_request *req,
7595 const char *pdata,
7596 int total_data,
7597 struct smb_filename *smb_fname)
7599 NTSTATUS status = NT_STATUS_OK;
7600 files_struct *fsp = NULL;
7601 uint16 flags = 0;
7602 char del = 1;
7603 int info = 0;
7604 int create_options = 0;
7605 int i;
7606 struct share_mode_lock *lck = NULL;
7608 if (total_data < 2) {
7609 return NT_STATUS_INVALID_PARAMETER;
7612 flags = SVAL(pdata,0);
7614 if (!VALID_STAT(smb_fname->st)) {
7615 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7618 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7619 !VALID_STAT_OF_DIR(smb_fname->st)) {
7620 return NT_STATUS_NOT_A_DIRECTORY;
7623 DEBUG(10,("smb_posix_unlink: %s %s\n",
7624 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7625 smb_fname_str_dbg(smb_fname)));
7627 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7628 create_options |= FILE_DIRECTORY_FILE;
7631 status = SMB_VFS_CREATE_FILE(
7632 conn, /* conn */
7633 req, /* req */
7634 0, /* root_dir_fid */
7635 smb_fname, /* fname */
7636 DELETE_ACCESS, /* access_mask */
7637 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7638 FILE_SHARE_DELETE),
7639 FILE_OPEN, /* create_disposition*/
7640 create_options, /* create_options */
7641 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7642 0, /* oplock_request */
7643 0, /* allocation_size */
7644 0, /* private_flags */
7645 NULL, /* sd */
7646 NULL, /* ea_list */
7647 &fsp, /* result */
7648 &info); /* pinfo */
7650 if (!NT_STATUS_IS_OK(status)) {
7651 return status;
7655 * Don't lie to client. If we can't really delete due to
7656 * non-POSIX opens return SHARING_VIOLATION.
7659 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7660 if (lck == NULL) {
7661 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7662 "lock for file %s\n", fsp_str_dbg(fsp)));
7663 close_file(req, fsp, NORMAL_CLOSE);
7664 return NT_STATUS_INVALID_PARAMETER;
7668 * See if others still have the file open. If this is the case, then
7669 * don't delete. If all opens are POSIX delete we can set the delete
7670 * on close disposition.
7672 for (i=0; i<lck->data->num_share_modes; i++) {
7673 struct share_mode_entry *e = &lck->data->share_modes[i];
7674 if (is_valid_share_mode_entry(e)) {
7675 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7676 continue;
7678 if (share_mode_stale_pid(lck->data, i)) {
7679 continue;
7681 /* Fail with sharing violation. */
7682 TALLOC_FREE(lck);
7683 close_file(req, fsp, NORMAL_CLOSE);
7684 return NT_STATUS_SHARING_VIOLATION;
7689 * Set the delete on close.
7691 status = smb_set_file_disposition_info(conn,
7692 &del,
7694 fsp,
7695 smb_fname);
7697 TALLOC_FREE(lck);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 close_file(req, fsp, NORMAL_CLOSE);
7701 return status;
7703 return close_file(req, fsp, NORMAL_CLOSE);
7706 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7707 struct smb_request *req,
7708 TALLOC_CTX *mem_ctx,
7709 uint16_t info_level,
7710 files_struct *fsp,
7711 struct smb_filename *smb_fname,
7712 char **ppdata, int total_data,
7713 int *ret_data_size)
7715 char *pdata = *ppdata;
7716 NTSTATUS status = NT_STATUS_OK;
7717 int data_return_size = 0;
7719 *ret_data_size = 0;
7721 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7722 return NT_STATUS_INVALID_LEVEL;
7725 if (!CAN_WRITE(conn)) {
7726 /* Allow POSIX opens. The open path will deny
7727 * any non-readonly opens. */
7728 if (info_level != SMB_POSIX_PATH_OPEN) {
7729 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7733 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7734 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7735 fsp_fnum_dbg(fsp),
7736 info_level, total_data));
7738 switch (info_level) {
7740 case SMB_INFO_STANDARD:
7742 status = smb_set_info_standard(conn,
7743 pdata,
7744 total_data,
7745 fsp,
7746 smb_fname);
7747 break;
7750 case SMB_INFO_SET_EA:
7752 status = smb_info_set_ea(conn,
7753 pdata,
7754 total_data,
7755 fsp,
7756 smb_fname);
7757 break;
7760 case SMB_SET_FILE_BASIC_INFO:
7761 case SMB_FILE_BASIC_INFORMATION:
7763 status = smb_set_file_basic_info(conn,
7764 pdata,
7765 total_data,
7766 fsp,
7767 smb_fname);
7768 break;
7771 case SMB_FILE_ALLOCATION_INFORMATION:
7772 case SMB_SET_FILE_ALLOCATION_INFO:
7774 status = smb_set_file_allocation_info(conn, req,
7775 pdata,
7776 total_data,
7777 fsp,
7778 smb_fname);
7779 break;
7782 case SMB_FILE_END_OF_FILE_INFORMATION:
7783 case SMB_SET_FILE_END_OF_FILE_INFO:
7786 * XP/Win7 both fail after the createfile with
7787 * SMB_SET_FILE_END_OF_FILE_INFO but not
7788 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7789 * The level is known here, so pass it down
7790 * appropriately.
7792 bool should_fail =
7793 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7795 status = smb_set_file_end_of_file_info(conn, req,
7796 pdata,
7797 total_data,
7798 fsp,
7799 smb_fname,
7800 should_fail);
7801 break;
7804 case SMB_FILE_DISPOSITION_INFORMATION:
7805 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7807 #if 0
7808 /* JRA - We used to just ignore this on a path ?
7809 * Shouldn't this be invalid level on a pathname
7810 * based call ?
7812 if (tran_call != TRANSACT2_SETFILEINFO) {
7813 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7815 #endif
7816 status = smb_set_file_disposition_info(conn,
7817 pdata,
7818 total_data,
7819 fsp,
7820 smb_fname);
7821 break;
7824 case SMB_FILE_POSITION_INFORMATION:
7826 status = smb_file_position_information(conn,
7827 pdata,
7828 total_data,
7829 fsp);
7830 break;
7833 case SMB_FILE_FULL_EA_INFORMATION:
7835 status = smb_set_file_full_ea_info(conn,
7836 pdata,
7837 total_data,
7838 fsp);
7839 break;
7842 /* From tridge Samba4 :
7843 * MODE_INFORMATION in setfileinfo (I have no
7844 * idea what "mode information" on a file is - it takes a value of 0,
7845 * 2, 4 or 6. What could it be?).
7848 case SMB_FILE_MODE_INFORMATION:
7850 status = smb_file_mode_information(conn,
7851 pdata,
7852 total_data);
7853 break;
7857 * CIFS UNIX extensions.
7860 case SMB_SET_FILE_UNIX_BASIC:
7862 status = smb_set_file_unix_basic(conn, req,
7863 pdata,
7864 total_data,
7865 fsp,
7866 smb_fname);
7867 break;
7870 case SMB_SET_FILE_UNIX_INFO2:
7872 status = smb_set_file_unix_info2(conn, req,
7873 pdata,
7874 total_data,
7875 fsp,
7876 smb_fname);
7877 break;
7880 case SMB_SET_FILE_UNIX_LINK:
7882 if (fsp) {
7883 /* We must have a pathname for this. */
7884 return NT_STATUS_INVALID_LEVEL;
7886 status = smb_set_file_unix_link(conn, req, pdata,
7887 total_data, smb_fname);
7888 break;
7891 case SMB_SET_FILE_UNIX_HLINK:
7893 if (fsp) {
7894 /* We must have a pathname for this. */
7895 return NT_STATUS_INVALID_LEVEL;
7897 status = smb_set_file_unix_hlink(conn, req,
7898 pdata, total_data,
7899 smb_fname);
7900 break;
7903 case SMB_FILE_RENAME_INFORMATION:
7905 status = smb_file_rename_information(conn, req,
7906 pdata, total_data,
7907 fsp, smb_fname);
7908 break;
7911 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7913 /* SMB2 rename information. */
7914 status = smb2_file_rename_information(conn, req,
7915 pdata, total_data,
7916 fsp, smb_fname);
7917 break;
7920 case SMB_FILE_LINK_INFORMATION:
7922 status = smb_file_link_information(conn, req,
7923 pdata, total_data,
7924 fsp, smb_fname);
7925 break;
7928 #if defined(HAVE_POSIX_ACLS)
7929 case SMB_SET_POSIX_ACL:
7931 status = smb_set_posix_acl(conn,
7932 pdata,
7933 total_data,
7934 fsp,
7935 smb_fname);
7936 break;
7938 #endif
7940 case SMB_SET_POSIX_LOCK:
7942 if (!fsp) {
7943 return NT_STATUS_INVALID_LEVEL;
7945 status = smb_set_posix_lock(conn, req,
7946 pdata, total_data, fsp);
7947 break;
7950 case SMB_POSIX_PATH_OPEN:
7952 if (fsp) {
7953 /* We must have a pathname for this. */
7954 return NT_STATUS_INVALID_LEVEL;
7957 status = smb_posix_open(conn, req,
7958 ppdata,
7959 total_data,
7960 smb_fname,
7961 &data_return_size);
7962 break;
7965 case SMB_POSIX_PATH_UNLINK:
7967 if (fsp) {
7968 /* We must have a pathname for this. */
7969 return NT_STATUS_INVALID_LEVEL;
7972 status = smb_posix_unlink(conn, req,
7973 pdata,
7974 total_data,
7975 smb_fname);
7976 break;
7979 default:
7980 return NT_STATUS_INVALID_LEVEL;
7983 if (!NT_STATUS_IS_OK(status)) {
7984 return status;
7987 *ret_data_size = data_return_size;
7988 return NT_STATUS_OK;
7991 /****************************************************************************
7992 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7993 ****************************************************************************/
7995 static void call_trans2setfilepathinfo(connection_struct *conn,
7996 struct smb_request *req,
7997 unsigned int tran_call,
7998 char **pparams, int total_params,
7999 char **ppdata, int total_data,
8000 unsigned int max_data_bytes)
8002 char *params = *pparams;
8003 char *pdata = *ppdata;
8004 uint16 info_level;
8005 struct smb_filename *smb_fname = NULL;
8006 files_struct *fsp = NULL;
8007 NTSTATUS status = NT_STATUS_OK;
8008 int data_return_size = 0;
8010 if (!params) {
8011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8012 return;
8015 if (tran_call == TRANSACT2_SETFILEINFO) {
8016 if (total_params < 4) {
8017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8018 return;
8021 fsp = file_fsp(req, SVAL(params,0));
8022 /* Basic check for non-null fsp. */
8023 if (!check_fsp_open(conn, req, fsp)) {
8024 return;
8026 info_level = SVAL(params,2);
8028 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8029 &smb_fname);
8030 if (!NT_STATUS_IS_OK(status)) {
8031 reply_nterror(req, status);
8032 return;
8035 if(fsp->fh->fd == -1) {
8037 * This is actually a SETFILEINFO on a directory
8038 * handle (returned from an NT SMB). NT5.0 seems
8039 * to do this call. JRA.
8041 if (INFO_LEVEL_IS_UNIX(info_level)) {
8042 /* Always do lstat for UNIX calls. */
8043 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8044 DEBUG(3,("call_trans2setfilepathinfo: "
8045 "SMB_VFS_LSTAT of %s failed "
8046 "(%s)\n",
8047 smb_fname_str_dbg(smb_fname),
8048 strerror(errno)));
8049 reply_nterror(req, map_nt_error_from_unix(errno));
8050 return;
8052 } else {
8053 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8054 DEBUG(3,("call_trans2setfilepathinfo: "
8055 "fileinfo of %s failed (%s)\n",
8056 smb_fname_str_dbg(smb_fname),
8057 strerror(errno)));
8058 reply_nterror(req, map_nt_error_from_unix(errno));
8059 return;
8062 } else if (fsp->print_file) {
8064 * Doing a DELETE_ON_CLOSE should cancel a print job.
8066 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8067 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8069 DEBUG(3,("call_trans2setfilepathinfo: "
8070 "Cancelling print job (%s)\n",
8071 fsp_str_dbg(fsp)));
8073 SSVAL(params,0,0);
8074 send_trans2_replies(conn, req, params, 2,
8075 *ppdata, 0,
8076 max_data_bytes);
8077 return;
8078 } else {
8079 reply_nterror(req,
8080 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8081 return;
8083 } else {
8085 * Original code - this is an open file.
8087 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8088 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8089 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8090 strerror(errno)));
8091 reply_nterror(req, map_nt_error_from_unix(errno));
8092 return;
8095 } else {
8096 char *fname = NULL;
8097 uint32_t ucf_flags = 0;
8099 /* set path info */
8100 if (total_params < 7) {
8101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8102 return;
8105 info_level = SVAL(params,0);
8106 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8107 total_params - 6, STR_TERMINATE,
8108 &status);
8109 if (!NT_STATUS_IS_OK(status)) {
8110 reply_nterror(req, status);
8111 return;
8114 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8115 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8116 info_level == SMB_FILE_RENAME_INFORMATION ||
8117 info_level == SMB_POSIX_PATH_UNLINK) {
8118 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8121 status = filename_convert(req, conn,
8122 req->flags2 & FLAGS2_DFS_PATHNAMES,
8123 fname,
8124 ucf_flags,
8125 NULL,
8126 &smb_fname);
8127 if (!NT_STATUS_IS_OK(status)) {
8128 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8129 reply_botherror(req,
8130 NT_STATUS_PATH_NOT_COVERED,
8131 ERRSRV, ERRbadpath);
8132 return;
8134 reply_nterror(req, status);
8135 return;
8138 if (INFO_LEVEL_IS_UNIX(info_level)) {
8140 * For CIFS UNIX extensions the target name may not exist.
8143 /* Always do lstat for UNIX calls. */
8144 SMB_VFS_LSTAT(conn, smb_fname);
8146 } else if (!VALID_STAT(smb_fname->st) &&
8147 SMB_VFS_STAT(conn, smb_fname)) {
8148 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8149 "%s failed (%s)\n",
8150 smb_fname_str_dbg(smb_fname),
8151 strerror(errno)));
8152 reply_nterror(req, map_nt_error_from_unix(errno));
8153 return;
8157 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8158 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8159 fsp_fnum_dbg(fsp),
8160 info_level,total_data));
8162 /* Realloc the parameter size */
8163 *pparams = (char *)SMB_REALLOC(*pparams,2);
8164 if (*pparams == NULL) {
8165 reply_nterror(req, NT_STATUS_NO_MEMORY);
8166 return;
8168 params = *pparams;
8170 SSVAL(params,0,0);
8172 status = smbd_do_setfilepathinfo(conn, req, req,
8173 info_level,
8174 fsp,
8175 smb_fname,
8176 ppdata, total_data,
8177 &data_return_size);
8178 if (!NT_STATUS_IS_OK(status)) {
8179 if (open_was_deferred(req->sconn, req->mid)) {
8180 /* We have re-scheduled this call. */
8181 return;
8183 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8184 /* We have re-scheduled this call. */
8185 return;
8187 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8188 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8189 ERRSRV, ERRbadpath);
8190 return;
8192 if (info_level == SMB_POSIX_PATH_OPEN) {
8193 reply_openerror(req, status);
8194 return;
8197 reply_nterror(req, status);
8198 return;
8201 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8202 max_data_bytes);
8204 return;
8207 /****************************************************************************
8208 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8209 ****************************************************************************/
8211 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8212 char **pparams, int total_params,
8213 char **ppdata, int total_data,
8214 unsigned int max_data_bytes)
8216 struct smb_filename *smb_dname = NULL;
8217 char *params = *pparams;
8218 char *pdata = *ppdata;
8219 char *directory = NULL;
8220 NTSTATUS status = NT_STATUS_OK;
8221 struct ea_list *ea_list = NULL;
8222 TALLOC_CTX *ctx = talloc_tos();
8224 if (!CAN_WRITE(conn)) {
8225 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8226 return;
8229 if (total_params < 5) {
8230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8231 return;
8234 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8235 total_params - 4, STR_TERMINATE,
8236 &status);
8237 if (!NT_STATUS_IS_OK(status)) {
8238 reply_nterror(req, status);
8239 return;
8242 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8244 status = filename_convert(ctx,
8245 conn,
8246 req->flags2 & FLAGS2_DFS_PATHNAMES,
8247 directory,
8249 NULL,
8250 &smb_dname);
8252 if (!NT_STATUS_IS_OK(status)) {
8253 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8254 reply_botherror(req,
8255 NT_STATUS_PATH_NOT_COVERED,
8256 ERRSRV, ERRbadpath);
8257 return;
8259 reply_nterror(req, status);
8260 return;
8264 * OS/2 workplace shell seems to send SET_EA requests of "null"
8265 * length (4 bytes containing IVAL 4).
8266 * They seem to have no effect. Bug #3212. JRA.
8269 if (total_data && (total_data != 4)) {
8270 /* Any data in this call is an EA list. */
8271 if (total_data < 10) {
8272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8273 goto out;
8276 if (IVAL(pdata,0) > total_data) {
8277 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8278 IVAL(pdata,0), (unsigned int)total_data));
8279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 goto out;
8283 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8284 total_data - 4);
8285 if (!ea_list) {
8286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8287 goto out;
8290 if (!lp_ea_support(SNUM(conn))) {
8291 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8292 goto out;
8295 /* If total_data == 4 Windows doesn't care what values
8296 * are placed in that field, it just ignores them.
8297 * The System i QNTC IBM SMB client puts bad values here,
8298 * so ignore them. */
8300 status = create_directory(conn, req, smb_dname);
8302 if (!NT_STATUS_IS_OK(status)) {
8303 reply_nterror(req, status);
8304 goto out;
8307 /* Try and set any given EA. */
8308 if (ea_list) {
8309 status = set_ea(conn, NULL, smb_dname, ea_list);
8310 if (!NT_STATUS_IS_OK(status)) {
8311 reply_nterror(req, status);
8312 goto out;
8316 /* Realloc the parameter and data sizes */
8317 *pparams = (char *)SMB_REALLOC(*pparams,2);
8318 if(*pparams == NULL) {
8319 reply_nterror(req, NT_STATUS_NO_MEMORY);
8320 goto out;
8322 params = *pparams;
8324 SSVAL(params,0,0);
8326 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8328 out:
8329 TALLOC_FREE(smb_dname);
8330 return;
8333 /****************************************************************************
8334 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8335 We don't actually do this - we just send a null response.
8336 ****************************************************************************/
8338 static void call_trans2findnotifyfirst(connection_struct *conn,
8339 struct smb_request *req,
8340 char **pparams, int total_params,
8341 char **ppdata, int total_data,
8342 unsigned int max_data_bytes)
8344 char *params = *pparams;
8345 uint16 info_level;
8347 if (total_params < 6) {
8348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8349 return;
8352 info_level = SVAL(params,4);
8353 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8355 switch (info_level) {
8356 case 1:
8357 case 2:
8358 break;
8359 default:
8360 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8361 return;
8364 /* Realloc the parameter and data sizes */
8365 *pparams = (char *)SMB_REALLOC(*pparams,6);
8366 if (*pparams == NULL) {
8367 reply_nterror(req, NT_STATUS_NO_MEMORY);
8368 return;
8370 params = *pparams;
8372 SSVAL(params,0,fnf_handle);
8373 SSVAL(params,2,0); /* No changes */
8374 SSVAL(params,4,0); /* No EA errors */
8376 fnf_handle++;
8378 if(fnf_handle == 0)
8379 fnf_handle = 257;
8381 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8383 return;
8386 /****************************************************************************
8387 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8388 changes). Currently this does nothing.
8389 ****************************************************************************/
8391 static void call_trans2findnotifynext(connection_struct *conn,
8392 struct smb_request *req,
8393 char **pparams, int total_params,
8394 char **ppdata, int total_data,
8395 unsigned int max_data_bytes)
8397 char *params = *pparams;
8399 DEBUG(3,("call_trans2findnotifynext\n"));
8401 /* Realloc the parameter and data sizes */
8402 *pparams = (char *)SMB_REALLOC(*pparams,4);
8403 if (*pparams == NULL) {
8404 reply_nterror(req, NT_STATUS_NO_MEMORY);
8405 return;
8407 params = *pparams;
8409 SSVAL(params,0,0); /* No changes */
8410 SSVAL(params,2,0); /* No EA errors */
8412 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8414 return;
8417 /****************************************************************************
8418 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8419 ****************************************************************************/
8421 static void call_trans2getdfsreferral(connection_struct *conn,
8422 struct smb_request *req,
8423 char **pparams, int total_params,
8424 char **ppdata, int total_data,
8425 unsigned int max_data_bytes)
8427 char *params = *pparams;
8428 char *pathname = NULL;
8429 int reply_size = 0;
8430 int max_referral_level;
8431 NTSTATUS status = NT_STATUS_OK;
8432 TALLOC_CTX *ctx = talloc_tos();
8434 DEBUG(10,("call_trans2getdfsreferral\n"));
8436 if (total_params < 3) {
8437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8438 return;
8441 max_referral_level = SVAL(params,0);
8443 if(!lp_host_msdfs()) {
8444 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8445 return;
8448 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8449 total_params - 2, STR_TERMINATE);
8450 if (!pathname) {
8451 reply_nterror(req, NT_STATUS_NOT_FOUND);
8452 return;
8454 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8455 ppdata,&status)) < 0) {
8456 reply_nterror(req, status);
8457 return;
8460 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8461 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8462 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8464 return;
8467 #define LMCAT_SPL 0x53
8468 #define LMFUNC_GETJOBID 0x60
8470 /****************************************************************************
8471 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8472 ****************************************************************************/
8474 static void call_trans2ioctl(connection_struct *conn,
8475 struct smb_request *req,
8476 char **pparams, int total_params,
8477 char **ppdata, int total_data,
8478 unsigned int max_data_bytes)
8480 char *pdata = *ppdata;
8481 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8483 /* check for an invalid fid before proceeding */
8485 if (!fsp) {
8486 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8487 return;
8490 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8491 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8492 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8493 if (*ppdata == NULL) {
8494 reply_nterror(req, NT_STATUS_NO_MEMORY);
8495 return;
8497 pdata = *ppdata;
8499 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8500 CAN ACCEPT THIS IN UNICODE. JRA. */
8502 /* Job number */
8503 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8505 srvstr_push(pdata, req->flags2, pdata + 2,
8506 lp_netbios_name(), 15,
8507 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8508 srvstr_push(pdata, req->flags2, pdata+18,
8509 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8510 STR_ASCII|STR_TERMINATE); /* Service name */
8511 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8512 max_data_bytes);
8513 return;
8516 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8517 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8520 /****************************************************************************
8521 Reply to a SMBfindclose (stop trans2 directory search).
8522 ****************************************************************************/
8524 void reply_findclose(struct smb_request *req)
8526 int dptr_num;
8527 struct smbd_server_connection *sconn = req->sconn;
8529 START_PROFILE(SMBfindclose);
8531 if (req->wct < 1) {
8532 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8533 END_PROFILE(SMBfindclose);
8534 return;
8537 dptr_num = SVALS(req->vwv+0, 0);
8539 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8541 dptr_close(sconn, &dptr_num);
8543 reply_outbuf(req, 0, 0);
8545 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8547 END_PROFILE(SMBfindclose);
8548 return;
8551 /****************************************************************************
8552 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8553 ****************************************************************************/
8555 void reply_findnclose(struct smb_request *req)
8557 int dptr_num;
8559 START_PROFILE(SMBfindnclose);
8561 if (req->wct < 1) {
8562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8563 END_PROFILE(SMBfindnclose);
8564 return;
8567 dptr_num = SVAL(req->vwv+0, 0);
8569 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8571 /* We never give out valid handles for a
8572 findnotifyfirst - so any dptr_num is ok here.
8573 Just ignore it. */
8575 reply_outbuf(req, 0, 0);
8577 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8579 END_PROFILE(SMBfindnclose);
8580 return;
8583 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8584 struct trans_state *state)
8586 if (get_Protocol() >= PROTOCOL_NT1) {
8587 req->flags2 |= 0x40; /* IS_LONG_NAME */
8588 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8591 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8592 if (state->call != TRANSACT2_QFSINFO &&
8593 state->call != TRANSACT2_SETFSINFO) {
8594 DEBUG(0,("handle_trans2: encryption required "
8595 "with call 0x%x\n",
8596 (unsigned int)state->call));
8597 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8598 return;
8602 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8604 /* Now we must call the relevant TRANS2 function */
8605 switch(state->call) {
8606 case TRANSACT2_OPEN:
8608 START_PROFILE(Trans2_open);
8609 call_trans2open(conn, req,
8610 &state->param, state->total_param,
8611 &state->data, state->total_data,
8612 state->max_data_return);
8613 END_PROFILE(Trans2_open);
8614 break;
8617 case TRANSACT2_FINDFIRST:
8619 START_PROFILE(Trans2_findfirst);
8620 call_trans2findfirst(conn, req,
8621 &state->param, state->total_param,
8622 &state->data, state->total_data,
8623 state->max_data_return);
8624 END_PROFILE(Trans2_findfirst);
8625 break;
8628 case TRANSACT2_FINDNEXT:
8630 START_PROFILE(Trans2_findnext);
8631 call_trans2findnext(conn, req,
8632 &state->param, state->total_param,
8633 &state->data, state->total_data,
8634 state->max_data_return);
8635 END_PROFILE(Trans2_findnext);
8636 break;
8639 case TRANSACT2_QFSINFO:
8641 START_PROFILE(Trans2_qfsinfo);
8642 call_trans2qfsinfo(conn, req,
8643 &state->param, state->total_param,
8644 &state->data, state->total_data,
8645 state->max_data_return);
8646 END_PROFILE(Trans2_qfsinfo);
8647 break;
8650 case TRANSACT2_SETFSINFO:
8652 START_PROFILE(Trans2_setfsinfo);
8653 call_trans2setfsinfo(conn, req,
8654 &state->param, state->total_param,
8655 &state->data, state->total_data,
8656 state->max_data_return);
8657 END_PROFILE(Trans2_setfsinfo);
8658 break;
8661 case TRANSACT2_QPATHINFO:
8662 case TRANSACT2_QFILEINFO:
8664 START_PROFILE(Trans2_qpathinfo);
8665 call_trans2qfilepathinfo(conn, req, state->call,
8666 &state->param, state->total_param,
8667 &state->data, state->total_data,
8668 state->max_data_return);
8669 END_PROFILE(Trans2_qpathinfo);
8670 break;
8673 case TRANSACT2_SETPATHINFO:
8674 case TRANSACT2_SETFILEINFO:
8676 START_PROFILE(Trans2_setpathinfo);
8677 call_trans2setfilepathinfo(conn, req, state->call,
8678 &state->param, state->total_param,
8679 &state->data, state->total_data,
8680 state->max_data_return);
8681 END_PROFILE(Trans2_setpathinfo);
8682 break;
8685 case TRANSACT2_FINDNOTIFYFIRST:
8687 START_PROFILE(Trans2_findnotifyfirst);
8688 call_trans2findnotifyfirst(conn, req,
8689 &state->param, state->total_param,
8690 &state->data, state->total_data,
8691 state->max_data_return);
8692 END_PROFILE(Trans2_findnotifyfirst);
8693 break;
8696 case TRANSACT2_FINDNOTIFYNEXT:
8698 START_PROFILE(Trans2_findnotifynext);
8699 call_trans2findnotifynext(conn, req,
8700 &state->param, state->total_param,
8701 &state->data, state->total_data,
8702 state->max_data_return);
8703 END_PROFILE(Trans2_findnotifynext);
8704 break;
8707 case TRANSACT2_MKDIR:
8709 START_PROFILE(Trans2_mkdir);
8710 call_trans2mkdir(conn, req,
8711 &state->param, state->total_param,
8712 &state->data, state->total_data,
8713 state->max_data_return);
8714 END_PROFILE(Trans2_mkdir);
8715 break;
8718 case TRANSACT2_GET_DFS_REFERRAL:
8720 START_PROFILE(Trans2_get_dfs_referral);
8721 call_trans2getdfsreferral(conn, req,
8722 &state->param, state->total_param,
8723 &state->data, state->total_data,
8724 state->max_data_return);
8725 END_PROFILE(Trans2_get_dfs_referral);
8726 break;
8729 case TRANSACT2_IOCTL:
8731 START_PROFILE(Trans2_ioctl);
8732 call_trans2ioctl(conn, req,
8733 &state->param, state->total_param,
8734 &state->data, state->total_data,
8735 state->max_data_return);
8736 END_PROFILE(Trans2_ioctl);
8737 break;
8740 default:
8741 /* Error in request */
8742 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8743 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8747 /****************************************************************************
8748 Reply to a SMBtrans2.
8749 ****************************************************************************/
8751 void reply_trans2(struct smb_request *req)
8753 connection_struct *conn = req->conn;
8754 unsigned int dsoff;
8755 unsigned int dscnt;
8756 unsigned int psoff;
8757 unsigned int pscnt;
8758 unsigned int tran_call;
8759 struct trans_state *state;
8760 NTSTATUS result;
8762 START_PROFILE(SMBtrans2);
8764 if (req->wct < 14) {
8765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8766 END_PROFILE(SMBtrans2);
8767 return;
8770 dsoff = SVAL(req->vwv+12, 0);
8771 dscnt = SVAL(req->vwv+11, 0);
8772 psoff = SVAL(req->vwv+10, 0);
8773 pscnt = SVAL(req->vwv+9, 0);
8774 tran_call = SVAL(req->vwv+14, 0);
8776 result = allow_new_trans(conn->pending_trans, req->mid);
8777 if (!NT_STATUS_IS_OK(result)) {
8778 DEBUG(2, ("Got invalid trans2 request: %s\n",
8779 nt_errstr(result)));
8780 reply_nterror(req, result);
8781 END_PROFILE(SMBtrans2);
8782 return;
8785 if (IS_IPC(conn)) {
8786 switch (tran_call) {
8787 /* List the allowed trans2 calls on IPC$ */
8788 case TRANSACT2_OPEN:
8789 case TRANSACT2_GET_DFS_REFERRAL:
8790 case TRANSACT2_QFILEINFO:
8791 case TRANSACT2_QFSINFO:
8792 case TRANSACT2_SETFSINFO:
8793 break;
8794 default:
8795 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8796 END_PROFILE(SMBtrans2);
8797 return;
8801 if ((state = talloc(conn, struct trans_state)) == NULL) {
8802 DEBUG(0, ("talloc failed\n"));
8803 reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 END_PROFILE(SMBtrans2);
8805 return;
8808 state->cmd = SMBtrans2;
8810 state->mid = req->mid;
8811 state->vuid = req->vuid;
8812 state->setup_count = SVAL(req->vwv+13, 0);
8813 state->setup = NULL;
8814 state->total_param = SVAL(req->vwv+0, 0);
8815 state->param = NULL;
8816 state->total_data = SVAL(req->vwv+1, 0);
8817 state->data = NULL;
8818 state->max_param_return = SVAL(req->vwv+2, 0);
8819 state->max_data_return = SVAL(req->vwv+3, 0);
8820 state->max_setup_return = SVAL(req->vwv+4, 0);
8821 state->close_on_completion = BITSETW(req->vwv+5, 0);
8822 state->one_way = BITSETW(req->vwv+5, 1);
8824 state->call = tran_call;
8826 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8827 is so as a sanity check */
8828 if (state->setup_count != 1) {
8830 * Need to have rc=0 for ioctl to get job id for OS/2.
8831 * Network printing will fail if function is not successful.
8832 * Similar function in reply.c will be used if protocol
8833 * is LANMAN1.0 instead of LM1.2X002.
8834 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8835 * outbuf doesn't have to be set(only job id is used).
8837 if ( (state->setup_count == 4)
8838 && (tran_call == TRANSACT2_IOCTL)
8839 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8840 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8841 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8842 } else {
8843 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8844 DEBUG(2,("Transaction is %d\n",tran_call));
8845 TALLOC_FREE(state);
8846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8847 END_PROFILE(SMBtrans2);
8848 return;
8852 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8853 goto bad_param;
8855 if (state->total_data) {
8857 if (trans_oob(state->total_data, 0, dscnt)
8858 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8859 goto bad_param;
8862 /* Can't use talloc here, the core routines do realloc on the
8863 * params and data. */
8864 state->data = (char *)SMB_MALLOC(state->total_data);
8865 if (state->data == NULL) {
8866 DEBUG(0,("reply_trans2: data malloc fail for %u "
8867 "bytes !\n", (unsigned int)state->total_data));
8868 TALLOC_FREE(state);
8869 reply_nterror(req, NT_STATUS_NO_MEMORY);
8870 END_PROFILE(SMBtrans2);
8871 return;
8874 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8877 if (state->total_param) {
8879 if (trans_oob(state->total_param, 0, pscnt)
8880 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8881 goto bad_param;
8884 /* Can't use talloc here, the core routines do realloc on the
8885 * params and data. */
8886 state->param = (char *)SMB_MALLOC(state->total_param);
8887 if (state->param == NULL) {
8888 DEBUG(0,("reply_trans: param malloc fail for %u "
8889 "bytes !\n", (unsigned int)state->total_param));
8890 SAFE_FREE(state->data);
8891 TALLOC_FREE(state);
8892 reply_nterror(req, NT_STATUS_NO_MEMORY);
8893 END_PROFILE(SMBtrans2);
8894 return;
8897 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8900 state->received_data = dscnt;
8901 state->received_param = pscnt;
8903 if ((state->received_param == state->total_param) &&
8904 (state->received_data == state->total_data)) {
8906 handle_trans2(conn, req, state);
8908 SAFE_FREE(state->data);
8909 SAFE_FREE(state->param);
8910 TALLOC_FREE(state);
8911 END_PROFILE(SMBtrans2);
8912 return;
8915 DLIST_ADD(conn->pending_trans, state);
8917 /* We need to send an interim response then receive the rest
8918 of the parameter/data bytes */
8919 reply_outbuf(req, 0, 0);
8920 show_msg((char *)req->outbuf);
8921 END_PROFILE(SMBtrans2);
8922 return;
8924 bad_param:
8926 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8927 SAFE_FREE(state->data);
8928 SAFE_FREE(state->param);
8929 TALLOC_FREE(state);
8930 END_PROFILE(SMBtrans2);
8931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8935 /****************************************************************************
8936 Reply to a SMBtranss2
8937 ****************************************************************************/
8939 void reply_transs2(struct smb_request *req)
8941 connection_struct *conn = req->conn;
8942 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8943 struct trans_state *state;
8945 START_PROFILE(SMBtranss2);
8947 show_msg((const char *)req->inbuf);
8949 /* Windows clients expect all replies to
8950 a transact secondary (SMBtranss2 0x33)
8951 to have a command code of transact
8952 (SMBtrans2 0x32). See bug #8989
8953 and also [MS-CIFS] section 2.2.4.47.2
8954 for details.
8956 req->cmd = SMBtrans2;
8958 if (req->wct < 8) {
8959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8960 END_PROFILE(SMBtranss2);
8961 return;
8964 for (state = conn->pending_trans; state != NULL;
8965 state = state->next) {
8966 if (state->mid == req->mid) {
8967 break;
8971 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8973 END_PROFILE(SMBtranss2);
8974 return;
8977 /* Revise state->total_param and state->total_data in case they have
8978 changed downwards */
8980 if (SVAL(req->vwv+0, 0) < state->total_param)
8981 state->total_param = SVAL(req->vwv+0, 0);
8982 if (SVAL(req->vwv+1, 0) < state->total_data)
8983 state->total_data = SVAL(req->vwv+1, 0);
8985 pcnt = SVAL(req->vwv+2, 0);
8986 poff = SVAL(req->vwv+3, 0);
8987 pdisp = SVAL(req->vwv+4, 0);
8989 dcnt = SVAL(req->vwv+5, 0);
8990 doff = SVAL(req->vwv+6, 0);
8991 ddisp = SVAL(req->vwv+7, 0);
8993 state->received_param += pcnt;
8994 state->received_data += dcnt;
8996 if ((state->received_data > state->total_data) ||
8997 (state->received_param > state->total_param))
8998 goto bad_param;
9000 if (pcnt) {
9001 if (trans_oob(state->total_param, pdisp, pcnt)
9002 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9003 goto bad_param;
9005 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9008 if (dcnt) {
9009 if (trans_oob(state->total_data, ddisp, dcnt)
9010 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9011 goto bad_param;
9013 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9016 if ((state->received_param < state->total_param) ||
9017 (state->received_data < state->total_data)) {
9018 END_PROFILE(SMBtranss2);
9019 return;
9022 handle_trans2(conn, req, state);
9024 DLIST_REMOVE(conn->pending_trans, state);
9025 SAFE_FREE(state->data);
9026 SAFE_FREE(state->param);
9027 TALLOC_FREE(state);
9029 END_PROFILE(SMBtranss2);
9030 return;
9032 bad_param:
9034 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9035 DLIST_REMOVE(conn->pending_trans, state);
9036 SAFE_FREE(state->data);
9037 SAFE_FREE(state->param);
9038 TALLOC_FREE(state);
9039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9040 END_PROFILE(SMBtranss2);
9041 return;