Fix service control for non-internal services.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobd108ee6243fd225d7dc8e08e5fd998f51f07c953
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 /* Apply mode mask */
1369 ret &= lp_create_mask(SNUM(conn));
1370 /* Add in force bits */
1371 ret |= lp_force_create_mode(SNUM(conn));
1372 break;
1373 case PERM_NEW_DIR:
1374 ret &= lp_dir_mask(SNUM(conn));
1375 /* Add in force bits */
1376 ret |= lp_force_dir_mode(SNUM(conn));
1377 break;
1378 case PERM_EXISTING_FILE:
1379 /* Apply mode mask */
1380 ret &= lp_security_mask(SNUM(conn));
1381 /* Add in force bits */
1382 ret |= lp_force_security_mode(SNUM(conn));
1383 break;
1384 case PERM_EXISTING_DIR:
1385 /* Apply mode mask */
1386 ret &= lp_dir_security_mask(SNUM(conn));
1387 /* Add in force bits */
1388 ret |= lp_force_dir_security_mode(SNUM(conn));
1389 break;
1392 *ret_perms = ret;
1393 return NT_STATUS_OK;
1396 /****************************************************************************
1397 Needed to show the msdfs symlinks as directories. Modifies psbuf
1398 to be a directory if it's a msdfs link.
1399 ****************************************************************************/
1401 static bool check_msdfs_link(connection_struct *conn,
1402 const char *pathname,
1403 SMB_STRUCT_STAT *psbuf)
1405 int saved_errno = errno;
1406 if(lp_host_msdfs() &&
1407 lp_msdfs_root(SNUM(conn)) &&
1408 is_msdfs_link(conn, pathname, psbuf)) {
1410 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1411 "as a directory\n",
1412 pathname));
1413 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1414 errno = saved_errno;
1415 return true;
1417 errno = saved_errno;
1418 return false;
1422 /****************************************************************************
1423 Get a level dependent lanman2 dir entry.
1424 ****************************************************************************/
1426 struct smbd_dirptr_lanman2_state {
1427 connection_struct *conn;
1428 uint32_t info_level;
1429 bool check_mangled_names;
1430 bool has_wild;
1431 bool got_exact_match;
1434 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1435 void *private_data,
1436 const char *dname,
1437 const char *mask,
1438 char **_fname)
1440 struct smbd_dirptr_lanman2_state *state =
1441 (struct smbd_dirptr_lanman2_state *)private_data;
1442 bool ok;
1443 char mangled_name[13]; /* mangled 8.3 name. */
1444 bool got_match;
1445 const char *fname;
1447 /* Mangle fname if it's an illegal name. */
1448 if (mangle_must_mangle(dname, state->conn->params)) {
1449 ok = name_to_8_3(dname, mangled_name,
1450 true, state->conn->params);
1451 if (!ok) {
1452 return false;
1454 fname = mangled_name;
1455 } else {
1456 fname = dname;
1459 got_match = exact_match(state->has_wild,
1460 state->conn->case_sensitive,
1461 fname, mask);
1462 state->got_exact_match = got_match;
1463 if (!got_match) {
1464 got_match = mask_match(fname, mask,
1465 state->conn->case_sensitive);
1468 if(!got_match && state->check_mangled_names &&
1469 !mangle_is_8_3(fname, false, state->conn->params)) {
1471 * It turns out that NT matches wildcards against
1472 * both long *and* short names. This may explain some
1473 * of the wildcard wierdness from old DOS clients
1474 * that some people have been seeing.... JRA.
1476 /* Force the mangling into 8.3. */
1477 ok = name_to_8_3(fname, mangled_name,
1478 false, state->conn->params);
1479 if (!ok) {
1480 return false;
1483 got_match = exact_match(state->has_wild,
1484 state->conn->case_sensitive,
1485 mangled_name, mask);
1486 state->got_exact_match = got_match;
1487 if (!got_match) {
1488 got_match = mask_match(mangled_name, mask,
1489 state->conn->case_sensitive);
1493 if (!got_match) {
1494 return false;
1497 *_fname = talloc_strdup(ctx, fname);
1498 if (*_fname == NULL) {
1499 return false;
1502 return true;
1505 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1506 void *private_data,
1507 struct smb_filename *smb_fname,
1508 uint32_t *_mode)
1510 struct smbd_dirptr_lanman2_state *state =
1511 (struct smbd_dirptr_lanman2_state *)private_data;
1512 bool ms_dfs_link = false;
1513 uint32_t mode = 0;
1515 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1516 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1517 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1518 "Couldn't lstat [%s] (%s)\n",
1519 smb_fname_str_dbg(smb_fname),
1520 strerror(errno)));
1521 return false;
1523 } else if (!VALID_STAT(smb_fname->st) &&
1524 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1525 /* Needed to show the msdfs symlinks as
1526 * directories */
1528 ms_dfs_link = check_msdfs_link(state->conn,
1529 smb_fname->base_name,
1530 &smb_fname->st);
1531 if (!ms_dfs_link) {
1532 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1533 "Couldn't stat [%s] (%s)\n",
1534 smb_fname_str_dbg(smb_fname),
1535 strerror(errno)));
1536 return false;
1540 if (ms_dfs_link) {
1541 mode = dos_mode_msdfs(state->conn, smb_fname);
1542 } else {
1543 mode = dos_mode(state->conn, smb_fname);
1546 *_mode = mode;
1547 return true;
1550 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1551 connection_struct *conn,
1552 uint16_t flags2,
1553 uint32_t info_level,
1554 struct ea_list *name_list,
1555 bool check_mangled_names,
1556 bool requires_resume_key,
1557 uint32_t mode,
1558 const char *fname,
1559 const struct smb_filename *smb_fname,
1560 int space_remaining,
1561 uint8_t align,
1562 bool do_pad,
1563 char *base_data,
1564 char **ppdata,
1565 char *end_data,
1566 bool *out_of_space,
1567 uint64_t *last_entry_off)
1569 char *p, *q, *pdata = *ppdata;
1570 uint32_t reskey=0;
1571 uint64_t file_size = 0;
1572 uint64_t allocation_size = 0;
1573 uint64_t file_index = 0;
1574 uint32_t len;
1575 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1576 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1577 char *nameptr;
1578 char *last_entry_ptr;
1579 bool was_8_3;
1580 int off;
1581 int pad = 0;
1583 *out_of_space = false;
1585 ZERO_STRUCT(mdate_ts);
1586 ZERO_STRUCT(adate_ts);
1587 ZERO_STRUCT(create_date_ts);
1588 ZERO_STRUCT(cdate_ts);
1590 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1591 file_size = get_file_size_stat(&smb_fname->st);
1593 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1595 file_index = get_FileIndex(conn, &smb_fname->st);
1597 mdate_ts = smb_fname->st.st_ex_mtime;
1598 adate_ts = smb_fname->st.st_ex_atime;
1599 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1600 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1602 if (lp_dos_filetime_resolution(SNUM(conn))) {
1603 dos_filetime_timespec(&create_date_ts);
1604 dos_filetime_timespec(&mdate_ts);
1605 dos_filetime_timespec(&adate_ts);
1606 dos_filetime_timespec(&cdate_ts);
1609 create_date = convert_timespec_to_time_t(create_date_ts);
1610 mdate = convert_timespec_to_time_t(mdate_ts);
1611 adate = convert_timespec_to_time_t(adate_ts);
1613 /* align the record */
1614 SMB_ASSERT(align >= 1);
1616 off = (int)PTR_DIFF(pdata, base_data);
1617 pad = (off + (align-1)) & ~(align-1);
1618 pad -= off;
1620 if (pad && pad > space_remaining) {
1621 *out_of_space = true;
1622 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1623 "for padding (wanted %u, had %d)\n",
1624 (unsigned int)pad,
1625 space_remaining ));
1626 return false; /* Not finished - just out of space */
1629 off += pad;
1630 /* initialize padding to 0 */
1631 if (pad) {
1632 memset(pdata, 0, pad);
1634 space_remaining -= pad;
1636 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1637 space_remaining ));
1639 pdata += pad;
1640 p = pdata;
1641 last_entry_ptr = p;
1643 pad = 0;
1644 off = 0;
1646 switch (info_level) {
1647 case SMB_FIND_INFO_STANDARD:
1648 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1649 if(requires_resume_key) {
1650 SIVAL(p,0,reskey);
1651 p += 4;
1653 srv_put_dos_date2(p,0,create_date);
1654 srv_put_dos_date2(p,4,adate);
1655 srv_put_dos_date2(p,8,mdate);
1656 SIVAL(p,12,(uint32)file_size);
1657 SIVAL(p,16,(uint32)allocation_size);
1658 SSVAL(p,20,mode);
1659 p += 23;
1660 nameptr = p;
1661 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1662 p += ucs2_align(base_data, p, 0);
1664 len = srvstr_push(base_data, flags2, p,
1665 fname, PTR_DIFF(end_data, p),
1666 STR_TERMINATE);
1667 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1668 if (len > 2) {
1669 SCVAL(nameptr, -1, len - 2);
1670 } else {
1671 SCVAL(nameptr, -1, 0);
1673 } else {
1674 if (len > 1) {
1675 SCVAL(nameptr, -1, len - 1);
1676 } else {
1677 SCVAL(nameptr, -1, 0);
1680 p += len;
1681 break;
1683 case SMB_FIND_EA_SIZE:
1684 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1685 if (requires_resume_key) {
1686 SIVAL(p,0,reskey);
1687 p += 4;
1689 srv_put_dos_date2(p,0,create_date);
1690 srv_put_dos_date2(p,4,adate);
1691 srv_put_dos_date2(p,8,mdate);
1692 SIVAL(p,12,(uint32)file_size);
1693 SIVAL(p,16,(uint32)allocation_size);
1694 SSVAL(p,20,mode);
1696 unsigned int ea_size = estimate_ea_size(conn, NULL,
1697 smb_fname);
1698 SIVAL(p,22,ea_size); /* Extended attributes */
1700 p += 27;
1701 nameptr = p - 1;
1702 len = srvstr_push(base_data, flags2,
1703 p, fname, PTR_DIFF(end_data, p),
1704 STR_TERMINATE | STR_NOALIGN);
1705 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1706 if (len > 2) {
1707 len -= 2;
1708 } else {
1709 len = 0;
1711 } else {
1712 if (len > 1) {
1713 len -= 1;
1714 } else {
1715 len = 0;
1718 SCVAL(nameptr,0,len);
1719 p += len;
1720 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1721 break;
1723 case SMB_FIND_EA_LIST:
1725 struct ea_list *file_list = NULL;
1726 size_t ea_len = 0;
1727 NTSTATUS status;
1729 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1730 if (!name_list) {
1731 return false;
1733 if (requires_resume_key) {
1734 SIVAL(p,0,reskey);
1735 p += 4;
1737 srv_put_dos_date2(p,0,create_date);
1738 srv_put_dos_date2(p,4,adate);
1739 srv_put_dos_date2(p,8,mdate);
1740 SIVAL(p,12,(uint32)file_size);
1741 SIVAL(p,16,(uint32)allocation_size);
1742 SSVAL(p,20,mode);
1743 p += 22; /* p now points to the EA area. */
1745 status = get_ea_list_from_file(ctx, conn, NULL,
1746 smb_fname,
1747 &ea_len, &file_list);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 file_list = NULL;
1751 name_list = ea_list_union(name_list, file_list, &ea_len);
1753 /* We need to determine if this entry will fit in the space available. */
1754 /* Max string size is 255 bytes. */
1755 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1756 *out_of_space = true;
1757 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1758 "(wanted %u, had %d)\n",
1759 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1760 space_remaining ));
1761 return False; /* Not finished - just out of space */
1764 /* Push the ea_data followed by the name. */
1765 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1766 nameptr = p;
1767 len = srvstr_push(base_data, flags2,
1768 p + 1, fname, PTR_DIFF(end_data, p+1),
1769 STR_TERMINATE | STR_NOALIGN);
1770 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1771 if (len > 2) {
1772 len -= 2;
1773 } else {
1774 len = 0;
1776 } else {
1777 if (len > 1) {
1778 len -= 1;
1779 } else {
1780 len = 0;
1783 SCVAL(nameptr,0,len);
1784 p += len + 1;
1785 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1786 break;
1789 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1790 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1791 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1792 p += 4;
1793 SIVAL(p,0,reskey); p += 4;
1794 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1798 SOFF_T(p,0,file_size); p += 8;
1799 SOFF_T(p,0,allocation_size); p += 8;
1800 SIVAL(p,0,mode); p += 4;
1801 q = p; p += 4; /* q is placeholder for name length. */
1803 unsigned int ea_size = estimate_ea_size(conn, NULL,
1804 smb_fname);
1805 SIVAL(p,0,ea_size); /* Extended attributes */
1806 p += 4;
1808 /* Clear the short name buffer. This is
1809 * IMPORTANT as not doing so will trigger
1810 * a Win2k client bug. JRA.
1812 if (!was_8_3 && check_mangled_names) {
1813 char mangled_name[13]; /* mangled 8.3 name. */
1814 if (!name_to_8_3(fname,mangled_name,True,
1815 conn->params)) {
1816 /* Error - mangle failed ! */
1817 memset(mangled_name,'\0',12);
1819 mangled_name[12] = 0;
1820 len = srvstr_push(base_data, flags2,
1821 p+2, mangled_name, 24,
1822 STR_UPPER|STR_UNICODE);
1823 if (len < 24) {
1824 memset(p + 2 + len,'\0',24 - len);
1826 SSVAL(p, 0, len);
1827 } else {
1828 memset(p,'\0',26);
1830 p += 2 + 24;
1831 len = srvstr_push(base_data, flags2, p,
1832 fname, PTR_DIFF(end_data, p),
1833 STR_TERMINATE_ASCII);
1834 SIVAL(q,0,len);
1835 p += len;
1837 len = PTR_DIFF(p, pdata);
1838 pad = (len + (align-1)) & ~(align-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1844 SIVAL(pdata,0,pad);
1846 * set padding to zero
1848 if (do_pad) {
1849 memset(p, 0, pad - len);
1850 p = pdata + pad;
1851 } else {
1852 p = pdata + len;
1854 break;
1856 case SMB_FIND_FILE_DIRECTORY_INFO:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1858 p += 4;
1859 SIVAL(p,0,reskey); p += 4;
1860 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1863 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1864 SOFF_T(p,0,file_size); p += 8;
1865 SOFF_T(p,0,allocation_size); p += 8;
1866 SIVAL(p,0,mode); p += 4;
1867 len = srvstr_push(base_data, flags2,
1868 p + 4, fname, PTR_DIFF(end_data, p+4),
1869 STR_TERMINATE_ASCII);
1870 SIVAL(p,0,len);
1871 p += 4 + len;
1873 len = PTR_DIFF(p, pdata);
1874 pad = (len + (align-1)) & ~(align-1);
1876 * offset to the next entry, the caller
1877 * will overwrite it for the last entry
1878 * that's why we always include the padding
1880 SIVAL(pdata,0,pad);
1882 * set padding to zero
1884 if (do_pad) {
1885 memset(p, 0, pad - len);
1886 p = pdata + pad;
1887 } else {
1888 p = pdata + len;
1890 break;
1892 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1893 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1894 p += 4;
1895 SIVAL(p,0,reskey); p += 4;
1896 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1899 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1900 SOFF_T(p,0,file_size); p += 8;
1901 SOFF_T(p,0,allocation_size); p += 8;
1902 SIVAL(p,0,mode); p += 4;
1903 q = p; p += 4; /* q is placeholder for name length. */
1905 unsigned int ea_size = estimate_ea_size(conn, NULL,
1906 smb_fname);
1907 SIVAL(p,0,ea_size); /* Extended attributes */
1908 p +=4;
1910 len = srvstr_push(base_data, flags2, p,
1911 fname, PTR_DIFF(end_data, p),
1912 STR_TERMINATE_ASCII);
1913 SIVAL(q, 0, len);
1914 p += len;
1916 len = PTR_DIFF(p, pdata);
1917 pad = (len + (align-1)) & ~(align-1);
1919 * offset to the next entry, the caller
1920 * will overwrite it for the last entry
1921 * that's why we always include the padding
1923 SIVAL(pdata,0,pad);
1925 * set padding to zero
1927 if (do_pad) {
1928 memset(p, 0, pad - len);
1929 p = pdata + pad;
1930 } else {
1931 p = pdata + len;
1933 break;
1935 case SMB_FIND_FILE_NAMES_INFO:
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1937 p += 4;
1938 SIVAL(p,0,reskey); p += 4;
1939 p += 4;
1940 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1941 acl on a dir (tridge) */
1942 len = srvstr_push(base_data, flags2, p,
1943 fname, PTR_DIFF(end_data, p),
1944 STR_TERMINATE_ASCII);
1945 SIVAL(p, -4, len);
1946 p += len;
1948 len = PTR_DIFF(p, pdata);
1949 pad = (len + (align-1)) & ~(align-1);
1951 * offset to the next entry, the caller
1952 * will overwrite it for the last entry
1953 * that's why we always include the padding
1955 SIVAL(pdata,0,pad);
1957 * set padding to zero
1959 if (do_pad) {
1960 memset(p, 0, pad - len);
1961 p = pdata + pad;
1962 } else {
1963 p = pdata + len;
1965 break;
1967 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1968 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1969 p += 4;
1970 SIVAL(p,0,reskey); p += 4;
1971 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1972 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1973 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1974 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1975 SOFF_T(p,0,file_size); p += 8;
1976 SOFF_T(p,0,allocation_size); p += 8;
1977 SIVAL(p,0,mode); p += 4;
1978 q = p; p += 4; /* q is placeholder for name length. */
1980 unsigned int ea_size = estimate_ea_size(conn, NULL,
1981 smb_fname);
1982 SIVAL(p,0,ea_size); /* Extended attributes */
1983 p +=4;
1985 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1986 SBVAL(p,0,file_index); p += 8;
1987 len = srvstr_push(base_data, flags2, p,
1988 fname, PTR_DIFF(end_data, p),
1989 STR_TERMINATE_ASCII);
1990 SIVAL(q, 0, len);
1991 p += len;
1993 len = PTR_DIFF(p, pdata);
1994 pad = (len + (align-1)) & ~(align-1);
1996 * offset to the next entry, the caller
1997 * will overwrite it for the last entry
1998 * that's why we always include the padding
2000 SIVAL(pdata,0,pad);
2002 * set padding to zero
2004 if (do_pad) {
2005 memset(p, 0, pad - len);
2006 p = pdata + pad;
2007 } else {
2008 p = pdata + len;
2010 break;
2012 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2013 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2014 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2015 p += 4;
2016 SIVAL(p,0,reskey); p += 4;
2017 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2018 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2019 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2020 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2021 SOFF_T(p,0,file_size); p += 8;
2022 SOFF_T(p,0,allocation_size); p += 8;
2023 SIVAL(p,0,mode); p += 4;
2024 q = p; p += 4; /* q is placeholder for name length */
2026 unsigned int ea_size = estimate_ea_size(conn, NULL,
2027 smb_fname);
2028 SIVAL(p,0,ea_size); /* Extended attributes */
2029 p +=4;
2031 /* Clear the short name buffer. This is
2032 * IMPORTANT as not doing so will trigger
2033 * a Win2k client bug. JRA.
2035 if (!was_8_3 && check_mangled_names) {
2036 char mangled_name[13]; /* mangled 8.3 name. */
2037 if (!name_to_8_3(fname,mangled_name,True,
2038 conn->params)) {
2039 /* Error - mangle failed ! */
2040 memset(mangled_name,'\0',12);
2042 mangled_name[12] = 0;
2043 len = srvstr_push(base_data, flags2,
2044 p+2, mangled_name, 24,
2045 STR_UPPER|STR_UNICODE);
2046 SSVAL(p, 0, len);
2047 if (len < 24) {
2048 memset(p + 2 + len,'\0',24 - len);
2050 SSVAL(p, 0, len);
2051 } else {
2052 memset(p,'\0',26);
2054 p += 26;
2055 SSVAL(p,0,0); p += 2; /* Reserved ? */
2056 SBVAL(p,0,file_index); p += 8;
2057 len = srvstr_push(base_data, flags2, p,
2058 fname, PTR_DIFF(end_data, p),
2059 STR_TERMINATE_ASCII);
2060 SIVAL(q,0,len);
2061 p += len;
2063 len = PTR_DIFF(p, pdata);
2064 pad = (len + (align-1)) & ~(align-1);
2066 * offset to the next entry, the caller
2067 * will overwrite it for the last entry
2068 * that's why we always include the padding
2070 SIVAL(pdata,0,pad);
2072 * set padding to zero
2074 if (do_pad) {
2075 memset(p, 0, pad - len);
2076 p = pdata + pad;
2077 } else {
2078 p = pdata + len;
2080 break;
2082 /* CIFS UNIX Extension. */
2084 case SMB_FIND_FILE_UNIX:
2085 case SMB_FIND_FILE_UNIX_INFO2:
2086 p+= 4;
2087 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2089 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2091 if (info_level == SMB_FIND_FILE_UNIX) {
2092 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2093 p = store_file_unix_basic(conn, p,
2094 NULL, &smb_fname->st);
2095 len = srvstr_push(base_data, flags2, p,
2096 fname, PTR_DIFF(end_data, p),
2097 STR_TERMINATE);
2098 } else {
2099 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2100 p = store_file_unix_basic_info2(conn, p,
2101 NULL, &smb_fname->st);
2102 nameptr = p;
2103 p += 4;
2104 len = srvstr_push(base_data, flags2, p, fname,
2105 PTR_DIFF(end_data, p), 0);
2106 SIVAL(nameptr, 0, len);
2109 p += len;
2111 len = PTR_DIFF(p, pdata);
2112 pad = (len + (align-1)) & ~(align-1);
2114 * offset to the next entry, the caller
2115 * will overwrite it for the last entry
2116 * that's why we always include the padding
2118 SIVAL(pdata,0,pad);
2120 * set padding to zero
2122 if (do_pad) {
2123 memset(p, 0, pad - len);
2124 p = pdata + pad;
2125 } else {
2126 p = pdata + len;
2128 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2130 break;
2132 default:
2133 return false;
2136 if (PTR_DIFF(p,pdata) > space_remaining) {
2137 *out_of_space = true;
2138 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2139 "(wanted %u, had %d)\n",
2140 (unsigned int)PTR_DIFF(p,pdata),
2141 space_remaining ));
2142 return false; /* Not finished - just out of space */
2145 /* Setup the last entry pointer, as an offset from base_data */
2146 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2147 /* Advance the data pointer to the next slot */
2148 *ppdata = p;
2150 return true;
2153 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2154 connection_struct *conn,
2155 struct dptr_struct *dirptr,
2156 uint16 flags2,
2157 const char *path_mask,
2158 uint32 dirtype,
2159 int info_level,
2160 int requires_resume_key,
2161 bool dont_descend,
2162 bool ask_sharemode,
2163 uint8_t align,
2164 bool do_pad,
2165 char **ppdata,
2166 char *base_data,
2167 char *end_data,
2168 int space_remaining,
2169 bool *out_of_space,
2170 bool *got_exact_match,
2171 int *_last_entry_off,
2172 struct ea_list *name_list)
2174 const char *p;
2175 const char *mask = NULL;
2176 long prev_dirpos = 0;
2177 uint32_t mode = 0;
2178 char *fname = NULL;
2179 struct smb_filename *smb_fname = NULL;
2180 struct smbd_dirptr_lanman2_state state;
2181 bool ok;
2182 uint64_t last_entry_off = 0;
2184 ZERO_STRUCT(state);
2185 state.conn = conn;
2186 state.info_level = info_level;
2187 state.check_mangled_names = lp_manglednames(conn->params);
2188 state.has_wild = dptr_has_wild(dirptr);
2189 state.got_exact_match = false;
2191 *out_of_space = false;
2192 *got_exact_match = false;
2194 p = strrchr_m(path_mask,'/');
2195 if(p != NULL) {
2196 if(p[1] == '\0') {
2197 mask = "*.*";
2198 } else {
2199 mask = p+1;
2201 } else {
2202 mask = path_mask;
2205 ok = smbd_dirptr_get_entry(ctx,
2206 dirptr,
2207 mask,
2208 dirtype,
2209 dont_descend,
2210 ask_sharemode,
2211 smbd_dirptr_lanman2_match_fn,
2212 smbd_dirptr_lanman2_mode_fn,
2213 &state,
2214 &fname,
2215 &smb_fname,
2216 &mode,
2217 &prev_dirpos);
2218 if (!ok) {
2219 return false;
2222 *got_exact_match = state.got_exact_match;
2224 ok = smbd_marshall_dir_entry(ctx,
2225 conn,
2226 flags2,
2227 info_level,
2228 name_list,
2229 state.check_mangled_names,
2230 requires_resume_key,
2231 mode,
2232 fname,
2233 smb_fname,
2234 space_remaining,
2235 align,
2236 do_pad,
2237 base_data,
2238 ppdata,
2239 end_data,
2240 out_of_space,
2241 &last_entry_off);
2242 TALLOC_FREE(fname);
2243 TALLOC_FREE(smb_fname);
2244 if (*out_of_space) {
2245 dptr_SeekDir(dirptr, prev_dirpos);
2246 return false;
2248 if (!ok) {
2249 return false;
2252 *_last_entry_off = last_entry_off;
2253 return true;
2256 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2257 connection_struct *conn,
2258 struct dptr_struct *dirptr,
2259 uint16 flags2,
2260 const char *path_mask,
2261 uint32 dirtype,
2262 int info_level,
2263 bool requires_resume_key,
2264 bool dont_descend,
2265 bool ask_sharemode,
2266 char **ppdata,
2267 char *base_data,
2268 char *end_data,
2269 int space_remaining,
2270 bool *out_of_space,
2271 bool *got_exact_match,
2272 int *last_entry_off,
2273 struct ea_list *name_list)
2275 uint8_t align = 4;
2276 const bool do_pad = true;
2278 if (info_level >= 1 && info_level <= 3) {
2279 /* No alignment on earlier info levels. */
2280 align = 1;
2283 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2284 path_mask, dirtype, info_level,
2285 requires_resume_key, dont_descend, ask_sharemode,
2286 align, do_pad,
2287 ppdata, base_data, end_data,
2288 space_remaining,
2289 out_of_space, got_exact_match,
2290 last_entry_off, name_list);
2293 /****************************************************************************
2294 Reply to a TRANS2_FINDFIRST.
2295 ****************************************************************************/
2297 static void call_trans2findfirst(connection_struct *conn,
2298 struct smb_request *req,
2299 char **pparams, int total_params,
2300 char **ppdata, int total_data,
2301 unsigned int max_data_bytes)
2303 /* We must be careful here that we don't return more than the
2304 allowed number of data bytes. If this means returning fewer than
2305 maxentries then so be it. We assume that the redirector has
2306 enough room for the fixed number of parameter bytes it has
2307 requested. */
2308 struct smb_filename *smb_dname = NULL;
2309 char *params = *pparams;
2310 char *pdata = *ppdata;
2311 char *data_end;
2312 uint32 dirtype;
2313 int maxentries;
2314 uint16 findfirst_flags;
2315 bool close_after_first;
2316 bool close_if_end;
2317 bool requires_resume_key;
2318 int info_level;
2319 char *directory = NULL;
2320 char *mask = NULL;
2321 char *p;
2322 int last_entry_off=0;
2323 int dptr_num = -1;
2324 int numentries = 0;
2325 int i;
2326 bool finished = False;
2327 bool dont_descend = False;
2328 bool out_of_space = False;
2329 int space_remaining;
2330 bool mask_contains_wcard = False;
2331 struct ea_list *ea_list = NULL;
2332 NTSTATUS ntstatus = NT_STATUS_OK;
2333 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2334 TALLOC_CTX *ctx = talloc_tos();
2335 struct dptr_struct *dirptr = NULL;
2336 struct smbd_server_connection *sconn = req->sconn;
2337 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2338 bool backup_priv = false;
2340 if (total_params < 13) {
2341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2342 goto out;
2345 dirtype = SVAL(params,0);
2346 maxentries = SVAL(params,2);
2347 findfirst_flags = SVAL(params,4);
2348 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2349 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2350 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2351 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2352 security_token_has_privilege(get_current_nttok(conn),
2353 SEC_PRIV_BACKUP));
2355 info_level = SVAL(params,6);
2357 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2358 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2359 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2360 (int)backup_priv,
2361 info_level, max_data_bytes));
2363 if (!maxentries) {
2364 /* W2K3 seems to treat zero as 1. */
2365 maxentries = 1;
2368 switch (info_level) {
2369 case SMB_FIND_INFO_STANDARD:
2370 case SMB_FIND_EA_SIZE:
2371 case SMB_FIND_EA_LIST:
2372 case SMB_FIND_FILE_DIRECTORY_INFO:
2373 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2374 case SMB_FIND_FILE_NAMES_INFO:
2375 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2376 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2377 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2378 break;
2379 case SMB_FIND_FILE_UNIX:
2380 case SMB_FIND_FILE_UNIX_INFO2:
2381 /* Always use filesystem for UNIX mtime query. */
2382 ask_sharemode = false;
2383 if (!lp_unix_extensions()) {
2384 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2385 goto out;
2387 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2388 break;
2389 default:
2390 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2391 goto out;
2394 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2395 params+12, total_params - 12,
2396 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2397 if (!NT_STATUS_IS_OK(ntstatus)) {
2398 reply_nterror(req, ntstatus);
2399 goto out;
2402 if (backup_priv) {
2403 become_root();
2404 ntstatus = filename_convert_with_privilege(ctx,
2405 conn,
2406 req,
2407 directory,
2408 ucf_flags,
2409 &mask_contains_wcard,
2410 &smb_dname);
2411 } else {
2412 ntstatus = filename_convert(ctx, conn,
2413 req->flags2 & FLAGS2_DFS_PATHNAMES,
2414 directory,
2415 ucf_flags,
2416 &mask_contains_wcard,
2417 &smb_dname);
2420 if (!NT_STATUS_IS_OK(ntstatus)) {
2421 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2422 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2423 ERRSRV, ERRbadpath);
2424 goto out;
2426 reply_nterror(req, ntstatus);
2427 goto out;
2430 mask = smb_dname->original_lcomp;
2432 directory = smb_dname->base_name;
2434 p = strrchr_m(directory,'/');
2435 if(p == NULL) {
2436 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2437 if((directory[0] == '.') && (directory[1] == '\0')) {
2438 mask = talloc_strdup(ctx,"*");
2439 if (!mask) {
2440 reply_nterror(req, NT_STATUS_NO_MEMORY);
2441 goto out;
2443 mask_contains_wcard = True;
2445 } else {
2446 *p = 0;
2449 if (p == NULL || p == directory) {
2450 /* Ensure we don't have a directory name of "". */
2451 directory = talloc_strdup(talloc_tos(), ".");
2452 if (!directory) {
2453 reply_nterror(req, NT_STATUS_NO_MEMORY);
2454 goto out;
2458 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2460 if (info_level == SMB_FIND_EA_LIST) {
2461 uint32 ea_size;
2463 if (total_data < 4) {
2464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2465 goto out;
2468 ea_size = IVAL(pdata,0);
2469 if (ea_size != total_data) {
2470 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2471 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2473 goto out;
2476 if (!lp_ea_support(SNUM(conn))) {
2477 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2478 goto out;
2481 /* Pull out the list of names. */
2482 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2483 if (!ea_list) {
2484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2485 goto out;
2489 *ppdata = (char *)SMB_REALLOC(
2490 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2491 if(*ppdata == NULL ) {
2492 reply_nterror(req, NT_STATUS_NO_MEMORY);
2493 goto out;
2495 pdata = *ppdata;
2496 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2498 /* Realloc the params space */
2499 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2500 if (*pparams == NULL) {
2501 reply_nterror(req, NT_STATUS_NO_MEMORY);
2502 goto out;
2504 params = *pparams;
2506 /* Save the wildcard match and attribs we are using on this directory -
2507 needed as lanman2 assumes these are being saved between calls */
2509 ntstatus = dptr_create(conn,
2510 req,
2511 NULL, /* fsp */
2512 directory,
2513 False,
2514 True,
2515 req->smbpid,
2516 mask,
2517 mask_contains_wcard,
2518 dirtype,
2519 &dirptr);
2521 if (!NT_STATUS_IS_OK(ntstatus)) {
2522 reply_nterror(req, ntstatus);
2523 goto out;
2526 if (backup_priv) {
2527 /* Remember this in case we have
2528 to do a findnext. */
2529 dptr_set_priv(dirptr);
2532 dptr_num = dptr_dnum(dirptr);
2533 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2535 /* Initialize per TRANS2_FIND_FIRST operation data */
2536 dptr_init_search_op(dirptr);
2538 /* We don't need to check for VOL here as this is returned by
2539 a different TRANS2 call. */
2541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2542 directory,lp_dontdescend(ctx, SNUM(conn))));
2543 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2544 dont_descend = True;
2546 p = pdata;
2547 space_remaining = max_data_bytes;
2548 out_of_space = False;
2550 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2551 bool got_exact_match = False;
2553 /* this is a heuristic to avoid seeking the dirptr except when
2554 absolutely necessary. It allows for a filename of about 40 chars */
2555 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2556 out_of_space = True;
2557 finished = False;
2558 } else {
2559 finished = !get_lanman2_dir_entry(ctx,
2560 conn,
2561 dirptr,
2562 req->flags2,
2563 mask,dirtype,info_level,
2564 requires_resume_key,dont_descend,
2565 ask_sharemode,
2566 &p,pdata,data_end,
2567 space_remaining, &out_of_space,
2568 &got_exact_match,
2569 &last_entry_off, ea_list);
2572 if (finished && out_of_space)
2573 finished = False;
2575 if (!finished && !out_of_space)
2576 numentries++;
2579 * As an optimisation if we know we aren't looking
2580 * for a wildcard name (ie. the name matches the wildcard exactly)
2581 * then we can finish on any (first) match.
2582 * This speeds up large directory searches. JRA.
2585 if(got_exact_match)
2586 finished = True;
2588 /* Ensure space_remaining never goes -ve. */
2589 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2590 space_remaining = 0;
2591 out_of_space = true;
2592 } else {
2593 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2597 /* Check if we can close the dirptr */
2598 if(close_after_first || (finished && close_if_end)) {
2599 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2600 dptr_close(sconn, &dptr_num);
2604 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2605 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2606 * the protocol level is less than NT1. Tested with smbclient. JRA.
2607 * This should fix the OS/2 client bug #2335.
2610 if(numentries == 0) {
2611 dptr_close(sconn, &dptr_num);
2612 if (get_Protocol() < PROTOCOL_NT1) {
2613 reply_force_doserror(req, ERRDOS, ERRnofiles);
2614 goto out;
2615 } else {
2616 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2617 ERRDOS, ERRbadfile);
2618 goto out;
2622 /* At this point pdata points to numentries directory entries. */
2624 /* Set up the return parameter block */
2625 SSVAL(params,0,dptr_num);
2626 SSVAL(params,2,numentries);
2627 SSVAL(params,4,finished);
2628 SSVAL(params,6,0); /* Never an EA error */
2629 SSVAL(params,8,last_entry_off);
2631 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2632 max_data_bytes);
2634 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2635 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2636 if (!directory) {
2637 reply_nterror(req, NT_STATUS_NO_MEMORY);
2641 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2642 smb_fn_name(req->cmd),
2643 mask, directory, dirtype, numentries ) );
2646 * Force a name mangle here to ensure that the
2647 * mask as an 8.3 name is top of the mangled cache.
2648 * The reasons for this are subtle. Don't remove
2649 * this code unless you know what you are doing
2650 * (see PR#13758). JRA.
2653 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2654 char mangled_name[13];
2655 name_to_8_3(mask, mangled_name, True, conn->params);
2657 out:
2659 if (backup_priv) {
2660 unbecome_root();
2663 TALLOC_FREE(smb_dname);
2664 return;
2667 /****************************************************************************
2668 Reply to a TRANS2_FINDNEXT.
2669 ****************************************************************************/
2671 static void call_trans2findnext(connection_struct *conn,
2672 struct smb_request *req,
2673 char **pparams, int total_params,
2674 char **ppdata, int total_data,
2675 unsigned int max_data_bytes)
2677 /* We must be careful here that we don't return more than the
2678 allowed number of data bytes. If this means returning fewer than
2679 maxentries then so be it. We assume that the redirector has
2680 enough room for the fixed number of parameter bytes it has
2681 requested. */
2682 char *params = *pparams;
2683 char *pdata = *ppdata;
2684 char *data_end;
2685 int dptr_num;
2686 int maxentries;
2687 uint16 info_level;
2688 uint32 resume_key;
2689 uint16 findnext_flags;
2690 bool close_after_request;
2691 bool close_if_end;
2692 bool requires_resume_key;
2693 bool continue_bit;
2694 bool mask_contains_wcard = False;
2695 char *resume_name = NULL;
2696 const char *mask = NULL;
2697 const char *directory = NULL;
2698 char *p = NULL;
2699 uint16 dirtype;
2700 int numentries = 0;
2701 int i, last_entry_off=0;
2702 bool finished = False;
2703 bool dont_descend = False;
2704 bool out_of_space = False;
2705 int space_remaining;
2706 struct ea_list *ea_list = NULL;
2707 NTSTATUS ntstatus = NT_STATUS_OK;
2708 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2709 TALLOC_CTX *ctx = talloc_tos();
2710 struct dptr_struct *dirptr;
2711 struct smbd_server_connection *sconn = req->sconn;
2712 bool backup_priv = false;
2714 if (total_params < 13) {
2715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2716 return;
2719 dptr_num = SVAL(params,0);
2720 maxentries = SVAL(params,2);
2721 info_level = SVAL(params,4);
2722 resume_key = IVAL(params,6);
2723 findnext_flags = SVAL(params,10);
2724 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2725 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2726 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2727 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2729 if (!continue_bit) {
2730 /* We only need resume_name if continue_bit is zero. */
2731 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2732 params+12,
2733 total_params - 12, STR_TERMINATE, &ntstatus,
2734 &mask_contains_wcard);
2735 if (!NT_STATUS_IS_OK(ntstatus)) {
2736 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2737 complain (it thinks we're asking for the directory above the shared
2738 path or an invalid name). Catch this as the resume name is only compared, never used in
2739 a file access. JRA. */
2740 srvstr_pull_talloc(ctx, params, req->flags2,
2741 &resume_name, params+12,
2742 total_params - 12,
2743 STR_TERMINATE);
2745 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2746 reply_nterror(req, ntstatus);
2747 return;
2752 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2753 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2754 resume_key = %d resume name = %s continue=%d level = %d\n",
2755 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2756 requires_resume_key, resume_key,
2757 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2759 if (!maxentries) {
2760 /* W2K3 seems to treat zero as 1. */
2761 maxentries = 1;
2764 switch (info_level) {
2765 case SMB_FIND_INFO_STANDARD:
2766 case SMB_FIND_EA_SIZE:
2767 case SMB_FIND_EA_LIST:
2768 case SMB_FIND_FILE_DIRECTORY_INFO:
2769 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2770 case SMB_FIND_FILE_NAMES_INFO:
2771 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2772 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2773 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2774 break;
2775 case SMB_FIND_FILE_UNIX:
2776 case SMB_FIND_FILE_UNIX_INFO2:
2777 /* Always use filesystem for UNIX mtime query. */
2778 ask_sharemode = false;
2779 if (!lp_unix_extensions()) {
2780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2781 return;
2783 break;
2784 default:
2785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2786 return;
2789 if (info_level == SMB_FIND_EA_LIST) {
2790 uint32 ea_size;
2792 if (total_data < 4) {
2793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 return;
2797 ea_size = IVAL(pdata,0);
2798 if (ea_size != total_data) {
2799 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2800 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 return;
2805 if (!lp_ea_support(SNUM(conn))) {
2806 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2807 return;
2810 /* Pull out the list of names. */
2811 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2812 if (!ea_list) {
2813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2814 return;
2818 *ppdata = (char *)SMB_REALLOC(
2819 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2820 if(*ppdata == NULL) {
2821 reply_nterror(req, NT_STATUS_NO_MEMORY);
2822 return;
2825 pdata = *ppdata;
2826 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2828 /* Realloc the params space */
2829 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2830 if(*pparams == NULL ) {
2831 reply_nterror(req, NT_STATUS_NO_MEMORY);
2832 return;
2835 params = *pparams;
2837 /* Check that the dptr is valid */
2838 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2839 reply_nterror(req, STATUS_NO_MORE_FILES);
2840 return;
2843 directory = dptr_path(sconn, dptr_num);
2845 /* Get the wildcard mask from the dptr */
2846 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2847 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2848 reply_nterror(req, STATUS_NO_MORE_FILES);
2849 return;
2852 /* Get the attr mask from the dptr */
2853 dirtype = dptr_attr(sconn, dptr_num);
2855 backup_priv = dptr_get_priv(dirptr);
2857 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2858 "backup_priv = %d\n",
2859 dptr_num, mask, dirtype,
2860 (long)dirptr,
2861 dptr_TellDir(dirptr),
2862 (int)backup_priv));
2864 /* Initialize per TRANS2_FIND_NEXT operation data */
2865 dptr_init_search_op(dirptr);
2867 /* We don't need to check for VOL here as this is returned by
2868 a different TRANS2 call. */
2870 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2871 directory,lp_dontdescend(ctx, SNUM(conn))));
2872 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2873 dont_descend = True;
2875 p = pdata;
2876 space_remaining = max_data_bytes;
2877 out_of_space = False;
2879 if (backup_priv) {
2880 become_root();
2884 * Seek to the correct position. We no longer use the resume key but
2885 * depend on the last file name instead.
2888 if(!continue_bit && resume_name && *resume_name) {
2889 SMB_STRUCT_STAT st;
2891 long current_pos = 0;
2893 * Remember, name_to_8_3 is called by
2894 * get_lanman2_dir_entry(), so the resume name
2895 * could be mangled. Ensure we check the unmangled name.
2898 if (mangle_is_mangled(resume_name, conn->params)) {
2899 char *new_resume_name = NULL;
2900 mangle_lookup_name_from_8_3(ctx,
2901 resume_name,
2902 &new_resume_name,
2903 conn->params);
2904 if (new_resume_name) {
2905 resume_name = new_resume_name;
2910 * Fix for NT redirector problem triggered by resume key indexes
2911 * changing between directory scans. We now return a resume key of 0
2912 * and instead look for the filename to continue from (also given
2913 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2914 * findfirst/findnext (as is usual) then the directory pointer
2915 * should already be at the correct place.
2918 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2919 } /* end if resume_name && !continue_bit */
2921 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2922 bool got_exact_match = False;
2924 /* this is a heuristic to avoid seeking the dirptr except when
2925 absolutely necessary. It allows for a filename of about 40 chars */
2926 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2927 out_of_space = True;
2928 finished = False;
2929 } else {
2930 finished = !get_lanman2_dir_entry(ctx,
2931 conn,
2932 dirptr,
2933 req->flags2,
2934 mask,dirtype,info_level,
2935 requires_resume_key,dont_descend,
2936 ask_sharemode,
2937 &p,pdata,data_end,
2938 space_remaining, &out_of_space,
2939 &got_exact_match,
2940 &last_entry_off, ea_list);
2943 if (finished && out_of_space)
2944 finished = False;
2946 if (!finished && !out_of_space)
2947 numentries++;
2950 * As an optimisation if we know we aren't looking
2951 * for a wildcard name (ie. the name matches the wildcard exactly)
2952 * then we can finish on any (first) match.
2953 * This speeds up large directory searches. JRA.
2956 if(got_exact_match)
2957 finished = True;
2959 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2962 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2963 smb_fn_name(req->cmd),
2964 mask, directory, dirtype, numentries ) );
2966 /* Check if we can close the dirptr */
2967 if(close_after_request || (finished && close_if_end)) {
2968 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2969 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2972 if (backup_priv) {
2973 unbecome_root();
2976 /* Set up the return parameter block */
2977 SSVAL(params,0,numentries);
2978 SSVAL(params,2,finished);
2979 SSVAL(params,4,0); /* Never an EA error */
2980 SSVAL(params,6,last_entry_off);
2982 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2983 max_data_bytes);
2985 return;
2988 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2990 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2991 return objid;
2994 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2996 SMB_ASSERT(extended_info != NULL);
2998 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2999 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3000 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3001 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3002 #ifdef SAMBA_VERSION_REVISION
3003 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3004 #endif
3005 extended_info->samba_subversion = 0;
3006 #ifdef SAMBA_VERSION_RC_RELEASE
3007 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3008 #else
3009 #ifdef SAMBA_VERSION_PRE_RELEASE
3010 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3011 #endif
3012 #endif
3013 #ifdef SAMBA_VERSION_VENDOR_PATCH
3014 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3015 #endif
3016 extended_info->samba_gitcommitdate = 0;
3017 #ifdef SAMBA_VERSION_COMMIT_TIME
3018 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3019 #endif
3021 memset(extended_info->samba_version_string, 0,
3022 sizeof(extended_info->samba_version_string));
3024 snprintf (extended_info->samba_version_string,
3025 sizeof(extended_info->samba_version_string),
3026 "%s", samba_version_string());
3029 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3030 TALLOC_CTX *mem_ctx,
3031 uint16_t info_level,
3032 uint16_t flags2,
3033 unsigned int max_data_bytes,
3034 char **ppdata,
3035 int *ret_data_len)
3037 char *pdata, *end_data;
3038 int data_len = 0, len;
3039 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3040 int snum = SNUM(conn);
3041 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3042 uint32 additional_flags = 0;
3043 struct smb_filename smb_fname_dot;
3044 SMB_STRUCT_STAT st;
3046 if (IS_IPC(conn)) {
3047 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3048 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3049 "info level (0x%x) on IPC$.\n",
3050 (unsigned int)info_level));
3051 return NT_STATUS_ACCESS_DENIED;
3055 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3057 ZERO_STRUCT(smb_fname_dot);
3058 smb_fname_dot.base_name = discard_const_p(char, ".");
3060 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3061 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3062 return map_nt_error_from_unix(errno);
3065 st = smb_fname_dot.st;
3067 *ppdata = (char *)SMB_REALLOC(
3068 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3069 if (*ppdata == NULL) {
3070 return NT_STATUS_NO_MEMORY;
3073 pdata = *ppdata;
3074 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3075 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3077 switch (info_level) {
3078 case SMB_INFO_ALLOCATION:
3080 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3081 data_len = 18;
3082 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno);
3086 block_size = lp_block_size(snum);
3087 if (bsize < block_size) {
3088 uint64_t factor = block_size/bsize;
3089 bsize = block_size;
3090 dsize /= factor;
3091 dfree /= factor;
3093 if (bsize > block_size) {
3094 uint64_t factor = bsize/block_size;
3095 bsize = block_size;
3096 dsize *= factor;
3097 dfree *= factor;
3099 bytes_per_sector = 512;
3100 sectors_per_unit = bsize/bytes_per_sector;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3104 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3106 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3107 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3108 SIVAL(pdata,l1_cUnit,dsize);
3109 SIVAL(pdata,l1_cUnitAvail,dfree);
3110 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3111 break;
3114 case SMB_INFO_VOLUME:
3115 /* Return volume name */
3117 * Add volume serial number - hash of a combination of
3118 * the called hostname and the service name.
3120 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3122 * Win2k3 and previous mess this up by sending a name length
3123 * one byte short. I believe only older clients (OS/2 Win9x) use
3124 * this call so try fixing this by adding a terminating null to
3125 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3127 len = srvstr_push(
3128 pdata, flags2,
3129 pdata+l2_vol_szVolLabel, vname,
3130 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3131 STR_NOALIGN|STR_TERMINATE);
3132 SCVAL(pdata,l2_vol_cch,len);
3133 data_len = l2_vol_szVolLabel + len;
3134 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3135 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3136 len, vname));
3137 break;
3139 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3140 case SMB_FS_ATTRIBUTE_INFORMATION:
3142 additional_flags = 0;
3143 #if defined(HAVE_SYS_QUOTAS)
3144 additional_flags |= FILE_VOLUME_QUOTAS;
3145 #endif
3147 if(lp_nt_acl_support(SNUM(conn))) {
3148 additional_flags |= FILE_PERSISTENT_ACLS;
3151 /* Capabilities are filled in at connection time through STATVFS call */
3152 additional_flags |= conn->fs_capabilities;
3153 additional_flags |= lp_parm_int(conn->params->service,
3154 "share", "fake_fscaps",
3157 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3158 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3159 additional_flags); /* FS ATTRIBUTES */
3161 SIVAL(pdata,4,255); /* Max filename component length */
3162 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3163 and will think we can't do long filenames */
3164 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3165 PTR_DIFF(end_data, pdata+12),
3166 STR_UNICODE);
3167 SIVAL(pdata,8,len);
3168 data_len = 12 + len;
3169 break;
3171 case SMB_QUERY_FS_LABEL_INFO:
3172 case SMB_FS_LABEL_INFORMATION:
3173 len = srvstr_push(pdata, flags2, pdata+4, vname,
3174 PTR_DIFF(end_data, pdata+4), 0);
3175 data_len = 4 + len;
3176 SIVAL(pdata,0,len);
3177 break;
3179 case SMB_QUERY_FS_VOLUME_INFO:
3180 case SMB_FS_VOLUME_INFORMATION:
3183 * Add volume serial number - hash of a combination of
3184 * the called hostname and the service name.
3186 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3187 (str_checksum(get_local_machine_name())<<16));
3189 /* Max label len is 32 characters. */
3190 len = srvstr_push(pdata, flags2, pdata+18, vname,
3191 PTR_DIFF(end_data, pdata+18),
3192 STR_UNICODE);
3193 SIVAL(pdata,12,len);
3194 data_len = 18+len;
3196 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3197 (int)strlen(vname),vname,
3198 lp_servicename(talloc_tos(), snum)));
3199 break;
3201 case SMB_QUERY_FS_SIZE_INFO:
3202 case SMB_FS_SIZE_INFORMATION:
3204 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3205 data_len = 24;
3206 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3207 return map_nt_error_from_unix(errno);
3209 block_size = lp_block_size(snum);
3210 if (bsize < block_size) {
3211 uint64_t factor = block_size/bsize;
3212 bsize = block_size;
3213 dsize /= factor;
3214 dfree /= factor;
3216 if (bsize > block_size) {
3217 uint64_t factor = bsize/block_size;
3218 bsize = block_size;
3219 dsize *= factor;
3220 dfree *= factor;
3222 bytes_per_sector = 512;
3223 sectors_per_unit = bsize/bytes_per_sector;
3224 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3225 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3226 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3227 SBIG_UINT(pdata,0,dsize);
3228 SBIG_UINT(pdata,8,dfree);
3229 SIVAL(pdata,16,sectors_per_unit);
3230 SIVAL(pdata,20,bytes_per_sector);
3231 break;
3234 case SMB_FS_FULL_SIZE_INFORMATION:
3236 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3237 data_len = 32;
3238 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3239 return map_nt_error_from_unix(errno);
3241 block_size = lp_block_size(snum);
3242 if (bsize < block_size) {
3243 uint64_t factor = block_size/bsize;
3244 bsize = block_size;
3245 dsize /= factor;
3246 dfree /= factor;
3248 if (bsize > block_size) {
3249 uint64_t factor = bsize/block_size;
3250 bsize = block_size;
3251 dsize *= factor;
3252 dfree *= factor;
3254 bytes_per_sector = 512;
3255 sectors_per_unit = bsize/bytes_per_sector;
3256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3257 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3258 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3259 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3260 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3261 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3262 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3263 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3264 break;
3267 case SMB_QUERY_FS_DEVICE_INFO:
3268 case SMB_FS_DEVICE_INFORMATION:
3270 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3272 if (!CAN_WRITE(conn)) {
3273 characteristics |= FILE_READ_ONLY_DEVICE;
3275 data_len = 8;
3276 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3277 SIVAL(pdata,4,characteristics);
3278 break;
3281 #ifdef HAVE_SYS_QUOTAS
3282 case SMB_FS_QUOTA_INFORMATION:
3284 * what we have to send --metze:
3286 * Unknown1: 24 NULL bytes
3287 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3288 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3289 * Quota Flags: 2 byte :
3290 * Unknown3: 6 NULL bytes
3292 * 48 bytes total
3294 * details for Quota Flags:
3296 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3297 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3298 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3299 * 0x0001 Enable Quotas: enable quota for this fs
3303 /* we need to fake up a fsp here,
3304 * because its not send in this call
3306 files_struct fsp;
3307 SMB_NTQUOTA_STRUCT quotas;
3309 ZERO_STRUCT(fsp);
3310 ZERO_STRUCT(quotas);
3312 fsp.conn = conn;
3313 fsp.fnum = FNUM_FIELD_INVALID;
3315 /* access check */
3316 if (get_current_uid(conn) != 0) {
3317 DEBUG(0,("set_user_quota: access_denied "
3318 "service [%s] user [%s]\n",
3319 lp_servicename(talloc_tos(), SNUM(conn)),
3320 conn->session_info->unix_info->unix_name));
3321 return NT_STATUS_ACCESS_DENIED;
3324 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3325 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3326 return map_nt_error_from_unix(errno);
3329 data_len = 48;
3331 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3332 lp_servicename(talloc_tos(), SNUM(conn))));
3334 /* Unknown1 24 NULL bytes*/
3335 SBIG_UINT(pdata,0,(uint64_t)0);
3336 SBIG_UINT(pdata,8,(uint64_t)0);
3337 SBIG_UINT(pdata,16,(uint64_t)0);
3339 /* Default Soft Quota 8 bytes */
3340 SBIG_UINT(pdata,24,quotas.softlim);
3342 /* Default Hard Quota 8 bytes */
3343 SBIG_UINT(pdata,32,quotas.hardlim);
3345 /* Quota flag 2 bytes */
3346 SSVAL(pdata,40,quotas.qflags);
3348 /* Unknown3 6 NULL bytes */
3349 SSVAL(pdata,42,0);
3350 SIVAL(pdata,44,0);
3352 break;
3354 #endif /* HAVE_SYS_QUOTAS */
3355 case SMB_FS_OBJECTID_INFORMATION:
3357 unsigned char objid[16];
3358 struct smb_extended_info extended_info;
3359 memcpy(pdata,create_volume_objectid(conn, objid),16);
3360 samba_extended_info_version (&extended_info);
3361 SIVAL(pdata,16,extended_info.samba_magic);
3362 SIVAL(pdata,20,extended_info.samba_version);
3363 SIVAL(pdata,24,extended_info.samba_subversion);
3364 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3365 memcpy(pdata+36,extended_info.samba_version_string,28);
3366 data_len = 64;
3367 break;
3371 * Query the version and capabilities of the CIFS UNIX extensions
3372 * in use.
3375 case SMB_QUERY_CIFS_UNIX_INFO:
3377 bool large_write = lp_min_receive_file_size() &&
3378 !srv_is_signing_active(conn->sconn);
3379 bool large_read = !srv_is_signing_active(conn->sconn);
3380 int encrypt_caps = 0;
3382 if (!lp_unix_extensions()) {
3383 return NT_STATUS_INVALID_LEVEL;
3386 switch (conn->encrypt_level) {
3387 case SMB_SIGNING_OFF:
3388 encrypt_caps = 0;
3389 break;
3390 case SMB_SIGNING_IF_REQUIRED:
3391 case SMB_SIGNING_DEFAULT:
3392 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3393 break;
3394 case SMB_SIGNING_REQUIRED:
3395 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3396 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3397 large_write = false;
3398 large_read = false;
3399 break;
3402 data_len = 12;
3403 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3404 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3406 /* We have POSIX ACLs, pathname, encryption,
3407 * large read/write, and locking capability. */
3409 SBIG_UINT(pdata,4,((uint64_t)(
3410 CIFS_UNIX_POSIX_ACLS_CAP|
3411 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3412 CIFS_UNIX_FCNTL_LOCKS_CAP|
3413 CIFS_UNIX_EXTATTR_CAP|
3414 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3415 encrypt_caps|
3416 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3417 (large_write ?
3418 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3419 break;
3422 case SMB_QUERY_POSIX_FS_INFO:
3424 int rc;
3425 vfs_statvfs_struct svfs;
3427 if (!lp_unix_extensions()) {
3428 return NT_STATUS_INVALID_LEVEL;
3431 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3433 if (!rc) {
3434 data_len = 56;
3435 SIVAL(pdata,0,svfs.OptimalTransferSize);
3436 SIVAL(pdata,4,svfs.BlockSize);
3437 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3438 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3439 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3440 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3441 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3442 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3443 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3444 #ifdef EOPNOTSUPP
3445 } else if (rc == EOPNOTSUPP) {
3446 return NT_STATUS_INVALID_LEVEL;
3447 #endif /* EOPNOTSUPP */
3448 } else {
3449 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3450 return NT_STATUS_DOS(ERRSRV, ERRerror);
3452 break;
3455 case SMB_QUERY_POSIX_WHOAMI:
3457 uint32_t flags = 0;
3458 uint32_t sid_bytes;
3459 int i;
3461 if (!lp_unix_extensions()) {
3462 return NT_STATUS_INVALID_LEVEL;
3465 if (max_data_bytes < 40) {
3466 return NT_STATUS_BUFFER_TOO_SMALL;
3469 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3470 flags |= SMB_WHOAMI_GUEST;
3473 /* NOTE: 8 bytes for UID/GID, irrespective of native
3474 * platform size. This matches
3475 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3477 data_len = 4 /* flags */
3478 + 4 /* flag mask */
3479 + 8 /* uid */
3480 + 8 /* gid */
3481 + 4 /* ngroups */
3482 + 4 /* num_sids */
3483 + 4 /* SID bytes */
3484 + 4 /* pad/reserved */
3485 + (conn->session_info->unix_token->ngroups * 8)
3486 /* groups list */
3487 + (conn->session_info->security_token->num_sids *
3488 SID_MAX_SIZE)
3489 /* SID list */;
3491 SIVAL(pdata, 0, flags);
3492 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3493 SBIG_UINT(pdata, 8,
3494 (uint64_t)conn->session_info->unix_token->uid);
3495 SBIG_UINT(pdata, 16,
3496 (uint64_t)conn->session_info->unix_token->gid);
3499 if (data_len >= max_data_bytes) {
3500 /* Potential overflow, skip the GIDs and SIDs. */
3502 SIVAL(pdata, 24, 0); /* num_groups */
3503 SIVAL(pdata, 28, 0); /* num_sids */
3504 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3505 SIVAL(pdata, 36, 0); /* reserved */
3507 data_len = 40;
3508 break;
3511 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3512 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3514 /* We walk the SID list twice, but this call is fairly
3515 * infrequent, and I don't expect that it's performance
3516 * sensitive -- jpeach
3518 for (i = 0, sid_bytes = 0;
3519 i < conn->session_info->security_token->num_sids; ++i) {
3520 sid_bytes += ndr_size_dom_sid(
3521 &conn->session_info->security_token->sids[i],
3525 /* SID list byte count */
3526 SIVAL(pdata, 32, sid_bytes);
3528 /* 4 bytes pad/reserved - must be zero */
3529 SIVAL(pdata, 36, 0);
3530 data_len = 40;
3532 /* GID list */
3533 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3534 SBIG_UINT(pdata, data_len,
3535 (uint64_t)conn->session_info->unix_token->groups[i]);
3536 data_len += 8;
3539 /* SID list */
3540 for (i = 0;
3541 i < conn->session_info->security_token->num_sids; ++i) {
3542 int sid_len = ndr_size_dom_sid(
3543 &conn->session_info->security_token->sids[i],
3546 sid_linearize(pdata + data_len, sid_len,
3547 &conn->session_info->security_token->sids[i]);
3548 data_len += sid_len;
3551 break;
3554 case SMB_MAC_QUERY_FS_INFO:
3556 * Thursby MAC extension... ONLY on NTFS filesystems
3557 * once we do streams then we don't need this
3559 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3560 data_len = 88;
3561 SIVAL(pdata,84,0x100); /* Don't support mac... */
3562 break;
3564 /* drop through */
3565 default:
3566 return NT_STATUS_INVALID_LEVEL;
3569 *ret_data_len = data_len;
3570 return NT_STATUS_OK;
3573 /****************************************************************************
3574 Reply to a TRANS2_QFSINFO (query filesystem info).
3575 ****************************************************************************/
3577 static void call_trans2qfsinfo(connection_struct *conn,
3578 struct smb_request *req,
3579 char **pparams, int total_params,
3580 char **ppdata, int total_data,
3581 unsigned int max_data_bytes)
3583 char *params = *pparams;
3584 uint16_t info_level;
3585 int data_len = 0;
3586 NTSTATUS status;
3588 if (total_params < 2) {
3589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3590 return;
3593 info_level = SVAL(params,0);
3595 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3596 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3597 DEBUG(0,("call_trans2qfsinfo: encryption required "
3598 "and info level 0x%x sent.\n",
3599 (unsigned int)info_level));
3600 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3601 return;
3605 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3607 status = smbd_do_qfsinfo(conn, req,
3608 info_level,
3609 req->flags2,
3610 max_data_bytes,
3611 ppdata, &data_len);
3612 if (!NT_STATUS_IS_OK(status)) {
3613 reply_nterror(req, status);
3614 return;
3617 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3618 max_data_bytes);
3620 DEBUG( 4, ( "%s info_level = %d\n",
3621 smb_fn_name(req->cmd), info_level) );
3623 return;
3626 /****************************************************************************
3627 Reply to a TRANS2_SETFSINFO (set filesystem info).
3628 ****************************************************************************/
3630 static void call_trans2setfsinfo(connection_struct *conn,
3631 struct smb_request *req,
3632 char **pparams, int total_params,
3633 char **ppdata, int total_data,
3634 unsigned int max_data_bytes)
3636 struct smbd_server_connection *sconn = req->sconn;
3637 char *pdata = *ppdata;
3638 char *params = *pparams;
3639 uint16 info_level;
3641 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3642 lp_servicename(talloc_tos(), SNUM(conn))));
3644 /* */
3645 if (total_params < 4) {
3646 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3647 total_params));
3648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3649 return;
3652 info_level = SVAL(params,2);
3654 if (IS_IPC(conn)) {
3655 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3656 info_level != SMB_SET_CIFS_UNIX_INFO) {
3657 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3658 "info level (0x%x) on IPC$.\n",
3659 (unsigned int)info_level));
3660 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3661 return;
3665 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3666 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3667 DEBUG(0,("call_trans2setfsinfo: encryption required "
3668 "and info level 0x%x sent.\n",
3669 (unsigned int)info_level));
3670 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3671 return;
3675 switch(info_level) {
3676 case SMB_SET_CIFS_UNIX_INFO:
3677 if (!lp_unix_extensions()) {
3678 DEBUG(2,("call_trans2setfsinfo: "
3679 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3680 "unix extensions off\n"));
3681 reply_nterror(req,
3682 NT_STATUS_INVALID_LEVEL);
3683 return;
3686 /* There should be 12 bytes of capabilities set. */
3687 if (total_data < 12) {
3688 reply_nterror(
3689 req,
3690 NT_STATUS_INVALID_PARAMETER);
3691 return;
3693 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3694 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3695 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3696 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3697 /* Just print these values for now. */
3698 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3699 "major = %u, minor = %u cap_low = 0x%x, "
3700 "cap_high = 0x%xn",
3701 (unsigned int)sconn->
3702 smb1.unix_info.client_major,
3703 (unsigned int)sconn->
3704 smb1.unix_info.client_minor,
3705 (unsigned int)sconn->
3706 smb1.unix_info.client_cap_low,
3707 (unsigned int)sconn->
3708 smb1.unix_info.client_cap_high));
3710 /* Here is where we must switch to posix pathname processing... */
3711 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3712 lp_set_posix_pathnames();
3713 mangle_change_to_posix();
3716 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3717 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3718 /* Client that knows how to do posix locks,
3719 * but not posix open/mkdir operations. Set a
3720 * default type for read/write checks. */
3722 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3725 break;
3727 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3729 NTSTATUS status;
3730 size_t param_len = 0;
3731 size_t data_len = total_data;
3733 if (!lp_unix_extensions()) {
3734 reply_nterror(
3735 req,
3736 NT_STATUS_INVALID_LEVEL);
3737 return;
3740 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3741 reply_nterror(
3742 req,
3743 NT_STATUS_NOT_SUPPORTED);
3744 return;
3747 if (req->sconn->smb1.echo_handler.trusted_fde) {
3748 DEBUG( 2,("call_trans2setfsinfo: "
3749 "request transport encryption disabled"
3750 "with 'fork echo handler = yes'\n"));
3751 reply_nterror(
3752 req,
3753 NT_STATUS_NOT_SUPPORTED);
3754 return;
3757 DEBUG( 4,("call_trans2setfsinfo: "
3758 "request transport encryption.\n"));
3760 status = srv_request_encryption_setup(conn,
3761 (unsigned char **)ppdata,
3762 &data_len,
3763 (unsigned char **)pparams,
3764 &param_len);
3766 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3767 !NT_STATUS_IS_OK(status)) {
3768 reply_nterror(req, status);
3769 return;
3772 send_trans2_replies(conn, req,
3773 *pparams,
3774 param_len,
3775 *ppdata,
3776 data_len,
3777 max_data_bytes);
3779 if (NT_STATUS_IS_OK(status)) {
3780 /* Server-side transport
3781 * encryption is now *on*. */
3782 status = srv_encryption_start(conn);
3783 if (!NT_STATUS_IS_OK(status)) {
3784 char *reason = talloc_asprintf(talloc_tos(),
3785 "Failure in setting "
3786 "up encrypted transport: %s",
3787 nt_errstr(status));
3788 exit_server_cleanly(reason);
3791 return;
3794 case SMB_FS_QUOTA_INFORMATION:
3796 files_struct *fsp = NULL;
3797 SMB_NTQUOTA_STRUCT quotas;
3799 ZERO_STRUCT(quotas);
3801 /* access check */
3802 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3803 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3804 lp_servicename(talloc_tos(), SNUM(conn)),
3805 conn->session_info->unix_info->unix_name));
3806 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3807 return;
3810 /* note: normaly there're 48 bytes,
3811 * but we didn't use the last 6 bytes for now
3812 * --metze
3814 fsp = file_fsp(req, SVAL(params,0));
3816 if (!check_fsp_ntquota_handle(conn, req,
3817 fsp)) {
3818 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3819 reply_nterror(
3820 req, NT_STATUS_INVALID_HANDLE);
3821 return;
3824 if (total_data < 42) {
3825 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3826 total_data));
3827 reply_nterror(
3828 req,
3829 NT_STATUS_INVALID_PARAMETER);
3830 return;
3833 /* unknown_1 24 NULL bytes in pdata*/
3835 /* the soft quotas 8 bytes (uint64_t)*/
3836 quotas.softlim = BVAL(pdata,24);
3838 /* the hard quotas 8 bytes (uint64_t)*/
3839 quotas.hardlim = BVAL(pdata,32);
3841 /* quota_flags 2 bytes **/
3842 quotas.qflags = SVAL(pdata,40);
3844 /* unknown_2 6 NULL bytes follow*/
3846 /* now set the quotas */
3847 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3848 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3849 reply_nterror(req, map_nt_error_from_unix(errno));
3850 return;
3853 break;
3855 default:
3856 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3857 info_level));
3858 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3859 return;
3860 break;
3864 * sending this reply works fine,
3865 * but I'm not sure it's the same
3866 * like windows do...
3867 * --metze
3869 reply_outbuf(req, 10, 0);
3872 #if defined(HAVE_POSIX_ACLS)
3873 /****************************************************************************
3874 Utility function to count the number of entries in a POSIX acl.
3875 ****************************************************************************/
3877 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3879 unsigned int ace_count = 0;
3880 int entry_id = SMB_ACL_FIRST_ENTRY;
3881 SMB_ACL_ENTRY_T entry;
3883 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3884 /* get_next... */
3885 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3886 entry_id = SMB_ACL_NEXT_ENTRY;
3888 ace_count++;
3890 return ace_count;
3893 /****************************************************************************
3894 Utility function to marshall a POSIX acl into wire format.
3895 ****************************************************************************/
3897 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3899 int entry_id = SMB_ACL_FIRST_ENTRY;
3900 SMB_ACL_ENTRY_T entry;
3902 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3903 SMB_ACL_TAG_T tagtype;
3904 SMB_ACL_PERMSET_T permset;
3905 unsigned char perms = 0;
3906 unsigned int own_grp;
3908 /* get_next... */
3909 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3910 entry_id = SMB_ACL_NEXT_ENTRY;
3913 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3914 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3915 return False;
3918 if (sys_acl_get_permset(entry, &permset) == -1) {
3919 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3920 return False;
3923 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3924 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3925 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3927 SCVAL(pdata,1,perms);
3929 switch (tagtype) {
3930 case SMB_ACL_USER_OBJ:
3931 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3932 own_grp = (unsigned int)pst->st_ex_uid;
3933 SIVAL(pdata,2,own_grp);
3934 SIVAL(pdata,6,0);
3935 break;
3936 case SMB_ACL_USER:
3938 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3939 if (!puid) {
3940 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3941 return False;
3943 own_grp = (unsigned int)*puid;
3944 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3945 SIVAL(pdata,2,own_grp);
3946 SIVAL(pdata,6,0);
3947 break;
3949 case SMB_ACL_GROUP_OBJ:
3950 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3951 own_grp = (unsigned int)pst->st_ex_gid;
3952 SIVAL(pdata,2,own_grp);
3953 SIVAL(pdata,6,0);
3954 break;
3955 case SMB_ACL_GROUP:
3957 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3958 if (!pgid) {
3959 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3960 return False;
3962 own_grp = (unsigned int)*pgid;
3963 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3964 SIVAL(pdata,2,own_grp);
3965 SIVAL(pdata,6,0);
3966 break;
3968 case SMB_ACL_MASK:
3969 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3970 SIVAL(pdata,2,0xFFFFFFFF);
3971 SIVAL(pdata,6,0xFFFFFFFF);
3972 break;
3973 case SMB_ACL_OTHER:
3974 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3975 SIVAL(pdata,2,0xFFFFFFFF);
3976 SIVAL(pdata,6,0xFFFFFFFF);
3977 break;
3978 default:
3979 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3980 return False;
3982 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3985 return True;
3987 #endif
3989 /****************************************************************************
3990 Store the FILE_UNIX_BASIC info.
3991 ****************************************************************************/
3993 static char *store_file_unix_basic(connection_struct *conn,
3994 char *pdata,
3995 files_struct *fsp,
3996 const SMB_STRUCT_STAT *psbuf)
3998 uint64_t file_index = get_FileIndex(conn, psbuf);
3999 dev_t devno;
4001 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4002 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4004 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4005 pdata += 8;
4007 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4008 pdata += 8;
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4012 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4013 pdata += 24;
4015 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4016 SIVAL(pdata,4,0);
4017 pdata += 8;
4019 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4020 SIVAL(pdata,4,0);
4021 pdata += 8;
4023 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4024 pdata += 4;
4026 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4027 devno = psbuf->st_ex_rdev;
4028 } else {
4029 devno = psbuf->st_ex_dev;
4032 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4033 SIVAL(pdata,4,0);
4034 pdata += 8;
4036 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4037 SIVAL(pdata,4,0);
4038 pdata += 8;
4040 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4041 pdata += 8;
4043 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4044 SIVAL(pdata,4,0);
4045 pdata += 8;
4047 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4048 SIVAL(pdata,4,0);
4049 pdata += 8;
4051 return pdata;
4054 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4055 * the chflags(2) (or equivalent) flags.
4057 * XXX: this really should be behind the VFS interface. To do this, we would
4058 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4059 * Each VFS module could then implement its own mapping as appropriate for the
4060 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4062 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4063 info2_flags_map[] =
4065 #ifdef UF_NODUMP
4066 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4067 #endif
4069 #ifdef UF_IMMUTABLE
4070 { UF_IMMUTABLE, EXT_IMMUTABLE },
4071 #endif
4073 #ifdef UF_APPEND
4074 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4075 #endif
4077 #ifdef UF_HIDDEN
4078 { UF_HIDDEN, EXT_HIDDEN },
4079 #endif
4081 /* Do not remove. We need to guarantee that this array has at least one
4082 * entry to build on HP-UX.
4084 { 0, 0 }
4088 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4089 uint32 *smb_fflags, uint32 *smb_fmask)
4091 int i;
4093 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4094 *smb_fmask |= info2_flags_map[i].smb_fflag;
4095 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4096 *smb_fflags |= info2_flags_map[i].smb_fflag;
4101 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4102 const uint32 smb_fflags,
4103 const uint32 smb_fmask,
4104 int *stat_fflags)
4106 uint32 max_fmask = 0;
4107 int i;
4109 *stat_fflags = psbuf->st_ex_flags;
4111 /* For each flags requested in smb_fmask, check the state of the
4112 * corresponding flag in smb_fflags and set or clear the matching
4113 * stat flag.
4116 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4117 max_fmask |= info2_flags_map[i].smb_fflag;
4118 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4119 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4120 *stat_fflags |= info2_flags_map[i].stat_fflag;
4121 } else {
4122 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4127 /* If smb_fmask is asking to set any bits that are not supported by
4128 * our flag mappings, we should fail.
4130 if ((smb_fmask & max_fmask) != smb_fmask) {
4131 return False;
4134 return True;
4138 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4139 * of file flags and birth (create) time.
4141 static char *store_file_unix_basic_info2(connection_struct *conn,
4142 char *pdata,
4143 files_struct *fsp,
4144 const SMB_STRUCT_STAT *psbuf)
4146 uint32 file_flags = 0;
4147 uint32 flags_mask = 0;
4149 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4151 /* Create (birth) time 64 bit */
4152 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4153 pdata += 8;
4155 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4156 SIVAL(pdata, 0, file_flags); /* flags */
4157 SIVAL(pdata, 4, flags_mask); /* mask */
4158 pdata += 8;
4160 return pdata;
4163 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4164 const struct stream_struct *streams,
4165 char *data,
4166 unsigned int max_data_bytes,
4167 unsigned int *data_size)
4169 unsigned int i;
4170 unsigned int ofs = 0;
4172 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4173 unsigned int next_offset;
4174 size_t namelen;
4175 smb_ucs2_t *namebuf;
4177 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4178 streams[i].name, &namelen) ||
4179 namelen <= 2)
4181 return NT_STATUS_INVALID_PARAMETER;
4185 * name_buf is now null-terminated, we need to marshall as not
4186 * terminated
4189 namelen -= 2;
4191 SIVAL(data, ofs+4, namelen);
4192 SOFF_T(data, ofs+8, streams[i].size);
4193 SOFF_T(data, ofs+16, streams[i].alloc_size);
4194 memcpy(data+ofs+24, namebuf, namelen);
4195 TALLOC_FREE(namebuf);
4197 next_offset = ofs + 24 + namelen;
4199 if (i == num_streams-1) {
4200 SIVAL(data, ofs, 0);
4202 else {
4203 unsigned int align = ndr_align_size(next_offset, 8);
4205 memset(data+next_offset, 0, align);
4206 next_offset += align;
4208 SIVAL(data, ofs, next_offset - ofs);
4209 ofs = next_offset;
4212 ofs = next_offset;
4215 *data_size = ofs;
4217 return NT_STATUS_OK;
4220 /****************************************************************************
4221 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4222 ****************************************************************************/
4224 static void call_trans2qpipeinfo(connection_struct *conn,
4225 struct smb_request *req,
4226 unsigned int tran_call,
4227 char **pparams, int total_params,
4228 char **ppdata, int total_data,
4229 unsigned int max_data_bytes)
4231 char *params = *pparams;
4232 char *pdata = *ppdata;
4233 unsigned int data_size = 0;
4234 unsigned int param_size = 2;
4235 uint16 info_level;
4236 files_struct *fsp;
4238 if (!params) {
4239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4240 return;
4243 if (total_params < 4) {
4244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4245 return;
4248 fsp = file_fsp(req, SVAL(params,0));
4249 if (!fsp_is_np(fsp)) {
4250 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4251 return;
4254 info_level = SVAL(params,2);
4256 *pparams = (char *)SMB_REALLOC(*pparams,2);
4257 if (*pparams == NULL) {
4258 reply_nterror(req, NT_STATUS_NO_MEMORY);
4259 return;
4261 params = *pparams;
4262 SSVAL(params,0,0);
4263 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4264 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4265 if (*ppdata == NULL ) {
4266 reply_nterror(req, NT_STATUS_NO_MEMORY);
4267 return;
4269 pdata = *ppdata;
4271 switch (info_level) {
4272 case SMB_FILE_STANDARD_INFORMATION:
4273 memset(pdata,0,24);
4274 SOFF_T(pdata,0,4096LL);
4275 SIVAL(pdata,16,1);
4276 SIVAL(pdata,20,1);
4277 data_size = 24;
4278 break;
4280 default:
4281 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4282 return;
4285 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4286 max_data_bytes);
4288 return;
4291 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4292 TALLOC_CTX *mem_ctx,
4293 uint16_t info_level,
4294 files_struct *fsp,
4295 struct smb_filename *smb_fname,
4296 bool delete_pending,
4297 struct timespec write_time_ts,
4298 struct ea_list *ea_list,
4299 int lock_data_count,
4300 char *lock_data,
4301 uint16_t flags2,
4302 unsigned int max_data_bytes,
4303 char **ppdata,
4304 unsigned int *pdata_size)
4306 char *pdata = *ppdata;
4307 char *dstart, *dend;
4308 unsigned int data_size;
4309 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4310 time_t create_time, mtime, atime, c_time;
4311 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4312 char *p;
4313 char *base_name;
4314 char *dos_fname;
4315 int mode;
4316 int nlink;
4317 NTSTATUS status;
4318 uint64_t file_size = 0;
4319 uint64_t pos = 0;
4320 uint64_t allocation_size = 0;
4321 uint64_t file_index = 0;
4322 uint32_t access_mask = 0;
4324 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4325 return NT_STATUS_INVALID_LEVEL;
4328 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4329 smb_fname_str_dbg(smb_fname),
4330 fsp_fnum_dbg(fsp),
4331 info_level, max_data_bytes));
4333 mode = dos_mode(conn, smb_fname);
4334 nlink = psbuf->st_ex_nlink;
4336 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4337 nlink = 1;
4340 if ((nlink > 0) && delete_pending) {
4341 nlink -= 1;
4344 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4345 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4346 if (*ppdata == NULL) {
4347 return NT_STATUS_NO_MEMORY;
4349 pdata = *ppdata;
4350 dstart = pdata;
4351 dend = dstart + data_size - 1;
4353 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4354 update_stat_ex_mtime(psbuf, write_time_ts);
4357 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4358 mtime_ts = psbuf->st_ex_mtime;
4359 atime_ts = psbuf->st_ex_atime;
4360 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4362 if (lp_dos_filetime_resolution(SNUM(conn))) {
4363 dos_filetime_timespec(&create_time_ts);
4364 dos_filetime_timespec(&mtime_ts);
4365 dos_filetime_timespec(&atime_ts);
4366 dos_filetime_timespec(&ctime_ts);
4369 create_time = convert_timespec_to_time_t(create_time_ts);
4370 mtime = convert_timespec_to_time_t(mtime_ts);
4371 atime = convert_timespec_to_time_t(atime_ts);
4372 c_time = convert_timespec_to_time_t(ctime_ts);
4374 p = strrchr_m(smb_fname->base_name,'/');
4375 if (!p)
4376 base_name = smb_fname->base_name;
4377 else
4378 base_name = p+1;
4380 /* NT expects the name to be in an exact form of the *full*
4381 filename. See the trans2 torture test */
4382 if (ISDOT(base_name)) {
4383 dos_fname = talloc_strdup(mem_ctx, "\\");
4384 if (!dos_fname) {
4385 return NT_STATUS_NO_MEMORY;
4387 } else {
4388 dos_fname = talloc_asprintf(mem_ctx,
4389 "\\%s",
4390 smb_fname->base_name);
4391 if (!dos_fname) {
4392 return NT_STATUS_NO_MEMORY;
4394 if (is_ntfs_stream_smb_fname(smb_fname)) {
4395 dos_fname = talloc_asprintf(dos_fname, "%s",
4396 smb_fname->stream_name);
4397 if (!dos_fname) {
4398 return NT_STATUS_NO_MEMORY;
4402 string_replace(dos_fname, '/', '\\');
4405 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4407 if (!fsp) {
4408 /* Do we have this path open ? */
4409 files_struct *fsp1;
4410 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4411 fsp1 = file_find_di_first(conn->sconn, fileid);
4412 if (fsp1 && fsp1->initial_allocation_size) {
4413 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4417 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4418 file_size = get_file_size_stat(psbuf);
4421 if (fsp) {
4422 pos = fsp->fh->position_information;
4425 if (fsp) {
4426 access_mask = fsp->access_mask;
4427 } else {
4428 /* GENERIC_EXECUTE mapping from Windows */
4429 access_mask = 0x12019F;
4432 /* This should be an index number - looks like
4433 dev/ino to me :-)
4435 I think this causes us to fail the IFSKIT
4436 BasicFileInformationTest. -tpot */
4437 file_index = get_FileIndex(conn, psbuf);
4439 switch (info_level) {
4440 case SMB_INFO_STANDARD:
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4442 data_size = 22;
4443 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4444 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4445 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4446 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4447 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4448 SSVAL(pdata,l1_attrFile,mode);
4449 break;
4451 case SMB_INFO_QUERY_EA_SIZE:
4453 unsigned int ea_size =
4454 estimate_ea_size(conn, fsp,
4455 smb_fname);
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4457 data_size = 26;
4458 srv_put_dos_date2(pdata,0,create_time);
4459 srv_put_dos_date2(pdata,4,atime);
4460 srv_put_dos_date2(pdata,8,mtime); /* write time */
4461 SIVAL(pdata,12,(uint32)file_size);
4462 SIVAL(pdata,16,(uint32)allocation_size);
4463 SSVAL(pdata,20,mode);
4464 SIVAL(pdata,22,ea_size);
4465 break;
4468 case SMB_INFO_IS_NAME_VALID:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4470 if (fsp) {
4471 /* os/2 needs this ? really ?*/
4472 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4474 /* This is only reached for qpathinfo */
4475 data_size = 0;
4476 break;
4478 case SMB_INFO_QUERY_EAS_FROM_LIST:
4480 size_t total_ea_len = 0;
4481 struct ea_list *ea_file_list = NULL;
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4484 status =
4485 get_ea_list_from_file(mem_ctx, conn, fsp,
4486 smb_fname,
4487 &total_ea_len, &ea_file_list);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 return status;
4492 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4494 if (!ea_list || (total_ea_len > data_size)) {
4495 data_size = 4;
4496 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4497 break;
4500 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4501 break;
4504 case SMB_INFO_QUERY_ALL_EAS:
4506 /* We have data_size bytes to put EA's into. */
4507 size_t total_ea_len = 0;
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4510 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4511 smb_fname,
4512 &total_ea_len, &ea_list);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 return status;
4517 if (!ea_list || (total_ea_len > data_size)) {
4518 data_size = 4;
4519 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4520 break;
4523 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4524 break;
4527 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4529 /* This is FileFullEaInformation - 0xF which maps to
4530 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4532 /* We have data_size bytes to put EA's into. */
4533 size_t total_ea_len = 0;
4534 struct ea_list *ea_file_list = NULL;
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4538 /*TODO: add filtering and index handling */
4540 status =
4541 get_ea_list_from_file(mem_ctx, conn, fsp,
4542 smb_fname,
4543 &total_ea_len, &ea_file_list);
4544 if (!NT_STATUS_IS_OK(status)) {
4545 return status;
4547 if (!ea_file_list) {
4548 return NT_STATUS_NO_EAS_ON_FILE;
4551 status = fill_ea_chained_buffer(mem_ctx,
4552 pdata,
4553 data_size,
4554 &data_size,
4555 conn, ea_file_list);
4556 if (!NT_STATUS_IS_OK(status)) {
4557 return status;
4559 break;
4562 case SMB_FILE_BASIC_INFORMATION:
4563 case SMB_QUERY_FILE_BASIC_INFO:
4565 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4567 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4568 } else {
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4570 data_size = 40;
4571 SIVAL(pdata,36,0);
4573 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4574 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4575 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4576 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4577 SIVAL(pdata,32,mode);
4579 DEBUG(5,("SMB_QFBI - "));
4580 DEBUG(5,("create: %s ", ctime(&create_time)));
4581 DEBUG(5,("access: %s ", ctime(&atime)));
4582 DEBUG(5,("write: %s ", ctime(&mtime)));
4583 DEBUG(5,("change: %s ", ctime(&c_time)));
4584 DEBUG(5,("mode: %x\n", mode));
4585 break;
4587 case SMB_FILE_STANDARD_INFORMATION:
4588 case SMB_QUERY_FILE_STANDARD_INFO:
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4591 data_size = 24;
4592 SOFF_T(pdata,0,allocation_size);
4593 SOFF_T(pdata,8,file_size);
4594 SIVAL(pdata,16,nlink);
4595 SCVAL(pdata,20,delete_pending?1:0);
4596 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4597 SSVAL(pdata,22,0); /* Padding. */
4598 break;
4600 case SMB_FILE_EA_INFORMATION:
4601 case SMB_QUERY_FILE_EA_INFO:
4603 unsigned int ea_size =
4604 estimate_ea_size(conn, fsp, smb_fname);
4605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4606 data_size = 4;
4607 SIVAL(pdata,0,ea_size);
4608 break;
4611 /* Get the 8.3 name - used if NT SMB was negotiated. */
4612 case SMB_QUERY_FILE_ALT_NAME_INFO:
4613 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4615 int len;
4616 char mangled_name[13];
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4618 if (!name_to_8_3(base_name,mangled_name,
4619 True,conn->params)) {
4620 return NT_STATUS_NO_MEMORY;
4622 len = srvstr_push(dstart, flags2,
4623 pdata+4, mangled_name,
4624 PTR_DIFF(dend, pdata+4),
4625 STR_UNICODE);
4626 data_size = 4 + len;
4627 SIVAL(pdata,0,len);
4628 break;
4631 case SMB_QUERY_FILE_NAME_INFO:
4633 int len;
4635 this must be *exactly* right for ACLs on mapped drives to work
4637 len = srvstr_push(dstart, flags2,
4638 pdata+4, dos_fname,
4639 PTR_DIFF(dend, pdata+4),
4640 STR_UNICODE);
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4642 data_size = 4 + len;
4643 SIVAL(pdata,0,len);
4644 break;
4647 case SMB_FILE_ALLOCATION_INFORMATION:
4648 case SMB_QUERY_FILE_ALLOCATION_INFO:
4649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4650 data_size = 8;
4651 SOFF_T(pdata,0,allocation_size);
4652 break;
4654 case SMB_FILE_END_OF_FILE_INFORMATION:
4655 case SMB_QUERY_FILE_END_OF_FILEINFO:
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4657 data_size = 8;
4658 SOFF_T(pdata,0,file_size);
4659 break;
4661 case SMB_QUERY_FILE_ALL_INFO:
4662 case SMB_FILE_ALL_INFORMATION:
4664 int len;
4665 unsigned int ea_size =
4666 estimate_ea_size(conn, fsp, smb_fname);
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4668 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4669 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4670 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4671 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4672 SIVAL(pdata,32,mode);
4673 SIVAL(pdata,36,0); /* padding. */
4674 pdata += 40;
4675 SOFF_T(pdata,0,allocation_size);
4676 SOFF_T(pdata,8,file_size);
4677 SIVAL(pdata,16,nlink);
4678 SCVAL(pdata,20,delete_pending);
4679 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4680 SSVAL(pdata,22,0);
4681 pdata += 24;
4682 SIVAL(pdata,0,ea_size);
4683 pdata += 4; /* EA info */
4684 len = srvstr_push(dstart, flags2,
4685 pdata+4, dos_fname,
4686 PTR_DIFF(dend, pdata+4),
4687 STR_UNICODE);
4688 SIVAL(pdata,0,len);
4689 pdata += 4 + len;
4690 data_size = PTR_DIFF(pdata,(*ppdata));
4691 break;
4694 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4696 int len;
4697 unsigned int ea_size =
4698 estimate_ea_size(conn, fsp, smb_fname);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4700 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4701 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4702 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4703 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4704 SIVAL(pdata, 0x20, mode);
4705 SIVAL(pdata, 0x24, 0); /* padding. */
4706 SBVAL(pdata, 0x28, allocation_size);
4707 SBVAL(pdata, 0x30, file_size);
4708 SIVAL(pdata, 0x38, nlink);
4709 SCVAL(pdata, 0x3C, delete_pending);
4710 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4711 SSVAL(pdata, 0x3E, 0); /* padding */
4712 SBVAL(pdata, 0x40, file_index);
4713 SIVAL(pdata, 0x48, ea_size);
4714 SIVAL(pdata, 0x4C, access_mask);
4715 SBVAL(pdata, 0x50, pos);
4716 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4717 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4719 pdata += 0x60;
4721 len = srvstr_push(dstart, flags2,
4722 pdata+4, dos_fname,
4723 PTR_DIFF(dend, pdata+4),
4724 STR_UNICODE);
4725 SIVAL(pdata,0,len);
4726 pdata += 4 + len;
4727 data_size = PTR_DIFF(pdata,(*ppdata));
4728 break;
4730 case SMB_FILE_INTERNAL_INFORMATION:
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4733 SBVAL(pdata, 0, file_index);
4734 data_size = 8;
4735 break;
4737 case SMB_FILE_ACCESS_INFORMATION:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4739 SIVAL(pdata, 0, access_mask);
4740 data_size = 4;
4741 break;
4743 case SMB_FILE_NAME_INFORMATION:
4744 /* Pathname with leading '\'. */
4746 size_t byte_len;
4747 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4749 SIVAL(pdata,0,byte_len);
4750 data_size = 4 + byte_len;
4751 break;
4754 case SMB_FILE_DISPOSITION_INFORMATION:
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4756 data_size = 1;
4757 SCVAL(pdata,0,delete_pending);
4758 break;
4760 case SMB_FILE_POSITION_INFORMATION:
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4762 data_size = 8;
4763 SOFF_T(pdata,0,pos);
4764 break;
4766 case SMB_FILE_MODE_INFORMATION:
4767 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4768 SIVAL(pdata,0,mode);
4769 data_size = 4;
4770 break;
4772 case SMB_FILE_ALIGNMENT_INFORMATION:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4774 SIVAL(pdata,0,0); /* No alignment needed. */
4775 data_size = 4;
4776 break;
4779 * NT4 server just returns "invalid query" to this - if we try
4780 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4781 * want this. JRA.
4783 /* The first statement above is false - verified using Thursby
4784 * client against NT4 -- gcolley.
4786 case SMB_QUERY_FILE_STREAM_INFO:
4787 case SMB_FILE_STREAM_INFORMATION: {
4788 unsigned int num_streams = 0;
4789 struct stream_struct *streams = NULL;
4791 DEBUG(10,("smbd_do_qfilepathinfo: "
4792 "SMB_FILE_STREAM_INFORMATION\n"));
4794 if (is_ntfs_stream_smb_fname(smb_fname)) {
4795 return NT_STATUS_INVALID_PARAMETER;
4798 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4799 talloc_tos(), &num_streams, &streams);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 DEBUG(10, ("could not get stream info: %s\n",
4803 nt_errstr(status)));
4804 return status;
4807 status = marshall_stream_info(num_streams, streams,
4808 pdata, max_data_bytes,
4809 &data_size);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 DEBUG(10, ("marshall_stream_info failed: %s\n",
4813 nt_errstr(status)));
4814 return status;
4817 TALLOC_FREE(streams);
4819 break;
4821 case SMB_QUERY_COMPRESSION_INFO:
4822 case SMB_FILE_COMPRESSION_INFORMATION:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4824 SOFF_T(pdata,0,file_size);
4825 SIVAL(pdata,8,0); /* ??? */
4826 SIVAL(pdata,12,0); /* ??? */
4827 data_size = 16;
4828 break;
4830 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4832 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4833 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4834 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4835 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4836 SOFF_T(pdata,32,allocation_size);
4837 SOFF_T(pdata,40,file_size);
4838 SIVAL(pdata,48,mode);
4839 SIVAL(pdata,52,0); /* ??? */
4840 data_size = 56;
4841 break;
4843 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4845 SIVAL(pdata,0,mode);
4846 SIVAL(pdata,4,0);
4847 data_size = 8;
4848 break;
4851 * CIFS UNIX Extensions.
4854 case SMB_QUERY_FILE_UNIX_BASIC:
4856 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4857 data_size = PTR_DIFF(pdata,(*ppdata));
4859 DEBUG(4,("smbd_do_qfilepathinfo: "
4860 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4861 dump_data(4, (uint8_t *)(*ppdata), data_size);
4863 break;
4865 case SMB_QUERY_FILE_UNIX_INFO2:
4867 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4868 data_size = PTR_DIFF(pdata,(*ppdata));
4871 int i;
4872 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4874 for (i=0; i<100; i++)
4875 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4876 DEBUG(4,("\n"));
4879 break;
4881 case SMB_QUERY_FILE_UNIX_LINK:
4883 int len;
4884 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4886 if (!buffer) {
4887 return NT_STATUS_NO_MEMORY;
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4891 #ifdef S_ISLNK
4892 if(!S_ISLNK(psbuf->st_ex_mode)) {
4893 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4895 #else
4896 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4897 #endif
4898 len = SMB_VFS_READLINK(conn,
4899 smb_fname->base_name,
4900 buffer, PATH_MAX);
4901 if (len == -1) {
4902 return map_nt_error_from_unix(errno);
4904 buffer[len] = 0;
4905 len = srvstr_push(dstart, flags2,
4906 pdata, buffer,
4907 PTR_DIFF(dend, pdata),
4908 STR_TERMINATE);
4909 pdata += len;
4910 data_size = PTR_DIFF(pdata,(*ppdata));
4912 break;
4915 #if defined(HAVE_POSIX_ACLS)
4916 case SMB_QUERY_POSIX_ACL:
4918 SMB_ACL_T file_acl = NULL;
4919 SMB_ACL_T def_acl = NULL;
4920 uint16 num_file_acls = 0;
4921 uint16 num_def_acls = 0;
4923 if (fsp && fsp->fh->fd != -1) {
4924 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4925 } else {
4926 file_acl =
4927 SMB_VFS_SYS_ACL_GET_FILE(conn,
4928 smb_fname->base_name,
4929 SMB_ACL_TYPE_ACCESS);
4932 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4933 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4934 "not implemented on "
4935 "filesystem containing %s\n",
4936 smb_fname->base_name));
4937 return NT_STATUS_NOT_IMPLEMENTED;
4940 if (S_ISDIR(psbuf->st_ex_mode)) {
4941 if (fsp && fsp->is_directory) {
4942 def_acl =
4943 SMB_VFS_SYS_ACL_GET_FILE(
4944 conn,
4945 fsp->fsp_name->base_name,
4946 SMB_ACL_TYPE_DEFAULT);
4947 } else {
4948 def_acl =
4949 SMB_VFS_SYS_ACL_GET_FILE(
4950 conn,
4951 smb_fname->base_name,
4952 SMB_ACL_TYPE_DEFAULT);
4954 def_acl = free_empty_sys_acl(conn, def_acl);
4957 num_file_acls = count_acl_entries(conn, file_acl);
4958 num_def_acls = count_acl_entries(conn, def_acl);
4960 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4961 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4962 data_size,
4963 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4964 SMB_POSIX_ACL_HEADER_SIZE) ));
4965 if (file_acl) {
4966 TALLOC_FREE(file_acl);
4968 if (def_acl) {
4969 TALLOC_FREE(def_acl);
4971 return NT_STATUS_BUFFER_TOO_SMALL;
4974 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4975 SSVAL(pdata,2,num_file_acls);
4976 SSVAL(pdata,4,num_def_acls);
4977 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4978 if (file_acl) {
4979 TALLOC_FREE(file_acl);
4981 if (def_acl) {
4982 TALLOC_FREE(def_acl);
4984 return NT_STATUS_INTERNAL_ERROR;
4986 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4987 if (file_acl) {
4988 TALLOC_FREE(file_acl);
4990 if (def_acl) {
4991 TALLOC_FREE(def_acl);
4993 return NT_STATUS_INTERNAL_ERROR;
4996 if (file_acl) {
4997 TALLOC_FREE(file_acl);
4999 if (def_acl) {
5000 TALLOC_FREE(def_acl);
5002 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5003 break;
5005 #endif
5008 case SMB_QUERY_POSIX_LOCK:
5010 uint64_t count;
5011 uint64_t offset;
5012 uint64_t smblctx;
5013 enum brl_type lock_type;
5015 /* We need an open file with a real fd for this. */
5016 if (!fsp || fsp->fh->fd == -1) {
5017 return NT_STATUS_INVALID_LEVEL;
5020 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5021 return NT_STATUS_INVALID_PARAMETER;
5024 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5025 case POSIX_LOCK_TYPE_READ:
5026 lock_type = READ_LOCK;
5027 break;
5028 case POSIX_LOCK_TYPE_WRITE:
5029 lock_type = WRITE_LOCK;
5030 break;
5031 case POSIX_LOCK_TYPE_UNLOCK:
5032 default:
5033 /* There's no point in asking for an unlock... */
5034 return NT_STATUS_INVALID_PARAMETER;
5037 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5038 #if defined(HAVE_LONGLONG)
5039 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5040 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5041 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5042 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5043 #else /* HAVE_LONGLONG */
5044 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5045 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5046 #endif /* HAVE_LONGLONG */
5048 status = query_lock(fsp,
5049 &smblctx,
5050 &count,
5051 &offset,
5052 &lock_type,
5053 POSIX_LOCK);
5055 if (ERROR_WAS_LOCK_DENIED(status)) {
5056 /* Here we need to report who has it locked... */
5057 data_size = POSIX_LOCK_DATA_SIZE;
5059 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5060 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5061 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5062 #if defined(HAVE_LONGLONG)
5063 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5064 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5065 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5066 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5067 #else /* HAVE_LONGLONG */
5068 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5069 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5070 #endif /* HAVE_LONGLONG */
5072 } else if (NT_STATUS_IS_OK(status)) {
5073 /* For success we just return a copy of what we sent
5074 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5075 data_size = POSIX_LOCK_DATA_SIZE;
5076 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5077 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5078 } else {
5079 return status;
5081 break;
5084 default:
5085 return NT_STATUS_INVALID_LEVEL;
5088 *pdata_size = data_size;
5089 return NT_STATUS_OK;
5092 /****************************************************************************
5093 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5094 file name or file id).
5095 ****************************************************************************/
5097 static void call_trans2qfilepathinfo(connection_struct *conn,
5098 struct smb_request *req,
5099 unsigned int tran_call,
5100 char **pparams, int total_params,
5101 char **ppdata, int total_data,
5102 unsigned int max_data_bytes)
5104 char *params = *pparams;
5105 char *pdata = *ppdata;
5106 uint16 info_level;
5107 unsigned int data_size = 0;
5108 unsigned int param_size = 2;
5109 struct smb_filename *smb_fname = NULL;
5110 bool delete_pending = False;
5111 struct timespec write_time_ts;
5112 files_struct *fsp = NULL;
5113 struct file_id fileid;
5114 struct ea_list *ea_list = NULL;
5115 int lock_data_count = 0;
5116 char *lock_data = NULL;
5117 NTSTATUS status = NT_STATUS_OK;
5119 if (!params) {
5120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5121 return;
5124 ZERO_STRUCT(write_time_ts);
5126 if (tran_call == TRANSACT2_QFILEINFO) {
5127 if (total_params < 4) {
5128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5129 return;
5132 if (IS_IPC(conn)) {
5133 call_trans2qpipeinfo(conn, req, tran_call,
5134 pparams, total_params,
5135 ppdata, total_data,
5136 max_data_bytes);
5137 return;
5140 fsp = file_fsp(req, SVAL(params,0));
5141 info_level = SVAL(params,2);
5143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5145 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5146 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5147 return;
5150 /* Initial check for valid fsp ptr. */
5151 if (!check_fsp_open(conn, req, fsp)) {
5152 return;
5155 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5156 &smb_fname);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5159 return;
5162 if(fsp->fake_file_handle) {
5164 * This is actually for the QUOTA_FAKE_FILE --metze
5167 /* We know this name is ok, it's already passed the checks. */
5169 } else if(fsp->fh->fd == -1) {
5171 * This is actually a QFILEINFO on a directory
5172 * handle (returned from an NT SMB). NT5.0 seems
5173 * to do this call. JRA.
5176 if (INFO_LEVEL_IS_UNIX(info_level)) {
5177 /* Always do lstat for UNIX calls. */
5178 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5179 DEBUG(3,("call_trans2qfilepathinfo: "
5180 "SMB_VFS_LSTAT of %s failed "
5181 "(%s)\n",
5182 smb_fname_str_dbg(smb_fname),
5183 strerror(errno)));
5184 reply_nterror(req,
5185 map_nt_error_from_unix(errno));
5186 return;
5188 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_STAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname),
5192 strerror(errno)));
5193 reply_nterror(req,
5194 map_nt_error_from_unix(errno));
5195 return;
5198 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5199 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5200 } else {
5202 * Original code - this is an open file.
5204 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5205 DEBUG(3, ("fstat of %s failed (%s)\n",
5206 fsp_fnum_dbg(fsp), strerror(errno)));
5207 reply_nterror(req,
5208 map_nt_error_from_unix(errno));
5209 return;
5211 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5212 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5215 } else {
5216 uint32_t name_hash;
5217 char *fname = NULL;
5218 uint32_t ucf_flags = 0;
5220 /* qpathinfo */
5221 if (total_params < 7) {
5222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5223 return;
5226 info_level = SVAL(params,0);
5228 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5230 if (INFO_LEVEL_IS_UNIX(info_level)) {
5231 if (!lp_unix_extensions()) {
5232 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5233 return;
5235 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5236 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5237 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5238 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5242 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5243 total_params - 6,
5244 STR_TERMINATE, &status);
5245 if (!NT_STATUS_IS_OK(status)) {
5246 reply_nterror(req, status);
5247 return;
5250 status = filename_convert(req,
5251 conn,
5252 req->flags2 & FLAGS2_DFS_PATHNAMES,
5253 fname,
5254 ucf_flags,
5255 NULL,
5256 &smb_fname);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5259 reply_botherror(req,
5260 NT_STATUS_PATH_NOT_COVERED,
5261 ERRSRV, ERRbadpath);
5262 return;
5264 reply_nterror(req, status);
5265 return;
5268 /* If this is a stream, check if there is a delete_pending. */
5269 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5270 && is_ntfs_stream_smb_fname(smb_fname)) {
5271 struct smb_filename *smb_fname_base = NULL;
5273 /* Create an smb_filename with stream_name == NULL. */
5274 status =
5275 create_synthetic_smb_fname(talloc_tos(),
5276 smb_fname->base_name,
5277 NULL, NULL,
5278 &smb_fname_base);
5279 if (!NT_STATUS_IS_OK(status)) {
5280 reply_nterror(req, status);
5281 return;
5284 if (INFO_LEVEL_IS_UNIX(info_level)) {
5285 /* Always do lstat for UNIX calls. */
5286 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5287 DEBUG(3,("call_trans2qfilepathinfo: "
5288 "SMB_VFS_LSTAT of %s failed "
5289 "(%s)\n",
5290 smb_fname_str_dbg(smb_fname_base),
5291 strerror(errno)));
5292 TALLOC_FREE(smb_fname_base);
5293 reply_nterror(req,
5294 map_nt_error_from_unix(errno));
5295 return;
5297 } else {
5298 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "fileinfo of %s failed "
5301 "(%s)\n",
5302 smb_fname_str_dbg(smb_fname_base),
5303 strerror(errno)));
5304 TALLOC_FREE(smb_fname_base);
5305 reply_nterror(req,
5306 map_nt_error_from_unix(errno));
5307 return;
5311 status = file_name_hash(conn,
5312 smb_fname_str_dbg(smb_fname_base),
5313 &name_hash);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 TALLOC_FREE(smb_fname_base);
5316 reply_nterror(req, status);
5317 return;
5320 fileid = vfs_file_id_from_sbuf(conn,
5321 &smb_fname_base->st);
5322 TALLOC_FREE(smb_fname_base);
5323 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5324 if (delete_pending) {
5325 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5326 return;
5330 if (INFO_LEVEL_IS_UNIX(info_level)) {
5331 /* Always do lstat for UNIX calls. */
5332 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5333 DEBUG(3,("call_trans2qfilepathinfo: "
5334 "SMB_VFS_LSTAT of %s failed (%s)\n",
5335 smb_fname_str_dbg(smb_fname),
5336 strerror(errno)));
5337 reply_nterror(req,
5338 map_nt_error_from_unix(errno));
5339 return;
5342 } else {
5343 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5344 DEBUG(3,("call_trans2qfilepathinfo: "
5345 "SMB_VFS_STAT of %s failed (%s)\n",
5346 smb_fname_str_dbg(smb_fname),
5347 strerror(errno)));
5348 reply_nterror(req,
5349 map_nt_error_from_unix(errno));
5350 return;
5354 status = file_name_hash(conn,
5355 smb_fname_str_dbg(smb_fname),
5356 &name_hash);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 reply_nterror(req, status);
5359 return;
5362 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5363 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5364 if (delete_pending) {
5365 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5366 return;
5370 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5371 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5372 fsp_fnum_dbg(fsp),
5373 info_level,tran_call,total_data));
5375 /* Pull out any data sent here before we realloc. */
5376 switch (info_level) {
5377 case SMB_INFO_QUERY_EAS_FROM_LIST:
5379 /* Pull any EA list from the data portion. */
5380 uint32 ea_size;
5382 if (total_data < 4) {
5383 reply_nterror(
5384 req, NT_STATUS_INVALID_PARAMETER);
5385 return;
5387 ea_size = IVAL(pdata,0);
5389 if (total_data > 0 && ea_size != total_data) {
5390 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5391 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5392 reply_nterror(
5393 req, NT_STATUS_INVALID_PARAMETER);
5394 return;
5397 if (!lp_ea_support(SNUM(conn))) {
5398 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5399 return;
5402 /* Pull out the list of names. */
5403 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5404 if (!ea_list) {
5405 reply_nterror(
5406 req, NT_STATUS_INVALID_PARAMETER);
5407 return;
5409 break;
5412 case SMB_QUERY_POSIX_LOCK:
5414 if (fsp == NULL || fsp->fh->fd == -1) {
5415 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5416 return;
5419 if (total_data != POSIX_LOCK_DATA_SIZE) {
5420 reply_nterror(
5421 req, NT_STATUS_INVALID_PARAMETER);
5422 return;
5425 /* Copy the lock range data. */
5426 lock_data = (char *)talloc_memdup(
5427 req, pdata, total_data);
5428 if (!lock_data) {
5429 reply_nterror(req, NT_STATUS_NO_MEMORY);
5430 return;
5432 lock_data_count = total_data;
5434 default:
5435 break;
5438 *pparams = (char *)SMB_REALLOC(*pparams,2);
5439 if (*pparams == NULL) {
5440 reply_nterror(req, NT_STATUS_NO_MEMORY);
5441 return;
5443 params = *pparams;
5444 SSVAL(params,0,0);
5447 * draft-leach-cifs-v1-spec-02.txt
5448 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5449 * says:
5451 * The requested information is placed in the Data portion of the
5452 * transaction response. For the information levels greater than 0x100,
5453 * the transaction response has 1 parameter word which should be
5454 * ignored by the client.
5456 * However Windows only follows this rule for the IS_NAME_VALID call.
5458 switch (info_level) {
5459 case SMB_INFO_IS_NAME_VALID:
5460 param_size = 0;
5461 break;
5464 if ((info_level & 0xFF00) == 0xFF00) {
5466 * We use levels that start with 0xFF00
5467 * internally to represent SMB2 specific levels
5469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5470 return;
5473 status = smbd_do_qfilepathinfo(conn, req, info_level,
5474 fsp, smb_fname,
5475 delete_pending, write_time_ts,
5476 ea_list,
5477 lock_data_count, lock_data,
5478 req->flags2, max_data_bytes,
5479 ppdata, &data_size);
5480 if (!NT_STATUS_IS_OK(status)) {
5481 reply_nterror(req, status);
5482 return;
5485 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5486 max_data_bytes);
5488 return;
5491 /****************************************************************************
5492 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5493 code.
5494 ****************************************************************************/
5496 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5497 connection_struct *conn,
5498 struct smb_request *req,
5499 bool overwrite_if_exists,
5500 const struct smb_filename *smb_fname_old,
5501 struct smb_filename *smb_fname_new)
5503 NTSTATUS status = NT_STATUS_OK;
5505 /* source must already exist. */
5506 if (!VALID_STAT(smb_fname_old->st)) {
5507 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5510 if (VALID_STAT(smb_fname_new->st)) {
5511 if (overwrite_if_exists) {
5512 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5513 return NT_STATUS_FILE_IS_A_DIRECTORY;
5515 status = unlink_internals(conn,
5516 req,
5517 FILE_ATTRIBUTE_NORMAL,
5518 smb_fname_new,
5519 false);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 return status;
5523 } else {
5524 /* Disallow if newname already exists. */
5525 return NT_STATUS_OBJECT_NAME_COLLISION;
5529 /* No links from a directory. */
5530 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5531 return NT_STATUS_FILE_IS_A_DIRECTORY;
5534 /* Setting a hardlink to/from a stream isn't currently supported. */
5535 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5536 is_ntfs_stream_smb_fname(smb_fname_new)) {
5537 return NT_STATUS_INVALID_PARAMETER;
5540 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5541 smb_fname_old->base_name, smb_fname_new->base_name));
5543 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5544 smb_fname_new->base_name) != 0) {
5545 status = map_nt_error_from_unix(errno);
5546 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5547 nt_errstr(status), smb_fname_old->base_name,
5548 smb_fname_new->base_name));
5550 return status;
5553 /****************************************************************************
5554 Deal with setting the time from any of the setfilepathinfo functions.
5555 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5556 calling this function.
5557 ****************************************************************************/
5559 NTSTATUS smb_set_file_time(connection_struct *conn,
5560 files_struct *fsp,
5561 const struct smb_filename *smb_fname,
5562 struct smb_file_time *ft,
5563 bool setting_write_time)
5565 struct smb_filename smb_fname_base;
5566 uint32 action =
5567 FILE_NOTIFY_CHANGE_LAST_ACCESS
5568 |FILE_NOTIFY_CHANGE_LAST_WRITE
5569 |FILE_NOTIFY_CHANGE_CREATION;
5571 if (!VALID_STAT(smb_fname->st)) {
5572 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5575 /* get some defaults (no modifications) if any info is zero or -1. */
5576 if (null_timespec(ft->create_time)) {
5577 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5580 if (null_timespec(ft->atime)) {
5581 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5584 if (null_timespec(ft->mtime)) {
5585 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5588 if (!setting_write_time) {
5589 /* ft->mtime comes from change time, not write time. */
5590 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5593 /* Ensure the resolution is the correct for
5594 * what we can store on this filesystem. */
5596 round_timespec(conn->ts_res, &ft->create_time);
5597 round_timespec(conn->ts_res, &ft->ctime);
5598 round_timespec(conn->ts_res, &ft->atime);
5599 round_timespec(conn->ts_res, &ft->mtime);
5601 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5602 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5603 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5604 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5605 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5606 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5607 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5608 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5610 if (setting_write_time) {
5612 * This was a Windows setfileinfo on an open file.
5613 * NT does this a lot. We also need to
5614 * set the time here, as it can be read by
5615 * FindFirst/FindNext and with the patch for bug #2045
5616 * in smbd/fileio.c it ensures that this timestamp is
5617 * kept sticky even after a write. We save the request
5618 * away and will set it on file close and after a write. JRA.
5621 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5622 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5624 if (fsp != NULL) {
5625 if (fsp->base_fsp) {
5626 set_sticky_write_time_fsp(fsp->base_fsp,
5627 ft->mtime);
5628 } else {
5629 set_sticky_write_time_fsp(fsp, ft->mtime);
5631 } else {
5632 set_sticky_write_time_path(
5633 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5634 ft->mtime);
5638 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5640 /* Always call ntimes on the base, even if a stream was passed in. */
5641 smb_fname_base = *smb_fname;
5642 smb_fname_base.stream_name = NULL;
5644 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5645 return map_nt_error_from_unix(errno);
5648 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5649 smb_fname->base_name);
5650 return NT_STATUS_OK;
5653 /****************************************************************************
5654 Deal with setting the dosmode from any of the setfilepathinfo functions.
5655 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5656 done before calling this function.
5657 ****************************************************************************/
5659 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5660 const struct smb_filename *smb_fname,
5661 uint32 dosmode)
5663 struct smb_filename *smb_fname_base = NULL;
5664 NTSTATUS status;
5666 if (!VALID_STAT(smb_fname->st)) {
5667 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5670 /* Always operate on the base_name, even if a stream was passed in. */
5671 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5672 NULL, &smb_fname->st,
5673 &smb_fname_base);
5674 if (!NT_STATUS_IS_OK(status)) {
5675 return status;
5678 if (dosmode) {
5679 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5680 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5681 } else {
5682 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5686 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5688 /* check the mode isn't different, before changing it */
5689 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5690 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5691 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5692 (unsigned int)dosmode));
5694 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5695 false)) {
5696 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5697 "%s failed (%s)\n",
5698 smb_fname_str_dbg(smb_fname_base),
5699 strerror(errno)));
5700 status = map_nt_error_from_unix(errno);
5701 goto out;
5704 status = NT_STATUS_OK;
5705 out:
5706 TALLOC_FREE(smb_fname_base);
5707 return status;
5710 /****************************************************************************
5711 Deal with setting the size from any of the setfilepathinfo functions.
5712 ****************************************************************************/
5714 static NTSTATUS smb_set_file_size(connection_struct *conn,
5715 struct smb_request *req,
5716 files_struct *fsp,
5717 const struct smb_filename *smb_fname,
5718 const SMB_STRUCT_STAT *psbuf,
5719 off_t size,
5720 bool fail_after_createfile)
5722 NTSTATUS status = NT_STATUS_OK;
5723 struct smb_filename *smb_fname_tmp = NULL;
5724 files_struct *new_fsp = NULL;
5726 if (!VALID_STAT(*psbuf)) {
5727 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5730 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5732 if (size == get_file_size_stat(psbuf)) {
5733 return NT_STATUS_OK;
5736 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5737 smb_fname_str_dbg(smb_fname), (double)size));
5739 if (fsp && fsp->fh->fd != -1) {
5740 /* Handle based call. */
5741 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5742 return NT_STATUS_ACCESS_DENIED;
5745 if (vfs_set_filelen(fsp, size) == -1) {
5746 return map_nt_error_from_unix(errno);
5748 trigger_write_time_update_immediate(fsp);
5749 return NT_STATUS_OK;
5752 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 return status;
5757 smb_fname_tmp->st = *psbuf;
5759 status = SMB_VFS_CREATE_FILE(
5760 conn, /* conn */
5761 req, /* req */
5762 0, /* root_dir_fid */
5763 smb_fname_tmp, /* fname */
5764 FILE_WRITE_DATA, /* access_mask */
5765 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5766 FILE_SHARE_DELETE),
5767 FILE_OPEN, /* create_disposition*/
5768 0, /* create_options */
5769 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5770 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5771 0, /* allocation_size */
5772 0, /* private_flags */
5773 NULL, /* sd */
5774 NULL, /* ea_list */
5775 &new_fsp, /* result */
5776 NULL); /* pinfo */
5778 TALLOC_FREE(smb_fname_tmp);
5780 if (!NT_STATUS_IS_OK(status)) {
5781 /* NB. We check for open_was_deferred in the caller. */
5782 return status;
5785 /* See RAW-SFILEINFO-END-OF-FILE */
5786 if (fail_after_createfile) {
5787 close_file(req, new_fsp,NORMAL_CLOSE);
5788 return NT_STATUS_INVALID_LEVEL;
5791 if (vfs_set_filelen(new_fsp, size) == -1) {
5792 status = map_nt_error_from_unix(errno);
5793 close_file(req, new_fsp,NORMAL_CLOSE);
5794 return status;
5797 trigger_write_time_update_immediate(new_fsp);
5798 close_file(req, new_fsp,NORMAL_CLOSE);
5799 return NT_STATUS_OK;
5802 /****************************************************************************
5803 Deal with SMB_INFO_SET_EA.
5804 ****************************************************************************/
5806 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5807 const char *pdata,
5808 int total_data,
5809 files_struct *fsp,
5810 const struct smb_filename *smb_fname)
5812 struct ea_list *ea_list = NULL;
5813 TALLOC_CTX *ctx = NULL;
5814 NTSTATUS status = NT_STATUS_OK;
5816 if (total_data < 10) {
5818 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5819 length. They seem to have no effect. Bug #3212. JRA */
5821 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5822 /* We're done. We only get EA info in this call. */
5823 return NT_STATUS_OK;
5826 return NT_STATUS_INVALID_PARAMETER;
5829 if (IVAL(pdata,0) > total_data) {
5830 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5831 IVAL(pdata,0), (unsigned int)total_data));
5832 return NT_STATUS_INVALID_PARAMETER;
5835 ctx = talloc_tos();
5836 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5837 if (!ea_list) {
5838 return NT_STATUS_INVALID_PARAMETER;
5841 status = set_ea(conn, fsp, smb_fname, ea_list);
5843 return status;
5846 /****************************************************************************
5847 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5848 ****************************************************************************/
5850 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5851 const char *pdata,
5852 int total_data,
5853 files_struct *fsp)
5855 struct ea_list *ea_list = NULL;
5856 NTSTATUS status;
5858 if (!fsp) {
5859 return NT_STATUS_INVALID_HANDLE;
5862 if (!lp_ea_support(SNUM(conn))) {
5863 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5864 "EA's not supported.\n",
5865 (unsigned int)total_data));
5866 return NT_STATUS_EAS_NOT_SUPPORTED;
5869 if (total_data < 10) {
5870 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5871 "too small.\n",
5872 (unsigned int)total_data));
5873 return NT_STATUS_INVALID_PARAMETER;
5876 ea_list = read_nttrans_ea_list(talloc_tos(),
5877 pdata,
5878 total_data);
5880 if (!ea_list) {
5881 return NT_STATUS_INVALID_PARAMETER;
5884 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5886 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5887 smb_fname_str_dbg(fsp->fsp_name),
5888 nt_errstr(status) ));
5890 return status;
5894 /****************************************************************************
5895 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5896 ****************************************************************************/
5898 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5899 const char *pdata,
5900 int total_data,
5901 files_struct *fsp,
5902 struct smb_filename *smb_fname)
5904 NTSTATUS status = NT_STATUS_OK;
5905 bool delete_on_close;
5906 uint32 dosmode = 0;
5908 if (total_data < 1) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 if (fsp == NULL) {
5913 return NT_STATUS_INVALID_HANDLE;
5916 delete_on_close = (CVAL(pdata,0) ? True : False);
5917 dosmode = dos_mode(conn, smb_fname);
5919 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5920 "delete_on_close = %u\n",
5921 smb_fname_str_dbg(smb_fname),
5922 (unsigned int)dosmode,
5923 (unsigned int)delete_on_close ));
5925 if (delete_on_close) {
5926 status = can_set_delete_on_close(fsp, dosmode);
5927 if (!NT_STATUS_IS_OK(status)) {
5928 return status;
5932 /* The set is across all open files on this dev/inode pair. */
5933 if (!set_delete_on_close(fsp, delete_on_close,
5934 conn->session_info->security_token,
5935 conn->session_info->unix_token)) {
5936 return NT_STATUS_ACCESS_DENIED;
5938 return NT_STATUS_OK;
5941 /****************************************************************************
5942 Deal with SMB_FILE_POSITION_INFORMATION.
5943 ****************************************************************************/
5945 static NTSTATUS smb_file_position_information(connection_struct *conn,
5946 const char *pdata,
5947 int total_data,
5948 files_struct *fsp)
5950 uint64_t position_information;
5952 if (total_data < 8) {
5953 return NT_STATUS_INVALID_PARAMETER;
5956 if (fsp == NULL) {
5957 /* Ignore on pathname based set. */
5958 return NT_STATUS_OK;
5961 position_information = (uint64_t)IVAL(pdata,0);
5962 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5964 DEBUG(10,("smb_file_position_information: Set file position "
5965 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5966 (double)position_information));
5967 fsp->fh->position_information = position_information;
5968 return NT_STATUS_OK;
5971 /****************************************************************************
5972 Deal with SMB_FILE_MODE_INFORMATION.
5973 ****************************************************************************/
5975 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5976 const char *pdata,
5977 int total_data)
5979 uint32 mode;
5981 if (total_data < 4) {
5982 return NT_STATUS_INVALID_PARAMETER;
5984 mode = IVAL(pdata,0);
5985 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5986 return NT_STATUS_INVALID_PARAMETER;
5988 return NT_STATUS_OK;
5991 /****************************************************************************
5992 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5993 ****************************************************************************/
5995 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5996 struct smb_request *req,
5997 const char *pdata,
5998 int total_data,
5999 const struct smb_filename *smb_fname)
6001 char *link_target = NULL;
6002 const char *newname = smb_fname->base_name;
6003 TALLOC_CTX *ctx = talloc_tos();
6005 /* Set a symbolic link. */
6006 /* Don't allow this if follow links is false. */
6008 if (total_data == 0) {
6009 return NT_STATUS_INVALID_PARAMETER;
6012 if (!lp_symlinks(SNUM(conn))) {
6013 return NT_STATUS_ACCESS_DENIED;
6016 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6017 total_data, STR_TERMINATE);
6019 if (!link_target) {
6020 return NT_STATUS_INVALID_PARAMETER;
6023 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6024 newname, link_target ));
6026 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6027 return map_nt_error_from_unix(errno);
6030 return NT_STATUS_OK;
6033 /****************************************************************************
6034 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6035 ****************************************************************************/
6037 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6038 struct smb_request *req,
6039 const char *pdata, int total_data,
6040 struct smb_filename *smb_fname_new)
6042 char *oldname = NULL;
6043 struct smb_filename *smb_fname_old = NULL;
6044 TALLOC_CTX *ctx = talloc_tos();
6045 NTSTATUS status = NT_STATUS_OK;
6047 /* Set a hard link. */
6048 if (total_data == 0) {
6049 return NT_STATUS_INVALID_PARAMETER;
6052 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6053 total_data, STR_TERMINATE, &status);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 return status;
6058 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6059 smb_fname_str_dbg(smb_fname_new), oldname));
6061 status = filename_convert(ctx,
6062 conn,
6063 req->flags2 & FLAGS2_DFS_PATHNAMES,
6064 oldname,
6066 NULL,
6067 &smb_fname_old);
6068 if (!NT_STATUS_IS_OK(status)) {
6069 return status;
6072 return hardlink_internals(ctx, conn, req, false,
6073 smb_fname_old, smb_fname_new);
6076 /****************************************************************************
6077 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6078 ****************************************************************************/
6080 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6081 struct smb_request *req,
6082 const char *pdata,
6083 int total_data,
6084 files_struct *fsp,
6085 struct smb_filename *smb_fname_src)
6087 bool overwrite;
6088 uint32_t len;
6089 char *newname = NULL;
6090 struct smb_filename *smb_fname_dst = NULL;
6091 NTSTATUS status = NT_STATUS_OK;
6092 TALLOC_CTX *ctx = talloc_tos();
6094 if (!fsp) {
6095 return NT_STATUS_INVALID_HANDLE;
6098 if (total_data < 20) {
6099 return NT_STATUS_INVALID_PARAMETER;
6102 overwrite = (CVAL(pdata,0) ? True : False);
6103 len = IVAL(pdata,16);
6105 if (len > (total_data - 20) || (len == 0)) {
6106 return NT_STATUS_INVALID_PARAMETER;
6109 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6110 &pdata[20], len, STR_TERMINATE,
6111 &status);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 return status;
6116 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6117 newname));
6119 status = filename_convert(ctx,
6120 conn,
6121 req->flags2 & FLAGS2_DFS_PATHNAMES,
6122 newname,
6123 UCF_SAVE_LCOMP,
6124 NULL,
6125 &smb_fname_dst);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return status;
6130 if (fsp->base_fsp) {
6131 /* newname must be a stream name. */
6132 if (newname[0] != ':') {
6133 return NT_STATUS_NOT_SUPPORTED;
6136 /* Create an smb_fname to call rename_internals_fsp() with. */
6137 status = create_synthetic_smb_fname(talloc_tos(),
6138 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6139 &smb_fname_dst);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 goto out;
6145 * Set the original last component, since
6146 * rename_internals_fsp() requires it.
6148 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6149 newname);
6150 if (smb_fname_dst->original_lcomp == NULL) {
6151 status = NT_STATUS_NO_MEMORY;
6152 goto out;
6157 DEBUG(10,("smb2_file_rename_information: "
6158 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6159 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6160 smb_fname_str_dbg(smb_fname_dst)));
6161 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6162 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6163 overwrite);
6165 out:
6166 TALLOC_FREE(smb_fname_dst);
6167 return status;
6170 static NTSTATUS smb_file_link_information(connection_struct *conn,
6171 struct smb_request *req,
6172 const char *pdata,
6173 int total_data,
6174 files_struct *fsp,
6175 struct smb_filename *smb_fname_src)
6177 bool overwrite;
6178 uint32_t len;
6179 char *newname = NULL;
6180 struct smb_filename *smb_fname_dst = NULL;
6181 NTSTATUS status = NT_STATUS_OK;
6182 TALLOC_CTX *ctx = talloc_tos();
6184 if (!fsp) {
6185 return NT_STATUS_INVALID_HANDLE;
6188 if (total_data < 20) {
6189 return NT_STATUS_INVALID_PARAMETER;
6192 overwrite = (CVAL(pdata,0) ? true : false);
6193 len = IVAL(pdata,16);
6195 if (len > (total_data - 20) || (len == 0)) {
6196 return NT_STATUS_INVALID_PARAMETER;
6199 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6200 &pdata[20], len, STR_TERMINATE,
6201 &status);
6202 if (!NT_STATUS_IS_OK(status)) {
6203 return status;
6206 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6207 newname));
6209 status = filename_convert(ctx,
6210 conn,
6211 req->flags2 & FLAGS2_DFS_PATHNAMES,
6212 newname,
6213 UCF_SAVE_LCOMP,
6214 NULL,
6215 &smb_fname_dst);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 return status;
6220 if (fsp->base_fsp) {
6221 /* No stream names. */
6222 return NT_STATUS_NOT_SUPPORTED;
6225 DEBUG(10,("smb_file_link_information: "
6226 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6227 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6228 smb_fname_str_dbg(smb_fname_dst)));
6229 status = hardlink_internals(ctx,
6230 conn,
6231 req,
6232 overwrite,
6233 fsp->fsp_name,
6234 smb_fname_dst);
6236 TALLOC_FREE(smb_fname_dst);
6237 return status;
6240 /****************************************************************************
6241 Deal with SMB_FILE_RENAME_INFORMATION.
6242 ****************************************************************************/
6244 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6245 struct smb_request *req,
6246 const char *pdata,
6247 int total_data,
6248 files_struct *fsp,
6249 struct smb_filename *smb_fname_src)
6251 bool overwrite;
6252 uint32 root_fid;
6253 uint32 len;
6254 char *newname = NULL;
6255 struct smb_filename *smb_fname_dst = NULL;
6256 bool dest_has_wcard = False;
6257 NTSTATUS status = NT_STATUS_OK;
6258 char *p;
6259 TALLOC_CTX *ctx = talloc_tos();
6261 if (total_data < 13) {
6262 return NT_STATUS_INVALID_PARAMETER;
6265 overwrite = (CVAL(pdata,0) ? True : False);
6266 root_fid = IVAL(pdata,4);
6267 len = IVAL(pdata,8);
6269 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6270 return NT_STATUS_INVALID_PARAMETER;
6273 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6274 len, 0, &status,
6275 &dest_has_wcard);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 return status;
6280 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6281 newname));
6283 status = resolve_dfspath_wcard(ctx, conn,
6284 req->flags2 & FLAGS2_DFS_PATHNAMES,
6285 newname,
6286 true,
6287 !conn->sconn->using_smb2,
6288 &newname,
6289 &dest_has_wcard);
6290 if (!NT_STATUS_IS_OK(status)) {
6291 return status;
6294 /* Check the new name has no '/' characters. */
6295 if (strchr_m(newname, '/')) {
6296 return NT_STATUS_NOT_SUPPORTED;
6299 if (fsp && fsp->base_fsp) {
6300 /* newname must be a stream name. */
6301 if (newname[0] != ':') {
6302 return NT_STATUS_NOT_SUPPORTED;
6305 /* Create an smb_fname to call rename_internals_fsp() with. */
6306 status = create_synthetic_smb_fname(talloc_tos(),
6307 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6308 &smb_fname_dst);
6309 if (!NT_STATUS_IS_OK(status)) {
6310 goto out;
6314 * Set the original last component, since
6315 * rename_internals_fsp() requires it.
6317 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6318 newname);
6319 if (smb_fname_dst->original_lcomp == NULL) {
6320 status = NT_STATUS_NO_MEMORY;
6321 goto out;
6324 } else {
6326 * Build up an smb_fname_dst based on the filename passed in.
6327 * We basically just strip off the last component, and put on
6328 * the newname instead.
6330 char *base_name = NULL;
6332 /* newname must *not* be a stream name. */
6333 if (newname[0] == ':') {
6334 return NT_STATUS_NOT_SUPPORTED;
6338 * Strip off the last component (filename) of the path passed
6339 * in.
6341 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6342 if (!base_name) {
6343 return NT_STATUS_NO_MEMORY;
6345 p = strrchr_m(base_name, '/');
6346 if (p) {
6347 p[1] = '\0';
6348 } else {
6349 base_name = talloc_strdup(ctx, "");
6350 if (!base_name) {
6351 return NT_STATUS_NO_MEMORY;
6354 /* Append the new name. */
6355 base_name = talloc_asprintf_append(base_name,
6356 "%s",
6357 newname);
6358 if (!base_name) {
6359 return NT_STATUS_NO_MEMORY;
6362 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6363 (UCF_SAVE_LCOMP |
6364 (dest_has_wcard ?
6365 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6366 0)));
6368 /* If an error we expect this to be
6369 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6371 if (!NT_STATUS_IS_OK(status)) {
6372 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6373 status)) {
6374 goto out;
6376 /* Create an smb_fname to call rename_internals_fsp() */
6377 status = create_synthetic_smb_fname(ctx,
6378 base_name, NULL,
6379 NULL,
6380 &smb_fname_dst);
6381 if (!NT_STATUS_IS_OK(status)) {
6382 goto out;
6387 if (fsp) {
6388 DEBUG(10,("smb_file_rename_information: "
6389 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6390 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6391 smb_fname_str_dbg(smb_fname_dst)));
6392 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6393 overwrite);
6394 } else {
6395 DEBUG(10,("smb_file_rename_information: "
6396 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6397 smb_fname_str_dbg(smb_fname_src),
6398 smb_fname_str_dbg(smb_fname_dst)));
6399 status = rename_internals(ctx, conn, req, smb_fname_src,
6400 smb_fname_dst, 0, overwrite, false,
6401 dest_has_wcard,
6402 FILE_WRITE_ATTRIBUTES);
6404 out:
6405 TALLOC_FREE(smb_fname_dst);
6406 return status;
6409 /****************************************************************************
6410 Deal with SMB_SET_POSIX_ACL.
6411 ****************************************************************************/
6413 #if defined(HAVE_POSIX_ACLS)
6414 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6415 const char *pdata,
6416 int total_data,
6417 files_struct *fsp,
6418 const struct smb_filename *smb_fname)
6420 uint16 posix_acl_version;
6421 uint16 num_file_acls;
6422 uint16 num_def_acls;
6423 bool valid_file_acls = True;
6424 bool valid_def_acls = True;
6426 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6427 return NT_STATUS_INVALID_PARAMETER;
6429 posix_acl_version = SVAL(pdata,0);
6430 num_file_acls = SVAL(pdata,2);
6431 num_def_acls = SVAL(pdata,4);
6433 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6434 valid_file_acls = False;
6435 num_file_acls = 0;
6438 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6439 valid_def_acls = False;
6440 num_def_acls = 0;
6443 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6444 return NT_STATUS_INVALID_PARAMETER;
6447 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6448 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6449 return NT_STATUS_INVALID_PARAMETER;
6452 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6453 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6454 (unsigned int)num_file_acls,
6455 (unsigned int)num_def_acls));
6457 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6458 smb_fname->base_name, num_file_acls,
6459 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6460 return map_nt_error_from_unix(errno);
6463 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6464 smb_fname->base_name, &smb_fname->st, num_def_acls,
6465 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6466 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6467 return map_nt_error_from_unix(errno);
6469 return NT_STATUS_OK;
6471 #endif
6473 /****************************************************************************
6474 Deal with SMB_SET_POSIX_LOCK.
6475 ****************************************************************************/
6477 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6478 struct smb_request *req,
6479 const char *pdata,
6480 int total_data,
6481 files_struct *fsp)
6483 uint64_t count;
6484 uint64_t offset;
6485 uint64_t smblctx;
6486 bool blocking_lock = False;
6487 enum brl_type lock_type;
6489 NTSTATUS status = NT_STATUS_OK;
6491 if (fsp == NULL || fsp->fh->fd == -1) {
6492 return NT_STATUS_INVALID_HANDLE;
6495 if (total_data != POSIX_LOCK_DATA_SIZE) {
6496 return NT_STATUS_INVALID_PARAMETER;
6499 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6500 case POSIX_LOCK_TYPE_READ:
6501 lock_type = READ_LOCK;
6502 break;
6503 case POSIX_LOCK_TYPE_WRITE:
6504 /* Return the right POSIX-mappable error code for files opened read-only. */
6505 if (!fsp->can_write) {
6506 return NT_STATUS_INVALID_HANDLE;
6508 lock_type = WRITE_LOCK;
6509 break;
6510 case POSIX_LOCK_TYPE_UNLOCK:
6511 lock_type = UNLOCK_LOCK;
6512 break;
6513 default:
6514 return NT_STATUS_INVALID_PARAMETER;
6517 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6518 blocking_lock = False;
6519 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6520 blocking_lock = True;
6521 } else {
6522 return NT_STATUS_INVALID_PARAMETER;
6525 if (!lp_blocking_locks(SNUM(conn))) {
6526 blocking_lock = False;
6529 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6530 #if defined(HAVE_LONGLONG)
6531 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6532 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6533 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6534 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6535 #else /* HAVE_LONGLONG */
6536 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6537 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6538 #endif /* HAVE_LONGLONG */
6540 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6541 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6542 fsp_str_dbg(fsp),
6543 (unsigned int)lock_type,
6544 (unsigned long long)smblctx,
6545 (double)count,
6546 (double)offset ));
6548 if (lock_type == UNLOCK_LOCK) {
6549 status = do_unlock(req->sconn->msg_ctx,
6550 fsp,
6551 smblctx,
6552 count,
6553 offset,
6554 POSIX_LOCK);
6555 } else {
6556 uint64_t block_smblctx;
6558 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6559 fsp,
6560 smblctx,
6561 count,
6562 offset,
6563 lock_type,
6564 POSIX_LOCK,
6565 blocking_lock,
6566 &status,
6567 &block_smblctx,
6568 NULL);
6570 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6572 * A blocking lock was requested. Package up
6573 * this smb into a queued request and push it
6574 * onto the blocking lock queue.
6576 if(push_blocking_lock_request(br_lck,
6577 req,
6578 fsp,
6579 -1, /* infinite timeout. */
6581 smblctx,
6582 lock_type,
6583 POSIX_LOCK,
6584 offset,
6585 count,
6586 block_smblctx)) {
6587 TALLOC_FREE(br_lck);
6588 return status;
6591 TALLOC_FREE(br_lck);
6594 return status;
6597 /****************************************************************************
6598 Deal with SMB_SET_FILE_BASIC_INFO.
6599 ****************************************************************************/
6601 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6602 const char *pdata,
6603 int total_data,
6604 files_struct *fsp,
6605 const struct smb_filename *smb_fname)
6607 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6608 struct smb_file_time ft;
6609 uint32 dosmode = 0;
6610 NTSTATUS status = NT_STATUS_OK;
6612 ZERO_STRUCT(ft);
6614 if (total_data < 36) {
6615 return NT_STATUS_INVALID_PARAMETER;
6618 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6619 if (!NT_STATUS_IS_OK(status)) {
6620 return status;
6623 /* Set the attributes */
6624 dosmode = IVAL(pdata,32);
6625 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6626 if (!NT_STATUS_IS_OK(status)) {
6627 return status;
6630 /* create time */
6631 ft.create_time = interpret_long_date(pdata);
6633 /* access time */
6634 ft.atime = interpret_long_date(pdata+8);
6636 /* write time. */
6637 ft.mtime = interpret_long_date(pdata+16);
6639 /* change time. */
6640 ft.ctime = interpret_long_date(pdata+24);
6642 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6643 smb_fname_str_dbg(smb_fname)));
6645 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6646 true);
6649 /****************************************************************************
6650 Deal with SMB_INFO_STANDARD.
6651 ****************************************************************************/
6653 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6654 const char *pdata,
6655 int total_data,
6656 files_struct *fsp,
6657 const struct smb_filename *smb_fname)
6659 NTSTATUS status;
6660 struct smb_file_time ft;
6662 ZERO_STRUCT(ft);
6664 if (total_data < 12) {
6665 return NT_STATUS_INVALID_PARAMETER;
6668 /* create time */
6669 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6670 /* access time */
6671 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6672 /* write time */
6673 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6675 DEBUG(10,("smb_set_info_standard: file %s\n",
6676 smb_fname_str_dbg(smb_fname)));
6678 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 return status;
6683 return smb_set_file_time(conn,
6684 fsp,
6685 smb_fname,
6686 &ft,
6687 true);
6690 /****************************************************************************
6691 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6692 ****************************************************************************/
6694 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6695 struct smb_request *req,
6696 const char *pdata,
6697 int total_data,
6698 files_struct *fsp,
6699 struct smb_filename *smb_fname)
6701 uint64_t allocation_size = 0;
6702 NTSTATUS status = NT_STATUS_OK;
6703 files_struct *new_fsp = NULL;
6705 if (!VALID_STAT(smb_fname->st)) {
6706 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6709 if (total_data < 8) {
6710 return NT_STATUS_INVALID_PARAMETER;
6713 allocation_size = (uint64_t)IVAL(pdata,0);
6714 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6715 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6716 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6717 (double)allocation_size));
6719 if (allocation_size) {
6720 allocation_size = smb_roundup(conn, allocation_size);
6723 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6724 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6725 (double)allocation_size));
6727 if (fsp && fsp->fh->fd != -1) {
6728 /* Open file handle. */
6729 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6730 return NT_STATUS_ACCESS_DENIED;
6733 /* Only change if needed. */
6734 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6735 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6736 return map_nt_error_from_unix(errno);
6739 /* But always update the time. */
6741 * This is equivalent to a write. Ensure it's seen immediately
6742 * if there are no pending writes.
6744 trigger_write_time_update_immediate(fsp);
6745 return NT_STATUS_OK;
6748 /* Pathname or stat or directory file. */
6749 status = SMB_VFS_CREATE_FILE(
6750 conn, /* conn */
6751 req, /* req */
6752 0, /* root_dir_fid */
6753 smb_fname, /* fname */
6754 FILE_WRITE_DATA, /* access_mask */
6755 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6756 FILE_SHARE_DELETE),
6757 FILE_OPEN, /* create_disposition*/
6758 0, /* create_options */
6759 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6760 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6761 0, /* allocation_size */
6762 0, /* private_flags */
6763 NULL, /* sd */
6764 NULL, /* ea_list */
6765 &new_fsp, /* result */
6766 NULL); /* pinfo */
6768 if (!NT_STATUS_IS_OK(status)) {
6769 /* NB. We check for open_was_deferred in the caller. */
6770 return status;
6773 /* Only change if needed. */
6774 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6775 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6776 status = map_nt_error_from_unix(errno);
6777 close_file(req, new_fsp, NORMAL_CLOSE);
6778 return status;
6782 /* Changing the allocation size should set the last mod time. */
6784 * This is equivalent to a write. Ensure it's seen immediately
6785 * if there are no pending writes.
6787 trigger_write_time_update_immediate(new_fsp);
6789 close_file(req, new_fsp, NORMAL_CLOSE);
6790 return NT_STATUS_OK;
6793 /****************************************************************************
6794 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6795 ****************************************************************************/
6797 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6798 struct smb_request *req,
6799 const char *pdata,
6800 int total_data,
6801 files_struct *fsp,
6802 const struct smb_filename *smb_fname,
6803 bool fail_after_createfile)
6805 off_t size;
6807 if (total_data < 8) {
6808 return NT_STATUS_INVALID_PARAMETER;
6811 size = IVAL(pdata,0);
6812 size |= (((off_t)IVAL(pdata,4)) << 32);
6813 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6814 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6815 (double)size));
6817 return smb_set_file_size(conn, req,
6818 fsp,
6819 smb_fname,
6820 &smb_fname->st,
6821 size,
6822 fail_after_createfile);
6825 /****************************************************************************
6826 Allow a UNIX info mknod.
6827 ****************************************************************************/
6829 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6830 const char *pdata,
6831 int total_data,
6832 const struct smb_filename *smb_fname)
6834 uint32 file_type = IVAL(pdata,56);
6835 #if defined(HAVE_MAKEDEV)
6836 uint32 dev_major = IVAL(pdata,60);
6837 uint32 dev_minor = IVAL(pdata,68);
6838 #endif
6839 SMB_DEV_T dev = (SMB_DEV_T)0;
6840 uint32 raw_unixmode = IVAL(pdata,84);
6841 NTSTATUS status;
6842 mode_t unixmode;
6844 if (total_data < 100) {
6845 return NT_STATUS_INVALID_PARAMETER;
6848 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6849 PERM_NEW_FILE, &unixmode);
6850 if (!NT_STATUS_IS_OK(status)) {
6851 return status;
6854 #if defined(HAVE_MAKEDEV)
6855 dev = makedev(dev_major, dev_minor);
6856 #endif
6858 switch (file_type) {
6859 #if defined(S_IFIFO)
6860 case UNIX_TYPE_FIFO:
6861 unixmode |= S_IFIFO;
6862 break;
6863 #endif
6864 #if defined(S_IFSOCK)
6865 case UNIX_TYPE_SOCKET:
6866 unixmode |= S_IFSOCK;
6867 break;
6868 #endif
6869 #if defined(S_IFCHR)
6870 case UNIX_TYPE_CHARDEV:
6871 unixmode |= S_IFCHR;
6872 break;
6873 #endif
6874 #if defined(S_IFBLK)
6875 case UNIX_TYPE_BLKDEV:
6876 unixmode |= S_IFBLK;
6877 break;
6878 #endif
6879 default:
6880 return NT_STATUS_INVALID_PARAMETER;
6883 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6884 "%.0f mode 0%o for file %s\n", (double)dev,
6885 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6887 /* Ok - do the mknod. */
6888 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6889 return map_nt_error_from_unix(errno);
6892 /* If any of the other "set" calls fail we
6893 * don't want to end up with a half-constructed mknod.
6896 if (lp_inherit_perms(SNUM(conn))) {
6897 char *parent;
6898 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6899 &parent, NULL)) {
6900 return NT_STATUS_NO_MEMORY;
6902 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6903 unixmode);
6904 TALLOC_FREE(parent);
6907 return NT_STATUS_OK;
6910 /****************************************************************************
6911 Deal with SMB_SET_FILE_UNIX_BASIC.
6912 ****************************************************************************/
6914 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6915 struct smb_request *req,
6916 const char *pdata,
6917 int total_data,
6918 files_struct *fsp,
6919 const struct smb_filename *smb_fname)
6921 struct smb_file_time ft;
6922 uint32 raw_unixmode;
6923 mode_t unixmode;
6924 off_t size = 0;
6925 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6926 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6927 NTSTATUS status = NT_STATUS_OK;
6928 bool delete_on_fail = False;
6929 enum perm_type ptype;
6930 files_struct *all_fsps = NULL;
6931 bool modify_mtime = true;
6932 struct file_id id;
6933 struct smb_filename *smb_fname_tmp = NULL;
6934 SMB_STRUCT_STAT sbuf;
6936 ZERO_STRUCT(ft);
6938 if (total_data < 100) {
6939 return NT_STATUS_INVALID_PARAMETER;
6942 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6943 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6944 size=IVAL(pdata,0); /* first 8 Bytes are size */
6945 size |= (((off_t)IVAL(pdata,4)) << 32);
6948 ft.atime = interpret_long_date(pdata+24); /* access_time */
6949 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6950 set_owner = (uid_t)IVAL(pdata,40);
6951 set_grp = (gid_t)IVAL(pdata,48);
6952 raw_unixmode = IVAL(pdata,84);
6954 if (VALID_STAT(smb_fname->st)) {
6955 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6956 ptype = PERM_EXISTING_DIR;
6957 } else {
6958 ptype = PERM_EXISTING_FILE;
6960 } else {
6961 ptype = PERM_NEW_FILE;
6964 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6965 ptype, &unixmode);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 return status;
6970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6971 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6972 smb_fname_str_dbg(smb_fname), (double)size,
6973 (unsigned int)set_owner, (unsigned int)set_grp,
6974 (int)raw_unixmode));
6976 sbuf = smb_fname->st;
6978 if (!VALID_STAT(sbuf)) {
6980 * The only valid use of this is to create character and block
6981 * devices, and named pipes. This is deprecated (IMHO) and
6982 * a new info level should be used for mknod. JRA.
6985 status = smb_unix_mknod(conn,
6986 pdata,
6987 total_data,
6988 smb_fname);
6989 if (!NT_STATUS_IS_OK(status)) {
6990 return status;
6993 status = copy_smb_filename(talloc_tos(), smb_fname,
6994 &smb_fname_tmp);
6995 if (!NT_STATUS_IS_OK(status)) {
6996 return status;
6999 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7000 status = map_nt_error_from_unix(errno);
7001 TALLOC_FREE(smb_fname_tmp);
7002 SMB_VFS_UNLINK(conn, smb_fname);
7003 return status;
7006 sbuf = smb_fname_tmp->st;
7007 smb_fname = smb_fname_tmp;
7009 /* Ensure we don't try and change anything else. */
7010 raw_unixmode = SMB_MODE_NO_CHANGE;
7011 size = get_file_size_stat(&sbuf);
7012 ft.atime = sbuf.st_ex_atime;
7013 ft.mtime = sbuf.st_ex_mtime;
7015 * We continue here as we might want to change the
7016 * owner uid/gid.
7018 delete_on_fail = True;
7021 #if 1
7022 /* Horrible backwards compatibility hack as an old server bug
7023 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7024 * */
7026 if (!size) {
7027 size = get_file_size_stat(&sbuf);
7029 #endif
7032 * Deal with the UNIX specific mode set.
7035 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7036 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7037 "setting mode 0%o for file %s\n",
7038 (unsigned int)unixmode,
7039 smb_fname_str_dbg(smb_fname)));
7040 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7041 return map_nt_error_from_unix(errno);
7046 * Deal with the UNIX specific uid set.
7049 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7050 (sbuf.st_ex_uid != set_owner)) {
7051 int ret;
7053 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7054 "changing owner %u for path %s\n",
7055 (unsigned int)set_owner,
7056 smb_fname_str_dbg(smb_fname)));
7058 if (S_ISLNK(sbuf.st_ex_mode)) {
7059 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7060 set_owner, (gid_t)-1);
7061 } else {
7062 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7063 set_owner, (gid_t)-1);
7066 if (ret != 0) {
7067 status = map_nt_error_from_unix(errno);
7068 if (delete_on_fail) {
7069 SMB_VFS_UNLINK(conn, smb_fname);
7071 return status;
7076 * Deal with the UNIX specific gid set.
7079 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7080 (sbuf.st_ex_gid != set_grp)) {
7081 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7082 "changing group %u for file %s\n",
7083 (unsigned int)set_owner,
7084 smb_fname_str_dbg(smb_fname)));
7085 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7086 set_grp) != 0) {
7087 status = map_nt_error_from_unix(errno);
7088 if (delete_on_fail) {
7089 SMB_VFS_UNLINK(conn, smb_fname);
7091 return status;
7095 /* Deal with any size changes. */
7097 status = smb_set_file_size(conn, req,
7098 fsp,
7099 smb_fname,
7100 &sbuf,
7101 size,
7102 false);
7103 if (!NT_STATUS_IS_OK(status)) {
7104 return status;
7107 /* Deal with any time changes. */
7108 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7109 /* No change, don't cancel anything. */
7110 return status;
7113 id = vfs_file_id_from_sbuf(conn, &sbuf);
7114 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7115 all_fsps = file_find_di_next(all_fsps)) {
7117 * We're setting the time explicitly for UNIX.
7118 * Cancel any pending changes over all handles.
7120 all_fsps->update_write_time_on_close = false;
7121 TALLOC_FREE(all_fsps->update_write_time_event);
7125 * Override the "setting_write_time"
7126 * parameter here as it almost does what
7127 * we need. Just remember if we modified
7128 * mtime and send the notify ourselves.
7130 if (null_timespec(ft.mtime)) {
7131 modify_mtime = false;
7134 status = smb_set_file_time(conn,
7135 fsp,
7136 smb_fname,
7137 &ft,
7138 false);
7139 if (modify_mtime) {
7140 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7141 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7143 return status;
7146 /****************************************************************************
7147 Deal with SMB_SET_FILE_UNIX_INFO2.
7148 ****************************************************************************/
7150 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7151 struct smb_request *req,
7152 const char *pdata,
7153 int total_data,
7154 files_struct *fsp,
7155 const struct smb_filename *smb_fname)
7157 NTSTATUS status;
7158 uint32 smb_fflags;
7159 uint32 smb_fmask;
7161 if (total_data < 116) {
7162 return NT_STATUS_INVALID_PARAMETER;
7165 /* Start by setting all the fields that are common between UNIX_BASIC
7166 * and UNIX_INFO2.
7168 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7169 fsp, smb_fname);
7170 if (!NT_STATUS_IS_OK(status)) {
7171 return status;
7174 smb_fflags = IVAL(pdata, 108);
7175 smb_fmask = IVAL(pdata, 112);
7177 /* NB: We should only attempt to alter the file flags if the client
7178 * sends a non-zero mask.
7180 if (smb_fmask != 0) {
7181 int stat_fflags = 0;
7183 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7184 smb_fmask, &stat_fflags)) {
7185 /* Client asked to alter a flag we don't understand. */
7186 return NT_STATUS_INVALID_PARAMETER;
7189 if (fsp && fsp->fh->fd != -1) {
7190 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7191 return NT_STATUS_NOT_SUPPORTED;
7192 } else {
7193 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7194 stat_fflags) != 0) {
7195 return map_nt_error_from_unix(errno);
7200 /* XXX: need to add support for changing the create_time here. You
7201 * can do this for paths on Darwin with setattrlist(2). The right way
7202 * to hook this up is probably by extending the VFS utimes interface.
7205 return NT_STATUS_OK;
7208 /****************************************************************************
7209 Create a directory with POSIX semantics.
7210 ****************************************************************************/
7212 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7213 struct smb_request *req,
7214 char **ppdata,
7215 int total_data,
7216 struct smb_filename *smb_fname,
7217 int *pdata_return_size)
7219 NTSTATUS status = NT_STATUS_OK;
7220 uint32 raw_unixmode = 0;
7221 uint32 mod_unixmode = 0;
7222 mode_t unixmode = (mode_t)0;
7223 files_struct *fsp = NULL;
7224 uint16 info_level_return = 0;
7225 int info;
7226 char *pdata = *ppdata;
7228 if (total_data < 18) {
7229 return NT_STATUS_INVALID_PARAMETER;
7232 raw_unixmode = IVAL(pdata,8);
7233 /* Next 4 bytes are not yet defined. */
7235 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7236 PERM_NEW_DIR, &unixmode);
7237 if (!NT_STATUS_IS_OK(status)) {
7238 return status;
7241 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7243 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7244 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7246 status = SMB_VFS_CREATE_FILE(
7247 conn, /* conn */
7248 req, /* req */
7249 0, /* root_dir_fid */
7250 smb_fname, /* fname */
7251 FILE_READ_ATTRIBUTES, /* access_mask */
7252 FILE_SHARE_NONE, /* share_access */
7253 FILE_CREATE, /* create_disposition*/
7254 FILE_DIRECTORY_FILE, /* create_options */
7255 mod_unixmode, /* file_attributes */
7256 0, /* oplock_request */
7257 0, /* allocation_size */
7258 0, /* private_flags */
7259 NULL, /* sd */
7260 NULL, /* ea_list */
7261 &fsp, /* result */
7262 &info); /* pinfo */
7264 if (NT_STATUS_IS_OK(status)) {
7265 close_file(req, fsp, NORMAL_CLOSE);
7268 info_level_return = SVAL(pdata,16);
7270 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7271 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7272 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7273 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7274 } else {
7275 *pdata_return_size = 12;
7278 /* Realloc the data size */
7279 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7280 if (*ppdata == NULL) {
7281 *pdata_return_size = 0;
7282 return NT_STATUS_NO_MEMORY;
7284 pdata = *ppdata;
7286 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7287 SSVAL(pdata,2,0); /* No fnum. */
7288 SIVAL(pdata,4,info); /* Was directory created. */
7290 switch (info_level_return) {
7291 case SMB_QUERY_FILE_UNIX_BASIC:
7292 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7293 SSVAL(pdata,10,0); /* Padding. */
7294 store_file_unix_basic(conn, pdata + 12, fsp,
7295 &smb_fname->st);
7296 break;
7297 case SMB_QUERY_FILE_UNIX_INFO2:
7298 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7299 SSVAL(pdata,10,0); /* Padding. */
7300 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7301 &smb_fname->st);
7302 break;
7303 default:
7304 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7305 SSVAL(pdata,10,0); /* Padding. */
7306 break;
7309 return status;
7312 /****************************************************************************
7313 Open/Create a file with POSIX semantics.
7314 ****************************************************************************/
7316 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7317 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7319 static NTSTATUS smb_posix_open(connection_struct *conn,
7320 struct smb_request *req,
7321 char **ppdata,
7322 int total_data,
7323 struct smb_filename *smb_fname,
7324 int *pdata_return_size)
7326 bool extended_oplock_granted = False;
7327 char *pdata = *ppdata;
7328 uint32 flags = 0;
7329 uint32 wire_open_mode = 0;
7330 uint32 raw_unixmode = 0;
7331 uint32 mod_unixmode = 0;
7332 uint32 create_disp = 0;
7333 uint32 access_mask = 0;
7334 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7335 NTSTATUS status = NT_STATUS_OK;
7336 mode_t unixmode = (mode_t)0;
7337 files_struct *fsp = NULL;
7338 int oplock_request = 0;
7339 int info = 0;
7340 uint16 info_level_return = 0;
7342 if (total_data < 18) {
7343 return NT_STATUS_INVALID_PARAMETER;
7346 flags = IVAL(pdata,0);
7347 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7348 if (oplock_request) {
7349 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7352 wire_open_mode = IVAL(pdata,4);
7354 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7355 return smb_posix_mkdir(conn, req,
7356 ppdata,
7357 total_data,
7358 smb_fname,
7359 pdata_return_size);
7362 switch (wire_open_mode & SMB_ACCMODE) {
7363 case SMB_O_RDONLY:
7364 access_mask = SMB_O_RDONLY_MAPPING;
7365 break;
7366 case SMB_O_WRONLY:
7367 access_mask = SMB_O_WRONLY_MAPPING;
7368 break;
7369 case SMB_O_RDWR:
7370 access_mask = (SMB_O_RDONLY_MAPPING|
7371 SMB_O_WRONLY_MAPPING);
7372 break;
7373 default:
7374 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7375 (unsigned int)wire_open_mode ));
7376 return NT_STATUS_INVALID_PARAMETER;
7379 wire_open_mode &= ~SMB_ACCMODE;
7381 /* First take care of O_CREAT|O_EXCL interactions. */
7382 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7383 case (SMB_O_CREAT | SMB_O_EXCL):
7384 /* File exists fail. File not exist create. */
7385 create_disp = FILE_CREATE;
7386 break;
7387 case SMB_O_CREAT:
7388 /* File exists open. File not exist create. */
7389 create_disp = FILE_OPEN_IF;
7390 break;
7391 case 0:
7392 /* File exists open. File not exist fail. */
7393 create_disp = FILE_OPEN;
7394 break;
7395 case SMB_O_EXCL:
7396 /* O_EXCL on its own without O_CREAT is undefined. */
7397 default:
7398 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7399 (unsigned int)wire_open_mode ));
7400 return NT_STATUS_INVALID_PARAMETER;
7403 /* Next factor in the effects of O_TRUNC. */
7404 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7406 if (wire_open_mode & SMB_O_TRUNC) {
7407 switch (create_disp) {
7408 case FILE_CREATE:
7409 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7410 /* Leave create_disp alone as
7411 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7413 /* File exists fail. File not exist create. */
7414 break;
7415 case FILE_OPEN_IF:
7416 /* SMB_O_CREAT | SMB_O_TRUNC */
7417 /* File exists overwrite. File not exist create. */
7418 create_disp = FILE_OVERWRITE_IF;
7419 break;
7420 case FILE_OPEN:
7421 /* SMB_O_TRUNC */
7422 /* File exists overwrite. File not exist fail. */
7423 create_disp = FILE_OVERWRITE;
7424 break;
7425 default:
7426 /* Cannot get here. */
7427 smb_panic("smb_posix_open: logic error");
7428 return NT_STATUS_INVALID_PARAMETER;
7432 raw_unixmode = IVAL(pdata,8);
7433 /* Next 4 bytes are not yet defined. */
7435 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7436 (VALID_STAT(smb_fname->st) ?
7437 PERM_EXISTING_FILE : PERM_NEW_FILE),
7438 &unixmode);
7440 if (!NT_STATUS_IS_OK(status)) {
7441 return status;
7444 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7446 if (wire_open_mode & SMB_O_SYNC) {
7447 create_options |= FILE_WRITE_THROUGH;
7449 if (wire_open_mode & SMB_O_APPEND) {
7450 access_mask |= FILE_APPEND_DATA;
7452 if (wire_open_mode & SMB_O_DIRECT) {
7453 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7456 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7457 VALID_STAT_OF_DIR(smb_fname->st)) {
7458 if (access_mask != SMB_O_RDONLY_MAPPING) {
7459 return NT_STATUS_FILE_IS_A_DIRECTORY;
7461 create_options &= ~FILE_NON_DIRECTORY_FILE;
7462 create_options |= FILE_DIRECTORY_FILE;
7465 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7466 smb_fname_str_dbg(smb_fname),
7467 (unsigned int)wire_open_mode,
7468 (unsigned int)unixmode ));
7470 status = SMB_VFS_CREATE_FILE(
7471 conn, /* conn */
7472 req, /* req */
7473 0, /* root_dir_fid */
7474 smb_fname, /* fname */
7475 access_mask, /* access_mask */
7476 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7477 FILE_SHARE_DELETE),
7478 create_disp, /* create_disposition*/
7479 create_options, /* create_options */
7480 mod_unixmode, /* file_attributes */
7481 oplock_request, /* oplock_request */
7482 0, /* allocation_size */
7483 0, /* private_flags */
7484 NULL, /* sd */
7485 NULL, /* ea_list */
7486 &fsp, /* result */
7487 &info); /* pinfo */
7489 if (!NT_STATUS_IS_OK(status)) {
7490 return status;
7493 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7494 extended_oplock_granted = True;
7497 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7498 extended_oplock_granted = True;
7501 info_level_return = SVAL(pdata,16);
7503 /* Allocate the correct return size. */
7505 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7506 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7507 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7508 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7509 } else {
7510 *pdata_return_size = 12;
7513 /* Realloc the data size */
7514 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7515 if (*ppdata == NULL) {
7516 close_file(req, fsp, ERROR_CLOSE);
7517 *pdata_return_size = 0;
7518 return NT_STATUS_NO_MEMORY;
7520 pdata = *ppdata;
7522 if (extended_oplock_granted) {
7523 if (flags & REQUEST_BATCH_OPLOCK) {
7524 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7525 } else {
7526 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7528 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7529 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7530 } else {
7531 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7534 SSVAL(pdata,2,fsp->fnum);
7535 SIVAL(pdata,4,info); /* Was file created etc. */
7537 switch (info_level_return) {
7538 case SMB_QUERY_FILE_UNIX_BASIC:
7539 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7540 SSVAL(pdata,10,0); /* padding. */
7541 store_file_unix_basic(conn, pdata + 12, fsp,
7542 &smb_fname->st);
7543 break;
7544 case SMB_QUERY_FILE_UNIX_INFO2:
7545 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7546 SSVAL(pdata,10,0); /* padding. */
7547 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7548 &smb_fname->st);
7549 break;
7550 default:
7551 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7552 SSVAL(pdata,10,0); /* padding. */
7553 break;
7555 return NT_STATUS_OK;
7558 /****************************************************************************
7559 Delete a file with POSIX semantics.
7560 ****************************************************************************/
7562 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7563 struct smb_request *req,
7564 const char *pdata,
7565 int total_data,
7566 struct smb_filename *smb_fname)
7568 NTSTATUS status = NT_STATUS_OK;
7569 files_struct *fsp = NULL;
7570 uint16 flags = 0;
7571 char del = 1;
7572 int info = 0;
7573 int create_options = 0;
7574 int i;
7575 struct share_mode_lock *lck = NULL;
7577 if (total_data < 2) {
7578 return NT_STATUS_INVALID_PARAMETER;
7581 flags = SVAL(pdata,0);
7583 if (!VALID_STAT(smb_fname->st)) {
7584 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7587 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7588 !VALID_STAT_OF_DIR(smb_fname->st)) {
7589 return NT_STATUS_NOT_A_DIRECTORY;
7592 DEBUG(10,("smb_posix_unlink: %s %s\n",
7593 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7594 smb_fname_str_dbg(smb_fname)));
7596 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7597 create_options |= FILE_DIRECTORY_FILE;
7600 status = SMB_VFS_CREATE_FILE(
7601 conn, /* conn */
7602 req, /* req */
7603 0, /* root_dir_fid */
7604 smb_fname, /* fname */
7605 DELETE_ACCESS, /* access_mask */
7606 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7607 FILE_SHARE_DELETE),
7608 FILE_OPEN, /* create_disposition*/
7609 create_options, /* create_options */
7610 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7611 0, /* oplock_request */
7612 0, /* allocation_size */
7613 0, /* private_flags */
7614 NULL, /* sd */
7615 NULL, /* ea_list */
7616 &fsp, /* result */
7617 &info); /* pinfo */
7619 if (!NT_STATUS_IS_OK(status)) {
7620 return status;
7624 * Don't lie to client. If we can't really delete due to
7625 * non-POSIX opens return SHARING_VIOLATION.
7628 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7629 if (lck == NULL) {
7630 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7631 "lock for file %s\n", fsp_str_dbg(fsp)));
7632 close_file(req, fsp, NORMAL_CLOSE);
7633 return NT_STATUS_INVALID_PARAMETER;
7637 * See if others still have the file open. If this is the case, then
7638 * don't delete. If all opens are POSIX delete we can set the delete
7639 * on close disposition.
7641 for (i=0; i<lck->data->num_share_modes; i++) {
7642 struct share_mode_entry *e = &lck->data->share_modes[i];
7643 if (is_valid_share_mode_entry(e)) {
7644 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7645 continue;
7647 if (share_mode_stale_pid(lck->data, i)) {
7648 continue;
7650 /* Fail with sharing violation. */
7651 close_file(req, fsp, NORMAL_CLOSE);
7652 TALLOC_FREE(lck);
7653 return NT_STATUS_SHARING_VIOLATION;
7658 * Set the delete on close.
7660 status = smb_set_file_disposition_info(conn,
7661 &del,
7663 fsp,
7664 smb_fname);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 close_file(req, fsp, NORMAL_CLOSE);
7668 TALLOC_FREE(lck);
7669 return status;
7671 TALLOC_FREE(lck);
7672 return close_file(req, fsp, NORMAL_CLOSE);
7675 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7676 struct smb_request *req,
7677 TALLOC_CTX *mem_ctx,
7678 uint16_t info_level,
7679 files_struct *fsp,
7680 struct smb_filename *smb_fname,
7681 char **ppdata, int total_data,
7682 int *ret_data_size)
7684 char *pdata = *ppdata;
7685 NTSTATUS status = NT_STATUS_OK;
7686 int data_return_size = 0;
7688 *ret_data_size = 0;
7690 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7691 return NT_STATUS_INVALID_LEVEL;
7694 if (!CAN_WRITE(conn)) {
7695 /* Allow POSIX opens. The open path will deny
7696 * any non-readonly opens. */
7697 if (info_level != SMB_POSIX_PATH_OPEN) {
7698 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7702 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7703 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7704 fsp_fnum_dbg(fsp),
7705 info_level, total_data));
7707 switch (info_level) {
7709 case SMB_INFO_STANDARD:
7711 status = smb_set_info_standard(conn,
7712 pdata,
7713 total_data,
7714 fsp,
7715 smb_fname);
7716 break;
7719 case SMB_INFO_SET_EA:
7721 status = smb_info_set_ea(conn,
7722 pdata,
7723 total_data,
7724 fsp,
7725 smb_fname);
7726 break;
7729 case SMB_SET_FILE_BASIC_INFO:
7730 case SMB_FILE_BASIC_INFORMATION:
7732 status = smb_set_file_basic_info(conn,
7733 pdata,
7734 total_data,
7735 fsp,
7736 smb_fname);
7737 break;
7740 case SMB_FILE_ALLOCATION_INFORMATION:
7741 case SMB_SET_FILE_ALLOCATION_INFO:
7743 status = smb_set_file_allocation_info(conn, req,
7744 pdata,
7745 total_data,
7746 fsp,
7747 smb_fname);
7748 break;
7751 case SMB_FILE_END_OF_FILE_INFORMATION:
7752 case SMB_SET_FILE_END_OF_FILE_INFO:
7755 * XP/Win7 both fail after the createfile with
7756 * SMB_SET_FILE_END_OF_FILE_INFO but not
7757 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7758 * The level is known here, so pass it down
7759 * appropriately.
7761 bool should_fail =
7762 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7764 status = smb_set_file_end_of_file_info(conn, req,
7765 pdata,
7766 total_data,
7767 fsp,
7768 smb_fname,
7769 should_fail);
7770 break;
7773 case SMB_FILE_DISPOSITION_INFORMATION:
7774 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7776 #if 0
7777 /* JRA - We used to just ignore this on a path ?
7778 * Shouldn't this be invalid level on a pathname
7779 * based call ?
7781 if (tran_call != TRANSACT2_SETFILEINFO) {
7782 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7784 #endif
7785 status = smb_set_file_disposition_info(conn,
7786 pdata,
7787 total_data,
7788 fsp,
7789 smb_fname);
7790 break;
7793 case SMB_FILE_POSITION_INFORMATION:
7795 status = smb_file_position_information(conn,
7796 pdata,
7797 total_data,
7798 fsp);
7799 break;
7802 case SMB_FILE_FULL_EA_INFORMATION:
7804 status = smb_set_file_full_ea_info(conn,
7805 pdata,
7806 total_data,
7807 fsp);
7808 break;
7811 /* From tridge Samba4 :
7812 * MODE_INFORMATION in setfileinfo (I have no
7813 * idea what "mode information" on a file is - it takes a value of 0,
7814 * 2, 4 or 6. What could it be?).
7817 case SMB_FILE_MODE_INFORMATION:
7819 status = smb_file_mode_information(conn,
7820 pdata,
7821 total_data);
7822 break;
7826 * CIFS UNIX extensions.
7829 case SMB_SET_FILE_UNIX_BASIC:
7831 status = smb_set_file_unix_basic(conn, req,
7832 pdata,
7833 total_data,
7834 fsp,
7835 smb_fname);
7836 break;
7839 case SMB_SET_FILE_UNIX_INFO2:
7841 status = smb_set_file_unix_info2(conn, req,
7842 pdata,
7843 total_data,
7844 fsp,
7845 smb_fname);
7846 break;
7849 case SMB_SET_FILE_UNIX_LINK:
7851 if (fsp) {
7852 /* We must have a pathname for this. */
7853 return NT_STATUS_INVALID_LEVEL;
7855 status = smb_set_file_unix_link(conn, req, pdata,
7856 total_data, smb_fname);
7857 break;
7860 case SMB_SET_FILE_UNIX_HLINK:
7862 if (fsp) {
7863 /* We must have a pathname for this. */
7864 return NT_STATUS_INVALID_LEVEL;
7866 status = smb_set_file_unix_hlink(conn, req,
7867 pdata, total_data,
7868 smb_fname);
7869 break;
7872 case SMB_FILE_RENAME_INFORMATION:
7874 status = smb_file_rename_information(conn, req,
7875 pdata, total_data,
7876 fsp, smb_fname);
7877 break;
7880 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7882 /* SMB2 rename information. */
7883 status = smb2_file_rename_information(conn, req,
7884 pdata, total_data,
7885 fsp, smb_fname);
7886 break;
7889 case SMB_FILE_LINK_INFORMATION:
7891 status = smb_file_link_information(conn, req,
7892 pdata, total_data,
7893 fsp, smb_fname);
7894 break;
7897 #if defined(HAVE_POSIX_ACLS)
7898 case SMB_SET_POSIX_ACL:
7900 status = smb_set_posix_acl(conn,
7901 pdata,
7902 total_data,
7903 fsp,
7904 smb_fname);
7905 break;
7907 #endif
7909 case SMB_SET_POSIX_LOCK:
7911 if (!fsp) {
7912 return NT_STATUS_INVALID_LEVEL;
7914 status = smb_set_posix_lock(conn, req,
7915 pdata, total_data, fsp);
7916 break;
7919 case SMB_POSIX_PATH_OPEN:
7921 if (fsp) {
7922 /* We must have a pathname for this. */
7923 return NT_STATUS_INVALID_LEVEL;
7926 status = smb_posix_open(conn, req,
7927 ppdata,
7928 total_data,
7929 smb_fname,
7930 &data_return_size);
7931 break;
7934 case SMB_POSIX_PATH_UNLINK:
7936 if (fsp) {
7937 /* We must have a pathname for this. */
7938 return NT_STATUS_INVALID_LEVEL;
7941 status = smb_posix_unlink(conn, req,
7942 pdata,
7943 total_data,
7944 smb_fname);
7945 break;
7948 default:
7949 return NT_STATUS_INVALID_LEVEL;
7952 if (!NT_STATUS_IS_OK(status)) {
7953 return status;
7956 *ret_data_size = data_return_size;
7957 return NT_STATUS_OK;
7960 /****************************************************************************
7961 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7962 ****************************************************************************/
7964 static void call_trans2setfilepathinfo(connection_struct *conn,
7965 struct smb_request *req,
7966 unsigned int tran_call,
7967 char **pparams, int total_params,
7968 char **ppdata, int total_data,
7969 unsigned int max_data_bytes)
7971 char *params = *pparams;
7972 char *pdata = *ppdata;
7973 uint16 info_level;
7974 struct smb_filename *smb_fname = NULL;
7975 files_struct *fsp = NULL;
7976 NTSTATUS status = NT_STATUS_OK;
7977 int data_return_size = 0;
7979 if (!params) {
7980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7981 return;
7984 if (tran_call == TRANSACT2_SETFILEINFO) {
7985 if (total_params < 4) {
7986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7987 return;
7990 fsp = file_fsp(req, SVAL(params,0));
7991 /* Basic check for non-null fsp. */
7992 if (!check_fsp_open(conn, req, fsp)) {
7993 return;
7995 info_level = SVAL(params,2);
7997 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7998 &smb_fname);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 reply_nterror(req, status);
8001 return;
8004 if(fsp->fh->fd == -1) {
8006 * This is actually a SETFILEINFO on a directory
8007 * handle (returned from an NT SMB). NT5.0 seems
8008 * to do this call. JRA.
8010 if (INFO_LEVEL_IS_UNIX(info_level)) {
8011 /* Always do lstat for UNIX calls. */
8012 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8013 DEBUG(3,("call_trans2setfilepathinfo: "
8014 "SMB_VFS_LSTAT of %s failed "
8015 "(%s)\n",
8016 smb_fname_str_dbg(smb_fname),
8017 strerror(errno)));
8018 reply_nterror(req, map_nt_error_from_unix(errno));
8019 return;
8021 } else {
8022 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8023 DEBUG(3,("call_trans2setfilepathinfo: "
8024 "fileinfo of %s failed (%s)\n",
8025 smb_fname_str_dbg(smb_fname),
8026 strerror(errno)));
8027 reply_nterror(req, map_nt_error_from_unix(errno));
8028 return;
8031 } else if (fsp->print_file) {
8033 * Doing a DELETE_ON_CLOSE should cancel a print job.
8035 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8036 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8038 DEBUG(3,("call_trans2setfilepathinfo: "
8039 "Cancelling print job (%s)\n",
8040 fsp_str_dbg(fsp)));
8042 SSVAL(params,0,0);
8043 send_trans2_replies(conn, req, params, 2,
8044 *ppdata, 0,
8045 max_data_bytes);
8046 return;
8047 } else {
8048 reply_nterror(req,
8049 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8050 return;
8052 } else {
8054 * Original code - this is an open file.
8056 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8057 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8058 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8059 strerror(errno)));
8060 reply_nterror(req, map_nt_error_from_unix(errno));
8061 return;
8064 } else {
8065 char *fname = NULL;
8066 uint32_t ucf_flags = 0;
8068 /* set path info */
8069 if (total_params < 7) {
8070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8071 return;
8074 info_level = SVAL(params,0);
8075 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8076 total_params - 6, STR_TERMINATE,
8077 &status);
8078 if (!NT_STATUS_IS_OK(status)) {
8079 reply_nterror(req, status);
8080 return;
8083 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8084 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8085 info_level == SMB_FILE_RENAME_INFORMATION ||
8086 info_level == SMB_POSIX_PATH_UNLINK) {
8087 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8090 status = filename_convert(req, conn,
8091 req->flags2 & FLAGS2_DFS_PATHNAMES,
8092 fname,
8093 ucf_flags,
8094 NULL,
8095 &smb_fname);
8096 if (!NT_STATUS_IS_OK(status)) {
8097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8098 reply_botherror(req,
8099 NT_STATUS_PATH_NOT_COVERED,
8100 ERRSRV, ERRbadpath);
8101 return;
8103 reply_nterror(req, status);
8104 return;
8107 if (INFO_LEVEL_IS_UNIX(info_level)) {
8109 * For CIFS UNIX extensions the target name may not exist.
8112 /* Always do lstat for UNIX calls. */
8113 SMB_VFS_LSTAT(conn, smb_fname);
8115 } else if (!VALID_STAT(smb_fname->st) &&
8116 SMB_VFS_STAT(conn, smb_fname)) {
8117 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8118 "%s failed (%s)\n",
8119 smb_fname_str_dbg(smb_fname),
8120 strerror(errno)));
8121 reply_nterror(req, map_nt_error_from_unix(errno));
8122 return;
8126 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8127 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8128 fsp_fnum_dbg(fsp),
8129 info_level,total_data));
8131 /* Realloc the parameter size */
8132 *pparams = (char *)SMB_REALLOC(*pparams,2);
8133 if (*pparams == NULL) {
8134 reply_nterror(req, NT_STATUS_NO_MEMORY);
8135 return;
8137 params = *pparams;
8139 SSVAL(params,0,0);
8141 status = smbd_do_setfilepathinfo(conn, req, req,
8142 info_level,
8143 fsp,
8144 smb_fname,
8145 ppdata, total_data,
8146 &data_return_size);
8147 if (!NT_STATUS_IS_OK(status)) {
8148 if (open_was_deferred(req->sconn, req->mid)) {
8149 /* We have re-scheduled this call. */
8150 return;
8152 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8153 /* We have re-scheduled this call. */
8154 return;
8156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8157 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8158 ERRSRV, ERRbadpath);
8159 return;
8161 if (info_level == SMB_POSIX_PATH_OPEN) {
8162 reply_openerror(req, status);
8163 return;
8166 reply_nterror(req, status);
8167 return;
8170 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8171 max_data_bytes);
8173 return;
8176 /****************************************************************************
8177 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8178 ****************************************************************************/
8180 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8181 char **pparams, int total_params,
8182 char **ppdata, int total_data,
8183 unsigned int max_data_bytes)
8185 struct smb_filename *smb_dname = NULL;
8186 char *params = *pparams;
8187 char *pdata = *ppdata;
8188 char *directory = NULL;
8189 NTSTATUS status = NT_STATUS_OK;
8190 struct ea_list *ea_list = NULL;
8191 TALLOC_CTX *ctx = talloc_tos();
8193 if (!CAN_WRITE(conn)) {
8194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8195 return;
8198 if (total_params < 5) {
8199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8200 return;
8203 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8204 total_params - 4, STR_TERMINATE,
8205 &status);
8206 if (!NT_STATUS_IS_OK(status)) {
8207 reply_nterror(req, status);
8208 return;
8211 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8213 status = filename_convert(ctx,
8214 conn,
8215 req->flags2 & FLAGS2_DFS_PATHNAMES,
8216 directory,
8218 NULL,
8219 &smb_dname);
8221 if (!NT_STATUS_IS_OK(status)) {
8222 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8223 reply_botherror(req,
8224 NT_STATUS_PATH_NOT_COVERED,
8225 ERRSRV, ERRbadpath);
8226 return;
8228 reply_nterror(req, status);
8229 return;
8233 * OS/2 workplace shell seems to send SET_EA requests of "null"
8234 * length (4 bytes containing IVAL 4).
8235 * They seem to have no effect. Bug #3212. JRA.
8238 if (total_data && (total_data != 4)) {
8239 /* Any data in this call is an EA list. */
8240 if (total_data < 10) {
8241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8242 goto out;
8245 if (IVAL(pdata,0) > total_data) {
8246 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8247 IVAL(pdata,0), (unsigned int)total_data));
8248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8249 goto out;
8252 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8253 total_data - 4);
8254 if (!ea_list) {
8255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8256 goto out;
8259 if (!lp_ea_support(SNUM(conn))) {
8260 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8261 goto out;
8264 /* If total_data == 4 Windows doesn't care what values
8265 * are placed in that field, it just ignores them.
8266 * The System i QNTC IBM SMB client puts bad values here,
8267 * so ignore them. */
8269 status = create_directory(conn, req, smb_dname);
8271 if (!NT_STATUS_IS_OK(status)) {
8272 reply_nterror(req, status);
8273 goto out;
8276 /* Try and set any given EA. */
8277 if (ea_list) {
8278 status = set_ea(conn, NULL, smb_dname, ea_list);
8279 if (!NT_STATUS_IS_OK(status)) {
8280 reply_nterror(req, status);
8281 goto out;
8285 /* Realloc the parameter and data sizes */
8286 *pparams = (char *)SMB_REALLOC(*pparams,2);
8287 if(*pparams == NULL) {
8288 reply_nterror(req, NT_STATUS_NO_MEMORY);
8289 goto out;
8291 params = *pparams;
8293 SSVAL(params,0,0);
8295 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8297 out:
8298 TALLOC_FREE(smb_dname);
8299 return;
8302 /****************************************************************************
8303 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8304 We don't actually do this - we just send a null response.
8305 ****************************************************************************/
8307 static void call_trans2findnotifyfirst(connection_struct *conn,
8308 struct smb_request *req,
8309 char **pparams, int total_params,
8310 char **ppdata, int total_data,
8311 unsigned int max_data_bytes)
8313 char *params = *pparams;
8314 uint16 info_level;
8316 if (total_params < 6) {
8317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8318 return;
8321 info_level = SVAL(params,4);
8322 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8324 switch (info_level) {
8325 case 1:
8326 case 2:
8327 break;
8328 default:
8329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8330 return;
8333 /* Realloc the parameter and data sizes */
8334 *pparams = (char *)SMB_REALLOC(*pparams,6);
8335 if (*pparams == NULL) {
8336 reply_nterror(req, NT_STATUS_NO_MEMORY);
8337 return;
8339 params = *pparams;
8341 SSVAL(params,0,fnf_handle);
8342 SSVAL(params,2,0); /* No changes */
8343 SSVAL(params,4,0); /* No EA errors */
8345 fnf_handle++;
8347 if(fnf_handle == 0)
8348 fnf_handle = 257;
8350 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8352 return;
8355 /****************************************************************************
8356 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8357 changes). Currently this does nothing.
8358 ****************************************************************************/
8360 static void call_trans2findnotifynext(connection_struct *conn,
8361 struct smb_request *req,
8362 char **pparams, int total_params,
8363 char **ppdata, int total_data,
8364 unsigned int max_data_bytes)
8366 char *params = *pparams;
8368 DEBUG(3,("call_trans2findnotifynext\n"));
8370 /* Realloc the parameter and data sizes */
8371 *pparams = (char *)SMB_REALLOC(*pparams,4);
8372 if (*pparams == NULL) {
8373 reply_nterror(req, NT_STATUS_NO_MEMORY);
8374 return;
8376 params = *pparams;
8378 SSVAL(params,0,0); /* No changes */
8379 SSVAL(params,2,0); /* No EA errors */
8381 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8383 return;
8386 /****************************************************************************
8387 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8388 ****************************************************************************/
8390 static void call_trans2getdfsreferral(connection_struct *conn,
8391 struct smb_request *req,
8392 char **pparams, int total_params,
8393 char **ppdata, int total_data,
8394 unsigned int max_data_bytes)
8396 char *params = *pparams;
8397 char *pathname = NULL;
8398 int reply_size = 0;
8399 int max_referral_level;
8400 NTSTATUS status = NT_STATUS_OK;
8401 TALLOC_CTX *ctx = talloc_tos();
8403 DEBUG(10,("call_trans2getdfsreferral\n"));
8405 if (total_params < 3) {
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 return;
8410 max_referral_level = SVAL(params,0);
8412 if(!lp_host_msdfs()) {
8413 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8414 return;
8417 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8418 total_params - 2, STR_TERMINATE);
8419 if (!pathname) {
8420 reply_nterror(req, NT_STATUS_NOT_FOUND);
8421 return;
8423 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8424 ppdata,&status)) < 0) {
8425 reply_nterror(req, status);
8426 return;
8429 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8430 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8431 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8433 return;
8436 #define LMCAT_SPL 0x53
8437 #define LMFUNC_GETJOBID 0x60
8439 /****************************************************************************
8440 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8441 ****************************************************************************/
8443 static void call_trans2ioctl(connection_struct *conn,
8444 struct smb_request *req,
8445 char **pparams, int total_params,
8446 char **ppdata, int total_data,
8447 unsigned int max_data_bytes)
8449 char *pdata = *ppdata;
8450 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8452 /* check for an invalid fid before proceeding */
8454 if (!fsp) {
8455 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8456 return;
8459 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8460 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8461 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8462 if (*ppdata == NULL) {
8463 reply_nterror(req, NT_STATUS_NO_MEMORY);
8464 return;
8466 pdata = *ppdata;
8468 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8469 CAN ACCEPT THIS IN UNICODE. JRA. */
8471 /* Job number */
8472 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8474 srvstr_push(pdata, req->flags2, pdata + 2,
8475 lp_netbios_name(), 15,
8476 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8477 srvstr_push(pdata, req->flags2, pdata+18,
8478 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8479 STR_ASCII|STR_TERMINATE); /* Service name */
8480 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8481 max_data_bytes);
8482 return;
8485 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8486 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8489 /****************************************************************************
8490 Reply to a SMBfindclose (stop trans2 directory search).
8491 ****************************************************************************/
8493 void reply_findclose(struct smb_request *req)
8495 int dptr_num;
8496 struct smbd_server_connection *sconn = req->sconn;
8498 START_PROFILE(SMBfindclose);
8500 if (req->wct < 1) {
8501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8502 END_PROFILE(SMBfindclose);
8503 return;
8506 dptr_num = SVALS(req->vwv+0, 0);
8508 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8510 dptr_close(sconn, &dptr_num);
8512 reply_outbuf(req, 0, 0);
8514 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8516 END_PROFILE(SMBfindclose);
8517 return;
8520 /****************************************************************************
8521 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8522 ****************************************************************************/
8524 void reply_findnclose(struct smb_request *req)
8526 int dptr_num;
8528 START_PROFILE(SMBfindnclose);
8530 if (req->wct < 1) {
8531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8532 END_PROFILE(SMBfindnclose);
8533 return;
8536 dptr_num = SVAL(req->vwv+0, 0);
8538 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8540 /* We never give out valid handles for a
8541 findnotifyfirst - so any dptr_num is ok here.
8542 Just ignore it. */
8544 reply_outbuf(req, 0, 0);
8546 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8548 END_PROFILE(SMBfindnclose);
8549 return;
8552 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8553 struct trans_state *state)
8555 if (get_Protocol() >= PROTOCOL_NT1) {
8556 req->flags2 |= 0x40; /* IS_LONG_NAME */
8557 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8560 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8561 if (state->call != TRANSACT2_QFSINFO &&
8562 state->call != TRANSACT2_SETFSINFO) {
8563 DEBUG(0,("handle_trans2: encryption required "
8564 "with call 0x%x\n",
8565 (unsigned int)state->call));
8566 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8567 return;
8571 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8573 /* Now we must call the relevant TRANS2 function */
8574 switch(state->call) {
8575 case TRANSACT2_OPEN:
8577 START_PROFILE(Trans2_open);
8578 call_trans2open(conn, req,
8579 &state->param, state->total_param,
8580 &state->data, state->total_data,
8581 state->max_data_return);
8582 END_PROFILE(Trans2_open);
8583 break;
8586 case TRANSACT2_FINDFIRST:
8588 START_PROFILE(Trans2_findfirst);
8589 call_trans2findfirst(conn, req,
8590 &state->param, state->total_param,
8591 &state->data, state->total_data,
8592 state->max_data_return);
8593 END_PROFILE(Trans2_findfirst);
8594 break;
8597 case TRANSACT2_FINDNEXT:
8599 START_PROFILE(Trans2_findnext);
8600 call_trans2findnext(conn, req,
8601 &state->param, state->total_param,
8602 &state->data, state->total_data,
8603 state->max_data_return);
8604 END_PROFILE(Trans2_findnext);
8605 break;
8608 case TRANSACT2_QFSINFO:
8610 START_PROFILE(Trans2_qfsinfo);
8611 call_trans2qfsinfo(conn, req,
8612 &state->param, state->total_param,
8613 &state->data, state->total_data,
8614 state->max_data_return);
8615 END_PROFILE(Trans2_qfsinfo);
8616 break;
8619 case TRANSACT2_SETFSINFO:
8621 START_PROFILE(Trans2_setfsinfo);
8622 call_trans2setfsinfo(conn, req,
8623 &state->param, state->total_param,
8624 &state->data, state->total_data,
8625 state->max_data_return);
8626 END_PROFILE(Trans2_setfsinfo);
8627 break;
8630 case TRANSACT2_QPATHINFO:
8631 case TRANSACT2_QFILEINFO:
8633 START_PROFILE(Trans2_qpathinfo);
8634 call_trans2qfilepathinfo(conn, req, state->call,
8635 &state->param, state->total_param,
8636 &state->data, state->total_data,
8637 state->max_data_return);
8638 END_PROFILE(Trans2_qpathinfo);
8639 break;
8642 case TRANSACT2_SETPATHINFO:
8643 case TRANSACT2_SETFILEINFO:
8645 START_PROFILE(Trans2_setpathinfo);
8646 call_trans2setfilepathinfo(conn, req, state->call,
8647 &state->param, state->total_param,
8648 &state->data, state->total_data,
8649 state->max_data_return);
8650 END_PROFILE(Trans2_setpathinfo);
8651 break;
8654 case TRANSACT2_FINDNOTIFYFIRST:
8656 START_PROFILE(Trans2_findnotifyfirst);
8657 call_trans2findnotifyfirst(conn, req,
8658 &state->param, state->total_param,
8659 &state->data, state->total_data,
8660 state->max_data_return);
8661 END_PROFILE(Trans2_findnotifyfirst);
8662 break;
8665 case TRANSACT2_FINDNOTIFYNEXT:
8667 START_PROFILE(Trans2_findnotifynext);
8668 call_trans2findnotifynext(conn, req,
8669 &state->param, state->total_param,
8670 &state->data, state->total_data,
8671 state->max_data_return);
8672 END_PROFILE(Trans2_findnotifynext);
8673 break;
8676 case TRANSACT2_MKDIR:
8678 START_PROFILE(Trans2_mkdir);
8679 call_trans2mkdir(conn, req,
8680 &state->param, state->total_param,
8681 &state->data, state->total_data,
8682 state->max_data_return);
8683 END_PROFILE(Trans2_mkdir);
8684 break;
8687 case TRANSACT2_GET_DFS_REFERRAL:
8689 START_PROFILE(Trans2_get_dfs_referral);
8690 call_trans2getdfsreferral(conn, req,
8691 &state->param, state->total_param,
8692 &state->data, state->total_data,
8693 state->max_data_return);
8694 END_PROFILE(Trans2_get_dfs_referral);
8695 break;
8698 case TRANSACT2_IOCTL:
8700 START_PROFILE(Trans2_ioctl);
8701 call_trans2ioctl(conn, req,
8702 &state->param, state->total_param,
8703 &state->data, state->total_data,
8704 state->max_data_return);
8705 END_PROFILE(Trans2_ioctl);
8706 break;
8709 default:
8710 /* Error in request */
8711 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8712 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8716 /****************************************************************************
8717 Reply to a SMBtrans2.
8718 ****************************************************************************/
8720 void reply_trans2(struct smb_request *req)
8722 connection_struct *conn = req->conn;
8723 unsigned int dsoff;
8724 unsigned int dscnt;
8725 unsigned int psoff;
8726 unsigned int pscnt;
8727 unsigned int tran_call;
8728 struct trans_state *state;
8729 NTSTATUS result;
8731 START_PROFILE(SMBtrans2);
8733 if (req->wct < 14) {
8734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8735 END_PROFILE(SMBtrans2);
8736 return;
8739 dsoff = SVAL(req->vwv+12, 0);
8740 dscnt = SVAL(req->vwv+11, 0);
8741 psoff = SVAL(req->vwv+10, 0);
8742 pscnt = SVAL(req->vwv+9, 0);
8743 tran_call = SVAL(req->vwv+14, 0);
8745 result = allow_new_trans(conn->pending_trans, req->mid);
8746 if (!NT_STATUS_IS_OK(result)) {
8747 DEBUG(2, ("Got invalid trans2 request: %s\n",
8748 nt_errstr(result)));
8749 reply_nterror(req, result);
8750 END_PROFILE(SMBtrans2);
8751 return;
8754 if (IS_IPC(conn)) {
8755 switch (tran_call) {
8756 /* List the allowed trans2 calls on IPC$ */
8757 case TRANSACT2_OPEN:
8758 case TRANSACT2_GET_DFS_REFERRAL:
8759 case TRANSACT2_QFILEINFO:
8760 case TRANSACT2_QFSINFO:
8761 case TRANSACT2_SETFSINFO:
8762 break;
8763 default:
8764 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8765 END_PROFILE(SMBtrans2);
8766 return;
8770 if ((state = talloc(conn, struct trans_state)) == NULL) {
8771 DEBUG(0, ("talloc failed\n"));
8772 reply_nterror(req, NT_STATUS_NO_MEMORY);
8773 END_PROFILE(SMBtrans2);
8774 return;
8777 state->cmd = SMBtrans2;
8779 state->mid = req->mid;
8780 state->vuid = req->vuid;
8781 state->setup_count = SVAL(req->vwv+13, 0);
8782 state->setup = NULL;
8783 state->total_param = SVAL(req->vwv+0, 0);
8784 state->param = NULL;
8785 state->total_data = SVAL(req->vwv+1, 0);
8786 state->data = NULL;
8787 state->max_param_return = SVAL(req->vwv+2, 0);
8788 state->max_data_return = SVAL(req->vwv+3, 0);
8789 state->max_setup_return = SVAL(req->vwv+4, 0);
8790 state->close_on_completion = BITSETW(req->vwv+5, 0);
8791 state->one_way = BITSETW(req->vwv+5, 1);
8793 state->call = tran_call;
8795 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8796 is so as a sanity check */
8797 if (state->setup_count != 1) {
8799 * Need to have rc=0 for ioctl to get job id for OS/2.
8800 * Network printing will fail if function is not successful.
8801 * Similar function in reply.c will be used if protocol
8802 * is LANMAN1.0 instead of LM1.2X002.
8803 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8804 * outbuf doesn't have to be set(only job id is used).
8806 if ( (state->setup_count == 4)
8807 && (tran_call == TRANSACT2_IOCTL)
8808 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8809 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8810 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8811 } else {
8812 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8813 DEBUG(2,("Transaction is %d\n",tran_call));
8814 TALLOC_FREE(state);
8815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8816 END_PROFILE(SMBtrans2);
8817 return;
8821 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8822 goto bad_param;
8824 if (state->total_data) {
8826 if (trans_oob(state->total_data, 0, dscnt)
8827 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8828 goto bad_param;
8831 /* Can't use talloc here, the core routines do realloc on the
8832 * params and data. */
8833 state->data = (char *)SMB_MALLOC(state->total_data);
8834 if (state->data == NULL) {
8835 DEBUG(0,("reply_trans2: data malloc fail for %u "
8836 "bytes !\n", (unsigned int)state->total_data));
8837 TALLOC_FREE(state);
8838 reply_nterror(req, NT_STATUS_NO_MEMORY);
8839 END_PROFILE(SMBtrans2);
8840 return;
8843 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8846 if (state->total_param) {
8848 if (trans_oob(state->total_param, 0, pscnt)
8849 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8850 goto bad_param;
8853 /* Can't use talloc here, the core routines do realloc on the
8854 * params and data. */
8855 state->param = (char *)SMB_MALLOC(state->total_param);
8856 if (state->param == NULL) {
8857 DEBUG(0,("reply_trans: param malloc fail for %u "
8858 "bytes !\n", (unsigned int)state->total_param));
8859 SAFE_FREE(state->data);
8860 TALLOC_FREE(state);
8861 reply_nterror(req, NT_STATUS_NO_MEMORY);
8862 END_PROFILE(SMBtrans2);
8863 return;
8866 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8869 state->received_data = dscnt;
8870 state->received_param = pscnt;
8872 if ((state->received_param == state->total_param) &&
8873 (state->received_data == state->total_data)) {
8875 handle_trans2(conn, req, state);
8877 SAFE_FREE(state->data);
8878 SAFE_FREE(state->param);
8879 TALLOC_FREE(state);
8880 END_PROFILE(SMBtrans2);
8881 return;
8884 DLIST_ADD(conn->pending_trans, state);
8886 /* We need to send an interim response then receive the rest
8887 of the parameter/data bytes */
8888 reply_outbuf(req, 0, 0);
8889 show_msg((char *)req->outbuf);
8890 END_PROFILE(SMBtrans2);
8891 return;
8893 bad_param:
8895 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8896 SAFE_FREE(state->data);
8897 SAFE_FREE(state->param);
8898 TALLOC_FREE(state);
8899 END_PROFILE(SMBtrans2);
8900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8904 /****************************************************************************
8905 Reply to a SMBtranss2
8906 ****************************************************************************/
8908 void reply_transs2(struct smb_request *req)
8910 connection_struct *conn = req->conn;
8911 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8912 struct trans_state *state;
8914 START_PROFILE(SMBtranss2);
8916 show_msg((const char *)req->inbuf);
8918 /* Windows clients expect all replies to
8919 a transact secondary (SMBtranss2 0x33)
8920 to have a command code of transact
8921 (SMBtrans2 0x32). See bug #8989
8922 and also [MS-CIFS] section 2.2.4.47.2
8923 for details.
8925 req->cmd = SMBtrans2;
8927 if (req->wct < 8) {
8928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8929 END_PROFILE(SMBtranss2);
8930 return;
8933 for (state = conn->pending_trans; state != NULL;
8934 state = state->next) {
8935 if (state->mid == req->mid) {
8936 break;
8940 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8942 END_PROFILE(SMBtranss2);
8943 return;
8946 /* Revise state->total_param and state->total_data in case they have
8947 changed downwards */
8949 if (SVAL(req->vwv+0, 0) < state->total_param)
8950 state->total_param = SVAL(req->vwv+0, 0);
8951 if (SVAL(req->vwv+1, 0) < state->total_data)
8952 state->total_data = SVAL(req->vwv+1, 0);
8954 pcnt = SVAL(req->vwv+2, 0);
8955 poff = SVAL(req->vwv+3, 0);
8956 pdisp = SVAL(req->vwv+4, 0);
8958 dcnt = SVAL(req->vwv+5, 0);
8959 doff = SVAL(req->vwv+6, 0);
8960 ddisp = SVAL(req->vwv+7, 0);
8962 state->received_param += pcnt;
8963 state->received_data += dcnt;
8965 if ((state->received_data > state->total_data) ||
8966 (state->received_param > state->total_param))
8967 goto bad_param;
8969 if (pcnt) {
8970 if (trans_oob(state->total_param, pdisp, pcnt)
8971 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8972 goto bad_param;
8974 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8977 if (dcnt) {
8978 if (trans_oob(state->total_data, ddisp, dcnt)
8979 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8980 goto bad_param;
8982 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8985 if ((state->received_param < state->total_param) ||
8986 (state->received_data < state->total_data)) {
8987 END_PROFILE(SMBtranss2);
8988 return;
8991 handle_trans2(conn, req, state);
8993 DLIST_REMOVE(conn->pending_trans, state);
8994 SAFE_FREE(state->data);
8995 SAFE_FREE(state->param);
8996 TALLOC_FREE(state);
8998 END_PROFILE(SMBtranss2);
8999 return;
9001 bad_param:
9003 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9004 DLIST_REMOVE(conn->pending_trans, state);
9005 SAFE_FREE(state->data);
9006 SAFE_FREE(state->param);
9007 TALLOC_FREE(state);
9008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9009 END_PROFILE(SMBtranss2);
9010 return;