Final fix for bug #9130 - Certain xattrs cause Windows error 0x800700FF
[Samba/vl.git] / source3 / smbd / trans2.c
blob4cdd2394ca56f7b6d41e2162fdde1bb251dab9da
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;
326 *ea_list = NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 &names, &num_names);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 if (num_names == 0) {
336 *ea_list = NULL;
337 return NT_STATUS_OK;
340 for (i=0; i<num_names; i++) {
341 struct ea_list *listp;
342 fstring dos_ea_name;
344 if (strnequal(names[i], "system.", 7)
345 || samba_private_attr_name(names[i]))
346 continue;
348 listp = talloc(mem_ctx, struct ea_list);
349 if (listp == NULL) {
350 return NT_STATUS_NO_MEMORY;
353 status = get_ea_value(mem_ctx, conn, fsp,
354 fname, names[i],
355 &listp->ea);
357 if (!NT_STATUS_IS_OK(status)) {
358 return status;
361 if (listp->ea.value.length == 0) {
363 * We can never return a zero length EA.
364 * Windows reports the EA's as corrupted.
366 TALLOC_FREE(listp);
367 continue;
370 push_ascii_fstring(dos_ea_name, listp->ea.name);
372 *pea_total_len +=
373 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
375 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
376 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
377 (unsigned int)listp->ea.value.length));
379 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
383 /* Add on 4 for total length. */
384 if (*pea_total_len) {
385 *pea_total_len += 4;
388 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
389 (unsigned int)*pea_total_len));
391 *ea_list = ea_list_head;
392 return NT_STATUS_OK;
395 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
396 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
398 *pea_total_len = 0;
399 *ea_list = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
402 return NT_STATUS_OK;
405 if (is_ntfs_stream_smb_fname(smb_fname)) {
406 return NT_STATUS_INVALID_PARAMETER;
409 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
412 /****************************************************************************
413 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
414 that was filled.
415 ****************************************************************************/
417 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
418 connection_struct *conn, struct ea_list *ea_list)
420 unsigned int ret_data_size = 4;
421 char *p = pdata;
423 SMB_ASSERT(total_data_size >= 4);
425 if (!lp_ea_support(SNUM(conn))) {
426 SIVAL(pdata,4,0);
427 return 4;
430 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
431 size_t dos_namelen;
432 fstring dos_ea_name;
433 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
434 dos_namelen = strlen(dos_ea_name);
435 if (dos_namelen > 255 || dos_namelen == 0) {
436 break;
438 if (ea_list->ea.value.length > 65535) {
439 break;
441 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
442 break;
445 /* We know we have room. */
446 SCVAL(p,0,ea_list->ea.flags);
447 SCVAL(p,1,dos_namelen);
448 SSVAL(p,2,ea_list->ea.value.length);
449 strlcpy(p+4, dos_ea_name, dos_namelen+1);
450 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
452 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
453 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
456 ret_data_size = PTR_DIFF(p, pdata);
457 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
458 SIVAL(pdata,0,ret_data_size);
459 return ret_data_size;
462 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
463 char *pdata,
464 unsigned int total_data_size,
465 unsigned int *ret_data_size,
466 connection_struct *conn,
467 struct ea_list *ea_list)
469 uint8_t *p = (uint8_t *)pdata;
470 uint8_t *last_start = NULL;
471 bool do_store_data = (pdata != NULL);
473 *ret_data_size = 0;
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_NO_EAS_ON_FILE;
479 for (; ea_list; ea_list = ea_list->next) {
480 size_t dos_namelen;
481 fstring dos_ea_name;
482 size_t this_size;
483 size_t pad = 0;
485 if (last_start != NULL && do_store_data) {
486 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
488 last_start = p;
490 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
491 dos_namelen = strlen(dos_ea_name);
492 if (dos_namelen > 255 || dos_namelen == 0) {
493 return NT_STATUS_INTERNAL_ERROR;
495 if (ea_list->ea.value.length > 65535) {
496 return NT_STATUS_INTERNAL_ERROR;
499 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
501 if (ea_list->next) {
502 pad = (4 - (this_size % 4)) % 4;
503 this_size += pad;
506 if (do_store_data) {
507 if (this_size > total_data_size) {
508 return NT_STATUS_INFO_LENGTH_MISMATCH;
511 /* We know we have room. */
512 SIVAL(p, 0x00, 0); /* next offset */
513 SCVAL(p, 0x04, ea_list->ea.flags);
514 SCVAL(p, 0x05, dos_namelen);
515 SSVAL(p, 0x06, ea_list->ea.value.length);
516 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
517 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
518 if (pad) {
519 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
520 '\0',
521 pad);
523 total_data_size -= this_size;
526 p += this_size;
529 *ret_data_size = PTR_DIFF(p, pdata);
530 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
531 return NT_STATUS_OK;
534 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
536 size_t total_ea_len = 0;
537 TALLOC_CTX *mem_ctx;
538 struct ea_list *ea_list = NULL;
540 if (!lp_ea_support(SNUM(conn))) {
541 return 0;
543 mem_ctx = talloc_stackframe();
545 /* If this is a stream fsp, then we need to instead find the
546 * estimated ea len from the main file, not the stream
547 * (streams cannot have EAs), but the estimate isn't just 0 in
548 * this case! */
549 if (is_ntfs_stream_smb_fname(smb_fname)) {
550 fsp = NULL;
552 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
553 if(conn->sconn->using_smb2) {
554 NTSTATUS status;
555 unsigned int ret_data_size;
557 * We're going to be using fill_ea_chained_buffer() to
558 * marshall EA's - this size is significantly larger
559 * than the SMB1 buffer. Re-calculate the size without
560 * marshalling.
562 status = fill_ea_chained_buffer(mem_ctx,
563 NULL,
565 &ret_data_size,
566 conn,
567 ea_list);
568 if (!NT_STATUS_IS_OK(status)) {
569 ret_data_size = 0;
571 total_ea_len = ret_data_size;
573 TALLOC_FREE(mem_ctx);
574 return total_ea_len;
577 /****************************************************************************
578 Ensure the EA name is case insensitive by matching any existing EA name.
579 ****************************************************************************/
581 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
583 size_t total_ea_len;
584 TALLOC_CTX *mem_ctx = talloc_tos();
585 struct ea_list *ea_list;
586 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
587 if (!NT_STATUS_IS_OK(status)) {
588 return;
591 for (; ea_list; ea_list = ea_list->next) {
592 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
593 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
594 &unix_ea_name[5], ea_list->ea.name));
595 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
596 break;
601 /****************************************************************************
602 Set or delete an extended attribute.
603 ****************************************************************************/
605 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
606 const struct smb_filename *smb_fname, struct ea_list *ea_list)
608 NTSTATUS status;
609 char *fname = NULL;
611 if (!lp_ea_support(SNUM(conn))) {
612 return NT_STATUS_EAS_NOT_SUPPORTED;
615 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
616 if (!NT_STATUS_IS_OK(status)) {
617 return status;
620 /* Setting EAs on streams isn't supported. */
621 if (is_ntfs_stream_smb_fname(smb_fname)) {
622 return NT_STATUS_INVALID_PARAMETER;
625 fname = smb_fname->base_name;
627 for (;ea_list; ea_list = ea_list->next) {
628 int ret;
629 fstring unix_ea_name;
631 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
632 fstrcat(unix_ea_name, ea_list->ea.name);
634 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
636 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
638 if (samba_private_attr_name(unix_ea_name)) {
639 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
640 return NT_STATUS_ACCESS_DENIED;
643 if (ea_list->ea.value.length == 0) {
644 /* Remove the attribute. */
645 if (fsp && (fsp->fh->fd != -1)) {
646 DEBUG(10,("set_ea: deleting ea name %s on "
647 "file %s by file descriptor.\n",
648 unix_ea_name, fsp_str_dbg(fsp)));
649 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
650 } else {
651 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
652 unix_ea_name, fname));
653 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
655 #ifdef ENOATTR
656 /* Removing a non existent attribute always succeeds. */
657 if (ret == -1 && errno == ENOATTR) {
658 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
659 unix_ea_name));
660 ret = 0;
662 #endif
663 } else {
664 if (fsp && (fsp->fh->fd != -1)) {
665 DEBUG(10,("set_ea: setting ea name %s on file "
666 "%s by file descriptor.\n",
667 unix_ea_name, fsp_str_dbg(fsp)));
668 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
669 ea_list->ea.value.data, ea_list->ea.value.length, 0);
670 } else {
671 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
672 unix_ea_name, fname));
673 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
674 ea_list->ea.value.data, ea_list->ea.value.length, 0);
678 if (ret == -1) {
679 #ifdef ENOTSUP
680 if (errno == ENOTSUP) {
681 return NT_STATUS_EAS_NOT_SUPPORTED;
683 #endif
684 return map_nt_error_from_unix(errno);
688 return NT_STATUS_OK;
690 /****************************************************************************
691 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
692 ****************************************************************************/
694 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
696 struct ea_list *ea_list_head = NULL;
697 size_t converted_size, offset = 0;
699 while (offset + 2 < data_size) {
700 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
701 unsigned int namelen = CVAL(pdata,offset);
703 offset++; /* Go past the namelen byte. */
705 /* integer wrap paranioa. */
706 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
707 (offset > data_size) || (namelen > data_size) ||
708 (offset + namelen >= data_size)) {
709 break;
711 /* Ensure the name is null terminated. */
712 if (pdata[offset + namelen] != '\0') {
713 return NULL;
715 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
716 &converted_size)) {
717 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
718 "failed: %s", strerror(errno)));
720 if (!eal->ea.name) {
721 return NULL;
724 offset += (namelen + 1); /* Go past the name + terminating zero. */
725 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
726 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
729 return ea_list_head;
732 /****************************************************************************
733 Read one EA list entry from the buffer.
734 ****************************************************************************/
736 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
738 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
739 uint16 val_len;
740 unsigned int namelen;
741 size_t converted_size;
743 if (!eal) {
744 return NULL;
747 if (data_size < 6) {
748 return NULL;
751 eal->ea.flags = CVAL(pdata,0);
752 namelen = CVAL(pdata,1);
753 val_len = SVAL(pdata,2);
755 if (4 + namelen + 1 + val_len > data_size) {
756 return NULL;
759 /* Ensure the name is null terminated. */
760 if (pdata[namelen + 4] != '\0') {
761 return NULL;
763 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
764 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
765 strerror(errno)));
767 if (!eal->ea.name) {
768 return NULL;
771 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
772 if (!eal->ea.value.data) {
773 return NULL;
776 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
778 /* Ensure we're null terminated just in case we print the value. */
779 eal->ea.value.data[val_len] = '\0';
780 /* But don't count the null. */
781 eal->ea.value.length--;
783 if (pbytes_used) {
784 *pbytes_used = 4 + namelen + 1 + val_len;
787 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
788 dump_data(10, eal->ea.value.data, eal->ea.value.length);
790 return eal;
793 /****************************************************************************
794 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
795 ****************************************************************************/
797 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
799 struct ea_list *ea_list_head = NULL;
800 size_t offset = 0;
801 size_t bytes_used = 0;
803 while (offset < data_size) {
804 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
806 if (!eal) {
807 return NULL;
810 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
811 offset += bytes_used;
814 return ea_list_head;
817 /****************************************************************************
818 Count the total EA size needed.
819 ****************************************************************************/
821 static size_t ea_list_size(struct ea_list *ealist)
823 fstring dos_ea_name;
824 struct ea_list *listp;
825 size_t ret = 0;
827 for (listp = ealist; listp; listp = listp->next) {
828 push_ascii_fstring(dos_ea_name, listp->ea.name);
829 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
831 /* Add on 4 for total length. */
832 if (ret) {
833 ret += 4;
836 return ret;
839 /****************************************************************************
840 Return a union of EA's from a file list and a list of names.
841 The TALLOC context for the two lists *MUST* be identical as we steal
842 memory from one list to add to another. JRA.
843 ****************************************************************************/
845 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
847 struct ea_list *nlistp, *flistp;
849 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
850 for (flistp = file_list; flistp; flistp = flistp->next) {
851 if (strequal(nlistp->ea.name, flistp->ea.name)) {
852 break;
856 if (flistp) {
857 /* Copy the data from this entry. */
858 nlistp->ea.flags = flistp->ea.flags;
859 nlistp->ea.value = flistp->ea.value;
860 } else {
861 /* Null entry. */
862 nlistp->ea.flags = 0;
863 ZERO_STRUCT(nlistp->ea.value);
867 *total_ea_len = ea_list_size(name_list);
868 return name_list;
871 /****************************************************************************
872 Send the required number of replies back.
873 We assume all fields other than the data fields are
874 set correctly for the type of call.
875 HACK ! Always assumes smb_setup field is zero.
876 ****************************************************************************/
878 void send_trans2_replies(connection_struct *conn,
879 struct smb_request *req,
880 const char *params,
881 int paramsize,
882 const char *pdata,
883 int datasize,
884 int max_data_bytes)
886 /* As we are using a protocol > LANMAN1 then the max_send
887 variable must have been set in the sessetupX call.
888 This takes precedence over the max_xmit field in the
889 global struct. These different max_xmit variables should
890 be merged as this is now too confusing */
892 int data_to_send = datasize;
893 int params_to_send = paramsize;
894 int useable_space;
895 const char *pp = params;
896 const char *pd = pdata;
897 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
898 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
899 int data_alignment_offset = 0;
900 bool overflow = False;
901 struct smbd_server_connection *sconn = req->sconn;
902 int max_send = sconn->smb1.sessions.max_send;
904 /* Modify the data_to_send and datasize and set the error if
905 we're trying to send more than max_data_bytes. We still send
906 the part of the packet(s) that fit. Strange, but needed
907 for OS/2. */
909 if (max_data_bytes > 0 && datasize > max_data_bytes) {
910 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
911 max_data_bytes, datasize ));
912 datasize = data_to_send = max_data_bytes;
913 overflow = True;
916 /* If there genuinely are no parameters or data to send just send the empty packet */
918 if(params_to_send == 0 && data_to_send == 0) {
919 reply_outbuf(req, 10, 0);
920 show_msg((char *)req->outbuf);
921 if (!srv_send_smb(sconn,
922 (char *)req->outbuf,
923 true, req->seqnum+1,
924 IS_CONN_ENCRYPTED(conn),
925 &req->pcd)) {
926 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
928 TALLOC_FREE(req->outbuf);
929 return;
932 /* When sending params and data ensure that both are nicely aligned */
933 /* Only do this alignment when there is also data to send - else
934 can cause NT redirector problems. */
936 if (((params_to_send % 4) != 0) && (data_to_send != 0))
937 data_alignment_offset = 4 - (params_to_send % 4);
939 /* Space is bufsize minus Netbios over TCP header minus SMB header */
940 /* The alignment_offset is to align the param bytes on an even byte
941 boundary. NT 4.0 Beta needs this to work correctly. */
943 useable_space = max_send - (smb_size
944 + 2 * 10 /* wct */
945 + alignment_offset
946 + data_alignment_offset);
948 if (useable_space < 0) {
949 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
950 "= %d!!!", useable_space));
951 exit_server_cleanly("send_trans2_replies: Not enough space");
954 while (params_to_send || data_to_send) {
955 /* Calculate whether we will totally or partially fill this packet */
957 total_sent_thistime = params_to_send + data_to_send;
959 /* We can never send more than useable_space */
961 * Note that 'useable_space' does not include the alignment offsets,
962 * but we must include the alignment offsets in the calculation of
963 * the length of the data we send over the wire, as the alignment offsets
964 * are sent here. Fix from Marc_Jacobsen@hp.com.
967 total_sent_thistime = MIN(total_sent_thistime, useable_space);
969 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
970 + data_alignment_offset);
972 /* Set total params and data to be sent */
973 SSVAL(req->outbuf,smb_tprcnt,paramsize);
974 SSVAL(req->outbuf,smb_tdrcnt,datasize);
976 /* Calculate how many parameters and data we can fit into
977 * this packet. Parameters get precedence
980 params_sent_thistime = MIN(params_to_send,useable_space);
981 data_sent_thistime = useable_space - params_sent_thistime;
982 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
984 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
986 /* smb_proff is the offset from the start of the SMB header to the
987 parameter bytes, however the first 4 bytes of outbuf are
988 the Netbios over TCP header. Thus use smb_base() to subtract
989 them from the calculation */
991 SSVAL(req->outbuf,smb_proff,
992 ((smb_buf(req->outbuf)+alignment_offset)
993 - smb_base(req->outbuf)));
995 if(params_sent_thistime == 0)
996 SSVAL(req->outbuf,smb_prdisp,0);
997 else
998 /* Absolute displacement of param bytes sent in this packet */
999 SSVAL(req->outbuf,smb_prdisp,pp - params);
1001 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1002 if(data_sent_thistime == 0) {
1003 SSVAL(req->outbuf,smb_droff,0);
1004 SSVAL(req->outbuf,smb_drdisp, 0);
1005 } else {
1006 /* The offset of the data bytes is the offset of the
1007 parameter bytes plus the number of parameters being sent this time */
1008 SSVAL(req->outbuf, smb_droff,
1009 ((smb_buf(req->outbuf)+alignment_offset)
1010 - smb_base(req->outbuf))
1011 + params_sent_thistime + data_alignment_offset);
1012 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1015 /* Initialize the padding for alignment */
1017 if (alignment_offset != 0) {
1018 memset(smb_buf(req->outbuf), 0, alignment_offset);
1021 /* Copy the param bytes into the packet */
1023 if(params_sent_thistime) {
1024 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1025 params_sent_thistime);
1028 /* Copy in the data bytes */
1029 if(data_sent_thistime) {
1030 if (data_alignment_offset != 0) {
1031 memset((smb_buf(req->outbuf)+alignment_offset+
1032 params_sent_thistime), 0,
1033 data_alignment_offset);
1035 memcpy(smb_buf(req->outbuf)+alignment_offset
1036 +params_sent_thistime+data_alignment_offset,
1037 pd,data_sent_thistime);
1040 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1041 params_sent_thistime, data_sent_thistime, useable_space));
1042 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1043 params_to_send, data_to_send, paramsize, datasize));
1045 if (overflow) {
1046 error_packet_set((char *)req->outbuf,
1047 ERRDOS,ERRbufferoverflow,
1048 STATUS_BUFFER_OVERFLOW,
1049 __LINE__,__FILE__);
1052 /* Send the packet */
1053 show_msg((char *)req->outbuf);
1054 if (!srv_send_smb(sconn,
1055 (char *)req->outbuf,
1056 true, req->seqnum+1,
1057 IS_CONN_ENCRYPTED(conn),
1058 &req->pcd))
1059 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1061 TALLOC_FREE(req->outbuf);
1063 pp += params_sent_thistime;
1064 pd += data_sent_thistime;
1066 params_to_send -= params_sent_thistime;
1067 data_to_send -= data_sent_thistime;
1069 /* Sanity check */
1070 if(params_to_send < 0 || data_to_send < 0) {
1071 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1072 params_to_send, data_to_send));
1073 return;
1077 return;
1080 /****************************************************************************
1081 Reply to a TRANSACT2_OPEN.
1082 ****************************************************************************/
1084 static void call_trans2open(connection_struct *conn,
1085 struct smb_request *req,
1086 char **pparams, int total_params,
1087 char **ppdata, int total_data,
1088 unsigned int max_data_bytes)
1090 struct smb_filename *smb_fname = NULL;
1091 char *params = *pparams;
1092 char *pdata = *ppdata;
1093 int deny_mode;
1094 int32 open_attr;
1095 bool oplock_request;
1096 #if 0
1097 bool return_additional_info;
1098 int16 open_sattr;
1099 time_t open_time;
1100 #endif
1101 int open_ofun;
1102 uint32 open_size;
1103 char *pname;
1104 char *fname = NULL;
1105 off_t size=0;
1106 int fattr=0,mtime=0;
1107 SMB_INO_T inode = 0;
1108 int smb_action = 0;
1109 files_struct *fsp;
1110 struct ea_list *ea_list = NULL;
1111 uint16 flags = 0;
1112 NTSTATUS status;
1113 uint32 access_mask;
1114 uint32 share_mode;
1115 uint32 create_disposition;
1116 uint32 create_options = 0;
1117 uint32_t private_flags = 0;
1118 TALLOC_CTX *ctx = talloc_tos();
1121 * Ensure we have enough parameters to perform the operation.
1124 if (total_params < 29) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126 goto out;
1129 flags = SVAL(params, 0);
1130 deny_mode = SVAL(params, 2);
1131 open_attr = SVAL(params,6);
1132 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1133 if (oplock_request) {
1134 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1137 #if 0
1138 return_additional_info = BITSETW(params,0);
1139 open_sattr = SVAL(params, 4);
1140 open_time = make_unix_date3(params+8);
1141 #endif
1142 open_ofun = SVAL(params,12);
1143 open_size = IVAL(params,14);
1144 pname = &params[28];
1146 if (IS_IPC(conn)) {
1147 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1148 goto out;
1151 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1152 total_params - 28, STR_TERMINATE,
1153 &status);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 reply_nterror(req, status);
1156 goto out;
1159 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1160 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1161 (unsigned int)open_ofun, open_size));
1163 status = filename_convert(ctx,
1164 conn,
1165 req->flags2 & FLAGS2_DFS_PATHNAMES,
1166 fname,
1168 NULL,
1169 &smb_fname);
1170 if (!NT_STATUS_IS_OK(status)) {
1171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1172 reply_botherror(req,
1173 NT_STATUS_PATH_NOT_COVERED,
1174 ERRSRV, ERRbadpath);
1175 goto out;
1177 reply_nterror(req, status);
1178 goto out;
1181 if (open_ofun == 0) {
1182 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1183 goto out;
1186 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1187 open_ofun,
1188 &access_mask, &share_mode,
1189 &create_disposition,
1190 &create_options,
1191 &private_flags)) {
1192 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1193 goto out;
1196 /* Any data in this call is an EA list. */
1197 if (total_data && (total_data != 4)) {
1198 if (total_data < 10) {
1199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1200 goto out;
1203 if (IVAL(pdata,0) > total_data) {
1204 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1205 IVAL(pdata,0), (unsigned int)total_data));
1206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1207 goto out;
1210 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1211 total_data - 4);
1212 if (!ea_list) {
1213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1214 goto out;
1217 if (!lp_ea_support(SNUM(conn))) {
1218 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1219 goto out;
1223 status = SMB_VFS_CREATE_FILE(
1224 conn, /* conn */
1225 req, /* req */
1226 0, /* root_dir_fid */
1227 smb_fname, /* fname */
1228 access_mask, /* access_mask */
1229 share_mode, /* share_access */
1230 create_disposition, /* create_disposition*/
1231 create_options, /* create_options */
1232 open_attr, /* file_attributes */
1233 oplock_request, /* oplock_request */
1234 open_size, /* allocation_size */
1235 private_flags,
1236 NULL, /* sd */
1237 ea_list, /* ea_list */
1238 &fsp, /* result */
1239 &smb_action); /* psbuf */
1241 if (!NT_STATUS_IS_OK(status)) {
1242 if (open_was_deferred(req->sconn, req->mid)) {
1243 /* We have re-scheduled this call. */
1244 goto out;
1246 reply_openerror(req, status);
1247 goto out;
1250 size = get_file_size_stat(&smb_fname->st);
1251 fattr = dos_mode(conn, smb_fname);
1252 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1253 inode = smb_fname->st.st_ex_ino;
1254 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1255 close_file(req, fsp, ERROR_CLOSE);
1256 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1257 goto out;
1260 /* Realloc the size of parameters and data we will return */
1261 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1262 if(*pparams == NULL ) {
1263 reply_nterror(req, NT_STATUS_NO_MEMORY);
1264 goto out;
1266 params = *pparams;
1268 SSVAL(params,0,fsp->fnum);
1269 SSVAL(params,2,fattr);
1270 srv_put_dos_date2(params,4, mtime);
1271 SIVAL(params,8, (uint32)size);
1272 SSVAL(params,12,deny_mode);
1273 SSVAL(params,14,0); /* open_type - file or directory. */
1274 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1276 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1277 smb_action |= EXTENDED_OPLOCK_GRANTED;
1280 SSVAL(params,18,smb_action);
1283 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1285 SIVAL(params,20,inode);
1286 SSVAL(params,24,0); /* Padding. */
1287 if (flags & 8) {
1288 uint32 ea_size = estimate_ea_size(conn, fsp,
1289 smb_fname);
1290 SIVAL(params, 26, ea_size);
1291 } else {
1292 SIVAL(params, 26, 0);
1295 /* Send the required number of replies */
1296 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1297 out:
1298 TALLOC_FREE(smb_fname);
1301 /*********************************************************
1302 Routine to check if a given string matches exactly.
1303 as a special case a mask of "." does NOT match. That
1304 is required for correct wildcard semantics
1305 Case can be significant or not.
1306 **********************************************************/
1308 static bool exact_match(bool has_wild,
1309 bool case_sensitive,
1310 const char *str,
1311 const char *mask)
1313 if (mask[0] == '.' && mask[1] == 0) {
1314 return false;
1317 if (has_wild) {
1318 return false;
1321 if (case_sensitive) {
1322 return strcmp(str,mask)==0;
1323 } else {
1324 return strcasecmp_m(str,mask) == 0;
1328 /****************************************************************************
1329 Return the filetype for UNIX extensions.
1330 ****************************************************************************/
1332 static uint32 unix_filetype(mode_t mode)
1334 if(S_ISREG(mode))
1335 return UNIX_TYPE_FILE;
1336 else if(S_ISDIR(mode))
1337 return UNIX_TYPE_DIR;
1338 #ifdef S_ISLNK
1339 else if(S_ISLNK(mode))
1340 return UNIX_TYPE_SYMLINK;
1341 #endif
1342 #ifdef S_ISCHR
1343 else if(S_ISCHR(mode))
1344 return UNIX_TYPE_CHARDEV;
1345 #endif
1346 #ifdef S_ISBLK
1347 else if(S_ISBLK(mode))
1348 return UNIX_TYPE_BLKDEV;
1349 #endif
1350 #ifdef S_ISFIFO
1351 else if(S_ISFIFO(mode))
1352 return UNIX_TYPE_FIFO;
1353 #endif
1354 #ifdef S_ISSOCK
1355 else if(S_ISSOCK(mode))
1356 return UNIX_TYPE_SOCKET;
1357 #endif
1359 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1360 return UNIX_TYPE_UNKNOWN;
1363 /****************************************************************************
1364 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1365 ****************************************************************************/
1367 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1369 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1370 const SMB_STRUCT_STAT *psbuf,
1371 uint32 perms,
1372 enum perm_type ptype,
1373 mode_t *ret_perms)
1375 mode_t ret = 0;
1377 if (perms == SMB_MODE_NO_CHANGE) {
1378 if (!VALID_STAT(*psbuf)) {
1379 return NT_STATUS_INVALID_PARAMETER;
1380 } else {
1381 *ret_perms = psbuf->st_ex_mode;
1382 return NT_STATUS_OK;
1386 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1387 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1388 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1389 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1390 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1391 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1392 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1393 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1394 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1395 #ifdef S_ISVTX
1396 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1397 #endif
1398 #ifdef S_ISGID
1399 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1400 #endif
1401 #ifdef S_ISUID
1402 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1403 #endif
1405 switch (ptype) {
1406 case PERM_NEW_FILE:
1407 case PERM_EXISTING_FILE:
1408 /* Apply mode mask */
1409 ret &= lp_create_mask(SNUM(conn));
1410 /* Add in force bits */
1411 ret |= lp_force_create_mode(SNUM(conn));
1412 break;
1413 case PERM_NEW_DIR:
1414 case PERM_EXISTING_DIR:
1415 ret &= lp_dir_mask(SNUM(conn));
1416 /* Add in force bits */
1417 ret |= lp_force_dir_mode(SNUM(conn));
1418 break;
1421 *ret_perms = ret;
1422 return NT_STATUS_OK;
1425 /****************************************************************************
1426 Needed to show the msdfs symlinks as directories. Modifies psbuf
1427 to be a directory if it's a msdfs link.
1428 ****************************************************************************/
1430 static bool check_msdfs_link(connection_struct *conn,
1431 const char *pathname,
1432 SMB_STRUCT_STAT *psbuf)
1434 int saved_errno = errno;
1435 if(lp_host_msdfs() &&
1436 lp_msdfs_root(SNUM(conn)) &&
1437 is_msdfs_link(conn, pathname, psbuf)) {
1439 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1440 "as a directory\n",
1441 pathname));
1442 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1443 errno = saved_errno;
1444 return true;
1446 errno = saved_errno;
1447 return false;
1451 /****************************************************************************
1452 Get a level dependent lanman2 dir entry.
1453 ****************************************************************************/
1455 struct smbd_dirptr_lanman2_state {
1456 connection_struct *conn;
1457 uint32_t info_level;
1458 bool check_mangled_names;
1459 bool has_wild;
1460 bool got_exact_match;
1463 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1464 void *private_data,
1465 const char *dname,
1466 const char *mask,
1467 char **_fname)
1469 struct smbd_dirptr_lanman2_state *state =
1470 (struct smbd_dirptr_lanman2_state *)private_data;
1471 bool ok;
1472 char mangled_name[13]; /* mangled 8.3 name. */
1473 bool got_match;
1474 const char *fname;
1476 /* Mangle fname if it's an illegal name. */
1477 if (mangle_must_mangle(dname, state->conn->params)) {
1478 ok = name_to_8_3(dname, mangled_name,
1479 true, state->conn->params);
1480 if (!ok) {
1481 return false;
1483 fname = mangled_name;
1484 } else {
1485 fname = dname;
1488 got_match = exact_match(state->has_wild,
1489 state->conn->case_sensitive,
1490 fname, mask);
1491 state->got_exact_match = got_match;
1492 if (!got_match) {
1493 got_match = mask_match(fname, mask,
1494 state->conn->case_sensitive);
1497 if(!got_match && state->check_mangled_names &&
1498 !mangle_is_8_3(fname, false, state->conn->params)) {
1500 * It turns out that NT matches wildcards against
1501 * both long *and* short names. This may explain some
1502 * of the wildcard wierdness from old DOS clients
1503 * that some people have been seeing.... JRA.
1505 /* Force the mangling into 8.3. */
1506 ok = name_to_8_3(fname, mangled_name,
1507 false, state->conn->params);
1508 if (!ok) {
1509 return false;
1512 got_match = exact_match(state->has_wild,
1513 state->conn->case_sensitive,
1514 mangled_name, mask);
1515 state->got_exact_match = got_match;
1516 if (!got_match) {
1517 got_match = mask_match(mangled_name, mask,
1518 state->conn->case_sensitive);
1522 if (!got_match) {
1523 return false;
1526 *_fname = talloc_strdup(ctx, fname);
1527 if (*_fname == NULL) {
1528 return false;
1531 return true;
1534 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1535 void *private_data,
1536 struct smb_filename *smb_fname,
1537 uint32_t *_mode)
1539 struct smbd_dirptr_lanman2_state *state =
1540 (struct smbd_dirptr_lanman2_state *)private_data;
1541 bool ms_dfs_link = false;
1542 uint32_t mode = 0;
1544 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1545 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1546 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1547 "Couldn't lstat [%s] (%s)\n",
1548 smb_fname_str_dbg(smb_fname),
1549 strerror(errno)));
1550 return false;
1552 } else if (!VALID_STAT(smb_fname->st) &&
1553 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1554 /* Needed to show the msdfs symlinks as
1555 * directories */
1557 ms_dfs_link = check_msdfs_link(state->conn,
1558 smb_fname->base_name,
1559 &smb_fname->st);
1560 if (!ms_dfs_link) {
1561 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1562 "Couldn't stat [%s] (%s)\n",
1563 smb_fname_str_dbg(smb_fname),
1564 strerror(errno)));
1565 return false;
1569 if (ms_dfs_link) {
1570 mode = dos_mode_msdfs(state->conn, smb_fname);
1571 } else {
1572 mode = dos_mode(state->conn, smb_fname);
1575 *_mode = mode;
1576 return true;
1579 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1580 connection_struct *conn,
1581 uint16_t flags2,
1582 uint32_t info_level,
1583 struct ea_list *name_list,
1584 bool check_mangled_names,
1585 bool requires_resume_key,
1586 uint32_t mode,
1587 const char *fname,
1588 const struct smb_filename *smb_fname,
1589 int space_remaining,
1590 uint8_t align,
1591 bool do_pad,
1592 char *base_data,
1593 char **ppdata,
1594 char *end_data,
1595 bool *out_of_space,
1596 uint64_t *last_entry_off)
1598 char *p, *q, *pdata = *ppdata;
1599 uint32_t reskey=0;
1600 uint64_t file_size = 0;
1601 uint64_t allocation_size = 0;
1602 uint64_t file_index = 0;
1603 uint32_t len;
1604 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1605 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1606 char *nameptr;
1607 char *last_entry_ptr;
1608 bool was_8_3;
1609 int off;
1610 int pad = 0;
1612 *out_of_space = false;
1614 ZERO_STRUCT(mdate_ts);
1615 ZERO_STRUCT(adate_ts);
1616 ZERO_STRUCT(create_date_ts);
1617 ZERO_STRUCT(cdate_ts);
1619 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1620 file_size = get_file_size_stat(&smb_fname->st);
1622 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1624 file_index = get_FileIndex(conn, &smb_fname->st);
1626 mdate_ts = smb_fname->st.st_ex_mtime;
1627 adate_ts = smb_fname->st.st_ex_atime;
1628 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1629 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1631 if (lp_dos_filetime_resolution(SNUM(conn))) {
1632 dos_filetime_timespec(&create_date_ts);
1633 dos_filetime_timespec(&mdate_ts);
1634 dos_filetime_timespec(&adate_ts);
1635 dos_filetime_timespec(&cdate_ts);
1638 create_date = convert_timespec_to_time_t(create_date_ts);
1639 mdate = convert_timespec_to_time_t(mdate_ts);
1640 adate = convert_timespec_to_time_t(adate_ts);
1642 /* align the record */
1643 SMB_ASSERT(align >= 1);
1645 off = (int)PTR_DIFF(pdata, base_data);
1646 pad = (off + (align-1)) & ~(align-1);
1647 pad -= off;
1649 if (pad && pad > space_remaining) {
1650 *out_of_space = true;
1651 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1652 "for padding (wanted %u, had %d)\n",
1653 (unsigned int)pad,
1654 space_remaining ));
1655 return false; /* Not finished - just out of space */
1658 off += pad;
1659 /* initialize padding to 0 */
1660 if (pad) {
1661 memset(pdata, 0, pad);
1663 space_remaining -= pad;
1665 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1666 space_remaining ));
1668 pdata += pad;
1669 p = pdata;
1670 last_entry_ptr = p;
1672 pad = 0;
1673 off = 0;
1675 switch (info_level) {
1676 case SMB_FIND_INFO_STANDARD:
1677 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1678 if(requires_resume_key) {
1679 SIVAL(p,0,reskey);
1680 p += 4;
1682 srv_put_dos_date2(p,0,create_date);
1683 srv_put_dos_date2(p,4,adate);
1684 srv_put_dos_date2(p,8,mdate);
1685 SIVAL(p,12,(uint32)file_size);
1686 SIVAL(p,16,(uint32)allocation_size);
1687 SSVAL(p,20,mode);
1688 p += 23;
1689 nameptr = p;
1690 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1691 p += ucs2_align(base_data, p, 0);
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE);
1696 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1697 if (len > 2) {
1698 SCVAL(nameptr, -1, len - 2);
1699 } else {
1700 SCVAL(nameptr, -1, 0);
1702 } else {
1703 if (len > 1) {
1704 SCVAL(nameptr, -1, len - 1);
1705 } else {
1706 SCVAL(nameptr, -1, 0);
1709 p += len;
1710 break;
1712 case SMB_FIND_EA_SIZE:
1713 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1714 if (requires_resume_key) {
1715 SIVAL(p,0,reskey);
1716 p += 4;
1718 srv_put_dos_date2(p,0,create_date);
1719 srv_put_dos_date2(p,4,adate);
1720 srv_put_dos_date2(p,8,mdate);
1721 SIVAL(p,12,(uint32)file_size);
1722 SIVAL(p,16,(uint32)allocation_size);
1723 SSVAL(p,20,mode);
1725 unsigned int ea_size = estimate_ea_size(conn, NULL,
1726 smb_fname);
1727 SIVAL(p,22,ea_size); /* Extended attributes */
1729 p += 27;
1730 nameptr = p - 1;
1731 len = srvstr_push(base_data, flags2,
1732 p, fname, PTR_DIFF(end_data, p),
1733 STR_TERMINATE | STR_NOALIGN);
1734 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1735 if (len > 2) {
1736 len -= 2;
1737 } else {
1738 len = 0;
1740 } else {
1741 if (len > 1) {
1742 len -= 1;
1743 } else {
1744 len = 0;
1747 SCVAL(nameptr,0,len);
1748 p += len;
1749 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1750 break;
1752 case SMB_FIND_EA_LIST:
1754 struct ea_list *file_list = NULL;
1755 size_t ea_len = 0;
1756 NTSTATUS status;
1758 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1759 if (!name_list) {
1760 return false;
1762 if (requires_resume_key) {
1763 SIVAL(p,0,reskey);
1764 p += 4;
1766 srv_put_dos_date2(p,0,create_date);
1767 srv_put_dos_date2(p,4,adate);
1768 srv_put_dos_date2(p,8,mdate);
1769 SIVAL(p,12,(uint32)file_size);
1770 SIVAL(p,16,(uint32)allocation_size);
1771 SSVAL(p,20,mode);
1772 p += 22; /* p now points to the EA area. */
1774 status = get_ea_list_from_file(ctx, conn, NULL,
1775 smb_fname,
1776 &ea_len, &file_list);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 file_list = NULL;
1780 name_list = ea_list_union(name_list, file_list, &ea_len);
1782 /* We need to determine if this entry will fit in the space available. */
1783 /* Max string size is 255 bytes. */
1784 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1785 *out_of_space = true;
1786 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1787 "(wanted %u, had %d)\n",
1788 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1789 space_remaining ));
1790 return False; /* Not finished - just out of space */
1793 /* Push the ea_data followed by the name. */
1794 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1795 nameptr = p;
1796 len = srvstr_push(base_data, flags2,
1797 p + 1, fname, PTR_DIFF(end_data, p+1),
1798 STR_TERMINATE | STR_NOALIGN);
1799 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1800 if (len > 2) {
1801 len -= 2;
1802 } else {
1803 len = 0;
1805 } else {
1806 if (len > 1) {
1807 len -= 1;
1808 } else {
1809 len = 0;
1812 SCVAL(nameptr,0,len);
1813 p += len + 1;
1814 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1815 break;
1818 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1819 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1820 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1821 p += 4;
1822 SIVAL(p,0,reskey); p += 4;
1823 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1827 SOFF_T(p,0,file_size); p += 8;
1828 SOFF_T(p,0,allocation_size); p += 8;
1829 SIVAL(p,0,mode); p += 4;
1830 q = p; p += 4; /* q is placeholder for name length. */
1832 unsigned int ea_size = estimate_ea_size(conn, NULL,
1833 smb_fname);
1834 SIVAL(p,0,ea_size); /* Extended attributes */
1835 p += 4;
1837 /* Clear the short name buffer. This is
1838 * IMPORTANT as not doing so will trigger
1839 * a Win2k client bug. JRA.
1841 if (!was_8_3 && check_mangled_names) {
1842 char mangled_name[13]; /* mangled 8.3 name. */
1843 if (!name_to_8_3(fname,mangled_name,True,
1844 conn->params)) {
1845 /* Error - mangle failed ! */
1846 memset(mangled_name,'\0',12);
1848 mangled_name[12] = 0;
1849 len = srvstr_push(base_data, flags2,
1850 p+2, mangled_name, 24,
1851 STR_UPPER|STR_UNICODE);
1852 if (len < 24) {
1853 memset(p + 2 + len,'\0',24 - len);
1855 SSVAL(p, 0, len);
1856 } else {
1857 memset(p,'\0',26);
1859 p += 2 + 24;
1860 len = srvstr_push(base_data, flags2, p,
1861 fname, PTR_DIFF(end_data, p),
1862 STR_TERMINATE_ASCII);
1863 SIVAL(q,0,len);
1864 p += len;
1866 len = PTR_DIFF(p, pdata);
1867 pad = (len + (align-1)) & ~(align-1);
1869 * offset to the next entry, the caller
1870 * will overwrite it for the last entry
1871 * that's why we always include the padding
1873 SIVAL(pdata,0,pad);
1875 * set padding to zero
1877 if (do_pad) {
1878 memset(p, 0, pad - len);
1879 p = pdata + pad;
1880 } else {
1881 p = pdata + len;
1883 break;
1885 case SMB_FIND_FILE_DIRECTORY_INFO:
1886 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1887 p += 4;
1888 SIVAL(p,0,reskey); p += 4;
1889 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1890 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1891 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1892 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1893 SOFF_T(p,0,file_size); p += 8;
1894 SOFF_T(p,0,allocation_size); p += 8;
1895 SIVAL(p,0,mode); p += 4;
1896 len = srvstr_push(base_data, flags2,
1897 p + 4, fname, PTR_DIFF(end_data, p+4),
1898 STR_TERMINATE_ASCII);
1899 SIVAL(p,0,len);
1900 p += 4 + len;
1902 len = PTR_DIFF(p, pdata);
1903 pad = (len + (align-1)) & ~(align-1);
1905 * offset to the next entry, the caller
1906 * will overwrite it for the last entry
1907 * that's why we always include the padding
1909 SIVAL(pdata,0,pad);
1911 * set padding to zero
1913 if (do_pad) {
1914 memset(p, 0, pad - len);
1915 p = pdata + pad;
1916 } else {
1917 p = pdata + len;
1919 break;
1921 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1922 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1923 p += 4;
1924 SIVAL(p,0,reskey); p += 4;
1925 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1926 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1927 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1929 SOFF_T(p,0,file_size); p += 8;
1930 SOFF_T(p,0,allocation_size); p += 8;
1931 SIVAL(p,0,mode); p += 4;
1932 q = p; p += 4; /* q is placeholder for name length. */
1934 unsigned int ea_size = estimate_ea_size(conn, NULL,
1935 smb_fname);
1936 SIVAL(p,0,ea_size); /* Extended attributes */
1937 p +=4;
1939 len = srvstr_push(base_data, flags2, p,
1940 fname, PTR_DIFF(end_data, p),
1941 STR_TERMINATE_ASCII);
1942 SIVAL(q, 0, len);
1943 p += len;
1945 len = PTR_DIFF(p, pdata);
1946 pad = (len + (align-1)) & ~(align-1);
1948 * offset to the next entry, the caller
1949 * will overwrite it for the last entry
1950 * that's why we always include the padding
1952 SIVAL(pdata,0,pad);
1954 * set padding to zero
1956 if (do_pad) {
1957 memset(p, 0, pad - len);
1958 p = pdata + pad;
1959 } else {
1960 p = pdata + len;
1962 break;
1964 case SMB_FIND_FILE_NAMES_INFO:
1965 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1966 p += 4;
1967 SIVAL(p,0,reskey); p += 4;
1968 p += 4;
1969 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1970 acl on a dir (tridge) */
1971 len = srvstr_push(base_data, flags2, p,
1972 fname, PTR_DIFF(end_data, p),
1973 STR_TERMINATE_ASCII);
1974 SIVAL(p, -4, len);
1975 p += len;
1977 len = PTR_DIFF(p, pdata);
1978 pad = (len + (align-1)) & ~(align-1);
1980 * offset to the next entry, the caller
1981 * will overwrite it for the last entry
1982 * that's why we always include the padding
1984 SIVAL(pdata,0,pad);
1986 * set padding to zero
1988 if (do_pad) {
1989 memset(p, 0, pad - len);
1990 p = pdata + pad;
1991 } else {
1992 p = pdata + len;
1994 break;
1996 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1997 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1998 p += 4;
1999 SIVAL(p,0,reskey); p += 4;
2000 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2001 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2002 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2003 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2004 SOFF_T(p,0,file_size); p += 8;
2005 SOFF_T(p,0,allocation_size); p += 8;
2006 SIVAL(p,0,mode); p += 4;
2007 q = p; p += 4; /* q is placeholder for name length. */
2009 unsigned int ea_size = estimate_ea_size(conn, NULL,
2010 smb_fname);
2011 SIVAL(p,0,ea_size); /* Extended attributes */
2012 p +=4;
2014 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2015 SBVAL(p,0,file_index); p += 8;
2016 len = srvstr_push(base_data, flags2, p,
2017 fname, PTR_DIFF(end_data, p),
2018 STR_TERMINATE_ASCII);
2019 SIVAL(q, 0, len);
2020 p += len;
2022 len = PTR_DIFF(p, pdata);
2023 pad = (len + (align-1)) & ~(align-1);
2025 * offset to the next entry, the caller
2026 * will overwrite it for the last entry
2027 * that's why we always include the padding
2029 SIVAL(pdata,0,pad);
2031 * set padding to zero
2033 if (do_pad) {
2034 memset(p, 0, pad - len);
2035 p = pdata + pad;
2036 } else {
2037 p = pdata + len;
2039 break;
2041 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2042 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2043 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2044 p += 4;
2045 SIVAL(p,0,reskey); p += 4;
2046 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2047 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2049 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2050 SOFF_T(p,0,file_size); p += 8;
2051 SOFF_T(p,0,allocation_size); p += 8;
2052 SIVAL(p,0,mode); p += 4;
2053 q = p; p += 4; /* q is placeholder for name length */
2055 unsigned int ea_size = estimate_ea_size(conn, NULL,
2056 smb_fname);
2057 SIVAL(p,0,ea_size); /* Extended attributes */
2058 p +=4;
2060 /* Clear the short name buffer. This is
2061 * IMPORTANT as not doing so will trigger
2062 * a Win2k client bug. JRA.
2064 if (!was_8_3 && check_mangled_names) {
2065 char mangled_name[13]; /* mangled 8.3 name. */
2066 if (!name_to_8_3(fname,mangled_name,True,
2067 conn->params)) {
2068 /* Error - mangle failed ! */
2069 memset(mangled_name,'\0',12);
2071 mangled_name[12] = 0;
2072 len = srvstr_push(base_data, flags2,
2073 p+2, mangled_name, 24,
2074 STR_UPPER|STR_UNICODE);
2075 SSVAL(p, 0, len);
2076 if (len < 24) {
2077 memset(p + 2 + len,'\0',24 - len);
2079 SSVAL(p, 0, len);
2080 } else {
2081 memset(p,'\0',26);
2083 p += 26;
2084 SSVAL(p,0,0); p += 2; /* Reserved ? */
2085 SBVAL(p,0,file_index); p += 8;
2086 len = srvstr_push(base_data, flags2, p,
2087 fname, PTR_DIFF(end_data, p),
2088 STR_TERMINATE_ASCII);
2089 SIVAL(q,0,len);
2090 p += len;
2092 len = PTR_DIFF(p, pdata);
2093 pad = (len + (align-1)) & ~(align-1);
2095 * offset to the next entry, the caller
2096 * will overwrite it for the last entry
2097 * that's why we always include the padding
2099 SIVAL(pdata,0,pad);
2101 * set padding to zero
2103 if (do_pad) {
2104 memset(p, 0, pad - len);
2105 p = pdata + pad;
2106 } else {
2107 p = pdata + len;
2109 break;
2111 /* CIFS UNIX Extension. */
2113 case SMB_FIND_FILE_UNIX:
2114 case SMB_FIND_FILE_UNIX_INFO2:
2115 p+= 4;
2116 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2118 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2120 if (info_level == SMB_FIND_FILE_UNIX) {
2121 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2122 p = store_file_unix_basic(conn, p,
2123 NULL, &smb_fname->st);
2124 len = srvstr_push(base_data, flags2, p,
2125 fname, PTR_DIFF(end_data, p),
2126 STR_TERMINATE);
2127 } else {
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2129 p = store_file_unix_basic_info2(conn, p,
2130 NULL, &smb_fname->st);
2131 nameptr = p;
2132 p += 4;
2133 len = srvstr_push(base_data, flags2, p, fname,
2134 PTR_DIFF(end_data, p), 0);
2135 SIVAL(nameptr, 0, len);
2138 p += len;
2140 len = PTR_DIFF(p, pdata);
2141 pad = (len + (align-1)) & ~(align-1);
2143 * offset to the next entry, the caller
2144 * will overwrite it for the last entry
2145 * that's why we always include the padding
2147 SIVAL(pdata,0,pad);
2149 * set padding to zero
2151 if (do_pad) {
2152 memset(p, 0, pad - len);
2153 p = pdata + pad;
2154 } else {
2155 p = pdata + len;
2157 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2159 break;
2161 default:
2162 return false;
2165 if (PTR_DIFF(p,pdata) > space_remaining) {
2166 *out_of_space = true;
2167 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2168 "(wanted %u, had %d)\n",
2169 (unsigned int)PTR_DIFF(p,pdata),
2170 space_remaining ));
2171 return false; /* Not finished - just out of space */
2174 /* Setup the last entry pointer, as an offset from base_data */
2175 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2176 /* Advance the data pointer to the next slot */
2177 *ppdata = p;
2179 return true;
2182 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2183 connection_struct *conn,
2184 struct dptr_struct *dirptr,
2185 uint16 flags2,
2186 const char *path_mask,
2187 uint32 dirtype,
2188 int info_level,
2189 int requires_resume_key,
2190 bool dont_descend,
2191 bool ask_sharemode,
2192 uint8_t align,
2193 bool do_pad,
2194 char **ppdata,
2195 char *base_data,
2196 char *end_data,
2197 int space_remaining,
2198 bool *out_of_space,
2199 bool *got_exact_match,
2200 int *_last_entry_off,
2201 struct ea_list *name_list)
2203 const char *p;
2204 const char *mask = NULL;
2205 long prev_dirpos = 0;
2206 uint32_t mode = 0;
2207 char *fname = NULL;
2208 struct smb_filename *smb_fname = NULL;
2209 struct smbd_dirptr_lanman2_state state;
2210 bool ok;
2211 uint64_t last_entry_off = 0;
2213 ZERO_STRUCT(state);
2214 state.conn = conn;
2215 state.info_level = info_level;
2216 state.check_mangled_names = lp_manglednames(conn->params);
2217 state.has_wild = dptr_has_wild(dirptr);
2218 state.got_exact_match = false;
2220 *out_of_space = false;
2221 *got_exact_match = false;
2223 p = strrchr_m(path_mask,'/');
2224 if(p != NULL) {
2225 if(p[1] == '\0') {
2226 mask = "*.*";
2227 } else {
2228 mask = p+1;
2230 } else {
2231 mask = path_mask;
2234 ok = smbd_dirptr_get_entry(ctx,
2235 dirptr,
2236 mask,
2237 dirtype,
2238 dont_descend,
2239 ask_sharemode,
2240 smbd_dirptr_lanman2_match_fn,
2241 smbd_dirptr_lanman2_mode_fn,
2242 &state,
2243 &fname,
2244 &smb_fname,
2245 &mode,
2246 &prev_dirpos);
2247 if (!ok) {
2248 return false;
2251 *got_exact_match = state.got_exact_match;
2253 ok = smbd_marshall_dir_entry(ctx,
2254 conn,
2255 flags2,
2256 info_level,
2257 name_list,
2258 state.check_mangled_names,
2259 requires_resume_key,
2260 mode,
2261 fname,
2262 smb_fname,
2263 space_remaining,
2264 align,
2265 do_pad,
2266 base_data,
2267 ppdata,
2268 end_data,
2269 out_of_space,
2270 &last_entry_off);
2271 TALLOC_FREE(fname);
2272 TALLOC_FREE(smb_fname);
2273 if (*out_of_space) {
2274 dptr_SeekDir(dirptr, prev_dirpos);
2275 return false;
2277 if (!ok) {
2278 return false;
2281 *_last_entry_off = last_entry_off;
2282 return true;
2285 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2286 connection_struct *conn,
2287 struct dptr_struct *dirptr,
2288 uint16 flags2,
2289 const char *path_mask,
2290 uint32 dirtype,
2291 int info_level,
2292 bool requires_resume_key,
2293 bool dont_descend,
2294 bool ask_sharemode,
2295 char **ppdata,
2296 char *base_data,
2297 char *end_data,
2298 int space_remaining,
2299 bool *out_of_space,
2300 bool *got_exact_match,
2301 int *last_entry_off,
2302 struct ea_list *name_list)
2304 uint8_t align = 4;
2305 const bool do_pad = true;
2307 if (info_level >= 1 && info_level <= 3) {
2308 /* No alignment on earlier info levels. */
2309 align = 1;
2312 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2313 path_mask, dirtype, info_level,
2314 requires_resume_key, dont_descend, ask_sharemode,
2315 align, do_pad,
2316 ppdata, base_data, end_data,
2317 space_remaining,
2318 out_of_space, got_exact_match,
2319 last_entry_off, name_list);
2322 /****************************************************************************
2323 Reply to a TRANS2_FINDFIRST.
2324 ****************************************************************************/
2326 static void call_trans2findfirst(connection_struct *conn,
2327 struct smb_request *req,
2328 char **pparams, int total_params,
2329 char **ppdata, int total_data,
2330 unsigned int max_data_bytes)
2332 /* We must be careful here that we don't return more than the
2333 allowed number of data bytes. If this means returning fewer than
2334 maxentries then so be it. We assume that the redirector has
2335 enough room for the fixed number of parameter bytes it has
2336 requested. */
2337 struct smb_filename *smb_dname = NULL;
2338 char *params = *pparams;
2339 char *pdata = *ppdata;
2340 char *data_end;
2341 uint32 dirtype;
2342 int maxentries;
2343 uint16 findfirst_flags;
2344 bool close_after_first;
2345 bool close_if_end;
2346 bool requires_resume_key;
2347 int info_level;
2348 char *directory = NULL;
2349 char *mask = NULL;
2350 char *p;
2351 int last_entry_off=0;
2352 int dptr_num = -1;
2353 int numentries = 0;
2354 int i;
2355 bool finished = False;
2356 bool dont_descend = False;
2357 bool out_of_space = False;
2358 int space_remaining;
2359 bool mask_contains_wcard = False;
2360 struct ea_list *ea_list = NULL;
2361 NTSTATUS ntstatus = NT_STATUS_OK;
2362 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2363 TALLOC_CTX *ctx = talloc_tos();
2364 struct dptr_struct *dirptr = NULL;
2365 struct smbd_server_connection *sconn = req->sconn;
2366 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2367 bool backup_priv = false;
2369 if (total_params < 13) {
2370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 goto out;
2374 dirtype = SVAL(params,0);
2375 maxentries = SVAL(params,2);
2376 findfirst_flags = SVAL(params,4);
2377 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2378 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2379 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2380 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2381 security_token_has_privilege(get_current_nttok(conn),
2382 SEC_PRIV_BACKUP));
2384 info_level = SVAL(params,6);
2386 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2387 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2388 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2389 (int)backup_priv,
2390 info_level, max_data_bytes));
2392 if (!maxentries) {
2393 /* W2K3 seems to treat zero as 1. */
2394 maxentries = 1;
2397 switch (info_level) {
2398 case SMB_FIND_INFO_STANDARD:
2399 case SMB_FIND_EA_SIZE:
2400 case SMB_FIND_EA_LIST:
2401 case SMB_FIND_FILE_DIRECTORY_INFO:
2402 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2403 case SMB_FIND_FILE_NAMES_INFO:
2404 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2405 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2406 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2407 break;
2408 case SMB_FIND_FILE_UNIX:
2409 case SMB_FIND_FILE_UNIX_INFO2:
2410 /* Always use filesystem for UNIX mtime query. */
2411 ask_sharemode = false;
2412 if (!lp_unix_extensions()) {
2413 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2414 goto out;
2416 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2417 break;
2418 default:
2419 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2420 goto out;
2423 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2424 params+12, total_params - 12,
2425 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2426 if (!NT_STATUS_IS_OK(ntstatus)) {
2427 reply_nterror(req, ntstatus);
2428 goto out;
2431 if (backup_priv) {
2432 become_root();
2433 ntstatus = filename_convert_with_privilege(ctx,
2434 conn,
2435 req,
2436 directory,
2437 ucf_flags,
2438 &mask_contains_wcard,
2439 &smb_dname);
2440 } else {
2441 ntstatus = filename_convert(ctx, conn,
2442 req->flags2 & FLAGS2_DFS_PATHNAMES,
2443 directory,
2444 ucf_flags,
2445 &mask_contains_wcard,
2446 &smb_dname);
2449 if (!NT_STATUS_IS_OK(ntstatus)) {
2450 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2451 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2452 ERRSRV, ERRbadpath);
2453 goto out;
2455 reply_nterror(req, ntstatus);
2456 goto out;
2459 mask = smb_dname->original_lcomp;
2461 directory = smb_dname->base_name;
2463 p = strrchr_m(directory,'/');
2464 if(p == NULL) {
2465 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2466 if((directory[0] == '.') && (directory[1] == '\0')) {
2467 mask = talloc_strdup(ctx,"*");
2468 if (!mask) {
2469 reply_nterror(req, NT_STATUS_NO_MEMORY);
2470 goto out;
2472 mask_contains_wcard = True;
2474 } else {
2475 *p = 0;
2478 if (p == NULL || p == directory) {
2479 /* Ensure we don't have a directory name of "". */
2480 directory = talloc_strdup(talloc_tos(), ".");
2481 if (!directory) {
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 goto out;
2487 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2489 if (info_level == SMB_FIND_EA_LIST) {
2490 uint32 ea_size;
2492 if (total_data < 4) {
2493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2494 goto out;
2497 ea_size = IVAL(pdata,0);
2498 if (ea_size != total_data) {
2499 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2500 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2502 goto out;
2505 if (!lp_ea_support(SNUM(conn))) {
2506 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2507 goto out;
2510 /* Pull out the list of names. */
2511 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2512 if (!ea_list) {
2513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2514 goto out;
2518 *ppdata = (char *)SMB_REALLOC(
2519 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2520 if(*ppdata == NULL ) {
2521 reply_nterror(req, NT_STATUS_NO_MEMORY);
2522 goto out;
2524 pdata = *ppdata;
2525 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2527 /* Realloc the params space */
2528 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2529 if (*pparams == NULL) {
2530 reply_nterror(req, NT_STATUS_NO_MEMORY);
2531 goto out;
2533 params = *pparams;
2535 /* Save the wildcard match and attribs we are using on this directory -
2536 needed as lanman2 assumes these are being saved between calls */
2538 ntstatus = dptr_create(conn,
2539 req,
2540 NULL, /* fsp */
2541 directory,
2542 False,
2543 True,
2544 req->smbpid,
2545 mask,
2546 mask_contains_wcard,
2547 dirtype,
2548 &dirptr);
2550 if (!NT_STATUS_IS_OK(ntstatus)) {
2551 reply_nterror(req, ntstatus);
2552 goto out;
2555 if (backup_priv) {
2556 /* Remember this in case we have
2557 to do a findnext. */
2558 dptr_set_priv(dirptr);
2561 dptr_num = dptr_dnum(dirptr);
2562 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2564 /* Initialize per TRANS2_FIND_FIRST operation data */
2565 dptr_init_search_op(dirptr);
2567 /* We don't need to check for VOL here as this is returned by
2568 a different TRANS2 call. */
2570 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2571 directory,lp_dontdescend(ctx, SNUM(conn))));
2572 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2573 dont_descend = True;
2575 p = pdata;
2576 space_remaining = max_data_bytes;
2577 out_of_space = False;
2579 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2580 bool got_exact_match = False;
2582 /* this is a heuristic to avoid seeking the dirptr except when
2583 absolutely necessary. It allows for a filename of about 40 chars */
2584 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2585 out_of_space = True;
2586 finished = False;
2587 } else {
2588 finished = !get_lanman2_dir_entry(ctx,
2589 conn,
2590 dirptr,
2591 req->flags2,
2592 mask,dirtype,info_level,
2593 requires_resume_key,dont_descend,
2594 ask_sharemode,
2595 &p,pdata,data_end,
2596 space_remaining, &out_of_space,
2597 &got_exact_match,
2598 &last_entry_off, ea_list);
2601 if (finished && out_of_space)
2602 finished = False;
2604 if (!finished && !out_of_space)
2605 numentries++;
2608 * As an optimisation if we know we aren't looking
2609 * for a wildcard name (ie. the name matches the wildcard exactly)
2610 * then we can finish on any (first) match.
2611 * This speeds up large directory searches. JRA.
2614 if(got_exact_match)
2615 finished = True;
2617 /* Ensure space_remaining never goes -ve. */
2618 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2619 space_remaining = 0;
2620 out_of_space = true;
2621 } else {
2622 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2626 /* Check if we can close the dirptr */
2627 if(close_after_first || (finished && close_if_end)) {
2628 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2629 dptr_close(sconn, &dptr_num);
2633 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2634 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2635 * the protocol level is less than NT1. Tested with smbclient. JRA.
2636 * This should fix the OS/2 client bug #2335.
2639 if(numentries == 0) {
2640 dptr_close(sconn, &dptr_num);
2641 if (get_Protocol() < PROTOCOL_NT1) {
2642 reply_force_doserror(req, ERRDOS, ERRnofiles);
2643 goto out;
2644 } else {
2645 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2646 ERRDOS, ERRbadfile);
2647 goto out;
2651 /* At this point pdata points to numentries directory entries. */
2653 /* Set up the return parameter block */
2654 SSVAL(params,0,dptr_num);
2655 SSVAL(params,2,numentries);
2656 SSVAL(params,4,finished);
2657 SSVAL(params,6,0); /* Never an EA error */
2658 SSVAL(params,8,last_entry_off);
2660 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2661 max_data_bytes);
2663 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2664 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2665 if (!directory) {
2666 reply_nterror(req, NT_STATUS_NO_MEMORY);
2670 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2671 smb_fn_name(req->cmd),
2672 mask, directory, dirtype, numentries ) );
2675 * Force a name mangle here to ensure that the
2676 * mask as an 8.3 name is top of the mangled cache.
2677 * The reasons for this are subtle. Don't remove
2678 * this code unless you know what you are doing
2679 * (see PR#13758). JRA.
2682 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2683 char mangled_name[13];
2684 name_to_8_3(mask, mangled_name, True, conn->params);
2686 out:
2688 if (backup_priv) {
2689 unbecome_root();
2692 TALLOC_FREE(smb_dname);
2693 return;
2696 /****************************************************************************
2697 Reply to a TRANS2_FINDNEXT.
2698 ****************************************************************************/
2700 static void call_trans2findnext(connection_struct *conn,
2701 struct smb_request *req,
2702 char **pparams, int total_params,
2703 char **ppdata, int total_data,
2704 unsigned int max_data_bytes)
2706 /* We must be careful here that we don't return more than the
2707 allowed number of data bytes. If this means returning fewer than
2708 maxentries then so be it. We assume that the redirector has
2709 enough room for the fixed number of parameter bytes it has
2710 requested. */
2711 char *params = *pparams;
2712 char *pdata = *ppdata;
2713 char *data_end;
2714 int dptr_num;
2715 int maxentries;
2716 uint16 info_level;
2717 uint32 resume_key;
2718 uint16 findnext_flags;
2719 bool close_after_request;
2720 bool close_if_end;
2721 bool requires_resume_key;
2722 bool continue_bit;
2723 bool mask_contains_wcard = False;
2724 char *resume_name = NULL;
2725 const char *mask = NULL;
2726 const char *directory = NULL;
2727 char *p = NULL;
2728 uint16 dirtype;
2729 int numentries = 0;
2730 int i, last_entry_off=0;
2731 bool finished = False;
2732 bool dont_descend = False;
2733 bool out_of_space = False;
2734 int space_remaining;
2735 struct ea_list *ea_list = NULL;
2736 NTSTATUS ntstatus = NT_STATUS_OK;
2737 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2738 TALLOC_CTX *ctx = talloc_tos();
2739 struct dptr_struct *dirptr;
2740 struct smbd_server_connection *sconn = req->sconn;
2741 bool backup_priv = false;
2743 if (total_params < 13) {
2744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2745 return;
2748 dptr_num = SVAL(params,0);
2749 maxentries = SVAL(params,2);
2750 info_level = SVAL(params,4);
2751 resume_key = IVAL(params,6);
2752 findnext_flags = SVAL(params,10);
2753 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2754 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2755 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2756 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2758 if (!continue_bit) {
2759 /* We only need resume_name if continue_bit is zero. */
2760 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2761 params+12,
2762 total_params - 12, STR_TERMINATE, &ntstatus,
2763 &mask_contains_wcard);
2764 if (!NT_STATUS_IS_OK(ntstatus)) {
2765 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2766 complain (it thinks we're asking for the directory above the shared
2767 path or an invalid name). Catch this as the resume name is only compared, never used in
2768 a file access. JRA. */
2769 srvstr_pull_talloc(ctx, params, req->flags2,
2770 &resume_name, params+12,
2771 total_params - 12,
2772 STR_TERMINATE);
2774 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2775 reply_nterror(req, ntstatus);
2776 return;
2781 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2782 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2783 resume_key = %d resume name = %s continue=%d level = %d\n",
2784 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2785 requires_resume_key, resume_key,
2786 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2788 if (!maxentries) {
2789 /* W2K3 seems to treat zero as 1. */
2790 maxentries = 1;
2793 switch (info_level) {
2794 case SMB_FIND_INFO_STANDARD:
2795 case SMB_FIND_EA_SIZE:
2796 case SMB_FIND_EA_LIST:
2797 case SMB_FIND_FILE_DIRECTORY_INFO:
2798 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2799 case SMB_FIND_FILE_NAMES_INFO:
2800 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2801 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2802 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2803 break;
2804 case SMB_FIND_FILE_UNIX:
2805 case SMB_FIND_FILE_UNIX_INFO2:
2806 /* Always use filesystem for UNIX mtime query. */
2807 ask_sharemode = false;
2808 if (!lp_unix_extensions()) {
2809 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2810 return;
2812 break;
2813 default:
2814 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2815 return;
2818 if (info_level == SMB_FIND_EA_LIST) {
2819 uint32 ea_size;
2821 if (total_data < 4) {
2822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2823 return;
2826 ea_size = IVAL(pdata,0);
2827 if (ea_size != total_data) {
2828 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2829 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2831 return;
2834 if (!lp_ea_support(SNUM(conn))) {
2835 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2836 return;
2839 /* Pull out the list of names. */
2840 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2841 if (!ea_list) {
2842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2843 return;
2847 *ppdata = (char *)SMB_REALLOC(
2848 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2849 if(*ppdata == NULL) {
2850 reply_nterror(req, NT_STATUS_NO_MEMORY);
2851 return;
2854 pdata = *ppdata;
2855 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2857 /* Realloc the params space */
2858 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2859 if(*pparams == NULL ) {
2860 reply_nterror(req, NT_STATUS_NO_MEMORY);
2861 return;
2864 params = *pparams;
2866 /* Check that the dptr is valid */
2867 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2868 reply_nterror(req, STATUS_NO_MORE_FILES);
2869 return;
2872 directory = dptr_path(sconn, dptr_num);
2874 /* Get the wildcard mask from the dptr */
2875 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2876 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2877 reply_nterror(req, STATUS_NO_MORE_FILES);
2878 return;
2881 /* Get the attr mask from the dptr */
2882 dirtype = dptr_attr(sconn, dptr_num);
2884 backup_priv = dptr_get_priv(dirptr);
2886 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2887 "backup_priv = %d\n",
2888 dptr_num, mask, dirtype,
2889 (long)dirptr,
2890 dptr_TellDir(dirptr),
2891 (int)backup_priv));
2893 /* Initialize per TRANS2_FIND_NEXT operation data */
2894 dptr_init_search_op(dirptr);
2896 /* We don't need to check for VOL here as this is returned by
2897 a different TRANS2 call. */
2899 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2900 directory,lp_dontdescend(ctx, SNUM(conn))));
2901 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2902 dont_descend = True;
2904 p = pdata;
2905 space_remaining = max_data_bytes;
2906 out_of_space = False;
2908 if (backup_priv) {
2909 become_root();
2913 * Seek to the correct position. We no longer use the resume key but
2914 * depend on the last file name instead.
2917 if(!continue_bit && resume_name && *resume_name) {
2918 SMB_STRUCT_STAT st;
2920 long current_pos = 0;
2922 * Remember, name_to_8_3 is called by
2923 * get_lanman2_dir_entry(), so the resume name
2924 * could be mangled. Ensure we check the unmangled name.
2927 if (mangle_is_mangled(resume_name, conn->params)) {
2928 char *new_resume_name = NULL;
2929 mangle_lookup_name_from_8_3(ctx,
2930 resume_name,
2931 &new_resume_name,
2932 conn->params);
2933 if (new_resume_name) {
2934 resume_name = new_resume_name;
2939 * Fix for NT redirector problem triggered by resume key indexes
2940 * changing between directory scans. We now return a resume key of 0
2941 * and instead look for the filename to continue from (also given
2942 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2943 * findfirst/findnext (as is usual) then the directory pointer
2944 * should already be at the correct place.
2947 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2948 } /* end if resume_name && !continue_bit */
2950 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2951 bool got_exact_match = False;
2953 /* this is a heuristic to avoid seeking the dirptr except when
2954 absolutely necessary. It allows for a filename of about 40 chars */
2955 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2956 out_of_space = True;
2957 finished = False;
2958 } else {
2959 finished = !get_lanman2_dir_entry(ctx,
2960 conn,
2961 dirptr,
2962 req->flags2,
2963 mask,dirtype,info_level,
2964 requires_resume_key,dont_descend,
2965 ask_sharemode,
2966 &p,pdata,data_end,
2967 space_remaining, &out_of_space,
2968 &got_exact_match,
2969 &last_entry_off, ea_list);
2972 if (finished && out_of_space)
2973 finished = False;
2975 if (!finished && !out_of_space)
2976 numentries++;
2979 * As an optimisation if we know we aren't looking
2980 * for a wildcard name (ie. the name matches the wildcard exactly)
2981 * then we can finish on any (first) match.
2982 * This speeds up large directory searches. JRA.
2985 if(got_exact_match)
2986 finished = True;
2988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2991 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2992 smb_fn_name(req->cmd),
2993 mask, directory, dirtype, numentries ) );
2995 /* Check if we can close the dirptr */
2996 if(close_after_request || (finished && close_if_end)) {
2997 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2998 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3001 if (backup_priv) {
3002 unbecome_root();
3005 /* Set up the return parameter block */
3006 SSVAL(params,0,numentries);
3007 SSVAL(params,2,finished);
3008 SSVAL(params,4,0); /* Never an EA error */
3009 SSVAL(params,6,last_entry_off);
3011 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3012 max_data_bytes);
3014 return;
3017 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3019 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3020 return objid;
3023 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3025 SMB_ASSERT(extended_info != NULL);
3027 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3028 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3029 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3030 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3031 #ifdef SAMBA_VERSION_REVISION
3032 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3033 #endif
3034 extended_info->samba_subversion = 0;
3035 #ifdef SAMBA_VERSION_RC_RELEASE
3036 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3037 #else
3038 #ifdef SAMBA_VERSION_PRE_RELEASE
3039 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3040 #endif
3041 #endif
3042 #ifdef SAMBA_VERSION_VENDOR_PATCH
3043 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3044 #endif
3045 extended_info->samba_gitcommitdate = 0;
3046 #ifdef SAMBA_VERSION_COMMIT_TIME
3047 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3048 #endif
3050 memset(extended_info->samba_version_string, 0,
3051 sizeof(extended_info->samba_version_string));
3053 snprintf (extended_info->samba_version_string,
3054 sizeof(extended_info->samba_version_string),
3055 "%s", samba_version_string());
3058 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3059 TALLOC_CTX *mem_ctx,
3060 uint16_t info_level,
3061 uint16_t flags2,
3062 unsigned int max_data_bytes,
3063 struct smb_filename *fname,
3064 char **ppdata,
3065 int *ret_data_len)
3067 char *pdata, *end_data;
3068 int data_len = 0, len;
3069 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3070 int snum = SNUM(conn);
3071 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3072 char *filename = NULL;
3073 uint32 additional_flags = 0;
3074 struct smb_filename smb_fname;
3075 SMB_STRUCT_STAT st;
3077 if (fname == NULL || fname->base_name == NULL) {
3078 filename = ".";
3079 } else {
3080 filename = fname->base_name;
3083 if (IS_IPC(conn)) {
3084 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3085 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3086 "info level (0x%x) on IPC$.\n",
3087 (unsigned int)info_level));
3088 return NT_STATUS_ACCESS_DENIED;
3092 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3094 ZERO_STRUCT(smb_fname);
3095 smb_fname.base_name = discard_const_p(char, filename);
3097 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3098 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3099 return map_nt_error_from_unix(errno);
3102 st = smb_fname.st;
3104 *ppdata = (char *)SMB_REALLOC(
3105 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3106 if (*ppdata == NULL) {
3107 return NT_STATUS_NO_MEMORY;
3110 pdata = *ppdata;
3111 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3112 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3114 switch (info_level) {
3115 case SMB_INFO_ALLOCATION:
3117 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3118 data_len = 18;
3119 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3120 return map_nt_error_from_unix(errno);
3123 block_size = lp_block_size(snum);
3124 if (bsize < block_size) {
3125 uint64_t factor = block_size/bsize;
3126 bsize = block_size;
3127 dsize /= factor;
3128 dfree /= factor;
3130 if (bsize > block_size) {
3131 uint64_t factor = bsize/block_size;
3132 bsize = block_size;
3133 dsize *= factor;
3134 dfree *= factor;
3136 bytes_per_sector = 512;
3137 sectors_per_unit = bsize/bytes_per_sector;
3139 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3140 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3141 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3143 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3144 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3145 SIVAL(pdata,l1_cUnit,dsize);
3146 SIVAL(pdata,l1_cUnitAvail,dfree);
3147 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3148 break;
3151 case SMB_INFO_VOLUME:
3152 /* Return volume name */
3154 * Add volume serial number - hash of a combination of
3155 * the called hostname and the service name.
3157 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3159 * Win2k3 and previous mess this up by sending a name length
3160 * one byte short. I believe only older clients (OS/2 Win9x) use
3161 * this call so try fixing this by adding a terminating null to
3162 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3164 len = srvstr_push(
3165 pdata, flags2,
3166 pdata+l2_vol_szVolLabel, vname,
3167 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3168 STR_NOALIGN|STR_TERMINATE);
3169 SCVAL(pdata,l2_vol_cch,len);
3170 data_len = l2_vol_szVolLabel + len;
3171 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3172 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3173 len, vname));
3174 break;
3176 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3177 case SMB_FS_ATTRIBUTE_INFORMATION:
3179 additional_flags = 0;
3180 #if defined(HAVE_SYS_QUOTAS)
3181 additional_flags |= FILE_VOLUME_QUOTAS;
3182 #endif
3184 if(lp_nt_acl_support(SNUM(conn))) {
3185 additional_flags |= FILE_PERSISTENT_ACLS;
3188 /* Capabilities are filled in at connection time through STATVFS call */
3189 additional_flags |= conn->fs_capabilities;
3190 additional_flags |= lp_parm_int(conn->params->service,
3191 "share", "fake_fscaps",
3194 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3195 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3196 additional_flags); /* FS ATTRIBUTES */
3198 SIVAL(pdata,4,255); /* Max filename component length */
3199 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3200 and will think we can't do long filenames */
3201 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3202 PTR_DIFF(end_data, pdata+12),
3203 STR_UNICODE);
3204 SIVAL(pdata,8,len);
3205 data_len = 12 + len;
3206 break;
3208 case SMB_QUERY_FS_LABEL_INFO:
3209 case SMB_FS_LABEL_INFORMATION:
3210 len = srvstr_push(pdata, flags2, pdata+4, vname,
3211 PTR_DIFF(end_data, pdata+4), 0);
3212 data_len = 4 + len;
3213 SIVAL(pdata,0,len);
3214 break;
3216 case SMB_QUERY_FS_VOLUME_INFO:
3217 case SMB_FS_VOLUME_INFORMATION:
3220 * Add volume serial number - hash of a combination of
3221 * the called hostname and the service name.
3223 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3224 (str_checksum(get_local_machine_name())<<16));
3226 /* Max label len is 32 characters. */
3227 len = srvstr_push(pdata, flags2, pdata+18, vname,
3228 PTR_DIFF(end_data, pdata+18),
3229 STR_UNICODE);
3230 SIVAL(pdata,12,len);
3231 data_len = 18+len;
3233 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3234 (int)strlen(vname),vname,
3235 lp_servicename(talloc_tos(), snum)));
3236 break;
3238 case SMB_QUERY_FS_SIZE_INFO:
3239 case SMB_FS_SIZE_INFORMATION:
3241 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3242 data_len = 24;
3243 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3244 return map_nt_error_from_unix(errno);
3246 block_size = lp_block_size(snum);
3247 if (bsize < block_size) {
3248 uint64_t factor = block_size/bsize;
3249 bsize = block_size;
3250 dsize /= factor;
3251 dfree /= factor;
3253 if (bsize > block_size) {
3254 uint64_t factor = bsize/block_size;
3255 bsize = block_size;
3256 dsize *= factor;
3257 dfree *= factor;
3259 bytes_per_sector = 512;
3260 sectors_per_unit = bsize/bytes_per_sector;
3261 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3262 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3263 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3264 SBIG_UINT(pdata,0,dsize);
3265 SBIG_UINT(pdata,8,dfree);
3266 SIVAL(pdata,16,sectors_per_unit);
3267 SIVAL(pdata,20,bytes_per_sector);
3268 break;
3271 case SMB_FS_FULL_SIZE_INFORMATION:
3273 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3274 data_len = 32;
3275 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3276 return map_nt_error_from_unix(errno);
3278 block_size = lp_block_size(snum);
3279 if (bsize < block_size) {
3280 uint64_t factor = block_size/bsize;
3281 bsize = block_size;
3282 dsize /= factor;
3283 dfree /= factor;
3285 if (bsize > block_size) {
3286 uint64_t factor = bsize/block_size;
3287 bsize = block_size;
3288 dsize *= factor;
3289 dfree *= factor;
3291 bytes_per_sector = 512;
3292 sectors_per_unit = bsize/bytes_per_sector;
3293 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3294 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3295 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3296 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3297 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3298 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3299 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3300 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3301 break;
3304 case SMB_QUERY_FS_DEVICE_INFO:
3305 case SMB_FS_DEVICE_INFORMATION:
3307 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3309 if (!CAN_WRITE(conn)) {
3310 characteristics |= FILE_READ_ONLY_DEVICE;
3312 data_len = 8;
3313 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3314 SIVAL(pdata,4,characteristics);
3315 break;
3318 #ifdef HAVE_SYS_QUOTAS
3319 case SMB_FS_QUOTA_INFORMATION:
3321 * what we have to send --metze:
3323 * Unknown1: 24 NULL bytes
3324 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3325 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3326 * Quota Flags: 2 byte :
3327 * Unknown3: 6 NULL bytes
3329 * 48 bytes total
3331 * details for Quota Flags:
3333 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3334 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3335 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3336 * 0x0001 Enable Quotas: enable quota for this fs
3340 /* we need to fake up a fsp here,
3341 * because its not send in this call
3343 files_struct fsp;
3344 SMB_NTQUOTA_STRUCT quotas;
3346 ZERO_STRUCT(fsp);
3347 ZERO_STRUCT(quotas);
3349 fsp.conn = conn;
3350 fsp.fnum = FNUM_FIELD_INVALID;
3352 /* access check */
3353 if (get_current_uid(conn) != 0) {
3354 DEBUG(0,("set_user_quota: access_denied "
3355 "service [%s] user [%s]\n",
3356 lp_servicename(talloc_tos(), SNUM(conn)),
3357 conn->session_info->unix_info->unix_name));
3358 return NT_STATUS_ACCESS_DENIED;
3361 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3362 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3363 return map_nt_error_from_unix(errno);
3366 data_len = 48;
3368 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3369 lp_servicename(talloc_tos(), SNUM(conn))));
3371 /* Unknown1 24 NULL bytes*/
3372 SBIG_UINT(pdata,0,(uint64_t)0);
3373 SBIG_UINT(pdata,8,(uint64_t)0);
3374 SBIG_UINT(pdata,16,(uint64_t)0);
3376 /* Default Soft Quota 8 bytes */
3377 SBIG_UINT(pdata,24,quotas.softlim);
3379 /* Default Hard Quota 8 bytes */
3380 SBIG_UINT(pdata,32,quotas.hardlim);
3382 /* Quota flag 2 bytes */
3383 SSVAL(pdata,40,quotas.qflags);
3385 /* Unknown3 6 NULL bytes */
3386 SSVAL(pdata,42,0);
3387 SIVAL(pdata,44,0);
3389 break;
3391 #endif /* HAVE_SYS_QUOTAS */
3392 case SMB_FS_OBJECTID_INFORMATION:
3394 unsigned char objid[16];
3395 struct smb_extended_info extended_info;
3396 memcpy(pdata,create_volume_objectid(conn, objid),16);
3397 samba_extended_info_version (&extended_info);
3398 SIVAL(pdata,16,extended_info.samba_magic);
3399 SIVAL(pdata,20,extended_info.samba_version);
3400 SIVAL(pdata,24,extended_info.samba_subversion);
3401 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3402 memcpy(pdata+36,extended_info.samba_version_string,28);
3403 data_len = 64;
3404 break;
3408 * Query the version and capabilities of the CIFS UNIX extensions
3409 * in use.
3412 case SMB_QUERY_CIFS_UNIX_INFO:
3414 bool large_write = lp_min_receive_file_size() &&
3415 !srv_is_signing_active(conn->sconn);
3416 bool large_read = !srv_is_signing_active(conn->sconn);
3417 int encrypt_caps = 0;
3419 if (!lp_unix_extensions()) {
3420 return NT_STATUS_INVALID_LEVEL;
3423 switch (conn->encrypt_level) {
3424 case SMB_SIGNING_OFF:
3425 encrypt_caps = 0;
3426 break;
3427 case SMB_SIGNING_IF_REQUIRED:
3428 case SMB_SIGNING_DEFAULT:
3429 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3430 break;
3431 case SMB_SIGNING_REQUIRED:
3432 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3433 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3434 large_write = false;
3435 large_read = false;
3436 break;
3439 data_len = 12;
3440 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3441 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3443 /* We have POSIX ACLs, pathname, encryption,
3444 * large read/write, and locking capability. */
3446 SBIG_UINT(pdata,4,((uint64_t)(
3447 CIFS_UNIX_POSIX_ACLS_CAP|
3448 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3449 CIFS_UNIX_FCNTL_LOCKS_CAP|
3450 CIFS_UNIX_EXTATTR_CAP|
3451 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3452 encrypt_caps|
3453 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3454 (large_write ?
3455 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3456 break;
3459 case SMB_QUERY_POSIX_FS_INFO:
3461 int rc;
3462 vfs_statvfs_struct svfs;
3464 if (!lp_unix_extensions()) {
3465 return NT_STATUS_INVALID_LEVEL;
3468 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3470 if (!rc) {
3471 data_len = 56;
3472 SIVAL(pdata,0,svfs.OptimalTransferSize);
3473 SIVAL(pdata,4,svfs.BlockSize);
3474 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3475 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3476 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3477 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3478 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3479 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3480 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3481 #ifdef EOPNOTSUPP
3482 } else if (rc == EOPNOTSUPP) {
3483 return NT_STATUS_INVALID_LEVEL;
3484 #endif /* EOPNOTSUPP */
3485 } else {
3486 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3487 return NT_STATUS_DOS(ERRSRV, ERRerror);
3489 break;
3492 case SMB_QUERY_POSIX_WHOAMI:
3494 uint32_t flags = 0;
3495 uint32_t sid_bytes;
3496 int i;
3498 if (!lp_unix_extensions()) {
3499 return NT_STATUS_INVALID_LEVEL;
3502 if (max_data_bytes < 40) {
3503 return NT_STATUS_BUFFER_TOO_SMALL;
3506 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3507 flags |= SMB_WHOAMI_GUEST;
3510 /* NOTE: 8 bytes for UID/GID, irrespective of native
3511 * platform size. This matches
3512 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3514 data_len = 4 /* flags */
3515 + 4 /* flag mask */
3516 + 8 /* uid */
3517 + 8 /* gid */
3518 + 4 /* ngroups */
3519 + 4 /* num_sids */
3520 + 4 /* SID bytes */
3521 + 4 /* pad/reserved */
3522 + (conn->session_info->unix_token->ngroups * 8)
3523 /* groups list */
3524 + (conn->session_info->security_token->num_sids *
3525 SID_MAX_SIZE)
3526 /* SID list */;
3528 SIVAL(pdata, 0, flags);
3529 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3530 SBIG_UINT(pdata, 8,
3531 (uint64_t)conn->session_info->unix_token->uid);
3532 SBIG_UINT(pdata, 16,
3533 (uint64_t)conn->session_info->unix_token->gid);
3536 if (data_len >= max_data_bytes) {
3537 /* Potential overflow, skip the GIDs and SIDs. */
3539 SIVAL(pdata, 24, 0); /* num_groups */
3540 SIVAL(pdata, 28, 0); /* num_sids */
3541 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3542 SIVAL(pdata, 36, 0); /* reserved */
3544 data_len = 40;
3545 break;
3548 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3549 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3551 /* We walk the SID list twice, but this call is fairly
3552 * infrequent, and I don't expect that it's performance
3553 * sensitive -- jpeach
3555 for (i = 0, sid_bytes = 0;
3556 i < conn->session_info->security_token->num_sids; ++i) {
3557 sid_bytes += ndr_size_dom_sid(
3558 &conn->session_info->security_token->sids[i],
3562 /* SID list byte count */
3563 SIVAL(pdata, 32, sid_bytes);
3565 /* 4 bytes pad/reserved - must be zero */
3566 SIVAL(pdata, 36, 0);
3567 data_len = 40;
3569 /* GID list */
3570 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3571 SBIG_UINT(pdata, data_len,
3572 (uint64_t)conn->session_info->unix_token->groups[i]);
3573 data_len += 8;
3576 /* SID list */
3577 for (i = 0;
3578 i < conn->session_info->security_token->num_sids; ++i) {
3579 int sid_len = ndr_size_dom_sid(
3580 &conn->session_info->security_token->sids[i],
3583 sid_linearize(pdata + data_len, sid_len,
3584 &conn->session_info->security_token->sids[i]);
3585 data_len += sid_len;
3588 break;
3591 case SMB_MAC_QUERY_FS_INFO:
3593 * Thursby MAC extension... ONLY on NTFS filesystems
3594 * once we do streams then we don't need this
3596 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3597 data_len = 88;
3598 SIVAL(pdata,84,0x100); /* Don't support mac... */
3599 break;
3601 /* drop through */
3602 default:
3603 return NT_STATUS_INVALID_LEVEL;
3606 *ret_data_len = data_len;
3607 return NT_STATUS_OK;
3610 /****************************************************************************
3611 Reply to a TRANS2_QFSINFO (query filesystem info).
3612 ****************************************************************************/
3614 static void call_trans2qfsinfo(connection_struct *conn,
3615 struct smb_request *req,
3616 char **pparams, int total_params,
3617 char **ppdata, int total_data,
3618 unsigned int max_data_bytes)
3620 char *params = *pparams;
3621 uint16_t info_level;
3622 int data_len = 0;
3623 NTSTATUS status;
3625 if (total_params < 2) {
3626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3627 return;
3630 info_level = SVAL(params,0);
3632 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3633 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3634 DEBUG(0,("call_trans2qfsinfo: encryption required "
3635 "and info level 0x%x sent.\n",
3636 (unsigned int)info_level));
3637 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3638 return;
3642 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3644 status = smbd_do_qfsinfo(conn, req,
3645 info_level,
3646 req->flags2,
3647 max_data_bytes,
3648 NULL,
3649 ppdata, &data_len);
3650 if (!NT_STATUS_IS_OK(status)) {
3651 reply_nterror(req, status);
3652 return;
3655 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3656 max_data_bytes);
3658 DEBUG( 4, ( "%s info_level = %d\n",
3659 smb_fn_name(req->cmd), info_level) );
3661 return;
3664 /****************************************************************************
3665 Reply to a TRANS2_SETFSINFO (set filesystem info).
3666 ****************************************************************************/
3668 static void call_trans2setfsinfo(connection_struct *conn,
3669 struct smb_request *req,
3670 char **pparams, int total_params,
3671 char **ppdata, int total_data,
3672 unsigned int max_data_bytes)
3674 struct smbd_server_connection *sconn = req->sconn;
3675 char *pdata = *ppdata;
3676 char *params = *pparams;
3677 uint16 info_level;
3679 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3680 lp_servicename(talloc_tos(), SNUM(conn))));
3682 /* */
3683 if (total_params < 4) {
3684 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3685 total_params));
3686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3687 return;
3690 info_level = SVAL(params,2);
3692 if (IS_IPC(conn)) {
3693 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3694 info_level != SMB_SET_CIFS_UNIX_INFO) {
3695 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3696 "info level (0x%x) on IPC$.\n",
3697 (unsigned int)info_level));
3698 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3699 return;
3703 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3704 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3705 DEBUG(0,("call_trans2setfsinfo: encryption required "
3706 "and info level 0x%x sent.\n",
3707 (unsigned int)info_level));
3708 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3709 return;
3713 switch(info_level) {
3714 case SMB_SET_CIFS_UNIX_INFO:
3715 if (!lp_unix_extensions()) {
3716 DEBUG(2,("call_trans2setfsinfo: "
3717 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3718 "unix extensions off\n"));
3719 reply_nterror(req,
3720 NT_STATUS_INVALID_LEVEL);
3721 return;
3724 /* There should be 12 bytes of capabilities set. */
3725 if (total_data < 12) {
3726 reply_nterror(
3727 req,
3728 NT_STATUS_INVALID_PARAMETER);
3729 return;
3731 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3732 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3733 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3734 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3735 /* Just print these values for now. */
3736 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3737 "major = %u, minor = %u cap_low = 0x%x, "
3738 "cap_high = 0x%xn",
3739 (unsigned int)sconn->
3740 smb1.unix_info.client_major,
3741 (unsigned int)sconn->
3742 smb1.unix_info.client_minor,
3743 (unsigned int)sconn->
3744 smb1.unix_info.client_cap_low,
3745 (unsigned int)sconn->
3746 smb1.unix_info.client_cap_high));
3748 /* Here is where we must switch to posix pathname processing... */
3749 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3750 lp_set_posix_pathnames();
3751 mangle_change_to_posix();
3754 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3755 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3756 /* Client that knows how to do posix locks,
3757 * but not posix open/mkdir operations. Set a
3758 * default type for read/write checks. */
3760 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3763 break;
3765 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3767 NTSTATUS status;
3768 size_t param_len = 0;
3769 size_t data_len = total_data;
3771 if (!lp_unix_extensions()) {
3772 reply_nterror(
3773 req,
3774 NT_STATUS_INVALID_LEVEL);
3775 return;
3778 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3779 reply_nterror(
3780 req,
3781 NT_STATUS_NOT_SUPPORTED);
3782 return;
3785 if (req->sconn->smb1.echo_handler.trusted_fde) {
3786 DEBUG( 2,("call_trans2setfsinfo: "
3787 "request transport encryption disabled"
3788 "with 'fork echo handler = yes'\n"));
3789 reply_nterror(
3790 req,
3791 NT_STATUS_NOT_SUPPORTED);
3792 return;
3795 DEBUG( 4,("call_trans2setfsinfo: "
3796 "request transport encryption.\n"));
3798 status = srv_request_encryption_setup(conn,
3799 (unsigned char **)ppdata,
3800 &data_len,
3801 (unsigned char **)pparams,
3802 &param_len);
3804 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3805 !NT_STATUS_IS_OK(status)) {
3806 reply_nterror(req, status);
3807 return;
3810 send_trans2_replies(conn, req,
3811 *pparams,
3812 param_len,
3813 *ppdata,
3814 data_len,
3815 max_data_bytes);
3817 if (NT_STATUS_IS_OK(status)) {
3818 /* Server-side transport
3819 * encryption is now *on*. */
3820 status = srv_encryption_start(conn);
3821 if (!NT_STATUS_IS_OK(status)) {
3822 char *reason = talloc_asprintf(talloc_tos(),
3823 "Failure in setting "
3824 "up encrypted transport: %s",
3825 nt_errstr(status));
3826 exit_server_cleanly(reason);
3829 return;
3832 case SMB_FS_QUOTA_INFORMATION:
3834 files_struct *fsp = NULL;
3835 SMB_NTQUOTA_STRUCT quotas;
3837 ZERO_STRUCT(quotas);
3839 /* access check */
3840 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3841 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3842 lp_servicename(talloc_tos(), SNUM(conn)),
3843 conn->session_info->unix_info->unix_name));
3844 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3845 return;
3848 /* note: normaly there're 48 bytes,
3849 * but we didn't use the last 6 bytes for now
3850 * --metze
3852 fsp = file_fsp(req, SVAL(params,0));
3854 if (!check_fsp_ntquota_handle(conn, req,
3855 fsp)) {
3856 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3857 reply_nterror(
3858 req, NT_STATUS_INVALID_HANDLE);
3859 return;
3862 if (total_data < 42) {
3863 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3864 total_data));
3865 reply_nterror(
3866 req,
3867 NT_STATUS_INVALID_PARAMETER);
3868 return;
3871 /* unknown_1 24 NULL bytes in pdata*/
3873 /* the soft quotas 8 bytes (uint64_t)*/
3874 quotas.softlim = BVAL(pdata,24);
3876 /* the hard quotas 8 bytes (uint64_t)*/
3877 quotas.hardlim = BVAL(pdata,32);
3879 /* quota_flags 2 bytes **/
3880 quotas.qflags = SVAL(pdata,40);
3882 /* unknown_2 6 NULL bytes follow*/
3884 /* now set the quotas */
3885 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3886 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3887 reply_nterror(req, map_nt_error_from_unix(errno));
3888 return;
3891 break;
3893 default:
3894 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3895 info_level));
3896 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3897 return;
3898 break;
3902 * sending this reply works fine,
3903 * but I'm not sure it's the same
3904 * like windows do...
3905 * --metze
3907 reply_outbuf(req, 10, 0);
3910 #if defined(HAVE_POSIX_ACLS)
3911 /****************************************************************************
3912 Utility function to count the number of entries in a POSIX acl.
3913 ****************************************************************************/
3915 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3917 unsigned int ace_count = 0;
3918 int entry_id = SMB_ACL_FIRST_ENTRY;
3919 SMB_ACL_ENTRY_T entry;
3921 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3922 /* get_next... */
3923 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3924 entry_id = SMB_ACL_NEXT_ENTRY;
3926 ace_count++;
3928 return ace_count;
3931 /****************************************************************************
3932 Utility function to marshall a POSIX acl into wire format.
3933 ****************************************************************************/
3935 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3937 int entry_id = SMB_ACL_FIRST_ENTRY;
3938 SMB_ACL_ENTRY_T entry;
3940 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3941 SMB_ACL_TAG_T tagtype;
3942 SMB_ACL_PERMSET_T permset;
3943 unsigned char perms = 0;
3944 unsigned int own_grp;
3946 /* get_next... */
3947 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3948 entry_id = SMB_ACL_NEXT_ENTRY;
3951 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3952 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3953 return False;
3956 if (sys_acl_get_permset(entry, &permset) == -1) {
3957 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3958 return False;
3961 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3962 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3963 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3965 SCVAL(pdata,1,perms);
3967 switch (tagtype) {
3968 case SMB_ACL_USER_OBJ:
3969 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3970 own_grp = (unsigned int)pst->st_ex_uid;
3971 SIVAL(pdata,2,own_grp);
3972 SIVAL(pdata,6,0);
3973 break;
3974 case SMB_ACL_USER:
3976 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3977 if (!puid) {
3978 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3979 return False;
3981 own_grp = (unsigned int)*puid;
3982 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3983 SIVAL(pdata,2,own_grp);
3984 SIVAL(pdata,6,0);
3985 break;
3987 case SMB_ACL_GROUP_OBJ:
3988 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3989 own_grp = (unsigned int)pst->st_ex_gid;
3990 SIVAL(pdata,2,own_grp);
3991 SIVAL(pdata,6,0);
3992 break;
3993 case SMB_ACL_GROUP:
3995 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3996 if (!pgid) {
3997 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3998 return False;
4000 own_grp = (unsigned int)*pgid;
4001 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4002 SIVAL(pdata,2,own_grp);
4003 SIVAL(pdata,6,0);
4004 break;
4006 case SMB_ACL_MASK:
4007 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4008 SIVAL(pdata,2,0xFFFFFFFF);
4009 SIVAL(pdata,6,0xFFFFFFFF);
4010 break;
4011 case SMB_ACL_OTHER:
4012 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4013 SIVAL(pdata,2,0xFFFFFFFF);
4014 SIVAL(pdata,6,0xFFFFFFFF);
4015 break;
4016 default:
4017 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4018 return False;
4020 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4023 return True;
4025 #endif
4027 /****************************************************************************
4028 Store the FILE_UNIX_BASIC info.
4029 ****************************************************************************/
4031 static char *store_file_unix_basic(connection_struct *conn,
4032 char *pdata,
4033 files_struct *fsp,
4034 const SMB_STRUCT_STAT *psbuf)
4036 uint64_t file_index = get_FileIndex(conn, psbuf);
4037 dev_t devno;
4039 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4040 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4042 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4043 pdata += 8;
4045 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4046 pdata += 8;
4048 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4050 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4051 pdata += 24;
4053 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4054 SIVAL(pdata,4,0);
4055 pdata += 8;
4057 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4058 SIVAL(pdata,4,0);
4059 pdata += 8;
4061 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4062 pdata += 4;
4064 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4065 devno = psbuf->st_ex_rdev;
4066 } else {
4067 devno = psbuf->st_ex_dev;
4070 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4071 SIVAL(pdata,4,0);
4072 pdata += 8;
4074 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4075 SIVAL(pdata,4,0);
4076 pdata += 8;
4078 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4079 pdata += 8;
4081 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4082 SIVAL(pdata,4,0);
4083 pdata += 8;
4085 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4086 SIVAL(pdata,4,0);
4087 pdata += 8;
4089 return pdata;
4092 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4093 * the chflags(2) (or equivalent) flags.
4095 * XXX: this really should be behind the VFS interface. To do this, we would
4096 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4097 * Each VFS module could then implement its own mapping as appropriate for the
4098 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4100 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4101 info2_flags_map[] =
4103 #ifdef UF_NODUMP
4104 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4105 #endif
4107 #ifdef UF_IMMUTABLE
4108 { UF_IMMUTABLE, EXT_IMMUTABLE },
4109 #endif
4111 #ifdef UF_APPEND
4112 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4113 #endif
4115 #ifdef UF_HIDDEN
4116 { UF_HIDDEN, EXT_HIDDEN },
4117 #endif
4119 /* Do not remove. We need to guarantee that this array has at least one
4120 * entry to build on HP-UX.
4122 { 0, 0 }
4126 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4127 uint32 *smb_fflags, uint32 *smb_fmask)
4129 int i;
4131 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4132 *smb_fmask |= info2_flags_map[i].smb_fflag;
4133 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4134 *smb_fflags |= info2_flags_map[i].smb_fflag;
4139 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4140 const uint32 smb_fflags,
4141 const uint32 smb_fmask,
4142 int *stat_fflags)
4144 uint32 max_fmask = 0;
4145 int i;
4147 *stat_fflags = psbuf->st_ex_flags;
4149 /* For each flags requested in smb_fmask, check the state of the
4150 * corresponding flag in smb_fflags and set or clear the matching
4151 * stat flag.
4154 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4155 max_fmask |= info2_flags_map[i].smb_fflag;
4156 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4157 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4158 *stat_fflags |= info2_flags_map[i].stat_fflag;
4159 } else {
4160 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4165 /* If smb_fmask is asking to set any bits that are not supported by
4166 * our flag mappings, we should fail.
4168 if ((smb_fmask & max_fmask) != smb_fmask) {
4169 return False;
4172 return True;
4176 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4177 * of file flags and birth (create) time.
4179 static char *store_file_unix_basic_info2(connection_struct *conn,
4180 char *pdata,
4181 files_struct *fsp,
4182 const SMB_STRUCT_STAT *psbuf)
4184 uint32 file_flags = 0;
4185 uint32 flags_mask = 0;
4187 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4189 /* Create (birth) time 64 bit */
4190 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4191 pdata += 8;
4193 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4194 SIVAL(pdata, 0, file_flags); /* flags */
4195 SIVAL(pdata, 4, flags_mask); /* mask */
4196 pdata += 8;
4198 return pdata;
4201 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4202 const struct stream_struct *streams,
4203 char *data,
4204 unsigned int max_data_bytes,
4205 unsigned int *data_size)
4207 unsigned int i;
4208 unsigned int ofs = 0;
4210 for (i = 0; i < num_streams; i++) {
4211 unsigned int next_offset;
4212 size_t namelen;
4213 smb_ucs2_t *namebuf;
4215 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4216 streams[i].name, &namelen) ||
4217 namelen <= 2)
4219 return NT_STATUS_INVALID_PARAMETER;
4223 * name_buf is now null-terminated, we need to marshall as not
4224 * terminated
4227 namelen -= 2;
4230 * We cannot overflow ...
4232 if ((ofs + 24 + namelen) > max_data_bytes) {
4233 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4234 i));
4235 TALLOC_FREE(namebuf);
4236 return STATUS_BUFFER_OVERFLOW;
4239 SIVAL(data, ofs+4, namelen);
4240 SOFF_T(data, ofs+8, streams[i].size);
4241 SOFF_T(data, ofs+16, streams[i].alloc_size);
4242 memcpy(data+ofs+24, namebuf, namelen);
4243 TALLOC_FREE(namebuf);
4245 next_offset = ofs + 24 + namelen;
4247 if (i == num_streams-1) {
4248 SIVAL(data, ofs, 0);
4250 else {
4251 unsigned int align = ndr_align_size(next_offset, 8);
4253 if ((next_offset + align) > max_data_bytes) {
4254 DEBUG(10, ("refusing to overflow align "
4255 "reply at stream %u\n",
4256 i));
4257 TALLOC_FREE(namebuf);
4258 return STATUS_BUFFER_OVERFLOW;
4261 memset(data+next_offset, 0, align);
4262 next_offset += align;
4264 SIVAL(data, ofs, next_offset - ofs);
4265 ofs = next_offset;
4268 ofs = next_offset;
4271 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4273 *data_size = ofs;
4275 return NT_STATUS_OK;
4278 /****************************************************************************
4279 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4280 ****************************************************************************/
4282 static void call_trans2qpipeinfo(connection_struct *conn,
4283 struct smb_request *req,
4284 unsigned int tran_call,
4285 char **pparams, int total_params,
4286 char **ppdata, int total_data,
4287 unsigned int max_data_bytes)
4289 char *params = *pparams;
4290 char *pdata = *ppdata;
4291 unsigned int data_size = 0;
4292 unsigned int param_size = 2;
4293 uint16 info_level;
4294 files_struct *fsp;
4296 if (!params) {
4297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4298 return;
4301 if (total_params < 4) {
4302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4303 return;
4306 fsp = file_fsp(req, SVAL(params,0));
4307 if (!fsp_is_np(fsp)) {
4308 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4309 return;
4312 info_level = SVAL(params,2);
4314 *pparams = (char *)SMB_REALLOC(*pparams,2);
4315 if (*pparams == NULL) {
4316 reply_nterror(req, NT_STATUS_NO_MEMORY);
4317 return;
4319 params = *pparams;
4320 SSVAL(params,0,0);
4321 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4322 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4323 if (*ppdata == NULL ) {
4324 reply_nterror(req, NT_STATUS_NO_MEMORY);
4325 return;
4327 pdata = *ppdata;
4329 switch (info_level) {
4330 case SMB_FILE_STANDARD_INFORMATION:
4331 memset(pdata,0,24);
4332 SOFF_T(pdata,0,4096LL);
4333 SIVAL(pdata,16,1);
4334 SIVAL(pdata,20,1);
4335 data_size = 24;
4336 break;
4338 default:
4339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4340 return;
4343 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4344 max_data_bytes);
4346 return;
4349 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4350 TALLOC_CTX *mem_ctx,
4351 uint16_t info_level,
4352 files_struct *fsp,
4353 struct smb_filename *smb_fname,
4354 bool delete_pending,
4355 struct timespec write_time_ts,
4356 struct ea_list *ea_list,
4357 int lock_data_count,
4358 char *lock_data,
4359 uint16_t flags2,
4360 unsigned int max_data_bytes,
4361 char **ppdata,
4362 unsigned int *pdata_size)
4364 char *pdata = *ppdata;
4365 char *dstart, *dend;
4366 unsigned int data_size;
4367 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4368 time_t create_time, mtime, atime, c_time;
4369 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4370 char *p;
4371 char *base_name;
4372 char *dos_fname;
4373 int mode;
4374 int nlink;
4375 NTSTATUS status;
4376 uint64_t file_size = 0;
4377 uint64_t pos = 0;
4378 uint64_t allocation_size = 0;
4379 uint64_t file_index = 0;
4380 uint32_t access_mask = 0;
4382 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4383 return NT_STATUS_INVALID_LEVEL;
4386 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4387 smb_fname_str_dbg(smb_fname),
4388 fsp_fnum_dbg(fsp),
4389 info_level, max_data_bytes));
4391 mode = dos_mode(conn, smb_fname);
4392 nlink = psbuf->st_ex_nlink;
4394 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4395 nlink = 1;
4398 if ((nlink > 0) && delete_pending) {
4399 nlink -= 1;
4402 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4403 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4404 if (*ppdata == NULL) {
4405 return NT_STATUS_NO_MEMORY;
4407 pdata = *ppdata;
4408 dstart = pdata;
4409 dend = dstart + data_size - 1;
4411 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4412 update_stat_ex_mtime(psbuf, write_time_ts);
4415 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4416 mtime_ts = psbuf->st_ex_mtime;
4417 atime_ts = psbuf->st_ex_atime;
4418 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4420 if (lp_dos_filetime_resolution(SNUM(conn))) {
4421 dos_filetime_timespec(&create_time_ts);
4422 dos_filetime_timespec(&mtime_ts);
4423 dos_filetime_timespec(&atime_ts);
4424 dos_filetime_timespec(&ctime_ts);
4427 create_time = convert_timespec_to_time_t(create_time_ts);
4428 mtime = convert_timespec_to_time_t(mtime_ts);
4429 atime = convert_timespec_to_time_t(atime_ts);
4430 c_time = convert_timespec_to_time_t(ctime_ts);
4432 p = strrchr_m(smb_fname->base_name,'/');
4433 if (!p)
4434 base_name = smb_fname->base_name;
4435 else
4436 base_name = p+1;
4438 /* NT expects the name to be in an exact form of the *full*
4439 filename. See the trans2 torture test */
4440 if (ISDOT(base_name)) {
4441 dos_fname = talloc_strdup(mem_ctx, "\\");
4442 if (!dos_fname) {
4443 return NT_STATUS_NO_MEMORY;
4445 } else {
4446 dos_fname = talloc_asprintf(mem_ctx,
4447 "\\%s",
4448 smb_fname->base_name);
4449 if (!dos_fname) {
4450 return NT_STATUS_NO_MEMORY;
4452 if (is_ntfs_stream_smb_fname(smb_fname)) {
4453 dos_fname = talloc_asprintf(dos_fname, "%s",
4454 smb_fname->stream_name);
4455 if (!dos_fname) {
4456 return NT_STATUS_NO_MEMORY;
4460 string_replace(dos_fname, '/', '\\');
4463 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4465 if (!fsp) {
4466 /* Do we have this path open ? */
4467 files_struct *fsp1;
4468 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4469 fsp1 = file_find_di_first(conn->sconn, fileid);
4470 if (fsp1 && fsp1->initial_allocation_size) {
4471 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4475 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4476 file_size = get_file_size_stat(psbuf);
4479 if (fsp) {
4480 pos = fsp->fh->position_information;
4483 if (fsp) {
4484 access_mask = fsp->access_mask;
4485 } else {
4486 /* GENERIC_EXECUTE mapping from Windows */
4487 access_mask = 0x12019F;
4490 /* This should be an index number - looks like
4491 dev/ino to me :-)
4493 I think this causes us to fail the IFSKIT
4494 BasicFileInformationTest. -tpot */
4495 file_index = get_FileIndex(conn, psbuf);
4497 switch (info_level) {
4498 case SMB_INFO_STANDARD:
4499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4500 data_size = 22;
4501 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4502 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4503 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4504 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4505 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4506 SSVAL(pdata,l1_attrFile,mode);
4507 break;
4509 case SMB_INFO_QUERY_EA_SIZE:
4511 unsigned int ea_size =
4512 estimate_ea_size(conn, fsp,
4513 smb_fname);
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4515 data_size = 26;
4516 srv_put_dos_date2(pdata,0,create_time);
4517 srv_put_dos_date2(pdata,4,atime);
4518 srv_put_dos_date2(pdata,8,mtime); /* write time */
4519 SIVAL(pdata,12,(uint32)file_size);
4520 SIVAL(pdata,16,(uint32)allocation_size);
4521 SSVAL(pdata,20,mode);
4522 SIVAL(pdata,22,ea_size);
4523 break;
4526 case SMB_INFO_IS_NAME_VALID:
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4528 if (fsp) {
4529 /* os/2 needs this ? really ?*/
4530 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4532 /* This is only reached for qpathinfo */
4533 data_size = 0;
4534 break;
4536 case SMB_INFO_QUERY_EAS_FROM_LIST:
4538 size_t total_ea_len = 0;
4539 struct ea_list *ea_file_list = NULL;
4540 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4542 status =
4543 get_ea_list_from_file(mem_ctx, conn, fsp,
4544 smb_fname,
4545 &total_ea_len, &ea_file_list);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 return status;
4550 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4552 if (!ea_list || (total_ea_len > data_size)) {
4553 data_size = 4;
4554 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4555 break;
4558 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4559 break;
4562 case SMB_INFO_QUERY_ALL_EAS:
4564 /* We have data_size bytes to put EA's into. */
4565 size_t total_ea_len = 0;
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4568 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4569 smb_fname,
4570 &total_ea_len, &ea_list);
4571 if (!NT_STATUS_IS_OK(status)) {
4572 return status;
4575 if (!ea_list || (total_ea_len > data_size)) {
4576 data_size = 4;
4577 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4578 break;
4581 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4582 break;
4585 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4587 /* This is FileFullEaInformation - 0xF which maps to
4588 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4590 /* We have data_size bytes to put EA's into. */
4591 size_t total_ea_len = 0;
4592 struct ea_list *ea_file_list = NULL;
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4596 /*TODO: add filtering and index handling */
4598 status =
4599 get_ea_list_from_file(mem_ctx, conn, fsp,
4600 smb_fname,
4601 &total_ea_len, &ea_file_list);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 return status;
4605 if (!ea_file_list) {
4606 return NT_STATUS_NO_EAS_ON_FILE;
4609 status = fill_ea_chained_buffer(mem_ctx,
4610 pdata,
4611 data_size,
4612 &data_size,
4613 conn, ea_file_list);
4614 if (!NT_STATUS_IS_OK(status)) {
4615 return status;
4617 break;
4620 case SMB_FILE_BASIC_INFORMATION:
4621 case SMB_QUERY_FILE_BASIC_INFO:
4623 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4625 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4626 } else {
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4628 data_size = 40;
4629 SIVAL(pdata,36,0);
4631 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4632 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4633 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4634 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4635 SIVAL(pdata,32,mode);
4637 DEBUG(5,("SMB_QFBI - "));
4638 DEBUG(5,("create: %s ", ctime(&create_time)));
4639 DEBUG(5,("access: %s ", ctime(&atime)));
4640 DEBUG(5,("write: %s ", ctime(&mtime)));
4641 DEBUG(5,("change: %s ", ctime(&c_time)));
4642 DEBUG(5,("mode: %x\n", mode));
4643 break;
4645 case SMB_FILE_STANDARD_INFORMATION:
4646 case SMB_QUERY_FILE_STANDARD_INFO:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4649 data_size = 24;
4650 SOFF_T(pdata,0,allocation_size);
4651 SOFF_T(pdata,8,file_size);
4652 SIVAL(pdata,16,nlink);
4653 SCVAL(pdata,20,delete_pending?1:0);
4654 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4655 SSVAL(pdata,22,0); /* Padding. */
4656 break;
4658 case SMB_FILE_EA_INFORMATION:
4659 case SMB_QUERY_FILE_EA_INFO:
4661 unsigned int ea_size =
4662 estimate_ea_size(conn, fsp, smb_fname);
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4664 data_size = 4;
4665 SIVAL(pdata,0,ea_size);
4666 break;
4669 /* Get the 8.3 name - used if NT SMB was negotiated. */
4670 case SMB_QUERY_FILE_ALT_NAME_INFO:
4671 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4673 int len;
4674 char mangled_name[13];
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4676 if (!name_to_8_3(base_name,mangled_name,
4677 True,conn->params)) {
4678 return NT_STATUS_NO_MEMORY;
4680 len = srvstr_push(dstart, flags2,
4681 pdata+4, mangled_name,
4682 PTR_DIFF(dend, pdata+4),
4683 STR_UNICODE);
4684 data_size = 4 + len;
4685 SIVAL(pdata,0,len);
4686 break;
4689 case SMB_QUERY_FILE_NAME_INFO:
4691 int len;
4693 this must be *exactly* right for ACLs on mapped drives to work
4695 len = srvstr_push(dstart, flags2,
4696 pdata+4, dos_fname,
4697 PTR_DIFF(dend, pdata+4),
4698 STR_UNICODE);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4700 data_size = 4 + len;
4701 SIVAL(pdata,0,len);
4702 break;
4705 case SMB_FILE_ALLOCATION_INFORMATION:
4706 case SMB_QUERY_FILE_ALLOCATION_INFO:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4708 data_size = 8;
4709 SOFF_T(pdata,0,allocation_size);
4710 break;
4712 case SMB_FILE_END_OF_FILE_INFORMATION:
4713 case SMB_QUERY_FILE_END_OF_FILEINFO:
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4715 data_size = 8;
4716 SOFF_T(pdata,0,file_size);
4717 break;
4719 case SMB_QUERY_FILE_ALL_INFO:
4720 case SMB_FILE_ALL_INFORMATION:
4722 int len;
4723 unsigned int ea_size =
4724 estimate_ea_size(conn, fsp, smb_fname);
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4726 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4727 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4728 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4729 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4730 SIVAL(pdata,32,mode);
4731 SIVAL(pdata,36,0); /* padding. */
4732 pdata += 40;
4733 SOFF_T(pdata,0,allocation_size);
4734 SOFF_T(pdata,8,file_size);
4735 SIVAL(pdata,16,nlink);
4736 SCVAL(pdata,20,delete_pending);
4737 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4738 SSVAL(pdata,22,0);
4739 pdata += 24;
4740 SIVAL(pdata,0,ea_size);
4741 pdata += 4; /* EA info */
4742 len = srvstr_push(dstart, flags2,
4743 pdata+4, dos_fname,
4744 PTR_DIFF(dend, pdata+4),
4745 STR_UNICODE);
4746 SIVAL(pdata,0,len);
4747 pdata += 4 + len;
4748 data_size = PTR_DIFF(pdata,(*ppdata));
4749 break;
4752 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4754 int len;
4755 unsigned int ea_size =
4756 estimate_ea_size(conn, fsp, smb_fname);
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4758 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4759 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4760 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4761 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4762 SIVAL(pdata, 0x20, mode);
4763 SIVAL(pdata, 0x24, 0); /* padding. */
4764 SBVAL(pdata, 0x28, allocation_size);
4765 SBVAL(pdata, 0x30, file_size);
4766 SIVAL(pdata, 0x38, nlink);
4767 SCVAL(pdata, 0x3C, delete_pending);
4768 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4769 SSVAL(pdata, 0x3E, 0); /* padding */
4770 SBVAL(pdata, 0x40, file_index);
4771 SIVAL(pdata, 0x48, ea_size);
4772 SIVAL(pdata, 0x4C, access_mask);
4773 SBVAL(pdata, 0x50, pos);
4774 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4775 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4777 pdata += 0x60;
4779 len = srvstr_push(dstart, flags2,
4780 pdata+4, dos_fname,
4781 PTR_DIFF(dend, pdata+4),
4782 STR_UNICODE);
4783 SIVAL(pdata,0,len);
4784 pdata += 4 + len;
4785 data_size = PTR_DIFF(pdata,(*ppdata));
4786 break;
4788 case SMB_FILE_INTERNAL_INFORMATION:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4791 SBVAL(pdata, 0, file_index);
4792 data_size = 8;
4793 break;
4795 case SMB_FILE_ACCESS_INFORMATION:
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4797 SIVAL(pdata, 0, access_mask);
4798 data_size = 4;
4799 break;
4801 case SMB_FILE_NAME_INFORMATION:
4802 /* Pathname with leading '\'. */
4804 size_t byte_len;
4805 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4806 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4807 SIVAL(pdata,0,byte_len);
4808 data_size = 4 + byte_len;
4809 break;
4812 case SMB_FILE_DISPOSITION_INFORMATION:
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4814 data_size = 1;
4815 SCVAL(pdata,0,delete_pending);
4816 break;
4818 case SMB_FILE_POSITION_INFORMATION:
4819 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4820 data_size = 8;
4821 SOFF_T(pdata,0,pos);
4822 break;
4824 case SMB_FILE_MODE_INFORMATION:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4826 SIVAL(pdata,0,mode);
4827 data_size = 4;
4828 break;
4830 case SMB_FILE_ALIGNMENT_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4832 SIVAL(pdata,0,0); /* No alignment needed. */
4833 data_size = 4;
4834 break;
4837 * NT4 server just returns "invalid query" to this - if we try
4838 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4839 * want this. JRA.
4841 /* The first statement above is false - verified using Thursby
4842 * client against NT4 -- gcolley.
4844 case SMB_QUERY_FILE_STREAM_INFO:
4845 case SMB_FILE_STREAM_INFORMATION: {
4846 unsigned int num_streams = 0;
4847 struct stream_struct *streams = NULL;
4849 DEBUG(10,("smbd_do_qfilepathinfo: "
4850 "SMB_FILE_STREAM_INFORMATION\n"));
4852 if (is_ntfs_stream_smb_fname(smb_fname)) {
4853 return NT_STATUS_INVALID_PARAMETER;
4856 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4857 talloc_tos(), &num_streams, &streams);
4859 if (!NT_STATUS_IS_OK(status)) {
4860 DEBUG(10, ("could not get stream info: %s\n",
4861 nt_errstr(status)));
4862 return status;
4865 status = marshall_stream_info(num_streams, streams,
4866 pdata, max_data_bytes,
4867 &data_size);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 DEBUG(10, ("marshall_stream_info failed: %s\n",
4871 nt_errstr(status)));
4872 TALLOC_FREE(streams);
4873 return status;
4876 TALLOC_FREE(streams);
4878 break;
4880 case SMB_QUERY_COMPRESSION_INFO:
4881 case SMB_FILE_COMPRESSION_INFORMATION:
4882 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4883 SOFF_T(pdata,0,file_size);
4884 SIVAL(pdata,8,0); /* ??? */
4885 SIVAL(pdata,12,0); /* ??? */
4886 data_size = 16;
4887 break;
4889 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4891 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4892 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4893 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4894 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4895 SOFF_T(pdata,32,allocation_size);
4896 SOFF_T(pdata,40,file_size);
4897 SIVAL(pdata,48,mode);
4898 SIVAL(pdata,52,0); /* ??? */
4899 data_size = 56;
4900 break;
4902 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4903 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4904 SIVAL(pdata,0,mode);
4905 SIVAL(pdata,4,0);
4906 data_size = 8;
4907 break;
4910 * CIFS UNIX Extensions.
4913 case SMB_QUERY_FILE_UNIX_BASIC:
4915 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4916 data_size = PTR_DIFF(pdata,(*ppdata));
4918 DEBUG(4,("smbd_do_qfilepathinfo: "
4919 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4920 dump_data(4, (uint8_t *)(*ppdata), data_size);
4922 break;
4924 case SMB_QUERY_FILE_UNIX_INFO2:
4926 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4927 data_size = PTR_DIFF(pdata,(*ppdata));
4930 int i;
4931 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4933 for (i=0; i<100; i++)
4934 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4935 DEBUG(4,("\n"));
4938 break;
4940 case SMB_QUERY_FILE_UNIX_LINK:
4942 int len;
4943 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4945 if (!buffer) {
4946 return NT_STATUS_NO_MEMORY;
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4950 #ifdef S_ISLNK
4951 if(!S_ISLNK(psbuf->st_ex_mode)) {
4952 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4954 #else
4955 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4956 #endif
4957 len = SMB_VFS_READLINK(conn,
4958 smb_fname->base_name,
4959 buffer, PATH_MAX);
4960 if (len == -1) {
4961 return map_nt_error_from_unix(errno);
4963 buffer[len] = 0;
4964 len = srvstr_push(dstart, flags2,
4965 pdata, buffer,
4966 PTR_DIFF(dend, pdata),
4967 STR_TERMINATE);
4968 pdata += len;
4969 data_size = PTR_DIFF(pdata,(*ppdata));
4971 break;
4974 #if defined(HAVE_POSIX_ACLS)
4975 case SMB_QUERY_POSIX_ACL:
4977 SMB_ACL_T file_acl = NULL;
4978 SMB_ACL_T def_acl = NULL;
4979 uint16 num_file_acls = 0;
4980 uint16 num_def_acls = 0;
4982 if (fsp && fsp->fh->fd != -1) {
4983 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4984 talloc_tos());
4985 } else {
4986 file_acl =
4987 SMB_VFS_SYS_ACL_GET_FILE(conn,
4988 smb_fname->base_name,
4989 SMB_ACL_TYPE_ACCESS,
4990 talloc_tos());
4993 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4994 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4995 "not implemented on "
4996 "filesystem containing %s\n",
4997 smb_fname->base_name));
4998 return NT_STATUS_NOT_IMPLEMENTED;
5001 if (S_ISDIR(psbuf->st_ex_mode)) {
5002 if (fsp && fsp->is_directory) {
5003 def_acl =
5004 SMB_VFS_SYS_ACL_GET_FILE(
5005 conn,
5006 fsp->fsp_name->base_name,
5007 SMB_ACL_TYPE_DEFAULT,
5008 talloc_tos());
5009 } else {
5010 def_acl =
5011 SMB_VFS_SYS_ACL_GET_FILE(
5012 conn,
5013 smb_fname->base_name,
5014 SMB_ACL_TYPE_DEFAULT,
5015 talloc_tos());
5017 def_acl = free_empty_sys_acl(conn, def_acl);
5020 num_file_acls = count_acl_entries(conn, file_acl);
5021 num_def_acls = count_acl_entries(conn, def_acl);
5023 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5024 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5025 data_size,
5026 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5027 SMB_POSIX_ACL_HEADER_SIZE) ));
5028 if (file_acl) {
5029 TALLOC_FREE(file_acl);
5031 if (def_acl) {
5032 TALLOC_FREE(def_acl);
5034 return NT_STATUS_BUFFER_TOO_SMALL;
5037 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5038 SSVAL(pdata,2,num_file_acls);
5039 SSVAL(pdata,4,num_def_acls);
5040 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5041 if (file_acl) {
5042 TALLOC_FREE(file_acl);
5044 if (def_acl) {
5045 TALLOC_FREE(def_acl);
5047 return NT_STATUS_INTERNAL_ERROR;
5049 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5050 if (file_acl) {
5051 TALLOC_FREE(file_acl);
5053 if (def_acl) {
5054 TALLOC_FREE(def_acl);
5056 return NT_STATUS_INTERNAL_ERROR;
5059 if (file_acl) {
5060 TALLOC_FREE(file_acl);
5062 if (def_acl) {
5063 TALLOC_FREE(def_acl);
5065 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5066 break;
5068 #endif
5071 case SMB_QUERY_POSIX_LOCK:
5073 uint64_t count;
5074 uint64_t offset;
5075 uint64_t smblctx;
5076 enum brl_type lock_type;
5078 /* We need an open file with a real fd for this. */
5079 if (!fsp || fsp->fh->fd == -1) {
5080 return NT_STATUS_INVALID_LEVEL;
5083 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5084 return NT_STATUS_INVALID_PARAMETER;
5087 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5088 case POSIX_LOCK_TYPE_READ:
5089 lock_type = READ_LOCK;
5090 break;
5091 case POSIX_LOCK_TYPE_WRITE:
5092 lock_type = WRITE_LOCK;
5093 break;
5094 case POSIX_LOCK_TYPE_UNLOCK:
5095 default:
5096 /* There's no point in asking for an unlock... */
5097 return NT_STATUS_INVALID_PARAMETER;
5100 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5101 #if defined(HAVE_LONGLONG)
5102 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5103 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5104 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5105 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5106 #else /* HAVE_LONGLONG */
5107 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5108 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5109 #endif /* HAVE_LONGLONG */
5111 status = query_lock(fsp,
5112 &smblctx,
5113 &count,
5114 &offset,
5115 &lock_type,
5116 POSIX_LOCK);
5118 if (ERROR_WAS_LOCK_DENIED(status)) {
5119 /* Here we need to report who has it locked... */
5120 data_size = POSIX_LOCK_DATA_SIZE;
5122 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5123 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5124 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5125 #if defined(HAVE_LONGLONG)
5126 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5127 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5128 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5129 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5130 #else /* HAVE_LONGLONG */
5131 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5132 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5133 #endif /* HAVE_LONGLONG */
5135 } else if (NT_STATUS_IS_OK(status)) {
5136 /* For success we just return a copy of what we sent
5137 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5138 data_size = POSIX_LOCK_DATA_SIZE;
5139 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5140 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5141 } else {
5142 return status;
5144 break;
5147 default:
5148 return NT_STATUS_INVALID_LEVEL;
5151 *pdata_size = data_size;
5152 return NT_STATUS_OK;
5155 /****************************************************************************
5156 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5157 file name or file id).
5158 ****************************************************************************/
5160 static void call_trans2qfilepathinfo(connection_struct *conn,
5161 struct smb_request *req,
5162 unsigned int tran_call,
5163 char **pparams, int total_params,
5164 char **ppdata, int total_data,
5165 unsigned int max_data_bytes)
5167 char *params = *pparams;
5168 char *pdata = *ppdata;
5169 uint16 info_level;
5170 unsigned int data_size = 0;
5171 unsigned int param_size = 2;
5172 struct smb_filename *smb_fname = NULL;
5173 bool delete_pending = False;
5174 struct timespec write_time_ts;
5175 files_struct *fsp = NULL;
5176 struct file_id fileid;
5177 struct ea_list *ea_list = NULL;
5178 int lock_data_count = 0;
5179 char *lock_data = NULL;
5180 NTSTATUS status = NT_STATUS_OK;
5182 if (!params) {
5183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5184 return;
5187 ZERO_STRUCT(write_time_ts);
5189 if (tran_call == TRANSACT2_QFILEINFO) {
5190 if (total_params < 4) {
5191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5192 return;
5195 if (IS_IPC(conn)) {
5196 call_trans2qpipeinfo(conn, req, tran_call,
5197 pparams, total_params,
5198 ppdata, total_data,
5199 max_data_bytes);
5200 return;
5203 fsp = file_fsp(req, SVAL(params,0));
5204 info_level = SVAL(params,2);
5206 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5208 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5209 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5210 return;
5213 /* Initial check for valid fsp ptr. */
5214 if (!check_fsp_open(conn, req, fsp)) {
5215 return;
5218 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5219 &smb_fname);
5220 if (!NT_STATUS_IS_OK(status)) {
5221 reply_nterror(req, status);
5222 return;
5225 if(fsp->fake_file_handle) {
5227 * This is actually for the QUOTA_FAKE_FILE --metze
5230 /* We know this name is ok, it's already passed the checks. */
5232 } else if(fsp->fh->fd == -1) {
5234 * This is actually a QFILEINFO on a directory
5235 * handle (returned from an NT SMB). NT5.0 seems
5236 * to do this call. JRA.
5239 if (INFO_LEVEL_IS_UNIX(info_level)) {
5240 /* Always do lstat for UNIX calls. */
5241 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5242 DEBUG(3,("call_trans2qfilepathinfo: "
5243 "SMB_VFS_LSTAT of %s failed "
5244 "(%s)\n",
5245 smb_fname_str_dbg(smb_fname),
5246 strerror(errno)));
5247 reply_nterror(req,
5248 map_nt_error_from_unix(errno));
5249 return;
5251 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5252 DEBUG(3,("call_trans2qfilepathinfo: "
5253 "SMB_VFS_STAT of %s failed (%s)\n",
5254 smb_fname_str_dbg(smb_fname),
5255 strerror(errno)));
5256 reply_nterror(req,
5257 map_nt_error_from_unix(errno));
5258 return;
5261 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5262 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5263 } else {
5265 * Original code - this is an open file.
5267 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5268 DEBUG(3, ("fstat of %s failed (%s)\n",
5269 fsp_fnum_dbg(fsp), strerror(errno)));
5270 reply_nterror(req,
5271 map_nt_error_from_unix(errno));
5272 return;
5274 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5275 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5278 } else {
5279 uint32_t name_hash;
5280 char *fname = NULL;
5281 uint32_t ucf_flags = 0;
5283 /* qpathinfo */
5284 if (total_params < 7) {
5285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5286 return;
5289 info_level = SVAL(params,0);
5291 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5293 if (INFO_LEVEL_IS_UNIX(info_level)) {
5294 if (!lp_unix_extensions()) {
5295 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5296 return;
5298 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5299 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5300 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5301 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5305 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5306 total_params - 6,
5307 STR_TERMINATE, &status);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 reply_nterror(req, status);
5310 return;
5313 status = filename_convert(req,
5314 conn,
5315 req->flags2 & FLAGS2_DFS_PATHNAMES,
5316 fname,
5317 ucf_flags,
5318 NULL,
5319 &smb_fname);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5322 reply_botherror(req,
5323 NT_STATUS_PATH_NOT_COVERED,
5324 ERRSRV, ERRbadpath);
5325 return;
5327 reply_nterror(req, status);
5328 return;
5331 /* If this is a stream, check if there is a delete_pending. */
5332 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5333 && is_ntfs_stream_smb_fname(smb_fname)) {
5334 struct smb_filename *smb_fname_base = NULL;
5336 /* Create an smb_filename with stream_name == NULL. */
5337 status =
5338 create_synthetic_smb_fname(talloc_tos(),
5339 smb_fname->base_name,
5340 NULL, NULL,
5341 &smb_fname_base);
5342 if (!NT_STATUS_IS_OK(status)) {
5343 reply_nterror(req, status);
5344 return;
5347 if (INFO_LEVEL_IS_UNIX(info_level)) {
5348 /* Always do lstat for UNIX calls. */
5349 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5350 DEBUG(3,("call_trans2qfilepathinfo: "
5351 "SMB_VFS_LSTAT of %s failed "
5352 "(%s)\n",
5353 smb_fname_str_dbg(smb_fname_base),
5354 strerror(errno)));
5355 TALLOC_FREE(smb_fname_base);
5356 reply_nterror(req,
5357 map_nt_error_from_unix(errno));
5358 return;
5360 } else {
5361 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5362 DEBUG(3,("call_trans2qfilepathinfo: "
5363 "fileinfo of %s failed "
5364 "(%s)\n",
5365 smb_fname_str_dbg(smb_fname_base),
5366 strerror(errno)));
5367 TALLOC_FREE(smb_fname_base);
5368 reply_nterror(req,
5369 map_nt_error_from_unix(errno));
5370 return;
5374 status = file_name_hash(conn,
5375 smb_fname_str_dbg(smb_fname_base),
5376 &name_hash);
5377 if (!NT_STATUS_IS_OK(status)) {
5378 TALLOC_FREE(smb_fname_base);
5379 reply_nterror(req, status);
5380 return;
5383 fileid = vfs_file_id_from_sbuf(conn,
5384 &smb_fname_base->st);
5385 TALLOC_FREE(smb_fname_base);
5386 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5387 if (delete_pending) {
5388 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5389 return;
5393 if (INFO_LEVEL_IS_UNIX(info_level)) {
5394 /* Always do lstat for UNIX calls. */
5395 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5396 DEBUG(3,("call_trans2qfilepathinfo: "
5397 "SMB_VFS_LSTAT of %s failed (%s)\n",
5398 smb_fname_str_dbg(smb_fname),
5399 strerror(errno)));
5400 reply_nterror(req,
5401 map_nt_error_from_unix(errno));
5402 return;
5405 } else {
5406 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5407 DEBUG(3,("call_trans2qfilepathinfo: "
5408 "SMB_VFS_STAT of %s failed (%s)\n",
5409 smb_fname_str_dbg(smb_fname),
5410 strerror(errno)));
5411 reply_nterror(req,
5412 map_nt_error_from_unix(errno));
5413 return;
5417 status = file_name_hash(conn,
5418 smb_fname_str_dbg(smb_fname),
5419 &name_hash);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 reply_nterror(req, status);
5422 return;
5425 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5426 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5427 if (delete_pending) {
5428 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5429 return;
5433 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5434 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5435 fsp_fnum_dbg(fsp),
5436 info_level,tran_call,total_data));
5438 /* Pull out any data sent here before we realloc. */
5439 switch (info_level) {
5440 case SMB_INFO_QUERY_EAS_FROM_LIST:
5442 /* Pull any EA list from the data portion. */
5443 uint32 ea_size;
5445 if (total_data < 4) {
5446 reply_nterror(
5447 req, NT_STATUS_INVALID_PARAMETER);
5448 return;
5450 ea_size = IVAL(pdata,0);
5452 if (total_data > 0 && ea_size != total_data) {
5453 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5454 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5455 reply_nterror(
5456 req, NT_STATUS_INVALID_PARAMETER);
5457 return;
5460 if (!lp_ea_support(SNUM(conn))) {
5461 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5462 return;
5465 /* Pull out the list of names. */
5466 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5467 if (!ea_list) {
5468 reply_nterror(
5469 req, NT_STATUS_INVALID_PARAMETER);
5470 return;
5472 break;
5475 case SMB_QUERY_POSIX_LOCK:
5477 if (fsp == NULL || fsp->fh->fd == -1) {
5478 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5479 return;
5482 if (total_data != POSIX_LOCK_DATA_SIZE) {
5483 reply_nterror(
5484 req, NT_STATUS_INVALID_PARAMETER);
5485 return;
5488 /* Copy the lock range data. */
5489 lock_data = (char *)talloc_memdup(
5490 req, pdata, total_data);
5491 if (!lock_data) {
5492 reply_nterror(req, NT_STATUS_NO_MEMORY);
5493 return;
5495 lock_data_count = total_data;
5497 default:
5498 break;
5501 *pparams = (char *)SMB_REALLOC(*pparams,2);
5502 if (*pparams == NULL) {
5503 reply_nterror(req, NT_STATUS_NO_MEMORY);
5504 return;
5506 params = *pparams;
5507 SSVAL(params,0,0);
5510 * draft-leach-cifs-v1-spec-02.txt
5511 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5512 * says:
5514 * The requested information is placed in the Data portion of the
5515 * transaction response. For the information levels greater than 0x100,
5516 * the transaction response has 1 parameter word which should be
5517 * ignored by the client.
5519 * However Windows only follows this rule for the IS_NAME_VALID call.
5521 switch (info_level) {
5522 case SMB_INFO_IS_NAME_VALID:
5523 param_size = 0;
5524 break;
5527 if ((info_level & 0xFF00) == 0xFF00) {
5529 * We use levels that start with 0xFF00
5530 * internally to represent SMB2 specific levels
5532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5533 return;
5536 status = smbd_do_qfilepathinfo(conn, req, info_level,
5537 fsp, smb_fname,
5538 delete_pending, write_time_ts,
5539 ea_list,
5540 lock_data_count, lock_data,
5541 req->flags2, max_data_bytes,
5542 ppdata, &data_size);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 reply_nterror(req, status);
5545 return;
5548 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5549 max_data_bytes);
5551 return;
5554 /****************************************************************************
5555 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5556 code.
5557 ****************************************************************************/
5559 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5560 connection_struct *conn,
5561 struct smb_request *req,
5562 bool overwrite_if_exists,
5563 const struct smb_filename *smb_fname_old,
5564 struct smb_filename *smb_fname_new)
5566 NTSTATUS status = NT_STATUS_OK;
5568 /* source must already exist. */
5569 if (!VALID_STAT(smb_fname_old->st)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5573 if (VALID_STAT(smb_fname_new->st)) {
5574 if (overwrite_if_exists) {
5575 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5576 return NT_STATUS_FILE_IS_A_DIRECTORY;
5578 status = unlink_internals(conn,
5579 req,
5580 FILE_ATTRIBUTE_NORMAL,
5581 smb_fname_new,
5582 false);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 return status;
5586 } else {
5587 /* Disallow if newname already exists. */
5588 return NT_STATUS_OBJECT_NAME_COLLISION;
5592 /* No links from a directory. */
5593 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5594 return NT_STATUS_FILE_IS_A_DIRECTORY;
5597 /* Setting a hardlink to/from a stream isn't currently supported. */
5598 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5599 is_ntfs_stream_smb_fname(smb_fname_new)) {
5600 return NT_STATUS_INVALID_PARAMETER;
5603 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5604 smb_fname_old->base_name, smb_fname_new->base_name));
5606 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5607 smb_fname_new->base_name) != 0) {
5608 status = map_nt_error_from_unix(errno);
5609 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5610 nt_errstr(status), smb_fname_old->base_name,
5611 smb_fname_new->base_name));
5613 return status;
5616 /****************************************************************************
5617 Deal with setting the time from any of the setfilepathinfo functions.
5618 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5619 calling this function.
5620 ****************************************************************************/
5622 NTSTATUS smb_set_file_time(connection_struct *conn,
5623 files_struct *fsp,
5624 const struct smb_filename *smb_fname,
5625 struct smb_file_time *ft,
5626 bool setting_write_time)
5628 struct smb_filename smb_fname_base;
5629 uint32 action =
5630 FILE_NOTIFY_CHANGE_LAST_ACCESS
5631 |FILE_NOTIFY_CHANGE_LAST_WRITE
5632 |FILE_NOTIFY_CHANGE_CREATION;
5634 if (!VALID_STAT(smb_fname->st)) {
5635 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5638 /* get some defaults (no modifications) if any info is zero or -1. */
5639 if (null_timespec(ft->create_time)) {
5640 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5643 if (null_timespec(ft->atime)) {
5644 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5647 if (null_timespec(ft->mtime)) {
5648 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5651 if (!setting_write_time) {
5652 /* ft->mtime comes from change time, not write time. */
5653 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5656 /* Ensure the resolution is the correct for
5657 * what we can store on this filesystem. */
5659 round_timespec(conn->ts_res, &ft->create_time);
5660 round_timespec(conn->ts_res, &ft->ctime);
5661 round_timespec(conn->ts_res, &ft->atime);
5662 round_timespec(conn->ts_res, &ft->mtime);
5664 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5665 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5666 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5667 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5668 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5669 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5670 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5671 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5673 if (setting_write_time) {
5675 * This was a Windows setfileinfo on an open file.
5676 * NT does this a lot. We also need to
5677 * set the time here, as it can be read by
5678 * FindFirst/FindNext and with the patch for bug #2045
5679 * in smbd/fileio.c it ensures that this timestamp is
5680 * kept sticky even after a write. We save the request
5681 * away and will set it on file close and after a write. JRA.
5684 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5685 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5687 if (fsp != NULL) {
5688 if (fsp->base_fsp) {
5689 set_sticky_write_time_fsp(fsp->base_fsp,
5690 ft->mtime);
5691 } else {
5692 set_sticky_write_time_fsp(fsp, ft->mtime);
5694 } else {
5695 set_sticky_write_time_path(
5696 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5697 ft->mtime);
5701 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5703 /* Always call ntimes on the base, even if a stream was passed in. */
5704 smb_fname_base = *smb_fname;
5705 smb_fname_base.stream_name = NULL;
5707 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5708 return map_nt_error_from_unix(errno);
5711 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5712 smb_fname->base_name);
5713 return NT_STATUS_OK;
5716 /****************************************************************************
5717 Deal with setting the dosmode from any of the setfilepathinfo functions.
5718 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5719 done before calling this function.
5720 ****************************************************************************/
5722 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5723 const struct smb_filename *smb_fname,
5724 uint32 dosmode)
5726 struct smb_filename *smb_fname_base = NULL;
5727 NTSTATUS status;
5729 if (!VALID_STAT(smb_fname->st)) {
5730 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5733 /* Always operate on the base_name, even if a stream was passed in. */
5734 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5735 NULL, &smb_fname->st,
5736 &smb_fname_base);
5737 if (!NT_STATUS_IS_OK(status)) {
5738 return status;
5741 if (dosmode) {
5742 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5743 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5744 } else {
5745 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5749 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5751 /* check the mode isn't different, before changing it */
5752 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5753 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5754 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5755 (unsigned int)dosmode));
5757 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5758 false)) {
5759 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5760 "%s failed (%s)\n",
5761 smb_fname_str_dbg(smb_fname_base),
5762 strerror(errno)));
5763 status = map_nt_error_from_unix(errno);
5764 goto out;
5767 status = NT_STATUS_OK;
5768 out:
5769 TALLOC_FREE(smb_fname_base);
5770 return status;
5773 /****************************************************************************
5774 Deal with setting the size from any of the setfilepathinfo functions.
5775 ****************************************************************************/
5777 static NTSTATUS smb_set_file_size(connection_struct *conn,
5778 struct smb_request *req,
5779 files_struct *fsp,
5780 const struct smb_filename *smb_fname,
5781 const SMB_STRUCT_STAT *psbuf,
5782 off_t size,
5783 bool fail_after_createfile)
5785 NTSTATUS status = NT_STATUS_OK;
5786 struct smb_filename *smb_fname_tmp = NULL;
5787 files_struct *new_fsp = NULL;
5789 if (!VALID_STAT(*psbuf)) {
5790 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5793 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5795 if (size == get_file_size_stat(psbuf)) {
5796 return NT_STATUS_OK;
5799 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5800 smb_fname_str_dbg(smb_fname), (double)size));
5802 if (fsp && fsp->fh->fd != -1) {
5803 /* Handle based call. */
5804 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5805 return NT_STATUS_ACCESS_DENIED;
5808 if (vfs_set_filelen(fsp, size) == -1) {
5809 return map_nt_error_from_unix(errno);
5811 trigger_write_time_update_immediate(fsp);
5812 return NT_STATUS_OK;
5815 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5816 if (!NT_STATUS_IS_OK(status)) {
5817 return status;
5820 smb_fname_tmp->st = *psbuf;
5822 status = SMB_VFS_CREATE_FILE(
5823 conn, /* conn */
5824 req, /* req */
5825 0, /* root_dir_fid */
5826 smb_fname_tmp, /* fname */
5827 FILE_WRITE_DATA, /* access_mask */
5828 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5829 FILE_SHARE_DELETE),
5830 FILE_OPEN, /* create_disposition*/
5831 0, /* create_options */
5832 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5833 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5834 0, /* allocation_size */
5835 0, /* private_flags */
5836 NULL, /* sd */
5837 NULL, /* ea_list */
5838 &new_fsp, /* result */
5839 NULL); /* pinfo */
5841 TALLOC_FREE(smb_fname_tmp);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 /* NB. We check for open_was_deferred in the caller. */
5845 return status;
5848 /* See RAW-SFILEINFO-END-OF-FILE */
5849 if (fail_after_createfile) {
5850 close_file(req, new_fsp,NORMAL_CLOSE);
5851 return NT_STATUS_INVALID_LEVEL;
5854 if (vfs_set_filelen(new_fsp, size) == -1) {
5855 status = map_nt_error_from_unix(errno);
5856 close_file(req, new_fsp,NORMAL_CLOSE);
5857 return status;
5860 trigger_write_time_update_immediate(new_fsp);
5861 close_file(req, new_fsp,NORMAL_CLOSE);
5862 return NT_STATUS_OK;
5865 /****************************************************************************
5866 Deal with SMB_INFO_SET_EA.
5867 ****************************************************************************/
5869 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5870 const char *pdata,
5871 int total_data,
5872 files_struct *fsp,
5873 const struct smb_filename *smb_fname)
5875 struct ea_list *ea_list = NULL;
5876 TALLOC_CTX *ctx = NULL;
5877 NTSTATUS status = NT_STATUS_OK;
5879 if (total_data < 10) {
5881 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5882 length. They seem to have no effect. Bug #3212. JRA */
5884 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5885 /* We're done. We only get EA info in this call. */
5886 return NT_STATUS_OK;
5889 return NT_STATUS_INVALID_PARAMETER;
5892 if (IVAL(pdata,0) > total_data) {
5893 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5894 IVAL(pdata,0), (unsigned int)total_data));
5895 return NT_STATUS_INVALID_PARAMETER;
5898 ctx = talloc_tos();
5899 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5900 if (!ea_list) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 status = set_ea(conn, fsp, smb_fname, ea_list);
5906 return status;
5909 /****************************************************************************
5910 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5911 ****************************************************************************/
5913 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5914 const char *pdata,
5915 int total_data,
5916 files_struct *fsp)
5918 struct ea_list *ea_list = NULL;
5919 NTSTATUS status;
5921 if (!fsp) {
5922 return NT_STATUS_INVALID_HANDLE;
5925 if (!lp_ea_support(SNUM(conn))) {
5926 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5927 "EA's not supported.\n",
5928 (unsigned int)total_data));
5929 return NT_STATUS_EAS_NOT_SUPPORTED;
5932 if (total_data < 10) {
5933 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5934 "too small.\n",
5935 (unsigned int)total_data));
5936 return NT_STATUS_INVALID_PARAMETER;
5939 ea_list = read_nttrans_ea_list(talloc_tos(),
5940 pdata,
5941 total_data);
5943 if (!ea_list) {
5944 return NT_STATUS_INVALID_PARAMETER;
5947 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5949 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5950 smb_fname_str_dbg(fsp->fsp_name),
5951 nt_errstr(status) ));
5953 return status;
5957 /****************************************************************************
5958 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5959 ****************************************************************************/
5961 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5962 const char *pdata,
5963 int total_data,
5964 files_struct *fsp,
5965 struct smb_filename *smb_fname)
5967 NTSTATUS status = NT_STATUS_OK;
5968 bool delete_on_close;
5969 uint32 dosmode = 0;
5971 if (total_data < 1) {
5972 return NT_STATUS_INVALID_PARAMETER;
5975 if (fsp == NULL) {
5976 return NT_STATUS_INVALID_HANDLE;
5979 delete_on_close = (CVAL(pdata,0) ? True : False);
5980 dosmode = dos_mode(conn, smb_fname);
5982 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5983 "delete_on_close = %u\n",
5984 smb_fname_str_dbg(smb_fname),
5985 (unsigned int)dosmode,
5986 (unsigned int)delete_on_close ));
5988 if (delete_on_close) {
5989 status = can_set_delete_on_close(fsp, dosmode);
5990 if (!NT_STATUS_IS_OK(status)) {
5991 return status;
5995 /* The set is across all open files on this dev/inode pair. */
5996 if (!set_delete_on_close(fsp, delete_on_close,
5997 conn->session_info->security_token,
5998 conn->session_info->unix_token)) {
5999 return NT_STATUS_ACCESS_DENIED;
6001 return NT_STATUS_OK;
6004 /****************************************************************************
6005 Deal with SMB_FILE_POSITION_INFORMATION.
6006 ****************************************************************************/
6008 static NTSTATUS smb_file_position_information(connection_struct *conn,
6009 const char *pdata,
6010 int total_data,
6011 files_struct *fsp)
6013 uint64_t position_information;
6015 if (total_data < 8) {
6016 return NT_STATUS_INVALID_PARAMETER;
6019 if (fsp == NULL) {
6020 /* Ignore on pathname based set. */
6021 return NT_STATUS_OK;
6024 position_information = (uint64_t)IVAL(pdata,0);
6025 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6027 DEBUG(10,("smb_file_position_information: Set file position "
6028 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6029 (double)position_information));
6030 fsp->fh->position_information = position_information;
6031 return NT_STATUS_OK;
6034 /****************************************************************************
6035 Deal with SMB_FILE_MODE_INFORMATION.
6036 ****************************************************************************/
6038 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6039 const char *pdata,
6040 int total_data)
6042 uint32 mode;
6044 if (total_data < 4) {
6045 return NT_STATUS_INVALID_PARAMETER;
6047 mode = IVAL(pdata,0);
6048 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6049 return NT_STATUS_INVALID_PARAMETER;
6051 return NT_STATUS_OK;
6054 /****************************************************************************
6055 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6056 ****************************************************************************/
6058 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6059 struct smb_request *req,
6060 const char *pdata,
6061 int total_data,
6062 const struct smb_filename *smb_fname)
6064 char *link_target = NULL;
6065 const char *newname = smb_fname->base_name;
6066 TALLOC_CTX *ctx = talloc_tos();
6068 /* Set a symbolic link. */
6069 /* Don't allow this if follow links is false. */
6071 if (total_data == 0) {
6072 return NT_STATUS_INVALID_PARAMETER;
6075 if (!lp_symlinks(SNUM(conn))) {
6076 return NT_STATUS_ACCESS_DENIED;
6079 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6080 total_data, STR_TERMINATE);
6082 if (!link_target) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6087 newname, link_target ));
6089 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6090 return map_nt_error_from_unix(errno);
6093 return NT_STATUS_OK;
6096 /****************************************************************************
6097 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6098 ****************************************************************************/
6100 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6101 struct smb_request *req,
6102 const char *pdata, int total_data,
6103 struct smb_filename *smb_fname_new)
6105 char *oldname = NULL;
6106 struct smb_filename *smb_fname_old = NULL;
6107 TALLOC_CTX *ctx = talloc_tos();
6108 NTSTATUS status = NT_STATUS_OK;
6110 /* Set a hard link. */
6111 if (total_data == 0) {
6112 return NT_STATUS_INVALID_PARAMETER;
6115 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6116 total_data, STR_TERMINATE, &status);
6117 if (!NT_STATUS_IS_OK(status)) {
6118 return status;
6121 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6122 smb_fname_str_dbg(smb_fname_new), oldname));
6124 status = filename_convert(ctx,
6125 conn,
6126 req->flags2 & FLAGS2_DFS_PATHNAMES,
6127 oldname,
6129 NULL,
6130 &smb_fname_old);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 return status;
6135 return hardlink_internals(ctx, conn, req, false,
6136 smb_fname_old, smb_fname_new);
6139 /****************************************************************************
6140 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6141 ****************************************************************************/
6143 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6144 struct smb_request *req,
6145 const char *pdata,
6146 int total_data,
6147 files_struct *fsp,
6148 struct smb_filename *smb_fname_src)
6150 bool overwrite;
6151 uint32_t len;
6152 char *newname = NULL;
6153 struct smb_filename *smb_fname_dst = NULL;
6154 NTSTATUS status = NT_STATUS_OK;
6155 TALLOC_CTX *ctx = talloc_tos();
6157 if (!fsp) {
6158 return NT_STATUS_INVALID_HANDLE;
6161 if (total_data < 20) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 overwrite = (CVAL(pdata,0) ? True : False);
6166 len = IVAL(pdata,16);
6168 if (len > (total_data - 20) || (len == 0)) {
6169 return NT_STATUS_INVALID_PARAMETER;
6172 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6173 &pdata[20], len, STR_TERMINATE,
6174 &status);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 return status;
6179 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6180 newname));
6182 status = filename_convert(ctx,
6183 conn,
6184 req->flags2 & FLAGS2_DFS_PATHNAMES,
6185 newname,
6186 UCF_SAVE_LCOMP,
6187 NULL,
6188 &smb_fname_dst);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 return status;
6193 if (fsp->base_fsp) {
6194 /* newname must be a stream name. */
6195 if (newname[0] != ':') {
6196 return NT_STATUS_NOT_SUPPORTED;
6199 /* Create an smb_fname to call rename_internals_fsp() with. */
6200 status = create_synthetic_smb_fname(talloc_tos(),
6201 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6202 &smb_fname_dst);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 goto out;
6208 * Set the original last component, since
6209 * rename_internals_fsp() requires it.
6211 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6212 newname);
6213 if (smb_fname_dst->original_lcomp == NULL) {
6214 status = NT_STATUS_NO_MEMORY;
6215 goto out;
6220 DEBUG(10,("smb2_file_rename_information: "
6221 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6222 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6223 smb_fname_str_dbg(smb_fname_dst)));
6224 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6225 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6226 overwrite);
6228 out:
6229 TALLOC_FREE(smb_fname_dst);
6230 return status;
6233 static NTSTATUS smb_file_link_information(connection_struct *conn,
6234 struct smb_request *req,
6235 const char *pdata,
6236 int total_data,
6237 files_struct *fsp,
6238 struct smb_filename *smb_fname_src)
6240 bool overwrite;
6241 uint32_t len;
6242 char *newname = NULL;
6243 struct smb_filename *smb_fname_dst = NULL;
6244 NTSTATUS status = NT_STATUS_OK;
6245 TALLOC_CTX *ctx = talloc_tos();
6247 if (!fsp) {
6248 return NT_STATUS_INVALID_HANDLE;
6251 if (total_data < 20) {
6252 return NT_STATUS_INVALID_PARAMETER;
6255 overwrite = (CVAL(pdata,0) ? true : false);
6256 len = IVAL(pdata,16);
6258 if (len > (total_data - 20) || (len == 0)) {
6259 return NT_STATUS_INVALID_PARAMETER;
6262 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6263 &pdata[20], len, STR_TERMINATE,
6264 &status);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 return status;
6269 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6270 newname));
6272 status = filename_convert(ctx,
6273 conn,
6274 req->flags2 & FLAGS2_DFS_PATHNAMES,
6275 newname,
6276 UCF_SAVE_LCOMP,
6277 NULL,
6278 &smb_fname_dst);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 return status;
6283 if (fsp->base_fsp) {
6284 /* No stream names. */
6285 return NT_STATUS_NOT_SUPPORTED;
6288 DEBUG(10,("smb_file_link_information: "
6289 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6290 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6291 smb_fname_str_dbg(smb_fname_dst)));
6292 status = hardlink_internals(ctx,
6293 conn,
6294 req,
6295 overwrite,
6296 fsp->fsp_name,
6297 smb_fname_dst);
6299 TALLOC_FREE(smb_fname_dst);
6300 return status;
6303 /****************************************************************************
6304 Deal with SMB_FILE_RENAME_INFORMATION.
6305 ****************************************************************************/
6307 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6308 struct smb_request *req,
6309 const char *pdata,
6310 int total_data,
6311 files_struct *fsp,
6312 struct smb_filename *smb_fname_src)
6314 bool overwrite;
6315 uint32 root_fid;
6316 uint32 len;
6317 char *newname = NULL;
6318 struct smb_filename *smb_fname_dst = NULL;
6319 bool dest_has_wcard = False;
6320 NTSTATUS status = NT_STATUS_OK;
6321 char *p;
6322 TALLOC_CTX *ctx = talloc_tos();
6324 if (total_data < 13) {
6325 return NT_STATUS_INVALID_PARAMETER;
6328 overwrite = (CVAL(pdata,0) ? True : False);
6329 root_fid = IVAL(pdata,4);
6330 len = IVAL(pdata,8);
6332 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6337 len, 0, &status,
6338 &dest_has_wcard);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 return status;
6343 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6344 newname));
6346 status = resolve_dfspath_wcard(ctx, conn,
6347 req->flags2 & FLAGS2_DFS_PATHNAMES,
6348 newname,
6349 true,
6350 !conn->sconn->using_smb2,
6351 &newname,
6352 &dest_has_wcard);
6353 if (!NT_STATUS_IS_OK(status)) {
6354 return status;
6357 /* Check the new name has no '/' characters. */
6358 if (strchr_m(newname, '/')) {
6359 return NT_STATUS_NOT_SUPPORTED;
6362 if (fsp && fsp->base_fsp) {
6363 /* newname must be a stream name. */
6364 if (newname[0] != ':') {
6365 return NT_STATUS_NOT_SUPPORTED;
6368 /* Create an smb_fname to call rename_internals_fsp() with. */
6369 status = create_synthetic_smb_fname(talloc_tos(),
6370 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6371 &smb_fname_dst);
6372 if (!NT_STATUS_IS_OK(status)) {
6373 goto out;
6377 * Set the original last component, since
6378 * rename_internals_fsp() requires it.
6380 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6381 newname);
6382 if (smb_fname_dst->original_lcomp == NULL) {
6383 status = NT_STATUS_NO_MEMORY;
6384 goto out;
6387 } else {
6389 * Build up an smb_fname_dst based on the filename passed in.
6390 * We basically just strip off the last component, and put on
6391 * the newname instead.
6393 char *base_name = NULL;
6395 /* newname must *not* be a stream name. */
6396 if (newname[0] == ':') {
6397 return NT_STATUS_NOT_SUPPORTED;
6401 * Strip off the last component (filename) of the path passed
6402 * in.
6404 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6405 if (!base_name) {
6406 return NT_STATUS_NO_MEMORY;
6408 p = strrchr_m(base_name, '/');
6409 if (p) {
6410 p[1] = '\0';
6411 } else {
6412 base_name = talloc_strdup(ctx, "");
6413 if (!base_name) {
6414 return NT_STATUS_NO_MEMORY;
6417 /* Append the new name. */
6418 base_name = talloc_asprintf_append(base_name,
6419 "%s",
6420 newname);
6421 if (!base_name) {
6422 return NT_STATUS_NO_MEMORY;
6425 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6426 (UCF_SAVE_LCOMP |
6427 (dest_has_wcard ?
6428 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6429 0)));
6431 /* If an error we expect this to be
6432 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6434 if (!NT_STATUS_IS_OK(status)) {
6435 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6436 status)) {
6437 goto out;
6439 /* Create an smb_fname to call rename_internals_fsp() */
6440 status = create_synthetic_smb_fname(ctx,
6441 base_name, NULL,
6442 NULL,
6443 &smb_fname_dst);
6444 if (!NT_STATUS_IS_OK(status)) {
6445 goto out;
6450 if (fsp) {
6451 DEBUG(10,("smb_file_rename_information: "
6452 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6453 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6454 smb_fname_str_dbg(smb_fname_dst)));
6455 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6456 overwrite);
6457 } else {
6458 DEBUG(10,("smb_file_rename_information: "
6459 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6460 smb_fname_str_dbg(smb_fname_src),
6461 smb_fname_str_dbg(smb_fname_dst)));
6462 status = rename_internals(ctx, conn, req, smb_fname_src,
6463 smb_fname_dst, 0, overwrite, false,
6464 dest_has_wcard,
6465 FILE_WRITE_ATTRIBUTES);
6467 out:
6468 TALLOC_FREE(smb_fname_dst);
6469 return status;
6472 /****************************************************************************
6473 Deal with SMB_SET_POSIX_ACL.
6474 ****************************************************************************/
6476 #if defined(HAVE_POSIX_ACLS)
6477 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6478 const char *pdata,
6479 int total_data,
6480 files_struct *fsp,
6481 const struct smb_filename *smb_fname)
6483 uint16 posix_acl_version;
6484 uint16 num_file_acls;
6485 uint16 num_def_acls;
6486 bool valid_file_acls = True;
6487 bool valid_def_acls = True;
6489 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6490 return NT_STATUS_INVALID_PARAMETER;
6492 posix_acl_version = SVAL(pdata,0);
6493 num_file_acls = SVAL(pdata,2);
6494 num_def_acls = SVAL(pdata,4);
6496 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6497 valid_file_acls = False;
6498 num_file_acls = 0;
6501 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6502 valid_def_acls = False;
6503 num_def_acls = 0;
6506 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6507 return NT_STATUS_INVALID_PARAMETER;
6510 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6511 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6512 return NT_STATUS_INVALID_PARAMETER;
6515 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6516 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6517 (unsigned int)num_file_acls,
6518 (unsigned int)num_def_acls));
6520 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6521 smb_fname->base_name, num_file_acls,
6522 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6523 return map_nt_error_from_unix(errno);
6526 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6527 smb_fname->base_name, &smb_fname->st, num_def_acls,
6528 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6529 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6530 return map_nt_error_from_unix(errno);
6532 return NT_STATUS_OK;
6534 #endif
6536 /****************************************************************************
6537 Deal with SMB_SET_POSIX_LOCK.
6538 ****************************************************************************/
6540 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6541 struct smb_request *req,
6542 const char *pdata,
6543 int total_data,
6544 files_struct *fsp)
6546 uint64_t count;
6547 uint64_t offset;
6548 uint64_t smblctx;
6549 bool blocking_lock = False;
6550 enum brl_type lock_type;
6552 NTSTATUS status = NT_STATUS_OK;
6554 if (fsp == NULL || fsp->fh->fd == -1) {
6555 return NT_STATUS_INVALID_HANDLE;
6558 if (total_data != POSIX_LOCK_DATA_SIZE) {
6559 return NT_STATUS_INVALID_PARAMETER;
6562 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6563 case POSIX_LOCK_TYPE_READ:
6564 lock_type = READ_LOCK;
6565 break;
6566 case POSIX_LOCK_TYPE_WRITE:
6567 /* Return the right POSIX-mappable error code for files opened read-only. */
6568 if (!fsp->can_write) {
6569 return NT_STATUS_INVALID_HANDLE;
6571 lock_type = WRITE_LOCK;
6572 break;
6573 case POSIX_LOCK_TYPE_UNLOCK:
6574 lock_type = UNLOCK_LOCK;
6575 break;
6576 default:
6577 return NT_STATUS_INVALID_PARAMETER;
6580 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6581 blocking_lock = False;
6582 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6583 blocking_lock = True;
6584 } else {
6585 return NT_STATUS_INVALID_PARAMETER;
6588 if (!lp_blocking_locks(SNUM(conn))) {
6589 blocking_lock = False;
6592 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6593 #if defined(HAVE_LONGLONG)
6594 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6595 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6596 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6597 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6598 #else /* HAVE_LONGLONG */
6599 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6600 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6601 #endif /* HAVE_LONGLONG */
6603 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6604 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6605 fsp_str_dbg(fsp),
6606 (unsigned int)lock_type,
6607 (unsigned long long)smblctx,
6608 (double)count,
6609 (double)offset ));
6611 if (lock_type == UNLOCK_LOCK) {
6612 status = do_unlock(req->sconn->msg_ctx,
6613 fsp,
6614 smblctx,
6615 count,
6616 offset,
6617 POSIX_LOCK);
6618 } else {
6619 uint64_t block_smblctx;
6621 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6622 fsp,
6623 smblctx,
6624 count,
6625 offset,
6626 lock_type,
6627 POSIX_LOCK,
6628 blocking_lock,
6629 &status,
6630 &block_smblctx,
6631 NULL);
6633 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6635 * A blocking lock was requested. Package up
6636 * this smb into a queued request and push it
6637 * onto the blocking lock queue.
6639 if(push_blocking_lock_request(br_lck,
6640 req,
6641 fsp,
6642 -1, /* infinite timeout. */
6644 smblctx,
6645 lock_type,
6646 POSIX_LOCK,
6647 offset,
6648 count,
6649 block_smblctx)) {
6650 TALLOC_FREE(br_lck);
6651 return status;
6654 TALLOC_FREE(br_lck);
6657 return status;
6660 /****************************************************************************
6661 Deal with SMB_SET_FILE_BASIC_INFO.
6662 ****************************************************************************/
6664 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6665 const char *pdata,
6666 int total_data,
6667 files_struct *fsp,
6668 const struct smb_filename *smb_fname)
6670 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6671 struct smb_file_time ft;
6672 uint32 dosmode = 0;
6673 NTSTATUS status = NT_STATUS_OK;
6675 ZERO_STRUCT(ft);
6677 if (total_data < 36) {
6678 return NT_STATUS_INVALID_PARAMETER;
6681 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 return status;
6686 /* Set the attributes */
6687 dosmode = IVAL(pdata,32);
6688 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 return status;
6693 /* create time */
6694 ft.create_time = interpret_long_date(pdata);
6696 /* access time */
6697 ft.atime = interpret_long_date(pdata+8);
6699 /* write time. */
6700 ft.mtime = interpret_long_date(pdata+16);
6702 /* change time. */
6703 ft.ctime = interpret_long_date(pdata+24);
6705 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6706 smb_fname_str_dbg(smb_fname)));
6708 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6709 true);
6712 /****************************************************************************
6713 Deal with SMB_INFO_STANDARD.
6714 ****************************************************************************/
6716 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6717 const char *pdata,
6718 int total_data,
6719 files_struct *fsp,
6720 const struct smb_filename *smb_fname)
6722 NTSTATUS status;
6723 struct smb_file_time ft;
6725 ZERO_STRUCT(ft);
6727 if (total_data < 12) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 /* create time */
6732 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6733 /* access time */
6734 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6735 /* write time */
6736 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6738 DEBUG(10,("smb_set_info_standard: file %s\n",
6739 smb_fname_str_dbg(smb_fname)));
6741 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 return status;
6746 return smb_set_file_time(conn,
6747 fsp,
6748 smb_fname,
6749 &ft,
6750 true);
6753 /****************************************************************************
6754 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6755 ****************************************************************************/
6757 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6758 struct smb_request *req,
6759 const char *pdata,
6760 int total_data,
6761 files_struct *fsp,
6762 struct smb_filename *smb_fname)
6764 uint64_t allocation_size = 0;
6765 NTSTATUS status = NT_STATUS_OK;
6766 files_struct *new_fsp = NULL;
6768 if (!VALID_STAT(smb_fname->st)) {
6769 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6772 if (total_data < 8) {
6773 return NT_STATUS_INVALID_PARAMETER;
6776 allocation_size = (uint64_t)IVAL(pdata,0);
6777 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6778 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6779 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6780 (double)allocation_size));
6782 if (allocation_size) {
6783 allocation_size = smb_roundup(conn, allocation_size);
6786 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6787 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6788 (double)allocation_size));
6790 if (fsp && fsp->fh->fd != -1) {
6791 /* Open file handle. */
6792 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6793 return NT_STATUS_ACCESS_DENIED;
6796 /* Only change if needed. */
6797 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6798 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6799 return map_nt_error_from_unix(errno);
6802 /* But always update the time. */
6804 * This is equivalent to a write. Ensure it's seen immediately
6805 * if there are no pending writes.
6807 trigger_write_time_update_immediate(fsp);
6808 return NT_STATUS_OK;
6811 /* Pathname or stat or directory file. */
6812 status = SMB_VFS_CREATE_FILE(
6813 conn, /* conn */
6814 req, /* req */
6815 0, /* root_dir_fid */
6816 smb_fname, /* fname */
6817 FILE_WRITE_DATA, /* access_mask */
6818 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6819 FILE_SHARE_DELETE),
6820 FILE_OPEN, /* create_disposition*/
6821 0, /* create_options */
6822 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6823 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6824 0, /* allocation_size */
6825 0, /* private_flags */
6826 NULL, /* sd */
6827 NULL, /* ea_list */
6828 &new_fsp, /* result */
6829 NULL); /* pinfo */
6831 if (!NT_STATUS_IS_OK(status)) {
6832 /* NB. We check for open_was_deferred in the caller. */
6833 return status;
6836 /* Only change if needed. */
6837 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6838 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6839 status = map_nt_error_from_unix(errno);
6840 close_file(req, new_fsp, NORMAL_CLOSE);
6841 return status;
6845 /* Changing the allocation size should set the last mod time. */
6847 * This is equivalent to a write. Ensure it's seen immediately
6848 * if there are no pending writes.
6850 trigger_write_time_update_immediate(new_fsp);
6852 close_file(req, new_fsp, NORMAL_CLOSE);
6853 return NT_STATUS_OK;
6856 /****************************************************************************
6857 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6858 ****************************************************************************/
6860 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6861 struct smb_request *req,
6862 const char *pdata,
6863 int total_data,
6864 files_struct *fsp,
6865 const struct smb_filename *smb_fname,
6866 bool fail_after_createfile)
6868 off_t size;
6870 if (total_data < 8) {
6871 return NT_STATUS_INVALID_PARAMETER;
6874 size = IVAL(pdata,0);
6875 size |= (((off_t)IVAL(pdata,4)) << 32);
6876 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6877 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6878 (double)size));
6880 return smb_set_file_size(conn, req,
6881 fsp,
6882 smb_fname,
6883 &smb_fname->st,
6884 size,
6885 fail_after_createfile);
6888 /****************************************************************************
6889 Allow a UNIX info mknod.
6890 ****************************************************************************/
6892 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6893 const char *pdata,
6894 int total_data,
6895 const struct smb_filename *smb_fname)
6897 uint32 file_type = IVAL(pdata,56);
6898 #if defined(HAVE_MAKEDEV)
6899 uint32 dev_major = IVAL(pdata,60);
6900 uint32 dev_minor = IVAL(pdata,68);
6901 #endif
6902 SMB_DEV_T dev = (SMB_DEV_T)0;
6903 uint32 raw_unixmode = IVAL(pdata,84);
6904 NTSTATUS status;
6905 mode_t unixmode;
6907 if (total_data < 100) {
6908 return NT_STATUS_INVALID_PARAMETER;
6911 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6912 PERM_NEW_FILE, &unixmode);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 return status;
6917 #if defined(HAVE_MAKEDEV)
6918 dev = makedev(dev_major, dev_minor);
6919 #endif
6921 switch (file_type) {
6922 #if defined(S_IFIFO)
6923 case UNIX_TYPE_FIFO:
6924 unixmode |= S_IFIFO;
6925 break;
6926 #endif
6927 #if defined(S_IFSOCK)
6928 case UNIX_TYPE_SOCKET:
6929 unixmode |= S_IFSOCK;
6930 break;
6931 #endif
6932 #if defined(S_IFCHR)
6933 case UNIX_TYPE_CHARDEV:
6934 unixmode |= S_IFCHR;
6935 break;
6936 #endif
6937 #if defined(S_IFBLK)
6938 case UNIX_TYPE_BLKDEV:
6939 unixmode |= S_IFBLK;
6940 break;
6941 #endif
6942 default:
6943 return NT_STATUS_INVALID_PARAMETER;
6946 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6947 "%.0f mode 0%o for file %s\n", (double)dev,
6948 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6950 /* Ok - do the mknod. */
6951 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6952 return map_nt_error_from_unix(errno);
6955 /* If any of the other "set" calls fail we
6956 * don't want to end up with a half-constructed mknod.
6959 if (lp_inherit_perms(SNUM(conn))) {
6960 char *parent;
6961 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6962 &parent, NULL)) {
6963 return NT_STATUS_NO_MEMORY;
6965 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6966 unixmode);
6967 TALLOC_FREE(parent);
6970 return NT_STATUS_OK;
6973 /****************************************************************************
6974 Deal with SMB_SET_FILE_UNIX_BASIC.
6975 ****************************************************************************/
6977 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6978 struct smb_request *req,
6979 const char *pdata,
6980 int total_data,
6981 files_struct *fsp,
6982 const struct smb_filename *smb_fname)
6984 struct smb_file_time ft;
6985 uint32 raw_unixmode;
6986 mode_t unixmode;
6987 off_t size = 0;
6988 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6989 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6990 NTSTATUS status = NT_STATUS_OK;
6991 bool delete_on_fail = False;
6992 enum perm_type ptype;
6993 files_struct *all_fsps = NULL;
6994 bool modify_mtime = true;
6995 struct file_id id;
6996 struct smb_filename *smb_fname_tmp = NULL;
6997 SMB_STRUCT_STAT sbuf;
6999 ZERO_STRUCT(ft);
7001 if (total_data < 100) {
7002 return NT_STATUS_INVALID_PARAMETER;
7005 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7006 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7007 size=IVAL(pdata,0); /* first 8 Bytes are size */
7008 size |= (((off_t)IVAL(pdata,4)) << 32);
7011 ft.atime = interpret_long_date(pdata+24); /* access_time */
7012 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7013 set_owner = (uid_t)IVAL(pdata,40);
7014 set_grp = (gid_t)IVAL(pdata,48);
7015 raw_unixmode = IVAL(pdata,84);
7017 if (VALID_STAT(smb_fname->st)) {
7018 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7019 ptype = PERM_EXISTING_DIR;
7020 } else {
7021 ptype = PERM_EXISTING_FILE;
7023 } else {
7024 ptype = PERM_NEW_FILE;
7027 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7028 ptype, &unixmode);
7029 if (!NT_STATUS_IS_OK(status)) {
7030 return status;
7033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7034 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7035 smb_fname_str_dbg(smb_fname), (double)size,
7036 (unsigned int)set_owner, (unsigned int)set_grp,
7037 (int)raw_unixmode));
7039 sbuf = smb_fname->st;
7041 if (!VALID_STAT(sbuf)) {
7043 * The only valid use of this is to create character and block
7044 * devices, and named pipes. This is deprecated (IMHO) and
7045 * a new info level should be used for mknod. JRA.
7048 status = smb_unix_mknod(conn,
7049 pdata,
7050 total_data,
7051 smb_fname);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return status;
7056 status = copy_smb_filename(talloc_tos(), smb_fname,
7057 &smb_fname_tmp);
7058 if (!NT_STATUS_IS_OK(status)) {
7059 return status;
7062 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7063 status = map_nt_error_from_unix(errno);
7064 TALLOC_FREE(smb_fname_tmp);
7065 SMB_VFS_UNLINK(conn, smb_fname);
7066 return status;
7069 sbuf = smb_fname_tmp->st;
7070 smb_fname = smb_fname_tmp;
7072 /* Ensure we don't try and change anything else. */
7073 raw_unixmode = SMB_MODE_NO_CHANGE;
7074 size = get_file_size_stat(&sbuf);
7075 ft.atime = sbuf.st_ex_atime;
7076 ft.mtime = sbuf.st_ex_mtime;
7078 * We continue here as we might want to change the
7079 * owner uid/gid.
7081 delete_on_fail = True;
7084 #if 1
7085 /* Horrible backwards compatibility hack as an old server bug
7086 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7087 * */
7089 if (!size) {
7090 size = get_file_size_stat(&sbuf);
7092 #endif
7095 * Deal with the UNIX specific mode set.
7098 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7099 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7100 "setting mode 0%o for file %s\n",
7101 (unsigned int)unixmode,
7102 smb_fname_str_dbg(smb_fname)));
7103 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7104 return map_nt_error_from_unix(errno);
7109 * Deal with the UNIX specific uid set.
7112 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7113 (sbuf.st_ex_uid != set_owner)) {
7114 int ret;
7116 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7117 "changing owner %u for path %s\n",
7118 (unsigned int)set_owner,
7119 smb_fname_str_dbg(smb_fname)));
7121 if (S_ISLNK(sbuf.st_ex_mode)) {
7122 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7123 set_owner, (gid_t)-1);
7124 } else {
7125 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7126 set_owner, (gid_t)-1);
7129 if (ret != 0) {
7130 status = map_nt_error_from_unix(errno);
7131 if (delete_on_fail) {
7132 SMB_VFS_UNLINK(conn, smb_fname);
7134 return status;
7139 * Deal with the UNIX specific gid set.
7142 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7143 (sbuf.st_ex_gid != set_grp)) {
7144 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7145 "changing group %u for file %s\n",
7146 (unsigned int)set_owner,
7147 smb_fname_str_dbg(smb_fname)));
7148 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7149 set_grp) != 0) {
7150 status = map_nt_error_from_unix(errno);
7151 if (delete_on_fail) {
7152 SMB_VFS_UNLINK(conn, smb_fname);
7154 return status;
7158 /* Deal with any size changes. */
7160 status = smb_set_file_size(conn, req,
7161 fsp,
7162 smb_fname,
7163 &sbuf,
7164 size,
7165 false);
7166 if (!NT_STATUS_IS_OK(status)) {
7167 return status;
7170 /* Deal with any time changes. */
7171 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7172 /* No change, don't cancel anything. */
7173 return status;
7176 id = vfs_file_id_from_sbuf(conn, &sbuf);
7177 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7178 all_fsps = file_find_di_next(all_fsps)) {
7180 * We're setting the time explicitly for UNIX.
7181 * Cancel any pending changes over all handles.
7183 all_fsps->update_write_time_on_close = false;
7184 TALLOC_FREE(all_fsps->update_write_time_event);
7188 * Override the "setting_write_time"
7189 * parameter here as it almost does what
7190 * we need. Just remember if we modified
7191 * mtime and send the notify ourselves.
7193 if (null_timespec(ft.mtime)) {
7194 modify_mtime = false;
7197 status = smb_set_file_time(conn,
7198 fsp,
7199 smb_fname,
7200 &ft,
7201 false);
7202 if (modify_mtime) {
7203 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7204 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7206 return status;
7209 /****************************************************************************
7210 Deal with SMB_SET_FILE_UNIX_INFO2.
7211 ****************************************************************************/
7213 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7214 struct smb_request *req,
7215 const char *pdata,
7216 int total_data,
7217 files_struct *fsp,
7218 const struct smb_filename *smb_fname)
7220 NTSTATUS status;
7221 uint32 smb_fflags;
7222 uint32 smb_fmask;
7224 if (total_data < 116) {
7225 return NT_STATUS_INVALID_PARAMETER;
7228 /* Start by setting all the fields that are common between UNIX_BASIC
7229 * and UNIX_INFO2.
7231 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7232 fsp, smb_fname);
7233 if (!NT_STATUS_IS_OK(status)) {
7234 return status;
7237 smb_fflags = IVAL(pdata, 108);
7238 smb_fmask = IVAL(pdata, 112);
7240 /* NB: We should only attempt to alter the file flags if the client
7241 * sends a non-zero mask.
7243 if (smb_fmask != 0) {
7244 int stat_fflags = 0;
7246 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7247 smb_fmask, &stat_fflags)) {
7248 /* Client asked to alter a flag we don't understand. */
7249 return NT_STATUS_INVALID_PARAMETER;
7252 if (fsp && fsp->fh->fd != -1) {
7253 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7254 return NT_STATUS_NOT_SUPPORTED;
7255 } else {
7256 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7257 stat_fflags) != 0) {
7258 return map_nt_error_from_unix(errno);
7263 /* XXX: need to add support for changing the create_time here. You
7264 * can do this for paths on Darwin with setattrlist(2). The right way
7265 * to hook this up is probably by extending the VFS utimes interface.
7268 return NT_STATUS_OK;
7271 /****************************************************************************
7272 Create a directory with POSIX semantics.
7273 ****************************************************************************/
7275 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7276 struct smb_request *req,
7277 char **ppdata,
7278 int total_data,
7279 struct smb_filename *smb_fname,
7280 int *pdata_return_size)
7282 NTSTATUS status = NT_STATUS_OK;
7283 uint32 raw_unixmode = 0;
7284 uint32 mod_unixmode = 0;
7285 mode_t unixmode = (mode_t)0;
7286 files_struct *fsp = NULL;
7287 uint16 info_level_return = 0;
7288 int info;
7289 char *pdata = *ppdata;
7291 if (total_data < 18) {
7292 return NT_STATUS_INVALID_PARAMETER;
7295 raw_unixmode = IVAL(pdata,8);
7296 /* Next 4 bytes are not yet defined. */
7298 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7299 PERM_NEW_DIR, &unixmode);
7300 if (!NT_STATUS_IS_OK(status)) {
7301 return status;
7304 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7306 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7307 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7309 status = SMB_VFS_CREATE_FILE(
7310 conn, /* conn */
7311 req, /* req */
7312 0, /* root_dir_fid */
7313 smb_fname, /* fname */
7314 FILE_READ_ATTRIBUTES, /* access_mask */
7315 FILE_SHARE_NONE, /* share_access */
7316 FILE_CREATE, /* create_disposition*/
7317 FILE_DIRECTORY_FILE, /* create_options */
7318 mod_unixmode, /* file_attributes */
7319 0, /* oplock_request */
7320 0, /* allocation_size */
7321 0, /* private_flags */
7322 NULL, /* sd */
7323 NULL, /* ea_list */
7324 &fsp, /* result */
7325 &info); /* pinfo */
7327 if (NT_STATUS_IS_OK(status)) {
7328 close_file(req, fsp, NORMAL_CLOSE);
7331 info_level_return = SVAL(pdata,16);
7333 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7334 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7335 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7336 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7337 } else {
7338 *pdata_return_size = 12;
7341 /* Realloc the data size */
7342 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7343 if (*ppdata == NULL) {
7344 *pdata_return_size = 0;
7345 return NT_STATUS_NO_MEMORY;
7347 pdata = *ppdata;
7349 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7350 SSVAL(pdata,2,0); /* No fnum. */
7351 SIVAL(pdata,4,info); /* Was directory created. */
7353 switch (info_level_return) {
7354 case SMB_QUERY_FILE_UNIX_BASIC:
7355 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7356 SSVAL(pdata,10,0); /* Padding. */
7357 store_file_unix_basic(conn, pdata + 12, fsp,
7358 &smb_fname->st);
7359 break;
7360 case SMB_QUERY_FILE_UNIX_INFO2:
7361 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7362 SSVAL(pdata,10,0); /* Padding. */
7363 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7364 &smb_fname->st);
7365 break;
7366 default:
7367 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7368 SSVAL(pdata,10,0); /* Padding. */
7369 break;
7372 return status;
7375 /****************************************************************************
7376 Open/Create a file with POSIX semantics.
7377 ****************************************************************************/
7379 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7380 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7382 static NTSTATUS smb_posix_open(connection_struct *conn,
7383 struct smb_request *req,
7384 char **ppdata,
7385 int total_data,
7386 struct smb_filename *smb_fname,
7387 int *pdata_return_size)
7389 bool extended_oplock_granted = False;
7390 char *pdata = *ppdata;
7391 uint32 flags = 0;
7392 uint32 wire_open_mode = 0;
7393 uint32 raw_unixmode = 0;
7394 uint32 mod_unixmode = 0;
7395 uint32 create_disp = 0;
7396 uint32 access_mask = 0;
7397 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7398 NTSTATUS status = NT_STATUS_OK;
7399 mode_t unixmode = (mode_t)0;
7400 files_struct *fsp = NULL;
7401 int oplock_request = 0;
7402 int info = 0;
7403 uint16 info_level_return = 0;
7405 if (total_data < 18) {
7406 return NT_STATUS_INVALID_PARAMETER;
7409 flags = IVAL(pdata,0);
7410 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7411 if (oplock_request) {
7412 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7415 wire_open_mode = IVAL(pdata,4);
7417 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7418 return smb_posix_mkdir(conn, req,
7419 ppdata,
7420 total_data,
7421 smb_fname,
7422 pdata_return_size);
7425 switch (wire_open_mode & SMB_ACCMODE) {
7426 case SMB_O_RDONLY:
7427 access_mask = SMB_O_RDONLY_MAPPING;
7428 break;
7429 case SMB_O_WRONLY:
7430 access_mask = SMB_O_WRONLY_MAPPING;
7431 break;
7432 case SMB_O_RDWR:
7433 access_mask = (SMB_O_RDONLY_MAPPING|
7434 SMB_O_WRONLY_MAPPING);
7435 break;
7436 default:
7437 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7438 (unsigned int)wire_open_mode ));
7439 return NT_STATUS_INVALID_PARAMETER;
7442 wire_open_mode &= ~SMB_ACCMODE;
7444 /* First take care of O_CREAT|O_EXCL interactions. */
7445 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7446 case (SMB_O_CREAT | SMB_O_EXCL):
7447 /* File exists fail. File not exist create. */
7448 create_disp = FILE_CREATE;
7449 break;
7450 case SMB_O_CREAT:
7451 /* File exists open. File not exist create. */
7452 create_disp = FILE_OPEN_IF;
7453 break;
7454 case SMB_O_EXCL:
7455 /* O_EXCL on its own without O_CREAT is undefined.
7456 We deliberately ignore it as some versions of
7457 Linux CIFSFS can send a bare O_EXCL on the
7458 wire which other filesystems in the kernel
7459 ignore. See bug 9519 for details. */
7461 /* Fallthrough. */
7463 case 0:
7464 /* File exists open. File not exist fail. */
7465 create_disp = FILE_OPEN;
7466 break;
7467 default:
7468 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7469 (unsigned int)wire_open_mode ));
7470 return NT_STATUS_INVALID_PARAMETER;
7473 /* Next factor in the effects of O_TRUNC. */
7474 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7476 if (wire_open_mode & SMB_O_TRUNC) {
7477 switch (create_disp) {
7478 case FILE_CREATE:
7479 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7480 /* Leave create_disp alone as
7481 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7483 /* File exists fail. File not exist create. */
7484 break;
7485 case FILE_OPEN_IF:
7486 /* SMB_O_CREAT | SMB_O_TRUNC */
7487 /* File exists overwrite. File not exist create. */
7488 create_disp = FILE_OVERWRITE_IF;
7489 break;
7490 case FILE_OPEN:
7491 /* SMB_O_TRUNC */
7492 /* File exists overwrite. File not exist fail. */
7493 create_disp = FILE_OVERWRITE;
7494 break;
7495 default:
7496 /* Cannot get here. */
7497 smb_panic("smb_posix_open: logic error");
7498 return NT_STATUS_INVALID_PARAMETER;
7502 raw_unixmode = IVAL(pdata,8);
7503 /* Next 4 bytes are not yet defined. */
7505 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7506 (VALID_STAT(smb_fname->st) ?
7507 PERM_EXISTING_FILE : PERM_NEW_FILE),
7508 &unixmode);
7510 if (!NT_STATUS_IS_OK(status)) {
7511 return status;
7514 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7516 if (wire_open_mode & SMB_O_SYNC) {
7517 create_options |= FILE_WRITE_THROUGH;
7519 if (wire_open_mode & SMB_O_APPEND) {
7520 access_mask |= FILE_APPEND_DATA;
7522 if (wire_open_mode & SMB_O_DIRECT) {
7523 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7526 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7527 VALID_STAT_OF_DIR(smb_fname->st)) {
7528 if (access_mask != SMB_O_RDONLY_MAPPING) {
7529 return NT_STATUS_FILE_IS_A_DIRECTORY;
7531 create_options &= ~FILE_NON_DIRECTORY_FILE;
7532 create_options |= FILE_DIRECTORY_FILE;
7535 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7536 smb_fname_str_dbg(smb_fname),
7537 (unsigned int)wire_open_mode,
7538 (unsigned int)unixmode ));
7540 status = SMB_VFS_CREATE_FILE(
7541 conn, /* conn */
7542 req, /* req */
7543 0, /* root_dir_fid */
7544 smb_fname, /* fname */
7545 access_mask, /* access_mask */
7546 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7547 FILE_SHARE_DELETE),
7548 create_disp, /* create_disposition*/
7549 create_options, /* create_options */
7550 mod_unixmode, /* file_attributes */
7551 oplock_request, /* oplock_request */
7552 0, /* allocation_size */
7553 0, /* private_flags */
7554 NULL, /* sd */
7555 NULL, /* ea_list */
7556 &fsp, /* result */
7557 &info); /* pinfo */
7559 if (!NT_STATUS_IS_OK(status)) {
7560 return status;
7563 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7564 extended_oplock_granted = True;
7567 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7568 extended_oplock_granted = True;
7571 info_level_return = SVAL(pdata,16);
7573 /* Allocate the correct return size. */
7575 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7576 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7577 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7578 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7579 } else {
7580 *pdata_return_size = 12;
7583 /* Realloc the data size */
7584 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7585 if (*ppdata == NULL) {
7586 close_file(req, fsp, ERROR_CLOSE);
7587 *pdata_return_size = 0;
7588 return NT_STATUS_NO_MEMORY;
7590 pdata = *ppdata;
7592 if (extended_oplock_granted) {
7593 if (flags & REQUEST_BATCH_OPLOCK) {
7594 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7595 } else {
7596 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7598 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7599 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7600 } else {
7601 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7604 SSVAL(pdata,2,fsp->fnum);
7605 SIVAL(pdata,4,info); /* Was file created etc. */
7607 switch (info_level_return) {
7608 case SMB_QUERY_FILE_UNIX_BASIC:
7609 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7610 SSVAL(pdata,10,0); /* padding. */
7611 store_file_unix_basic(conn, pdata + 12, fsp,
7612 &smb_fname->st);
7613 break;
7614 case SMB_QUERY_FILE_UNIX_INFO2:
7615 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7616 SSVAL(pdata,10,0); /* padding. */
7617 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7618 &smb_fname->st);
7619 break;
7620 default:
7621 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7622 SSVAL(pdata,10,0); /* padding. */
7623 break;
7625 return NT_STATUS_OK;
7628 /****************************************************************************
7629 Delete a file with POSIX semantics.
7630 ****************************************************************************/
7632 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7633 struct smb_request *req,
7634 const char *pdata,
7635 int total_data,
7636 struct smb_filename *smb_fname)
7638 NTSTATUS status = NT_STATUS_OK;
7639 files_struct *fsp = NULL;
7640 uint16 flags = 0;
7641 char del = 1;
7642 int info = 0;
7643 int create_options = 0;
7644 int i;
7645 struct share_mode_lock *lck = NULL;
7647 if (total_data < 2) {
7648 return NT_STATUS_INVALID_PARAMETER;
7651 flags = SVAL(pdata,0);
7653 if (!VALID_STAT(smb_fname->st)) {
7654 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7657 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7658 !VALID_STAT_OF_DIR(smb_fname->st)) {
7659 return NT_STATUS_NOT_A_DIRECTORY;
7662 DEBUG(10,("smb_posix_unlink: %s %s\n",
7663 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7664 smb_fname_str_dbg(smb_fname)));
7666 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7667 create_options |= FILE_DIRECTORY_FILE;
7670 status = SMB_VFS_CREATE_FILE(
7671 conn, /* conn */
7672 req, /* req */
7673 0, /* root_dir_fid */
7674 smb_fname, /* fname */
7675 DELETE_ACCESS, /* access_mask */
7676 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7677 FILE_SHARE_DELETE),
7678 FILE_OPEN, /* create_disposition*/
7679 create_options, /* create_options */
7680 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7681 0, /* oplock_request */
7682 0, /* allocation_size */
7683 0, /* private_flags */
7684 NULL, /* sd */
7685 NULL, /* ea_list */
7686 &fsp, /* result */
7687 &info); /* pinfo */
7689 if (!NT_STATUS_IS_OK(status)) {
7690 return status;
7694 * Don't lie to client. If we can't really delete due to
7695 * non-POSIX opens return SHARING_VIOLATION.
7698 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7699 if (lck == NULL) {
7700 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7701 "lock for file %s\n", fsp_str_dbg(fsp)));
7702 close_file(req, fsp, NORMAL_CLOSE);
7703 return NT_STATUS_INVALID_PARAMETER;
7707 * See if others still have the file open. If this is the case, then
7708 * don't delete. If all opens are POSIX delete we can set the delete
7709 * on close disposition.
7711 for (i=0; i<lck->data->num_share_modes; i++) {
7712 struct share_mode_entry *e = &lck->data->share_modes[i];
7713 if (is_valid_share_mode_entry(e)) {
7714 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7715 continue;
7717 if (share_mode_stale_pid(lck->data, i)) {
7718 continue;
7720 /* Fail with sharing violation. */
7721 TALLOC_FREE(lck);
7722 close_file(req, fsp, NORMAL_CLOSE);
7723 return NT_STATUS_SHARING_VIOLATION;
7728 * Set the delete on close.
7730 status = smb_set_file_disposition_info(conn,
7731 &del,
7733 fsp,
7734 smb_fname);
7736 TALLOC_FREE(lck);
7738 if (!NT_STATUS_IS_OK(status)) {
7739 close_file(req, fsp, NORMAL_CLOSE);
7740 return status;
7742 return close_file(req, fsp, NORMAL_CLOSE);
7745 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7746 struct smb_request *req,
7747 TALLOC_CTX *mem_ctx,
7748 uint16_t info_level,
7749 files_struct *fsp,
7750 struct smb_filename *smb_fname,
7751 char **ppdata, int total_data,
7752 int *ret_data_size)
7754 char *pdata = *ppdata;
7755 NTSTATUS status = NT_STATUS_OK;
7756 int data_return_size = 0;
7758 *ret_data_size = 0;
7760 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7761 return NT_STATUS_INVALID_LEVEL;
7764 if (!CAN_WRITE(conn)) {
7765 /* Allow POSIX opens. The open path will deny
7766 * any non-readonly opens. */
7767 if (info_level != SMB_POSIX_PATH_OPEN) {
7768 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7772 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7773 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7774 fsp_fnum_dbg(fsp),
7775 info_level, total_data));
7777 switch (info_level) {
7779 case SMB_INFO_STANDARD:
7781 status = smb_set_info_standard(conn,
7782 pdata,
7783 total_data,
7784 fsp,
7785 smb_fname);
7786 break;
7789 case SMB_INFO_SET_EA:
7791 status = smb_info_set_ea(conn,
7792 pdata,
7793 total_data,
7794 fsp,
7795 smb_fname);
7796 break;
7799 case SMB_SET_FILE_BASIC_INFO:
7800 case SMB_FILE_BASIC_INFORMATION:
7802 status = smb_set_file_basic_info(conn,
7803 pdata,
7804 total_data,
7805 fsp,
7806 smb_fname);
7807 break;
7810 case SMB_FILE_ALLOCATION_INFORMATION:
7811 case SMB_SET_FILE_ALLOCATION_INFO:
7813 status = smb_set_file_allocation_info(conn, req,
7814 pdata,
7815 total_data,
7816 fsp,
7817 smb_fname);
7818 break;
7821 case SMB_FILE_END_OF_FILE_INFORMATION:
7822 case SMB_SET_FILE_END_OF_FILE_INFO:
7825 * XP/Win7 both fail after the createfile with
7826 * SMB_SET_FILE_END_OF_FILE_INFO but not
7827 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7828 * The level is known here, so pass it down
7829 * appropriately.
7831 bool should_fail =
7832 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7834 status = smb_set_file_end_of_file_info(conn, req,
7835 pdata,
7836 total_data,
7837 fsp,
7838 smb_fname,
7839 should_fail);
7840 break;
7843 case SMB_FILE_DISPOSITION_INFORMATION:
7844 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7846 #if 0
7847 /* JRA - We used to just ignore this on a path ?
7848 * Shouldn't this be invalid level on a pathname
7849 * based call ?
7851 if (tran_call != TRANSACT2_SETFILEINFO) {
7852 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7854 #endif
7855 status = smb_set_file_disposition_info(conn,
7856 pdata,
7857 total_data,
7858 fsp,
7859 smb_fname);
7860 break;
7863 case SMB_FILE_POSITION_INFORMATION:
7865 status = smb_file_position_information(conn,
7866 pdata,
7867 total_data,
7868 fsp);
7869 break;
7872 case SMB_FILE_FULL_EA_INFORMATION:
7874 status = smb_set_file_full_ea_info(conn,
7875 pdata,
7876 total_data,
7877 fsp);
7878 break;
7881 /* From tridge Samba4 :
7882 * MODE_INFORMATION in setfileinfo (I have no
7883 * idea what "mode information" on a file is - it takes a value of 0,
7884 * 2, 4 or 6. What could it be?).
7887 case SMB_FILE_MODE_INFORMATION:
7889 status = smb_file_mode_information(conn,
7890 pdata,
7891 total_data);
7892 break;
7896 * CIFS UNIX extensions.
7899 case SMB_SET_FILE_UNIX_BASIC:
7901 status = smb_set_file_unix_basic(conn, req,
7902 pdata,
7903 total_data,
7904 fsp,
7905 smb_fname);
7906 break;
7909 case SMB_SET_FILE_UNIX_INFO2:
7911 status = smb_set_file_unix_info2(conn, req,
7912 pdata,
7913 total_data,
7914 fsp,
7915 smb_fname);
7916 break;
7919 case SMB_SET_FILE_UNIX_LINK:
7921 if (fsp) {
7922 /* We must have a pathname for this. */
7923 return NT_STATUS_INVALID_LEVEL;
7925 status = smb_set_file_unix_link(conn, req, pdata,
7926 total_data, smb_fname);
7927 break;
7930 case SMB_SET_FILE_UNIX_HLINK:
7932 if (fsp) {
7933 /* We must have a pathname for this. */
7934 return NT_STATUS_INVALID_LEVEL;
7936 status = smb_set_file_unix_hlink(conn, req,
7937 pdata, total_data,
7938 smb_fname);
7939 break;
7942 case SMB_FILE_RENAME_INFORMATION:
7944 status = smb_file_rename_information(conn, req,
7945 pdata, total_data,
7946 fsp, smb_fname);
7947 break;
7950 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7952 /* SMB2 rename information. */
7953 status = smb2_file_rename_information(conn, req,
7954 pdata, total_data,
7955 fsp, smb_fname);
7956 break;
7959 case SMB_FILE_LINK_INFORMATION:
7961 status = smb_file_link_information(conn, req,
7962 pdata, total_data,
7963 fsp, smb_fname);
7964 break;
7967 #if defined(HAVE_POSIX_ACLS)
7968 case SMB_SET_POSIX_ACL:
7970 status = smb_set_posix_acl(conn,
7971 pdata,
7972 total_data,
7973 fsp,
7974 smb_fname);
7975 break;
7977 #endif
7979 case SMB_SET_POSIX_LOCK:
7981 if (!fsp) {
7982 return NT_STATUS_INVALID_LEVEL;
7984 status = smb_set_posix_lock(conn, req,
7985 pdata, total_data, fsp);
7986 break;
7989 case SMB_POSIX_PATH_OPEN:
7991 if (fsp) {
7992 /* We must have a pathname for this. */
7993 return NT_STATUS_INVALID_LEVEL;
7996 status = smb_posix_open(conn, req,
7997 ppdata,
7998 total_data,
7999 smb_fname,
8000 &data_return_size);
8001 break;
8004 case SMB_POSIX_PATH_UNLINK:
8006 if (fsp) {
8007 /* We must have a pathname for this. */
8008 return NT_STATUS_INVALID_LEVEL;
8011 status = smb_posix_unlink(conn, req,
8012 pdata,
8013 total_data,
8014 smb_fname);
8015 break;
8018 default:
8019 return NT_STATUS_INVALID_LEVEL;
8022 if (!NT_STATUS_IS_OK(status)) {
8023 return status;
8026 *ret_data_size = data_return_size;
8027 return NT_STATUS_OK;
8030 /****************************************************************************
8031 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8032 ****************************************************************************/
8034 static void call_trans2setfilepathinfo(connection_struct *conn,
8035 struct smb_request *req,
8036 unsigned int tran_call,
8037 char **pparams, int total_params,
8038 char **ppdata, int total_data,
8039 unsigned int max_data_bytes)
8041 char *params = *pparams;
8042 char *pdata = *ppdata;
8043 uint16 info_level;
8044 struct smb_filename *smb_fname = NULL;
8045 files_struct *fsp = NULL;
8046 NTSTATUS status = NT_STATUS_OK;
8047 int data_return_size = 0;
8049 if (!params) {
8050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8051 return;
8054 if (tran_call == TRANSACT2_SETFILEINFO) {
8055 if (total_params < 4) {
8056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8057 return;
8060 fsp = file_fsp(req, SVAL(params,0));
8061 /* Basic check for non-null fsp. */
8062 if (!check_fsp_open(conn, req, fsp)) {
8063 return;
8065 info_level = SVAL(params,2);
8067 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8068 &smb_fname);
8069 if (!NT_STATUS_IS_OK(status)) {
8070 reply_nterror(req, status);
8071 return;
8074 if(fsp->fh->fd == -1) {
8076 * This is actually a SETFILEINFO on a directory
8077 * handle (returned from an NT SMB). NT5.0 seems
8078 * to do this call. JRA.
8080 if (INFO_LEVEL_IS_UNIX(info_level)) {
8081 /* Always do lstat for UNIX calls. */
8082 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8083 DEBUG(3,("call_trans2setfilepathinfo: "
8084 "SMB_VFS_LSTAT of %s failed "
8085 "(%s)\n",
8086 smb_fname_str_dbg(smb_fname),
8087 strerror(errno)));
8088 reply_nterror(req, map_nt_error_from_unix(errno));
8089 return;
8091 } else {
8092 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8093 DEBUG(3,("call_trans2setfilepathinfo: "
8094 "fileinfo of %s failed (%s)\n",
8095 smb_fname_str_dbg(smb_fname),
8096 strerror(errno)));
8097 reply_nterror(req, map_nt_error_from_unix(errno));
8098 return;
8101 } else if (fsp->print_file) {
8103 * Doing a DELETE_ON_CLOSE should cancel a print job.
8105 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8106 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8108 DEBUG(3,("call_trans2setfilepathinfo: "
8109 "Cancelling print job (%s)\n",
8110 fsp_str_dbg(fsp)));
8112 SSVAL(params,0,0);
8113 send_trans2_replies(conn, req, params, 2,
8114 *ppdata, 0,
8115 max_data_bytes);
8116 return;
8117 } else {
8118 reply_nterror(req,
8119 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8120 return;
8122 } else {
8124 * Original code - this is an open file.
8126 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8127 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8128 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8129 strerror(errno)));
8130 reply_nterror(req, map_nt_error_from_unix(errno));
8131 return;
8134 } else {
8135 char *fname = NULL;
8136 uint32_t ucf_flags = 0;
8138 /* set path info */
8139 if (total_params < 7) {
8140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 return;
8144 info_level = SVAL(params,0);
8145 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8146 total_params - 6, STR_TERMINATE,
8147 &status);
8148 if (!NT_STATUS_IS_OK(status)) {
8149 reply_nterror(req, status);
8150 return;
8153 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8154 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8155 info_level == SMB_FILE_RENAME_INFORMATION ||
8156 info_level == SMB_POSIX_PATH_UNLINK) {
8157 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8160 status = filename_convert(req, conn,
8161 req->flags2 & FLAGS2_DFS_PATHNAMES,
8162 fname,
8163 ucf_flags,
8164 NULL,
8165 &smb_fname);
8166 if (!NT_STATUS_IS_OK(status)) {
8167 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8168 reply_botherror(req,
8169 NT_STATUS_PATH_NOT_COVERED,
8170 ERRSRV, ERRbadpath);
8171 return;
8173 reply_nterror(req, status);
8174 return;
8177 if (INFO_LEVEL_IS_UNIX(info_level)) {
8179 * For CIFS UNIX extensions the target name may not exist.
8182 /* Always do lstat for UNIX calls. */
8183 SMB_VFS_LSTAT(conn, smb_fname);
8185 } else if (!VALID_STAT(smb_fname->st) &&
8186 SMB_VFS_STAT(conn, smb_fname)) {
8187 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8188 "%s failed (%s)\n",
8189 smb_fname_str_dbg(smb_fname),
8190 strerror(errno)));
8191 reply_nterror(req, map_nt_error_from_unix(errno));
8192 return;
8196 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8197 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8198 fsp_fnum_dbg(fsp),
8199 info_level,total_data));
8201 /* Realloc the parameter size */
8202 *pparams = (char *)SMB_REALLOC(*pparams,2);
8203 if (*pparams == NULL) {
8204 reply_nterror(req, NT_STATUS_NO_MEMORY);
8205 return;
8207 params = *pparams;
8209 SSVAL(params,0,0);
8211 status = smbd_do_setfilepathinfo(conn, req, req,
8212 info_level,
8213 fsp,
8214 smb_fname,
8215 ppdata, total_data,
8216 &data_return_size);
8217 if (!NT_STATUS_IS_OK(status)) {
8218 if (open_was_deferred(req->sconn, req->mid)) {
8219 /* We have re-scheduled this call. */
8220 return;
8222 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8223 /* We have re-scheduled this call. */
8224 return;
8226 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8227 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8228 ERRSRV, ERRbadpath);
8229 return;
8231 if (info_level == SMB_POSIX_PATH_OPEN) {
8232 reply_openerror(req, status);
8233 return;
8236 reply_nterror(req, status);
8237 return;
8240 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8241 max_data_bytes);
8243 return;
8246 /****************************************************************************
8247 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8248 ****************************************************************************/
8250 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8251 char **pparams, int total_params,
8252 char **ppdata, int total_data,
8253 unsigned int max_data_bytes)
8255 struct smb_filename *smb_dname = NULL;
8256 char *params = *pparams;
8257 char *pdata = *ppdata;
8258 char *directory = NULL;
8259 NTSTATUS status = NT_STATUS_OK;
8260 struct ea_list *ea_list = NULL;
8261 TALLOC_CTX *ctx = talloc_tos();
8263 if (!CAN_WRITE(conn)) {
8264 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8265 return;
8268 if (total_params < 5) {
8269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8270 return;
8273 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8274 total_params - 4, STR_TERMINATE,
8275 &status);
8276 if (!NT_STATUS_IS_OK(status)) {
8277 reply_nterror(req, status);
8278 return;
8281 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8283 status = filename_convert(ctx,
8284 conn,
8285 req->flags2 & FLAGS2_DFS_PATHNAMES,
8286 directory,
8288 NULL,
8289 &smb_dname);
8291 if (!NT_STATUS_IS_OK(status)) {
8292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8293 reply_botherror(req,
8294 NT_STATUS_PATH_NOT_COVERED,
8295 ERRSRV, ERRbadpath);
8296 return;
8298 reply_nterror(req, status);
8299 return;
8303 * OS/2 workplace shell seems to send SET_EA requests of "null"
8304 * length (4 bytes containing IVAL 4).
8305 * They seem to have no effect. Bug #3212. JRA.
8308 if (total_data && (total_data != 4)) {
8309 /* Any data in this call is an EA list. */
8310 if (total_data < 10) {
8311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8312 goto out;
8315 if (IVAL(pdata,0) > total_data) {
8316 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8317 IVAL(pdata,0), (unsigned int)total_data));
8318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8319 goto out;
8322 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8323 total_data - 4);
8324 if (!ea_list) {
8325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8326 goto out;
8329 if (!lp_ea_support(SNUM(conn))) {
8330 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8331 goto out;
8334 /* If total_data == 4 Windows doesn't care what values
8335 * are placed in that field, it just ignores them.
8336 * The System i QNTC IBM SMB client puts bad values here,
8337 * so ignore them. */
8339 status = create_directory(conn, req, smb_dname);
8341 if (!NT_STATUS_IS_OK(status)) {
8342 reply_nterror(req, status);
8343 goto out;
8346 /* Try and set any given EA. */
8347 if (ea_list) {
8348 status = set_ea(conn, NULL, smb_dname, ea_list);
8349 if (!NT_STATUS_IS_OK(status)) {
8350 reply_nterror(req, status);
8351 goto out;
8355 /* Realloc the parameter and data sizes */
8356 *pparams = (char *)SMB_REALLOC(*pparams,2);
8357 if(*pparams == NULL) {
8358 reply_nterror(req, NT_STATUS_NO_MEMORY);
8359 goto out;
8361 params = *pparams;
8363 SSVAL(params,0,0);
8365 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8367 out:
8368 TALLOC_FREE(smb_dname);
8369 return;
8372 /****************************************************************************
8373 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8374 We don't actually do this - we just send a null response.
8375 ****************************************************************************/
8377 static void call_trans2findnotifyfirst(connection_struct *conn,
8378 struct smb_request *req,
8379 char **pparams, int total_params,
8380 char **ppdata, int total_data,
8381 unsigned int max_data_bytes)
8383 char *params = *pparams;
8384 uint16 info_level;
8386 if (total_params < 6) {
8387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8388 return;
8391 info_level = SVAL(params,4);
8392 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8394 switch (info_level) {
8395 case 1:
8396 case 2:
8397 break;
8398 default:
8399 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8400 return;
8403 /* Realloc the parameter and data sizes */
8404 *pparams = (char *)SMB_REALLOC(*pparams,6);
8405 if (*pparams == NULL) {
8406 reply_nterror(req, NT_STATUS_NO_MEMORY);
8407 return;
8409 params = *pparams;
8411 SSVAL(params,0,fnf_handle);
8412 SSVAL(params,2,0); /* No changes */
8413 SSVAL(params,4,0); /* No EA errors */
8415 fnf_handle++;
8417 if(fnf_handle == 0)
8418 fnf_handle = 257;
8420 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8422 return;
8425 /****************************************************************************
8426 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8427 changes). Currently this does nothing.
8428 ****************************************************************************/
8430 static void call_trans2findnotifynext(connection_struct *conn,
8431 struct smb_request *req,
8432 char **pparams, int total_params,
8433 char **ppdata, int total_data,
8434 unsigned int max_data_bytes)
8436 char *params = *pparams;
8438 DEBUG(3,("call_trans2findnotifynext\n"));
8440 /* Realloc the parameter and data sizes */
8441 *pparams = (char *)SMB_REALLOC(*pparams,4);
8442 if (*pparams == NULL) {
8443 reply_nterror(req, NT_STATUS_NO_MEMORY);
8444 return;
8446 params = *pparams;
8448 SSVAL(params,0,0); /* No changes */
8449 SSVAL(params,2,0); /* No EA errors */
8451 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8453 return;
8456 /****************************************************************************
8457 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8458 ****************************************************************************/
8460 static void call_trans2getdfsreferral(connection_struct *conn,
8461 struct smb_request *req,
8462 char **pparams, int total_params,
8463 char **ppdata, int total_data,
8464 unsigned int max_data_bytes)
8466 char *params = *pparams;
8467 char *pathname = NULL;
8468 int reply_size = 0;
8469 int max_referral_level;
8470 NTSTATUS status = NT_STATUS_OK;
8471 TALLOC_CTX *ctx = talloc_tos();
8473 DEBUG(10,("call_trans2getdfsreferral\n"));
8475 if (total_params < 3) {
8476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8477 return;
8480 max_referral_level = SVAL(params,0);
8482 if(!lp_host_msdfs()) {
8483 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8484 return;
8487 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8488 total_params - 2, STR_TERMINATE);
8489 if (!pathname) {
8490 reply_nterror(req, NT_STATUS_NOT_FOUND);
8491 return;
8493 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8494 ppdata,&status)) < 0) {
8495 reply_nterror(req, status);
8496 return;
8499 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8500 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8501 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8503 return;
8506 #define LMCAT_SPL 0x53
8507 #define LMFUNC_GETJOBID 0x60
8509 /****************************************************************************
8510 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8511 ****************************************************************************/
8513 static void call_trans2ioctl(connection_struct *conn,
8514 struct smb_request *req,
8515 char **pparams, int total_params,
8516 char **ppdata, int total_data,
8517 unsigned int max_data_bytes)
8519 char *pdata = *ppdata;
8520 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8522 /* check for an invalid fid before proceeding */
8524 if (!fsp) {
8525 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8526 return;
8529 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8530 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8531 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8532 if (*ppdata == NULL) {
8533 reply_nterror(req, NT_STATUS_NO_MEMORY);
8534 return;
8536 pdata = *ppdata;
8538 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8539 CAN ACCEPT THIS IN UNICODE. JRA. */
8541 /* Job number */
8542 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8544 srvstr_push(pdata, req->flags2, pdata + 2,
8545 lp_netbios_name(), 15,
8546 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8547 srvstr_push(pdata, req->flags2, pdata+18,
8548 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8549 STR_ASCII|STR_TERMINATE); /* Service name */
8550 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8551 max_data_bytes);
8552 return;
8555 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8556 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8559 /****************************************************************************
8560 Reply to a SMBfindclose (stop trans2 directory search).
8561 ****************************************************************************/
8563 void reply_findclose(struct smb_request *req)
8565 int dptr_num;
8566 struct smbd_server_connection *sconn = req->sconn;
8568 START_PROFILE(SMBfindclose);
8570 if (req->wct < 1) {
8571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8572 END_PROFILE(SMBfindclose);
8573 return;
8576 dptr_num = SVALS(req->vwv+0, 0);
8578 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8580 dptr_close(sconn, &dptr_num);
8582 reply_outbuf(req, 0, 0);
8584 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8586 END_PROFILE(SMBfindclose);
8587 return;
8590 /****************************************************************************
8591 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8592 ****************************************************************************/
8594 void reply_findnclose(struct smb_request *req)
8596 int dptr_num;
8598 START_PROFILE(SMBfindnclose);
8600 if (req->wct < 1) {
8601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8602 END_PROFILE(SMBfindnclose);
8603 return;
8606 dptr_num = SVAL(req->vwv+0, 0);
8608 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8610 /* We never give out valid handles for a
8611 findnotifyfirst - so any dptr_num is ok here.
8612 Just ignore it. */
8614 reply_outbuf(req, 0, 0);
8616 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8618 END_PROFILE(SMBfindnclose);
8619 return;
8622 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8623 struct trans_state *state)
8625 if (get_Protocol() >= PROTOCOL_NT1) {
8626 req->flags2 |= 0x40; /* IS_LONG_NAME */
8627 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8630 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8631 if (state->call != TRANSACT2_QFSINFO &&
8632 state->call != TRANSACT2_SETFSINFO) {
8633 DEBUG(0,("handle_trans2: encryption required "
8634 "with call 0x%x\n",
8635 (unsigned int)state->call));
8636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8637 return;
8641 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8643 /* Now we must call the relevant TRANS2 function */
8644 switch(state->call) {
8645 case TRANSACT2_OPEN:
8647 START_PROFILE(Trans2_open);
8648 call_trans2open(conn, req,
8649 &state->param, state->total_param,
8650 &state->data, state->total_data,
8651 state->max_data_return);
8652 END_PROFILE(Trans2_open);
8653 break;
8656 case TRANSACT2_FINDFIRST:
8658 START_PROFILE(Trans2_findfirst);
8659 call_trans2findfirst(conn, req,
8660 &state->param, state->total_param,
8661 &state->data, state->total_data,
8662 state->max_data_return);
8663 END_PROFILE(Trans2_findfirst);
8664 break;
8667 case TRANSACT2_FINDNEXT:
8669 START_PROFILE(Trans2_findnext);
8670 call_trans2findnext(conn, req,
8671 &state->param, state->total_param,
8672 &state->data, state->total_data,
8673 state->max_data_return);
8674 END_PROFILE(Trans2_findnext);
8675 break;
8678 case TRANSACT2_QFSINFO:
8680 START_PROFILE(Trans2_qfsinfo);
8681 call_trans2qfsinfo(conn, req,
8682 &state->param, state->total_param,
8683 &state->data, state->total_data,
8684 state->max_data_return);
8685 END_PROFILE(Trans2_qfsinfo);
8686 break;
8689 case TRANSACT2_SETFSINFO:
8691 START_PROFILE(Trans2_setfsinfo);
8692 call_trans2setfsinfo(conn, req,
8693 &state->param, state->total_param,
8694 &state->data, state->total_data,
8695 state->max_data_return);
8696 END_PROFILE(Trans2_setfsinfo);
8697 break;
8700 case TRANSACT2_QPATHINFO:
8701 case TRANSACT2_QFILEINFO:
8703 START_PROFILE(Trans2_qpathinfo);
8704 call_trans2qfilepathinfo(conn, req, state->call,
8705 &state->param, state->total_param,
8706 &state->data, state->total_data,
8707 state->max_data_return);
8708 END_PROFILE(Trans2_qpathinfo);
8709 break;
8712 case TRANSACT2_SETPATHINFO:
8713 case TRANSACT2_SETFILEINFO:
8715 START_PROFILE(Trans2_setpathinfo);
8716 call_trans2setfilepathinfo(conn, req, state->call,
8717 &state->param, state->total_param,
8718 &state->data, state->total_data,
8719 state->max_data_return);
8720 END_PROFILE(Trans2_setpathinfo);
8721 break;
8724 case TRANSACT2_FINDNOTIFYFIRST:
8726 START_PROFILE(Trans2_findnotifyfirst);
8727 call_trans2findnotifyfirst(conn, req,
8728 &state->param, state->total_param,
8729 &state->data, state->total_data,
8730 state->max_data_return);
8731 END_PROFILE(Trans2_findnotifyfirst);
8732 break;
8735 case TRANSACT2_FINDNOTIFYNEXT:
8737 START_PROFILE(Trans2_findnotifynext);
8738 call_trans2findnotifynext(conn, req,
8739 &state->param, state->total_param,
8740 &state->data, state->total_data,
8741 state->max_data_return);
8742 END_PROFILE(Trans2_findnotifynext);
8743 break;
8746 case TRANSACT2_MKDIR:
8748 START_PROFILE(Trans2_mkdir);
8749 call_trans2mkdir(conn, req,
8750 &state->param, state->total_param,
8751 &state->data, state->total_data,
8752 state->max_data_return);
8753 END_PROFILE(Trans2_mkdir);
8754 break;
8757 case TRANSACT2_GET_DFS_REFERRAL:
8759 START_PROFILE(Trans2_get_dfs_referral);
8760 call_trans2getdfsreferral(conn, req,
8761 &state->param, state->total_param,
8762 &state->data, state->total_data,
8763 state->max_data_return);
8764 END_PROFILE(Trans2_get_dfs_referral);
8765 break;
8768 case TRANSACT2_IOCTL:
8770 START_PROFILE(Trans2_ioctl);
8771 call_trans2ioctl(conn, req,
8772 &state->param, state->total_param,
8773 &state->data, state->total_data,
8774 state->max_data_return);
8775 END_PROFILE(Trans2_ioctl);
8776 break;
8779 default:
8780 /* Error in request */
8781 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8782 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8786 /****************************************************************************
8787 Reply to a SMBtrans2.
8788 ****************************************************************************/
8790 void reply_trans2(struct smb_request *req)
8792 connection_struct *conn = req->conn;
8793 unsigned int dsoff;
8794 unsigned int dscnt;
8795 unsigned int psoff;
8796 unsigned int pscnt;
8797 unsigned int tran_call;
8798 struct trans_state *state;
8799 NTSTATUS result;
8801 START_PROFILE(SMBtrans2);
8803 if (req->wct < 14) {
8804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8805 END_PROFILE(SMBtrans2);
8806 return;
8809 dsoff = SVAL(req->vwv+12, 0);
8810 dscnt = SVAL(req->vwv+11, 0);
8811 psoff = SVAL(req->vwv+10, 0);
8812 pscnt = SVAL(req->vwv+9, 0);
8813 tran_call = SVAL(req->vwv+14, 0);
8815 result = allow_new_trans(conn->pending_trans, req->mid);
8816 if (!NT_STATUS_IS_OK(result)) {
8817 DEBUG(2, ("Got invalid trans2 request: %s\n",
8818 nt_errstr(result)));
8819 reply_nterror(req, result);
8820 END_PROFILE(SMBtrans2);
8821 return;
8824 if (IS_IPC(conn)) {
8825 switch (tran_call) {
8826 /* List the allowed trans2 calls on IPC$ */
8827 case TRANSACT2_OPEN:
8828 case TRANSACT2_GET_DFS_REFERRAL:
8829 case TRANSACT2_QFILEINFO:
8830 case TRANSACT2_QFSINFO:
8831 case TRANSACT2_SETFSINFO:
8832 break;
8833 default:
8834 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8835 END_PROFILE(SMBtrans2);
8836 return;
8840 if ((state = talloc(conn, struct trans_state)) == NULL) {
8841 DEBUG(0, ("talloc failed\n"));
8842 reply_nterror(req, NT_STATUS_NO_MEMORY);
8843 END_PROFILE(SMBtrans2);
8844 return;
8847 state->cmd = SMBtrans2;
8849 state->mid = req->mid;
8850 state->vuid = req->vuid;
8851 state->setup_count = SVAL(req->vwv+13, 0);
8852 state->setup = NULL;
8853 state->total_param = SVAL(req->vwv+0, 0);
8854 state->param = NULL;
8855 state->total_data = SVAL(req->vwv+1, 0);
8856 state->data = NULL;
8857 state->max_param_return = SVAL(req->vwv+2, 0);
8858 state->max_data_return = SVAL(req->vwv+3, 0);
8859 state->max_setup_return = SVAL(req->vwv+4, 0);
8860 state->close_on_completion = BITSETW(req->vwv+5, 0);
8861 state->one_way = BITSETW(req->vwv+5, 1);
8863 state->call = tran_call;
8865 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8866 is so as a sanity check */
8867 if (state->setup_count != 1) {
8869 * Need to have rc=0 for ioctl to get job id for OS/2.
8870 * Network printing will fail if function is not successful.
8871 * Similar function in reply.c will be used if protocol
8872 * is LANMAN1.0 instead of LM1.2X002.
8873 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8874 * outbuf doesn't have to be set(only job id is used).
8876 if ( (state->setup_count == 4)
8877 && (tran_call == TRANSACT2_IOCTL)
8878 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8879 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8880 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8881 } else {
8882 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8883 DEBUG(2,("Transaction is %d\n",tran_call));
8884 TALLOC_FREE(state);
8885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8886 END_PROFILE(SMBtrans2);
8887 return;
8891 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8892 goto bad_param;
8894 if (state->total_data) {
8896 if (trans_oob(state->total_data, 0, dscnt)
8897 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8898 goto bad_param;
8901 /* Can't use talloc here, the core routines do realloc on the
8902 * params and data. */
8903 state->data = (char *)SMB_MALLOC(state->total_data);
8904 if (state->data == NULL) {
8905 DEBUG(0,("reply_trans2: data malloc fail for %u "
8906 "bytes !\n", (unsigned int)state->total_data));
8907 TALLOC_FREE(state);
8908 reply_nterror(req, NT_STATUS_NO_MEMORY);
8909 END_PROFILE(SMBtrans2);
8910 return;
8913 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8916 if (state->total_param) {
8918 if (trans_oob(state->total_param, 0, pscnt)
8919 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8920 goto bad_param;
8923 /* Can't use talloc here, the core routines do realloc on the
8924 * params and data. */
8925 state->param = (char *)SMB_MALLOC(state->total_param);
8926 if (state->param == NULL) {
8927 DEBUG(0,("reply_trans: param malloc fail for %u "
8928 "bytes !\n", (unsigned int)state->total_param));
8929 SAFE_FREE(state->data);
8930 TALLOC_FREE(state);
8931 reply_nterror(req, NT_STATUS_NO_MEMORY);
8932 END_PROFILE(SMBtrans2);
8933 return;
8936 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8939 state->received_data = dscnt;
8940 state->received_param = pscnt;
8942 if ((state->received_param == state->total_param) &&
8943 (state->received_data == state->total_data)) {
8945 handle_trans2(conn, req, state);
8947 SAFE_FREE(state->data);
8948 SAFE_FREE(state->param);
8949 TALLOC_FREE(state);
8950 END_PROFILE(SMBtrans2);
8951 return;
8954 DLIST_ADD(conn->pending_trans, state);
8956 /* We need to send an interim response then receive the rest
8957 of the parameter/data bytes */
8958 reply_outbuf(req, 0, 0);
8959 show_msg((char *)req->outbuf);
8960 END_PROFILE(SMBtrans2);
8961 return;
8963 bad_param:
8965 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8966 SAFE_FREE(state->data);
8967 SAFE_FREE(state->param);
8968 TALLOC_FREE(state);
8969 END_PROFILE(SMBtrans2);
8970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8974 /****************************************************************************
8975 Reply to a SMBtranss2
8976 ****************************************************************************/
8978 void reply_transs2(struct smb_request *req)
8980 connection_struct *conn = req->conn;
8981 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8982 struct trans_state *state;
8984 START_PROFILE(SMBtranss2);
8986 show_msg((const char *)req->inbuf);
8988 /* Windows clients expect all replies to
8989 a transact secondary (SMBtranss2 0x33)
8990 to have a command code of transact
8991 (SMBtrans2 0x32). See bug #8989
8992 and also [MS-CIFS] section 2.2.4.47.2
8993 for details.
8995 req->cmd = SMBtrans2;
8997 if (req->wct < 8) {
8998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8999 END_PROFILE(SMBtranss2);
9000 return;
9003 for (state = conn->pending_trans; state != NULL;
9004 state = state->next) {
9005 if (state->mid == req->mid) {
9006 break;
9010 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9012 END_PROFILE(SMBtranss2);
9013 return;
9016 /* Revise state->total_param and state->total_data in case they have
9017 changed downwards */
9019 if (SVAL(req->vwv+0, 0) < state->total_param)
9020 state->total_param = SVAL(req->vwv+0, 0);
9021 if (SVAL(req->vwv+1, 0) < state->total_data)
9022 state->total_data = SVAL(req->vwv+1, 0);
9024 pcnt = SVAL(req->vwv+2, 0);
9025 poff = SVAL(req->vwv+3, 0);
9026 pdisp = SVAL(req->vwv+4, 0);
9028 dcnt = SVAL(req->vwv+5, 0);
9029 doff = SVAL(req->vwv+6, 0);
9030 ddisp = SVAL(req->vwv+7, 0);
9032 state->received_param += pcnt;
9033 state->received_data += dcnt;
9035 if ((state->received_data > state->total_data) ||
9036 (state->received_param > state->total_param))
9037 goto bad_param;
9039 if (pcnt) {
9040 if (trans_oob(state->total_param, pdisp, pcnt)
9041 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9042 goto bad_param;
9044 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9047 if (dcnt) {
9048 if (trans_oob(state->total_data, ddisp, dcnt)
9049 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9050 goto bad_param;
9052 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9055 if ((state->received_param < state->total_param) ||
9056 (state->received_data < state->total_data)) {
9057 END_PROFILE(SMBtranss2);
9058 return;
9061 handle_trans2(conn, req, state);
9063 DLIST_REMOVE(conn->pending_trans, state);
9064 SAFE_FREE(state->data);
9065 SAFE_FREE(state->param);
9066 TALLOC_FREE(state);
9068 END_PROFILE(SMBtranss2);
9069 return;
9071 bad_param:
9073 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9074 DLIST_REMOVE(conn->pending_trans, state);
9075 SAFE_FREE(state->data);
9076 SAFE_FREE(state->param);
9077 TALLOC_FREE(state);
9078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9079 END_PROFILE(SMBtranss2);
9080 return;