build: Make install_with_python.sh more portable
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob9c77f4d3f988d263212a57d3c94a573aa808a0ef
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
327 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
328 &names, &num_names);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (num_names == 0) {
335 *ea_list = NULL;
336 return NT_STATUS_OK;
339 for (i=0; i<num_names; i++) {
340 struct ea_list *listp;
341 fstring dos_ea_name;
343 if (strnequal(names[i], "system.", 7)
344 || samba_private_attr_name(names[i]))
345 continue;
347 listp = talloc(mem_ctx, struct ea_list);
348 if (listp == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 status = get_ea_value(mem_ctx, conn, fsp,
353 fname, names[i],
354 &listp->ea);
356 if (!NT_STATUS_IS_OK(status)) {
357 return status;
360 push_ascii_fstring(dos_ea_name, listp->ea.name);
362 *pea_total_len +=
363 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
365 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
366 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
367 (unsigned int)listp->ea.value.length));
369 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
373 /* Add on 4 for total length. */
374 if (*pea_total_len) {
375 *pea_total_len += 4;
378 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
379 (unsigned int)*pea_total_len));
381 *ea_list = ea_list_head;
382 return NT_STATUS_OK;
385 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
386 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
388 *pea_total_len = 0;
389 *ea_list = NULL;
391 if (!lp_ea_support(SNUM(conn))) {
392 return NT_STATUS_OK;
395 if (is_ntfs_stream_smb_fname(smb_fname)) {
396 return NT_STATUS_INVALID_PARAMETER;
399 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
402 /****************************************************************************
403 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
404 that was filled.
405 ****************************************************************************/
407 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
408 connection_struct *conn, struct ea_list *ea_list)
410 unsigned int ret_data_size = 4;
411 char *p = pdata;
413 SMB_ASSERT(total_data_size >= 4);
415 if (!lp_ea_support(SNUM(conn))) {
416 SIVAL(pdata,4,0);
417 return 4;
420 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
421 size_t dos_namelen;
422 fstring dos_ea_name;
423 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
424 dos_namelen = strlen(dos_ea_name);
425 if (dos_namelen > 255 || dos_namelen == 0) {
426 break;
428 if (ea_list->ea.value.length > 65535) {
429 break;
431 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
432 break;
435 /* We know we have room. */
436 SCVAL(p,0,ea_list->ea.flags);
437 SCVAL(p,1,dos_namelen);
438 SSVAL(p,2,ea_list->ea.value.length);
439 strlcpy(p+4, dos_ea_name, dos_namelen+1);
440 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
442 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
443 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
446 ret_data_size = PTR_DIFF(p, pdata);
447 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
448 SIVAL(pdata,0,ret_data_size);
449 return ret_data_size;
452 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
453 char *pdata,
454 unsigned int total_data_size,
455 unsigned int *ret_data_size,
456 connection_struct *conn,
457 struct ea_list *ea_list)
459 uint8_t *p = (uint8_t *)pdata;
460 uint8_t *last_start = NULL;
462 *ret_data_size = 0;
464 if (!lp_ea_support(SNUM(conn))) {
465 return NT_STATUS_NO_EAS_ON_FILE;
468 for (; ea_list; ea_list = ea_list->next) {
469 size_t dos_namelen;
470 fstring dos_ea_name;
471 size_t this_size;
473 if (last_start) {
474 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
476 last_start = p;
478 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
479 dos_namelen = strlen(dos_ea_name);
480 if (dos_namelen > 255 || dos_namelen == 0) {
481 return NT_STATUS_INTERNAL_ERROR;
483 if (ea_list->ea.value.length > 65535) {
484 return NT_STATUS_INTERNAL_ERROR;
487 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
489 if (ea_list->next) {
490 size_t pad = 4 - (this_size % 4);
491 this_size += pad;
494 if (this_size > total_data_size) {
495 return NT_STATUS_INFO_LENGTH_MISMATCH;
498 /* We know we have room. */
499 SIVAL(p, 0x00, 0); /* next offset */
500 SCVAL(p, 0x04, ea_list->ea.flags);
501 SCVAL(p, 0x05, dos_namelen);
502 SSVAL(p, 0x06, ea_list->ea.value.length);
503 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
504 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
506 total_data_size -= this_size;
507 p += this_size;
510 *ret_data_size = PTR_DIFF(p, pdata);
511 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
512 return NT_STATUS_OK;
515 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
517 size_t total_ea_len = 0;
518 TALLOC_CTX *mem_ctx;
519 struct ea_list *ea_list;
521 if (!lp_ea_support(SNUM(conn))) {
522 return 0;
524 mem_ctx = talloc_stackframe();
526 /* If this is a stream fsp, then we need to instead find the
527 * estimated ea len from the main file, not the stream
528 * (streams cannot have EAs), but the estimate isn't just 0 in
529 * this case! */
530 if (is_ntfs_stream_smb_fname(smb_fname)) {
531 fsp = NULL;
533 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
534 TALLOC_FREE(mem_ctx);
535 return total_ea_len;
538 /****************************************************************************
539 Ensure the EA name is case insensitive by matching any existing EA name.
540 ****************************************************************************/
542 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
544 size_t total_ea_len;
545 TALLOC_CTX *mem_ctx = talloc_tos();
546 struct ea_list *ea_list;
547 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
548 if (!NT_STATUS_IS_OK(status)) {
549 return;
552 for (; ea_list; ea_list = ea_list->next) {
553 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
554 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
555 &unix_ea_name[5], ea_list->ea.name));
556 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
557 break;
562 /****************************************************************************
563 Set or delete an extended attribute.
564 ****************************************************************************/
566 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
567 const struct smb_filename *smb_fname, struct ea_list *ea_list)
569 NTSTATUS status;
570 char *fname = NULL;
572 if (!lp_ea_support(SNUM(conn))) {
573 return NT_STATUS_EAS_NOT_SUPPORTED;
576 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
577 if (!NT_STATUS_IS_OK(status)) {
578 return status;
581 /* Setting EAs on streams isn't supported. */
582 if (is_ntfs_stream_smb_fname(smb_fname)) {
583 return NT_STATUS_INVALID_PARAMETER;
586 fname = smb_fname->base_name;
588 for (;ea_list; ea_list = ea_list->next) {
589 int ret;
590 fstring unix_ea_name;
592 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
593 fstrcat(unix_ea_name, ea_list->ea.name);
595 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
597 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
599 if (samba_private_attr_name(unix_ea_name)) {
600 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
601 return NT_STATUS_ACCESS_DENIED;
604 if (ea_list->ea.value.length == 0) {
605 /* Remove the attribute. */
606 if (fsp && (fsp->fh->fd != -1)) {
607 DEBUG(10,("set_ea: deleting ea name %s on "
608 "file %s by file descriptor.\n",
609 unix_ea_name, fsp_str_dbg(fsp)));
610 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
611 } else {
612 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
613 unix_ea_name, fname));
614 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
616 #ifdef ENOATTR
617 /* Removing a non existent attribute always succeeds. */
618 if (ret == -1 && errno == ENOATTR) {
619 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
620 unix_ea_name));
621 ret = 0;
623 #endif
624 } else {
625 if (fsp && (fsp->fh->fd != -1)) {
626 DEBUG(10,("set_ea: setting ea name %s on file "
627 "%s by file descriptor.\n",
628 unix_ea_name, fsp_str_dbg(fsp)));
629 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
630 ea_list->ea.value.data, ea_list->ea.value.length, 0);
631 } else {
632 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
633 unix_ea_name, fname));
634 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
635 ea_list->ea.value.data, ea_list->ea.value.length, 0);
639 if (ret == -1) {
640 #ifdef ENOTSUP
641 if (errno == ENOTSUP) {
642 return NT_STATUS_EAS_NOT_SUPPORTED;
644 #endif
645 return map_nt_error_from_unix(errno);
649 return NT_STATUS_OK;
651 /****************************************************************************
652 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
653 ****************************************************************************/
655 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
657 struct ea_list *ea_list_head = NULL;
658 size_t converted_size, offset = 0;
660 while (offset + 2 < data_size) {
661 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
662 unsigned int namelen = CVAL(pdata,offset);
664 offset++; /* Go past the namelen byte. */
666 /* integer wrap paranioa. */
667 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
668 (offset > data_size) || (namelen > data_size) ||
669 (offset + namelen >= data_size)) {
670 break;
672 /* Ensure the name is null terminated. */
673 if (pdata[offset + namelen] != '\0') {
674 return NULL;
676 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
677 &converted_size)) {
678 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
679 "failed: %s", strerror(errno)));
681 if (!eal->ea.name) {
682 return NULL;
685 offset += (namelen + 1); /* Go past the name + terminating zero. */
686 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
687 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
690 return ea_list_head;
693 /****************************************************************************
694 Read one EA list entry from the buffer.
695 ****************************************************************************/
697 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
699 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
700 uint16 val_len;
701 unsigned int namelen;
702 size_t converted_size;
704 if (!eal) {
705 return NULL;
708 if (data_size < 6) {
709 return NULL;
712 eal->ea.flags = CVAL(pdata,0);
713 namelen = CVAL(pdata,1);
714 val_len = SVAL(pdata,2);
716 if (4 + namelen + 1 + val_len > data_size) {
717 return NULL;
720 /* Ensure the name is null terminated. */
721 if (pdata[namelen + 4] != '\0') {
722 return NULL;
724 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
725 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
726 strerror(errno)));
728 if (!eal->ea.name) {
729 return NULL;
732 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
733 if (!eal->ea.value.data) {
734 return NULL;
737 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
739 /* Ensure we're null terminated just in case we print the value. */
740 eal->ea.value.data[val_len] = '\0';
741 /* But don't count the null. */
742 eal->ea.value.length--;
744 if (pbytes_used) {
745 *pbytes_used = 4 + namelen + 1 + val_len;
748 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
749 dump_data(10, eal->ea.value.data, eal->ea.value.length);
751 return eal;
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
760 struct ea_list *ea_list_head = NULL;
761 size_t offset = 0;
762 size_t bytes_used = 0;
764 while (offset < data_size) {
765 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
767 if (!eal) {
768 return NULL;
771 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
772 offset += bytes_used;
775 return ea_list_head;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list *ealist)
784 fstring dos_ea_name;
785 struct ea_list *listp;
786 size_t ret = 0;
788 for (listp = ealist; listp; listp = listp->next) {
789 push_ascii_fstring(dos_ea_name, listp->ea.name);
790 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
792 /* Add on 4 for total length. */
793 if (ret) {
794 ret += 4;
797 return ret;
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
808 struct ea_list *nlistp, *flistp;
810 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
811 for (flistp = file_list; flistp; flistp = flistp->next) {
812 if (strequal(nlistp->ea.name, flistp->ea.name)) {
813 break;
817 if (flistp) {
818 /* Copy the data from this entry. */
819 nlistp->ea.flags = flistp->ea.flags;
820 nlistp->ea.value = flistp->ea.value;
821 } else {
822 /* Null entry. */
823 nlistp->ea.flags = 0;
824 ZERO_STRUCT(nlistp->ea.value);
828 *total_ea_len = ea_list_size(name_list);
829 return name_list;
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct *conn,
840 struct smb_request *req,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 show_msg((char *)req->outbuf);
882 if (!srv_send_smb(sconn,
883 (char *)req->outbuf,
884 true, req->seqnum+1,
885 IS_CONN_ENCRYPTED(conn),
886 &req->pcd)) {
887 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
889 TALLOC_FREE(req->outbuf);
890 return;
893 /* When sending params and data ensure that both are nicely aligned */
894 /* Only do this alignment when there is also data to send - else
895 can cause NT redirector problems. */
897 if (((params_to_send % 4) != 0) && (data_to_send != 0))
898 data_alignment_offset = 4 - (params_to_send % 4);
900 /* Space is bufsize minus Netbios over TCP header minus SMB header */
901 /* The alignment_offset is to align the param bytes on an even byte
902 boundary. NT 4.0 Beta needs this to work correctly. */
904 useable_space = max_send - (smb_size
905 + 2 * 10 /* wct */
906 + alignment_offset
907 + data_alignment_offset);
909 if (useable_space < 0) {
910 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
911 "= %d!!!", useable_space));
912 exit_server_cleanly("send_trans2_replies: Not enough space");
915 while (params_to_send || data_to_send) {
916 /* Calculate whether we will totally or partially fill this packet */
918 total_sent_thistime = params_to_send + data_to_send;
920 /* We can never send more than useable_space */
922 * Note that 'useable_space' does not include the alignment offsets,
923 * but we must include the alignment offsets in the calculation of
924 * the length of the data we send over the wire, as the alignment offsets
925 * are sent here. Fix from Marc_Jacobsen@hp.com.
928 total_sent_thistime = MIN(total_sent_thistime, useable_space);
930 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
931 + data_alignment_offset);
933 /* Set total params and data to be sent */
934 SSVAL(req->outbuf,smb_tprcnt,paramsize);
935 SSVAL(req->outbuf,smb_tdrcnt,datasize);
937 /* Calculate how many parameters and data we can fit into
938 * this packet. Parameters get precedence
941 params_sent_thistime = MIN(params_to_send,useable_space);
942 data_sent_thistime = useable_space - params_sent_thistime;
943 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
945 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
947 /* smb_proff is the offset from the start of the SMB header to the
948 parameter bytes, however the first 4 bytes of outbuf are
949 the Netbios over TCP header. Thus use smb_base() to subtract
950 them from the calculation */
952 SSVAL(req->outbuf,smb_proff,
953 ((smb_buf(req->outbuf)+alignment_offset)
954 - smb_base(req->outbuf)));
956 if(params_sent_thistime == 0)
957 SSVAL(req->outbuf,smb_prdisp,0);
958 else
959 /* Absolute displacement of param bytes sent in this packet */
960 SSVAL(req->outbuf,smb_prdisp,pp - params);
962 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
963 if(data_sent_thistime == 0) {
964 SSVAL(req->outbuf,smb_droff,0);
965 SSVAL(req->outbuf,smb_drdisp, 0);
966 } else {
967 /* The offset of the data bytes is the offset of the
968 parameter bytes plus the number of parameters being sent this time */
969 SSVAL(req->outbuf, smb_droff,
970 ((smb_buf(req->outbuf)+alignment_offset)
971 - smb_base(req->outbuf))
972 + params_sent_thistime + data_alignment_offset);
973 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
976 /* Initialize the padding for alignment */
978 if (alignment_offset != 0) {
979 memset(smb_buf(req->outbuf), 0, alignment_offset);
982 /* Copy the param bytes into the packet */
984 if(params_sent_thistime) {
985 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
986 params_sent_thistime);
989 /* Copy in the data bytes */
990 if(data_sent_thistime) {
991 if (data_alignment_offset != 0) {
992 memset((smb_buf(req->outbuf)+alignment_offset+
993 params_sent_thistime), 0,
994 data_alignment_offset);
996 memcpy(smb_buf(req->outbuf)+alignment_offset
997 +params_sent_thistime+data_alignment_offset,
998 pd,data_sent_thistime);
1001 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1002 params_sent_thistime, data_sent_thistime, useable_space));
1003 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1004 params_to_send, data_to_send, paramsize, datasize));
1006 if (overflow) {
1007 error_packet_set((char *)req->outbuf,
1008 ERRDOS,ERRbufferoverflow,
1009 STATUS_BUFFER_OVERFLOW,
1010 __LINE__,__FILE__);
1013 /* Send the packet */
1014 show_msg((char *)req->outbuf);
1015 if (!srv_send_smb(sconn,
1016 (char *)req->outbuf,
1017 true, req->seqnum+1,
1018 IS_CONN_ENCRYPTED(conn),
1019 &req->pcd))
1020 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1022 TALLOC_FREE(req->outbuf);
1024 pp += params_sent_thistime;
1025 pd += data_sent_thistime;
1027 params_to_send -= params_sent_thistime;
1028 data_to_send -= data_sent_thistime;
1030 /* Sanity check */
1031 if(params_to_send < 0 || data_to_send < 0) {
1032 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1033 params_to_send, data_to_send));
1034 return;
1038 return;
1041 /****************************************************************************
1042 Reply to a TRANSACT2_OPEN.
1043 ****************************************************************************/
1045 static void call_trans2open(connection_struct *conn,
1046 struct smb_request *req,
1047 char **pparams, int total_params,
1048 char **ppdata, int total_data,
1049 unsigned int max_data_bytes)
1051 struct smb_filename *smb_fname = NULL;
1052 char *params = *pparams;
1053 char *pdata = *ppdata;
1054 int deny_mode;
1055 int32 open_attr;
1056 bool oplock_request;
1057 #if 0
1058 bool return_additional_info;
1059 int16 open_sattr;
1060 time_t open_time;
1061 #endif
1062 int open_ofun;
1063 uint32 open_size;
1064 char *pname;
1065 char *fname = NULL;
1066 off_t size=0;
1067 int fattr=0,mtime=0;
1068 SMB_INO_T inode = 0;
1069 int smb_action = 0;
1070 files_struct *fsp;
1071 struct ea_list *ea_list = NULL;
1072 uint16 flags = 0;
1073 NTSTATUS status;
1074 uint32 access_mask;
1075 uint32 share_mode;
1076 uint32 create_disposition;
1077 uint32 create_options = 0;
1078 uint32_t private_flags = 0;
1079 TALLOC_CTX *ctx = talloc_tos();
1082 * Ensure we have enough parameters to perform the operation.
1085 if (total_params < 29) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1090 flags = SVAL(params, 0);
1091 deny_mode = SVAL(params, 2);
1092 open_attr = SVAL(params,6);
1093 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1094 if (oplock_request) {
1095 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1098 #if 0
1099 return_additional_info = BITSETW(params,0);
1100 open_sattr = SVAL(params, 4);
1101 open_time = make_unix_date3(params+8);
1102 #endif
1103 open_ofun = SVAL(params,12);
1104 open_size = IVAL(params,14);
1105 pname = &params[28];
1107 if (IS_IPC(conn)) {
1108 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1109 goto out;
1112 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1113 total_params - 28, STR_TERMINATE,
1114 &status);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 goto out;
1120 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1121 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1122 (unsigned int)open_ofun, open_size));
1124 status = filename_convert(ctx,
1125 conn,
1126 req->flags2 & FLAGS2_DFS_PATHNAMES,
1127 fname,
1129 NULL,
1130 &smb_fname);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1133 reply_botherror(req,
1134 NT_STATUS_PATH_NOT_COVERED,
1135 ERRSRV, ERRbadpath);
1136 goto out;
1138 reply_nterror(req, status);
1139 goto out;
1142 if (open_ofun == 0) {
1143 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1144 goto out;
1147 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1148 open_ofun,
1149 &access_mask, &share_mode,
1150 &create_disposition,
1151 &create_options,
1152 &private_flags)) {
1153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1154 goto out;
1157 /* Any data in this call is an EA list. */
1158 if (total_data && (total_data != 4)) {
1159 if (total_data < 10) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 goto out;
1164 if (IVAL(pdata,0) > total_data) {
1165 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1166 IVAL(pdata,0), (unsigned int)total_data));
1167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1168 goto out;
1171 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1172 total_data - 4);
1173 if (!ea_list) {
1174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 goto out;
1178 if (!lp_ea_support(SNUM(conn))) {
1179 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1180 goto out;
1184 status = SMB_VFS_CREATE_FILE(
1185 conn, /* conn */
1186 req, /* req */
1187 0, /* root_dir_fid */
1188 smb_fname, /* fname */
1189 access_mask, /* access_mask */
1190 share_mode, /* share_access */
1191 create_disposition, /* create_disposition*/
1192 create_options, /* create_options */
1193 open_attr, /* file_attributes */
1194 oplock_request, /* oplock_request */
1195 open_size, /* allocation_size */
1196 private_flags,
1197 NULL, /* sd */
1198 ea_list, /* ea_list */
1199 &fsp, /* result */
1200 &smb_action); /* psbuf */
1202 if (!NT_STATUS_IS_OK(status)) {
1203 if (open_was_deferred(req->sconn, req->mid)) {
1204 /* We have re-scheduled this call. */
1205 goto out;
1207 reply_openerror(req, status);
1208 goto out;
1211 size = get_file_size_stat(&smb_fname->st);
1212 fattr = dos_mode(conn, smb_fname);
1213 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1214 inode = smb_fname->st.st_ex_ino;
1215 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1216 close_file(req, fsp, ERROR_CLOSE);
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 goto out;
1221 /* Realloc the size of parameters and data we will return */
1222 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1223 if(*pparams == NULL ) {
1224 reply_nterror(req, NT_STATUS_NO_MEMORY);
1225 goto out;
1227 params = *pparams;
1229 SSVAL(params,0,fsp->fnum);
1230 SSVAL(params,2,fattr);
1231 srv_put_dos_date2(params,4, mtime);
1232 SIVAL(params,8, (uint32)size);
1233 SSVAL(params,12,deny_mode);
1234 SSVAL(params,14,0); /* open_type - file or directory. */
1235 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1237 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1238 smb_action |= EXTENDED_OPLOCK_GRANTED;
1241 SSVAL(params,18,smb_action);
1244 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1246 SIVAL(params,20,inode);
1247 SSVAL(params,24,0); /* Padding. */
1248 if (flags & 8) {
1249 uint32 ea_size = estimate_ea_size(conn, fsp,
1250 smb_fname);
1251 SIVAL(params, 26, ea_size);
1252 } else {
1253 SIVAL(params, 26, 0);
1256 /* Send the required number of replies */
1257 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1258 out:
1259 TALLOC_FREE(smb_fname);
1262 /*********************************************************
1263 Routine to check if a given string matches exactly.
1264 as a special case a mask of "." does NOT match. That
1265 is required for correct wildcard semantics
1266 Case can be significant or not.
1267 **********************************************************/
1269 static bool exact_match(bool has_wild,
1270 bool case_sensitive,
1271 const char *str,
1272 const char *mask)
1274 if (mask[0] == '.' && mask[1] == 0) {
1275 return false;
1278 if (has_wild) {
1279 return false;
1282 if (case_sensitive) {
1283 return strcmp(str,mask)==0;
1284 } else {
1285 return strcasecmp_m(str,mask) == 0;
1289 /****************************************************************************
1290 Return the filetype for UNIX extensions.
1291 ****************************************************************************/
1293 static uint32 unix_filetype(mode_t mode)
1295 if(S_ISREG(mode))
1296 return UNIX_TYPE_FILE;
1297 else if(S_ISDIR(mode))
1298 return UNIX_TYPE_DIR;
1299 #ifdef S_ISLNK
1300 else if(S_ISLNK(mode))
1301 return UNIX_TYPE_SYMLINK;
1302 #endif
1303 #ifdef S_ISCHR
1304 else if(S_ISCHR(mode))
1305 return UNIX_TYPE_CHARDEV;
1306 #endif
1307 #ifdef S_ISBLK
1308 else if(S_ISBLK(mode))
1309 return UNIX_TYPE_BLKDEV;
1310 #endif
1311 #ifdef S_ISFIFO
1312 else if(S_ISFIFO(mode))
1313 return UNIX_TYPE_FIFO;
1314 #endif
1315 #ifdef S_ISSOCK
1316 else if(S_ISSOCK(mode))
1317 return UNIX_TYPE_SOCKET;
1318 #endif
1320 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1321 return UNIX_TYPE_UNKNOWN;
1324 /****************************************************************************
1325 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1326 ****************************************************************************/
1328 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1330 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1331 const SMB_STRUCT_STAT *psbuf,
1332 uint32 perms,
1333 enum perm_type ptype,
1334 mode_t *ret_perms)
1336 mode_t ret = 0;
1338 if (perms == SMB_MODE_NO_CHANGE) {
1339 if (!VALID_STAT(*psbuf)) {
1340 return NT_STATUS_INVALID_PARAMETER;
1341 } else {
1342 *ret_perms = psbuf->st_ex_mode;
1343 return NT_STATUS_OK;
1347 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1348 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1349 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1350 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1351 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1352 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1353 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1354 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1355 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1356 #ifdef S_ISVTX
1357 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1358 #endif
1359 #ifdef S_ISGID
1360 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1361 #endif
1362 #ifdef S_ISUID
1363 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1364 #endif
1366 switch (ptype) {
1367 case PERM_NEW_FILE:
1368 case PERM_EXISTING_FILE:
1369 /* Apply mode mask */
1370 ret &= lp_create_mask(SNUM(conn));
1371 /* Add in force bits */
1372 ret |= lp_force_create_mode(SNUM(conn));
1373 break;
1374 case PERM_NEW_DIR:
1375 case PERM_EXISTING_DIR:
1376 ret &= lp_dir_mask(SNUM(conn));
1377 /* Add in force bits */
1378 ret |= lp_force_dir_mode(SNUM(conn));
1379 break;
1382 *ret_perms = ret;
1383 return NT_STATUS_OK;
1386 /****************************************************************************
1387 Needed to show the msdfs symlinks as directories. Modifies psbuf
1388 to be a directory if it's a msdfs link.
1389 ****************************************************************************/
1391 static bool check_msdfs_link(connection_struct *conn,
1392 const char *pathname,
1393 SMB_STRUCT_STAT *psbuf)
1395 int saved_errno = errno;
1396 if(lp_host_msdfs() &&
1397 lp_msdfs_root(SNUM(conn)) &&
1398 is_msdfs_link(conn, pathname, psbuf)) {
1400 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1401 "as a directory\n",
1402 pathname));
1403 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1404 errno = saved_errno;
1405 return true;
1407 errno = saved_errno;
1408 return false;
1412 /****************************************************************************
1413 Get a level dependent lanman2 dir entry.
1414 ****************************************************************************/
1416 struct smbd_dirptr_lanman2_state {
1417 connection_struct *conn;
1418 uint32_t info_level;
1419 bool check_mangled_names;
1420 bool has_wild;
1421 bool got_exact_match;
1424 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1425 void *private_data,
1426 const char *dname,
1427 const char *mask,
1428 char **_fname)
1430 struct smbd_dirptr_lanman2_state *state =
1431 (struct smbd_dirptr_lanman2_state *)private_data;
1432 bool ok;
1433 char mangled_name[13]; /* mangled 8.3 name. */
1434 bool got_match;
1435 const char *fname;
1437 /* Mangle fname if it's an illegal name. */
1438 if (mangle_must_mangle(dname, state->conn->params)) {
1439 ok = name_to_8_3(dname, mangled_name,
1440 true, state->conn->params);
1441 if (!ok) {
1442 return false;
1444 fname = mangled_name;
1445 } else {
1446 fname = dname;
1449 got_match = exact_match(state->has_wild,
1450 state->conn->case_sensitive,
1451 fname, mask);
1452 state->got_exact_match = got_match;
1453 if (!got_match) {
1454 got_match = mask_match(fname, mask,
1455 state->conn->case_sensitive);
1458 if(!got_match && state->check_mangled_names &&
1459 !mangle_is_8_3(fname, false, state->conn->params)) {
1461 * It turns out that NT matches wildcards against
1462 * both long *and* short names. This may explain some
1463 * of the wildcard wierdness from old DOS clients
1464 * that some people have been seeing.... JRA.
1466 /* Force the mangling into 8.3. */
1467 ok = name_to_8_3(fname, mangled_name,
1468 false, state->conn->params);
1469 if (!ok) {
1470 return false;
1473 got_match = exact_match(state->has_wild,
1474 state->conn->case_sensitive,
1475 mangled_name, mask);
1476 state->got_exact_match = got_match;
1477 if (!got_match) {
1478 got_match = mask_match(mangled_name, mask,
1479 state->conn->case_sensitive);
1483 if (!got_match) {
1484 return false;
1487 *_fname = talloc_strdup(ctx, fname);
1488 if (*_fname == NULL) {
1489 return false;
1492 return true;
1495 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1496 void *private_data,
1497 struct smb_filename *smb_fname,
1498 uint32_t *_mode)
1500 struct smbd_dirptr_lanman2_state *state =
1501 (struct smbd_dirptr_lanman2_state *)private_data;
1502 bool ms_dfs_link = false;
1503 uint32_t mode = 0;
1505 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1506 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1507 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1508 "Couldn't lstat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname),
1510 strerror(errno)));
1511 return false;
1513 } else if (!VALID_STAT(smb_fname->st) &&
1514 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1515 /* Needed to show the msdfs symlinks as
1516 * directories */
1518 ms_dfs_link = check_msdfs_link(state->conn,
1519 smb_fname->base_name,
1520 &smb_fname->st);
1521 if (!ms_dfs_link) {
1522 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1523 "Couldn't stat [%s] (%s)\n",
1524 smb_fname_str_dbg(smb_fname),
1525 strerror(errno)));
1526 return false;
1530 if (ms_dfs_link) {
1531 mode = dos_mode_msdfs(state->conn, smb_fname);
1532 } else {
1533 mode = dos_mode(state->conn, smb_fname);
1536 *_mode = mode;
1537 return true;
1540 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1541 connection_struct *conn,
1542 uint16_t flags2,
1543 uint32_t info_level,
1544 struct ea_list *name_list,
1545 bool check_mangled_names,
1546 bool requires_resume_key,
1547 uint32_t mode,
1548 const char *fname,
1549 const struct smb_filename *smb_fname,
1550 int space_remaining,
1551 uint8_t align,
1552 bool do_pad,
1553 char *base_data,
1554 char **ppdata,
1555 char *end_data,
1556 bool *out_of_space,
1557 uint64_t *last_entry_off)
1559 char *p, *q, *pdata = *ppdata;
1560 uint32_t reskey=0;
1561 uint64_t file_size = 0;
1562 uint64_t allocation_size = 0;
1563 uint64_t file_index = 0;
1564 uint32_t len;
1565 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1566 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1567 char *nameptr;
1568 char *last_entry_ptr;
1569 bool was_8_3;
1570 int off;
1571 int pad = 0;
1573 *out_of_space = false;
1575 ZERO_STRUCT(mdate_ts);
1576 ZERO_STRUCT(adate_ts);
1577 ZERO_STRUCT(create_date_ts);
1578 ZERO_STRUCT(cdate_ts);
1580 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1581 file_size = get_file_size_stat(&smb_fname->st);
1583 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1585 file_index = get_FileIndex(conn, &smb_fname->st);
1587 mdate_ts = smb_fname->st.st_ex_mtime;
1588 adate_ts = smb_fname->st.st_ex_atime;
1589 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1590 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1592 if (lp_dos_filetime_resolution(SNUM(conn))) {
1593 dos_filetime_timespec(&create_date_ts);
1594 dos_filetime_timespec(&mdate_ts);
1595 dos_filetime_timespec(&adate_ts);
1596 dos_filetime_timespec(&cdate_ts);
1599 create_date = convert_timespec_to_time_t(create_date_ts);
1600 mdate = convert_timespec_to_time_t(mdate_ts);
1601 adate = convert_timespec_to_time_t(adate_ts);
1603 /* align the record */
1604 SMB_ASSERT(align >= 1);
1606 off = (int)PTR_DIFF(pdata, base_data);
1607 pad = (off + (align-1)) & ~(align-1);
1608 pad -= off;
1610 if (pad && pad > space_remaining) {
1611 *out_of_space = true;
1612 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1613 "for padding (wanted %u, had %d)\n",
1614 (unsigned int)pad,
1615 space_remaining ));
1616 return false; /* Not finished - just out of space */
1619 off += pad;
1620 /* initialize padding to 0 */
1621 if (pad) {
1622 memset(pdata, 0, pad);
1624 space_remaining -= pad;
1626 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1627 space_remaining ));
1629 pdata += pad;
1630 p = pdata;
1631 last_entry_ptr = p;
1633 pad = 0;
1634 off = 0;
1636 switch (info_level) {
1637 case SMB_FIND_INFO_STANDARD:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1639 if(requires_resume_key) {
1640 SIVAL(p,0,reskey);
1641 p += 4;
1643 srv_put_dos_date2(p,0,create_date);
1644 srv_put_dos_date2(p,4,adate);
1645 srv_put_dos_date2(p,8,mdate);
1646 SIVAL(p,12,(uint32)file_size);
1647 SIVAL(p,16,(uint32)allocation_size);
1648 SSVAL(p,20,mode);
1649 p += 23;
1650 nameptr = p;
1651 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1652 p += ucs2_align(base_data, p, 0);
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE);
1657 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 if (len > 2) {
1659 SCVAL(nameptr, -1, len - 2);
1660 } else {
1661 SCVAL(nameptr, -1, 0);
1663 } else {
1664 if (len > 1) {
1665 SCVAL(nameptr, -1, len - 1);
1666 } else {
1667 SCVAL(nameptr, -1, 0);
1670 p += len;
1671 break;
1673 case SMB_FIND_EA_SIZE:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1675 if (requires_resume_key) {
1676 SIVAL(p,0,reskey);
1677 p += 4;
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1684 SSVAL(p,20,mode);
1686 unsigned int ea_size = estimate_ea_size(conn, NULL,
1687 smb_fname);
1688 SIVAL(p,22,ea_size); /* Extended attributes */
1690 p += 27;
1691 nameptr = p - 1;
1692 len = srvstr_push(base_data, flags2,
1693 p, fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE | STR_NOALIGN);
1695 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1696 if (len > 2) {
1697 len -= 2;
1698 } else {
1699 len = 0;
1701 } else {
1702 if (len > 1) {
1703 len -= 1;
1704 } else {
1705 len = 0;
1708 SCVAL(nameptr,0,len);
1709 p += len;
1710 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1711 break;
1713 case SMB_FIND_EA_LIST:
1715 struct ea_list *file_list = NULL;
1716 size_t ea_len = 0;
1717 NTSTATUS status;
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1720 if (!name_list) {
1721 return false;
1723 if (requires_resume_key) {
1724 SIVAL(p,0,reskey);
1725 p += 4;
1727 srv_put_dos_date2(p,0,create_date);
1728 srv_put_dos_date2(p,4,adate);
1729 srv_put_dos_date2(p,8,mdate);
1730 SIVAL(p,12,(uint32)file_size);
1731 SIVAL(p,16,(uint32)allocation_size);
1732 SSVAL(p,20,mode);
1733 p += 22; /* p now points to the EA area. */
1735 status = get_ea_list_from_file(ctx, conn, NULL,
1736 smb_fname,
1737 &ea_len, &file_list);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 file_list = NULL;
1741 name_list = ea_list_union(name_list, file_list, &ea_len);
1743 /* We need to determine if this entry will fit in the space available. */
1744 /* Max string size is 255 bytes. */
1745 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1746 *out_of_space = true;
1747 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1748 "(wanted %u, had %d)\n",
1749 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1750 space_remaining ));
1751 return False; /* Not finished - just out of space */
1754 /* Push the ea_data followed by the name. */
1755 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1756 nameptr = p;
1757 len = srvstr_push(base_data, flags2,
1758 p + 1, fname, PTR_DIFF(end_data, p+1),
1759 STR_TERMINATE | STR_NOALIGN);
1760 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1761 if (len > 2) {
1762 len -= 2;
1763 } else {
1764 len = 0;
1766 } else {
1767 if (len > 1) {
1768 len -= 1;
1769 } else {
1770 len = 0;
1773 SCVAL(nameptr,0,len);
1774 p += len + 1;
1775 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1776 break;
1779 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1781 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1782 p += 4;
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,mode); p += 4;
1791 q = p; p += 4; /* q is placeholder for name length. */
1793 unsigned int ea_size = estimate_ea_size(conn, NULL,
1794 smb_fname);
1795 SIVAL(p,0,ea_size); /* Extended attributes */
1796 p += 4;
1798 /* Clear the short name buffer. This is
1799 * IMPORTANT as not doing so will trigger
1800 * a Win2k client bug. JRA.
1802 if (!was_8_3 && check_mangled_names) {
1803 char mangled_name[13]; /* mangled 8.3 name. */
1804 if (!name_to_8_3(fname,mangled_name,True,
1805 conn->params)) {
1806 /* Error - mangle failed ! */
1807 memset(mangled_name,'\0',12);
1809 mangled_name[12] = 0;
1810 len = srvstr_push(base_data, flags2,
1811 p+2, mangled_name, 24,
1812 STR_UPPER|STR_UNICODE);
1813 if (len < 24) {
1814 memset(p + 2 + len,'\0',24 - len);
1816 SSVAL(p, 0, len);
1817 } else {
1818 memset(p,'\0',26);
1820 p += 2 + 24;
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE_ASCII);
1824 SIVAL(q,0,len);
1825 p += len;
1827 len = PTR_DIFF(p, pdata);
1828 pad = (len + (align-1)) & ~(align-1);
1830 * offset to the next entry, the caller
1831 * will overwrite it for the last entry
1832 * that's why we always include the padding
1834 SIVAL(pdata,0,pad);
1836 * set padding to zero
1838 if (do_pad) {
1839 memset(p, 0, pad - len);
1840 p = pdata + pad;
1841 } else {
1842 p = pdata + len;
1844 break;
1846 case SMB_FIND_FILE_DIRECTORY_INFO:
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1848 p += 4;
1849 SIVAL(p,0,reskey); p += 4;
1850 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1851 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1852 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1853 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1854 SOFF_T(p,0,file_size); p += 8;
1855 SOFF_T(p,0,allocation_size); p += 8;
1856 SIVAL(p,0,mode); p += 4;
1857 len = srvstr_push(base_data, flags2,
1858 p + 4, fname, PTR_DIFF(end_data, p+4),
1859 STR_TERMINATE_ASCII);
1860 SIVAL(p,0,len);
1861 p += 4 + len;
1863 len = PTR_DIFF(p, pdata);
1864 pad = (len + (align-1)) & ~(align-1);
1866 * offset to the next entry, the caller
1867 * will overwrite it for the last entry
1868 * that's why we always include the padding
1870 SIVAL(pdata,0,pad);
1872 * set padding to zero
1874 if (do_pad) {
1875 memset(p, 0, pad - len);
1876 p = pdata + pad;
1877 } else {
1878 p = pdata + len;
1880 break;
1882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1883 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1884 p += 4;
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1888 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1889 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,mode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length. */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL,
1896 smb_fname);
1897 SIVAL(p,0,ea_size); /* Extended attributes */
1898 p +=4;
1900 len = srvstr_push(base_data, flags2, p,
1901 fname, PTR_DIFF(end_data, p),
1902 STR_TERMINATE_ASCII);
1903 SIVAL(q, 0, len);
1904 p += len;
1906 len = PTR_DIFF(p, pdata);
1907 pad = (len + (align-1)) & ~(align-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1913 SIVAL(pdata,0,pad);
1915 * set padding to zero
1917 if (do_pad) {
1918 memset(p, 0, pad - len);
1919 p = pdata + pad;
1920 } else {
1921 p = pdata + len;
1923 break;
1925 case SMB_FIND_FILE_NAMES_INFO:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1927 p += 4;
1928 SIVAL(p,0,reskey); p += 4;
1929 p += 4;
1930 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1931 acl on a dir (tridge) */
1932 len = srvstr_push(base_data, flags2, p,
1933 fname, PTR_DIFF(end_data, p),
1934 STR_TERMINATE_ASCII);
1935 SIVAL(p, -4, len);
1936 p += len;
1938 len = PTR_DIFF(p, pdata);
1939 pad = (len + (align-1)) & ~(align-1);
1941 * offset to the next entry, the caller
1942 * will overwrite it for the last entry
1943 * that's why we always include the padding
1945 SIVAL(pdata,0,pad);
1947 * set padding to zero
1949 if (do_pad) {
1950 memset(p, 0, pad - len);
1951 p = pdata + pad;
1952 } else {
1953 p = pdata + len;
1955 break;
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1958 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1959 p += 4;
1960 SIVAL(p,0,reskey); p += 4;
1961 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1962 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1963 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1964 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1965 SOFF_T(p,0,file_size); p += 8;
1966 SOFF_T(p,0,allocation_size); p += 8;
1967 SIVAL(p,0,mode); p += 4;
1968 q = p; p += 4; /* q is placeholder for name length. */
1970 unsigned int ea_size = estimate_ea_size(conn, NULL,
1971 smb_fname);
1972 SIVAL(p,0,ea_size); /* Extended attributes */
1973 p +=4;
1975 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1976 SBVAL(p,0,file_index); p += 8;
1977 len = srvstr_push(base_data, flags2, p,
1978 fname, PTR_DIFF(end_data, p),
1979 STR_TERMINATE_ASCII);
1980 SIVAL(q, 0, len);
1981 p += len;
1983 len = PTR_DIFF(p, pdata);
1984 pad = (len + (align-1)) & ~(align-1);
1986 * offset to the next entry, the caller
1987 * will overwrite it for the last entry
1988 * that's why we always include the padding
1990 SIVAL(pdata,0,pad);
1992 * set padding to zero
1994 if (do_pad) {
1995 memset(p, 0, pad - len);
1996 p = pdata + pad;
1997 } else {
1998 p = pdata + len;
2000 break;
2002 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 p += 4;
2006 SIVAL(p,0,reskey); p += 4;
2007 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2010 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2011 SOFF_T(p,0,file_size); p += 8;
2012 SOFF_T(p,0,allocation_size); p += 8;
2013 SIVAL(p,0,mode); p += 4;
2014 q = p; p += 4; /* q is placeholder for name length */
2016 unsigned int ea_size = estimate_ea_size(conn, NULL,
2017 smb_fname);
2018 SIVAL(p,0,ea_size); /* Extended attributes */
2019 p +=4;
2021 /* Clear the short name buffer. This is
2022 * IMPORTANT as not doing so will trigger
2023 * a Win2k client bug. JRA.
2025 if (!was_8_3 && check_mangled_names) {
2026 char mangled_name[13]; /* mangled 8.3 name. */
2027 if (!name_to_8_3(fname,mangled_name,True,
2028 conn->params)) {
2029 /* Error - mangle failed ! */
2030 memset(mangled_name,'\0',12);
2032 mangled_name[12] = 0;
2033 len = srvstr_push(base_data, flags2,
2034 p+2, mangled_name, 24,
2035 STR_UPPER|STR_UNICODE);
2036 SSVAL(p, 0, len);
2037 if (len < 24) {
2038 memset(p + 2 + len,'\0',24 - len);
2040 SSVAL(p, 0, len);
2041 } else {
2042 memset(p,'\0',26);
2044 p += 26;
2045 SSVAL(p,0,0); p += 2; /* Reserved ? */
2046 SBVAL(p,0,file_index); p += 8;
2047 len = srvstr_push(base_data, flags2, p,
2048 fname, PTR_DIFF(end_data, p),
2049 STR_TERMINATE_ASCII);
2050 SIVAL(q,0,len);
2051 p += len;
2053 len = PTR_DIFF(p, pdata);
2054 pad = (len + (align-1)) & ~(align-1);
2056 * offset to the next entry, the caller
2057 * will overwrite it for the last entry
2058 * that's why we always include the padding
2060 SIVAL(pdata,0,pad);
2062 * set padding to zero
2064 if (do_pad) {
2065 memset(p, 0, pad - len);
2066 p = pdata + pad;
2067 } else {
2068 p = pdata + len;
2070 break;
2072 /* CIFS UNIX Extension. */
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 p+= 4;
2077 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2079 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2081 if (info_level == SMB_FIND_FILE_UNIX) {
2082 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2083 p = store_file_unix_basic(conn, p,
2084 NULL, &smb_fname->st);
2085 len = srvstr_push(base_data, flags2, p,
2086 fname, PTR_DIFF(end_data, p),
2087 STR_TERMINATE);
2088 } else {
2089 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2090 p = store_file_unix_basic_info2(conn, p,
2091 NULL, &smb_fname->st);
2092 nameptr = p;
2093 p += 4;
2094 len = srvstr_push(base_data, flags2, p, fname,
2095 PTR_DIFF(end_data, p), 0);
2096 SIVAL(nameptr, 0, len);
2099 p += len;
2101 len = PTR_DIFF(p, pdata);
2102 pad = (len + (align-1)) & ~(align-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2108 SIVAL(pdata,0,pad);
2110 * set padding to zero
2112 if (do_pad) {
2113 memset(p, 0, pad - len);
2114 p = pdata + pad;
2115 } else {
2116 p = pdata + len;
2118 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2120 break;
2122 default:
2123 return false;
2126 if (PTR_DIFF(p,pdata) > space_remaining) {
2127 *out_of_space = true;
2128 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2129 "(wanted %u, had %d)\n",
2130 (unsigned int)PTR_DIFF(p,pdata),
2131 space_remaining ));
2132 return false; /* Not finished - just out of space */
2135 /* Setup the last entry pointer, as an offset from base_data */
2136 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2137 /* Advance the data pointer to the next slot */
2138 *ppdata = p;
2140 return true;
2143 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2144 connection_struct *conn,
2145 struct dptr_struct *dirptr,
2146 uint16 flags2,
2147 const char *path_mask,
2148 uint32 dirtype,
2149 int info_level,
2150 int requires_resume_key,
2151 bool dont_descend,
2152 bool ask_sharemode,
2153 uint8_t align,
2154 bool do_pad,
2155 char **ppdata,
2156 char *base_data,
2157 char *end_data,
2158 int space_remaining,
2159 bool *out_of_space,
2160 bool *got_exact_match,
2161 int *_last_entry_off,
2162 struct ea_list *name_list)
2164 const char *p;
2165 const char *mask = NULL;
2166 long prev_dirpos = 0;
2167 uint32_t mode = 0;
2168 char *fname = NULL;
2169 struct smb_filename *smb_fname = NULL;
2170 struct smbd_dirptr_lanman2_state state;
2171 bool ok;
2172 uint64_t last_entry_off = 0;
2174 ZERO_STRUCT(state);
2175 state.conn = conn;
2176 state.info_level = info_level;
2177 state.check_mangled_names = lp_manglednames(conn->params);
2178 state.has_wild = dptr_has_wild(dirptr);
2179 state.got_exact_match = false;
2181 *out_of_space = false;
2182 *got_exact_match = false;
2184 p = strrchr_m(path_mask,'/');
2185 if(p != NULL) {
2186 if(p[1] == '\0') {
2187 mask = "*.*";
2188 } else {
2189 mask = p+1;
2191 } else {
2192 mask = path_mask;
2195 ok = smbd_dirptr_get_entry(ctx,
2196 dirptr,
2197 mask,
2198 dirtype,
2199 dont_descend,
2200 ask_sharemode,
2201 smbd_dirptr_lanman2_match_fn,
2202 smbd_dirptr_lanman2_mode_fn,
2203 &state,
2204 &fname,
2205 &smb_fname,
2206 &mode,
2207 &prev_dirpos);
2208 if (!ok) {
2209 return false;
2212 *got_exact_match = state.got_exact_match;
2214 ok = smbd_marshall_dir_entry(ctx,
2215 conn,
2216 flags2,
2217 info_level,
2218 name_list,
2219 state.check_mangled_names,
2220 requires_resume_key,
2221 mode,
2222 fname,
2223 smb_fname,
2224 space_remaining,
2225 align,
2226 do_pad,
2227 base_data,
2228 ppdata,
2229 end_data,
2230 out_of_space,
2231 &last_entry_off);
2232 TALLOC_FREE(fname);
2233 TALLOC_FREE(smb_fname);
2234 if (*out_of_space) {
2235 dptr_SeekDir(dirptr, prev_dirpos);
2236 return false;
2238 if (!ok) {
2239 return false;
2242 *_last_entry_off = last_entry_off;
2243 return true;
2246 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2247 connection_struct *conn,
2248 struct dptr_struct *dirptr,
2249 uint16 flags2,
2250 const char *path_mask,
2251 uint32 dirtype,
2252 int info_level,
2253 bool requires_resume_key,
2254 bool dont_descend,
2255 bool ask_sharemode,
2256 char **ppdata,
2257 char *base_data,
2258 char *end_data,
2259 int space_remaining,
2260 bool *out_of_space,
2261 bool *got_exact_match,
2262 int *last_entry_off,
2263 struct ea_list *name_list)
2265 uint8_t align = 4;
2266 const bool do_pad = true;
2268 if (info_level >= 1 && info_level <= 3) {
2269 /* No alignment on earlier info levels. */
2270 align = 1;
2273 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2274 path_mask, dirtype, info_level,
2275 requires_resume_key, dont_descend, ask_sharemode,
2276 align, do_pad,
2277 ppdata, base_data, end_data,
2278 space_remaining,
2279 out_of_space, got_exact_match,
2280 last_entry_off, name_list);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDFIRST.
2285 ****************************************************************************/
2287 static void call_trans2findfirst(connection_struct *conn,
2288 struct smb_request *req,
2289 char **pparams, int total_params,
2290 char **ppdata, int total_data,
2291 unsigned int max_data_bytes)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2297 requested. */
2298 struct smb_filename *smb_dname = NULL;
2299 char *params = *pparams;
2300 char *pdata = *ppdata;
2301 char *data_end;
2302 uint32 dirtype;
2303 int maxentries;
2304 uint16 findfirst_flags;
2305 bool close_after_first;
2306 bool close_if_end;
2307 bool requires_resume_key;
2308 int info_level;
2309 char *directory = NULL;
2310 char *mask = NULL;
2311 char *p;
2312 int last_entry_off=0;
2313 int dptr_num = -1;
2314 int numentries = 0;
2315 int i;
2316 bool finished = False;
2317 bool dont_descend = False;
2318 bool out_of_space = False;
2319 int space_remaining;
2320 bool mask_contains_wcard = False;
2321 struct ea_list *ea_list = NULL;
2322 NTSTATUS ntstatus = NT_STATUS_OK;
2323 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX *ctx = talloc_tos();
2325 struct dptr_struct *dirptr = NULL;
2326 struct smbd_server_connection *sconn = req->sconn;
2327 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2328 bool backup_priv = false;
2330 if (total_params < 13) {
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 goto out;
2335 dirtype = SVAL(params,0);
2336 maxentries = SVAL(params,2);
2337 findfirst_flags = SVAL(params,4);
2338 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2339 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2340 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2341 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2342 security_token_has_privilege(get_current_nttok(conn),
2343 SEC_PRIV_BACKUP));
2345 info_level = SVAL(params,6);
2347 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2348 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2349 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2350 (int)backup_priv,
2351 info_level, max_data_bytes));
2353 if (!maxentries) {
2354 /* W2K3 seems to treat zero as 1. */
2355 maxentries = 1;
2358 switch (info_level) {
2359 case SMB_FIND_INFO_STANDARD:
2360 case SMB_FIND_EA_SIZE:
2361 case SMB_FIND_EA_LIST:
2362 case SMB_FIND_FILE_DIRECTORY_INFO:
2363 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2364 case SMB_FIND_FILE_NAMES_INFO:
2365 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2366 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2367 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2368 break;
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2371 /* Always use filesystem for UNIX mtime query. */
2372 ask_sharemode = false;
2373 if (!lp_unix_extensions()) {
2374 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2375 goto out;
2377 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2378 break;
2379 default:
2380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2381 goto out;
2384 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2385 params+12, total_params - 12,
2386 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2387 if (!NT_STATUS_IS_OK(ntstatus)) {
2388 reply_nterror(req, ntstatus);
2389 goto out;
2392 if (backup_priv) {
2393 become_root();
2394 ntstatus = filename_convert_with_privilege(ctx,
2395 conn,
2396 req,
2397 directory,
2398 ucf_flags,
2399 &mask_contains_wcard,
2400 &smb_dname);
2401 } else {
2402 ntstatus = filename_convert(ctx, conn,
2403 req->flags2 & FLAGS2_DFS_PATHNAMES,
2404 directory,
2405 ucf_flags,
2406 &mask_contains_wcard,
2407 &smb_dname);
2410 if (!NT_STATUS_IS_OK(ntstatus)) {
2411 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2412 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2413 ERRSRV, ERRbadpath);
2414 goto out;
2416 reply_nterror(req, ntstatus);
2417 goto out;
2420 mask = smb_dname->original_lcomp;
2422 directory = smb_dname->base_name;
2424 p = strrchr_m(directory,'/');
2425 if(p == NULL) {
2426 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2427 if((directory[0] == '.') && (directory[1] == '\0')) {
2428 mask = talloc_strdup(ctx,"*");
2429 if (!mask) {
2430 reply_nterror(req, NT_STATUS_NO_MEMORY);
2431 goto out;
2433 mask_contains_wcard = True;
2435 } else {
2436 *p = 0;
2439 if (p == NULL || p == directory) {
2440 /* Ensure we don't have a directory name of "". */
2441 directory = talloc_strdup(talloc_tos(), ".");
2442 if (!directory) {
2443 reply_nterror(req, NT_STATUS_NO_MEMORY);
2444 goto out;
2448 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2450 if (info_level == SMB_FIND_EA_LIST) {
2451 uint32 ea_size;
2453 if (total_data < 4) {
2454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2455 goto out;
2458 ea_size = IVAL(pdata,0);
2459 if (ea_size != total_data) {
2460 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2461 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2463 goto out;
2466 if (!lp_ea_support(SNUM(conn))) {
2467 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2468 goto out;
2471 /* Pull out the list of names. */
2472 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2473 if (!ea_list) {
2474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2475 goto out;
2479 *ppdata = (char *)SMB_REALLOC(
2480 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2481 if(*ppdata == NULL ) {
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 goto out;
2485 pdata = *ppdata;
2486 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2488 /* Realloc the params space */
2489 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2490 if (*pparams == NULL) {
2491 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 goto out;
2494 params = *pparams;
2496 /* Save the wildcard match and attribs we are using on this directory -
2497 needed as lanman2 assumes these are being saved between calls */
2499 ntstatus = dptr_create(conn,
2500 req,
2501 NULL, /* fsp */
2502 directory,
2503 False,
2504 True,
2505 req->smbpid,
2506 mask,
2507 mask_contains_wcard,
2508 dirtype,
2509 &dirptr);
2511 if (!NT_STATUS_IS_OK(ntstatus)) {
2512 reply_nterror(req, ntstatus);
2513 goto out;
2516 if (backup_priv) {
2517 /* Remember this in case we have
2518 to do a findnext. */
2519 dptr_set_priv(dirptr);
2522 dptr_num = dptr_dnum(dirptr);
2523 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2525 /* Initialize per TRANS2_FIND_FIRST operation data */
2526 dptr_init_search_op(dirptr);
2528 /* We don't need to check for VOL here as this is returned by
2529 a different TRANS2 call. */
2531 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2532 directory,lp_dontdescend(ctx, SNUM(conn))));
2533 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2534 dont_descend = True;
2536 p = pdata;
2537 space_remaining = max_data_bytes;
2538 out_of_space = False;
2540 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2541 bool got_exact_match = False;
2543 /* this is a heuristic to avoid seeking the dirptr except when
2544 absolutely necessary. It allows for a filename of about 40 chars */
2545 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2546 out_of_space = True;
2547 finished = False;
2548 } else {
2549 finished = !get_lanman2_dir_entry(ctx,
2550 conn,
2551 dirptr,
2552 req->flags2,
2553 mask,dirtype,info_level,
2554 requires_resume_key,dont_descend,
2555 ask_sharemode,
2556 &p,pdata,data_end,
2557 space_remaining, &out_of_space,
2558 &got_exact_match,
2559 &last_entry_off, ea_list);
2562 if (finished && out_of_space)
2563 finished = False;
2565 if (!finished && !out_of_space)
2566 numentries++;
2569 * As an optimisation if we know we aren't looking
2570 * for a wildcard name (ie. the name matches the wildcard exactly)
2571 * then we can finish on any (first) match.
2572 * This speeds up large directory searches. JRA.
2575 if(got_exact_match)
2576 finished = True;
2578 /* Ensure space_remaining never goes -ve. */
2579 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2580 space_remaining = 0;
2581 out_of_space = true;
2582 } else {
2583 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2587 /* Check if we can close the dirptr */
2588 if(close_after_first || (finished && close_if_end)) {
2589 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2590 dptr_close(sconn, &dptr_num);
2594 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2595 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2596 * the protocol level is less than NT1. Tested with smbclient. JRA.
2597 * This should fix the OS/2 client bug #2335.
2600 if(numentries == 0) {
2601 dptr_close(sconn, &dptr_num);
2602 if (get_Protocol() < PROTOCOL_NT1) {
2603 reply_force_doserror(req, ERRDOS, ERRnofiles);
2604 goto out;
2605 } else {
2606 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2607 ERRDOS, ERRbadfile);
2608 goto out;
2612 /* At this point pdata points to numentries directory entries. */
2614 /* Set up the return parameter block */
2615 SSVAL(params,0,dptr_num);
2616 SSVAL(params,2,numentries);
2617 SSVAL(params,4,finished);
2618 SSVAL(params,6,0); /* Never an EA error */
2619 SSVAL(params,8,last_entry_off);
2621 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2622 max_data_bytes);
2624 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2625 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2626 if (!directory) {
2627 reply_nterror(req, NT_STATUS_NO_MEMORY);
2631 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2632 smb_fn_name(req->cmd),
2633 mask, directory, dirtype, numentries ) );
2636 * Force a name mangle here to ensure that the
2637 * mask as an 8.3 name is top of the mangled cache.
2638 * The reasons for this are subtle. Don't remove
2639 * this code unless you know what you are doing
2640 * (see PR#13758). JRA.
2643 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2644 char mangled_name[13];
2645 name_to_8_3(mask, mangled_name, True, conn->params);
2647 out:
2649 if (backup_priv) {
2650 unbecome_root();
2653 TALLOC_FREE(smb_dname);
2654 return;
2657 /****************************************************************************
2658 Reply to a TRANS2_FINDNEXT.
2659 ****************************************************************************/
2661 static void call_trans2findnext(connection_struct *conn,
2662 struct smb_request *req,
2663 char **pparams, int total_params,
2664 char **ppdata, int total_data,
2665 unsigned int max_data_bytes)
2667 /* We must be careful here that we don't return more than the
2668 allowed number of data bytes. If this means returning fewer than
2669 maxentries then so be it. We assume that the redirector has
2670 enough room for the fixed number of parameter bytes it has
2671 requested. */
2672 char *params = *pparams;
2673 char *pdata = *ppdata;
2674 char *data_end;
2675 int dptr_num;
2676 int maxentries;
2677 uint16 info_level;
2678 uint32 resume_key;
2679 uint16 findnext_flags;
2680 bool close_after_request;
2681 bool close_if_end;
2682 bool requires_resume_key;
2683 bool continue_bit;
2684 bool mask_contains_wcard = False;
2685 char *resume_name = NULL;
2686 const char *mask = NULL;
2687 const char *directory = NULL;
2688 char *p = NULL;
2689 uint16 dirtype;
2690 int numentries = 0;
2691 int i, last_entry_off=0;
2692 bool finished = False;
2693 bool dont_descend = False;
2694 bool out_of_space = False;
2695 int space_remaining;
2696 struct ea_list *ea_list = NULL;
2697 NTSTATUS ntstatus = NT_STATUS_OK;
2698 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2699 TALLOC_CTX *ctx = talloc_tos();
2700 struct dptr_struct *dirptr;
2701 struct smbd_server_connection *sconn = req->sconn;
2702 bool backup_priv = false;
2704 if (total_params < 13) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2709 dptr_num = SVAL(params,0);
2710 maxentries = SVAL(params,2);
2711 info_level = SVAL(params,4);
2712 resume_key = IVAL(params,6);
2713 findnext_flags = SVAL(params,10);
2714 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2715 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2716 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2717 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2719 if (!continue_bit) {
2720 /* We only need resume_name if continue_bit is zero. */
2721 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2722 params+12,
2723 total_params - 12, STR_TERMINATE, &ntstatus,
2724 &mask_contains_wcard);
2725 if (!NT_STATUS_IS_OK(ntstatus)) {
2726 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2727 complain (it thinks we're asking for the directory above the shared
2728 path or an invalid name). Catch this as the resume name is only compared, never used in
2729 a file access. JRA. */
2730 srvstr_pull_talloc(ctx, params, req->flags2,
2731 &resume_name, params+12,
2732 total_params - 12,
2733 STR_TERMINATE);
2735 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2736 reply_nterror(req, ntstatus);
2737 return;
2742 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2743 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2744 resume_key = %d resume name = %s continue=%d level = %d\n",
2745 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2746 requires_resume_key, resume_key,
2747 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2749 if (!maxentries) {
2750 /* W2K3 seems to treat zero as 1. */
2751 maxentries = 1;
2754 switch (info_level) {
2755 case SMB_FIND_INFO_STANDARD:
2756 case SMB_FIND_EA_SIZE:
2757 case SMB_FIND_EA_LIST:
2758 case SMB_FIND_FILE_DIRECTORY_INFO:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2760 case SMB_FIND_FILE_NAMES_INFO:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2764 break;
2765 case SMB_FIND_FILE_UNIX:
2766 case SMB_FIND_FILE_UNIX_INFO2:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode = false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2771 return;
2773 break;
2774 default:
2775 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2776 return;
2779 if (info_level == SMB_FIND_EA_LIST) {
2780 uint32 ea_size;
2782 if (total_data < 4) {
2783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2784 return;
2787 ea_size = IVAL(pdata,0);
2788 if (ea_size != total_data) {
2789 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2790 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2792 return;
2795 if (!lp_ea_support(SNUM(conn))) {
2796 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2797 return;
2800 /* Pull out the list of names. */
2801 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2802 if (!ea_list) {
2803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2804 return;
2808 *ppdata = (char *)SMB_REALLOC(
2809 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2810 if(*ppdata == NULL) {
2811 reply_nterror(req, NT_STATUS_NO_MEMORY);
2812 return;
2815 pdata = *ppdata;
2816 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2818 /* Realloc the params space */
2819 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2820 if(*pparams == NULL ) {
2821 reply_nterror(req, NT_STATUS_NO_MEMORY);
2822 return;
2825 params = *pparams;
2827 /* Check that the dptr is valid */
2828 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2829 reply_nterror(req, STATUS_NO_MORE_FILES);
2830 return;
2833 directory = dptr_path(sconn, dptr_num);
2835 /* Get the wildcard mask from the dptr */
2836 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2837 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2838 reply_nterror(req, STATUS_NO_MORE_FILES);
2839 return;
2842 /* Get the attr mask from the dptr */
2843 dirtype = dptr_attr(sconn, dptr_num);
2845 backup_priv = dptr_get_priv(dirptr);
2847 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2848 "backup_priv = %d\n",
2849 dptr_num, mask, dirtype,
2850 (long)dirptr,
2851 dptr_TellDir(dirptr),
2852 (int)backup_priv));
2854 /* Initialize per TRANS2_FIND_NEXT operation data */
2855 dptr_init_search_op(dirptr);
2857 /* We don't need to check for VOL here as this is returned by
2858 a different TRANS2 call. */
2860 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2861 directory,lp_dontdescend(ctx, SNUM(conn))));
2862 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2863 dont_descend = True;
2865 p = pdata;
2866 space_remaining = max_data_bytes;
2867 out_of_space = False;
2869 if (backup_priv) {
2870 become_root();
2874 * Seek to the correct position. We no longer use the resume key but
2875 * depend on the last file name instead.
2878 if(!continue_bit && resume_name && *resume_name) {
2879 SMB_STRUCT_STAT st;
2881 long current_pos = 0;
2883 * Remember, name_to_8_3 is called by
2884 * get_lanman2_dir_entry(), so the resume name
2885 * could be mangled. Ensure we check the unmangled name.
2888 if (mangle_is_mangled(resume_name, conn->params)) {
2889 char *new_resume_name = NULL;
2890 mangle_lookup_name_from_8_3(ctx,
2891 resume_name,
2892 &new_resume_name,
2893 conn->params);
2894 if (new_resume_name) {
2895 resume_name = new_resume_name;
2900 * Fix for NT redirector problem triggered by resume key indexes
2901 * changing between directory scans. We now return a resume key of 0
2902 * and instead look for the filename to continue from (also given
2903 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2904 * findfirst/findnext (as is usual) then the directory pointer
2905 * should already be at the correct place.
2908 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2909 } /* end if resume_name && !continue_bit */
2911 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2912 bool got_exact_match = False;
2914 /* this is a heuristic to avoid seeking the dirptr except when
2915 absolutely necessary. It allows for a filename of about 40 chars */
2916 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2917 out_of_space = True;
2918 finished = False;
2919 } else {
2920 finished = !get_lanman2_dir_entry(ctx,
2921 conn,
2922 dirptr,
2923 req->flags2,
2924 mask,dirtype,info_level,
2925 requires_resume_key,dont_descend,
2926 ask_sharemode,
2927 &p,pdata,data_end,
2928 space_remaining, &out_of_space,
2929 &got_exact_match,
2930 &last_entry_off, ea_list);
2933 if (finished && out_of_space)
2934 finished = False;
2936 if (!finished && !out_of_space)
2937 numentries++;
2940 * As an optimisation if we know we aren't looking
2941 * for a wildcard name (ie. the name matches the wildcard exactly)
2942 * then we can finish on any (first) match.
2943 * This speeds up large directory searches. JRA.
2946 if(got_exact_match)
2947 finished = True;
2949 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2952 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2953 smb_fn_name(req->cmd),
2954 mask, directory, dirtype, numentries ) );
2956 /* Check if we can close the dirptr */
2957 if(close_after_request || (finished && close_if_end)) {
2958 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2959 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2962 if (backup_priv) {
2963 unbecome_root();
2966 /* Set up the return parameter block */
2967 SSVAL(params,0,numentries);
2968 SSVAL(params,2,finished);
2969 SSVAL(params,4,0); /* Never an EA error */
2970 SSVAL(params,6,last_entry_off);
2972 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2973 max_data_bytes);
2975 return;
2978 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2980 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2981 return objid;
2984 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2986 SMB_ASSERT(extended_info != NULL);
2988 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2989 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2990 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2991 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2992 #ifdef SAMBA_VERSION_REVISION
2993 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2994 #endif
2995 extended_info->samba_subversion = 0;
2996 #ifdef SAMBA_VERSION_RC_RELEASE
2997 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2998 #else
2999 #ifdef SAMBA_VERSION_PRE_RELEASE
3000 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3001 #endif
3002 #endif
3003 #ifdef SAMBA_VERSION_VENDOR_PATCH
3004 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3005 #endif
3006 extended_info->samba_gitcommitdate = 0;
3007 #ifdef SAMBA_VERSION_COMMIT_TIME
3008 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3009 #endif
3011 memset(extended_info->samba_version_string, 0,
3012 sizeof(extended_info->samba_version_string));
3014 snprintf (extended_info->samba_version_string,
3015 sizeof(extended_info->samba_version_string),
3016 "%s", samba_version_string());
3019 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3020 TALLOC_CTX *mem_ctx,
3021 uint16_t info_level,
3022 uint16_t flags2,
3023 unsigned int max_data_bytes,
3024 char **ppdata,
3025 int *ret_data_len)
3027 char *pdata, *end_data;
3028 int data_len = 0, len;
3029 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3030 int snum = SNUM(conn);
3031 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3032 uint32 additional_flags = 0;
3033 struct smb_filename smb_fname_dot;
3034 SMB_STRUCT_STAT st;
3036 if (IS_IPC(conn)) {
3037 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3038 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3039 "info level (0x%x) on IPC$.\n",
3040 (unsigned int)info_level));
3041 return NT_STATUS_ACCESS_DENIED;
3045 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3047 ZERO_STRUCT(smb_fname_dot);
3048 smb_fname_dot.base_name = discard_const_p(char, ".");
3050 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3051 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3052 return map_nt_error_from_unix(errno);
3055 st = smb_fname_dot.st;
3057 *ppdata = (char *)SMB_REALLOC(
3058 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3059 if (*ppdata == NULL) {
3060 return NT_STATUS_NO_MEMORY;
3063 pdata = *ppdata;
3064 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3065 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3067 switch (info_level) {
3068 case SMB_INFO_ALLOCATION:
3070 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3071 data_len = 18;
3072 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3073 return map_nt_error_from_unix(errno);
3076 block_size = lp_block_size(snum);
3077 if (bsize < block_size) {
3078 uint64_t factor = block_size/bsize;
3079 bsize = block_size;
3080 dsize /= factor;
3081 dfree /= factor;
3083 if (bsize > block_size) {
3084 uint64_t factor = bsize/block_size;
3085 bsize = block_size;
3086 dsize *= factor;
3087 dfree *= factor;
3089 bytes_per_sector = 512;
3090 sectors_per_unit = bsize/bytes_per_sector;
3092 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3093 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3094 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3096 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3097 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3098 SIVAL(pdata,l1_cUnit,dsize);
3099 SIVAL(pdata,l1_cUnitAvail,dfree);
3100 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3101 break;
3104 case SMB_INFO_VOLUME:
3105 /* Return volume name */
3107 * Add volume serial number - hash of a combination of
3108 * the called hostname and the service name.
3110 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3112 * Win2k3 and previous mess this up by sending a name length
3113 * one byte short. I believe only older clients (OS/2 Win9x) use
3114 * this call so try fixing this by adding a terminating null to
3115 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3117 len = srvstr_push(
3118 pdata, flags2,
3119 pdata+l2_vol_szVolLabel, vname,
3120 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3121 STR_NOALIGN|STR_TERMINATE);
3122 SCVAL(pdata,l2_vol_cch,len);
3123 data_len = l2_vol_szVolLabel + len;
3124 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3125 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3126 len, vname));
3127 break;
3129 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3130 case SMB_FS_ATTRIBUTE_INFORMATION:
3132 additional_flags = 0;
3133 #if defined(HAVE_SYS_QUOTAS)
3134 additional_flags |= FILE_VOLUME_QUOTAS;
3135 #endif
3137 if(lp_nt_acl_support(SNUM(conn))) {
3138 additional_flags |= FILE_PERSISTENT_ACLS;
3141 /* Capabilities are filled in at connection time through STATVFS call */
3142 additional_flags |= conn->fs_capabilities;
3143 additional_flags |= lp_parm_int(conn->params->service,
3144 "share", "fake_fscaps",
3147 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3148 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3149 additional_flags); /* FS ATTRIBUTES */
3151 SIVAL(pdata,4,255); /* Max filename component length */
3152 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3153 and will think we can't do long filenames */
3154 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3155 PTR_DIFF(end_data, pdata+12),
3156 STR_UNICODE);
3157 SIVAL(pdata,8,len);
3158 data_len = 12 + len;
3159 break;
3161 case SMB_QUERY_FS_LABEL_INFO:
3162 case SMB_FS_LABEL_INFORMATION:
3163 len = srvstr_push(pdata, flags2, pdata+4, vname,
3164 PTR_DIFF(end_data, pdata+4), 0);
3165 data_len = 4 + len;
3166 SIVAL(pdata,0,len);
3167 break;
3169 case SMB_QUERY_FS_VOLUME_INFO:
3170 case SMB_FS_VOLUME_INFORMATION:
3173 * Add volume serial number - hash of a combination of
3174 * the called hostname and the service name.
3176 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3177 (str_checksum(get_local_machine_name())<<16));
3179 /* Max label len is 32 characters. */
3180 len = srvstr_push(pdata, flags2, pdata+18, vname,
3181 PTR_DIFF(end_data, pdata+18),
3182 STR_UNICODE);
3183 SIVAL(pdata,12,len);
3184 data_len = 18+len;
3186 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3187 (int)strlen(vname),vname,
3188 lp_servicename(talloc_tos(), snum)));
3189 break;
3191 case SMB_QUERY_FS_SIZE_INFO:
3192 case SMB_FS_SIZE_INFORMATION:
3194 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3195 data_len = 24;
3196 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3197 return map_nt_error_from_unix(errno);
3199 block_size = lp_block_size(snum);
3200 if (bsize < block_size) {
3201 uint64_t factor = block_size/bsize;
3202 bsize = block_size;
3203 dsize /= factor;
3204 dfree /= factor;
3206 if (bsize > block_size) {
3207 uint64_t factor = bsize/block_size;
3208 bsize = block_size;
3209 dsize *= factor;
3210 dfree *= factor;
3212 bytes_per_sector = 512;
3213 sectors_per_unit = bsize/bytes_per_sector;
3214 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3215 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3216 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3217 SBIG_UINT(pdata,0,dsize);
3218 SBIG_UINT(pdata,8,dfree);
3219 SIVAL(pdata,16,sectors_per_unit);
3220 SIVAL(pdata,20,bytes_per_sector);
3221 break;
3224 case SMB_FS_FULL_SIZE_INFORMATION:
3226 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3227 data_len = 32;
3228 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3229 return map_nt_error_from_unix(errno);
3231 block_size = lp_block_size(snum);
3232 if (bsize < block_size) {
3233 uint64_t factor = block_size/bsize;
3234 bsize = block_size;
3235 dsize /= factor;
3236 dfree /= factor;
3238 if (bsize > block_size) {
3239 uint64_t factor = bsize/block_size;
3240 bsize = block_size;
3241 dsize *= factor;
3242 dfree *= factor;
3244 bytes_per_sector = 512;
3245 sectors_per_unit = bsize/bytes_per_sector;
3246 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3247 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3248 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3249 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3250 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3251 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3252 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3253 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3254 break;
3257 case SMB_QUERY_FS_DEVICE_INFO:
3258 case SMB_FS_DEVICE_INFORMATION:
3260 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3262 if (!CAN_WRITE(conn)) {
3263 characteristics |= FILE_READ_ONLY_DEVICE;
3265 data_len = 8;
3266 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3267 SIVAL(pdata,4,characteristics);
3268 break;
3271 #ifdef HAVE_SYS_QUOTAS
3272 case SMB_FS_QUOTA_INFORMATION:
3274 * what we have to send --metze:
3276 * Unknown1: 24 NULL bytes
3277 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3278 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3279 * Quota Flags: 2 byte :
3280 * Unknown3: 6 NULL bytes
3282 * 48 bytes total
3284 * details for Quota Flags:
3286 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3287 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3288 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3289 * 0x0001 Enable Quotas: enable quota for this fs
3293 /* we need to fake up a fsp here,
3294 * because its not send in this call
3296 files_struct fsp;
3297 SMB_NTQUOTA_STRUCT quotas;
3299 ZERO_STRUCT(fsp);
3300 ZERO_STRUCT(quotas);
3302 fsp.conn = conn;
3303 fsp.fnum = FNUM_FIELD_INVALID;
3305 /* access check */
3306 if (get_current_uid(conn) != 0) {
3307 DEBUG(0,("set_user_quota: access_denied "
3308 "service [%s] user [%s]\n",
3309 lp_servicename(talloc_tos(), SNUM(conn)),
3310 conn->session_info->unix_info->unix_name));
3311 return NT_STATUS_ACCESS_DENIED;
3314 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3315 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3316 return map_nt_error_from_unix(errno);
3319 data_len = 48;
3321 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3322 lp_servicename(talloc_tos(), SNUM(conn))));
3324 /* Unknown1 24 NULL bytes*/
3325 SBIG_UINT(pdata,0,(uint64_t)0);
3326 SBIG_UINT(pdata,8,(uint64_t)0);
3327 SBIG_UINT(pdata,16,(uint64_t)0);
3329 /* Default Soft Quota 8 bytes */
3330 SBIG_UINT(pdata,24,quotas.softlim);
3332 /* Default Hard Quota 8 bytes */
3333 SBIG_UINT(pdata,32,quotas.hardlim);
3335 /* Quota flag 2 bytes */
3336 SSVAL(pdata,40,quotas.qflags);
3338 /* Unknown3 6 NULL bytes */
3339 SSVAL(pdata,42,0);
3340 SIVAL(pdata,44,0);
3342 break;
3344 #endif /* HAVE_SYS_QUOTAS */
3345 case SMB_FS_OBJECTID_INFORMATION:
3347 unsigned char objid[16];
3348 struct smb_extended_info extended_info;
3349 memcpy(pdata,create_volume_objectid(conn, objid),16);
3350 samba_extended_info_version (&extended_info);
3351 SIVAL(pdata,16,extended_info.samba_magic);
3352 SIVAL(pdata,20,extended_info.samba_version);
3353 SIVAL(pdata,24,extended_info.samba_subversion);
3354 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3355 memcpy(pdata+36,extended_info.samba_version_string,28);
3356 data_len = 64;
3357 break;
3361 * Query the version and capabilities of the CIFS UNIX extensions
3362 * in use.
3365 case SMB_QUERY_CIFS_UNIX_INFO:
3367 bool large_write = lp_min_receive_file_size() &&
3368 !srv_is_signing_active(conn->sconn);
3369 bool large_read = !srv_is_signing_active(conn->sconn);
3370 int encrypt_caps = 0;
3372 if (!lp_unix_extensions()) {
3373 return NT_STATUS_INVALID_LEVEL;
3376 switch (conn->encrypt_level) {
3377 case SMB_SIGNING_OFF:
3378 encrypt_caps = 0;
3379 break;
3380 case SMB_SIGNING_IF_REQUIRED:
3381 case SMB_SIGNING_DEFAULT:
3382 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3383 break;
3384 case SMB_SIGNING_REQUIRED:
3385 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3386 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3387 large_write = false;
3388 large_read = false;
3389 break;
3392 data_len = 12;
3393 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3394 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3396 /* We have POSIX ACLs, pathname, encryption,
3397 * large read/write, and locking capability. */
3399 SBIG_UINT(pdata,4,((uint64_t)(
3400 CIFS_UNIX_POSIX_ACLS_CAP|
3401 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3402 CIFS_UNIX_FCNTL_LOCKS_CAP|
3403 CIFS_UNIX_EXTATTR_CAP|
3404 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3405 encrypt_caps|
3406 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3407 (large_write ?
3408 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3409 break;
3412 case SMB_QUERY_POSIX_FS_INFO:
3414 int rc;
3415 vfs_statvfs_struct svfs;
3417 if (!lp_unix_extensions()) {
3418 return NT_STATUS_INVALID_LEVEL;
3421 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3423 if (!rc) {
3424 data_len = 56;
3425 SIVAL(pdata,0,svfs.OptimalTransferSize);
3426 SIVAL(pdata,4,svfs.BlockSize);
3427 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3428 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3429 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3430 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3431 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3432 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3433 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3434 #ifdef EOPNOTSUPP
3435 } else if (rc == EOPNOTSUPP) {
3436 return NT_STATUS_INVALID_LEVEL;
3437 #endif /* EOPNOTSUPP */
3438 } else {
3439 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3440 return NT_STATUS_DOS(ERRSRV, ERRerror);
3442 break;
3445 case SMB_QUERY_POSIX_WHOAMI:
3447 uint32_t flags = 0;
3448 uint32_t sid_bytes;
3449 int i;
3451 if (!lp_unix_extensions()) {
3452 return NT_STATUS_INVALID_LEVEL;
3455 if (max_data_bytes < 40) {
3456 return NT_STATUS_BUFFER_TOO_SMALL;
3459 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3460 flags |= SMB_WHOAMI_GUEST;
3463 /* NOTE: 8 bytes for UID/GID, irrespective of native
3464 * platform size. This matches
3465 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3467 data_len = 4 /* flags */
3468 + 4 /* flag mask */
3469 + 8 /* uid */
3470 + 8 /* gid */
3471 + 4 /* ngroups */
3472 + 4 /* num_sids */
3473 + 4 /* SID bytes */
3474 + 4 /* pad/reserved */
3475 + (conn->session_info->unix_token->ngroups * 8)
3476 /* groups list */
3477 + (conn->session_info->security_token->num_sids *
3478 SID_MAX_SIZE)
3479 /* SID list */;
3481 SIVAL(pdata, 0, flags);
3482 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3483 SBIG_UINT(pdata, 8,
3484 (uint64_t)conn->session_info->unix_token->uid);
3485 SBIG_UINT(pdata, 16,
3486 (uint64_t)conn->session_info->unix_token->gid);
3489 if (data_len >= max_data_bytes) {
3490 /* Potential overflow, skip the GIDs and SIDs. */
3492 SIVAL(pdata, 24, 0); /* num_groups */
3493 SIVAL(pdata, 28, 0); /* num_sids */
3494 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3495 SIVAL(pdata, 36, 0); /* reserved */
3497 data_len = 40;
3498 break;
3501 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3502 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3504 /* We walk the SID list twice, but this call is fairly
3505 * infrequent, and I don't expect that it's performance
3506 * sensitive -- jpeach
3508 for (i = 0, sid_bytes = 0;
3509 i < conn->session_info->security_token->num_sids; ++i) {
3510 sid_bytes += ndr_size_dom_sid(
3511 &conn->session_info->security_token->sids[i],
3515 /* SID list byte count */
3516 SIVAL(pdata, 32, sid_bytes);
3518 /* 4 bytes pad/reserved - must be zero */
3519 SIVAL(pdata, 36, 0);
3520 data_len = 40;
3522 /* GID list */
3523 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3524 SBIG_UINT(pdata, data_len,
3525 (uint64_t)conn->session_info->unix_token->groups[i]);
3526 data_len += 8;
3529 /* SID list */
3530 for (i = 0;
3531 i < conn->session_info->security_token->num_sids; ++i) {
3532 int sid_len = ndr_size_dom_sid(
3533 &conn->session_info->security_token->sids[i],
3536 sid_linearize(pdata + data_len, sid_len,
3537 &conn->session_info->security_token->sids[i]);
3538 data_len += sid_len;
3541 break;
3544 case SMB_MAC_QUERY_FS_INFO:
3546 * Thursby MAC extension... ONLY on NTFS filesystems
3547 * once we do streams then we don't need this
3549 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3550 data_len = 88;
3551 SIVAL(pdata,84,0x100); /* Don't support mac... */
3552 break;
3554 /* drop through */
3555 default:
3556 return NT_STATUS_INVALID_LEVEL;
3559 *ret_data_len = data_len;
3560 return NT_STATUS_OK;
3563 /****************************************************************************
3564 Reply to a TRANS2_QFSINFO (query filesystem info).
3565 ****************************************************************************/
3567 static void call_trans2qfsinfo(connection_struct *conn,
3568 struct smb_request *req,
3569 char **pparams, int total_params,
3570 char **ppdata, int total_data,
3571 unsigned int max_data_bytes)
3573 char *params = *pparams;
3574 uint16_t info_level;
3575 int data_len = 0;
3576 NTSTATUS status;
3578 if (total_params < 2) {
3579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3580 return;
3583 info_level = SVAL(params,0);
3585 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3586 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3587 DEBUG(0,("call_trans2qfsinfo: encryption required "
3588 "and info level 0x%x sent.\n",
3589 (unsigned int)info_level));
3590 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3591 return;
3595 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3597 status = smbd_do_qfsinfo(conn, req,
3598 info_level,
3599 req->flags2,
3600 max_data_bytes,
3601 ppdata, &data_len);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 reply_nterror(req, status);
3604 return;
3607 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3608 max_data_bytes);
3610 DEBUG( 4, ( "%s info_level = %d\n",
3611 smb_fn_name(req->cmd), info_level) );
3613 return;
3616 /****************************************************************************
3617 Reply to a TRANS2_SETFSINFO (set filesystem info).
3618 ****************************************************************************/
3620 static void call_trans2setfsinfo(connection_struct *conn,
3621 struct smb_request *req,
3622 char **pparams, int total_params,
3623 char **ppdata, int total_data,
3624 unsigned int max_data_bytes)
3626 struct smbd_server_connection *sconn = req->sconn;
3627 char *pdata = *ppdata;
3628 char *params = *pparams;
3629 uint16 info_level;
3631 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3632 lp_servicename(talloc_tos(), SNUM(conn))));
3634 /* */
3635 if (total_params < 4) {
3636 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3637 total_params));
3638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3639 return;
3642 info_level = SVAL(params,2);
3644 if (IS_IPC(conn)) {
3645 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3646 info_level != SMB_SET_CIFS_UNIX_INFO) {
3647 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3648 "info level (0x%x) on IPC$.\n",
3649 (unsigned int)info_level));
3650 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3651 return;
3655 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3656 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3657 DEBUG(0,("call_trans2setfsinfo: encryption required "
3658 "and info level 0x%x sent.\n",
3659 (unsigned int)info_level));
3660 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3661 return;
3665 switch(info_level) {
3666 case SMB_SET_CIFS_UNIX_INFO:
3667 if (!lp_unix_extensions()) {
3668 DEBUG(2,("call_trans2setfsinfo: "
3669 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3670 "unix extensions off\n"));
3671 reply_nterror(req,
3672 NT_STATUS_INVALID_LEVEL);
3673 return;
3676 /* There should be 12 bytes of capabilities set. */
3677 if (total_data < 12) {
3678 reply_nterror(
3679 req,
3680 NT_STATUS_INVALID_PARAMETER);
3681 return;
3683 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3684 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3685 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3686 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3687 /* Just print these values for now. */
3688 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3689 "major = %u, minor = %u cap_low = 0x%x, "
3690 "cap_high = 0x%xn",
3691 (unsigned int)sconn->
3692 smb1.unix_info.client_major,
3693 (unsigned int)sconn->
3694 smb1.unix_info.client_minor,
3695 (unsigned int)sconn->
3696 smb1.unix_info.client_cap_low,
3697 (unsigned int)sconn->
3698 smb1.unix_info.client_cap_high));
3700 /* Here is where we must switch to posix pathname processing... */
3701 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3702 lp_set_posix_pathnames();
3703 mangle_change_to_posix();
3706 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3707 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3708 /* Client that knows how to do posix locks,
3709 * but not posix open/mkdir operations. Set a
3710 * default type for read/write checks. */
3712 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3715 break;
3717 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3719 NTSTATUS status;
3720 size_t param_len = 0;
3721 size_t data_len = total_data;
3723 if (!lp_unix_extensions()) {
3724 reply_nterror(
3725 req,
3726 NT_STATUS_INVALID_LEVEL);
3727 return;
3730 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3731 reply_nterror(
3732 req,
3733 NT_STATUS_NOT_SUPPORTED);
3734 return;
3737 if (req->sconn->smb1.echo_handler.trusted_fde) {
3738 DEBUG( 2,("call_trans2setfsinfo: "
3739 "request transport encryption disabled"
3740 "with 'fork echo handler = yes'\n"));
3741 reply_nterror(
3742 req,
3743 NT_STATUS_NOT_SUPPORTED);
3744 return;
3747 DEBUG( 4,("call_trans2setfsinfo: "
3748 "request transport encryption.\n"));
3750 status = srv_request_encryption_setup(conn,
3751 (unsigned char **)ppdata,
3752 &data_len,
3753 (unsigned char **)pparams,
3754 &param_len);
3756 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3757 !NT_STATUS_IS_OK(status)) {
3758 reply_nterror(req, status);
3759 return;
3762 send_trans2_replies(conn, req,
3763 *pparams,
3764 param_len,
3765 *ppdata,
3766 data_len,
3767 max_data_bytes);
3769 if (NT_STATUS_IS_OK(status)) {
3770 /* Server-side transport
3771 * encryption is now *on*. */
3772 status = srv_encryption_start(conn);
3773 if (!NT_STATUS_IS_OK(status)) {
3774 char *reason = talloc_asprintf(talloc_tos(),
3775 "Failure in setting "
3776 "up encrypted transport: %s",
3777 nt_errstr(status));
3778 exit_server_cleanly(reason);
3781 return;
3784 case SMB_FS_QUOTA_INFORMATION:
3786 files_struct *fsp = NULL;
3787 SMB_NTQUOTA_STRUCT quotas;
3789 ZERO_STRUCT(quotas);
3791 /* access check */
3792 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3793 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3794 lp_servicename(talloc_tos(), SNUM(conn)),
3795 conn->session_info->unix_info->unix_name));
3796 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3797 return;
3800 /* note: normaly there're 48 bytes,
3801 * but we didn't use the last 6 bytes for now
3802 * --metze
3804 fsp = file_fsp(req, SVAL(params,0));
3806 if (!check_fsp_ntquota_handle(conn, req,
3807 fsp)) {
3808 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3809 reply_nterror(
3810 req, NT_STATUS_INVALID_HANDLE);
3811 return;
3814 if (total_data < 42) {
3815 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3816 total_data));
3817 reply_nterror(
3818 req,
3819 NT_STATUS_INVALID_PARAMETER);
3820 return;
3823 /* unknown_1 24 NULL bytes in pdata*/
3825 /* the soft quotas 8 bytes (uint64_t)*/
3826 quotas.softlim = BVAL(pdata,24);
3828 /* the hard quotas 8 bytes (uint64_t)*/
3829 quotas.hardlim = BVAL(pdata,32);
3831 /* quota_flags 2 bytes **/
3832 quotas.qflags = SVAL(pdata,40);
3834 /* unknown_2 6 NULL bytes follow*/
3836 /* now set the quotas */
3837 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3838 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3839 reply_nterror(req, map_nt_error_from_unix(errno));
3840 return;
3843 break;
3845 default:
3846 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3847 info_level));
3848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3849 return;
3850 break;
3854 * sending this reply works fine,
3855 * but I'm not sure it's the same
3856 * like windows do...
3857 * --metze
3859 reply_outbuf(req, 10, 0);
3862 #if defined(HAVE_POSIX_ACLS)
3863 /****************************************************************************
3864 Utility function to count the number of entries in a POSIX acl.
3865 ****************************************************************************/
3867 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3869 unsigned int ace_count = 0;
3870 int entry_id = SMB_ACL_FIRST_ENTRY;
3871 SMB_ACL_ENTRY_T entry;
3873 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3874 /* get_next... */
3875 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3876 entry_id = SMB_ACL_NEXT_ENTRY;
3878 ace_count++;
3880 return ace_count;
3883 /****************************************************************************
3884 Utility function to marshall a POSIX acl into wire format.
3885 ****************************************************************************/
3887 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3889 int entry_id = SMB_ACL_FIRST_ENTRY;
3890 SMB_ACL_ENTRY_T entry;
3892 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3893 SMB_ACL_TAG_T tagtype;
3894 SMB_ACL_PERMSET_T permset;
3895 unsigned char perms = 0;
3896 unsigned int own_grp;
3898 /* get_next... */
3899 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3900 entry_id = SMB_ACL_NEXT_ENTRY;
3903 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3904 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3905 return False;
3908 if (sys_acl_get_permset(entry, &permset) == -1) {
3909 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3910 return False;
3913 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3914 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3915 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3917 SCVAL(pdata,1,perms);
3919 switch (tagtype) {
3920 case SMB_ACL_USER_OBJ:
3921 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3922 own_grp = (unsigned int)pst->st_ex_uid;
3923 SIVAL(pdata,2,own_grp);
3924 SIVAL(pdata,6,0);
3925 break;
3926 case SMB_ACL_USER:
3928 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3929 if (!puid) {
3930 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3931 return False;
3933 own_grp = (unsigned int)*puid;
3934 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3935 SIVAL(pdata,2,own_grp);
3936 SIVAL(pdata,6,0);
3937 break;
3939 case SMB_ACL_GROUP_OBJ:
3940 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3941 own_grp = (unsigned int)pst->st_ex_gid;
3942 SIVAL(pdata,2,own_grp);
3943 SIVAL(pdata,6,0);
3944 break;
3945 case SMB_ACL_GROUP:
3947 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3948 if (!pgid) {
3949 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3950 return False;
3952 own_grp = (unsigned int)*pgid;
3953 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3954 SIVAL(pdata,2,own_grp);
3955 SIVAL(pdata,6,0);
3956 break;
3958 case SMB_ACL_MASK:
3959 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3960 SIVAL(pdata,2,0xFFFFFFFF);
3961 SIVAL(pdata,6,0xFFFFFFFF);
3962 break;
3963 case SMB_ACL_OTHER:
3964 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3965 SIVAL(pdata,2,0xFFFFFFFF);
3966 SIVAL(pdata,6,0xFFFFFFFF);
3967 break;
3968 default:
3969 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3970 return False;
3972 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3975 return True;
3977 #endif
3979 /****************************************************************************
3980 Store the FILE_UNIX_BASIC info.
3981 ****************************************************************************/
3983 static char *store_file_unix_basic(connection_struct *conn,
3984 char *pdata,
3985 files_struct *fsp,
3986 const SMB_STRUCT_STAT *psbuf)
3988 uint64_t file_index = get_FileIndex(conn, psbuf);
3989 dev_t devno;
3991 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3992 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3994 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3995 pdata += 8;
3997 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3998 pdata += 8;
4000 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4001 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4002 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4003 pdata += 24;
4005 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4006 SIVAL(pdata,4,0);
4007 pdata += 8;
4009 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4010 SIVAL(pdata,4,0);
4011 pdata += 8;
4013 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4014 pdata += 4;
4016 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4017 devno = psbuf->st_ex_rdev;
4018 } else {
4019 devno = psbuf->st_ex_dev;
4022 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4023 SIVAL(pdata,4,0);
4024 pdata += 8;
4026 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4027 SIVAL(pdata,4,0);
4028 pdata += 8;
4030 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4031 pdata += 8;
4033 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4034 SIVAL(pdata,4,0);
4035 pdata += 8;
4037 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4038 SIVAL(pdata,4,0);
4039 pdata += 8;
4041 return pdata;
4044 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4045 * the chflags(2) (or equivalent) flags.
4047 * XXX: this really should be behind the VFS interface. To do this, we would
4048 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4049 * Each VFS module could then implement its own mapping as appropriate for the
4050 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4052 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4053 info2_flags_map[] =
4055 #ifdef UF_NODUMP
4056 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4057 #endif
4059 #ifdef UF_IMMUTABLE
4060 { UF_IMMUTABLE, EXT_IMMUTABLE },
4061 #endif
4063 #ifdef UF_APPEND
4064 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4065 #endif
4067 #ifdef UF_HIDDEN
4068 { UF_HIDDEN, EXT_HIDDEN },
4069 #endif
4071 /* Do not remove. We need to guarantee that this array has at least one
4072 * entry to build on HP-UX.
4074 { 0, 0 }
4078 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4079 uint32 *smb_fflags, uint32 *smb_fmask)
4081 int i;
4083 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4084 *smb_fmask |= info2_flags_map[i].smb_fflag;
4085 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4086 *smb_fflags |= info2_flags_map[i].smb_fflag;
4091 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4092 const uint32 smb_fflags,
4093 const uint32 smb_fmask,
4094 int *stat_fflags)
4096 uint32 max_fmask = 0;
4097 int i;
4099 *stat_fflags = psbuf->st_ex_flags;
4101 /* For each flags requested in smb_fmask, check the state of the
4102 * corresponding flag in smb_fflags and set or clear the matching
4103 * stat flag.
4106 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4107 max_fmask |= info2_flags_map[i].smb_fflag;
4108 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4109 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4110 *stat_fflags |= info2_flags_map[i].stat_fflag;
4111 } else {
4112 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4117 /* If smb_fmask is asking to set any bits that are not supported by
4118 * our flag mappings, we should fail.
4120 if ((smb_fmask & max_fmask) != smb_fmask) {
4121 return False;
4124 return True;
4128 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4129 * of file flags and birth (create) time.
4131 static char *store_file_unix_basic_info2(connection_struct *conn,
4132 char *pdata,
4133 files_struct *fsp,
4134 const SMB_STRUCT_STAT *psbuf)
4136 uint32 file_flags = 0;
4137 uint32 flags_mask = 0;
4139 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4141 /* Create (birth) time 64 bit */
4142 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4143 pdata += 8;
4145 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4146 SIVAL(pdata, 0, file_flags); /* flags */
4147 SIVAL(pdata, 4, flags_mask); /* mask */
4148 pdata += 8;
4150 return pdata;
4153 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4154 const struct stream_struct *streams,
4155 char *data,
4156 unsigned int max_data_bytes,
4157 unsigned int *data_size)
4159 unsigned int i;
4160 unsigned int ofs = 0;
4162 for (i = 0; i < num_streams; i++) {
4163 unsigned int next_offset;
4164 size_t namelen;
4165 smb_ucs2_t *namebuf;
4167 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4168 streams[i].name, &namelen) ||
4169 namelen <= 2)
4171 return NT_STATUS_INVALID_PARAMETER;
4175 * name_buf is now null-terminated, we need to marshall as not
4176 * terminated
4179 namelen -= 2;
4182 * We cannot overflow ...
4184 if ((ofs + 24 + namelen) > max_data_bytes) {
4185 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4186 i));
4187 TALLOC_FREE(namebuf);
4188 return STATUS_BUFFER_OVERFLOW;
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 if ((next_offset + align) > max_data_bytes) {
4206 DEBUG(10, ("refusing to overflow align "
4207 "reply at stream %u\n",
4208 i));
4209 TALLOC_FREE(namebuf);
4210 return STATUS_BUFFER_OVERFLOW;
4213 memset(data+next_offset, 0, align);
4214 next_offset += align;
4216 SIVAL(data, ofs, next_offset - ofs);
4217 ofs = next_offset;
4220 ofs = next_offset;
4223 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4225 *data_size = ofs;
4227 return NT_STATUS_OK;
4230 /****************************************************************************
4231 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4232 ****************************************************************************/
4234 static void call_trans2qpipeinfo(connection_struct *conn,
4235 struct smb_request *req,
4236 unsigned int tran_call,
4237 char **pparams, int total_params,
4238 char **ppdata, int total_data,
4239 unsigned int max_data_bytes)
4241 char *params = *pparams;
4242 char *pdata = *ppdata;
4243 unsigned int data_size = 0;
4244 unsigned int param_size = 2;
4245 uint16 info_level;
4246 files_struct *fsp;
4248 if (!params) {
4249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4250 return;
4253 if (total_params < 4) {
4254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4255 return;
4258 fsp = file_fsp(req, SVAL(params,0));
4259 if (!fsp_is_np(fsp)) {
4260 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4261 return;
4264 info_level = SVAL(params,2);
4266 *pparams = (char *)SMB_REALLOC(*pparams,2);
4267 if (*pparams == NULL) {
4268 reply_nterror(req, NT_STATUS_NO_MEMORY);
4269 return;
4271 params = *pparams;
4272 SSVAL(params,0,0);
4273 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4274 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4275 if (*ppdata == NULL ) {
4276 reply_nterror(req, NT_STATUS_NO_MEMORY);
4277 return;
4279 pdata = *ppdata;
4281 switch (info_level) {
4282 case SMB_FILE_STANDARD_INFORMATION:
4283 memset(pdata,0,24);
4284 SOFF_T(pdata,0,4096LL);
4285 SIVAL(pdata,16,1);
4286 SIVAL(pdata,20,1);
4287 data_size = 24;
4288 break;
4290 default:
4291 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4292 return;
4295 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4296 max_data_bytes);
4298 return;
4301 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4302 TALLOC_CTX *mem_ctx,
4303 uint16_t info_level,
4304 files_struct *fsp,
4305 struct smb_filename *smb_fname,
4306 bool delete_pending,
4307 struct timespec write_time_ts,
4308 struct ea_list *ea_list,
4309 int lock_data_count,
4310 char *lock_data,
4311 uint16_t flags2,
4312 unsigned int max_data_bytes,
4313 char **ppdata,
4314 unsigned int *pdata_size)
4316 char *pdata = *ppdata;
4317 char *dstart, *dend;
4318 unsigned int data_size;
4319 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4320 time_t create_time, mtime, atime, c_time;
4321 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4322 char *p;
4323 char *base_name;
4324 char *dos_fname;
4325 int mode;
4326 int nlink;
4327 NTSTATUS status;
4328 uint64_t file_size = 0;
4329 uint64_t pos = 0;
4330 uint64_t allocation_size = 0;
4331 uint64_t file_index = 0;
4332 uint32_t access_mask = 0;
4334 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4335 return NT_STATUS_INVALID_LEVEL;
4338 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4339 smb_fname_str_dbg(smb_fname),
4340 fsp_fnum_dbg(fsp),
4341 info_level, max_data_bytes));
4343 mode = dos_mode(conn, smb_fname);
4344 nlink = psbuf->st_ex_nlink;
4346 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4347 nlink = 1;
4350 if ((nlink > 0) && delete_pending) {
4351 nlink -= 1;
4354 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4355 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4356 if (*ppdata == NULL) {
4357 return NT_STATUS_NO_MEMORY;
4359 pdata = *ppdata;
4360 dstart = pdata;
4361 dend = dstart + data_size - 1;
4363 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4364 update_stat_ex_mtime(psbuf, write_time_ts);
4367 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4368 mtime_ts = psbuf->st_ex_mtime;
4369 atime_ts = psbuf->st_ex_atime;
4370 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4372 if (lp_dos_filetime_resolution(SNUM(conn))) {
4373 dos_filetime_timespec(&create_time_ts);
4374 dos_filetime_timespec(&mtime_ts);
4375 dos_filetime_timespec(&atime_ts);
4376 dos_filetime_timespec(&ctime_ts);
4379 create_time = convert_timespec_to_time_t(create_time_ts);
4380 mtime = convert_timespec_to_time_t(mtime_ts);
4381 atime = convert_timespec_to_time_t(atime_ts);
4382 c_time = convert_timespec_to_time_t(ctime_ts);
4384 p = strrchr_m(smb_fname->base_name,'/');
4385 if (!p)
4386 base_name = smb_fname->base_name;
4387 else
4388 base_name = p+1;
4390 /* NT expects the name to be in an exact form of the *full*
4391 filename. See the trans2 torture test */
4392 if (ISDOT(base_name)) {
4393 dos_fname = talloc_strdup(mem_ctx, "\\");
4394 if (!dos_fname) {
4395 return NT_STATUS_NO_MEMORY;
4397 } else {
4398 dos_fname = talloc_asprintf(mem_ctx,
4399 "\\%s",
4400 smb_fname->base_name);
4401 if (!dos_fname) {
4402 return NT_STATUS_NO_MEMORY;
4404 if (is_ntfs_stream_smb_fname(smb_fname)) {
4405 dos_fname = talloc_asprintf(dos_fname, "%s",
4406 smb_fname->stream_name);
4407 if (!dos_fname) {
4408 return NT_STATUS_NO_MEMORY;
4412 string_replace(dos_fname, '/', '\\');
4415 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4417 if (!fsp) {
4418 /* Do we have this path open ? */
4419 files_struct *fsp1;
4420 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4421 fsp1 = file_find_di_first(conn->sconn, fileid);
4422 if (fsp1 && fsp1->initial_allocation_size) {
4423 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4427 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4428 file_size = get_file_size_stat(psbuf);
4431 if (fsp) {
4432 pos = fsp->fh->position_information;
4435 if (fsp) {
4436 access_mask = fsp->access_mask;
4437 } else {
4438 /* GENERIC_EXECUTE mapping from Windows */
4439 access_mask = 0x12019F;
4442 /* This should be an index number - looks like
4443 dev/ino to me :-)
4445 I think this causes us to fail the IFSKIT
4446 BasicFileInformationTest. -tpot */
4447 file_index = get_FileIndex(conn, psbuf);
4449 switch (info_level) {
4450 case SMB_INFO_STANDARD:
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4452 data_size = 22;
4453 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4454 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4455 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4456 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4457 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4458 SSVAL(pdata,l1_attrFile,mode);
4459 break;
4461 case SMB_INFO_QUERY_EA_SIZE:
4463 unsigned int ea_size =
4464 estimate_ea_size(conn, fsp,
4465 smb_fname);
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4467 data_size = 26;
4468 srv_put_dos_date2(pdata,0,create_time);
4469 srv_put_dos_date2(pdata,4,atime);
4470 srv_put_dos_date2(pdata,8,mtime); /* write time */
4471 SIVAL(pdata,12,(uint32)file_size);
4472 SIVAL(pdata,16,(uint32)allocation_size);
4473 SSVAL(pdata,20,mode);
4474 SIVAL(pdata,22,ea_size);
4475 break;
4478 case SMB_INFO_IS_NAME_VALID:
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4480 if (fsp) {
4481 /* os/2 needs this ? really ?*/
4482 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4484 /* This is only reached for qpathinfo */
4485 data_size = 0;
4486 break;
4488 case SMB_INFO_QUERY_EAS_FROM_LIST:
4490 size_t total_ea_len = 0;
4491 struct ea_list *ea_file_list = NULL;
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4494 status =
4495 get_ea_list_from_file(mem_ctx, conn, fsp,
4496 smb_fname,
4497 &total_ea_len, &ea_file_list);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 return status;
4502 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4504 if (!ea_list || (total_ea_len > data_size)) {
4505 data_size = 4;
4506 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4507 break;
4510 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4511 break;
4514 case SMB_INFO_QUERY_ALL_EAS:
4516 /* We have data_size bytes to put EA's into. */
4517 size_t total_ea_len = 0;
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4520 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4521 smb_fname,
4522 &total_ea_len, &ea_list);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 return status;
4527 if (!ea_list || (total_ea_len > data_size)) {
4528 data_size = 4;
4529 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4530 break;
4533 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4534 break;
4537 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4539 /* This is FileFullEaInformation - 0xF which maps to
4540 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4542 /* We have data_size bytes to put EA's into. */
4543 size_t total_ea_len = 0;
4544 struct ea_list *ea_file_list = NULL;
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4548 /*TODO: add filtering and index handling */
4550 status =
4551 get_ea_list_from_file(mem_ctx, conn, fsp,
4552 smb_fname,
4553 &total_ea_len, &ea_file_list);
4554 if (!NT_STATUS_IS_OK(status)) {
4555 return status;
4557 if (!ea_file_list) {
4558 return NT_STATUS_NO_EAS_ON_FILE;
4561 status = fill_ea_chained_buffer(mem_ctx,
4562 pdata,
4563 data_size,
4564 &data_size,
4565 conn, ea_file_list);
4566 if (!NT_STATUS_IS_OK(status)) {
4567 return status;
4569 break;
4572 case SMB_FILE_BASIC_INFORMATION:
4573 case SMB_QUERY_FILE_BASIC_INFO:
4575 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4576 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4577 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4578 } else {
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4580 data_size = 40;
4581 SIVAL(pdata,36,0);
4583 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4584 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4585 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4586 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4587 SIVAL(pdata,32,mode);
4589 DEBUG(5,("SMB_QFBI - "));
4590 DEBUG(5,("create: %s ", ctime(&create_time)));
4591 DEBUG(5,("access: %s ", ctime(&atime)));
4592 DEBUG(5,("write: %s ", ctime(&mtime)));
4593 DEBUG(5,("change: %s ", ctime(&c_time)));
4594 DEBUG(5,("mode: %x\n", mode));
4595 break;
4597 case SMB_FILE_STANDARD_INFORMATION:
4598 case SMB_QUERY_FILE_STANDARD_INFO:
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4601 data_size = 24;
4602 SOFF_T(pdata,0,allocation_size);
4603 SOFF_T(pdata,8,file_size);
4604 SIVAL(pdata,16,nlink);
4605 SCVAL(pdata,20,delete_pending?1:0);
4606 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4607 SSVAL(pdata,22,0); /* Padding. */
4608 break;
4610 case SMB_FILE_EA_INFORMATION:
4611 case SMB_QUERY_FILE_EA_INFO:
4613 unsigned int ea_size =
4614 estimate_ea_size(conn, fsp, smb_fname);
4615 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4616 data_size = 4;
4617 SIVAL(pdata,0,ea_size);
4618 break;
4621 /* Get the 8.3 name - used if NT SMB was negotiated. */
4622 case SMB_QUERY_FILE_ALT_NAME_INFO:
4623 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4625 int len;
4626 char mangled_name[13];
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4628 if (!name_to_8_3(base_name,mangled_name,
4629 True,conn->params)) {
4630 return NT_STATUS_NO_MEMORY;
4632 len = srvstr_push(dstart, flags2,
4633 pdata+4, mangled_name,
4634 PTR_DIFF(dend, pdata+4),
4635 STR_UNICODE);
4636 data_size = 4 + len;
4637 SIVAL(pdata,0,len);
4638 break;
4641 case SMB_QUERY_FILE_NAME_INFO:
4643 int len;
4645 this must be *exactly* right for ACLs on mapped drives to work
4647 len = srvstr_push(dstart, flags2,
4648 pdata+4, dos_fname,
4649 PTR_DIFF(dend, pdata+4),
4650 STR_UNICODE);
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4652 data_size = 4 + len;
4653 SIVAL(pdata,0,len);
4654 break;
4657 case SMB_FILE_ALLOCATION_INFORMATION:
4658 case SMB_QUERY_FILE_ALLOCATION_INFO:
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4660 data_size = 8;
4661 SOFF_T(pdata,0,allocation_size);
4662 break;
4664 case SMB_FILE_END_OF_FILE_INFORMATION:
4665 case SMB_QUERY_FILE_END_OF_FILEINFO:
4666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4667 data_size = 8;
4668 SOFF_T(pdata,0,file_size);
4669 break;
4671 case SMB_QUERY_FILE_ALL_INFO:
4672 case SMB_FILE_ALL_INFORMATION:
4674 int len;
4675 unsigned int ea_size =
4676 estimate_ea_size(conn, fsp, smb_fname);
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4678 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4679 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4680 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4681 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4682 SIVAL(pdata,32,mode);
4683 SIVAL(pdata,36,0); /* padding. */
4684 pdata += 40;
4685 SOFF_T(pdata,0,allocation_size);
4686 SOFF_T(pdata,8,file_size);
4687 SIVAL(pdata,16,nlink);
4688 SCVAL(pdata,20,delete_pending);
4689 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4690 SSVAL(pdata,22,0);
4691 pdata += 24;
4692 SIVAL(pdata,0,ea_size);
4693 pdata += 4; /* EA info */
4694 len = srvstr_push(dstart, flags2,
4695 pdata+4, dos_fname,
4696 PTR_DIFF(dend, pdata+4),
4697 STR_UNICODE);
4698 SIVAL(pdata,0,len);
4699 pdata += 4 + len;
4700 data_size = PTR_DIFF(pdata,(*ppdata));
4701 break;
4704 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4706 int len;
4707 unsigned int ea_size =
4708 estimate_ea_size(conn, fsp, smb_fname);
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4710 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4711 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4712 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4713 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4714 SIVAL(pdata, 0x20, mode);
4715 SIVAL(pdata, 0x24, 0); /* padding. */
4716 SBVAL(pdata, 0x28, allocation_size);
4717 SBVAL(pdata, 0x30, file_size);
4718 SIVAL(pdata, 0x38, nlink);
4719 SCVAL(pdata, 0x3C, delete_pending);
4720 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4721 SSVAL(pdata, 0x3E, 0); /* padding */
4722 SBVAL(pdata, 0x40, file_index);
4723 SIVAL(pdata, 0x48, ea_size);
4724 SIVAL(pdata, 0x4C, access_mask);
4725 SBVAL(pdata, 0x50, pos);
4726 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4727 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4729 pdata += 0x60;
4731 len = srvstr_push(dstart, flags2,
4732 pdata+4, dos_fname,
4733 PTR_DIFF(dend, pdata+4),
4734 STR_UNICODE);
4735 SIVAL(pdata,0,len);
4736 pdata += 4 + len;
4737 data_size = PTR_DIFF(pdata,(*ppdata));
4738 break;
4740 case SMB_FILE_INTERNAL_INFORMATION:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4743 SBVAL(pdata, 0, file_index);
4744 data_size = 8;
4745 break;
4747 case SMB_FILE_ACCESS_INFORMATION:
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4749 SIVAL(pdata, 0, access_mask);
4750 data_size = 4;
4751 break;
4753 case SMB_FILE_NAME_INFORMATION:
4754 /* Pathname with leading '\'. */
4756 size_t byte_len;
4757 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4759 SIVAL(pdata,0,byte_len);
4760 data_size = 4 + byte_len;
4761 break;
4764 case SMB_FILE_DISPOSITION_INFORMATION:
4765 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4766 data_size = 1;
4767 SCVAL(pdata,0,delete_pending);
4768 break;
4770 case SMB_FILE_POSITION_INFORMATION:
4771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4772 data_size = 8;
4773 SOFF_T(pdata,0,pos);
4774 break;
4776 case SMB_FILE_MODE_INFORMATION:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4778 SIVAL(pdata,0,mode);
4779 data_size = 4;
4780 break;
4782 case SMB_FILE_ALIGNMENT_INFORMATION:
4783 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4784 SIVAL(pdata,0,0); /* No alignment needed. */
4785 data_size = 4;
4786 break;
4789 * NT4 server just returns "invalid query" to this - if we try
4790 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4791 * want this. JRA.
4793 /* The first statement above is false - verified using Thursby
4794 * client against NT4 -- gcolley.
4796 case SMB_QUERY_FILE_STREAM_INFO:
4797 case SMB_FILE_STREAM_INFORMATION: {
4798 unsigned int num_streams = 0;
4799 struct stream_struct *streams = NULL;
4801 DEBUG(10,("smbd_do_qfilepathinfo: "
4802 "SMB_FILE_STREAM_INFORMATION\n"));
4804 if (is_ntfs_stream_smb_fname(smb_fname)) {
4805 return NT_STATUS_INVALID_PARAMETER;
4808 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4809 talloc_tos(), &num_streams, &streams);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 DEBUG(10, ("could not get stream info: %s\n",
4813 nt_errstr(status)));
4814 return status;
4817 status = marshall_stream_info(num_streams, streams,
4818 pdata, max_data_bytes,
4819 &data_size);
4821 if (!NT_STATUS_IS_OK(status)) {
4822 DEBUG(10, ("marshall_stream_info failed: %s\n",
4823 nt_errstr(status)));
4824 TALLOC_FREE(streams);
4825 return status;
4828 TALLOC_FREE(streams);
4830 break;
4832 case SMB_QUERY_COMPRESSION_INFO:
4833 case SMB_FILE_COMPRESSION_INFORMATION:
4834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4835 SOFF_T(pdata,0,file_size);
4836 SIVAL(pdata,8,0); /* ??? */
4837 SIVAL(pdata,12,0); /* ??? */
4838 data_size = 16;
4839 break;
4841 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4842 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4843 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4844 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4845 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4846 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4847 SOFF_T(pdata,32,allocation_size);
4848 SOFF_T(pdata,40,file_size);
4849 SIVAL(pdata,48,mode);
4850 SIVAL(pdata,52,0); /* ??? */
4851 data_size = 56;
4852 break;
4854 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4856 SIVAL(pdata,0,mode);
4857 SIVAL(pdata,4,0);
4858 data_size = 8;
4859 break;
4862 * CIFS UNIX Extensions.
4865 case SMB_QUERY_FILE_UNIX_BASIC:
4867 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4868 data_size = PTR_DIFF(pdata,(*ppdata));
4870 DEBUG(4,("smbd_do_qfilepathinfo: "
4871 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4872 dump_data(4, (uint8_t *)(*ppdata), data_size);
4874 break;
4876 case SMB_QUERY_FILE_UNIX_INFO2:
4878 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4879 data_size = PTR_DIFF(pdata,(*ppdata));
4882 int i;
4883 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4885 for (i=0; i<100; i++)
4886 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4887 DEBUG(4,("\n"));
4890 break;
4892 case SMB_QUERY_FILE_UNIX_LINK:
4894 int len;
4895 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4897 if (!buffer) {
4898 return NT_STATUS_NO_MEMORY;
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4902 #ifdef S_ISLNK
4903 if(!S_ISLNK(psbuf->st_ex_mode)) {
4904 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4906 #else
4907 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4908 #endif
4909 len = SMB_VFS_READLINK(conn,
4910 smb_fname->base_name,
4911 buffer, PATH_MAX);
4912 if (len == -1) {
4913 return map_nt_error_from_unix(errno);
4915 buffer[len] = 0;
4916 len = srvstr_push(dstart, flags2,
4917 pdata, buffer,
4918 PTR_DIFF(dend, pdata),
4919 STR_TERMINATE);
4920 pdata += len;
4921 data_size = PTR_DIFF(pdata,(*ppdata));
4923 break;
4926 #if defined(HAVE_POSIX_ACLS)
4927 case SMB_QUERY_POSIX_ACL:
4929 SMB_ACL_T file_acl = NULL;
4930 SMB_ACL_T def_acl = NULL;
4931 uint16 num_file_acls = 0;
4932 uint16 num_def_acls = 0;
4934 if (fsp && fsp->fh->fd != -1) {
4935 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4936 talloc_tos());
4937 } else {
4938 file_acl =
4939 SMB_VFS_SYS_ACL_GET_FILE(conn,
4940 smb_fname->base_name,
4941 SMB_ACL_TYPE_ACCESS,
4942 talloc_tos());
4945 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4946 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4947 "not implemented on "
4948 "filesystem containing %s\n",
4949 smb_fname->base_name));
4950 return NT_STATUS_NOT_IMPLEMENTED;
4953 if (S_ISDIR(psbuf->st_ex_mode)) {
4954 if (fsp && fsp->is_directory) {
4955 def_acl =
4956 SMB_VFS_SYS_ACL_GET_FILE(
4957 conn,
4958 fsp->fsp_name->base_name,
4959 SMB_ACL_TYPE_DEFAULT,
4960 talloc_tos());
4961 } else {
4962 def_acl =
4963 SMB_VFS_SYS_ACL_GET_FILE(
4964 conn,
4965 smb_fname->base_name,
4966 SMB_ACL_TYPE_DEFAULT,
4967 talloc_tos());
4969 def_acl = free_empty_sys_acl(conn, def_acl);
4972 num_file_acls = count_acl_entries(conn, file_acl);
4973 num_def_acls = count_acl_entries(conn, def_acl);
4975 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4976 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4977 data_size,
4978 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4979 SMB_POSIX_ACL_HEADER_SIZE) ));
4980 if (file_acl) {
4981 TALLOC_FREE(file_acl);
4983 if (def_acl) {
4984 TALLOC_FREE(def_acl);
4986 return NT_STATUS_BUFFER_TOO_SMALL;
4989 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4990 SSVAL(pdata,2,num_file_acls);
4991 SSVAL(pdata,4,num_def_acls);
4992 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4993 if (file_acl) {
4994 TALLOC_FREE(file_acl);
4996 if (def_acl) {
4997 TALLOC_FREE(def_acl);
4999 return NT_STATUS_INTERNAL_ERROR;
5001 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5002 if (file_acl) {
5003 TALLOC_FREE(file_acl);
5005 if (def_acl) {
5006 TALLOC_FREE(def_acl);
5008 return NT_STATUS_INTERNAL_ERROR;
5011 if (file_acl) {
5012 TALLOC_FREE(file_acl);
5014 if (def_acl) {
5015 TALLOC_FREE(def_acl);
5017 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5018 break;
5020 #endif
5023 case SMB_QUERY_POSIX_LOCK:
5025 uint64_t count;
5026 uint64_t offset;
5027 uint64_t smblctx;
5028 enum brl_type lock_type;
5030 /* We need an open file with a real fd for this. */
5031 if (!fsp || fsp->fh->fd == -1) {
5032 return NT_STATUS_INVALID_LEVEL;
5035 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5036 return NT_STATUS_INVALID_PARAMETER;
5039 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5040 case POSIX_LOCK_TYPE_READ:
5041 lock_type = READ_LOCK;
5042 break;
5043 case POSIX_LOCK_TYPE_WRITE:
5044 lock_type = WRITE_LOCK;
5045 break;
5046 case POSIX_LOCK_TYPE_UNLOCK:
5047 default:
5048 /* There's no point in asking for an unlock... */
5049 return NT_STATUS_INVALID_PARAMETER;
5052 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5053 #if defined(HAVE_LONGLONG)
5054 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5055 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5056 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5057 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5058 #else /* HAVE_LONGLONG */
5059 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5060 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5061 #endif /* HAVE_LONGLONG */
5063 status = query_lock(fsp,
5064 &smblctx,
5065 &count,
5066 &offset,
5067 &lock_type,
5068 POSIX_LOCK);
5070 if (ERROR_WAS_LOCK_DENIED(status)) {
5071 /* Here we need to report who has it locked... */
5072 data_size = POSIX_LOCK_DATA_SIZE;
5074 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5075 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5076 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5077 #if defined(HAVE_LONGLONG)
5078 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5079 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5080 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5081 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5082 #else /* HAVE_LONGLONG */
5083 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5084 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5085 #endif /* HAVE_LONGLONG */
5087 } else if (NT_STATUS_IS_OK(status)) {
5088 /* For success we just return a copy of what we sent
5089 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5090 data_size = POSIX_LOCK_DATA_SIZE;
5091 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5092 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5093 } else {
5094 return status;
5096 break;
5099 default:
5100 return NT_STATUS_INVALID_LEVEL;
5103 *pdata_size = data_size;
5104 return NT_STATUS_OK;
5107 /****************************************************************************
5108 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5109 file name or file id).
5110 ****************************************************************************/
5112 static void call_trans2qfilepathinfo(connection_struct *conn,
5113 struct smb_request *req,
5114 unsigned int tran_call,
5115 char **pparams, int total_params,
5116 char **ppdata, int total_data,
5117 unsigned int max_data_bytes)
5119 char *params = *pparams;
5120 char *pdata = *ppdata;
5121 uint16 info_level;
5122 unsigned int data_size = 0;
5123 unsigned int param_size = 2;
5124 struct smb_filename *smb_fname = NULL;
5125 bool delete_pending = False;
5126 struct timespec write_time_ts;
5127 files_struct *fsp = NULL;
5128 struct file_id fileid;
5129 struct ea_list *ea_list = NULL;
5130 int lock_data_count = 0;
5131 char *lock_data = NULL;
5132 NTSTATUS status = NT_STATUS_OK;
5134 if (!params) {
5135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5136 return;
5139 ZERO_STRUCT(write_time_ts);
5141 if (tran_call == TRANSACT2_QFILEINFO) {
5142 if (total_params < 4) {
5143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5144 return;
5147 if (IS_IPC(conn)) {
5148 call_trans2qpipeinfo(conn, req, tran_call,
5149 pparams, total_params,
5150 ppdata, total_data,
5151 max_data_bytes);
5152 return;
5155 fsp = file_fsp(req, SVAL(params,0));
5156 info_level = SVAL(params,2);
5158 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5160 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5161 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5162 return;
5165 /* Initial check for valid fsp ptr. */
5166 if (!check_fsp_open(conn, req, fsp)) {
5167 return;
5170 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5171 &smb_fname);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 return;
5177 if(fsp->fake_file_handle) {
5179 * This is actually for the QUOTA_FAKE_FILE --metze
5182 /* We know this name is ok, it's already passed the checks. */
5184 } else if(fsp->fh->fd == -1) {
5186 * This is actually a QFILEINFO on a directory
5187 * handle (returned from an NT SMB). NT5.0 seems
5188 * to do this call. JRA.
5191 if (INFO_LEVEL_IS_UNIX(info_level)) {
5192 /* Always do lstat for UNIX calls. */
5193 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5194 DEBUG(3,("call_trans2qfilepathinfo: "
5195 "SMB_VFS_LSTAT of %s failed "
5196 "(%s)\n",
5197 smb_fname_str_dbg(smb_fname),
5198 strerror(errno)));
5199 reply_nterror(req,
5200 map_nt_error_from_unix(errno));
5201 return;
5203 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5204 DEBUG(3,("call_trans2qfilepathinfo: "
5205 "SMB_VFS_STAT of %s failed (%s)\n",
5206 smb_fname_str_dbg(smb_fname),
5207 strerror(errno)));
5208 reply_nterror(req,
5209 map_nt_error_from_unix(errno));
5210 return;
5213 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5214 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5215 } else {
5217 * Original code - this is an open file.
5219 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5220 DEBUG(3, ("fstat of %s failed (%s)\n",
5221 fsp_fnum_dbg(fsp), strerror(errno)));
5222 reply_nterror(req,
5223 map_nt_error_from_unix(errno));
5224 return;
5226 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5227 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5230 } else {
5231 uint32_t name_hash;
5232 char *fname = NULL;
5233 uint32_t ucf_flags = 0;
5235 /* qpathinfo */
5236 if (total_params < 7) {
5237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5238 return;
5241 info_level = SVAL(params,0);
5243 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5245 if (INFO_LEVEL_IS_UNIX(info_level)) {
5246 if (!lp_unix_extensions()) {
5247 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5248 return;
5250 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5251 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5252 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5253 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5257 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5258 total_params - 6,
5259 STR_TERMINATE, &status);
5260 if (!NT_STATUS_IS_OK(status)) {
5261 reply_nterror(req, status);
5262 return;
5265 status = filename_convert(req,
5266 conn,
5267 req->flags2 & FLAGS2_DFS_PATHNAMES,
5268 fname,
5269 ucf_flags,
5270 NULL,
5271 &smb_fname);
5272 if (!NT_STATUS_IS_OK(status)) {
5273 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5274 reply_botherror(req,
5275 NT_STATUS_PATH_NOT_COVERED,
5276 ERRSRV, ERRbadpath);
5277 return;
5279 reply_nterror(req, status);
5280 return;
5283 /* If this is a stream, check if there is a delete_pending. */
5284 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5285 && is_ntfs_stream_smb_fname(smb_fname)) {
5286 struct smb_filename *smb_fname_base = NULL;
5288 /* Create an smb_filename with stream_name == NULL. */
5289 status =
5290 create_synthetic_smb_fname(talloc_tos(),
5291 smb_fname->base_name,
5292 NULL, NULL,
5293 &smb_fname_base);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 reply_nterror(req, status);
5296 return;
5299 if (INFO_LEVEL_IS_UNIX(info_level)) {
5300 /* Always do lstat for UNIX calls. */
5301 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5302 DEBUG(3,("call_trans2qfilepathinfo: "
5303 "SMB_VFS_LSTAT of %s failed "
5304 "(%s)\n",
5305 smb_fname_str_dbg(smb_fname_base),
5306 strerror(errno)));
5307 TALLOC_FREE(smb_fname_base);
5308 reply_nterror(req,
5309 map_nt_error_from_unix(errno));
5310 return;
5312 } else {
5313 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5314 DEBUG(3,("call_trans2qfilepathinfo: "
5315 "fileinfo of %s failed "
5316 "(%s)\n",
5317 smb_fname_str_dbg(smb_fname_base),
5318 strerror(errno)));
5319 TALLOC_FREE(smb_fname_base);
5320 reply_nterror(req,
5321 map_nt_error_from_unix(errno));
5322 return;
5326 status = file_name_hash(conn,
5327 smb_fname_str_dbg(smb_fname_base),
5328 &name_hash);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 TALLOC_FREE(smb_fname_base);
5331 reply_nterror(req, status);
5332 return;
5335 fileid = vfs_file_id_from_sbuf(conn,
5336 &smb_fname_base->st);
5337 TALLOC_FREE(smb_fname_base);
5338 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5339 if (delete_pending) {
5340 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5341 return;
5345 if (INFO_LEVEL_IS_UNIX(info_level)) {
5346 /* Always do lstat for UNIX calls. */
5347 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5348 DEBUG(3,("call_trans2qfilepathinfo: "
5349 "SMB_VFS_LSTAT of %s failed (%s)\n",
5350 smb_fname_str_dbg(smb_fname),
5351 strerror(errno)));
5352 reply_nterror(req,
5353 map_nt_error_from_unix(errno));
5354 return;
5357 } else {
5358 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5359 DEBUG(3,("call_trans2qfilepathinfo: "
5360 "SMB_VFS_STAT of %s failed (%s)\n",
5361 smb_fname_str_dbg(smb_fname),
5362 strerror(errno)));
5363 reply_nterror(req,
5364 map_nt_error_from_unix(errno));
5365 return;
5369 status = file_name_hash(conn,
5370 smb_fname_str_dbg(smb_fname),
5371 &name_hash);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 reply_nterror(req, status);
5374 return;
5377 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5378 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5379 if (delete_pending) {
5380 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5381 return;
5385 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5386 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5387 fsp_fnum_dbg(fsp),
5388 info_level,tran_call,total_data));
5390 /* Pull out any data sent here before we realloc. */
5391 switch (info_level) {
5392 case SMB_INFO_QUERY_EAS_FROM_LIST:
5394 /* Pull any EA list from the data portion. */
5395 uint32 ea_size;
5397 if (total_data < 4) {
5398 reply_nterror(
5399 req, NT_STATUS_INVALID_PARAMETER);
5400 return;
5402 ea_size = IVAL(pdata,0);
5404 if (total_data > 0 && ea_size != total_data) {
5405 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5406 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5407 reply_nterror(
5408 req, NT_STATUS_INVALID_PARAMETER);
5409 return;
5412 if (!lp_ea_support(SNUM(conn))) {
5413 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5414 return;
5417 /* Pull out the list of names. */
5418 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5419 if (!ea_list) {
5420 reply_nterror(
5421 req, NT_STATUS_INVALID_PARAMETER);
5422 return;
5424 break;
5427 case SMB_QUERY_POSIX_LOCK:
5429 if (fsp == NULL || fsp->fh->fd == -1) {
5430 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5431 return;
5434 if (total_data != POSIX_LOCK_DATA_SIZE) {
5435 reply_nterror(
5436 req, NT_STATUS_INVALID_PARAMETER);
5437 return;
5440 /* Copy the lock range data. */
5441 lock_data = (char *)talloc_memdup(
5442 req, pdata, total_data);
5443 if (!lock_data) {
5444 reply_nterror(req, NT_STATUS_NO_MEMORY);
5445 return;
5447 lock_data_count = total_data;
5449 default:
5450 break;
5453 *pparams = (char *)SMB_REALLOC(*pparams,2);
5454 if (*pparams == NULL) {
5455 reply_nterror(req, NT_STATUS_NO_MEMORY);
5456 return;
5458 params = *pparams;
5459 SSVAL(params,0,0);
5462 * draft-leach-cifs-v1-spec-02.txt
5463 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5464 * says:
5466 * The requested information is placed in the Data portion of the
5467 * transaction response. For the information levels greater than 0x100,
5468 * the transaction response has 1 parameter word which should be
5469 * ignored by the client.
5471 * However Windows only follows this rule for the IS_NAME_VALID call.
5473 switch (info_level) {
5474 case SMB_INFO_IS_NAME_VALID:
5475 param_size = 0;
5476 break;
5479 if ((info_level & 0xFF00) == 0xFF00) {
5481 * We use levels that start with 0xFF00
5482 * internally to represent SMB2 specific levels
5484 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5485 return;
5488 status = smbd_do_qfilepathinfo(conn, req, info_level,
5489 fsp, smb_fname,
5490 delete_pending, write_time_ts,
5491 ea_list,
5492 lock_data_count, lock_data,
5493 req->flags2, max_data_bytes,
5494 ppdata, &data_size);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 reply_nterror(req, status);
5497 return;
5500 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5501 max_data_bytes);
5503 return;
5506 /****************************************************************************
5507 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5508 code.
5509 ****************************************************************************/
5511 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5512 connection_struct *conn,
5513 struct smb_request *req,
5514 bool overwrite_if_exists,
5515 const struct smb_filename *smb_fname_old,
5516 struct smb_filename *smb_fname_new)
5518 NTSTATUS status = NT_STATUS_OK;
5520 /* source must already exist. */
5521 if (!VALID_STAT(smb_fname_old->st)) {
5522 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5525 if (VALID_STAT(smb_fname_new->st)) {
5526 if (overwrite_if_exists) {
5527 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5528 return NT_STATUS_FILE_IS_A_DIRECTORY;
5530 status = unlink_internals(conn,
5531 req,
5532 FILE_ATTRIBUTE_NORMAL,
5533 smb_fname_new,
5534 false);
5535 if (!NT_STATUS_IS_OK(status)) {
5536 return status;
5538 } else {
5539 /* Disallow if newname already exists. */
5540 return NT_STATUS_OBJECT_NAME_COLLISION;
5544 /* No links from a directory. */
5545 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5546 return NT_STATUS_FILE_IS_A_DIRECTORY;
5549 /* Setting a hardlink to/from a stream isn't currently supported. */
5550 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5551 is_ntfs_stream_smb_fname(smb_fname_new)) {
5552 return NT_STATUS_INVALID_PARAMETER;
5555 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5556 smb_fname_old->base_name, smb_fname_new->base_name));
5558 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5559 smb_fname_new->base_name) != 0) {
5560 status = map_nt_error_from_unix(errno);
5561 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5562 nt_errstr(status), smb_fname_old->base_name,
5563 smb_fname_new->base_name));
5565 return status;
5568 /****************************************************************************
5569 Deal with setting the time from any of the setfilepathinfo functions.
5570 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5571 calling this function.
5572 ****************************************************************************/
5574 NTSTATUS smb_set_file_time(connection_struct *conn,
5575 files_struct *fsp,
5576 const struct smb_filename *smb_fname,
5577 struct smb_file_time *ft,
5578 bool setting_write_time)
5580 struct smb_filename smb_fname_base;
5581 uint32 action =
5582 FILE_NOTIFY_CHANGE_LAST_ACCESS
5583 |FILE_NOTIFY_CHANGE_LAST_WRITE
5584 |FILE_NOTIFY_CHANGE_CREATION;
5586 if (!VALID_STAT(smb_fname->st)) {
5587 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5590 /* get some defaults (no modifications) if any info is zero or -1. */
5591 if (null_timespec(ft->create_time)) {
5592 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5595 if (null_timespec(ft->atime)) {
5596 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5599 if (null_timespec(ft->mtime)) {
5600 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5603 if (!setting_write_time) {
5604 /* ft->mtime comes from change time, not write time. */
5605 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5608 /* Ensure the resolution is the correct for
5609 * what we can store on this filesystem. */
5611 round_timespec(conn->ts_res, &ft->create_time);
5612 round_timespec(conn->ts_res, &ft->ctime);
5613 round_timespec(conn->ts_res, &ft->atime);
5614 round_timespec(conn->ts_res, &ft->mtime);
5616 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5617 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5618 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5619 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5620 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5621 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5622 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5623 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5625 if (setting_write_time) {
5627 * This was a Windows setfileinfo on an open file.
5628 * NT does this a lot. We also need to
5629 * set the time here, as it can be read by
5630 * FindFirst/FindNext and with the patch for bug #2045
5631 * in smbd/fileio.c it ensures that this timestamp is
5632 * kept sticky even after a write. We save the request
5633 * away and will set it on file close and after a write. JRA.
5636 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5637 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5639 if (fsp != NULL) {
5640 if (fsp->base_fsp) {
5641 set_sticky_write_time_fsp(fsp->base_fsp,
5642 ft->mtime);
5643 } else {
5644 set_sticky_write_time_fsp(fsp, ft->mtime);
5646 } else {
5647 set_sticky_write_time_path(
5648 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5649 ft->mtime);
5653 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5655 /* Always call ntimes on the base, even if a stream was passed in. */
5656 smb_fname_base = *smb_fname;
5657 smb_fname_base.stream_name = NULL;
5659 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5660 return map_nt_error_from_unix(errno);
5663 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5664 smb_fname->base_name);
5665 return NT_STATUS_OK;
5668 /****************************************************************************
5669 Deal with setting the dosmode from any of the setfilepathinfo functions.
5670 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5671 done before calling this function.
5672 ****************************************************************************/
5674 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5675 const struct smb_filename *smb_fname,
5676 uint32 dosmode)
5678 struct smb_filename *smb_fname_base = NULL;
5679 NTSTATUS status;
5681 if (!VALID_STAT(smb_fname->st)) {
5682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5685 /* Always operate on the base_name, even if a stream was passed in. */
5686 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5687 NULL, &smb_fname->st,
5688 &smb_fname_base);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 return status;
5693 if (dosmode) {
5694 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5695 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5696 } else {
5697 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5701 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5703 /* check the mode isn't different, before changing it */
5704 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5705 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5706 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5707 (unsigned int)dosmode));
5709 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5710 false)) {
5711 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5712 "%s failed (%s)\n",
5713 smb_fname_str_dbg(smb_fname_base),
5714 strerror(errno)));
5715 status = map_nt_error_from_unix(errno);
5716 goto out;
5719 status = NT_STATUS_OK;
5720 out:
5721 TALLOC_FREE(smb_fname_base);
5722 return status;
5725 /****************************************************************************
5726 Deal with setting the size from any of the setfilepathinfo functions.
5727 ****************************************************************************/
5729 static NTSTATUS smb_set_file_size(connection_struct *conn,
5730 struct smb_request *req,
5731 files_struct *fsp,
5732 const struct smb_filename *smb_fname,
5733 const SMB_STRUCT_STAT *psbuf,
5734 off_t size,
5735 bool fail_after_createfile)
5737 NTSTATUS status = NT_STATUS_OK;
5738 struct smb_filename *smb_fname_tmp = NULL;
5739 files_struct *new_fsp = NULL;
5741 if (!VALID_STAT(*psbuf)) {
5742 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5745 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5747 if (size == get_file_size_stat(psbuf)) {
5748 return NT_STATUS_OK;
5751 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5752 smb_fname_str_dbg(smb_fname), (double)size));
5754 if (fsp && fsp->fh->fd != -1) {
5755 /* Handle based call. */
5756 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5757 return NT_STATUS_ACCESS_DENIED;
5760 if (vfs_set_filelen(fsp, size) == -1) {
5761 return map_nt_error_from_unix(errno);
5763 trigger_write_time_update_immediate(fsp);
5764 return NT_STATUS_OK;
5767 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5768 if (!NT_STATUS_IS_OK(status)) {
5769 return status;
5772 smb_fname_tmp->st = *psbuf;
5774 status = SMB_VFS_CREATE_FILE(
5775 conn, /* conn */
5776 req, /* req */
5777 0, /* root_dir_fid */
5778 smb_fname_tmp, /* fname */
5779 FILE_WRITE_DATA, /* access_mask */
5780 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5781 FILE_SHARE_DELETE),
5782 FILE_OPEN, /* create_disposition*/
5783 0, /* create_options */
5784 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5785 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5786 0, /* allocation_size */
5787 0, /* private_flags */
5788 NULL, /* sd */
5789 NULL, /* ea_list */
5790 &new_fsp, /* result */
5791 NULL); /* pinfo */
5793 TALLOC_FREE(smb_fname_tmp);
5795 if (!NT_STATUS_IS_OK(status)) {
5796 /* NB. We check for open_was_deferred in the caller. */
5797 return status;
5800 /* See RAW-SFILEINFO-END-OF-FILE */
5801 if (fail_after_createfile) {
5802 close_file(req, new_fsp,NORMAL_CLOSE);
5803 return NT_STATUS_INVALID_LEVEL;
5806 if (vfs_set_filelen(new_fsp, size) == -1) {
5807 status = map_nt_error_from_unix(errno);
5808 close_file(req, new_fsp,NORMAL_CLOSE);
5809 return status;
5812 trigger_write_time_update_immediate(new_fsp);
5813 close_file(req, new_fsp,NORMAL_CLOSE);
5814 return NT_STATUS_OK;
5817 /****************************************************************************
5818 Deal with SMB_INFO_SET_EA.
5819 ****************************************************************************/
5821 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5822 const char *pdata,
5823 int total_data,
5824 files_struct *fsp,
5825 const struct smb_filename *smb_fname)
5827 struct ea_list *ea_list = NULL;
5828 TALLOC_CTX *ctx = NULL;
5829 NTSTATUS status = NT_STATUS_OK;
5831 if (total_data < 10) {
5833 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5834 length. They seem to have no effect. Bug #3212. JRA */
5836 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5837 /* We're done. We only get EA info in this call. */
5838 return NT_STATUS_OK;
5841 return NT_STATUS_INVALID_PARAMETER;
5844 if (IVAL(pdata,0) > total_data) {
5845 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5846 IVAL(pdata,0), (unsigned int)total_data));
5847 return NT_STATUS_INVALID_PARAMETER;
5850 ctx = talloc_tos();
5851 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5852 if (!ea_list) {
5853 return NT_STATUS_INVALID_PARAMETER;
5856 status = set_ea(conn, fsp, smb_fname, ea_list);
5858 return status;
5861 /****************************************************************************
5862 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5863 ****************************************************************************/
5865 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5866 const char *pdata,
5867 int total_data,
5868 files_struct *fsp)
5870 struct ea_list *ea_list = NULL;
5871 NTSTATUS status;
5873 if (!fsp) {
5874 return NT_STATUS_INVALID_HANDLE;
5877 if (!lp_ea_support(SNUM(conn))) {
5878 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5879 "EA's not supported.\n",
5880 (unsigned int)total_data));
5881 return NT_STATUS_EAS_NOT_SUPPORTED;
5884 if (total_data < 10) {
5885 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5886 "too small.\n",
5887 (unsigned int)total_data));
5888 return NT_STATUS_INVALID_PARAMETER;
5891 ea_list = read_nttrans_ea_list(talloc_tos(),
5892 pdata,
5893 total_data);
5895 if (!ea_list) {
5896 return NT_STATUS_INVALID_PARAMETER;
5899 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5901 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5902 smb_fname_str_dbg(fsp->fsp_name),
5903 nt_errstr(status) ));
5905 return status;
5909 /****************************************************************************
5910 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5911 ****************************************************************************/
5913 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5914 const char *pdata,
5915 int total_data,
5916 files_struct *fsp,
5917 struct smb_filename *smb_fname)
5919 NTSTATUS status = NT_STATUS_OK;
5920 bool delete_on_close;
5921 uint32 dosmode = 0;
5923 if (total_data < 1) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 if (fsp == NULL) {
5928 return NT_STATUS_INVALID_HANDLE;
5931 delete_on_close = (CVAL(pdata,0) ? True : False);
5932 dosmode = dos_mode(conn, smb_fname);
5934 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5935 "delete_on_close = %u\n",
5936 smb_fname_str_dbg(smb_fname),
5937 (unsigned int)dosmode,
5938 (unsigned int)delete_on_close ));
5940 if (delete_on_close) {
5941 status = can_set_delete_on_close(fsp, dosmode);
5942 if (!NT_STATUS_IS_OK(status)) {
5943 return status;
5947 /* The set is across all open files on this dev/inode pair. */
5948 if (!set_delete_on_close(fsp, delete_on_close,
5949 conn->session_info->security_token,
5950 conn->session_info->unix_token)) {
5951 return NT_STATUS_ACCESS_DENIED;
5953 return NT_STATUS_OK;
5956 /****************************************************************************
5957 Deal with SMB_FILE_POSITION_INFORMATION.
5958 ****************************************************************************/
5960 static NTSTATUS smb_file_position_information(connection_struct *conn,
5961 const char *pdata,
5962 int total_data,
5963 files_struct *fsp)
5965 uint64_t position_information;
5967 if (total_data < 8) {
5968 return NT_STATUS_INVALID_PARAMETER;
5971 if (fsp == NULL) {
5972 /* Ignore on pathname based set. */
5973 return NT_STATUS_OK;
5976 position_information = (uint64_t)IVAL(pdata,0);
5977 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5979 DEBUG(10,("smb_file_position_information: Set file position "
5980 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5981 (double)position_information));
5982 fsp->fh->position_information = position_information;
5983 return NT_STATUS_OK;
5986 /****************************************************************************
5987 Deal with SMB_FILE_MODE_INFORMATION.
5988 ****************************************************************************/
5990 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5991 const char *pdata,
5992 int total_data)
5994 uint32 mode;
5996 if (total_data < 4) {
5997 return NT_STATUS_INVALID_PARAMETER;
5999 mode = IVAL(pdata,0);
6000 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6001 return NT_STATUS_INVALID_PARAMETER;
6003 return NT_STATUS_OK;
6006 /****************************************************************************
6007 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6008 ****************************************************************************/
6010 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6011 struct smb_request *req,
6012 const char *pdata,
6013 int total_data,
6014 const struct smb_filename *smb_fname)
6016 char *link_target = NULL;
6017 const char *newname = smb_fname->base_name;
6018 TALLOC_CTX *ctx = talloc_tos();
6020 /* Set a symbolic link. */
6021 /* Don't allow this if follow links is false. */
6023 if (total_data == 0) {
6024 return NT_STATUS_INVALID_PARAMETER;
6027 if (!lp_symlinks(SNUM(conn))) {
6028 return NT_STATUS_ACCESS_DENIED;
6031 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6032 total_data, STR_TERMINATE);
6034 if (!link_target) {
6035 return NT_STATUS_INVALID_PARAMETER;
6038 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6039 newname, link_target ));
6041 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6042 return map_nt_error_from_unix(errno);
6045 return NT_STATUS_OK;
6048 /****************************************************************************
6049 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6050 ****************************************************************************/
6052 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6053 struct smb_request *req,
6054 const char *pdata, int total_data,
6055 struct smb_filename *smb_fname_new)
6057 char *oldname = NULL;
6058 struct smb_filename *smb_fname_old = NULL;
6059 TALLOC_CTX *ctx = talloc_tos();
6060 NTSTATUS status = NT_STATUS_OK;
6062 /* Set a hard link. */
6063 if (total_data == 0) {
6064 return NT_STATUS_INVALID_PARAMETER;
6067 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6068 total_data, STR_TERMINATE, &status);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 return status;
6073 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6074 smb_fname_str_dbg(smb_fname_new), oldname));
6076 status = filename_convert(ctx,
6077 conn,
6078 req->flags2 & FLAGS2_DFS_PATHNAMES,
6079 oldname,
6081 NULL,
6082 &smb_fname_old);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 return status;
6087 return hardlink_internals(ctx, conn, req, false,
6088 smb_fname_old, smb_fname_new);
6091 /****************************************************************************
6092 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6093 ****************************************************************************/
6095 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6096 struct smb_request *req,
6097 const char *pdata,
6098 int total_data,
6099 files_struct *fsp,
6100 struct smb_filename *smb_fname_src)
6102 bool overwrite;
6103 uint32_t len;
6104 char *newname = NULL;
6105 struct smb_filename *smb_fname_dst = NULL;
6106 NTSTATUS status = NT_STATUS_OK;
6107 TALLOC_CTX *ctx = talloc_tos();
6109 if (!fsp) {
6110 return NT_STATUS_INVALID_HANDLE;
6113 if (total_data < 20) {
6114 return NT_STATUS_INVALID_PARAMETER;
6117 overwrite = (CVAL(pdata,0) ? True : False);
6118 len = IVAL(pdata,16);
6120 if (len > (total_data - 20) || (len == 0)) {
6121 return NT_STATUS_INVALID_PARAMETER;
6124 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6125 &pdata[20], len, STR_TERMINATE,
6126 &status);
6127 if (!NT_STATUS_IS_OK(status)) {
6128 return status;
6131 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6132 newname));
6134 status = filename_convert(ctx,
6135 conn,
6136 req->flags2 & FLAGS2_DFS_PATHNAMES,
6137 newname,
6138 UCF_SAVE_LCOMP,
6139 NULL,
6140 &smb_fname_dst);
6141 if (!NT_STATUS_IS_OK(status)) {
6142 return status;
6145 if (fsp->base_fsp) {
6146 /* newname must be a stream name. */
6147 if (newname[0] != ':') {
6148 return NT_STATUS_NOT_SUPPORTED;
6151 /* Create an smb_fname to call rename_internals_fsp() with. */
6152 status = create_synthetic_smb_fname(talloc_tos(),
6153 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6154 &smb_fname_dst);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 goto out;
6160 * Set the original last component, since
6161 * rename_internals_fsp() requires it.
6163 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6164 newname);
6165 if (smb_fname_dst->original_lcomp == NULL) {
6166 status = NT_STATUS_NO_MEMORY;
6167 goto out;
6172 DEBUG(10,("smb2_file_rename_information: "
6173 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6174 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6175 smb_fname_str_dbg(smb_fname_dst)));
6176 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6177 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6178 overwrite);
6180 out:
6181 TALLOC_FREE(smb_fname_dst);
6182 return status;
6185 static NTSTATUS smb_file_link_information(connection_struct *conn,
6186 struct smb_request *req,
6187 const char *pdata,
6188 int total_data,
6189 files_struct *fsp,
6190 struct smb_filename *smb_fname_src)
6192 bool overwrite;
6193 uint32_t len;
6194 char *newname = NULL;
6195 struct smb_filename *smb_fname_dst = NULL;
6196 NTSTATUS status = NT_STATUS_OK;
6197 TALLOC_CTX *ctx = talloc_tos();
6199 if (!fsp) {
6200 return NT_STATUS_INVALID_HANDLE;
6203 if (total_data < 20) {
6204 return NT_STATUS_INVALID_PARAMETER;
6207 overwrite = (CVAL(pdata,0) ? true : false);
6208 len = IVAL(pdata,16);
6210 if (len > (total_data - 20) || (len == 0)) {
6211 return NT_STATUS_INVALID_PARAMETER;
6214 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6215 &pdata[20], len, STR_TERMINATE,
6216 &status);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 return status;
6221 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6222 newname));
6224 status = filename_convert(ctx,
6225 conn,
6226 req->flags2 & FLAGS2_DFS_PATHNAMES,
6227 newname,
6228 UCF_SAVE_LCOMP,
6229 NULL,
6230 &smb_fname_dst);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 return status;
6235 if (fsp->base_fsp) {
6236 /* No stream names. */
6237 return NT_STATUS_NOT_SUPPORTED;
6240 DEBUG(10,("smb_file_link_information: "
6241 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6242 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6243 smb_fname_str_dbg(smb_fname_dst)));
6244 status = hardlink_internals(ctx,
6245 conn,
6246 req,
6247 overwrite,
6248 fsp->fsp_name,
6249 smb_fname_dst);
6251 TALLOC_FREE(smb_fname_dst);
6252 return status;
6255 /****************************************************************************
6256 Deal with SMB_FILE_RENAME_INFORMATION.
6257 ****************************************************************************/
6259 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6260 struct smb_request *req,
6261 const char *pdata,
6262 int total_data,
6263 files_struct *fsp,
6264 struct smb_filename *smb_fname_src)
6266 bool overwrite;
6267 uint32 root_fid;
6268 uint32 len;
6269 char *newname = NULL;
6270 struct smb_filename *smb_fname_dst = NULL;
6271 bool dest_has_wcard = False;
6272 NTSTATUS status = NT_STATUS_OK;
6273 char *p;
6274 TALLOC_CTX *ctx = talloc_tos();
6276 if (total_data < 13) {
6277 return NT_STATUS_INVALID_PARAMETER;
6280 overwrite = (CVAL(pdata,0) ? True : False);
6281 root_fid = IVAL(pdata,4);
6282 len = IVAL(pdata,8);
6284 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6285 return NT_STATUS_INVALID_PARAMETER;
6288 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6289 len, 0, &status,
6290 &dest_has_wcard);
6291 if (!NT_STATUS_IS_OK(status)) {
6292 return status;
6295 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6296 newname));
6298 status = resolve_dfspath_wcard(ctx, conn,
6299 req->flags2 & FLAGS2_DFS_PATHNAMES,
6300 newname,
6301 true,
6302 !conn->sconn->using_smb2,
6303 &newname,
6304 &dest_has_wcard);
6305 if (!NT_STATUS_IS_OK(status)) {
6306 return status;
6309 /* Check the new name has no '/' characters. */
6310 if (strchr_m(newname, '/')) {
6311 return NT_STATUS_NOT_SUPPORTED;
6314 if (fsp && fsp->base_fsp) {
6315 /* newname must be a stream name. */
6316 if (newname[0] != ':') {
6317 return NT_STATUS_NOT_SUPPORTED;
6320 /* Create an smb_fname to call rename_internals_fsp() with. */
6321 status = create_synthetic_smb_fname(talloc_tos(),
6322 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6323 &smb_fname_dst);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 goto out;
6329 * Set the original last component, since
6330 * rename_internals_fsp() requires it.
6332 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6333 newname);
6334 if (smb_fname_dst->original_lcomp == NULL) {
6335 status = NT_STATUS_NO_MEMORY;
6336 goto out;
6339 } else {
6341 * Build up an smb_fname_dst based on the filename passed in.
6342 * We basically just strip off the last component, and put on
6343 * the newname instead.
6345 char *base_name = NULL;
6347 /* newname must *not* be a stream name. */
6348 if (newname[0] == ':') {
6349 return NT_STATUS_NOT_SUPPORTED;
6353 * Strip off the last component (filename) of the path passed
6354 * in.
6356 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6357 if (!base_name) {
6358 return NT_STATUS_NO_MEMORY;
6360 p = strrchr_m(base_name, '/');
6361 if (p) {
6362 p[1] = '\0';
6363 } else {
6364 base_name = talloc_strdup(ctx, "");
6365 if (!base_name) {
6366 return NT_STATUS_NO_MEMORY;
6369 /* Append the new name. */
6370 base_name = talloc_asprintf_append(base_name,
6371 "%s",
6372 newname);
6373 if (!base_name) {
6374 return NT_STATUS_NO_MEMORY;
6377 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6378 (UCF_SAVE_LCOMP |
6379 (dest_has_wcard ?
6380 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6381 0)));
6383 /* If an error we expect this to be
6384 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6386 if (!NT_STATUS_IS_OK(status)) {
6387 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6388 status)) {
6389 goto out;
6391 /* Create an smb_fname to call rename_internals_fsp() */
6392 status = create_synthetic_smb_fname(ctx,
6393 base_name, NULL,
6394 NULL,
6395 &smb_fname_dst);
6396 if (!NT_STATUS_IS_OK(status)) {
6397 goto out;
6402 if (fsp) {
6403 DEBUG(10,("smb_file_rename_information: "
6404 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6405 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6406 smb_fname_str_dbg(smb_fname_dst)));
6407 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6408 overwrite);
6409 } else {
6410 DEBUG(10,("smb_file_rename_information: "
6411 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6412 smb_fname_str_dbg(smb_fname_src),
6413 smb_fname_str_dbg(smb_fname_dst)));
6414 status = rename_internals(ctx, conn, req, smb_fname_src,
6415 smb_fname_dst, 0, overwrite, false,
6416 dest_has_wcard,
6417 FILE_WRITE_ATTRIBUTES);
6419 out:
6420 TALLOC_FREE(smb_fname_dst);
6421 return status;
6424 /****************************************************************************
6425 Deal with SMB_SET_POSIX_ACL.
6426 ****************************************************************************/
6428 #if defined(HAVE_POSIX_ACLS)
6429 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6430 const char *pdata,
6431 int total_data,
6432 files_struct *fsp,
6433 const struct smb_filename *smb_fname)
6435 uint16 posix_acl_version;
6436 uint16 num_file_acls;
6437 uint16 num_def_acls;
6438 bool valid_file_acls = True;
6439 bool valid_def_acls = True;
6441 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6442 return NT_STATUS_INVALID_PARAMETER;
6444 posix_acl_version = SVAL(pdata,0);
6445 num_file_acls = SVAL(pdata,2);
6446 num_def_acls = SVAL(pdata,4);
6448 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6449 valid_file_acls = False;
6450 num_file_acls = 0;
6453 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6454 valid_def_acls = False;
6455 num_def_acls = 0;
6458 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6459 return NT_STATUS_INVALID_PARAMETER;
6462 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6463 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6464 return NT_STATUS_INVALID_PARAMETER;
6467 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6468 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6469 (unsigned int)num_file_acls,
6470 (unsigned int)num_def_acls));
6472 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6473 smb_fname->base_name, num_file_acls,
6474 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6475 return map_nt_error_from_unix(errno);
6478 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6479 smb_fname->base_name, &smb_fname->st, num_def_acls,
6480 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6481 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6482 return map_nt_error_from_unix(errno);
6484 return NT_STATUS_OK;
6486 #endif
6488 /****************************************************************************
6489 Deal with SMB_SET_POSIX_LOCK.
6490 ****************************************************************************/
6492 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6493 struct smb_request *req,
6494 const char *pdata,
6495 int total_data,
6496 files_struct *fsp)
6498 uint64_t count;
6499 uint64_t offset;
6500 uint64_t smblctx;
6501 bool blocking_lock = False;
6502 enum brl_type lock_type;
6504 NTSTATUS status = NT_STATUS_OK;
6506 if (fsp == NULL || fsp->fh->fd == -1) {
6507 return NT_STATUS_INVALID_HANDLE;
6510 if (total_data != POSIX_LOCK_DATA_SIZE) {
6511 return NT_STATUS_INVALID_PARAMETER;
6514 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6515 case POSIX_LOCK_TYPE_READ:
6516 lock_type = READ_LOCK;
6517 break;
6518 case POSIX_LOCK_TYPE_WRITE:
6519 /* Return the right POSIX-mappable error code for files opened read-only. */
6520 if (!fsp->can_write) {
6521 return NT_STATUS_INVALID_HANDLE;
6523 lock_type = WRITE_LOCK;
6524 break;
6525 case POSIX_LOCK_TYPE_UNLOCK:
6526 lock_type = UNLOCK_LOCK;
6527 break;
6528 default:
6529 return NT_STATUS_INVALID_PARAMETER;
6532 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6533 blocking_lock = False;
6534 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6535 blocking_lock = True;
6536 } else {
6537 return NT_STATUS_INVALID_PARAMETER;
6540 if (!lp_blocking_locks(SNUM(conn))) {
6541 blocking_lock = False;
6544 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6545 #if defined(HAVE_LONGLONG)
6546 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6547 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6548 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6549 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6550 #else /* HAVE_LONGLONG */
6551 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6552 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6553 #endif /* HAVE_LONGLONG */
6555 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6556 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6557 fsp_str_dbg(fsp),
6558 (unsigned int)lock_type,
6559 (unsigned long long)smblctx,
6560 (double)count,
6561 (double)offset ));
6563 if (lock_type == UNLOCK_LOCK) {
6564 status = do_unlock(req->sconn->msg_ctx,
6565 fsp,
6566 smblctx,
6567 count,
6568 offset,
6569 POSIX_LOCK);
6570 } else {
6571 uint64_t block_smblctx;
6573 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6574 fsp,
6575 smblctx,
6576 count,
6577 offset,
6578 lock_type,
6579 POSIX_LOCK,
6580 blocking_lock,
6581 &status,
6582 &block_smblctx,
6583 NULL);
6585 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6587 * A blocking lock was requested. Package up
6588 * this smb into a queued request and push it
6589 * onto the blocking lock queue.
6591 if(push_blocking_lock_request(br_lck,
6592 req,
6593 fsp,
6594 -1, /* infinite timeout. */
6596 smblctx,
6597 lock_type,
6598 POSIX_LOCK,
6599 offset,
6600 count,
6601 block_smblctx)) {
6602 TALLOC_FREE(br_lck);
6603 return status;
6606 TALLOC_FREE(br_lck);
6609 return status;
6612 /****************************************************************************
6613 Deal with SMB_SET_FILE_BASIC_INFO.
6614 ****************************************************************************/
6616 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6617 const char *pdata,
6618 int total_data,
6619 files_struct *fsp,
6620 const struct smb_filename *smb_fname)
6622 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6623 struct smb_file_time ft;
6624 uint32 dosmode = 0;
6625 NTSTATUS status = NT_STATUS_OK;
6627 ZERO_STRUCT(ft);
6629 if (total_data < 36) {
6630 return NT_STATUS_INVALID_PARAMETER;
6633 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 return status;
6638 /* Set the attributes */
6639 dosmode = IVAL(pdata,32);
6640 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6641 if (!NT_STATUS_IS_OK(status)) {
6642 return status;
6645 /* create time */
6646 ft.create_time = interpret_long_date(pdata);
6648 /* access time */
6649 ft.atime = interpret_long_date(pdata+8);
6651 /* write time. */
6652 ft.mtime = interpret_long_date(pdata+16);
6654 /* change time. */
6655 ft.ctime = interpret_long_date(pdata+24);
6657 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6658 smb_fname_str_dbg(smb_fname)));
6660 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6661 true);
6664 /****************************************************************************
6665 Deal with SMB_INFO_STANDARD.
6666 ****************************************************************************/
6668 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6669 const char *pdata,
6670 int total_data,
6671 files_struct *fsp,
6672 const struct smb_filename *smb_fname)
6674 NTSTATUS status;
6675 struct smb_file_time ft;
6677 ZERO_STRUCT(ft);
6679 if (total_data < 12) {
6680 return NT_STATUS_INVALID_PARAMETER;
6683 /* create time */
6684 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6685 /* access time */
6686 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6687 /* write time */
6688 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6690 DEBUG(10,("smb_set_info_standard: file %s\n",
6691 smb_fname_str_dbg(smb_fname)));
6693 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6694 if (!NT_STATUS_IS_OK(status)) {
6695 return status;
6698 return smb_set_file_time(conn,
6699 fsp,
6700 smb_fname,
6701 &ft,
6702 true);
6705 /****************************************************************************
6706 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6707 ****************************************************************************/
6709 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6710 struct smb_request *req,
6711 const char *pdata,
6712 int total_data,
6713 files_struct *fsp,
6714 struct smb_filename *smb_fname)
6716 uint64_t allocation_size = 0;
6717 NTSTATUS status = NT_STATUS_OK;
6718 files_struct *new_fsp = NULL;
6720 if (!VALID_STAT(smb_fname->st)) {
6721 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6724 if (total_data < 8) {
6725 return NT_STATUS_INVALID_PARAMETER;
6728 allocation_size = (uint64_t)IVAL(pdata,0);
6729 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6730 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6731 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6732 (double)allocation_size));
6734 if (allocation_size) {
6735 allocation_size = smb_roundup(conn, allocation_size);
6738 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6739 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6740 (double)allocation_size));
6742 if (fsp && fsp->fh->fd != -1) {
6743 /* Open file handle. */
6744 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6745 return NT_STATUS_ACCESS_DENIED;
6748 /* Only change if needed. */
6749 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6750 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6751 return map_nt_error_from_unix(errno);
6754 /* But always update the time. */
6756 * This is equivalent to a write. Ensure it's seen immediately
6757 * if there are no pending writes.
6759 trigger_write_time_update_immediate(fsp);
6760 return NT_STATUS_OK;
6763 /* Pathname or stat or directory file. */
6764 status = SMB_VFS_CREATE_FILE(
6765 conn, /* conn */
6766 req, /* req */
6767 0, /* root_dir_fid */
6768 smb_fname, /* fname */
6769 FILE_WRITE_DATA, /* access_mask */
6770 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6771 FILE_SHARE_DELETE),
6772 FILE_OPEN, /* create_disposition*/
6773 0, /* create_options */
6774 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6775 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6776 0, /* allocation_size */
6777 0, /* private_flags */
6778 NULL, /* sd */
6779 NULL, /* ea_list */
6780 &new_fsp, /* result */
6781 NULL); /* pinfo */
6783 if (!NT_STATUS_IS_OK(status)) {
6784 /* NB. We check for open_was_deferred in the caller. */
6785 return status;
6788 /* Only change if needed. */
6789 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6790 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6791 status = map_nt_error_from_unix(errno);
6792 close_file(req, new_fsp, NORMAL_CLOSE);
6793 return status;
6797 /* Changing the allocation size should set the last mod time. */
6799 * This is equivalent to a write. Ensure it's seen immediately
6800 * if there are no pending writes.
6802 trigger_write_time_update_immediate(new_fsp);
6804 close_file(req, new_fsp, NORMAL_CLOSE);
6805 return NT_STATUS_OK;
6808 /****************************************************************************
6809 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6810 ****************************************************************************/
6812 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6813 struct smb_request *req,
6814 const char *pdata,
6815 int total_data,
6816 files_struct *fsp,
6817 const struct smb_filename *smb_fname,
6818 bool fail_after_createfile)
6820 off_t size;
6822 if (total_data < 8) {
6823 return NT_STATUS_INVALID_PARAMETER;
6826 size = IVAL(pdata,0);
6827 size |= (((off_t)IVAL(pdata,4)) << 32);
6828 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6829 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6830 (double)size));
6832 return smb_set_file_size(conn, req,
6833 fsp,
6834 smb_fname,
6835 &smb_fname->st,
6836 size,
6837 fail_after_createfile);
6840 /****************************************************************************
6841 Allow a UNIX info mknod.
6842 ****************************************************************************/
6844 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6845 const char *pdata,
6846 int total_data,
6847 const struct smb_filename *smb_fname)
6849 uint32 file_type = IVAL(pdata,56);
6850 #if defined(HAVE_MAKEDEV)
6851 uint32 dev_major = IVAL(pdata,60);
6852 uint32 dev_minor = IVAL(pdata,68);
6853 #endif
6854 SMB_DEV_T dev = (SMB_DEV_T)0;
6855 uint32 raw_unixmode = IVAL(pdata,84);
6856 NTSTATUS status;
6857 mode_t unixmode;
6859 if (total_data < 100) {
6860 return NT_STATUS_INVALID_PARAMETER;
6863 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6864 PERM_NEW_FILE, &unixmode);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 return status;
6869 #if defined(HAVE_MAKEDEV)
6870 dev = makedev(dev_major, dev_minor);
6871 #endif
6873 switch (file_type) {
6874 #if defined(S_IFIFO)
6875 case UNIX_TYPE_FIFO:
6876 unixmode |= S_IFIFO;
6877 break;
6878 #endif
6879 #if defined(S_IFSOCK)
6880 case UNIX_TYPE_SOCKET:
6881 unixmode |= S_IFSOCK;
6882 break;
6883 #endif
6884 #if defined(S_IFCHR)
6885 case UNIX_TYPE_CHARDEV:
6886 unixmode |= S_IFCHR;
6887 break;
6888 #endif
6889 #if defined(S_IFBLK)
6890 case UNIX_TYPE_BLKDEV:
6891 unixmode |= S_IFBLK;
6892 break;
6893 #endif
6894 default:
6895 return NT_STATUS_INVALID_PARAMETER;
6898 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6899 "%.0f mode 0%o for file %s\n", (double)dev,
6900 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6902 /* Ok - do the mknod. */
6903 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6904 return map_nt_error_from_unix(errno);
6907 /* If any of the other "set" calls fail we
6908 * don't want to end up with a half-constructed mknod.
6911 if (lp_inherit_perms(SNUM(conn))) {
6912 char *parent;
6913 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6914 &parent, NULL)) {
6915 return NT_STATUS_NO_MEMORY;
6917 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6918 unixmode);
6919 TALLOC_FREE(parent);
6922 return NT_STATUS_OK;
6925 /****************************************************************************
6926 Deal with SMB_SET_FILE_UNIX_BASIC.
6927 ****************************************************************************/
6929 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6930 struct smb_request *req,
6931 const char *pdata,
6932 int total_data,
6933 files_struct *fsp,
6934 const struct smb_filename *smb_fname)
6936 struct smb_file_time ft;
6937 uint32 raw_unixmode;
6938 mode_t unixmode;
6939 off_t size = 0;
6940 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6941 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6942 NTSTATUS status = NT_STATUS_OK;
6943 bool delete_on_fail = False;
6944 enum perm_type ptype;
6945 files_struct *all_fsps = NULL;
6946 bool modify_mtime = true;
6947 struct file_id id;
6948 struct smb_filename *smb_fname_tmp = NULL;
6949 SMB_STRUCT_STAT sbuf;
6951 ZERO_STRUCT(ft);
6953 if (total_data < 100) {
6954 return NT_STATUS_INVALID_PARAMETER;
6957 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6958 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6959 size=IVAL(pdata,0); /* first 8 Bytes are size */
6960 size |= (((off_t)IVAL(pdata,4)) << 32);
6963 ft.atime = interpret_long_date(pdata+24); /* access_time */
6964 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6965 set_owner = (uid_t)IVAL(pdata,40);
6966 set_grp = (gid_t)IVAL(pdata,48);
6967 raw_unixmode = IVAL(pdata,84);
6969 if (VALID_STAT(smb_fname->st)) {
6970 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6971 ptype = PERM_EXISTING_DIR;
6972 } else {
6973 ptype = PERM_EXISTING_FILE;
6975 } else {
6976 ptype = PERM_NEW_FILE;
6979 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6980 ptype, &unixmode);
6981 if (!NT_STATUS_IS_OK(status)) {
6982 return status;
6985 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6986 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6987 smb_fname_str_dbg(smb_fname), (double)size,
6988 (unsigned int)set_owner, (unsigned int)set_grp,
6989 (int)raw_unixmode));
6991 sbuf = smb_fname->st;
6993 if (!VALID_STAT(sbuf)) {
6995 * The only valid use of this is to create character and block
6996 * devices, and named pipes. This is deprecated (IMHO) and
6997 * a new info level should be used for mknod. JRA.
7000 status = smb_unix_mknod(conn,
7001 pdata,
7002 total_data,
7003 smb_fname);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 return status;
7008 status = copy_smb_filename(talloc_tos(), smb_fname,
7009 &smb_fname_tmp);
7010 if (!NT_STATUS_IS_OK(status)) {
7011 return status;
7014 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7015 status = map_nt_error_from_unix(errno);
7016 TALLOC_FREE(smb_fname_tmp);
7017 SMB_VFS_UNLINK(conn, smb_fname);
7018 return status;
7021 sbuf = smb_fname_tmp->st;
7022 smb_fname = smb_fname_tmp;
7024 /* Ensure we don't try and change anything else. */
7025 raw_unixmode = SMB_MODE_NO_CHANGE;
7026 size = get_file_size_stat(&sbuf);
7027 ft.atime = sbuf.st_ex_atime;
7028 ft.mtime = sbuf.st_ex_mtime;
7030 * We continue here as we might want to change the
7031 * owner uid/gid.
7033 delete_on_fail = True;
7036 #if 1
7037 /* Horrible backwards compatibility hack as an old server bug
7038 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7039 * */
7041 if (!size) {
7042 size = get_file_size_stat(&sbuf);
7044 #endif
7047 * Deal with the UNIX specific mode set.
7050 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7051 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7052 "setting mode 0%o for file %s\n",
7053 (unsigned int)unixmode,
7054 smb_fname_str_dbg(smb_fname)));
7055 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7056 return map_nt_error_from_unix(errno);
7061 * Deal with the UNIX specific uid set.
7064 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7065 (sbuf.st_ex_uid != set_owner)) {
7066 int ret;
7068 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7069 "changing owner %u for path %s\n",
7070 (unsigned int)set_owner,
7071 smb_fname_str_dbg(smb_fname)));
7073 if (S_ISLNK(sbuf.st_ex_mode)) {
7074 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7075 set_owner, (gid_t)-1);
7076 } else {
7077 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7078 set_owner, (gid_t)-1);
7081 if (ret != 0) {
7082 status = map_nt_error_from_unix(errno);
7083 if (delete_on_fail) {
7084 SMB_VFS_UNLINK(conn, smb_fname);
7086 return status;
7091 * Deal with the UNIX specific gid set.
7094 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7095 (sbuf.st_ex_gid != set_grp)) {
7096 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7097 "changing group %u for file %s\n",
7098 (unsigned int)set_owner,
7099 smb_fname_str_dbg(smb_fname)));
7100 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7101 set_grp) != 0) {
7102 status = map_nt_error_from_unix(errno);
7103 if (delete_on_fail) {
7104 SMB_VFS_UNLINK(conn, smb_fname);
7106 return status;
7110 /* Deal with any size changes. */
7112 status = smb_set_file_size(conn, req,
7113 fsp,
7114 smb_fname,
7115 &sbuf,
7116 size,
7117 false);
7118 if (!NT_STATUS_IS_OK(status)) {
7119 return status;
7122 /* Deal with any time changes. */
7123 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7124 /* No change, don't cancel anything. */
7125 return status;
7128 id = vfs_file_id_from_sbuf(conn, &sbuf);
7129 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7130 all_fsps = file_find_di_next(all_fsps)) {
7132 * We're setting the time explicitly for UNIX.
7133 * Cancel any pending changes over all handles.
7135 all_fsps->update_write_time_on_close = false;
7136 TALLOC_FREE(all_fsps->update_write_time_event);
7140 * Override the "setting_write_time"
7141 * parameter here as it almost does what
7142 * we need. Just remember if we modified
7143 * mtime and send the notify ourselves.
7145 if (null_timespec(ft.mtime)) {
7146 modify_mtime = false;
7149 status = smb_set_file_time(conn,
7150 fsp,
7151 smb_fname,
7152 &ft,
7153 false);
7154 if (modify_mtime) {
7155 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7156 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7158 return status;
7161 /****************************************************************************
7162 Deal with SMB_SET_FILE_UNIX_INFO2.
7163 ****************************************************************************/
7165 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7166 struct smb_request *req,
7167 const char *pdata,
7168 int total_data,
7169 files_struct *fsp,
7170 const struct smb_filename *smb_fname)
7172 NTSTATUS status;
7173 uint32 smb_fflags;
7174 uint32 smb_fmask;
7176 if (total_data < 116) {
7177 return NT_STATUS_INVALID_PARAMETER;
7180 /* Start by setting all the fields that are common between UNIX_BASIC
7181 * and UNIX_INFO2.
7183 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7184 fsp, smb_fname);
7185 if (!NT_STATUS_IS_OK(status)) {
7186 return status;
7189 smb_fflags = IVAL(pdata, 108);
7190 smb_fmask = IVAL(pdata, 112);
7192 /* NB: We should only attempt to alter the file flags if the client
7193 * sends a non-zero mask.
7195 if (smb_fmask != 0) {
7196 int stat_fflags = 0;
7198 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7199 smb_fmask, &stat_fflags)) {
7200 /* Client asked to alter a flag we don't understand. */
7201 return NT_STATUS_INVALID_PARAMETER;
7204 if (fsp && fsp->fh->fd != -1) {
7205 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7206 return NT_STATUS_NOT_SUPPORTED;
7207 } else {
7208 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7209 stat_fflags) != 0) {
7210 return map_nt_error_from_unix(errno);
7215 /* XXX: need to add support for changing the create_time here. You
7216 * can do this for paths on Darwin with setattrlist(2). The right way
7217 * to hook this up is probably by extending the VFS utimes interface.
7220 return NT_STATUS_OK;
7223 /****************************************************************************
7224 Create a directory with POSIX semantics.
7225 ****************************************************************************/
7227 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7228 struct smb_request *req,
7229 char **ppdata,
7230 int total_data,
7231 struct smb_filename *smb_fname,
7232 int *pdata_return_size)
7234 NTSTATUS status = NT_STATUS_OK;
7235 uint32 raw_unixmode = 0;
7236 uint32 mod_unixmode = 0;
7237 mode_t unixmode = (mode_t)0;
7238 files_struct *fsp = NULL;
7239 uint16 info_level_return = 0;
7240 int info;
7241 char *pdata = *ppdata;
7243 if (total_data < 18) {
7244 return NT_STATUS_INVALID_PARAMETER;
7247 raw_unixmode = IVAL(pdata,8);
7248 /* Next 4 bytes are not yet defined. */
7250 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7251 PERM_NEW_DIR, &unixmode);
7252 if (!NT_STATUS_IS_OK(status)) {
7253 return status;
7256 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7258 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7259 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7261 status = SMB_VFS_CREATE_FILE(
7262 conn, /* conn */
7263 req, /* req */
7264 0, /* root_dir_fid */
7265 smb_fname, /* fname */
7266 FILE_READ_ATTRIBUTES, /* access_mask */
7267 FILE_SHARE_NONE, /* share_access */
7268 FILE_CREATE, /* create_disposition*/
7269 FILE_DIRECTORY_FILE, /* create_options */
7270 mod_unixmode, /* file_attributes */
7271 0, /* oplock_request */
7272 0, /* allocation_size */
7273 0, /* private_flags */
7274 NULL, /* sd */
7275 NULL, /* ea_list */
7276 &fsp, /* result */
7277 &info); /* pinfo */
7279 if (NT_STATUS_IS_OK(status)) {
7280 close_file(req, fsp, NORMAL_CLOSE);
7283 info_level_return = SVAL(pdata,16);
7285 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7286 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7287 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7288 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7289 } else {
7290 *pdata_return_size = 12;
7293 /* Realloc the data size */
7294 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7295 if (*ppdata == NULL) {
7296 *pdata_return_size = 0;
7297 return NT_STATUS_NO_MEMORY;
7299 pdata = *ppdata;
7301 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7302 SSVAL(pdata,2,0); /* No fnum. */
7303 SIVAL(pdata,4,info); /* Was directory created. */
7305 switch (info_level_return) {
7306 case SMB_QUERY_FILE_UNIX_BASIC:
7307 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7308 SSVAL(pdata,10,0); /* Padding. */
7309 store_file_unix_basic(conn, pdata + 12, fsp,
7310 &smb_fname->st);
7311 break;
7312 case SMB_QUERY_FILE_UNIX_INFO2:
7313 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7314 SSVAL(pdata,10,0); /* Padding. */
7315 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7316 &smb_fname->st);
7317 break;
7318 default:
7319 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7320 SSVAL(pdata,10,0); /* Padding. */
7321 break;
7324 return status;
7327 /****************************************************************************
7328 Open/Create a file with POSIX semantics.
7329 ****************************************************************************/
7331 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7332 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7334 static NTSTATUS smb_posix_open(connection_struct *conn,
7335 struct smb_request *req,
7336 char **ppdata,
7337 int total_data,
7338 struct smb_filename *smb_fname,
7339 int *pdata_return_size)
7341 bool extended_oplock_granted = False;
7342 char *pdata = *ppdata;
7343 uint32 flags = 0;
7344 uint32 wire_open_mode = 0;
7345 uint32 raw_unixmode = 0;
7346 uint32 mod_unixmode = 0;
7347 uint32 create_disp = 0;
7348 uint32 access_mask = 0;
7349 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7350 NTSTATUS status = NT_STATUS_OK;
7351 mode_t unixmode = (mode_t)0;
7352 files_struct *fsp = NULL;
7353 int oplock_request = 0;
7354 int info = 0;
7355 uint16 info_level_return = 0;
7357 if (total_data < 18) {
7358 return NT_STATUS_INVALID_PARAMETER;
7361 flags = IVAL(pdata,0);
7362 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7363 if (oplock_request) {
7364 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7367 wire_open_mode = IVAL(pdata,4);
7369 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7370 return smb_posix_mkdir(conn, req,
7371 ppdata,
7372 total_data,
7373 smb_fname,
7374 pdata_return_size);
7377 switch (wire_open_mode & SMB_ACCMODE) {
7378 case SMB_O_RDONLY:
7379 access_mask = SMB_O_RDONLY_MAPPING;
7380 break;
7381 case SMB_O_WRONLY:
7382 access_mask = SMB_O_WRONLY_MAPPING;
7383 break;
7384 case SMB_O_RDWR:
7385 access_mask = (SMB_O_RDONLY_MAPPING|
7386 SMB_O_WRONLY_MAPPING);
7387 break;
7388 default:
7389 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7390 (unsigned int)wire_open_mode ));
7391 return NT_STATUS_INVALID_PARAMETER;
7394 wire_open_mode &= ~SMB_ACCMODE;
7396 /* First take care of O_CREAT|O_EXCL interactions. */
7397 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7398 case (SMB_O_CREAT | SMB_O_EXCL):
7399 /* File exists fail. File not exist create. */
7400 create_disp = FILE_CREATE;
7401 break;
7402 case SMB_O_CREAT:
7403 /* File exists open. File not exist create. */
7404 create_disp = FILE_OPEN_IF;
7405 break;
7406 case 0:
7407 /* File exists open. File not exist fail. */
7408 create_disp = FILE_OPEN;
7409 break;
7410 case SMB_O_EXCL:
7411 /* O_EXCL on its own without O_CREAT is undefined. */
7412 default:
7413 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7414 (unsigned int)wire_open_mode ));
7415 return NT_STATUS_INVALID_PARAMETER;
7418 /* Next factor in the effects of O_TRUNC. */
7419 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7421 if (wire_open_mode & SMB_O_TRUNC) {
7422 switch (create_disp) {
7423 case FILE_CREATE:
7424 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7425 /* Leave create_disp alone as
7426 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7428 /* File exists fail. File not exist create. */
7429 break;
7430 case FILE_OPEN_IF:
7431 /* SMB_O_CREAT | SMB_O_TRUNC */
7432 /* File exists overwrite. File not exist create. */
7433 create_disp = FILE_OVERWRITE_IF;
7434 break;
7435 case FILE_OPEN:
7436 /* SMB_O_TRUNC */
7437 /* File exists overwrite. File not exist fail. */
7438 create_disp = FILE_OVERWRITE;
7439 break;
7440 default:
7441 /* Cannot get here. */
7442 smb_panic("smb_posix_open: logic error");
7443 return NT_STATUS_INVALID_PARAMETER;
7447 raw_unixmode = IVAL(pdata,8);
7448 /* Next 4 bytes are not yet defined. */
7450 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7451 (VALID_STAT(smb_fname->st) ?
7452 PERM_EXISTING_FILE : PERM_NEW_FILE),
7453 &unixmode);
7455 if (!NT_STATUS_IS_OK(status)) {
7456 return status;
7459 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7461 if (wire_open_mode & SMB_O_SYNC) {
7462 create_options |= FILE_WRITE_THROUGH;
7464 if (wire_open_mode & SMB_O_APPEND) {
7465 access_mask |= FILE_APPEND_DATA;
7467 if (wire_open_mode & SMB_O_DIRECT) {
7468 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7471 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7472 VALID_STAT_OF_DIR(smb_fname->st)) {
7473 if (access_mask != SMB_O_RDONLY_MAPPING) {
7474 return NT_STATUS_FILE_IS_A_DIRECTORY;
7476 create_options &= ~FILE_NON_DIRECTORY_FILE;
7477 create_options |= FILE_DIRECTORY_FILE;
7480 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7481 smb_fname_str_dbg(smb_fname),
7482 (unsigned int)wire_open_mode,
7483 (unsigned int)unixmode ));
7485 status = SMB_VFS_CREATE_FILE(
7486 conn, /* conn */
7487 req, /* req */
7488 0, /* root_dir_fid */
7489 smb_fname, /* fname */
7490 access_mask, /* access_mask */
7491 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7492 FILE_SHARE_DELETE),
7493 create_disp, /* create_disposition*/
7494 create_options, /* create_options */
7495 mod_unixmode, /* file_attributes */
7496 oplock_request, /* oplock_request */
7497 0, /* allocation_size */
7498 0, /* private_flags */
7499 NULL, /* sd */
7500 NULL, /* ea_list */
7501 &fsp, /* result */
7502 &info); /* pinfo */
7504 if (!NT_STATUS_IS_OK(status)) {
7505 return status;
7508 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7509 extended_oplock_granted = True;
7512 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7513 extended_oplock_granted = True;
7516 info_level_return = SVAL(pdata,16);
7518 /* Allocate the correct return size. */
7520 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7521 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7522 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7523 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7524 } else {
7525 *pdata_return_size = 12;
7528 /* Realloc the data size */
7529 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7530 if (*ppdata == NULL) {
7531 close_file(req, fsp, ERROR_CLOSE);
7532 *pdata_return_size = 0;
7533 return NT_STATUS_NO_MEMORY;
7535 pdata = *ppdata;
7537 if (extended_oplock_granted) {
7538 if (flags & REQUEST_BATCH_OPLOCK) {
7539 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7540 } else {
7541 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7543 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7544 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7545 } else {
7546 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7549 SSVAL(pdata,2,fsp->fnum);
7550 SIVAL(pdata,4,info); /* Was file created etc. */
7552 switch (info_level_return) {
7553 case SMB_QUERY_FILE_UNIX_BASIC:
7554 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7555 SSVAL(pdata,10,0); /* padding. */
7556 store_file_unix_basic(conn, pdata + 12, fsp,
7557 &smb_fname->st);
7558 break;
7559 case SMB_QUERY_FILE_UNIX_INFO2:
7560 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7561 SSVAL(pdata,10,0); /* padding. */
7562 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7563 &smb_fname->st);
7564 break;
7565 default:
7566 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7567 SSVAL(pdata,10,0); /* padding. */
7568 break;
7570 return NT_STATUS_OK;
7573 /****************************************************************************
7574 Delete a file with POSIX semantics.
7575 ****************************************************************************/
7577 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7578 struct smb_request *req,
7579 const char *pdata,
7580 int total_data,
7581 struct smb_filename *smb_fname)
7583 NTSTATUS status = NT_STATUS_OK;
7584 files_struct *fsp = NULL;
7585 uint16 flags = 0;
7586 char del = 1;
7587 int info = 0;
7588 int create_options = 0;
7589 int i;
7590 struct share_mode_lock *lck = NULL;
7592 if (total_data < 2) {
7593 return NT_STATUS_INVALID_PARAMETER;
7596 flags = SVAL(pdata,0);
7598 if (!VALID_STAT(smb_fname->st)) {
7599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7602 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7603 !VALID_STAT_OF_DIR(smb_fname->st)) {
7604 return NT_STATUS_NOT_A_DIRECTORY;
7607 DEBUG(10,("smb_posix_unlink: %s %s\n",
7608 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7609 smb_fname_str_dbg(smb_fname)));
7611 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7612 create_options |= FILE_DIRECTORY_FILE;
7615 status = SMB_VFS_CREATE_FILE(
7616 conn, /* conn */
7617 req, /* req */
7618 0, /* root_dir_fid */
7619 smb_fname, /* fname */
7620 DELETE_ACCESS, /* access_mask */
7621 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7622 FILE_SHARE_DELETE),
7623 FILE_OPEN, /* create_disposition*/
7624 create_options, /* create_options */
7625 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7626 0, /* oplock_request */
7627 0, /* allocation_size */
7628 0, /* private_flags */
7629 NULL, /* sd */
7630 NULL, /* ea_list */
7631 &fsp, /* result */
7632 &info); /* pinfo */
7634 if (!NT_STATUS_IS_OK(status)) {
7635 return status;
7639 * Don't lie to client. If we can't really delete due to
7640 * non-POSIX opens return SHARING_VIOLATION.
7643 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7644 if (lck == NULL) {
7645 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7646 "lock for file %s\n", fsp_str_dbg(fsp)));
7647 close_file(req, fsp, NORMAL_CLOSE);
7648 return NT_STATUS_INVALID_PARAMETER;
7652 * See if others still have the file open. If this is the case, then
7653 * don't delete. If all opens are POSIX delete we can set the delete
7654 * on close disposition.
7656 for (i=0; i<lck->data->num_share_modes; i++) {
7657 struct share_mode_entry *e = &lck->data->share_modes[i];
7658 if (is_valid_share_mode_entry(e)) {
7659 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7660 continue;
7662 if (share_mode_stale_pid(lck->data, i)) {
7663 continue;
7665 /* Fail with sharing violation. */
7666 close_file(req, fsp, NORMAL_CLOSE);
7667 TALLOC_FREE(lck);
7668 return NT_STATUS_SHARING_VIOLATION;
7673 * Set the delete on close.
7675 status = smb_set_file_disposition_info(conn,
7676 &del,
7678 fsp,
7679 smb_fname);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 close_file(req, fsp, NORMAL_CLOSE);
7683 TALLOC_FREE(lck);
7684 return status;
7686 TALLOC_FREE(lck);
7687 return close_file(req, fsp, NORMAL_CLOSE);
7690 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7691 struct smb_request *req,
7692 TALLOC_CTX *mem_ctx,
7693 uint16_t info_level,
7694 files_struct *fsp,
7695 struct smb_filename *smb_fname,
7696 char **ppdata, int total_data,
7697 int *ret_data_size)
7699 char *pdata = *ppdata;
7700 NTSTATUS status = NT_STATUS_OK;
7701 int data_return_size = 0;
7703 *ret_data_size = 0;
7705 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7706 return NT_STATUS_INVALID_LEVEL;
7709 if (!CAN_WRITE(conn)) {
7710 /* Allow POSIX opens. The open path will deny
7711 * any non-readonly opens. */
7712 if (info_level != SMB_POSIX_PATH_OPEN) {
7713 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7717 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7718 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7719 fsp_fnum_dbg(fsp),
7720 info_level, total_data));
7722 switch (info_level) {
7724 case SMB_INFO_STANDARD:
7726 status = smb_set_info_standard(conn,
7727 pdata,
7728 total_data,
7729 fsp,
7730 smb_fname);
7731 break;
7734 case SMB_INFO_SET_EA:
7736 status = smb_info_set_ea(conn,
7737 pdata,
7738 total_data,
7739 fsp,
7740 smb_fname);
7741 break;
7744 case SMB_SET_FILE_BASIC_INFO:
7745 case SMB_FILE_BASIC_INFORMATION:
7747 status = smb_set_file_basic_info(conn,
7748 pdata,
7749 total_data,
7750 fsp,
7751 smb_fname);
7752 break;
7755 case SMB_FILE_ALLOCATION_INFORMATION:
7756 case SMB_SET_FILE_ALLOCATION_INFO:
7758 status = smb_set_file_allocation_info(conn, req,
7759 pdata,
7760 total_data,
7761 fsp,
7762 smb_fname);
7763 break;
7766 case SMB_FILE_END_OF_FILE_INFORMATION:
7767 case SMB_SET_FILE_END_OF_FILE_INFO:
7770 * XP/Win7 both fail after the createfile with
7771 * SMB_SET_FILE_END_OF_FILE_INFO but not
7772 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7773 * The level is known here, so pass it down
7774 * appropriately.
7776 bool should_fail =
7777 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7779 status = smb_set_file_end_of_file_info(conn, req,
7780 pdata,
7781 total_data,
7782 fsp,
7783 smb_fname,
7784 should_fail);
7785 break;
7788 case SMB_FILE_DISPOSITION_INFORMATION:
7789 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7791 #if 0
7792 /* JRA - We used to just ignore this on a path ?
7793 * Shouldn't this be invalid level on a pathname
7794 * based call ?
7796 if (tran_call != TRANSACT2_SETFILEINFO) {
7797 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7799 #endif
7800 status = smb_set_file_disposition_info(conn,
7801 pdata,
7802 total_data,
7803 fsp,
7804 smb_fname);
7805 break;
7808 case SMB_FILE_POSITION_INFORMATION:
7810 status = smb_file_position_information(conn,
7811 pdata,
7812 total_data,
7813 fsp);
7814 break;
7817 case SMB_FILE_FULL_EA_INFORMATION:
7819 status = smb_set_file_full_ea_info(conn,
7820 pdata,
7821 total_data,
7822 fsp);
7823 break;
7826 /* From tridge Samba4 :
7827 * MODE_INFORMATION in setfileinfo (I have no
7828 * idea what "mode information" on a file is - it takes a value of 0,
7829 * 2, 4 or 6. What could it be?).
7832 case SMB_FILE_MODE_INFORMATION:
7834 status = smb_file_mode_information(conn,
7835 pdata,
7836 total_data);
7837 break;
7841 * CIFS UNIX extensions.
7844 case SMB_SET_FILE_UNIX_BASIC:
7846 status = smb_set_file_unix_basic(conn, req,
7847 pdata,
7848 total_data,
7849 fsp,
7850 smb_fname);
7851 break;
7854 case SMB_SET_FILE_UNIX_INFO2:
7856 status = smb_set_file_unix_info2(conn, req,
7857 pdata,
7858 total_data,
7859 fsp,
7860 smb_fname);
7861 break;
7864 case SMB_SET_FILE_UNIX_LINK:
7866 if (fsp) {
7867 /* We must have a pathname for this. */
7868 return NT_STATUS_INVALID_LEVEL;
7870 status = smb_set_file_unix_link(conn, req, pdata,
7871 total_data, smb_fname);
7872 break;
7875 case SMB_SET_FILE_UNIX_HLINK:
7877 if (fsp) {
7878 /* We must have a pathname for this. */
7879 return NT_STATUS_INVALID_LEVEL;
7881 status = smb_set_file_unix_hlink(conn, req,
7882 pdata, total_data,
7883 smb_fname);
7884 break;
7887 case SMB_FILE_RENAME_INFORMATION:
7889 status = smb_file_rename_information(conn, req,
7890 pdata, total_data,
7891 fsp, smb_fname);
7892 break;
7895 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7897 /* SMB2 rename information. */
7898 status = smb2_file_rename_information(conn, req,
7899 pdata, total_data,
7900 fsp, smb_fname);
7901 break;
7904 case SMB_FILE_LINK_INFORMATION:
7906 status = smb_file_link_information(conn, req,
7907 pdata, total_data,
7908 fsp, smb_fname);
7909 break;
7912 #if defined(HAVE_POSIX_ACLS)
7913 case SMB_SET_POSIX_ACL:
7915 status = smb_set_posix_acl(conn,
7916 pdata,
7917 total_data,
7918 fsp,
7919 smb_fname);
7920 break;
7922 #endif
7924 case SMB_SET_POSIX_LOCK:
7926 if (!fsp) {
7927 return NT_STATUS_INVALID_LEVEL;
7929 status = smb_set_posix_lock(conn, req,
7930 pdata, total_data, fsp);
7931 break;
7934 case SMB_POSIX_PATH_OPEN:
7936 if (fsp) {
7937 /* We must have a pathname for this. */
7938 return NT_STATUS_INVALID_LEVEL;
7941 status = smb_posix_open(conn, req,
7942 ppdata,
7943 total_data,
7944 smb_fname,
7945 &data_return_size);
7946 break;
7949 case SMB_POSIX_PATH_UNLINK:
7951 if (fsp) {
7952 /* We must have a pathname for this. */
7953 return NT_STATUS_INVALID_LEVEL;
7956 status = smb_posix_unlink(conn, req,
7957 pdata,
7958 total_data,
7959 smb_fname);
7960 break;
7963 default:
7964 return NT_STATUS_INVALID_LEVEL;
7967 if (!NT_STATUS_IS_OK(status)) {
7968 return status;
7971 *ret_data_size = data_return_size;
7972 return NT_STATUS_OK;
7975 /****************************************************************************
7976 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7977 ****************************************************************************/
7979 static void call_trans2setfilepathinfo(connection_struct *conn,
7980 struct smb_request *req,
7981 unsigned int tran_call,
7982 char **pparams, int total_params,
7983 char **ppdata, int total_data,
7984 unsigned int max_data_bytes)
7986 char *params = *pparams;
7987 char *pdata = *ppdata;
7988 uint16 info_level;
7989 struct smb_filename *smb_fname = NULL;
7990 files_struct *fsp = NULL;
7991 NTSTATUS status = NT_STATUS_OK;
7992 int data_return_size = 0;
7994 if (!params) {
7995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7996 return;
7999 if (tran_call == TRANSACT2_SETFILEINFO) {
8000 if (total_params < 4) {
8001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8002 return;
8005 fsp = file_fsp(req, SVAL(params,0));
8006 /* Basic check for non-null fsp. */
8007 if (!check_fsp_open(conn, req, fsp)) {
8008 return;
8010 info_level = SVAL(params,2);
8012 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8013 &smb_fname);
8014 if (!NT_STATUS_IS_OK(status)) {
8015 reply_nterror(req, status);
8016 return;
8019 if(fsp->fh->fd == -1) {
8021 * This is actually a SETFILEINFO on a directory
8022 * handle (returned from an NT SMB). NT5.0 seems
8023 * to do this call. JRA.
8025 if (INFO_LEVEL_IS_UNIX(info_level)) {
8026 /* Always do lstat for UNIX calls. */
8027 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8028 DEBUG(3,("call_trans2setfilepathinfo: "
8029 "SMB_VFS_LSTAT of %s failed "
8030 "(%s)\n",
8031 smb_fname_str_dbg(smb_fname),
8032 strerror(errno)));
8033 reply_nterror(req, map_nt_error_from_unix(errno));
8034 return;
8036 } else {
8037 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8038 DEBUG(3,("call_trans2setfilepathinfo: "
8039 "fileinfo of %s failed (%s)\n",
8040 smb_fname_str_dbg(smb_fname),
8041 strerror(errno)));
8042 reply_nterror(req, map_nt_error_from_unix(errno));
8043 return;
8046 } else if (fsp->print_file) {
8048 * Doing a DELETE_ON_CLOSE should cancel a print job.
8050 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8051 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8053 DEBUG(3,("call_trans2setfilepathinfo: "
8054 "Cancelling print job (%s)\n",
8055 fsp_str_dbg(fsp)));
8057 SSVAL(params,0,0);
8058 send_trans2_replies(conn, req, params, 2,
8059 *ppdata, 0,
8060 max_data_bytes);
8061 return;
8062 } else {
8063 reply_nterror(req,
8064 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8065 return;
8067 } else {
8069 * Original code - this is an open file.
8071 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8072 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8073 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8074 strerror(errno)));
8075 reply_nterror(req, map_nt_error_from_unix(errno));
8076 return;
8079 } else {
8080 char *fname = NULL;
8081 uint32_t ucf_flags = 0;
8083 /* set path info */
8084 if (total_params < 7) {
8085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8086 return;
8089 info_level = SVAL(params,0);
8090 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8091 total_params - 6, STR_TERMINATE,
8092 &status);
8093 if (!NT_STATUS_IS_OK(status)) {
8094 reply_nterror(req, status);
8095 return;
8098 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8099 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8100 info_level == SMB_FILE_RENAME_INFORMATION ||
8101 info_level == SMB_POSIX_PATH_UNLINK) {
8102 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8105 status = filename_convert(req, conn,
8106 req->flags2 & FLAGS2_DFS_PATHNAMES,
8107 fname,
8108 ucf_flags,
8109 NULL,
8110 &smb_fname);
8111 if (!NT_STATUS_IS_OK(status)) {
8112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8113 reply_botherror(req,
8114 NT_STATUS_PATH_NOT_COVERED,
8115 ERRSRV, ERRbadpath);
8116 return;
8118 reply_nterror(req, status);
8119 return;
8122 if (INFO_LEVEL_IS_UNIX(info_level)) {
8124 * For CIFS UNIX extensions the target name may not exist.
8127 /* Always do lstat for UNIX calls. */
8128 SMB_VFS_LSTAT(conn, smb_fname);
8130 } else if (!VALID_STAT(smb_fname->st) &&
8131 SMB_VFS_STAT(conn, smb_fname)) {
8132 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8133 "%s failed (%s)\n",
8134 smb_fname_str_dbg(smb_fname),
8135 strerror(errno)));
8136 reply_nterror(req, map_nt_error_from_unix(errno));
8137 return;
8141 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8142 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8143 fsp_fnum_dbg(fsp),
8144 info_level,total_data));
8146 /* Realloc the parameter size */
8147 *pparams = (char *)SMB_REALLOC(*pparams,2);
8148 if (*pparams == NULL) {
8149 reply_nterror(req, NT_STATUS_NO_MEMORY);
8150 return;
8152 params = *pparams;
8154 SSVAL(params,0,0);
8156 status = smbd_do_setfilepathinfo(conn, req, req,
8157 info_level,
8158 fsp,
8159 smb_fname,
8160 ppdata, total_data,
8161 &data_return_size);
8162 if (!NT_STATUS_IS_OK(status)) {
8163 if (open_was_deferred(req->sconn, req->mid)) {
8164 /* We have re-scheduled this call. */
8165 return;
8167 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8168 /* We have re-scheduled this call. */
8169 return;
8171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8172 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8173 ERRSRV, ERRbadpath);
8174 return;
8176 if (info_level == SMB_POSIX_PATH_OPEN) {
8177 reply_openerror(req, status);
8178 return;
8181 reply_nterror(req, status);
8182 return;
8185 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8186 max_data_bytes);
8188 return;
8191 /****************************************************************************
8192 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8193 ****************************************************************************/
8195 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8196 char **pparams, int total_params,
8197 char **ppdata, int total_data,
8198 unsigned int max_data_bytes)
8200 struct smb_filename *smb_dname = NULL;
8201 char *params = *pparams;
8202 char *pdata = *ppdata;
8203 char *directory = NULL;
8204 NTSTATUS status = NT_STATUS_OK;
8205 struct ea_list *ea_list = NULL;
8206 TALLOC_CTX *ctx = talloc_tos();
8208 if (!CAN_WRITE(conn)) {
8209 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8210 return;
8213 if (total_params < 5) {
8214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8215 return;
8218 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8219 total_params - 4, STR_TERMINATE,
8220 &status);
8221 if (!NT_STATUS_IS_OK(status)) {
8222 reply_nterror(req, status);
8223 return;
8226 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8228 status = filename_convert(ctx,
8229 conn,
8230 req->flags2 & FLAGS2_DFS_PATHNAMES,
8231 directory,
8233 NULL,
8234 &smb_dname);
8236 if (!NT_STATUS_IS_OK(status)) {
8237 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8238 reply_botherror(req,
8239 NT_STATUS_PATH_NOT_COVERED,
8240 ERRSRV, ERRbadpath);
8241 return;
8243 reply_nterror(req, status);
8244 return;
8248 * OS/2 workplace shell seems to send SET_EA requests of "null"
8249 * length (4 bytes containing IVAL 4).
8250 * They seem to have no effect. Bug #3212. JRA.
8253 if (total_data && (total_data != 4)) {
8254 /* Any data in this call is an EA list. */
8255 if (total_data < 10) {
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 goto out;
8260 if (IVAL(pdata,0) > total_data) {
8261 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8262 IVAL(pdata,0), (unsigned int)total_data));
8263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8264 goto out;
8267 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8268 total_data - 4);
8269 if (!ea_list) {
8270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8271 goto out;
8274 if (!lp_ea_support(SNUM(conn))) {
8275 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8276 goto out;
8279 /* If total_data == 4 Windows doesn't care what values
8280 * are placed in that field, it just ignores them.
8281 * The System i QNTC IBM SMB client puts bad values here,
8282 * so ignore them. */
8284 status = create_directory(conn, req, smb_dname);
8286 if (!NT_STATUS_IS_OK(status)) {
8287 reply_nterror(req, status);
8288 goto out;
8291 /* Try and set any given EA. */
8292 if (ea_list) {
8293 status = set_ea(conn, NULL, smb_dname, ea_list);
8294 if (!NT_STATUS_IS_OK(status)) {
8295 reply_nterror(req, status);
8296 goto out;
8300 /* Realloc the parameter and data sizes */
8301 *pparams = (char *)SMB_REALLOC(*pparams,2);
8302 if(*pparams == NULL) {
8303 reply_nterror(req, NT_STATUS_NO_MEMORY);
8304 goto out;
8306 params = *pparams;
8308 SSVAL(params,0,0);
8310 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8312 out:
8313 TALLOC_FREE(smb_dname);
8314 return;
8317 /****************************************************************************
8318 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8319 We don't actually do this - we just send a null response.
8320 ****************************************************************************/
8322 static void call_trans2findnotifyfirst(connection_struct *conn,
8323 struct smb_request *req,
8324 char **pparams, int total_params,
8325 char **ppdata, int total_data,
8326 unsigned int max_data_bytes)
8328 char *params = *pparams;
8329 uint16 info_level;
8331 if (total_params < 6) {
8332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8333 return;
8336 info_level = SVAL(params,4);
8337 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8339 switch (info_level) {
8340 case 1:
8341 case 2:
8342 break;
8343 default:
8344 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8345 return;
8348 /* Realloc the parameter and data sizes */
8349 *pparams = (char *)SMB_REALLOC(*pparams,6);
8350 if (*pparams == NULL) {
8351 reply_nterror(req, NT_STATUS_NO_MEMORY);
8352 return;
8354 params = *pparams;
8356 SSVAL(params,0,fnf_handle);
8357 SSVAL(params,2,0); /* No changes */
8358 SSVAL(params,4,0); /* No EA errors */
8360 fnf_handle++;
8362 if(fnf_handle == 0)
8363 fnf_handle = 257;
8365 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8367 return;
8370 /****************************************************************************
8371 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8372 changes). Currently this does nothing.
8373 ****************************************************************************/
8375 static void call_trans2findnotifynext(connection_struct *conn,
8376 struct smb_request *req,
8377 char **pparams, int total_params,
8378 char **ppdata, int total_data,
8379 unsigned int max_data_bytes)
8381 char *params = *pparams;
8383 DEBUG(3,("call_trans2findnotifynext\n"));
8385 /* Realloc the parameter and data sizes */
8386 *pparams = (char *)SMB_REALLOC(*pparams,4);
8387 if (*pparams == NULL) {
8388 reply_nterror(req, NT_STATUS_NO_MEMORY);
8389 return;
8391 params = *pparams;
8393 SSVAL(params,0,0); /* No changes */
8394 SSVAL(params,2,0); /* No EA errors */
8396 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8398 return;
8401 /****************************************************************************
8402 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8403 ****************************************************************************/
8405 static void call_trans2getdfsreferral(connection_struct *conn,
8406 struct smb_request *req,
8407 char **pparams, int total_params,
8408 char **ppdata, int total_data,
8409 unsigned int max_data_bytes)
8411 char *params = *pparams;
8412 char *pathname = NULL;
8413 int reply_size = 0;
8414 int max_referral_level;
8415 NTSTATUS status = NT_STATUS_OK;
8416 TALLOC_CTX *ctx = talloc_tos();
8418 DEBUG(10,("call_trans2getdfsreferral\n"));
8420 if (total_params < 3) {
8421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8422 return;
8425 max_referral_level = SVAL(params,0);
8427 if(!lp_host_msdfs()) {
8428 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8429 return;
8432 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8433 total_params - 2, STR_TERMINATE);
8434 if (!pathname) {
8435 reply_nterror(req, NT_STATUS_NOT_FOUND);
8436 return;
8438 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8439 ppdata,&status)) < 0) {
8440 reply_nterror(req, status);
8441 return;
8444 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8445 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8446 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8448 return;
8451 #define LMCAT_SPL 0x53
8452 #define LMFUNC_GETJOBID 0x60
8454 /****************************************************************************
8455 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8456 ****************************************************************************/
8458 static void call_trans2ioctl(connection_struct *conn,
8459 struct smb_request *req,
8460 char **pparams, int total_params,
8461 char **ppdata, int total_data,
8462 unsigned int max_data_bytes)
8464 char *pdata = *ppdata;
8465 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8467 /* check for an invalid fid before proceeding */
8469 if (!fsp) {
8470 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8471 return;
8474 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8475 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8476 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8477 if (*ppdata == NULL) {
8478 reply_nterror(req, NT_STATUS_NO_MEMORY);
8479 return;
8481 pdata = *ppdata;
8483 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8484 CAN ACCEPT THIS IN UNICODE. JRA. */
8486 /* Job number */
8487 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8489 srvstr_push(pdata, req->flags2, pdata + 2,
8490 lp_netbios_name(), 15,
8491 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8492 srvstr_push(pdata, req->flags2, pdata+18,
8493 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8494 STR_ASCII|STR_TERMINATE); /* Service name */
8495 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8496 max_data_bytes);
8497 return;
8500 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8501 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8504 /****************************************************************************
8505 Reply to a SMBfindclose (stop trans2 directory search).
8506 ****************************************************************************/
8508 void reply_findclose(struct smb_request *req)
8510 int dptr_num;
8511 struct smbd_server_connection *sconn = req->sconn;
8513 START_PROFILE(SMBfindclose);
8515 if (req->wct < 1) {
8516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8517 END_PROFILE(SMBfindclose);
8518 return;
8521 dptr_num = SVALS(req->vwv+0, 0);
8523 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8525 dptr_close(sconn, &dptr_num);
8527 reply_outbuf(req, 0, 0);
8529 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8531 END_PROFILE(SMBfindclose);
8532 return;
8535 /****************************************************************************
8536 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8537 ****************************************************************************/
8539 void reply_findnclose(struct smb_request *req)
8541 int dptr_num;
8543 START_PROFILE(SMBfindnclose);
8545 if (req->wct < 1) {
8546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8547 END_PROFILE(SMBfindnclose);
8548 return;
8551 dptr_num = SVAL(req->vwv+0, 0);
8553 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8555 /* We never give out valid handles for a
8556 findnotifyfirst - so any dptr_num is ok here.
8557 Just ignore it. */
8559 reply_outbuf(req, 0, 0);
8561 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8563 END_PROFILE(SMBfindnclose);
8564 return;
8567 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8568 struct trans_state *state)
8570 if (get_Protocol() >= PROTOCOL_NT1) {
8571 req->flags2 |= 0x40; /* IS_LONG_NAME */
8572 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8575 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8576 if (state->call != TRANSACT2_QFSINFO &&
8577 state->call != TRANSACT2_SETFSINFO) {
8578 DEBUG(0,("handle_trans2: encryption required "
8579 "with call 0x%x\n",
8580 (unsigned int)state->call));
8581 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8582 return;
8586 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8588 /* Now we must call the relevant TRANS2 function */
8589 switch(state->call) {
8590 case TRANSACT2_OPEN:
8592 START_PROFILE(Trans2_open);
8593 call_trans2open(conn, req,
8594 &state->param, state->total_param,
8595 &state->data, state->total_data,
8596 state->max_data_return);
8597 END_PROFILE(Trans2_open);
8598 break;
8601 case TRANSACT2_FINDFIRST:
8603 START_PROFILE(Trans2_findfirst);
8604 call_trans2findfirst(conn, req,
8605 &state->param, state->total_param,
8606 &state->data, state->total_data,
8607 state->max_data_return);
8608 END_PROFILE(Trans2_findfirst);
8609 break;
8612 case TRANSACT2_FINDNEXT:
8614 START_PROFILE(Trans2_findnext);
8615 call_trans2findnext(conn, req,
8616 &state->param, state->total_param,
8617 &state->data, state->total_data,
8618 state->max_data_return);
8619 END_PROFILE(Trans2_findnext);
8620 break;
8623 case TRANSACT2_QFSINFO:
8625 START_PROFILE(Trans2_qfsinfo);
8626 call_trans2qfsinfo(conn, req,
8627 &state->param, state->total_param,
8628 &state->data, state->total_data,
8629 state->max_data_return);
8630 END_PROFILE(Trans2_qfsinfo);
8631 break;
8634 case TRANSACT2_SETFSINFO:
8636 START_PROFILE(Trans2_setfsinfo);
8637 call_trans2setfsinfo(conn, req,
8638 &state->param, state->total_param,
8639 &state->data, state->total_data,
8640 state->max_data_return);
8641 END_PROFILE(Trans2_setfsinfo);
8642 break;
8645 case TRANSACT2_QPATHINFO:
8646 case TRANSACT2_QFILEINFO:
8648 START_PROFILE(Trans2_qpathinfo);
8649 call_trans2qfilepathinfo(conn, req, state->call,
8650 &state->param, state->total_param,
8651 &state->data, state->total_data,
8652 state->max_data_return);
8653 END_PROFILE(Trans2_qpathinfo);
8654 break;
8657 case TRANSACT2_SETPATHINFO:
8658 case TRANSACT2_SETFILEINFO:
8660 START_PROFILE(Trans2_setpathinfo);
8661 call_trans2setfilepathinfo(conn, req, state->call,
8662 &state->param, state->total_param,
8663 &state->data, state->total_data,
8664 state->max_data_return);
8665 END_PROFILE(Trans2_setpathinfo);
8666 break;
8669 case TRANSACT2_FINDNOTIFYFIRST:
8671 START_PROFILE(Trans2_findnotifyfirst);
8672 call_trans2findnotifyfirst(conn, req,
8673 &state->param, state->total_param,
8674 &state->data, state->total_data,
8675 state->max_data_return);
8676 END_PROFILE(Trans2_findnotifyfirst);
8677 break;
8680 case TRANSACT2_FINDNOTIFYNEXT:
8682 START_PROFILE(Trans2_findnotifynext);
8683 call_trans2findnotifynext(conn, req,
8684 &state->param, state->total_param,
8685 &state->data, state->total_data,
8686 state->max_data_return);
8687 END_PROFILE(Trans2_findnotifynext);
8688 break;
8691 case TRANSACT2_MKDIR:
8693 START_PROFILE(Trans2_mkdir);
8694 call_trans2mkdir(conn, req,
8695 &state->param, state->total_param,
8696 &state->data, state->total_data,
8697 state->max_data_return);
8698 END_PROFILE(Trans2_mkdir);
8699 break;
8702 case TRANSACT2_GET_DFS_REFERRAL:
8704 START_PROFILE(Trans2_get_dfs_referral);
8705 call_trans2getdfsreferral(conn, req,
8706 &state->param, state->total_param,
8707 &state->data, state->total_data,
8708 state->max_data_return);
8709 END_PROFILE(Trans2_get_dfs_referral);
8710 break;
8713 case TRANSACT2_IOCTL:
8715 START_PROFILE(Trans2_ioctl);
8716 call_trans2ioctl(conn, req,
8717 &state->param, state->total_param,
8718 &state->data, state->total_data,
8719 state->max_data_return);
8720 END_PROFILE(Trans2_ioctl);
8721 break;
8724 default:
8725 /* Error in request */
8726 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8727 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8731 /****************************************************************************
8732 Reply to a SMBtrans2.
8733 ****************************************************************************/
8735 void reply_trans2(struct smb_request *req)
8737 connection_struct *conn = req->conn;
8738 unsigned int dsoff;
8739 unsigned int dscnt;
8740 unsigned int psoff;
8741 unsigned int pscnt;
8742 unsigned int tran_call;
8743 struct trans_state *state;
8744 NTSTATUS result;
8746 START_PROFILE(SMBtrans2);
8748 if (req->wct < 14) {
8749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8750 END_PROFILE(SMBtrans2);
8751 return;
8754 dsoff = SVAL(req->vwv+12, 0);
8755 dscnt = SVAL(req->vwv+11, 0);
8756 psoff = SVAL(req->vwv+10, 0);
8757 pscnt = SVAL(req->vwv+9, 0);
8758 tran_call = SVAL(req->vwv+14, 0);
8760 result = allow_new_trans(conn->pending_trans, req->mid);
8761 if (!NT_STATUS_IS_OK(result)) {
8762 DEBUG(2, ("Got invalid trans2 request: %s\n",
8763 nt_errstr(result)));
8764 reply_nterror(req, result);
8765 END_PROFILE(SMBtrans2);
8766 return;
8769 if (IS_IPC(conn)) {
8770 switch (tran_call) {
8771 /* List the allowed trans2 calls on IPC$ */
8772 case TRANSACT2_OPEN:
8773 case TRANSACT2_GET_DFS_REFERRAL:
8774 case TRANSACT2_QFILEINFO:
8775 case TRANSACT2_QFSINFO:
8776 case TRANSACT2_SETFSINFO:
8777 break;
8778 default:
8779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8780 END_PROFILE(SMBtrans2);
8781 return;
8785 if ((state = talloc(conn, struct trans_state)) == NULL) {
8786 DEBUG(0, ("talloc failed\n"));
8787 reply_nterror(req, NT_STATUS_NO_MEMORY);
8788 END_PROFILE(SMBtrans2);
8789 return;
8792 state->cmd = SMBtrans2;
8794 state->mid = req->mid;
8795 state->vuid = req->vuid;
8796 state->setup_count = SVAL(req->vwv+13, 0);
8797 state->setup = NULL;
8798 state->total_param = SVAL(req->vwv+0, 0);
8799 state->param = NULL;
8800 state->total_data = SVAL(req->vwv+1, 0);
8801 state->data = NULL;
8802 state->max_param_return = SVAL(req->vwv+2, 0);
8803 state->max_data_return = SVAL(req->vwv+3, 0);
8804 state->max_setup_return = SVAL(req->vwv+4, 0);
8805 state->close_on_completion = BITSETW(req->vwv+5, 0);
8806 state->one_way = BITSETW(req->vwv+5, 1);
8808 state->call = tran_call;
8810 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8811 is so as a sanity check */
8812 if (state->setup_count != 1) {
8814 * Need to have rc=0 for ioctl to get job id for OS/2.
8815 * Network printing will fail if function is not successful.
8816 * Similar function in reply.c will be used if protocol
8817 * is LANMAN1.0 instead of LM1.2X002.
8818 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8819 * outbuf doesn't have to be set(only job id is used).
8821 if ( (state->setup_count == 4)
8822 && (tran_call == TRANSACT2_IOCTL)
8823 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8824 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8825 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8826 } else {
8827 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8828 DEBUG(2,("Transaction is %d\n",tran_call));
8829 TALLOC_FREE(state);
8830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8831 END_PROFILE(SMBtrans2);
8832 return;
8836 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8837 goto bad_param;
8839 if (state->total_data) {
8841 if (trans_oob(state->total_data, 0, dscnt)
8842 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8843 goto bad_param;
8846 /* Can't use talloc here, the core routines do realloc on the
8847 * params and data. */
8848 state->data = (char *)SMB_MALLOC(state->total_data);
8849 if (state->data == NULL) {
8850 DEBUG(0,("reply_trans2: data malloc fail for %u "
8851 "bytes !\n", (unsigned int)state->total_data));
8852 TALLOC_FREE(state);
8853 reply_nterror(req, NT_STATUS_NO_MEMORY);
8854 END_PROFILE(SMBtrans2);
8855 return;
8858 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8861 if (state->total_param) {
8863 if (trans_oob(state->total_param, 0, pscnt)
8864 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8865 goto bad_param;
8868 /* Can't use talloc here, the core routines do realloc on the
8869 * params and data. */
8870 state->param = (char *)SMB_MALLOC(state->total_param);
8871 if (state->param == NULL) {
8872 DEBUG(0,("reply_trans: param malloc fail for %u "
8873 "bytes !\n", (unsigned int)state->total_param));
8874 SAFE_FREE(state->data);
8875 TALLOC_FREE(state);
8876 reply_nterror(req, NT_STATUS_NO_MEMORY);
8877 END_PROFILE(SMBtrans2);
8878 return;
8881 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8884 state->received_data = dscnt;
8885 state->received_param = pscnt;
8887 if ((state->received_param == state->total_param) &&
8888 (state->received_data == state->total_data)) {
8890 handle_trans2(conn, req, state);
8892 SAFE_FREE(state->data);
8893 SAFE_FREE(state->param);
8894 TALLOC_FREE(state);
8895 END_PROFILE(SMBtrans2);
8896 return;
8899 DLIST_ADD(conn->pending_trans, state);
8901 /* We need to send an interim response then receive the rest
8902 of the parameter/data bytes */
8903 reply_outbuf(req, 0, 0);
8904 show_msg((char *)req->outbuf);
8905 END_PROFILE(SMBtrans2);
8906 return;
8908 bad_param:
8910 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8911 SAFE_FREE(state->data);
8912 SAFE_FREE(state->param);
8913 TALLOC_FREE(state);
8914 END_PROFILE(SMBtrans2);
8915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8919 /****************************************************************************
8920 Reply to a SMBtranss2
8921 ****************************************************************************/
8923 void reply_transs2(struct smb_request *req)
8925 connection_struct *conn = req->conn;
8926 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8927 struct trans_state *state;
8929 START_PROFILE(SMBtranss2);
8931 show_msg((const char *)req->inbuf);
8933 /* Windows clients expect all replies to
8934 a transact secondary (SMBtranss2 0x33)
8935 to have a command code of transact
8936 (SMBtrans2 0x32). See bug #8989
8937 and also [MS-CIFS] section 2.2.4.47.2
8938 for details.
8940 req->cmd = SMBtrans2;
8942 if (req->wct < 8) {
8943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8944 END_PROFILE(SMBtranss2);
8945 return;
8948 for (state = conn->pending_trans; state != NULL;
8949 state = state->next) {
8950 if (state->mid == req->mid) {
8951 break;
8955 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8957 END_PROFILE(SMBtranss2);
8958 return;
8961 /* Revise state->total_param and state->total_data in case they have
8962 changed downwards */
8964 if (SVAL(req->vwv+0, 0) < state->total_param)
8965 state->total_param = SVAL(req->vwv+0, 0);
8966 if (SVAL(req->vwv+1, 0) < state->total_data)
8967 state->total_data = SVAL(req->vwv+1, 0);
8969 pcnt = SVAL(req->vwv+2, 0);
8970 poff = SVAL(req->vwv+3, 0);
8971 pdisp = SVAL(req->vwv+4, 0);
8973 dcnt = SVAL(req->vwv+5, 0);
8974 doff = SVAL(req->vwv+6, 0);
8975 ddisp = SVAL(req->vwv+7, 0);
8977 state->received_param += pcnt;
8978 state->received_data += dcnt;
8980 if ((state->received_data > state->total_data) ||
8981 (state->received_param > state->total_param))
8982 goto bad_param;
8984 if (pcnt) {
8985 if (trans_oob(state->total_param, pdisp, pcnt)
8986 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8987 goto bad_param;
8989 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8992 if (dcnt) {
8993 if (trans_oob(state->total_data, ddisp, dcnt)
8994 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8995 goto bad_param;
8997 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9000 if ((state->received_param < state->total_param) ||
9001 (state->received_data < state->total_data)) {
9002 END_PROFILE(SMBtranss2);
9003 return;
9006 handle_trans2(conn, req, state);
9008 DLIST_REMOVE(conn->pending_trans, state);
9009 SAFE_FREE(state->data);
9010 SAFE_FREE(state->param);
9011 TALLOC_FREE(state);
9013 END_PROFILE(SMBtranss2);
9014 return;
9016 bad_param:
9018 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9019 DLIST_REMOVE(conn->pending_trans, state);
9020 SAFE_FREE(state->data);
9021 SAFE_FREE(state->param);
9022 TALLOC_FREE(state);
9023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9024 END_PROFILE(SMBtranss2);
9025 return;