Fix bug #9130 - Certain xattrs cause Windows error 0x800700FF
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobb243af8f279c4a1d7ec6faecf1c93eeac2dbc33a
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;
484 if (last_start != NULL && do_store_data) {
485 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
487 last_start = p;
489 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
490 dos_namelen = strlen(dos_ea_name);
491 if (dos_namelen > 255 || dos_namelen == 0) {
492 return NT_STATUS_INTERNAL_ERROR;
494 if (ea_list->ea.value.length > 65535) {
495 return NT_STATUS_INTERNAL_ERROR;
498 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
500 if (ea_list->next) {
501 size_t pad = 4 - (this_size % 4);
502 this_size += pad;
505 if (do_store_data) {
506 if (this_size > total_data_size) {
507 return NT_STATUS_INFO_LENGTH_MISMATCH;
510 /* We know we have room. */
511 SIVAL(p, 0x00, 0); /* next offset */
512 SCVAL(p, 0x04, ea_list->ea.flags);
513 SCVAL(p, 0x05, dos_namelen);
514 SSVAL(p, 0x06, ea_list->ea.value.length);
515 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
516 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
517 total_data_size -= this_size;
520 p += this_size;
523 *ret_data_size = PTR_DIFF(p, pdata);
524 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
525 return NT_STATUS_OK;
528 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
530 size_t total_ea_len = 0;
531 TALLOC_CTX *mem_ctx;
532 struct ea_list *ea_list = NULL;
534 if (!lp_ea_support(SNUM(conn))) {
535 return 0;
537 mem_ctx = talloc_stackframe();
539 /* If this is a stream fsp, then we need to instead find the
540 * estimated ea len from the main file, not the stream
541 * (streams cannot have EAs), but the estimate isn't just 0 in
542 * this case! */
543 if (is_ntfs_stream_smb_fname(smb_fname)) {
544 fsp = NULL;
546 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
547 if(conn->sconn->using_smb2) {
548 NTSTATUS status;
549 unsigned int ret_data_size;
551 * We're going to be using fill_ea_chained_buffer() to
552 * marshall EA's - this size is significantly larger
553 * than the SMB1 buffer. Re-calculate the size without
554 * marshalling.
556 status = fill_ea_chained_buffer(mem_ctx,
557 NULL,
559 &ret_data_size,
560 conn,
561 ea_list);
562 if (!NT_STATUS_IS_OK(status)) {
563 ret_data_size = 0;
565 total_ea_len = ret_data_size;
567 TALLOC_FREE(mem_ctx);
568 return total_ea_len;
571 /****************************************************************************
572 Ensure the EA name is case insensitive by matching any existing EA name.
573 ****************************************************************************/
575 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
577 size_t total_ea_len;
578 TALLOC_CTX *mem_ctx = talloc_tos();
579 struct ea_list *ea_list;
580 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
581 if (!NT_STATUS_IS_OK(status)) {
582 return;
585 for (; ea_list; ea_list = ea_list->next) {
586 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
587 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
588 &unix_ea_name[5], ea_list->ea.name));
589 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
590 break;
595 /****************************************************************************
596 Set or delete an extended attribute.
597 ****************************************************************************/
599 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
600 const struct smb_filename *smb_fname, struct ea_list *ea_list)
602 NTSTATUS status;
603 char *fname = NULL;
605 if (!lp_ea_support(SNUM(conn))) {
606 return NT_STATUS_EAS_NOT_SUPPORTED;
609 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
610 if (!NT_STATUS_IS_OK(status)) {
611 return status;
614 /* Setting EAs on streams isn't supported. */
615 if (is_ntfs_stream_smb_fname(smb_fname)) {
616 return NT_STATUS_INVALID_PARAMETER;
619 fname = smb_fname->base_name;
621 for (;ea_list; ea_list = ea_list->next) {
622 int ret;
623 fstring unix_ea_name;
625 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
626 fstrcat(unix_ea_name, ea_list->ea.name);
628 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
630 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
632 if (samba_private_attr_name(unix_ea_name)) {
633 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
634 return NT_STATUS_ACCESS_DENIED;
637 if (ea_list->ea.value.length == 0) {
638 /* Remove the attribute. */
639 if (fsp && (fsp->fh->fd != -1)) {
640 DEBUG(10,("set_ea: deleting ea name %s on "
641 "file %s by file descriptor.\n",
642 unix_ea_name, fsp_str_dbg(fsp)));
643 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
644 } else {
645 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
646 unix_ea_name, fname));
647 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
649 #ifdef ENOATTR
650 /* Removing a non existent attribute always succeeds. */
651 if (ret == -1 && errno == ENOATTR) {
652 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
653 unix_ea_name));
654 ret = 0;
656 #endif
657 } else {
658 if (fsp && (fsp->fh->fd != -1)) {
659 DEBUG(10,("set_ea: setting ea name %s on file "
660 "%s by file descriptor.\n",
661 unix_ea_name, fsp_str_dbg(fsp)));
662 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
663 ea_list->ea.value.data, ea_list->ea.value.length, 0);
664 } else {
665 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
666 unix_ea_name, fname));
667 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
668 ea_list->ea.value.data, ea_list->ea.value.length, 0);
672 if (ret == -1) {
673 #ifdef ENOTSUP
674 if (errno == ENOTSUP) {
675 return NT_STATUS_EAS_NOT_SUPPORTED;
677 #endif
678 return map_nt_error_from_unix(errno);
682 return NT_STATUS_OK;
684 /****************************************************************************
685 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
686 ****************************************************************************/
688 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
690 struct ea_list *ea_list_head = NULL;
691 size_t converted_size, offset = 0;
693 while (offset + 2 < data_size) {
694 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
695 unsigned int namelen = CVAL(pdata,offset);
697 offset++; /* Go past the namelen byte. */
699 /* integer wrap paranioa. */
700 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
701 (offset > data_size) || (namelen > data_size) ||
702 (offset + namelen >= data_size)) {
703 break;
705 /* Ensure the name is null terminated. */
706 if (pdata[offset + namelen] != '\0') {
707 return NULL;
709 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
710 &converted_size)) {
711 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
712 "failed: %s", strerror(errno)));
714 if (!eal->ea.name) {
715 return NULL;
718 offset += (namelen + 1); /* Go past the name + terminating zero. */
719 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
720 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
723 return ea_list_head;
726 /****************************************************************************
727 Read one EA list entry from the buffer.
728 ****************************************************************************/
730 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
732 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
733 uint16 val_len;
734 unsigned int namelen;
735 size_t converted_size;
737 if (!eal) {
738 return NULL;
741 if (data_size < 6) {
742 return NULL;
745 eal->ea.flags = CVAL(pdata,0);
746 namelen = CVAL(pdata,1);
747 val_len = SVAL(pdata,2);
749 if (4 + namelen + 1 + val_len > data_size) {
750 return NULL;
753 /* Ensure the name is null terminated. */
754 if (pdata[namelen + 4] != '\0') {
755 return NULL;
757 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
758 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
759 strerror(errno)));
761 if (!eal->ea.name) {
762 return NULL;
765 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
766 if (!eal->ea.value.data) {
767 return NULL;
770 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
772 /* Ensure we're null terminated just in case we print the value. */
773 eal->ea.value.data[val_len] = '\0';
774 /* But don't count the null. */
775 eal->ea.value.length--;
777 if (pbytes_used) {
778 *pbytes_used = 4 + namelen + 1 + val_len;
781 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
782 dump_data(10, eal->ea.value.data, eal->ea.value.length);
784 return eal;
787 /****************************************************************************
788 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
789 ****************************************************************************/
791 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
793 struct ea_list *ea_list_head = NULL;
794 size_t offset = 0;
795 size_t bytes_used = 0;
797 while (offset < data_size) {
798 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
800 if (!eal) {
801 return NULL;
804 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
805 offset += bytes_used;
808 return ea_list_head;
811 /****************************************************************************
812 Count the total EA size needed.
813 ****************************************************************************/
815 static size_t ea_list_size(struct ea_list *ealist)
817 fstring dos_ea_name;
818 struct ea_list *listp;
819 size_t ret = 0;
821 for (listp = ealist; listp; listp = listp->next) {
822 push_ascii_fstring(dos_ea_name, listp->ea.name);
823 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
825 /* Add on 4 for total length. */
826 if (ret) {
827 ret += 4;
830 return ret;
833 /****************************************************************************
834 Return a union of EA's from a file list and a list of names.
835 The TALLOC context for the two lists *MUST* be identical as we steal
836 memory from one list to add to another. JRA.
837 ****************************************************************************/
839 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
841 struct ea_list *nlistp, *flistp;
843 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
844 for (flistp = file_list; flistp; flistp = flistp->next) {
845 if (strequal(nlistp->ea.name, flistp->ea.name)) {
846 break;
850 if (flistp) {
851 /* Copy the data from this entry. */
852 nlistp->ea.flags = flistp->ea.flags;
853 nlistp->ea.value = flistp->ea.value;
854 } else {
855 /* Null entry. */
856 nlistp->ea.flags = 0;
857 ZERO_STRUCT(nlistp->ea.value);
861 *total_ea_len = ea_list_size(name_list);
862 return name_list;
865 /****************************************************************************
866 Send the required number of replies back.
867 We assume all fields other than the data fields are
868 set correctly for the type of call.
869 HACK ! Always assumes smb_setup field is zero.
870 ****************************************************************************/
872 void send_trans2_replies(connection_struct *conn,
873 struct smb_request *req,
874 const char *params,
875 int paramsize,
876 const char *pdata,
877 int datasize,
878 int max_data_bytes)
880 /* As we are using a protocol > LANMAN1 then the max_send
881 variable must have been set in the sessetupX call.
882 This takes precedence over the max_xmit field in the
883 global struct. These different max_xmit variables should
884 be merged as this is now too confusing */
886 int data_to_send = datasize;
887 int params_to_send = paramsize;
888 int useable_space;
889 const char *pp = params;
890 const char *pd = pdata;
891 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
892 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
893 int data_alignment_offset = 0;
894 bool overflow = False;
895 struct smbd_server_connection *sconn = req->sconn;
896 int max_send = sconn->smb1.sessions.max_send;
898 /* Modify the data_to_send and datasize and set the error if
899 we're trying to send more than max_data_bytes. We still send
900 the part of the packet(s) that fit. Strange, but needed
901 for OS/2. */
903 if (max_data_bytes > 0 && datasize > max_data_bytes) {
904 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
905 max_data_bytes, datasize ));
906 datasize = data_to_send = max_data_bytes;
907 overflow = True;
910 /* If there genuinely are no parameters or data to send just send the empty packet */
912 if(params_to_send == 0 && data_to_send == 0) {
913 reply_outbuf(req, 10, 0);
914 show_msg((char *)req->outbuf);
915 if (!srv_send_smb(sconn,
916 (char *)req->outbuf,
917 true, req->seqnum+1,
918 IS_CONN_ENCRYPTED(conn),
919 &req->pcd)) {
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req->outbuf);
923 return;
926 /* When sending params and data ensure that both are nicely aligned */
927 /* Only do this alignment when there is also data to send - else
928 can cause NT redirector problems. */
930 if (((params_to_send % 4) != 0) && (data_to_send != 0))
931 data_alignment_offset = 4 - (params_to_send % 4);
933 /* Space is bufsize minus Netbios over TCP header minus SMB header */
934 /* The alignment_offset is to align the param bytes on an even byte
935 boundary. NT 4.0 Beta needs this to work correctly. */
937 useable_space = max_send - (smb_size
938 + 2 * 10 /* wct */
939 + alignment_offset
940 + data_alignment_offset);
942 if (useable_space < 0) {
943 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
944 "= %d!!!", useable_space));
945 exit_server_cleanly("send_trans2_replies: Not enough space");
948 while (params_to_send || data_to_send) {
949 /* Calculate whether we will totally or partially fill this packet */
951 total_sent_thistime = params_to_send + data_to_send;
953 /* We can never send more than useable_space */
955 * Note that 'useable_space' does not include the alignment offsets,
956 * but we must include the alignment offsets in the calculation of
957 * the length of the data we send over the wire, as the alignment offsets
958 * are sent here. Fix from Marc_Jacobsen@hp.com.
961 total_sent_thistime = MIN(total_sent_thistime, useable_space);
963 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
964 + data_alignment_offset);
966 /* Set total params and data to be sent */
967 SSVAL(req->outbuf,smb_tprcnt,paramsize);
968 SSVAL(req->outbuf,smb_tdrcnt,datasize);
970 /* Calculate how many parameters and data we can fit into
971 * this packet. Parameters get precedence
974 params_sent_thistime = MIN(params_to_send,useable_space);
975 data_sent_thistime = useable_space - params_sent_thistime;
976 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
978 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
980 /* smb_proff is the offset from the start of the SMB header to the
981 parameter bytes, however the first 4 bytes of outbuf are
982 the Netbios over TCP header. Thus use smb_base() to subtract
983 them from the calculation */
985 SSVAL(req->outbuf,smb_proff,
986 ((smb_buf(req->outbuf)+alignment_offset)
987 - smb_base(req->outbuf)));
989 if(params_sent_thistime == 0)
990 SSVAL(req->outbuf,smb_prdisp,0);
991 else
992 /* Absolute displacement of param bytes sent in this packet */
993 SSVAL(req->outbuf,smb_prdisp,pp - params);
995 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
996 if(data_sent_thistime == 0) {
997 SSVAL(req->outbuf,smb_droff,0);
998 SSVAL(req->outbuf,smb_drdisp, 0);
999 } else {
1000 /* The offset of the data bytes is the offset of the
1001 parameter bytes plus the number of parameters being sent this time */
1002 SSVAL(req->outbuf, smb_droff,
1003 ((smb_buf(req->outbuf)+alignment_offset)
1004 - smb_base(req->outbuf))
1005 + params_sent_thistime + data_alignment_offset);
1006 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1009 /* Initialize the padding for alignment */
1011 if (alignment_offset != 0) {
1012 memset(smb_buf(req->outbuf), 0, alignment_offset);
1015 /* Copy the param bytes into the packet */
1017 if(params_sent_thistime) {
1018 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1019 params_sent_thistime);
1022 /* Copy in the data bytes */
1023 if(data_sent_thistime) {
1024 if (data_alignment_offset != 0) {
1025 memset((smb_buf(req->outbuf)+alignment_offset+
1026 params_sent_thistime), 0,
1027 data_alignment_offset);
1029 memcpy(smb_buf(req->outbuf)+alignment_offset
1030 +params_sent_thistime+data_alignment_offset,
1031 pd,data_sent_thistime);
1034 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1035 params_sent_thistime, data_sent_thistime, useable_space));
1036 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1037 params_to_send, data_to_send, paramsize, datasize));
1039 if (overflow) {
1040 error_packet_set((char *)req->outbuf,
1041 ERRDOS,ERRbufferoverflow,
1042 STATUS_BUFFER_OVERFLOW,
1043 __LINE__,__FILE__);
1046 /* Send the packet */
1047 show_msg((char *)req->outbuf);
1048 if (!srv_send_smb(sconn,
1049 (char *)req->outbuf,
1050 true, req->seqnum+1,
1051 IS_CONN_ENCRYPTED(conn),
1052 &req->pcd))
1053 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1055 TALLOC_FREE(req->outbuf);
1057 pp += params_sent_thistime;
1058 pd += data_sent_thistime;
1060 params_to_send -= params_sent_thistime;
1061 data_to_send -= data_sent_thistime;
1063 /* Sanity check */
1064 if(params_to_send < 0 || data_to_send < 0) {
1065 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1066 params_to_send, data_to_send));
1067 return;
1071 return;
1074 /****************************************************************************
1075 Reply to a TRANSACT2_OPEN.
1076 ****************************************************************************/
1078 static void call_trans2open(connection_struct *conn,
1079 struct smb_request *req,
1080 char **pparams, int total_params,
1081 char **ppdata, int total_data,
1082 unsigned int max_data_bytes)
1084 struct smb_filename *smb_fname = NULL;
1085 char *params = *pparams;
1086 char *pdata = *ppdata;
1087 int deny_mode;
1088 int32 open_attr;
1089 bool oplock_request;
1090 #if 0
1091 bool return_additional_info;
1092 int16 open_sattr;
1093 time_t open_time;
1094 #endif
1095 int open_ofun;
1096 uint32 open_size;
1097 char *pname;
1098 char *fname = NULL;
1099 off_t size=0;
1100 int fattr=0,mtime=0;
1101 SMB_INO_T inode = 0;
1102 int smb_action = 0;
1103 files_struct *fsp;
1104 struct ea_list *ea_list = NULL;
1105 uint16 flags = 0;
1106 NTSTATUS status;
1107 uint32 access_mask;
1108 uint32 share_mode;
1109 uint32 create_disposition;
1110 uint32 create_options = 0;
1111 uint32_t private_flags = 0;
1112 TALLOC_CTX *ctx = talloc_tos();
1115 * Ensure we have enough parameters to perform the operation.
1118 if (total_params < 29) {
1119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1120 goto out;
1123 flags = SVAL(params, 0);
1124 deny_mode = SVAL(params, 2);
1125 open_attr = SVAL(params,6);
1126 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1127 if (oplock_request) {
1128 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1131 #if 0
1132 return_additional_info = BITSETW(params,0);
1133 open_sattr = SVAL(params, 4);
1134 open_time = make_unix_date3(params+8);
1135 #endif
1136 open_ofun = SVAL(params,12);
1137 open_size = IVAL(params,14);
1138 pname = &params[28];
1140 if (IS_IPC(conn)) {
1141 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1142 goto out;
1145 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1146 total_params - 28, STR_TERMINATE,
1147 &status);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 reply_nterror(req, status);
1150 goto out;
1153 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1154 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1155 (unsigned int)open_ofun, open_size));
1157 status = filename_convert(ctx,
1158 conn,
1159 req->flags2 & FLAGS2_DFS_PATHNAMES,
1160 fname,
1162 NULL,
1163 &smb_fname);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1166 reply_botherror(req,
1167 NT_STATUS_PATH_NOT_COVERED,
1168 ERRSRV, ERRbadpath);
1169 goto out;
1171 reply_nterror(req, status);
1172 goto out;
1175 if (open_ofun == 0) {
1176 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1177 goto out;
1180 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1181 open_ofun,
1182 &access_mask, &share_mode,
1183 &create_disposition,
1184 &create_options,
1185 &private_flags)) {
1186 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1187 goto out;
1190 /* Any data in this call is an EA list. */
1191 if (total_data && (total_data != 4)) {
1192 if (total_data < 10) {
1193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1194 goto out;
1197 if (IVAL(pdata,0) > total_data) {
1198 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1199 IVAL(pdata,0), (unsigned int)total_data));
1200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1201 goto out;
1204 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1205 total_data - 4);
1206 if (!ea_list) {
1207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1208 goto out;
1211 if (!lp_ea_support(SNUM(conn))) {
1212 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1213 goto out;
1217 status = SMB_VFS_CREATE_FILE(
1218 conn, /* conn */
1219 req, /* req */
1220 0, /* root_dir_fid */
1221 smb_fname, /* fname */
1222 access_mask, /* access_mask */
1223 share_mode, /* share_access */
1224 create_disposition, /* create_disposition*/
1225 create_options, /* create_options */
1226 open_attr, /* file_attributes */
1227 oplock_request, /* oplock_request */
1228 open_size, /* allocation_size */
1229 private_flags,
1230 NULL, /* sd */
1231 ea_list, /* ea_list */
1232 &fsp, /* result */
1233 &smb_action); /* psbuf */
1235 if (!NT_STATUS_IS_OK(status)) {
1236 if (open_was_deferred(req->sconn, req->mid)) {
1237 /* We have re-scheduled this call. */
1238 goto out;
1240 reply_openerror(req, status);
1241 goto out;
1244 size = get_file_size_stat(&smb_fname->st);
1245 fattr = dos_mode(conn, smb_fname);
1246 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1247 inode = smb_fname->st.st_ex_ino;
1248 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1249 close_file(req, fsp, ERROR_CLOSE);
1250 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1251 goto out;
1254 /* Realloc the size of parameters and data we will return */
1255 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1256 if(*pparams == NULL ) {
1257 reply_nterror(req, NT_STATUS_NO_MEMORY);
1258 goto out;
1260 params = *pparams;
1262 SSVAL(params,0,fsp->fnum);
1263 SSVAL(params,2,fattr);
1264 srv_put_dos_date2(params,4, mtime);
1265 SIVAL(params,8, (uint32)size);
1266 SSVAL(params,12,deny_mode);
1267 SSVAL(params,14,0); /* open_type - file or directory. */
1268 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1270 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1271 smb_action |= EXTENDED_OPLOCK_GRANTED;
1274 SSVAL(params,18,smb_action);
1277 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1279 SIVAL(params,20,inode);
1280 SSVAL(params,24,0); /* Padding. */
1281 if (flags & 8) {
1282 uint32 ea_size = estimate_ea_size(conn, fsp,
1283 smb_fname);
1284 SIVAL(params, 26, ea_size);
1285 } else {
1286 SIVAL(params, 26, 0);
1289 /* Send the required number of replies */
1290 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1291 out:
1292 TALLOC_FREE(smb_fname);
1295 /*********************************************************
1296 Routine to check if a given string matches exactly.
1297 as a special case a mask of "." does NOT match. That
1298 is required for correct wildcard semantics
1299 Case can be significant or not.
1300 **********************************************************/
1302 static bool exact_match(bool has_wild,
1303 bool case_sensitive,
1304 const char *str,
1305 const char *mask)
1307 if (mask[0] == '.' && mask[1] == 0) {
1308 return false;
1311 if (has_wild) {
1312 return false;
1315 if (case_sensitive) {
1316 return strcmp(str,mask)==0;
1317 } else {
1318 return strcasecmp_m(str,mask) == 0;
1322 /****************************************************************************
1323 Return the filetype for UNIX extensions.
1324 ****************************************************************************/
1326 static uint32 unix_filetype(mode_t mode)
1328 if(S_ISREG(mode))
1329 return UNIX_TYPE_FILE;
1330 else if(S_ISDIR(mode))
1331 return UNIX_TYPE_DIR;
1332 #ifdef S_ISLNK
1333 else if(S_ISLNK(mode))
1334 return UNIX_TYPE_SYMLINK;
1335 #endif
1336 #ifdef S_ISCHR
1337 else if(S_ISCHR(mode))
1338 return UNIX_TYPE_CHARDEV;
1339 #endif
1340 #ifdef S_ISBLK
1341 else if(S_ISBLK(mode))
1342 return UNIX_TYPE_BLKDEV;
1343 #endif
1344 #ifdef S_ISFIFO
1345 else if(S_ISFIFO(mode))
1346 return UNIX_TYPE_FIFO;
1347 #endif
1348 #ifdef S_ISSOCK
1349 else if(S_ISSOCK(mode))
1350 return UNIX_TYPE_SOCKET;
1351 #endif
1353 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1354 return UNIX_TYPE_UNKNOWN;
1357 /****************************************************************************
1358 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1359 ****************************************************************************/
1361 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1363 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1364 const SMB_STRUCT_STAT *psbuf,
1365 uint32 perms,
1366 enum perm_type ptype,
1367 mode_t *ret_perms)
1369 mode_t ret = 0;
1371 if (perms == SMB_MODE_NO_CHANGE) {
1372 if (!VALID_STAT(*psbuf)) {
1373 return NT_STATUS_INVALID_PARAMETER;
1374 } else {
1375 *ret_perms = psbuf->st_ex_mode;
1376 return NT_STATUS_OK;
1380 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1381 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1382 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1383 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1384 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1385 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1386 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1387 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1388 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1389 #ifdef S_ISVTX
1390 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1391 #endif
1392 #ifdef S_ISGID
1393 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1394 #endif
1395 #ifdef S_ISUID
1396 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1397 #endif
1399 switch (ptype) {
1400 case PERM_NEW_FILE:
1401 case PERM_EXISTING_FILE:
1402 /* Apply mode mask */
1403 ret &= lp_create_mask(SNUM(conn));
1404 /* Add in force bits */
1405 ret |= lp_force_create_mode(SNUM(conn));
1406 break;
1407 case PERM_NEW_DIR:
1408 case PERM_EXISTING_DIR:
1409 ret &= lp_dir_mask(SNUM(conn));
1410 /* Add in force bits */
1411 ret |= lp_force_dir_mode(SNUM(conn));
1412 break;
1415 *ret_perms = ret;
1416 return NT_STATUS_OK;
1419 /****************************************************************************
1420 Needed to show the msdfs symlinks as directories. Modifies psbuf
1421 to be a directory if it's a msdfs link.
1422 ****************************************************************************/
1424 static bool check_msdfs_link(connection_struct *conn,
1425 const char *pathname,
1426 SMB_STRUCT_STAT *psbuf)
1428 int saved_errno = errno;
1429 if(lp_host_msdfs() &&
1430 lp_msdfs_root(SNUM(conn)) &&
1431 is_msdfs_link(conn, pathname, psbuf)) {
1433 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1434 "as a directory\n",
1435 pathname));
1436 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1437 errno = saved_errno;
1438 return true;
1440 errno = saved_errno;
1441 return false;
1445 /****************************************************************************
1446 Get a level dependent lanman2 dir entry.
1447 ****************************************************************************/
1449 struct smbd_dirptr_lanman2_state {
1450 connection_struct *conn;
1451 uint32_t info_level;
1452 bool check_mangled_names;
1453 bool has_wild;
1454 bool got_exact_match;
1457 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1458 void *private_data,
1459 const char *dname,
1460 const char *mask,
1461 char **_fname)
1463 struct smbd_dirptr_lanman2_state *state =
1464 (struct smbd_dirptr_lanman2_state *)private_data;
1465 bool ok;
1466 char mangled_name[13]; /* mangled 8.3 name. */
1467 bool got_match;
1468 const char *fname;
1470 /* Mangle fname if it's an illegal name. */
1471 if (mangle_must_mangle(dname, state->conn->params)) {
1472 ok = name_to_8_3(dname, mangled_name,
1473 true, state->conn->params);
1474 if (!ok) {
1475 return false;
1477 fname = mangled_name;
1478 } else {
1479 fname = dname;
1482 got_match = exact_match(state->has_wild,
1483 state->conn->case_sensitive,
1484 fname, mask);
1485 state->got_exact_match = got_match;
1486 if (!got_match) {
1487 got_match = mask_match(fname, mask,
1488 state->conn->case_sensitive);
1491 if(!got_match && state->check_mangled_names &&
1492 !mangle_is_8_3(fname, false, state->conn->params)) {
1494 * It turns out that NT matches wildcards against
1495 * both long *and* short names. This may explain some
1496 * of the wildcard wierdness from old DOS clients
1497 * that some people have been seeing.... JRA.
1499 /* Force the mangling into 8.3. */
1500 ok = name_to_8_3(fname, mangled_name,
1501 false, state->conn->params);
1502 if (!ok) {
1503 return false;
1506 got_match = exact_match(state->has_wild,
1507 state->conn->case_sensitive,
1508 mangled_name, mask);
1509 state->got_exact_match = got_match;
1510 if (!got_match) {
1511 got_match = mask_match(mangled_name, mask,
1512 state->conn->case_sensitive);
1516 if (!got_match) {
1517 return false;
1520 *_fname = talloc_strdup(ctx, fname);
1521 if (*_fname == NULL) {
1522 return false;
1525 return true;
1528 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1529 void *private_data,
1530 struct smb_filename *smb_fname,
1531 uint32_t *_mode)
1533 struct smbd_dirptr_lanman2_state *state =
1534 (struct smbd_dirptr_lanman2_state *)private_data;
1535 bool ms_dfs_link = false;
1536 uint32_t mode = 0;
1538 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1539 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1540 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1541 "Couldn't lstat [%s] (%s)\n",
1542 smb_fname_str_dbg(smb_fname),
1543 strerror(errno)));
1544 return false;
1546 } else if (!VALID_STAT(smb_fname->st) &&
1547 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1548 /* Needed to show the msdfs symlinks as
1549 * directories */
1551 ms_dfs_link = check_msdfs_link(state->conn,
1552 smb_fname->base_name,
1553 &smb_fname->st);
1554 if (!ms_dfs_link) {
1555 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1556 "Couldn't stat [%s] (%s)\n",
1557 smb_fname_str_dbg(smb_fname),
1558 strerror(errno)));
1559 return false;
1563 if (ms_dfs_link) {
1564 mode = dos_mode_msdfs(state->conn, smb_fname);
1565 } else {
1566 mode = dos_mode(state->conn, smb_fname);
1569 *_mode = mode;
1570 return true;
1573 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1574 connection_struct *conn,
1575 uint16_t flags2,
1576 uint32_t info_level,
1577 struct ea_list *name_list,
1578 bool check_mangled_names,
1579 bool requires_resume_key,
1580 uint32_t mode,
1581 const char *fname,
1582 const struct smb_filename *smb_fname,
1583 int space_remaining,
1584 uint8_t align,
1585 bool do_pad,
1586 char *base_data,
1587 char **ppdata,
1588 char *end_data,
1589 bool *out_of_space,
1590 uint64_t *last_entry_off)
1592 char *p, *q, *pdata = *ppdata;
1593 uint32_t reskey=0;
1594 uint64_t file_size = 0;
1595 uint64_t allocation_size = 0;
1596 uint64_t file_index = 0;
1597 uint32_t len;
1598 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1599 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1600 char *nameptr;
1601 char *last_entry_ptr;
1602 bool was_8_3;
1603 int off;
1604 int pad = 0;
1606 *out_of_space = false;
1608 ZERO_STRUCT(mdate_ts);
1609 ZERO_STRUCT(adate_ts);
1610 ZERO_STRUCT(create_date_ts);
1611 ZERO_STRUCT(cdate_ts);
1613 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1614 file_size = get_file_size_stat(&smb_fname->st);
1616 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1618 file_index = get_FileIndex(conn, &smb_fname->st);
1620 mdate_ts = smb_fname->st.st_ex_mtime;
1621 adate_ts = smb_fname->st.st_ex_atime;
1622 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1623 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1625 if (lp_dos_filetime_resolution(SNUM(conn))) {
1626 dos_filetime_timespec(&create_date_ts);
1627 dos_filetime_timespec(&mdate_ts);
1628 dos_filetime_timespec(&adate_ts);
1629 dos_filetime_timespec(&cdate_ts);
1632 create_date = convert_timespec_to_time_t(create_date_ts);
1633 mdate = convert_timespec_to_time_t(mdate_ts);
1634 adate = convert_timespec_to_time_t(adate_ts);
1636 /* align the record */
1637 SMB_ASSERT(align >= 1);
1639 off = (int)PTR_DIFF(pdata, base_data);
1640 pad = (off + (align-1)) & ~(align-1);
1641 pad -= off;
1643 if (pad && pad > space_remaining) {
1644 *out_of_space = true;
1645 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1646 "for padding (wanted %u, had %d)\n",
1647 (unsigned int)pad,
1648 space_remaining ));
1649 return false; /* Not finished - just out of space */
1652 off += pad;
1653 /* initialize padding to 0 */
1654 if (pad) {
1655 memset(pdata, 0, pad);
1657 space_remaining -= pad;
1659 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1660 space_remaining ));
1662 pdata += pad;
1663 p = pdata;
1664 last_entry_ptr = p;
1666 pad = 0;
1667 off = 0;
1669 switch (info_level) {
1670 case SMB_FIND_INFO_STANDARD:
1671 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1672 if(requires_resume_key) {
1673 SIVAL(p,0,reskey);
1674 p += 4;
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1681 SSVAL(p,20,mode);
1682 p += 23;
1683 nameptr = p;
1684 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1685 p += ucs2_align(base_data, p, 0);
1687 len = srvstr_push(base_data, flags2, p,
1688 fname, PTR_DIFF(end_data, p),
1689 STR_TERMINATE);
1690 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1691 if (len > 2) {
1692 SCVAL(nameptr, -1, len - 2);
1693 } else {
1694 SCVAL(nameptr, -1, 0);
1696 } else {
1697 if (len > 1) {
1698 SCVAL(nameptr, -1, len - 1);
1699 } else {
1700 SCVAL(nameptr, -1, 0);
1703 p += len;
1704 break;
1706 case SMB_FIND_EA_SIZE:
1707 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1708 if (requires_resume_key) {
1709 SIVAL(p,0,reskey);
1710 p += 4;
1712 srv_put_dos_date2(p,0,create_date);
1713 srv_put_dos_date2(p,4,adate);
1714 srv_put_dos_date2(p,8,mdate);
1715 SIVAL(p,12,(uint32)file_size);
1716 SIVAL(p,16,(uint32)allocation_size);
1717 SSVAL(p,20,mode);
1719 unsigned int ea_size = estimate_ea_size(conn, NULL,
1720 smb_fname);
1721 SIVAL(p,22,ea_size); /* Extended attributes */
1723 p += 27;
1724 nameptr = p - 1;
1725 len = srvstr_push(base_data, flags2,
1726 p, fname, PTR_DIFF(end_data, p),
1727 STR_TERMINATE | STR_NOALIGN);
1728 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1729 if (len > 2) {
1730 len -= 2;
1731 } else {
1732 len = 0;
1734 } else {
1735 if (len > 1) {
1736 len -= 1;
1737 } else {
1738 len = 0;
1741 SCVAL(nameptr,0,len);
1742 p += len;
1743 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1744 break;
1746 case SMB_FIND_EA_LIST:
1748 struct ea_list *file_list = NULL;
1749 size_t ea_len = 0;
1750 NTSTATUS status;
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1753 if (!name_list) {
1754 return false;
1756 if (requires_resume_key) {
1757 SIVAL(p,0,reskey);
1758 p += 4;
1760 srv_put_dos_date2(p,0,create_date);
1761 srv_put_dos_date2(p,4,adate);
1762 srv_put_dos_date2(p,8,mdate);
1763 SIVAL(p,12,(uint32)file_size);
1764 SIVAL(p,16,(uint32)allocation_size);
1765 SSVAL(p,20,mode);
1766 p += 22; /* p now points to the EA area. */
1768 status = get_ea_list_from_file(ctx, conn, NULL,
1769 smb_fname,
1770 &ea_len, &file_list);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 file_list = NULL;
1774 name_list = ea_list_union(name_list, file_list, &ea_len);
1776 /* We need to determine if this entry will fit in the space available. */
1777 /* Max string size is 255 bytes. */
1778 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1779 *out_of_space = true;
1780 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1781 "(wanted %u, had %d)\n",
1782 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1783 space_remaining ));
1784 return False; /* Not finished - just out of space */
1787 /* Push the ea_data followed by the name. */
1788 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1789 nameptr = p;
1790 len = srvstr_push(base_data, flags2,
1791 p + 1, fname, PTR_DIFF(end_data, p+1),
1792 STR_TERMINATE | STR_NOALIGN);
1793 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1794 if (len > 2) {
1795 len -= 2;
1796 } else {
1797 len = 0;
1799 } else {
1800 if (len > 1) {
1801 len -= 1;
1802 } else {
1803 len = 0;
1806 SCVAL(nameptr,0,len);
1807 p += len + 1;
1808 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1809 break;
1812 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1813 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1814 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1815 p += 4;
1816 SIVAL(p,0,reskey); p += 4;
1817 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1819 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1820 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1821 SOFF_T(p,0,file_size); p += 8;
1822 SOFF_T(p,0,allocation_size); p += 8;
1823 SIVAL(p,0,mode); p += 4;
1824 q = p; p += 4; /* q is placeholder for name length. */
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1829 p += 4;
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1838 conn->params)) {
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1846 if (len < 24) {
1847 memset(p + 2 + len,'\0',24 - len);
1849 SSVAL(p, 0, len);
1850 } else {
1851 memset(p,'\0',26);
1853 p += 2 + 24;
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1857 SIVAL(q,0,len);
1858 p += len;
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1867 SIVAL(pdata,0,pad);
1869 * set padding to zero
1871 if (do_pad) {
1872 memset(p, 0, pad - len);
1873 p = pdata + pad;
1874 } else {
1875 p = pdata + len;
1877 break;
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1881 p += 4;
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1893 SIVAL(p,0,len);
1894 p += 4 + len;
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1903 SIVAL(pdata,0,pad);
1905 * set padding to zero
1907 if (do_pad) {
1908 memset(p, 0, pad - len);
1909 p = pdata + pad;
1910 } else {
1911 p = pdata + len;
1913 break;
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1936 SIVAL(q, 0, len);
1937 p += len;
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1946 SIVAL(pdata,0,pad);
1948 * set padding to zero
1950 if (do_pad) {
1951 memset(p, 0, pad - len);
1952 p = pdata + pad;
1953 } else {
1954 p = pdata + len;
1956 break;
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1960 p += 4;
1961 SIVAL(p,0,reskey); p += 4;
1962 p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1968 SIVAL(p, -4, len);
1969 p += len;
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1978 SIVAL(pdata,0,pad);
1980 * set padding to zero
1982 if (do_pad) {
1983 memset(p, 0, pad - len);
1984 p = pdata + pad;
1985 } else {
1986 p = pdata + len;
1988 break;
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1992 p += 4;
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2003 unsigned int ea_size = estimate_ea_size(conn, NULL,
2004 smb_fname);
2005 SIVAL(p,0,ea_size); /* Extended attributes */
2006 p +=4;
2008 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2009 SBVAL(p,0,file_index); p += 8;
2010 len = srvstr_push(base_data, flags2, p,
2011 fname, PTR_DIFF(end_data, p),
2012 STR_TERMINATE_ASCII);
2013 SIVAL(q, 0, len);
2014 p += len;
2016 len = PTR_DIFF(p, pdata);
2017 pad = (len + (align-1)) & ~(align-1);
2019 * offset to the next entry, the caller
2020 * will overwrite it for the last entry
2021 * that's why we always include the padding
2023 SIVAL(pdata,0,pad);
2025 * set padding to zero
2027 if (do_pad) {
2028 memset(p, 0, pad - len);
2029 p = pdata + pad;
2030 } else {
2031 p = pdata + len;
2033 break;
2035 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2036 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2037 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2038 p += 4;
2039 SIVAL(p,0,reskey); p += 4;
2040 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2041 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2042 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2044 SOFF_T(p,0,file_size); p += 8;
2045 SOFF_T(p,0,allocation_size); p += 8;
2046 SIVAL(p,0,mode); p += 4;
2047 q = p; p += 4; /* q is placeholder for name length */
2049 unsigned int ea_size = estimate_ea_size(conn, NULL,
2050 smb_fname);
2051 SIVAL(p,0,ea_size); /* Extended attributes */
2052 p +=4;
2054 /* Clear the short name buffer. This is
2055 * IMPORTANT as not doing so will trigger
2056 * a Win2k client bug. JRA.
2058 if (!was_8_3 && check_mangled_names) {
2059 char mangled_name[13]; /* mangled 8.3 name. */
2060 if (!name_to_8_3(fname,mangled_name,True,
2061 conn->params)) {
2062 /* Error - mangle failed ! */
2063 memset(mangled_name,'\0',12);
2065 mangled_name[12] = 0;
2066 len = srvstr_push(base_data, flags2,
2067 p+2, mangled_name, 24,
2068 STR_UPPER|STR_UNICODE);
2069 SSVAL(p, 0, len);
2070 if (len < 24) {
2071 memset(p + 2 + len,'\0',24 - len);
2073 SSVAL(p, 0, len);
2074 } else {
2075 memset(p,'\0',26);
2077 p += 26;
2078 SSVAL(p,0,0); p += 2; /* Reserved ? */
2079 SBVAL(p,0,file_index); p += 8;
2080 len = srvstr_push(base_data, flags2, p,
2081 fname, PTR_DIFF(end_data, p),
2082 STR_TERMINATE_ASCII);
2083 SIVAL(q,0,len);
2084 p += len;
2086 len = PTR_DIFF(p, pdata);
2087 pad = (len + (align-1)) & ~(align-1);
2089 * offset to the next entry, the caller
2090 * will overwrite it for the last entry
2091 * that's why we always include the padding
2093 SIVAL(pdata,0,pad);
2095 * set padding to zero
2097 if (do_pad) {
2098 memset(p, 0, pad - len);
2099 p = pdata + pad;
2100 } else {
2101 p = pdata + len;
2103 break;
2105 /* CIFS UNIX Extension. */
2107 case SMB_FIND_FILE_UNIX:
2108 case SMB_FIND_FILE_UNIX_INFO2:
2109 p+= 4;
2110 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2112 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2114 if (info_level == SMB_FIND_FILE_UNIX) {
2115 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2116 p = store_file_unix_basic(conn, p,
2117 NULL, &smb_fname->st);
2118 len = srvstr_push(base_data, flags2, p,
2119 fname, PTR_DIFF(end_data, p),
2120 STR_TERMINATE);
2121 } else {
2122 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2123 p = store_file_unix_basic_info2(conn, p,
2124 NULL, &smb_fname->st);
2125 nameptr = p;
2126 p += 4;
2127 len = srvstr_push(base_data, flags2, p, fname,
2128 PTR_DIFF(end_data, p), 0);
2129 SIVAL(nameptr, 0, len);
2132 p += len;
2134 len = PTR_DIFF(p, pdata);
2135 pad = (len + (align-1)) & ~(align-1);
2137 * offset to the next entry, the caller
2138 * will overwrite it for the last entry
2139 * that's why we always include the padding
2141 SIVAL(pdata,0,pad);
2143 * set padding to zero
2145 if (do_pad) {
2146 memset(p, 0, pad - len);
2147 p = pdata + pad;
2148 } else {
2149 p = pdata + len;
2151 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2153 break;
2155 default:
2156 return false;
2159 if (PTR_DIFF(p,pdata) > space_remaining) {
2160 *out_of_space = true;
2161 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2162 "(wanted %u, had %d)\n",
2163 (unsigned int)PTR_DIFF(p,pdata),
2164 space_remaining ));
2165 return false; /* Not finished - just out of space */
2168 /* Setup the last entry pointer, as an offset from base_data */
2169 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2170 /* Advance the data pointer to the next slot */
2171 *ppdata = p;
2173 return true;
2176 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2177 connection_struct *conn,
2178 struct dptr_struct *dirptr,
2179 uint16 flags2,
2180 const char *path_mask,
2181 uint32 dirtype,
2182 int info_level,
2183 int requires_resume_key,
2184 bool dont_descend,
2185 bool ask_sharemode,
2186 uint8_t align,
2187 bool do_pad,
2188 char **ppdata,
2189 char *base_data,
2190 char *end_data,
2191 int space_remaining,
2192 bool *out_of_space,
2193 bool *got_exact_match,
2194 int *_last_entry_off,
2195 struct ea_list *name_list)
2197 const char *p;
2198 const char *mask = NULL;
2199 long prev_dirpos = 0;
2200 uint32_t mode = 0;
2201 char *fname = NULL;
2202 struct smb_filename *smb_fname = NULL;
2203 struct smbd_dirptr_lanman2_state state;
2204 bool ok;
2205 uint64_t last_entry_off = 0;
2207 ZERO_STRUCT(state);
2208 state.conn = conn;
2209 state.info_level = info_level;
2210 state.check_mangled_names = lp_manglednames(conn->params);
2211 state.has_wild = dptr_has_wild(dirptr);
2212 state.got_exact_match = false;
2214 *out_of_space = false;
2215 *got_exact_match = false;
2217 p = strrchr_m(path_mask,'/');
2218 if(p != NULL) {
2219 if(p[1] == '\0') {
2220 mask = "*.*";
2221 } else {
2222 mask = p+1;
2224 } else {
2225 mask = path_mask;
2228 ok = smbd_dirptr_get_entry(ctx,
2229 dirptr,
2230 mask,
2231 dirtype,
2232 dont_descend,
2233 ask_sharemode,
2234 smbd_dirptr_lanman2_match_fn,
2235 smbd_dirptr_lanman2_mode_fn,
2236 &state,
2237 &fname,
2238 &smb_fname,
2239 &mode,
2240 &prev_dirpos);
2241 if (!ok) {
2242 return false;
2245 *got_exact_match = state.got_exact_match;
2247 ok = smbd_marshall_dir_entry(ctx,
2248 conn,
2249 flags2,
2250 info_level,
2251 name_list,
2252 state.check_mangled_names,
2253 requires_resume_key,
2254 mode,
2255 fname,
2256 smb_fname,
2257 space_remaining,
2258 align,
2259 do_pad,
2260 base_data,
2261 ppdata,
2262 end_data,
2263 out_of_space,
2264 &last_entry_off);
2265 TALLOC_FREE(fname);
2266 TALLOC_FREE(smb_fname);
2267 if (*out_of_space) {
2268 dptr_SeekDir(dirptr, prev_dirpos);
2269 return false;
2271 if (!ok) {
2272 return false;
2275 *_last_entry_off = last_entry_off;
2276 return true;
2279 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2280 connection_struct *conn,
2281 struct dptr_struct *dirptr,
2282 uint16 flags2,
2283 const char *path_mask,
2284 uint32 dirtype,
2285 int info_level,
2286 bool requires_resume_key,
2287 bool dont_descend,
2288 bool ask_sharemode,
2289 char **ppdata,
2290 char *base_data,
2291 char *end_data,
2292 int space_remaining,
2293 bool *out_of_space,
2294 bool *got_exact_match,
2295 int *last_entry_off,
2296 struct ea_list *name_list)
2298 uint8_t align = 4;
2299 const bool do_pad = true;
2301 if (info_level >= 1 && info_level <= 3) {
2302 /* No alignment on earlier info levels. */
2303 align = 1;
2306 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2307 path_mask, dirtype, info_level,
2308 requires_resume_key, dont_descend, ask_sharemode,
2309 align, do_pad,
2310 ppdata, base_data, end_data,
2311 space_remaining,
2312 out_of_space, got_exact_match,
2313 last_entry_off, name_list);
2316 /****************************************************************************
2317 Reply to a TRANS2_FINDFIRST.
2318 ****************************************************************************/
2320 static void call_trans2findfirst(connection_struct *conn,
2321 struct smb_request *req,
2322 char **pparams, int total_params,
2323 char **ppdata, int total_data,
2324 unsigned int max_data_bytes)
2326 /* We must be careful here that we don't return more than the
2327 allowed number of data bytes. If this means returning fewer than
2328 maxentries then so be it. We assume that the redirector has
2329 enough room for the fixed number of parameter bytes it has
2330 requested. */
2331 struct smb_filename *smb_dname = NULL;
2332 char *params = *pparams;
2333 char *pdata = *ppdata;
2334 char *data_end;
2335 uint32 dirtype;
2336 int maxentries;
2337 uint16 findfirst_flags;
2338 bool close_after_first;
2339 bool close_if_end;
2340 bool requires_resume_key;
2341 int info_level;
2342 char *directory = NULL;
2343 char *mask = NULL;
2344 char *p;
2345 int last_entry_off=0;
2346 int dptr_num = -1;
2347 int numentries = 0;
2348 int i;
2349 bool finished = False;
2350 bool dont_descend = False;
2351 bool out_of_space = False;
2352 int space_remaining;
2353 bool mask_contains_wcard = False;
2354 struct ea_list *ea_list = NULL;
2355 NTSTATUS ntstatus = NT_STATUS_OK;
2356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2357 TALLOC_CTX *ctx = talloc_tos();
2358 struct dptr_struct *dirptr = NULL;
2359 struct smbd_server_connection *sconn = req->sconn;
2360 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2361 bool backup_priv = false;
2363 if (total_params < 13) {
2364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2365 goto out;
2368 dirtype = SVAL(params,0);
2369 maxentries = SVAL(params,2);
2370 findfirst_flags = SVAL(params,4);
2371 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2372 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2373 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2374 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2375 security_token_has_privilege(get_current_nttok(conn),
2376 SEC_PRIV_BACKUP));
2378 info_level = SVAL(params,6);
2380 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2381 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2382 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2383 (int)backup_priv,
2384 info_level, max_data_bytes));
2386 if (!maxentries) {
2387 /* W2K3 seems to treat zero as 1. */
2388 maxentries = 1;
2391 switch (info_level) {
2392 case SMB_FIND_INFO_STANDARD:
2393 case SMB_FIND_EA_SIZE:
2394 case SMB_FIND_EA_LIST:
2395 case SMB_FIND_FILE_DIRECTORY_INFO:
2396 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2397 case SMB_FIND_FILE_NAMES_INFO:
2398 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2399 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2400 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2401 break;
2402 case SMB_FIND_FILE_UNIX:
2403 case SMB_FIND_FILE_UNIX_INFO2:
2404 /* Always use filesystem for UNIX mtime query. */
2405 ask_sharemode = false;
2406 if (!lp_unix_extensions()) {
2407 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2408 goto out;
2410 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2411 break;
2412 default:
2413 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2414 goto out;
2417 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2418 params+12, total_params - 12,
2419 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2420 if (!NT_STATUS_IS_OK(ntstatus)) {
2421 reply_nterror(req, ntstatus);
2422 goto out;
2425 if (backup_priv) {
2426 become_root();
2427 ntstatus = filename_convert_with_privilege(ctx,
2428 conn,
2429 req,
2430 directory,
2431 ucf_flags,
2432 &mask_contains_wcard,
2433 &smb_dname);
2434 } else {
2435 ntstatus = filename_convert(ctx, conn,
2436 req->flags2 & FLAGS2_DFS_PATHNAMES,
2437 directory,
2438 ucf_flags,
2439 &mask_contains_wcard,
2440 &smb_dname);
2443 if (!NT_STATUS_IS_OK(ntstatus)) {
2444 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2445 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2446 ERRSRV, ERRbadpath);
2447 goto out;
2449 reply_nterror(req, ntstatus);
2450 goto out;
2453 mask = smb_dname->original_lcomp;
2455 directory = smb_dname->base_name;
2457 p = strrchr_m(directory,'/');
2458 if(p == NULL) {
2459 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2460 if((directory[0] == '.') && (directory[1] == '\0')) {
2461 mask = talloc_strdup(ctx,"*");
2462 if (!mask) {
2463 reply_nterror(req, NT_STATUS_NO_MEMORY);
2464 goto out;
2466 mask_contains_wcard = True;
2468 } else {
2469 *p = 0;
2472 if (p == NULL || p == directory) {
2473 /* Ensure we don't have a directory name of "". */
2474 directory = talloc_strdup(talloc_tos(), ".");
2475 if (!directory) {
2476 reply_nterror(req, NT_STATUS_NO_MEMORY);
2477 goto out;
2481 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2483 if (info_level == SMB_FIND_EA_LIST) {
2484 uint32 ea_size;
2486 if (total_data < 4) {
2487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2488 goto out;
2491 ea_size = IVAL(pdata,0);
2492 if (ea_size != total_data) {
2493 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2494 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2496 goto out;
2499 if (!lp_ea_support(SNUM(conn))) {
2500 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2501 goto out;
2504 /* Pull out the list of names. */
2505 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2506 if (!ea_list) {
2507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2508 goto out;
2512 *ppdata = (char *)SMB_REALLOC(
2513 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2514 if(*ppdata == NULL ) {
2515 reply_nterror(req, NT_STATUS_NO_MEMORY);
2516 goto out;
2518 pdata = *ppdata;
2519 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2521 /* Realloc the params space */
2522 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2523 if (*pparams == NULL) {
2524 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 goto out;
2527 params = *pparams;
2529 /* Save the wildcard match and attribs we are using on this directory -
2530 needed as lanman2 assumes these are being saved between calls */
2532 ntstatus = dptr_create(conn,
2533 req,
2534 NULL, /* fsp */
2535 directory,
2536 False,
2537 True,
2538 req->smbpid,
2539 mask,
2540 mask_contains_wcard,
2541 dirtype,
2542 &dirptr);
2544 if (!NT_STATUS_IS_OK(ntstatus)) {
2545 reply_nterror(req, ntstatus);
2546 goto out;
2549 if (backup_priv) {
2550 /* Remember this in case we have
2551 to do a findnext. */
2552 dptr_set_priv(dirptr);
2555 dptr_num = dptr_dnum(dirptr);
2556 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2558 /* Initialize per TRANS2_FIND_FIRST operation data */
2559 dptr_init_search_op(dirptr);
2561 /* We don't need to check for VOL here as this is returned by
2562 a different TRANS2 call. */
2564 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2565 directory,lp_dontdescend(ctx, SNUM(conn))));
2566 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2567 dont_descend = True;
2569 p = pdata;
2570 space_remaining = max_data_bytes;
2571 out_of_space = False;
2573 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2574 bool got_exact_match = False;
2576 /* this is a heuristic to avoid seeking the dirptr except when
2577 absolutely necessary. It allows for a filename of about 40 chars */
2578 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2579 out_of_space = True;
2580 finished = False;
2581 } else {
2582 finished = !get_lanman2_dir_entry(ctx,
2583 conn,
2584 dirptr,
2585 req->flags2,
2586 mask,dirtype,info_level,
2587 requires_resume_key,dont_descend,
2588 ask_sharemode,
2589 &p,pdata,data_end,
2590 space_remaining, &out_of_space,
2591 &got_exact_match,
2592 &last_entry_off, ea_list);
2595 if (finished && out_of_space)
2596 finished = False;
2598 if (!finished && !out_of_space)
2599 numentries++;
2602 * As an optimisation if we know we aren't looking
2603 * for a wildcard name (ie. the name matches the wildcard exactly)
2604 * then we can finish on any (first) match.
2605 * This speeds up large directory searches. JRA.
2608 if(got_exact_match)
2609 finished = True;
2611 /* Ensure space_remaining never goes -ve. */
2612 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2613 space_remaining = 0;
2614 out_of_space = true;
2615 } else {
2616 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2620 /* Check if we can close the dirptr */
2621 if(close_after_first || (finished && close_if_end)) {
2622 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2623 dptr_close(sconn, &dptr_num);
2627 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2628 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2629 * the protocol level is less than NT1. Tested with smbclient. JRA.
2630 * This should fix the OS/2 client bug #2335.
2633 if(numentries == 0) {
2634 dptr_close(sconn, &dptr_num);
2635 if (get_Protocol() < PROTOCOL_NT1) {
2636 reply_force_doserror(req, ERRDOS, ERRnofiles);
2637 goto out;
2638 } else {
2639 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2640 ERRDOS, ERRbadfile);
2641 goto out;
2645 /* At this point pdata points to numentries directory entries. */
2647 /* Set up the return parameter block */
2648 SSVAL(params,0,dptr_num);
2649 SSVAL(params,2,numentries);
2650 SSVAL(params,4,finished);
2651 SSVAL(params,6,0); /* Never an EA error */
2652 SSVAL(params,8,last_entry_off);
2654 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2655 max_data_bytes);
2657 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2658 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2659 if (!directory) {
2660 reply_nterror(req, NT_STATUS_NO_MEMORY);
2664 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2665 smb_fn_name(req->cmd),
2666 mask, directory, dirtype, numentries ) );
2669 * Force a name mangle here to ensure that the
2670 * mask as an 8.3 name is top of the mangled cache.
2671 * The reasons for this are subtle. Don't remove
2672 * this code unless you know what you are doing
2673 * (see PR#13758). JRA.
2676 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2677 char mangled_name[13];
2678 name_to_8_3(mask, mangled_name, True, conn->params);
2680 out:
2682 if (backup_priv) {
2683 unbecome_root();
2686 TALLOC_FREE(smb_dname);
2687 return;
2690 /****************************************************************************
2691 Reply to a TRANS2_FINDNEXT.
2692 ****************************************************************************/
2694 static void call_trans2findnext(connection_struct *conn,
2695 struct smb_request *req,
2696 char **pparams, int total_params,
2697 char **ppdata, int total_data,
2698 unsigned int max_data_bytes)
2700 /* We must be careful here that we don't return more than the
2701 allowed number of data bytes. If this means returning fewer than
2702 maxentries then so be it. We assume that the redirector has
2703 enough room for the fixed number of parameter bytes it has
2704 requested. */
2705 char *params = *pparams;
2706 char *pdata = *ppdata;
2707 char *data_end;
2708 int dptr_num;
2709 int maxentries;
2710 uint16 info_level;
2711 uint32 resume_key;
2712 uint16 findnext_flags;
2713 bool close_after_request;
2714 bool close_if_end;
2715 bool requires_resume_key;
2716 bool continue_bit;
2717 bool mask_contains_wcard = False;
2718 char *resume_name = NULL;
2719 const char *mask = NULL;
2720 const char *directory = NULL;
2721 char *p = NULL;
2722 uint16 dirtype;
2723 int numentries = 0;
2724 int i, last_entry_off=0;
2725 bool finished = False;
2726 bool dont_descend = False;
2727 bool out_of_space = False;
2728 int space_remaining;
2729 struct ea_list *ea_list = NULL;
2730 NTSTATUS ntstatus = NT_STATUS_OK;
2731 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2732 TALLOC_CTX *ctx = talloc_tos();
2733 struct dptr_struct *dirptr;
2734 struct smbd_server_connection *sconn = req->sconn;
2735 bool backup_priv = false;
2737 if (total_params < 13) {
2738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2739 return;
2742 dptr_num = SVAL(params,0);
2743 maxentries = SVAL(params,2);
2744 info_level = SVAL(params,4);
2745 resume_key = IVAL(params,6);
2746 findnext_flags = SVAL(params,10);
2747 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2748 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2749 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2750 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2752 if (!continue_bit) {
2753 /* We only need resume_name if continue_bit is zero. */
2754 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2755 params+12,
2756 total_params - 12, STR_TERMINATE, &ntstatus,
2757 &mask_contains_wcard);
2758 if (!NT_STATUS_IS_OK(ntstatus)) {
2759 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2760 complain (it thinks we're asking for the directory above the shared
2761 path or an invalid name). Catch this as the resume name is only compared, never used in
2762 a file access. JRA. */
2763 srvstr_pull_talloc(ctx, params, req->flags2,
2764 &resume_name, params+12,
2765 total_params - 12,
2766 STR_TERMINATE);
2768 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2769 reply_nterror(req, ntstatus);
2770 return;
2775 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2776 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2777 resume_key = %d resume name = %s continue=%d level = %d\n",
2778 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2779 requires_resume_key, resume_key,
2780 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2782 if (!maxentries) {
2783 /* W2K3 seems to treat zero as 1. */
2784 maxentries = 1;
2787 switch (info_level) {
2788 case SMB_FIND_INFO_STANDARD:
2789 case SMB_FIND_EA_SIZE:
2790 case SMB_FIND_EA_LIST:
2791 case SMB_FIND_FILE_DIRECTORY_INFO:
2792 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2793 case SMB_FIND_FILE_NAMES_INFO:
2794 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2795 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2796 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2797 break;
2798 case SMB_FIND_FILE_UNIX:
2799 case SMB_FIND_FILE_UNIX_INFO2:
2800 /* Always use filesystem for UNIX mtime query. */
2801 ask_sharemode = false;
2802 if (!lp_unix_extensions()) {
2803 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2804 return;
2806 break;
2807 default:
2808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2809 return;
2812 if (info_level == SMB_FIND_EA_LIST) {
2813 uint32 ea_size;
2815 if (total_data < 4) {
2816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2817 return;
2820 ea_size = IVAL(pdata,0);
2821 if (ea_size != total_data) {
2822 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2823 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2825 return;
2828 if (!lp_ea_support(SNUM(conn))) {
2829 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2830 return;
2833 /* Pull out the list of names. */
2834 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2835 if (!ea_list) {
2836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2837 return;
2841 *ppdata = (char *)SMB_REALLOC(
2842 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2843 if(*ppdata == NULL) {
2844 reply_nterror(req, NT_STATUS_NO_MEMORY);
2845 return;
2848 pdata = *ppdata;
2849 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2851 /* Realloc the params space */
2852 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2853 if(*pparams == NULL ) {
2854 reply_nterror(req, NT_STATUS_NO_MEMORY);
2855 return;
2858 params = *pparams;
2860 /* Check that the dptr is valid */
2861 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2862 reply_nterror(req, STATUS_NO_MORE_FILES);
2863 return;
2866 directory = dptr_path(sconn, dptr_num);
2868 /* Get the wildcard mask from the dptr */
2869 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2870 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2871 reply_nterror(req, STATUS_NO_MORE_FILES);
2872 return;
2875 /* Get the attr mask from the dptr */
2876 dirtype = dptr_attr(sconn, dptr_num);
2878 backup_priv = dptr_get_priv(dirptr);
2880 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2881 "backup_priv = %d\n",
2882 dptr_num, mask, dirtype,
2883 (long)dirptr,
2884 dptr_TellDir(dirptr),
2885 (int)backup_priv));
2887 /* Initialize per TRANS2_FIND_NEXT operation data */
2888 dptr_init_search_op(dirptr);
2890 /* We don't need to check for VOL here as this is returned by
2891 a different TRANS2 call. */
2893 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2894 directory,lp_dontdescend(ctx, SNUM(conn))));
2895 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2896 dont_descend = True;
2898 p = pdata;
2899 space_remaining = max_data_bytes;
2900 out_of_space = False;
2902 if (backup_priv) {
2903 become_root();
2907 * Seek to the correct position. We no longer use the resume key but
2908 * depend on the last file name instead.
2911 if(!continue_bit && resume_name && *resume_name) {
2912 SMB_STRUCT_STAT st;
2914 long current_pos = 0;
2916 * Remember, name_to_8_3 is called by
2917 * get_lanman2_dir_entry(), so the resume name
2918 * could be mangled. Ensure we check the unmangled name.
2921 if (mangle_is_mangled(resume_name, conn->params)) {
2922 char *new_resume_name = NULL;
2923 mangle_lookup_name_from_8_3(ctx,
2924 resume_name,
2925 &new_resume_name,
2926 conn->params);
2927 if (new_resume_name) {
2928 resume_name = new_resume_name;
2933 * Fix for NT redirector problem triggered by resume key indexes
2934 * changing between directory scans. We now return a resume key of 0
2935 * and instead look for the filename to continue from (also given
2936 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2937 * findfirst/findnext (as is usual) then the directory pointer
2938 * should already be at the correct place.
2941 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2942 } /* end if resume_name && !continue_bit */
2944 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2945 bool got_exact_match = False;
2947 /* this is a heuristic to avoid seeking the dirptr except when
2948 absolutely necessary. It allows for a filename of about 40 chars */
2949 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2950 out_of_space = True;
2951 finished = False;
2952 } else {
2953 finished = !get_lanman2_dir_entry(ctx,
2954 conn,
2955 dirptr,
2956 req->flags2,
2957 mask,dirtype,info_level,
2958 requires_resume_key,dont_descend,
2959 ask_sharemode,
2960 &p,pdata,data_end,
2961 space_remaining, &out_of_space,
2962 &got_exact_match,
2963 &last_entry_off, ea_list);
2966 if (finished && out_of_space)
2967 finished = False;
2969 if (!finished && !out_of_space)
2970 numentries++;
2973 * As an optimisation if we know we aren't looking
2974 * for a wildcard name (ie. the name matches the wildcard exactly)
2975 * then we can finish on any (first) match.
2976 * This speeds up large directory searches. JRA.
2979 if(got_exact_match)
2980 finished = True;
2982 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2985 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2986 smb_fn_name(req->cmd),
2987 mask, directory, dirtype, numentries ) );
2989 /* Check if we can close the dirptr */
2990 if(close_after_request || (finished && close_if_end)) {
2991 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2992 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2995 if (backup_priv) {
2996 unbecome_root();
2999 /* Set up the return parameter block */
3000 SSVAL(params,0,numentries);
3001 SSVAL(params,2,finished);
3002 SSVAL(params,4,0); /* Never an EA error */
3003 SSVAL(params,6,last_entry_off);
3005 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3006 max_data_bytes);
3008 return;
3011 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3013 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3014 return objid;
3017 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3019 SMB_ASSERT(extended_info != NULL);
3021 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3022 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3023 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3024 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3025 #ifdef SAMBA_VERSION_REVISION
3026 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3027 #endif
3028 extended_info->samba_subversion = 0;
3029 #ifdef SAMBA_VERSION_RC_RELEASE
3030 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3031 #else
3032 #ifdef SAMBA_VERSION_PRE_RELEASE
3033 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3034 #endif
3035 #endif
3036 #ifdef SAMBA_VERSION_VENDOR_PATCH
3037 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3038 #endif
3039 extended_info->samba_gitcommitdate = 0;
3040 #ifdef SAMBA_VERSION_COMMIT_TIME
3041 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3042 #endif
3044 memset(extended_info->samba_version_string, 0,
3045 sizeof(extended_info->samba_version_string));
3047 snprintf (extended_info->samba_version_string,
3048 sizeof(extended_info->samba_version_string),
3049 "%s", samba_version_string());
3052 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3053 TALLOC_CTX *mem_ctx,
3054 uint16_t info_level,
3055 uint16_t flags2,
3056 unsigned int max_data_bytes,
3057 struct smb_filename *fname,
3058 char **ppdata,
3059 int *ret_data_len)
3061 char *pdata, *end_data;
3062 int data_len = 0, len;
3063 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3064 int snum = SNUM(conn);
3065 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3066 char *filename = NULL;
3067 uint32 additional_flags = 0;
3068 struct smb_filename smb_fname;
3069 SMB_STRUCT_STAT st;
3071 if (fname == NULL || fname->base_name == NULL) {
3072 filename = ".";
3073 } else {
3074 filename = fname->base_name;
3077 if (IS_IPC(conn)) {
3078 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3079 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3080 "info level (0x%x) on IPC$.\n",
3081 (unsigned int)info_level));
3082 return NT_STATUS_ACCESS_DENIED;
3086 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3088 ZERO_STRUCT(smb_fname);
3089 smb_fname.base_name = discard_const_p(char, filename);
3091 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3092 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3093 return map_nt_error_from_unix(errno);
3096 st = smb_fname.st;
3098 *ppdata = (char *)SMB_REALLOC(
3099 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3100 if (*ppdata == NULL) {
3101 return NT_STATUS_NO_MEMORY;
3104 pdata = *ppdata;
3105 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3106 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3108 switch (info_level) {
3109 case SMB_INFO_ALLOCATION:
3111 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3112 data_len = 18;
3113 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3114 return map_nt_error_from_unix(errno);
3117 block_size = lp_block_size(snum);
3118 if (bsize < block_size) {
3119 uint64_t factor = block_size/bsize;
3120 bsize = block_size;
3121 dsize /= factor;
3122 dfree /= factor;
3124 if (bsize > block_size) {
3125 uint64_t factor = bsize/block_size;
3126 bsize = block_size;
3127 dsize *= factor;
3128 dfree *= factor;
3130 bytes_per_sector = 512;
3131 sectors_per_unit = bsize/bytes_per_sector;
3133 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3134 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3135 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3137 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3138 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3139 SIVAL(pdata,l1_cUnit,dsize);
3140 SIVAL(pdata,l1_cUnitAvail,dfree);
3141 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3142 break;
3145 case SMB_INFO_VOLUME:
3146 /* Return volume name */
3148 * Add volume serial number - hash of a combination of
3149 * the called hostname and the service name.
3151 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3153 * Win2k3 and previous mess this up by sending a name length
3154 * one byte short. I believe only older clients (OS/2 Win9x) use
3155 * this call so try fixing this by adding a terminating null to
3156 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3158 len = srvstr_push(
3159 pdata, flags2,
3160 pdata+l2_vol_szVolLabel, vname,
3161 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3162 STR_NOALIGN|STR_TERMINATE);
3163 SCVAL(pdata,l2_vol_cch,len);
3164 data_len = l2_vol_szVolLabel + len;
3165 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3166 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3167 len, vname));
3168 break;
3170 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3171 case SMB_FS_ATTRIBUTE_INFORMATION:
3173 additional_flags = 0;
3174 #if defined(HAVE_SYS_QUOTAS)
3175 additional_flags |= FILE_VOLUME_QUOTAS;
3176 #endif
3178 if(lp_nt_acl_support(SNUM(conn))) {
3179 additional_flags |= FILE_PERSISTENT_ACLS;
3182 /* Capabilities are filled in at connection time through STATVFS call */
3183 additional_flags |= conn->fs_capabilities;
3184 additional_flags |= lp_parm_int(conn->params->service,
3185 "share", "fake_fscaps",
3188 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3189 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3190 additional_flags); /* FS ATTRIBUTES */
3192 SIVAL(pdata,4,255); /* Max filename component length */
3193 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3194 and will think we can't do long filenames */
3195 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3196 PTR_DIFF(end_data, pdata+12),
3197 STR_UNICODE);
3198 SIVAL(pdata,8,len);
3199 data_len = 12 + len;
3200 break;
3202 case SMB_QUERY_FS_LABEL_INFO:
3203 case SMB_FS_LABEL_INFORMATION:
3204 len = srvstr_push(pdata, flags2, pdata+4, vname,
3205 PTR_DIFF(end_data, pdata+4), 0);
3206 data_len = 4 + len;
3207 SIVAL(pdata,0,len);
3208 break;
3210 case SMB_QUERY_FS_VOLUME_INFO:
3211 case SMB_FS_VOLUME_INFORMATION:
3214 * Add volume serial number - hash of a combination of
3215 * the called hostname and the service name.
3217 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3218 (str_checksum(get_local_machine_name())<<16));
3220 /* Max label len is 32 characters. */
3221 len = srvstr_push(pdata, flags2, pdata+18, vname,
3222 PTR_DIFF(end_data, pdata+18),
3223 STR_UNICODE);
3224 SIVAL(pdata,12,len);
3225 data_len = 18+len;
3227 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3228 (int)strlen(vname),vname,
3229 lp_servicename(talloc_tos(), snum)));
3230 break;
3232 case SMB_QUERY_FS_SIZE_INFO:
3233 case SMB_FS_SIZE_INFORMATION:
3235 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3236 data_len = 24;
3237 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3238 return map_nt_error_from_unix(errno);
3240 block_size = lp_block_size(snum);
3241 if (bsize < block_size) {
3242 uint64_t factor = block_size/bsize;
3243 bsize = block_size;
3244 dsize /= factor;
3245 dfree /= factor;
3247 if (bsize > block_size) {
3248 uint64_t factor = bsize/block_size;
3249 bsize = block_size;
3250 dsize *= factor;
3251 dfree *= factor;
3253 bytes_per_sector = 512;
3254 sectors_per_unit = bsize/bytes_per_sector;
3255 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3256 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3257 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3258 SBIG_UINT(pdata,0,dsize);
3259 SBIG_UINT(pdata,8,dfree);
3260 SIVAL(pdata,16,sectors_per_unit);
3261 SIVAL(pdata,20,bytes_per_sector);
3262 break;
3265 case SMB_FS_FULL_SIZE_INFORMATION:
3267 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3268 data_len = 32;
3269 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3270 return map_nt_error_from_unix(errno);
3272 block_size = lp_block_size(snum);
3273 if (bsize < block_size) {
3274 uint64_t factor = block_size/bsize;
3275 bsize = block_size;
3276 dsize /= factor;
3277 dfree /= factor;
3279 if (bsize > block_size) {
3280 uint64_t factor = bsize/block_size;
3281 bsize = block_size;
3282 dsize *= factor;
3283 dfree *= factor;
3285 bytes_per_sector = 512;
3286 sectors_per_unit = bsize/bytes_per_sector;
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3290 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3291 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3292 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3293 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3294 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3295 break;
3298 case SMB_QUERY_FS_DEVICE_INFO:
3299 case SMB_FS_DEVICE_INFORMATION:
3301 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3303 if (!CAN_WRITE(conn)) {
3304 characteristics |= FILE_READ_ONLY_DEVICE;
3306 data_len = 8;
3307 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3308 SIVAL(pdata,4,characteristics);
3309 break;
3312 #ifdef HAVE_SYS_QUOTAS
3313 case SMB_FS_QUOTA_INFORMATION:
3315 * what we have to send --metze:
3317 * Unknown1: 24 NULL bytes
3318 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3319 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3320 * Quota Flags: 2 byte :
3321 * Unknown3: 6 NULL bytes
3323 * 48 bytes total
3325 * details for Quota Flags:
3327 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3328 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3329 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3330 * 0x0001 Enable Quotas: enable quota for this fs
3334 /* we need to fake up a fsp here,
3335 * because its not send in this call
3337 files_struct fsp;
3338 SMB_NTQUOTA_STRUCT quotas;
3340 ZERO_STRUCT(fsp);
3341 ZERO_STRUCT(quotas);
3343 fsp.conn = conn;
3344 fsp.fnum = FNUM_FIELD_INVALID;
3346 /* access check */
3347 if (get_current_uid(conn) != 0) {
3348 DEBUG(0,("set_user_quota: access_denied "
3349 "service [%s] user [%s]\n",
3350 lp_servicename(talloc_tos(), SNUM(conn)),
3351 conn->session_info->unix_info->unix_name));
3352 return NT_STATUS_ACCESS_DENIED;
3355 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3356 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3357 return map_nt_error_from_unix(errno);
3360 data_len = 48;
3362 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3363 lp_servicename(talloc_tos(), SNUM(conn))));
3365 /* Unknown1 24 NULL bytes*/
3366 SBIG_UINT(pdata,0,(uint64_t)0);
3367 SBIG_UINT(pdata,8,(uint64_t)0);
3368 SBIG_UINT(pdata,16,(uint64_t)0);
3370 /* Default Soft Quota 8 bytes */
3371 SBIG_UINT(pdata,24,quotas.softlim);
3373 /* Default Hard Quota 8 bytes */
3374 SBIG_UINT(pdata,32,quotas.hardlim);
3376 /* Quota flag 2 bytes */
3377 SSVAL(pdata,40,quotas.qflags);
3379 /* Unknown3 6 NULL bytes */
3380 SSVAL(pdata,42,0);
3381 SIVAL(pdata,44,0);
3383 break;
3385 #endif /* HAVE_SYS_QUOTAS */
3386 case SMB_FS_OBJECTID_INFORMATION:
3388 unsigned char objid[16];
3389 struct smb_extended_info extended_info;
3390 memcpy(pdata,create_volume_objectid(conn, objid),16);
3391 samba_extended_info_version (&extended_info);
3392 SIVAL(pdata,16,extended_info.samba_magic);
3393 SIVAL(pdata,20,extended_info.samba_version);
3394 SIVAL(pdata,24,extended_info.samba_subversion);
3395 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3396 memcpy(pdata+36,extended_info.samba_version_string,28);
3397 data_len = 64;
3398 break;
3402 * Query the version and capabilities of the CIFS UNIX extensions
3403 * in use.
3406 case SMB_QUERY_CIFS_UNIX_INFO:
3408 bool large_write = lp_min_receive_file_size() &&
3409 !srv_is_signing_active(conn->sconn);
3410 bool large_read = !srv_is_signing_active(conn->sconn);
3411 int encrypt_caps = 0;
3413 if (!lp_unix_extensions()) {
3414 return NT_STATUS_INVALID_LEVEL;
3417 switch (conn->encrypt_level) {
3418 case SMB_SIGNING_OFF:
3419 encrypt_caps = 0;
3420 break;
3421 case SMB_SIGNING_IF_REQUIRED:
3422 case SMB_SIGNING_DEFAULT:
3423 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3424 break;
3425 case SMB_SIGNING_REQUIRED:
3426 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3427 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3428 large_write = false;
3429 large_read = false;
3430 break;
3433 data_len = 12;
3434 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3435 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3437 /* We have POSIX ACLs, pathname, encryption,
3438 * large read/write, and locking capability. */
3440 SBIG_UINT(pdata,4,((uint64_t)(
3441 CIFS_UNIX_POSIX_ACLS_CAP|
3442 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3443 CIFS_UNIX_FCNTL_LOCKS_CAP|
3444 CIFS_UNIX_EXTATTR_CAP|
3445 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3446 encrypt_caps|
3447 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3448 (large_write ?
3449 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3450 break;
3453 case SMB_QUERY_POSIX_FS_INFO:
3455 int rc;
3456 vfs_statvfs_struct svfs;
3458 if (!lp_unix_extensions()) {
3459 return NT_STATUS_INVALID_LEVEL;
3462 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3464 if (!rc) {
3465 data_len = 56;
3466 SIVAL(pdata,0,svfs.OptimalTransferSize);
3467 SIVAL(pdata,4,svfs.BlockSize);
3468 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3469 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3470 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3471 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3472 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3473 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3474 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3475 #ifdef EOPNOTSUPP
3476 } else if (rc == EOPNOTSUPP) {
3477 return NT_STATUS_INVALID_LEVEL;
3478 #endif /* EOPNOTSUPP */
3479 } else {
3480 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3481 return NT_STATUS_DOS(ERRSRV, ERRerror);
3483 break;
3486 case SMB_QUERY_POSIX_WHOAMI:
3488 uint32_t flags = 0;
3489 uint32_t sid_bytes;
3490 int i;
3492 if (!lp_unix_extensions()) {
3493 return NT_STATUS_INVALID_LEVEL;
3496 if (max_data_bytes < 40) {
3497 return NT_STATUS_BUFFER_TOO_SMALL;
3500 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3501 flags |= SMB_WHOAMI_GUEST;
3504 /* NOTE: 8 bytes for UID/GID, irrespective of native
3505 * platform size. This matches
3506 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3508 data_len = 4 /* flags */
3509 + 4 /* flag mask */
3510 + 8 /* uid */
3511 + 8 /* gid */
3512 + 4 /* ngroups */
3513 + 4 /* num_sids */
3514 + 4 /* SID bytes */
3515 + 4 /* pad/reserved */
3516 + (conn->session_info->unix_token->ngroups * 8)
3517 /* groups list */
3518 + (conn->session_info->security_token->num_sids *
3519 SID_MAX_SIZE)
3520 /* SID list */;
3522 SIVAL(pdata, 0, flags);
3523 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3524 SBIG_UINT(pdata, 8,
3525 (uint64_t)conn->session_info->unix_token->uid);
3526 SBIG_UINT(pdata, 16,
3527 (uint64_t)conn->session_info->unix_token->gid);
3530 if (data_len >= max_data_bytes) {
3531 /* Potential overflow, skip the GIDs and SIDs. */
3533 SIVAL(pdata, 24, 0); /* num_groups */
3534 SIVAL(pdata, 28, 0); /* num_sids */
3535 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3536 SIVAL(pdata, 36, 0); /* reserved */
3538 data_len = 40;
3539 break;
3542 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3543 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3545 /* We walk the SID list twice, but this call is fairly
3546 * infrequent, and I don't expect that it's performance
3547 * sensitive -- jpeach
3549 for (i = 0, sid_bytes = 0;
3550 i < conn->session_info->security_token->num_sids; ++i) {
3551 sid_bytes += ndr_size_dom_sid(
3552 &conn->session_info->security_token->sids[i],
3556 /* SID list byte count */
3557 SIVAL(pdata, 32, sid_bytes);
3559 /* 4 bytes pad/reserved - must be zero */
3560 SIVAL(pdata, 36, 0);
3561 data_len = 40;
3563 /* GID list */
3564 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3565 SBIG_UINT(pdata, data_len,
3566 (uint64_t)conn->session_info->unix_token->groups[i]);
3567 data_len += 8;
3570 /* SID list */
3571 for (i = 0;
3572 i < conn->session_info->security_token->num_sids; ++i) {
3573 int sid_len = ndr_size_dom_sid(
3574 &conn->session_info->security_token->sids[i],
3577 sid_linearize(pdata + data_len, sid_len,
3578 &conn->session_info->security_token->sids[i]);
3579 data_len += sid_len;
3582 break;
3585 case SMB_MAC_QUERY_FS_INFO:
3587 * Thursby MAC extension... ONLY on NTFS filesystems
3588 * once we do streams then we don't need this
3590 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3591 data_len = 88;
3592 SIVAL(pdata,84,0x100); /* Don't support mac... */
3593 break;
3595 /* drop through */
3596 default:
3597 return NT_STATUS_INVALID_LEVEL;
3600 *ret_data_len = data_len;
3601 return NT_STATUS_OK;
3604 /****************************************************************************
3605 Reply to a TRANS2_QFSINFO (query filesystem info).
3606 ****************************************************************************/
3608 static void call_trans2qfsinfo(connection_struct *conn,
3609 struct smb_request *req,
3610 char **pparams, int total_params,
3611 char **ppdata, int total_data,
3612 unsigned int max_data_bytes)
3614 char *params = *pparams;
3615 uint16_t info_level;
3616 int data_len = 0;
3617 NTSTATUS status;
3619 if (total_params < 2) {
3620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3621 return;
3624 info_level = SVAL(params,0);
3626 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3627 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3628 DEBUG(0,("call_trans2qfsinfo: encryption required "
3629 "and info level 0x%x sent.\n",
3630 (unsigned int)info_level));
3631 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3632 return;
3636 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3638 status = smbd_do_qfsinfo(conn, req,
3639 info_level,
3640 req->flags2,
3641 max_data_bytes,
3642 NULL,
3643 ppdata, &data_len);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 reply_nterror(req, status);
3646 return;
3649 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3650 max_data_bytes);
3652 DEBUG( 4, ( "%s info_level = %d\n",
3653 smb_fn_name(req->cmd), info_level) );
3655 return;
3658 /****************************************************************************
3659 Reply to a TRANS2_SETFSINFO (set filesystem info).
3660 ****************************************************************************/
3662 static void call_trans2setfsinfo(connection_struct *conn,
3663 struct smb_request *req,
3664 char **pparams, int total_params,
3665 char **ppdata, int total_data,
3666 unsigned int max_data_bytes)
3668 struct smbd_server_connection *sconn = req->sconn;
3669 char *pdata = *ppdata;
3670 char *params = *pparams;
3671 uint16 info_level;
3673 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3674 lp_servicename(talloc_tos(), SNUM(conn))));
3676 /* */
3677 if (total_params < 4) {
3678 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3679 total_params));
3680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3681 return;
3684 info_level = SVAL(params,2);
3686 if (IS_IPC(conn)) {
3687 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3688 info_level != SMB_SET_CIFS_UNIX_INFO) {
3689 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3690 "info level (0x%x) on IPC$.\n",
3691 (unsigned int)info_level));
3692 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3693 return;
3697 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3698 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3699 DEBUG(0,("call_trans2setfsinfo: encryption required "
3700 "and info level 0x%x sent.\n",
3701 (unsigned int)info_level));
3702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3703 return;
3707 switch(info_level) {
3708 case SMB_SET_CIFS_UNIX_INFO:
3709 if (!lp_unix_extensions()) {
3710 DEBUG(2,("call_trans2setfsinfo: "
3711 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3712 "unix extensions off\n"));
3713 reply_nterror(req,
3714 NT_STATUS_INVALID_LEVEL);
3715 return;
3718 /* There should be 12 bytes of capabilities set. */
3719 if (total_data < 12) {
3720 reply_nterror(
3721 req,
3722 NT_STATUS_INVALID_PARAMETER);
3723 return;
3725 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3726 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3727 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3728 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3729 /* Just print these values for now. */
3730 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3731 "major = %u, minor = %u cap_low = 0x%x, "
3732 "cap_high = 0x%xn",
3733 (unsigned int)sconn->
3734 smb1.unix_info.client_major,
3735 (unsigned int)sconn->
3736 smb1.unix_info.client_minor,
3737 (unsigned int)sconn->
3738 smb1.unix_info.client_cap_low,
3739 (unsigned int)sconn->
3740 smb1.unix_info.client_cap_high));
3742 /* Here is where we must switch to posix pathname processing... */
3743 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3744 lp_set_posix_pathnames();
3745 mangle_change_to_posix();
3748 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3749 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3750 /* Client that knows how to do posix locks,
3751 * but not posix open/mkdir operations. Set a
3752 * default type for read/write checks. */
3754 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3757 break;
3759 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3761 NTSTATUS status;
3762 size_t param_len = 0;
3763 size_t data_len = total_data;
3765 if (!lp_unix_extensions()) {
3766 reply_nterror(
3767 req,
3768 NT_STATUS_INVALID_LEVEL);
3769 return;
3772 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3773 reply_nterror(
3774 req,
3775 NT_STATUS_NOT_SUPPORTED);
3776 return;
3779 if (req->sconn->smb1.echo_handler.trusted_fde) {
3780 DEBUG( 2,("call_trans2setfsinfo: "
3781 "request transport encryption disabled"
3782 "with 'fork echo handler = yes'\n"));
3783 reply_nterror(
3784 req,
3785 NT_STATUS_NOT_SUPPORTED);
3786 return;
3789 DEBUG( 4,("call_trans2setfsinfo: "
3790 "request transport encryption.\n"));
3792 status = srv_request_encryption_setup(conn,
3793 (unsigned char **)ppdata,
3794 &data_len,
3795 (unsigned char **)pparams,
3796 &param_len);
3798 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3799 !NT_STATUS_IS_OK(status)) {
3800 reply_nterror(req, status);
3801 return;
3804 send_trans2_replies(conn, req,
3805 *pparams,
3806 param_len,
3807 *ppdata,
3808 data_len,
3809 max_data_bytes);
3811 if (NT_STATUS_IS_OK(status)) {
3812 /* Server-side transport
3813 * encryption is now *on*. */
3814 status = srv_encryption_start(conn);
3815 if (!NT_STATUS_IS_OK(status)) {
3816 char *reason = talloc_asprintf(talloc_tos(),
3817 "Failure in setting "
3818 "up encrypted transport: %s",
3819 nt_errstr(status));
3820 exit_server_cleanly(reason);
3823 return;
3826 case SMB_FS_QUOTA_INFORMATION:
3828 files_struct *fsp = NULL;
3829 SMB_NTQUOTA_STRUCT quotas;
3831 ZERO_STRUCT(quotas);
3833 /* access check */
3834 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3835 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3836 lp_servicename(talloc_tos(), SNUM(conn)),
3837 conn->session_info->unix_info->unix_name));
3838 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3839 return;
3842 /* note: normaly there're 48 bytes,
3843 * but we didn't use the last 6 bytes for now
3844 * --metze
3846 fsp = file_fsp(req, SVAL(params,0));
3848 if (!check_fsp_ntquota_handle(conn, req,
3849 fsp)) {
3850 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3851 reply_nterror(
3852 req, NT_STATUS_INVALID_HANDLE);
3853 return;
3856 if (total_data < 42) {
3857 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3858 total_data));
3859 reply_nterror(
3860 req,
3861 NT_STATUS_INVALID_PARAMETER);
3862 return;
3865 /* unknown_1 24 NULL bytes in pdata*/
3867 /* the soft quotas 8 bytes (uint64_t)*/
3868 quotas.softlim = BVAL(pdata,24);
3870 /* the hard quotas 8 bytes (uint64_t)*/
3871 quotas.hardlim = BVAL(pdata,32);
3873 /* quota_flags 2 bytes **/
3874 quotas.qflags = SVAL(pdata,40);
3876 /* unknown_2 6 NULL bytes follow*/
3878 /* now set the quotas */
3879 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3880 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3881 reply_nterror(req, map_nt_error_from_unix(errno));
3882 return;
3885 break;
3887 default:
3888 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3889 info_level));
3890 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3891 return;
3892 break;
3896 * sending this reply works fine,
3897 * but I'm not sure it's the same
3898 * like windows do...
3899 * --metze
3901 reply_outbuf(req, 10, 0);
3904 #if defined(HAVE_POSIX_ACLS)
3905 /****************************************************************************
3906 Utility function to count the number of entries in a POSIX acl.
3907 ****************************************************************************/
3909 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3911 unsigned int ace_count = 0;
3912 int entry_id = SMB_ACL_FIRST_ENTRY;
3913 SMB_ACL_ENTRY_T entry;
3915 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3916 /* get_next... */
3917 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3918 entry_id = SMB_ACL_NEXT_ENTRY;
3920 ace_count++;
3922 return ace_count;
3925 /****************************************************************************
3926 Utility function to marshall a POSIX acl into wire format.
3927 ****************************************************************************/
3929 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3931 int entry_id = SMB_ACL_FIRST_ENTRY;
3932 SMB_ACL_ENTRY_T entry;
3934 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3935 SMB_ACL_TAG_T tagtype;
3936 SMB_ACL_PERMSET_T permset;
3937 unsigned char perms = 0;
3938 unsigned int own_grp;
3940 /* get_next... */
3941 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3942 entry_id = SMB_ACL_NEXT_ENTRY;
3945 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3946 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3947 return False;
3950 if (sys_acl_get_permset(entry, &permset) == -1) {
3951 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3952 return False;
3955 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3956 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3957 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3959 SCVAL(pdata,1,perms);
3961 switch (tagtype) {
3962 case SMB_ACL_USER_OBJ:
3963 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3964 own_grp = (unsigned int)pst->st_ex_uid;
3965 SIVAL(pdata,2,own_grp);
3966 SIVAL(pdata,6,0);
3967 break;
3968 case SMB_ACL_USER:
3970 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3971 if (!puid) {
3972 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3973 return False;
3975 own_grp = (unsigned int)*puid;
3976 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3977 SIVAL(pdata,2,own_grp);
3978 SIVAL(pdata,6,0);
3979 break;
3981 case SMB_ACL_GROUP_OBJ:
3982 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3983 own_grp = (unsigned int)pst->st_ex_gid;
3984 SIVAL(pdata,2,own_grp);
3985 SIVAL(pdata,6,0);
3986 break;
3987 case SMB_ACL_GROUP:
3989 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3990 if (!pgid) {
3991 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3992 return False;
3994 own_grp = (unsigned int)*pgid;
3995 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3996 SIVAL(pdata,2,own_grp);
3997 SIVAL(pdata,6,0);
3998 break;
4000 case SMB_ACL_MASK:
4001 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4002 SIVAL(pdata,2,0xFFFFFFFF);
4003 SIVAL(pdata,6,0xFFFFFFFF);
4004 break;
4005 case SMB_ACL_OTHER:
4006 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4007 SIVAL(pdata,2,0xFFFFFFFF);
4008 SIVAL(pdata,6,0xFFFFFFFF);
4009 break;
4010 default:
4011 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4012 return False;
4014 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4017 return True;
4019 #endif
4021 /****************************************************************************
4022 Store the FILE_UNIX_BASIC info.
4023 ****************************************************************************/
4025 static char *store_file_unix_basic(connection_struct *conn,
4026 char *pdata,
4027 files_struct *fsp,
4028 const SMB_STRUCT_STAT *psbuf)
4030 uint64_t file_index = get_FileIndex(conn, psbuf);
4031 dev_t devno;
4033 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4034 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4036 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4037 pdata += 8;
4039 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4040 pdata += 8;
4042 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4043 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4044 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4045 pdata += 24;
4047 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4048 SIVAL(pdata,4,0);
4049 pdata += 8;
4051 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4052 SIVAL(pdata,4,0);
4053 pdata += 8;
4055 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4056 pdata += 4;
4058 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4059 devno = psbuf->st_ex_rdev;
4060 } else {
4061 devno = psbuf->st_ex_dev;
4064 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4065 SIVAL(pdata,4,0);
4066 pdata += 8;
4068 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4069 SIVAL(pdata,4,0);
4070 pdata += 8;
4072 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4073 pdata += 8;
4075 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4076 SIVAL(pdata,4,0);
4077 pdata += 8;
4079 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4080 SIVAL(pdata,4,0);
4081 pdata += 8;
4083 return pdata;
4086 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4087 * the chflags(2) (or equivalent) flags.
4089 * XXX: this really should be behind the VFS interface. To do this, we would
4090 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4091 * Each VFS module could then implement its own mapping as appropriate for the
4092 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4094 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4095 info2_flags_map[] =
4097 #ifdef UF_NODUMP
4098 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4099 #endif
4101 #ifdef UF_IMMUTABLE
4102 { UF_IMMUTABLE, EXT_IMMUTABLE },
4103 #endif
4105 #ifdef UF_APPEND
4106 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4107 #endif
4109 #ifdef UF_HIDDEN
4110 { UF_HIDDEN, EXT_HIDDEN },
4111 #endif
4113 /* Do not remove. We need to guarantee that this array has at least one
4114 * entry to build on HP-UX.
4116 { 0, 0 }
4120 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4121 uint32 *smb_fflags, uint32 *smb_fmask)
4123 int i;
4125 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4126 *smb_fmask |= info2_flags_map[i].smb_fflag;
4127 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4128 *smb_fflags |= info2_flags_map[i].smb_fflag;
4133 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4134 const uint32 smb_fflags,
4135 const uint32 smb_fmask,
4136 int *stat_fflags)
4138 uint32 max_fmask = 0;
4139 int i;
4141 *stat_fflags = psbuf->st_ex_flags;
4143 /* For each flags requested in smb_fmask, check the state of the
4144 * corresponding flag in smb_fflags and set or clear the matching
4145 * stat flag.
4148 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4149 max_fmask |= info2_flags_map[i].smb_fflag;
4150 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4151 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4152 *stat_fflags |= info2_flags_map[i].stat_fflag;
4153 } else {
4154 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4159 /* If smb_fmask is asking to set any bits that are not supported by
4160 * our flag mappings, we should fail.
4162 if ((smb_fmask & max_fmask) != smb_fmask) {
4163 return False;
4166 return True;
4170 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4171 * of file flags and birth (create) time.
4173 static char *store_file_unix_basic_info2(connection_struct *conn,
4174 char *pdata,
4175 files_struct *fsp,
4176 const SMB_STRUCT_STAT *psbuf)
4178 uint32 file_flags = 0;
4179 uint32 flags_mask = 0;
4181 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4183 /* Create (birth) time 64 bit */
4184 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4185 pdata += 8;
4187 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4188 SIVAL(pdata, 0, file_flags); /* flags */
4189 SIVAL(pdata, 4, flags_mask); /* mask */
4190 pdata += 8;
4192 return pdata;
4195 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4196 const struct stream_struct *streams,
4197 char *data,
4198 unsigned int max_data_bytes,
4199 unsigned int *data_size)
4201 unsigned int i;
4202 unsigned int ofs = 0;
4204 for (i = 0; i < num_streams; i++) {
4205 unsigned int next_offset;
4206 size_t namelen;
4207 smb_ucs2_t *namebuf;
4209 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4210 streams[i].name, &namelen) ||
4211 namelen <= 2)
4213 return NT_STATUS_INVALID_PARAMETER;
4217 * name_buf is now null-terminated, we need to marshall as not
4218 * terminated
4221 namelen -= 2;
4224 * We cannot overflow ...
4226 if ((ofs + 24 + namelen) > max_data_bytes) {
4227 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4228 i));
4229 TALLOC_FREE(namebuf);
4230 return STATUS_BUFFER_OVERFLOW;
4233 SIVAL(data, ofs+4, namelen);
4234 SOFF_T(data, ofs+8, streams[i].size);
4235 SOFF_T(data, ofs+16, streams[i].alloc_size);
4236 memcpy(data+ofs+24, namebuf, namelen);
4237 TALLOC_FREE(namebuf);
4239 next_offset = ofs + 24 + namelen;
4241 if (i == num_streams-1) {
4242 SIVAL(data, ofs, 0);
4244 else {
4245 unsigned int align = ndr_align_size(next_offset, 8);
4247 if ((next_offset + align) > max_data_bytes) {
4248 DEBUG(10, ("refusing to overflow align "
4249 "reply at stream %u\n",
4250 i));
4251 TALLOC_FREE(namebuf);
4252 return STATUS_BUFFER_OVERFLOW;
4255 memset(data+next_offset, 0, align);
4256 next_offset += align;
4258 SIVAL(data, ofs, next_offset - ofs);
4259 ofs = next_offset;
4262 ofs = next_offset;
4265 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4267 *data_size = ofs;
4269 return NT_STATUS_OK;
4272 /****************************************************************************
4273 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4274 ****************************************************************************/
4276 static void call_trans2qpipeinfo(connection_struct *conn,
4277 struct smb_request *req,
4278 unsigned int tran_call,
4279 char **pparams, int total_params,
4280 char **ppdata, int total_data,
4281 unsigned int max_data_bytes)
4283 char *params = *pparams;
4284 char *pdata = *ppdata;
4285 unsigned int data_size = 0;
4286 unsigned int param_size = 2;
4287 uint16 info_level;
4288 files_struct *fsp;
4290 if (!params) {
4291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4292 return;
4295 if (total_params < 4) {
4296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4297 return;
4300 fsp = file_fsp(req, SVAL(params,0));
4301 if (!fsp_is_np(fsp)) {
4302 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4303 return;
4306 info_level = SVAL(params,2);
4308 *pparams = (char *)SMB_REALLOC(*pparams,2);
4309 if (*pparams == NULL) {
4310 reply_nterror(req, NT_STATUS_NO_MEMORY);
4311 return;
4313 params = *pparams;
4314 SSVAL(params,0,0);
4315 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4316 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4317 if (*ppdata == NULL ) {
4318 reply_nterror(req, NT_STATUS_NO_MEMORY);
4319 return;
4321 pdata = *ppdata;
4323 switch (info_level) {
4324 case SMB_FILE_STANDARD_INFORMATION:
4325 memset(pdata,0,24);
4326 SOFF_T(pdata,0,4096LL);
4327 SIVAL(pdata,16,1);
4328 SIVAL(pdata,20,1);
4329 data_size = 24;
4330 break;
4332 default:
4333 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4334 return;
4337 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4338 max_data_bytes);
4340 return;
4343 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4344 TALLOC_CTX *mem_ctx,
4345 uint16_t info_level,
4346 files_struct *fsp,
4347 struct smb_filename *smb_fname,
4348 bool delete_pending,
4349 struct timespec write_time_ts,
4350 struct ea_list *ea_list,
4351 int lock_data_count,
4352 char *lock_data,
4353 uint16_t flags2,
4354 unsigned int max_data_bytes,
4355 char **ppdata,
4356 unsigned int *pdata_size)
4358 char *pdata = *ppdata;
4359 char *dstart, *dend;
4360 unsigned int data_size;
4361 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4362 time_t create_time, mtime, atime, c_time;
4363 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4364 char *p;
4365 char *base_name;
4366 char *dos_fname;
4367 int mode;
4368 int nlink;
4369 NTSTATUS status;
4370 uint64_t file_size = 0;
4371 uint64_t pos = 0;
4372 uint64_t allocation_size = 0;
4373 uint64_t file_index = 0;
4374 uint32_t access_mask = 0;
4376 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4377 return NT_STATUS_INVALID_LEVEL;
4380 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4381 smb_fname_str_dbg(smb_fname),
4382 fsp_fnum_dbg(fsp),
4383 info_level, max_data_bytes));
4385 mode = dos_mode(conn, smb_fname);
4386 nlink = psbuf->st_ex_nlink;
4388 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4389 nlink = 1;
4392 if ((nlink > 0) && delete_pending) {
4393 nlink -= 1;
4396 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4397 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4398 if (*ppdata == NULL) {
4399 return NT_STATUS_NO_MEMORY;
4401 pdata = *ppdata;
4402 dstart = pdata;
4403 dend = dstart + data_size - 1;
4405 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4406 update_stat_ex_mtime(psbuf, write_time_ts);
4409 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4410 mtime_ts = psbuf->st_ex_mtime;
4411 atime_ts = psbuf->st_ex_atime;
4412 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4414 if (lp_dos_filetime_resolution(SNUM(conn))) {
4415 dos_filetime_timespec(&create_time_ts);
4416 dos_filetime_timespec(&mtime_ts);
4417 dos_filetime_timespec(&atime_ts);
4418 dos_filetime_timespec(&ctime_ts);
4421 create_time = convert_timespec_to_time_t(create_time_ts);
4422 mtime = convert_timespec_to_time_t(mtime_ts);
4423 atime = convert_timespec_to_time_t(atime_ts);
4424 c_time = convert_timespec_to_time_t(ctime_ts);
4426 p = strrchr_m(smb_fname->base_name,'/');
4427 if (!p)
4428 base_name = smb_fname->base_name;
4429 else
4430 base_name = p+1;
4432 /* NT expects the name to be in an exact form of the *full*
4433 filename. See the trans2 torture test */
4434 if (ISDOT(base_name)) {
4435 dos_fname = talloc_strdup(mem_ctx, "\\");
4436 if (!dos_fname) {
4437 return NT_STATUS_NO_MEMORY;
4439 } else {
4440 dos_fname = talloc_asprintf(mem_ctx,
4441 "\\%s",
4442 smb_fname->base_name);
4443 if (!dos_fname) {
4444 return NT_STATUS_NO_MEMORY;
4446 if (is_ntfs_stream_smb_fname(smb_fname)) {
4447 dos_fname = talloc_asprintf(dos_fname, "%s",
4448 smb_fname->stream_name);
4449 if (!dos_fname) {
4450 return NT_STATUS_NO_MEMORY;
4454 string_replace(dos_fname, '/', '\\');
4457 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4459 if (!fsp) {
4460 /* Do we have this path open ? */
4461 files_struct *fsp1;
4462 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4463 fsp1 = file_find_di_first(conn->sconn, fileid);
4464 if (fsp1 && fsp1->initial_allocation_size) {
4465 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4469 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4470 file_size = get_file_size_stat(psbuf);
4473 if (fsp) {
4474 pos = fsp->fh->position_information;
4477 if (fsp) {
4478 access_mask = fsp->access_mask;
4479 } else {
4480 /* GENERIC_EXECUTE mapping from Windows */
4481 access_mask = 0x12019F;
4484 /* This should be an index number - looks like
4485 dev/ino to me :-)
4487 I think this causes us to fail the IFSKIT
4488 BasicFileInformationTest. -tpot */
4489 file_index = get_FileIndex(conn, psbuf);
4491 switch (info_level) {
4492 case SMB_INFO_STANDARD:
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4494 data_size = 22;
4495 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4496 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4497 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4498 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4499 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4500 SSVAL(pdata,l1_attrFile,mode);
4501 break;
4503 case SMB_INFO_QUERY_EA_SIZE:
4505 unsigned int ea_size =
4506 estimate_ea_size(conn, fsp,
4507 smb_fname);
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4509 data_size = 26;
4510 srv_put_dos_date2(pdata,0,create_time);
4511 srv_put_dos_date2(pdata,4,atime);
4512 srv_put_dos_date2(pdata,8,mtime); /* write time */
4513 SIVAL(pdata,12,(uint32)file_size);
4514 SIVAL(pdata,16,(uint32)allocation_size);
4515 SSVAL(pdata,20,mode);
4516 SIVAL(pdata,22,ea_size);
4517 break;
4520 case SMB_INFO_IS_NAME_VALID:
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4522 if (fsp) {
4523 /* os/2 needs this ? really ?*/
4524 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4526 /* This is only reached for qpathinfo */
4527 data_size = 0;
4528 break;
4530 case SMB_INFO_QUERY_EAS_FROM_LIST:
4532 size_t total_ea_len = 0;
4533 struct ea_list *ea_file_list = NULL;
4534 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4536 status =
4537 get_ea_list_from_file(mem_ctx, conn, fsp,
4538 smb_fname,
4539 &total_ea_len, &ea_file_list);
4540 if (!NT_STATUS_IS_OK(status)) {
4541 return status;
4544 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4546 if (!ea_list || (total_ea_len > data_size)) {
4547 data_size = 4;
4548 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4549 break;
4552 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4553 break;
4556 case SMB_INFO_QUERY_ALL_EAS:
4558 /* We have data_size bytes to put EA's into. */
4559 size_t total_ea_len = 0;
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4562 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4563 smb_fname,
4564 &total_ea_len, &ea_list);
4565 if (!NT_STATUS_IS_OK(status)) {
4566 return status;
4569 if (!ea_list || (total_ea_len > data_size)) {
4570 data_size = 4;
4571 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4572 break;
4575 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4576 break;
4579 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4581 /* This is FileFullEaInformation - 0xF which maps to
4582 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4584 /* We have data_size bytes to put EA's into. */
4585 size_t total_ea_len = 0;
4586 struct ea_list *ea_file_list = NULL;
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4590 /*TODO: add filtering and index handling */
4592 status =
4593 get_ea_list_from_file(mem_ctx, conn, fsp,
4594 smb_fname,
4595 &total_ea_len, &ea_file_list);
4596 if (!NT_STATUS_IS_OK(status)) {
4597 return status;
4599 if (!ea_file_list) {
4600 return NT_STATUS_NO_EAS_ON_FILE;
4603 status = fill_ea_chained_buffer(mem_ctx,
4604 pdata,
4605 data_size,
4606 &data_size,
4607 conn, ea_file_list);
4608 if (!NT_STATUS_IS_OK(status)) {
4609 return status;
4611 break;
4614 case SMB_FILE_BASIC_INFORMATION:
4615 case SMB_QUERY_FILE_BASIC_INFO:
4617 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4619 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4620 } else {
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4622 data_size = 40;
4623 SIVAL(pdata,36,0);
4625 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4626 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4627 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4628 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4629 SIVAL(pdata,32,mode);
4631 DEBUG(5,("SMB_QFBI - "));
4632 DEBUG(5,("create: %s ", ctime(&create_time)));
4633 DEBUG(5,("access: %s ", ctime(&atime)));
4634 DEBUG(5,("write: %s ", ctime(&mtime)));
4635 DEBUG(5,("change: %s ", ctime(&c_time)));
4636 DEBUG(5,("mode: %x\n", mode));
4637 break;
4639 case SMB_FILE_STANDARD_INFORMATION:
4640 case SMB_QUERY_FILE_STANDARD_INFO:
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4643 data_size = 24;
4644 SOFF_T(pdata,0,allocation_size);
4645 SOFF_T(pdata,8,file_size);
4646 SIVAL(pdata,16,nlink);
4647 SCVAL(pdata,20,delete_pending?1:0);
4648 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4649 SSVAL(pdata,22,0); /* Padding. */
4650 break;
4652 case SMB_FILE_EA_INFORMATION:
4653 case SMB_QUERY_FILE_EA_INFO:
4655 unsigned int ea_size =
4656 estimate_ea_size(conn, fsp, smb_fname);
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4658 data_size = 4;
4659 SIVAL(pdata,0,ea_size);
4660 break;
4663 /* Get the 8.3 name - used if NT SMB was negotiated. */
4664 case SMB_QUERY_FILE_ALT_NAME_INFO:
4665 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4667 int len;
4668 char mangled_name[13];
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4670 if (!name_to_8_3(base_name,mangled_name,
4671 True,conn->params)) {
4672 return NT_STATUS_NO_MEMORY;
4674 len = srvstr_push(dstart, flags2,
4675 pdata+4, mangled_name,
4676 PTR_DIFF(dend, pdata+4),
4677 STR_UNICODE);
4678 data_size = 4 + len;
4679 SIVAL(pdata,0,len);
4680 break;
4683 case SMB_QUERY_FILE_NAME_INFO:
4685 int len;
4687 this must be *exactly* right for ACLs on mapped drives to work
4689 len = srvstr_push(dstart, flags2,
4690 pdata+4, dos_fname,
4691 PTR_DIFF(dend, pdata+4),
4692 STR_UNICODE);
4693 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4694 data_size = 4 + len;
4695 SIVAL(pdata,0,len);
4696 break;
4699 case SMB_FILE_ALLOCATION_INFORMATION:
4700 case SMB_QUERY_FILE_ALLOCATION_INFO:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4702 data_size = 8;
4703 SOFF_T(pdata,0,allocation_size);
4704 break;
4706 case SMB_FILE_END_OF_FILE_INFORMATION:
4707 case SMB_QUERY_FILE_END_OF_FILEINFO:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4709 data_size = 8;
4710 SOFF_T(pdata,0,file_size);
4711 break;
4713 case SMB_QUERY_FILE_ALL_INFO:
4714 case SMB_FILE_ALL_INFORMATION:
4716 int len;
4717 unsigned int ea_size =
4718 estimate_ea_size(conn, fsp, smb_fname);
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4720 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4722 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4723 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4724 SIVAL(pdata,32,mode);
4725 SIVAL(pdata,36,0); /* padding. */
4726 pdata += 40;
4727 SOFF_T(pdata,0,allocation_size);
4728 SOFF_T(pdata,8,file_size);
4729 SIVAL(pdata,16,nlink);
4730 SCVAL(pdata,20,delete_pending);
4731 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4732 SSVAL(pdata,22,0);
4733 pdata += 24;
4734 SIVAL(pdata,0,ea_size);
4735 pdata += 4; /* EA info */
4736 len = srvstr_push(dstart, flags2,
4737 pdata+4, dos_fname,
4738 PTR_DIFF(dend, pdata+4),
4739 STR_UNICODE);
4740 SIVAL(pdata,0,len);
4741 pdata += 4 + len;
4742 data_size = PTR_DIFF(pdata,(*ppdata));
4743 break;
4746 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4748 int len;
4749 unsigned int ea_size =
4750 estimate_ea_size(conn, fsp, smb_fname);
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4752 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4753 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4754 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4755 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4756 SIVAL(pdata, 0x20, mode);
4757 SIVAL(pdata, 0x24, 0); /* padding. */
4758 SBVAL(pdata, 0x28, allocation_size);
4759 SBVAL(pdata, 0x30, file_size);
4760 SIVAL(pdata, 0x38, nlink);
4761 SCVAL(pdata, 0x3C, delete_pending);
4762 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4763 SSVAL(pdata, 0x3E, 0); /* padding */
4764 SBVAL(pdata, 0x40, file_index);
4765 SIVAL(pdata, 0x48, ea_size);
4766 SIVAL(pdata, 0x4C, access_mask);
4767 SBVAL(pdata, 0x50, pos);
4768 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4769 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4771 pdata += 0x60;
4773 len = srvstr_push(dstart, flags2,
4774 pdata+4, dos_fname,
4775 PTR_DIFF(dend, pdata+4),
4776 STR_UNICODE);
4777 SIVAL(pdata,0,len);
4778 pdata += 4 + len;
4779 data_size = PTR_DIFF(pdata,(*ppdata));
4780 break;
4782 case SMB_FILE_INTERNAL_INFORMATION:
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4785 SBVAL(pdata, 0, file_index);
4786 data_size = 8;
4787 break;
4789 case SMB_FILE_ACCESS_INFORMATION:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4791 SIVAL(pdata, 0, access_mask);
4792 data_size = 4;
4793 break;
4795 case SMB_FILE_NAME_INFORMATION:
4796 /* Pathname with leading '\'. */
4798 size_t byte_len;
4799 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4800 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4801 SIVAL(pdata,0,byte_len);
4802 data_size = 4 + byte_len;
4803 break;
4806 case SMB_FILE_DISPOSITION_INFORMATION:
4807 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4808 data_size = 1;
4809 SCVAL(pdata,0,delete_pending);
4810 break;
4812 case SMB_FILE_POSITION_INFORMATION:
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4814 data_size = 8;
4815 SOFF_T(pdata,0,pos);
4816 break;
4818 case SMB_FILE_MODE_INFORMATION:
4819 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4820 SIVAL(pdata,0,mode);
4821 data_size = 4;
4822 break;
4824 case SMB_FILE_ALIGNMENT_INFORMATION:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4826 SIVAL(pdata,0,0); /* No alignment needed. */
4827 data_size = 4;
4828 break;
4831 * NT4 server just returns "invalid query" to this - if we try
4832 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4833 * want this. JRA.
4835 /* The first statement above is false - verified using Thursby
4836 * client against NT4 -- gcolley.
4838 case SMB_QUERY_FILE_STREAM_INFO:
4839 case SMB_FILE_STREAM_INFORMATION: {
4840 unsigned int num_streams = 0;
4841 struct stream_struct *streams = NULL;
4843 DEBUG(10,("smbd_do_qfilepathinfo: "
4844 "SMB_FILE_STREAM_INFORMATION\n"));
4846 if (is_ntfs_stream_smb_fname(smb_fname)) {
4847 return NT_STATUS_INVALID_PARAMETER;
4850 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4851 talloc_tos(), &num_streams, &streams);
4853 if (!NT_STATUS_IS_OK(status)) {
4854 DEBUG(10, ("could not get stream info: %s\n",
4855 nt_errstr(status)));
4856 return status;
4859 status = marshall_stream_info(num_streams, streams,
4860 pdata, max_data_bytes,
4861 &data_size);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 DEBUG(10, ("marshall_stream_info failed: %s\n",
4865 nt_errstr(status)));
4866 TALLOC_FREE(streams);
4867 return status;
4870 TALLOC_FREE(streams);
4872 break;
4874 case SMB_QUERY_COMPRESSION_INFO:
4875 case SMB_FILE_COMPRESSION_INFORMATION:
4876 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4877 SOFF_T(pdata,0,file_size);
4878 SIVAL(pdata,8,0); /* ??? */
4879 SIVAL(pdata,12,0); /* ??? */
4880 data_size = 16;
4881 break;
4883 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4885 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4886 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4887 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4888 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4889 SOFF_T(pdata,32,allocation_size);
4890 SOFF_T(pdata,40,file_size);
4891 SIVAL(pdata,48,mode);
4892 SIVAL(pdata,52,0); /* ??? */
4893 data_size = 56;
4894 break;
4896 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4897 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4898 SIVAL(pdata,0,mode);
4899 SIVAL(pdata,4,0);
4900 data_size = 8;
4901 break;
4904 * CIFS UNIX Extensions.
4907 case SMB_QUERY_FILE_UNIX_BASIC:
4909 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4910 data_size = PTR_DIFF(pdata,(*ppdata));
4912 DEBUG(4,("smbd_do_qfilepathinfo: "
4913 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4914 dump_data(4, (uint8_t *)(*ppdata), data_size);
4916 break;
4918 case SMB_QUERY_FILE_UNIX_INFO2:
4920 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4921 data_size = PTR_DIFF(pdata,(*ppdata));
4924 int i;
4925 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4927 for (i=0; i<100; i++)
4928 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4929 DEBUG(4,("\n"));
4932 break;
4934 case SMB_QUERY_FILE_UNIX_LINK:
4936 int len;
4937 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4939 if (!buffer) {
4940 return NT_STATUS_NO_MEMORY;
4943 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4944 #ifdef S_ISLNK
4945 if(!S_ISLNK(psbuf->st_ex_mode)) {
4946 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4948 #else
4949 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4950 #endif
4951 len = SMB_VFS_READLINK(conn,
4952 smb_fname->base_name,
4953 buffer, PATH_MAX);
4954 if (len == -1) {
4955 return map_nt_error_from_unix(errno);
4957 buffer[len] = 0;
4958 len = srvstr_push(dstart, flags2,
4959 pdata, buffer,
4960 PTR_DIFF(dend, pdata),
4961 STR_TERMINATE);
4962 pdata += len;
4963 data_size = PTR_DIFF(pdata,(*ppdata));
4965 break;
4968 #if defined(HAVE_POSIX_ACLS)
4969 case SMB_QUERY_POSIX_ACL:
4971 SMB_ACL_T file_acl = NULL;
4972 SMB_ACL_T def_acl = NULL;
4973 uint16 num_file_acls = 0;
4974 uint16 num_def_acls = 0;
4976 if (fsp && fsp->fh->fd != -1) {
4977 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4978 talloc_tos());
4979 } else {
4980 file_acl =
4981 SMB_VFS_SYS_ACL_GET_FILE(conn,
4982 smb_fname->base_name,
4983 SMB_ACL_TYPE_ACCESS,
4984 talloc_tos());
4987 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4988 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4989 "not implemented on "
4990 "filesystem containing %s\n",
4991 smb_fname->base_name));
4992 return NT_STATUS_NOT_IMPLEMENTED;
4995 if (S_ISDIR(psbuf->st_ex_mode)) {
4996 if (fsp && fsp->is_directory) {
4997 def_acl =
4998 SMB_VFS_SYS_ACL_GET_FILE(
4999 conn,
5000 fsp->fsp_name->base_name,
5001 SMB_ACL_TYPE_DEFAULT,
5002 talloc_tos());
5003 } else {
5004 def_acl =
5005 SMB_VFS_SYS_ACL_GET_FILE(
5006 conn,
5007 smb_fname->base_name,
5008 SMB_ACL_TYPE_DEFAULT,
5009 talloc_tos());
5011 def_acl = free_empty_sys_acl(conn, def_acl);
5014 num_file_acls = count_acl_entries(conn, file_acl);
5015 num_def_acls = count_acl_entries(conn, def_acl);
5017 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5018 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5019 data_size,
5020 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5021 SMB_POSIX_ACL_HEADER_SIZE) ));
5022 if (file_acl) {
5023 TALLOC_FREE(file_acl);
5025 if (def_acl) {
5026 TALLOC_FREE(def_acl);
5028 return NT_STATUS_BUFFER_TOO_SMALL;
5031 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5032 SSVAL(pdata,2,num_file_acls);
5033 SSVAL(pdata,4,num_def_acls);
5034 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5035 if (file_acl) {
5036 TALLOC_FREE(file_acl);
5038 if (def_acl) {
5039 TALLOC_FREE(def_acl);
5041 return NT_STATUS_INTERNAL_ERROR;
5043 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5044 if (file_acl) {
5045 TALLOC_FREE(file_acl);
5047 if (def_acl) {
5048 TALLOC_FREE(def_acl);
5050 return NT_STATUS_INTERNAL_ERROR;
5053 if (file_acl) {
5054 TALLOC_FREE(file_acl);
5056 if (def_acl) {
5057 TALLOC_FREE(def_acl);
5059 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5060 break;
5062 #endif
5065 case SMB_QUERY_POSIX_LOCK:
5067 uint64_t count;
5068 uint64_t offset;
5069 uint64_t smblctx;
5070 enum brl_type lock_type;
5072 /* We need an open file with a real fd for this. */
5073 if (!fsp || fsp->fh->fd == -1) {
5074 return NT_STATUS_INVALID_LEVEL;
5077 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5078 return NT_STATUS_INVALID_PARAMETER;
5081 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5082 case POSIX_LOCK_TYPE_READ:
5083 lock_type = READ_LOCK;
5084 break;
5085 case POSIX_LOCK_TYPE_WRITE:
5086 lock_type = WRITE_LOCK;
5087 break;
5088 case POSIX_LOCK_TYPE_UNLOCK:
5089 default:
5090 /* There's no point in asking for an unlock... */
5091 return NT_STATUS_INVALID_PARAMETER;
5094 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5095 #if defined(HAVE_LONGLONG)
5096 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5097 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5098 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5099 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5100 #else /* HAVE_LONGLONG */
5101 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5102 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5103 #endif /* HAVE_LONGLONG */
5105 status = query_lock(fsp,
5106 &smblctx,
5107 &count,
5108 &offset,
5109 &lock_type,
5110 POSIX_LOCK);
5112 if (ERROR_WAS_LOCK_DENIED(status)) {
5113 /* Here we need to report who has it locked... */
5114 data_size = POSIX_LOCK_DATA_SIZE;
5116 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5117 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5118 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5119 #if defined(HAVE_LONGLONG)
5120 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5121 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5122 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5123 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5124 #else /* HAVE_LONGLONG */
5125 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5126 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5127 #endif /* HAVE_LONGLONG */
5129 } else if (NT_STATUS_IS_OK(status)) {
5130 /* For success we just return a copy of what we sent
5131 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5132 data_size = POSIX_LOCK_DATA_SIZE;
5133 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5134 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5135 } else {
5136 return status;
5138 break;
5141 default:
5142 return NT_STATUS_INVALID_LEVEL;
5145 *pdata_size = data_size;
5146 return NT_STATUS_OK;
5149 /****************************************************************************
5150 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5151 file name or file id).
5152 ****************************************************************************/
5154 static void call_trans2qfilepathinfo(connection_struct *conn,
5155 struct smb_request *req,
5156 unsigned int tran_call,
5157 char **pparams, int total_params,
5158 char **ppdata, int total_data,
5159 unsigned int max_data_bytes)
5161 char *params = *pparams;
5162 char *pdata = *ppdata;
5163 uint16 info_level;
5164 unsigned int data_size = 0;
5165 unsigned int param_size = 2;
5166 struct smb_filename *smb_fname = NULL;
5167 bool delete_pending = False;
5168 struct timespec write_time_ts;
5169 files_struct *fsp = NULL;
5170 struct file_id fileid;
5171 struct ea_list *ea_list = NULL;
5172 int lock_data_count = 0;
5173 char *lock_data = NULL;
5174 NTSTATUS status = NT_STATUS_OK;
5176 if (!params) {
5177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5178 return;
5181 ZERO_STRUCT(write_time_ts);
5183 if (tran_call == TRANSACT2_QFILEINFO) {
5184 if (total_params < 4) {
5185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5186 return;
5189 if (IS_IPC(conn)) {
5190 call_trans2qpipeinfo(conn, req, tran_call,
5191 pparams, total_params,
5192 ppdata, total_data,
5193 max_data_bytes);
5194 return;
5197 fsp = file_fsp(req, SVAL(params,0));
5198 info_level = SVAL(params,2);
5200 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5202 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5204 return;
5207 /* Initial check for valid fsp ptr. */
5208 if (!check_fsp_open(conn, req, fsp)) {
5209 return;
5212 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5213 &smb_fname);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 reply_nterror(req, status);
5216 return;
5219 if(fsp->fake_file_handle) {
5221 * This is actually for the QUOTA_FAKE_FILE --metze
5224 /* We know this name is ok, it's already passed the checks. */
5226 } else if(fsp->fh->fd == -1) {
5228 * This is actually a QFILEINFO on a directory
5229 * handle (returned from an NT SMB). NT5.0 seems
5230 * to do this call. JRA.
5233 if (INFO_LEVEL_IS_UNIX(info_level)) {
5234 /* Always do lstat for UNIX calls. */
5235 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5236 DEBUG(3,("call_trans2qfilepathinfo: "
5237 "SMB_VFS_LSTAT of %s failed "
5238 "(%s)\n",
5239 smb_fname_str_dbg(smb_fname),
5240 strerror(errno)));
5241 reply_nterror(req,
5242 map_nt_error_from_unix(errno));
5243 return;
5245 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5246 DEBUG(3,("call_trans2qfilepathinfo: "
5247 "SMB_VFS_STAT of %s failed (%s)\n",
5248 smb_fname_str_dbg(smb_fname),
5249 strerror(errno)));
5250 reply_nterror(req,
5251 map_nt_error_from_unix(errno));
5252 return;
5255 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5256 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5257 } else {
5259 * Original code - this is an open file.
5261 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5262 DEBUG(3, ("fstat of %s failed (%s)\n",
5263 fsp_fnum_dbg(fsp), strerror(errno)));
5264 reply_nterror(req,
5265 map_nt_error_from_unix(errno));
5266 return;
5268 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5269 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5272 } else {
5273 uint32_t name_hash;
5274 char *fname = NULL;
5275 uint32_t ucf_flags = 0;
5277 /* qpathinfo */
5278 if (total_params < 7) {
5279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5280 return;
5283 info_level = SVAL(params,0);
5285 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5287 if (INFO_LEVEL_IS_UNIX(info_level)) {
5288 if (!lp_unix_extensions()) {
5289 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5290 return;
5292 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5293 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5294 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5295 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5299 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5300 total_params - 6,
5301 STR_TERMINATE, &status);
5302 if (!NT_STATUS_IS_OK(status)) {
5303 reply_nterror(req, status);
5304 return;
5307 status = filename_convert(req,
5308 conn,
5309 req->flags2 & FLAGS2_DFS_PATHNAMES,
5310 fname,
5311 ucf_flags,
5312 NULL,
5313 &smb_fname);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5316 reply_botherror(req,
5317 NT_STATUS_PATH_NOT_COVERED,
5318 ERRSRV, ERRbadpath);
5319 return;
5321 reply_nterror(req, status);
5322 return;
5325 /* If this is a stream, check if there is a delete_pending. */
5326 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5327 && is_ntfs_stream_smb_fname(smb_fname)) {
5328 struct smb_filename *smb_fname_base = NULL;
5330 /* Create an smb_filename with stream_name == NULL. */
5331 status =
5332 create_synthetic_smb_fname(talloc_tos(),
5333 smb_fname->base_name,
5334 NULL, NULL,
5335 &smb_fname_base);
5336 if (!NT_STATUS_IS_OK(status)) {
5337 reply_nterror(req, status);
5338 return;
5341 if (INFO_LEVEL_IS_UNIX(info_level)) {
5342 /* Always do lstat for UNIX calls. */
5343 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5344 DEBUG(3,("call_trans2qfilepathinfo: "
5345 "SMB_VFS_LSTAT of %s failed "
5346 "(%s)\n",
5347 smb_fname_str_dbg(smb_fname_base),
5348 strerror(errno)));
5349 TALLOC_FREE(smb_fname_base);
5350 reply_nterror(req,
5351 map_nt_error_from_unix(errno));
5352 return;
5354 } else {
5355 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5356 DEBUG(3,("call_trans2qfilepathinfo: "
5357 "fileinfo of %s failed "
5358 "(%s)\n",
5359 smb_fname_str_dbg(smb_fname_base),
5360 strerror(errno)));
5361 TALLOC_FREE(smb_fname_base);
5362 reply_nterror(req,
5363 map_nt_error_from_unix(errno));
5364 return;
5368 status = file_name_hash(conn,
5369 smb_fname_str_dbg(smb_fname_base),
5370 &name_hash);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 TALLOC_FREE(smb_fname_base);
5373 reply_nterror(req, status);
5374 return;
5377 fileid = vfs_file_id_from_sbuf(conn,
5378 &smb_fname_base->st);
5379 TALLOC_FREE(smb_fname_base);
5380 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5381 if (delete_pending) {
5382 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5383 return;
5387 if (INFO_LEVEL_IS_UNIX(info_level)) {
5388 /* Always do lstat for UNIX calls. */
5389 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5390 DEBUG(3,("call_trans2qfilepathinfo: "
5391 "SMB_VFS_LSTAT of %s failed (%s)\n",
5392 smb_fname_str_dbg(smb_fname),
5393 strerror(errno)));
5394 reply_nterror(req,
5395 map_nt_error_from_unix(errno));
5396 return;
5399 } else {
5400 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5401 DEBUG(3,("call_trans2qfilepathinfo: "
5402 "SMB_VFS_STAT of %s failed (%s)\n",
5403 smb_fname_str_dbg(smb_fname),
5404 strerror(errno)));
5405 reply_nterror(req,
5406 map_nt_error_from_unix(errno));
5407 return;
5411 status = file_name_hash(conn,
5412 smb_fname_str_dbg(smb_fname),
5413 &name_hash);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 reply_nterror(req, status);
5416 return;
5419 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5420 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5421 if (delete_pending) {
5422 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5423 return;
5427 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5428 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5429 fsp_fnum_dbg(fsp),
5430 info_level,tran_call,total_data));
5432 /* Pull out any data sent here before we realloc. */
5433 switch (info_level) {
5434 case SMB_INFO_QUERY_EAS_FROM_LIST:
5436 /* Pull any EA list from the data portion. */
5437 uint32 ea_size;
5439 if (total_data < 4) {
5440 reply_nterror(
5441 req, NT_STATUS_INVALID_PARAMETER);
5442 return;
5444 ea_size = IVAL(pdata,0);
5446 if (total_data > 0 && ea_size != total_data) {
5447 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5448 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5449 reply_nterror(
5450 req, NT_STATUS_INVALID_PARAMETER);
5451 return;
5454 if (!lp_ea_support(SNUM(conn))) {
5455 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5456 return;
5459 /* Pull out the list of names. */
5460 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5461 if (!ea_list) {
5462 reply_nterror(
5463 req, NT_STATUS_INVALID_PARAMETER);
5464 return;
5466 break;
5469 case SMB_QUERY_POSIX_LOCK:
5471 if (fsp == NULL || fsp->fh->fd == -1) {
5472 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5473 return;
5476 if (total_data != POSIX_LOCK_DATA_SIZE) {
5477 reply_nterror(
5478 req, NT_STATUS_INVALID_PARAMETER);
5479 return;
5482 /* Copy the lock range data. */
5483 lock_data = (char *)talloc_memdup(
5484 req, pdata, total_data);
5485 if (!lock_data) {
5486 reply_nterror(req, NT_STATUS_NO_MEMORY);
5487 return;
5489 lock_data_count = total_data;
5491 default:
5492 break;
5495 *pparams = (char *)SMB_REALLOC(*pparams,2);
5496 if (*pparams == NULL) {
5497 reply_nterror(req, NT_STATUS_NO_MEMORY);
5498 return;
5500 params = *pparams;
5501 SSVAL(params,0,0);
5504 * draft-leach-cifs-v1-spec-02.txt
5505 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5506 * says:
5508 * The requested information is placed in the Data portion of the
5509 * transaction response. For the information levels greater than 0x100,
5510 * the transaction response has 1 parameter word which should be
5511 * ignored by the client.
5513 * However Windows only follows this rule for the IS_NAME_VALID call.
5515 switch (info_level) {
5516 case SMB_INFO_IS_NAME_VALID:
5517 param_size = 0;
5518 break;
5521 if ((info_level & 0xFF00) == 0xFF00) {
5523 * We use levels that start with 0xFF00
5524 * internally to represent SMB2 specific levels
5526 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5527 return;
5530 status = smbd_do_qfilepathinfo(conn, req, info_level,
5531 fsp, smb_fname,
5532 delete_pending, write_time_ts,
5533 ea_list,
5534 lock_data_count, lock_data,
5535 req->flags2, max_data_bytes,
5536 ppdata, &data_size);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 reply_nterror(req, status);
5539 return;
5542 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5543 max_data_bytes);
5545 return;
5548 /****************************************************************************
5549 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5550 code.
5551 ****************************************************************************/
5553 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5554 connection_struct *conn,
5555 struct smb_request *req,
5556 bool overwrite_if_exists,
5557 const struct smb_filename *smb_fname_old,
5558 struct smb_filename *smb_fname_new)
5560 NTSTATUS status = NT_STATUS_OK;
5562 /* source must already exist. */
5563 if (!VALID_STAT(smb_fname_old->st)) {
5564 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5567 if (VALID_STAT(smb_fname_new->st)) {
5568 if (overwrite_if_exists) {
5569 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5570 return NT_STATUS_FILE_IS_A_DIRECTORY;
5572 status = unlink_internals(conn,
5573 req,
5574 FILE_ATTRIBUTE_NORMAL,
5575 smb_fname_new,
5576 false);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 return status;
5580 } else {
5581 /* Disallow if newname already exists. */
5582 return NT_STATUS_OBJECT_NAME_COLLISION;
5586 /* No links from a directory. */
5587 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5588 return NT_STATUS_FILE_IS_A_DIRECTORY;
5591 /* Setting a hardlink to/from a stream isn't currently supported. */
5592 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5593 is_ntfs_stream_smb_fname(smb_fname_new)) {
5594 return NT_STATUS_INVALID_PARAMETER;
5597 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5598 smb_fname_old->base_name, smb_fname_new->base_name));
5600 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5601 smb_fname_new->base_name) != 0) {
5602 status = map_nt_error_from_unix(errno);
5603 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5604 nt_errstr(status), smb_fname_old->base_name,
5605 smb_fname_new->base_name));
5607 return status;
5610 /****************************************************************************
5611 Deal with setting the time from any of the setfilepathinfo functions.
5612 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5613 calling this function.
5614 ****************************************************************************/
5616 NTSTATUS smb_set_file_time(connection_struct *conn,
5617 files_struct *fsp,
5618 const struct smb_filename *smb_fname,
5619 struct smb_file_time *ft,
5620 bool setting_write_time)
5622 struct smb_filename smb_fname_base;
5623 uint32 action =
5624 FILE_NOTIFY_CHANGE_LAST_ACCESS
5625 |FILE_NOTIFY_CHANGE_LAST_WRITE
5626 |FILE_NOTIFY_CHANGE_CREATION;
5628 if (!VALID_STAT(smb_fname->st)) {
5629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5632 /* get some defaults (no modifications) if any info is zero or -1. */
5633 if (null_timespec(ft->create_time)) {
5634 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5637 if (null_timespec(ft->atime)) {
5638 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5641 if (null_timespec(ft->mtime)) {
5642 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5645 if (!setting_write_time) {
5646 /* ft->mtime comes from change time, not write time. */
5647 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5650 /* Ensure the resolution is the correct for
5651 * what we can store on this filesystem. */
5653 round_timespec(conn->ts_res, &ft->create_time);
5654 round_timespec(conn->ts_res, &ft->ctime);
5655 round_timespec(conn->ts_res, &ft->atime);
5656 round_timespec(conn->ts_res, &ft->mtime);
5658 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5659 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5660 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5661 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5662 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5663 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5664 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5665 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5667 if (setting_write_time) {
5669 * This was a Windows setfileinfo on an open file.
5670 * NT does this a lot. We also need to
5671 * set the time here, as it can be read by
5672 * FindFirst/FindNext and with the patch for bug #2045
5673 * in smbd/fileio.c it ensures that this timestamp is
5674 * kept sticky even after a write. We save the request
5675 * away and will set it on file close and after a write. JRA.
5678 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5679 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5681 if (fsp != NULL) {
5682 if (fsp->base_fsp) {
5683 set_sticky_write_time_fsp(fsp->base_fsp,
5684 ft->mtime);
5685 } else {
5686 set_sticky_write_time_fsp(fsp, ft->mtime);
5688 } else {
5689 set_sticky_write_time_path(
5690 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5691 ft->mtime);
5695 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5697 /* Always call ntimes on the base, even if a stream was passed in. */
5698 smb_fname_base = *smb_fname;
5699 smb_fname_base.stream_name = NULL;
5701 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5702 return map_nt_error_from_unix(errno);
5705 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5706 smb_fname->base_name);
5707 return NT_STATUS_OK;
5710 /****************************************************************************
5711 Deal with setting the dosmode from any of the setfilepathinfo functions.
5712 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5713 done before calling this function.
5714 ****************************************************************************/
5716 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5717 const struct smb_filename *smb_fname,
5718 uint32 dosmode)
5720 struct smb_filename *smb_fname_base = NULL;
5721 NTSTATUS status;
5723 if (!VALID_STAT(smb_fname->st)) {
5724 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5727 /* Always operate on the base_name, even if a stream was passed in. */
5728 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5729 NULL, &smb_fname->st,
5730 &smb_fname_base);
5731 if (!NT_STATUS_IS_OK(status)) {
5732 return status;
5735 if (dosmode) {
5736 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5737 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5738 } else {
5739 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5743 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5745 /* check the mode isn't different, before changing it */
5746 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5747 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5748 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5749 (unsigned int)dosmode));
5751 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5752 false)) {
5753 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5754 "%s failed (%s)\n",
5755 smb_fname_str_dbg(smb_fname_base),
5756 strerror(errno)));
5757 status = map_nt_error_from_unix(errno);
5758 goto out;
5761 status = NT_STATUS_OK;
5762 out:
5763 TALLOC_FREE(smb_fname_base);
5764 return status;
5767 /****************************************************************************
5768 Deal with setting the size from any of the setfilepathinfo functions.
5769 ****************************************************************************/
5771 static NTSTATUS smb_set_file_size(connection_struct *conn,
5772 struct smb_request *req,
5773 files_struct *fsp,
5774 const struct smb_filename *smb_fname,
5775 const SMB_STRUCT_STAT *psbuf,
5776 off_t size,
5777 bool fail_after_createfile)
5779 NTSTATUS status = NT_STATUS_OK;
5780 struct smb_filename *smb_fname_tmp = NULL;
5781 files_struct *new_fsp = NULL;
5783 if (!VALID_STAT(*psbuf)) {
5784 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5787 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5789 if (size == get_file_size_stat(psbuf)) {
5790 return NT_STATUS_OK;
5793 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5794 smb_fname_str_dbg(smb_fname), (double)size));
5796 if (fsp && fsp->fh->fd != -1) {
5797 /* Handle based call. */
5798 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5799 return NT_STATUS_ACCESS_DENIED;
5802 if (vfs_set_filelen(fsp, size) == -1) {
5803 return map_nt_error_from_unix(errno);
5805 trigger_write_time_update_immediate(fsp);
5806 return NT_STATUS_OK;
5809 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5810 if (!NT_STATUS_IS_OK(status)) {
5811 return status;
5814 smb_fname_tmp->st = *psbuf;
5816 status = SMB_VFS_CREATE_FILE(
5817 conn, /* conn */
5818 req, /* req */
5819 0, /* root_dir_fid */
5820 smb_fname_tmp, /* fname */
5821 FILE_WRITE_DATA, /* access_mask */
5822 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5823 FILE_SHARE_DELETE),
5824 FILE_OPEN, /* create_disposition*/
5825 0, /* create_options */
5826 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5827 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5828 0, /* allocation_size */
5829 0, /* private_flags */
5830 NULL, /* sd */
5831 NULL, /* ea_list */
5832 &new_fsp, /* result */
5833 NULL); /* pinfo */
5835 TALLOC_FREE(smb_fname_tmp);
5837 if (!NT_STATUS_IS_OK(status)) {
5838 /* NB. We check for open_was_deferred in the caller. */
5839 return status;
5842 /* See RAW-SFILEINFO-END-OF-FILE */
5843 if (fail_after_createfile) {
5844 close_file(req, new_fsp,NORMAL_CLOSE);
5845 return NT_STATUS_INVALID_LEVEL;
5848 if (vfs_set_filelen(new_fsp, size) == -1) {
5849 status = map_nt_error_from_unix(errno);
5850 close_file(req, new_fsp,NORMAL_CLOSE);
5851 return status;
5854 trigger_write_time_update_immediate(new_fsp);
5855 close_file(req, new_fsp,NORMAL_CLOSE);
5856 return NT_STATUS_OK;
5859 /****************************************************************************
5860 Deal with SMB_INFO_SET_EA.
5861 ****************************************************************************/
5863 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5864 const char *pdata,
5865 int total_data,
5866 files_struct *fsp,
5867 const struct smb_filename *smb_fname)
5869 struct ea_list *ea_list = NULL;
5870 TALLOC_CTX *ctx = NULL;
5871 NTSTATUS status = NT_STATUS_OK;
5873 if (total_data < 10) {
5875 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5876 length. They seem to have no effect. Bug #3212. JRA */
5878 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5879 /* We're done. We only get EA info in this call. */
5880 return NT_STATUS_OK;
5883 return NT_STATUS_INVALID_PARAMETER;
5886 if (IVAL(pdata,0) > total_data) {
5887 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5888 IVAL(pdata,0), (unsigned int)total_data));
5889 return NT_STATUS_INVALID_PARAMETER;
5892 ctx = talloc_tos();
5893 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5894 if (!ea_list) {
5895 return NT_STATUS_INVALID_PARAMETER;
5898 status = set_ea(conn, fsp, smb_fname, ea_list);
5900 return status;
5903 /****************************************************************************
5904 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5905 ****************************************************************************/
5907 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5908 const char *pdata,
5909 int total_data,
5910 files_struct *fsp)
5912 struct ea_list *ea_list = NULL;
5913 NTSTATUS status;
5915 if (!fsp) {
5916 return NT_STATUS_INVALID_HANDLE;
5919 if (!lp_ea_support(SNUM(conn))) {
5920 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5921 "EA's not supported.\n",
5922 (unsigned int)total_data));
5923 return NT_STATUS_EAS_NOT_SUPPORTED;
5926 if (total_data < 10) {
5927 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5928 "too small.\n",
5929 (unsigned int)total_data));
5930 return NT_STATUS_INVALID_PARAMETER;
5933 ea_list = read_nttrans_ea_list(talloc_tos(),
5934 pdata,
5935 total_data);
5937 if (!ea_list) {
5938 return NT_STATUS_INVALID_PARAMETER;
5941 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5943 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5944 smb_fname_str_dbg(fsp->fsp_name),
5945 nt_errstr(status) ));
5947 return status;
5951 /****************************************************************************
5952 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5953 ****************************************************************************/
5955 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5956 const char *pdata,
5957 int total_data,
5958 files_struct *fsp,
5959 struct smb_filename *smb_fname)
5961 NTSTATUS status = NT_STATUS_OK;
5962 bool delete_on_close;
5963 uint32 dosmode = 0;
5965 if (total_data < 1) {
5966 return NT_STATUS_INVALID_PARAMETER;
5969 if (fsp == NULL) {
5970 return NT_STATUS_INVALID_HANDLE;
5973 delete_on_close = (CVAL(pdata,0) ? True : False);
5974 dosmode = dos_mode(conn, smb_fname);
5976 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5977 "delete_on_close = %u\n",
5978 smb_fname_str_dbg(smb_fname),
5979 (unsigned int)dosmode,
5980 (unsigned int)delete_on_close ));
5982 if (delete_on_close) {
5983 status = can_set_delete_on_close(fsp, dosmode);
5984 if (!NT_STATUS_IS_OK(status)) {
5985 return status;
5989 /* The set is across all open files on this dev/inode pair. */
5990 if (!set_delete_on_close(fsp, delete_on_close,
5991 conn->session_info->security_token,
5992 conn->session_info->unix_token)) {
5993 return NT_STATUS_ACCESS_DENIED;
5995 return NT_STATUS_OK;
5998 /****************************************************************************
5999 Deal with SMB_FILE_POSITION_INFORMATION.
6000 ****************************************************************************/
6002 static NTSTATUS smb_file_position_information(connection_struct *conn,
6003 const char *pdata,
6004 int total_data,
6005 files_struct *fsp)
6007 uint64_t position_information;
6009 if (total_data < 8) {
6010 return NT_STATUS_INVALID_PARAMETER;
6013 if (fsp == NULL) {
6014 /* Ignore on pathname based set. */
6015 return NT_STATUS_OK;
6018 position_information = (uint64_t)IVAL(pdata,0);
6019 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6021 DEBUG(10,("smb_file_position_information: Set file position "
6022 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6023 (double)position_information));
6024 fsp->fh->position_information = position_information;
6025 return NT_STATUS_OK;
6028 /****************************************************************************
6029 Deal with SMB_FILE_MODE_INFORMATION.
6030 ****************************************************************************/
6032 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6033 const char *pdata,
6034 int total_data)
6036 uint32 mode;
6038 if (total_data < 4) {
6039 return NT_STATUS_INVALID_PARAMETER;
6041 mode = IVAL(pdata,0);
6042 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6043 return NT_STATUS_INVALID_PARAMETER;
6045 return NT_STATUS_OK;
6048 /****************************************************************************
6049 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6050 ****************************************************************************/
6052 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6053 struct smb_request *req,
6054 const char *pdata,
6055 int total_data,
6056 const struct smb_filename *smb_fname)
6058 char *link_target = NULL;
6059 const char *newname = smb_fname->base_name;
6060 TALLOC_CTX *ctx = talloc_tos();
6062 /* Set a symbolic link. */
6063 /* Don't allow this if follow links is false. */
6065 if (total_data == 0) {
6066 return NT_STATUS_INVALID_PARAMETER;
6069 if (!lp_symlinks(SNUM(conn))) {
6070 return NT_STATUS_ACCESS_DENIED;
6073 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6074 total_data, STR_TERMINATE);
6076 if (!link_target) {
6077 return NT_STATUS_INVALID_PARAMETER;
6080 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6081 newname, link_target ));
6083 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6084 return map_nt_error_from_unix(errno);
6087 return NT_STATUS_OK;
6090 /****************************************************************************
6091 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6092 ****************************************************************************/
6094 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6095 struct smb_request *req,
6096 const char *pdata, int total_data,
6097 struct smb_filename *smb_fname_new)
6099 char *oldname = NULL;
6100 struct smb_filename *smb_fname_old = NULL;
6101 TALLOC_CTX *ctx = talloc_tos();
6102 NTSTATUS status = NT_STATUS_OK;
6104 /* Set a hard link. */
6105 if (total_data == 0) {
6106 return NT_STATUS_INVALID_PARAMETER;
6109 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6110 total_data, STR_TERMINATE, &status);
6111 if (!NT_STATUS_IS_OK(status)) {
6112 return status;
6115 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6116 smb_fname_str_dbg(smb_fname_new), oldname));
6118 status = filename_convert(ctx,
6119 conn,
6120 req->flags2 & FLAGS2_DFS_PATHNAMES,
6121 oldname,
6123 NULL,
6124 &smb_fname_old);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 return status;
6129 return hardlink_internals(ctx, conn, req, false,
6130 smb_fname_old, smb_fname_new);
6133 /****************************************************************************
6134 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6135 ****************************************************************************/
6137 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6138 struct smb_request *req,
6139 const char *pdata,
6140 int total_data,
6141 files_struct *fsp,
6142 struct smb_filename *smb_fname_src)
6144 bool overwrite;
6145 uint32_t len;
6146 char *newname = NULL;
6147 struct smb_filename *smb_fname_dst = NULL;
6148 NTSTATUS status = NT_STATUS_OK;
6149 TALLOC_CTX *ctx = talloc_tos();
6151 if (!fsp) {
6152 return NT_STATUS_INVALID_HANDLE;
6155 if (total_data < 20) {
6156 return NT_STATUS_INVALID_PARAMETER;
6159 overwrite = (CVAL(pdata,0) ? True : False);
6160 len = IVAL(pdata,16);
6162 if (len > (total_data - 20) || (len == 0)) {
6163 return NT_STATUS_INVALID_PARAMETER;
6166 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6167 &pdata[20], len, STR_TERMINATE,
6168 &status);
6169 if (!NT_STATUS_IS_OK(status)) {
6170 return status;
6173 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6174 newname));
6176 status = filename_convert(ctx,
6177 conn,
6178 req->flags2 & FLAGS2_DFS_PATHNAMES,
6179 newname,
6180 UCF_SAVE_LCOMP,
6181 NULL,
6182 &smb_fname_dst);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 return status;
6187 if (fsp->base_fsp) {
6188 /* newname must be a stream name. */
6189 if (newname[0] != ':') {
6190 return NT_STATUS_NOT_SUPPORTED;
6193 /* Create an smb_fname to call rename_internals_fsp() with. */
6194 status = create_synthetic_smb_fname(talloc_tos(),
6195 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6196 &smb_fname_dst);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 goto out;
6202 * Set the original last component, since
6203 * rename_internals_fsp() requires it.
6205 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6206 newname);
6207 if (smb_fname_dst->original_lcomp == NULL) {
6208 status = NT_STATUS_NO_MEMORY;
6209 goto out;
6214 DEBUG(10,("smb2_file_rename_information: "
6215 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6216 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6217 smb_fname_str_dbg(smb_fname_dst)));
6218 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6219 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6220 overwrite);
6222 out:
6223 TALLOC_FREE(smb_fname_dst);
6224 return status;
6227 static NTSTATUS smb_file_link_information(connection_struct *conn,
6228 struct smb_request *req,
6229 const char *pdata,
6230 int total_data,
6231 files_struct *fsp,
6232 struct smb_filename *smb_fname_src)
6234 bool overwrite;
6235 uint32_t len;
6236 char *newname = NULL;
6237 struct smb_filename *smb_fname_dst = NULL;
6238 NTSTATUS status = NT_STATUS_OK;
6239 TALLOC_CTX *ctx = talloc_tos();
6241 if (!fsp) {
6242 return NT_STATUS_INVALID_HANDLE;
6245 if (total_data < 20) {
6246 return NT_STATUS_INVALID_PARAMETER;
6249 overwrite = (CVAL(pdata,0) ? true : false);
6250 len = IVAL(pdata,16);
6252 if (len > (total_data - 20) || (len == 0)) {
6253 return NT_STATUS_INVALID_PARAMETER;
6256 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6257 &pdata[20], len, STR_TERMINATE,
6258 &status);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 return status;
6263 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6264 newname));
6266 status = filename_convert(ctx,
6267 conn,
6268 req->flags2 & FLAGS2_DFS_PATHNAMES,
6269 newname,
6270 UCF_SAVE_LCOMP,
6271 NULL,
6272 &smb_fname_dst);
6273 if (!NT_STATUS_IS_OK(status)) {
6274 return status;
6277 if (fsp->base_fsp) {
6278 /* No stream names. */
6279 return NT_STATUS_NOT_SUPPORTED;
6282 DEBUG(10,("smb_file_link_information: "
6283 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6284 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6285 smb_fname_str_dbg(smb_fname_dst)));
6286 status = hardlink_internals(ctx,
6287 conn,
6288 req,
6289 overwrite,
6290 fsp->fsp_name,
6291 smb_fname_dst);
6293 TALLOC_FREE(smb_fname_dst);
6294 return status;
6297 /****************************************************************************
6298 Deal with SMB_FILE_RENAME_INFORMATION.
6299 ****************************************************************************/
6301 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6302 struct smb_request *req,
6303 const char *pdata,
6304 int total_data,
6305 files_struct *fsp,
6306 struct smb_filename *smb_fname_src)
6308 bool overwrite;
6309 uint32 root_fid;
6310 uint32 len;
6311 char *newname = NULL;
6312 struct smb_filename *smb_fname_dst = NULL;
6313 bool dest_has_wcard = False;
6314 NTSTATUS status = NT_STATUS_OK;
6315 char *p;
6316 TALLOC_CTX *ctx = talloc_tos();
6318 if (total_data < 13) {
6319 return NT_STATUS_INVALID_PARAMETER;
6322 overwrite = (CVAL(pdata,0) ? True : False);
6323 root_fid = IVAL(pdata,4);
6324 len = IVAL(pdata,8);
6326 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6327 return NT_STATUS_INVALID_PARAMETER;
6330 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6331 len, 0, &status,
6332 &dest_has_wcard);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 return status;
6337 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6338 newname));
6340 status = resolve_dfspath_wcard(ctx, conn,
6341 req->flags2 & FLAGS2_DFS_PATHNAMES,
6342 newname,
6343 true,
6344 !conn->sconn->using_smb2,
6345 &newname,
6346 &dest_has_wcard);
6347 if (!NT_STATUS_IS_OK(status)) {
6348 return status;
6351 /* Check the new name has no '/' characters. */
6352 if (strchr_m(newname, '/')) {
6353 return NT_STATUS_NOT_SUPPORTED;
6356 if (fsp && fsp->base_fsp) {
6357 /* newname must be a stream name. */
6358 if (newname[0] != ':') {
6359 return NT_STATUS_NOT_SUPPORTED;
6362 /* Create an smb_fname to call rename_internals_fsp() with. */
6363 status = create_synthetic_smb_fname(talloc_tos(),
6364 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6365 &smb_fname_dst);
6366 if (!NT_STATUS_IS_OK(status)) {
6367 goto out;
6371 * Set the original last component, since
6372 * rename_internals_fsp() requires it.
6374 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6375 newname);
6376 if (smb_fname_dst->original_lcomp == NULL) {
6377 status = NT_STATUS_NO_MEMORY;
6378 goto out;
6381 } else {
6383 * Build up an smb_fname_dst based on the filename passed in.
6384 * We basically just strip off the last component, and put on
6385 * the newname instead.
6387 char *base_name = NULL;
6389 /* newname must *not* be a stream name. */
6390 if (newname[0] == ':') {
6391 return NT_STATUS_NOT_SUPPORTED;
6395 * Strip off the last component (filename) of the path passed
6396 * in.
6398 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6399 if (!base_name) {
6400 return NT_STATUS_NO_MEMORY;
6402 p = strrchr_m(base_name, '/');
6403 if (p) {
6404 p[1] = '\0';
6405 } else {
6406 base_name = talloc_strdup(ctx, "");
6407 if (!base_name) {
6408 return NT_STATUS_NO_MEMORY;
6411 /* Append the new name. */
6412 base_name = talloc_asprintf_append(base_name,
6413 "%s",
6414 newname);
6415 if (!base_name) {
6416 return NT_STATUS_NO_MEMORY;
6419 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6420 (UCF_SAVE_LCOMP |
6421 (dest_has_wcard ?
6422 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6423 0)));
6425 /* If an error we expect this to be
6426 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6428 if (!NT_STATUS_IS_OK(status)) {
6429 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6430 status)) {
6431 goto out;
6433 /* Create an smb_fname to call rename_internals_fsp() */
6434 status = create_synthetic_smb_fname(ctx,
6435 base_name, NULL,
6436 NULL,
6437 &smb_fname_dst);
6438 if (!NT_STATUS_IS_OK(status)) {
6439 goto out;
6444 if (fsp) {
6445 DEBUG(10,("smb_file_rename_information: "
6446 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6447 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6448 smb_fname_str_dbg(smb_fname_dst)));
6449 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6450 overwrite);
6451 } else {
6452 DEBUG(10,("smb_file_rename_information: "
6453 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6454 smb_fname_str_dbg(smb_fname_src),
6455 smb_fname_str_dbg(smb_fname_dst)));
6456 status = rename_internals(ctx, conn, req, smb_fname_src,
6457 smb_fname_dst, 0, overwrite, false,
6458 dest_has_wcard,
6459 FILE_WRITE_ATTRIBUTES);
6461 out:
6462 TALLOC_FREE(smb_fname_dst);
6463 return status;
6466 /****************************************************************************
6467 Deal with SMB_SET_POSIX_ACL.
6468 ****************************************************************************/
6470 #if defined(HAVE_POSIX_ACLS)
6471 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6472 const char *pdata,
6473 int total_data,
6474 files_struct *fsp,
6475 const struct smb_filename *smb_fname)
6477 uint16 posix_acl_version;
6478 uint16 num_file_acls;
6479 uint16 num_def_acls;
6480 bool valid_file_acls = True;
6481 bool valid_def_acls = True;
6483 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6484 return NT_STATUS_INVALID_PARAMETER;
6486 posix_acl_version = SVAL(pdata,0);
6487 num_file_acls = SVAL(pdata,2);
6488 num_def_acls = SVAL(pdata,4);
6490 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6491 valid_file_acls = False;
6492 num_file_acls = 0;
6495 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6496 valid_def_acls = False;
6497 num_def_acls = 0;
6500 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6501 return NT_STATUS_INVALID_PARAMETER;
6504 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6505 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6506 return NT_STATUS_INVALID_PARAMETER;
6509 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6510 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6511 (unsigned int)num_file_acls,
6512 (unsigned int)num_def_acls));
6514 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6515 smb_fname->base_name, num_file_acls,
6516 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6517 return map_nt_error_from_unix(errno);
6520 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6521 smb_fname->base_name, &smb_fname->st, num_def_acls,
6522 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6523 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6524 return map_nt_error_from_unix(errno);
6526 return NT_STATUS_OK;
6528 #endif
6530 /****************************************************************************
6531 Deal with SMB_SET_POSIX_LOCK.
6532 ****************************************************************************/
6534 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6535 struct smb_request *req,
6536 const char *pdata,
6537 int total_data,
6538 files_struct *fsp)
6540 uint64_t count;
6541 uint64_t offset;
6542 uint64_t smblctx;
6543 bool blocking_lock = False;
6544 enum brl_type lock_type;
6546 NTSTATUS status = NT_STATUS_OK;
6548 if (fsp == NULL || fsp->fh->fd == -1) {
6549 return NT_STATUS_INVALID_HANDLE;
6552 if (total_data != POSIX_LOCK_DATA_SIZE) {
6553 return NT_STATUS_INVALID_PARAMETER;
6556 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6557 case POSIX_LOCK_TYPE_READ:
6558 lock_type = READ_LOCK;
6559 break;
6560 case POSIX_LOCK_TYPE_WRITE:
6561 /* Return the right POSIX-mappable error code for files opened read-only. */
6562 if (!fsp->can_write) {
6563 return NT_STATUS_INVALID_HANDLE;
6565 lock_type = WRITE_LOCK;
6566 break;
6567 case POSIX_LOCK_TYPE_UNLOCK:
6568 lock_type = UNLOCK_LOCK;
6569 break;
6570 default:
6571 return NT_STATUS_INVALID_PARAMETER;
6574 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6575 blocking_lock = False;
6576 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6577 blocking_lock = True;
6578 } else {
6579 return NT_STATUS_INVALID_PARAMETER;
6582 if (!lp_blocking_locks(SNUM(conn))) {
6583 blocking_lock = False;
6586 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6587 #if defined(HAVE_LONGLONG)
6588 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6589 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6590 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6591 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6592 #else /* HAVE_LONGLONG */
6593 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6594 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6595 #endif /* HAVE_LONGLONG */
6597 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6598 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6599 fsp_str_dbg(fsp),
6600 (unsigned int)lock_type,
6601 (unsigned long long)smblctx,
6602 (double)count,
6603 (double)offset ));
6605 if (lock_type == UNLOCK_LOCK) {
6606 status = do_unlock(req->sconn->msg_ctx,
6607 fsp,
6608 smblctx,
6609 count,
6610 offset,
6611 POSIX_LOCK);
6612 } else {
6613 uint64_t block_smblctx;
6615 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6616 fsp,
6617 smblctx,
6618 count,
6619 offset,
6620 lock_type,
6621 POSIX_LOCK,
6622 blocking_lock,
6623 &status,
6624 &block_smblctx,
6625 NULL);
6627 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6629 * A blocking lock was requested. Package up
6630 * this smb into a queued request and push it
6631 * onto the blocking lock queue.
6633 if(push_blocking_lock_request(br_lck,
6634 req,
6635 fsp,
6636 -1, /* infinite timeout. */
6638 smblctx,
6639 lock_type,
6640 POSIX_LOCK,
6641 offset,
6642 count,
6643 block_smblctx)) {
6644 TALLOC_FREE(br_lck);
6645 return status;
6648 TALLOC_FREE(br_lck);
6651 return status;
6654 /****************************************************************************
6655 Deal with SMB_SET_FILE_BASIC_INFO.
6656 ****************************************************************************/
6658 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6659 const char *pdata,
6660 int total_data,
6661 files_struct *fsp,
6662 const struct smb_filename *smb_fname)
6664 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6665 struct smb_file_time ft;
6666 uint32 dosmode = 0;
6667 NTSTATUS status = NT_STATUS_OK;
6669 ZERO_STRUCT(ft);
6671 if (total_data < 36) {
6672 return NT_STATUS_INVALID_PARAMETER;
6675 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 return status;
6680 /* Set the attributes */
6681 dosmode = IVAL(pdata,32);
6682 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6683 if (!NT_STATUS_IS_OK(status)) {
6684 return status;
6687 /* create time */
6688 ft.create_time = interpret_long_date(pdata);
6690 /* access time */
6691 ft.atime = interpret_long_date(pdata+8);
6693 /* write time. */
6694 ft.mtime = interpret_long_date(pdata+16);
6696 /* change time. */
6697 ft.ctime = interpret_long_date(pdata+24);
6699 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6700 smb_fname_str_dbg(smb_fname)));
6702 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6703 true);
6706 /****************************************************************************
6707 Deal with SMB_INFO_STANDARD.
6708 ****************************************************************************/
6710 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6711 const char *pdata,
6712 int total_data,
6713 files_struct *fsp,
6714 const struct smb_filename *smb_fname)
6716 NTSTATUS status;
6717 struct smb_file_time ft;
6719 ZERO_STRUCT(ft);
6721 if (total_data < 12) {
6722 return NT_STATUS_INVALID_PARAMETER;
6725 /* create time */
6726 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6727 /* access time */
6728 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6729 /* write time */
6730 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6732 DEBUG(10,("smb_set_info_standard: file %s\n",
6733 smb_fname_str_dbg(smb_fname)));
6735 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6736 if (!NT_STATUS_IS_OK(status)) {
6737 return status;
6740 return smb_set_file_time(conn,
6741 fsp,
6742 smb_fname,
6743 &ft,
6744 true);
6747 /****************************************************************************
6748 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6749 ****************************************************************************/
6751 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6752 struct smb_request *req,
6753 const char *pdata,
6754 int total_data,
6755 files_struct *fsp,
6756 struct smb_filename *smb_fname)
6758 uint64_t allocation_size = 0;
6759 NTSTATUS status = NT_STATUS_OK;
6760 files_struct *new_fsp = NULL;
6762 if (!VALID_STAT(smb_fname->st)) {
6763 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6766 if (total_data < 8) {
6767 return NT_STATUS_INVALID_PARAMETER;
6770 allocation_size = (uint64_t)IVAL(pdata,0);
6771 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6772 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6773 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6774 (double)allocation_size));
6776 if (allocation_size) {
6777 allocation_size = smb_roundup(conn, allocation_size);
6780 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6781 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6782 (double)allocation_size));
6784 if (fsp && fsp->fh->fd != -1) {
6785 /* Open file handle. */
6786 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6787 return NT_STATUS_ACCESS_DENIED;
6790 /* Only change if needed. */
6791 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6792 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6793 return map_nt_error_from_unix(errno);
6796 /* But always update the time. */
6798 * This is equivalent to a write. Ensure it's seen immediately
6799 * if there are no pending writes.
6801 trigger_write_time_update_immediate(fsp);
6802 return NT_STATUS_OK;
6805 /* Pathname or stat or directory file. */
6806 status = SMB_VFS_CREATE_FILE(
6807 conn, /* conn */
6808 req, /* req */
6809 0, /* root_dir_fid */
6810 smb_fname, /* fname */
6811 FILE_WRITE_DATA, /* access_mask */
6812 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6813 FILE_SHARE_DELETE),
6814 FILE_OPEN, /* create_disposition*/
6815 0, /* create_options */
6816 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6817 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6818 0, /* allocation_size */
6819 0, /* private_flags */
6820 NULL, /* sd */
6821 NULL, /* ea_list */
6822 &new_fsp, /* result */
6823 NULL); /* pinfo */
6825 if (!NT_STATUS_IS_OK(status)) {
6826 /* NB. We check for open_was_deferred in the caller. */
6827 return status;
6830 /* Only change if needed. */
6831 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6832 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6833 status = map_nt_error_from_unix(errno);
6834 close_file(req, new_fsp, NORMAL_CLOSE);
6835 return status;
6839 /* Changing the allocation size should set the last mod time. */
6841 * This is equivalent to a write. Ensure it's seen immediately
6842 * if there are no pending writes.
6844 trigger_write_time_update_immediate(new_fsp);
6846 close_file(req, new_fsp, NORMAL_CLOSE);
6847 return NT_STATUS_OK;
6850 /****************************************************************************
6851 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6852 ****************************************************************************/
6854 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6855 struct smb_request *req,
6856 const char *pdata,
6857 int total_data,
6858 files_struct *fsp,
6859 const struct smb_filename *smb_fname,
6860 bool fail_after_createfile)
6862 off_t size;
6864 if (total_data < 8) {
6865 return NT_STATUS_INVALID_PARAMETER;
6868 size = IVAL(pdata,0);
6869 size |= (((off_t)IVAL(pdata,4)) << 32);
6870 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6871 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6872 (double)size));
6874 return smb_set_file_size(conn, req,
6875 fsp,
6876 smb_fname,
6877 &smb_fname->st,
6878 size,
6879 fail_after_createfile);
6882 /****************************************************************************
6883 Allow a UNIX info mknod.
6884 ****************************************************************************/
6886 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6887 const char *pdata,
6888 int total_data,
6889 const struct smb_filename *smb_fname)
6891 uint32 file_type = IVAL(pdata,56);
6892 #if defined(HAVE_MAKEDEV)
6893 uint32 dev_major = IVAL(pdata,60);
6894 uint32 dev_minor = IVAL(pdata,68);
6895 #endif
6896 SMB_DEV_T dev = (SMB_DEV_T)0;
6897 uint32 raw_unixmode = IVAL(pdata,84);
6898 NTSTATUS status;
6899 mode_t unixmode;
6901 if (total_data < 100) {
6902 return NT_STATUS_INVALID_PARAMETER;
6905 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6906 PERM_NEW_FILE, &unixmode);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 return status;
6911 #if defined(HAVE_MAKEDEV)
6912 dev = makedev(dev_major, dev_minor);
6913 #endif
6915 switch (file_type) {
6916 #if defined(S_IFIFO)
6917 case UNIX_TYPE_FIFO:
6918 unixmode |= S_IFIFO;
6919 break;
6920 #endif
6921 #if defined(S_IFSOCK)
6922 case UNIX_TYPE_SOCKET:
6923 unixmode |= S_IFSOCK;
6924 break;
6925 #endif
6926 #if defined(S_IFCHR)
6927 case UNIX_TYPE_CHARDEV:
6928 unixmode |= S_IFCHR;
6929 break;
6930 #endif
6931 #if defined(S_IFBLK)
6932 case UNIX_TYPE_BLKDEV:
6933 unixmode |= S_IFBLK;
6934 break;
6935 #endif
6936 default:
6937 return NT_STATUS_INVALID_PARAMETER;
6940 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6941 "%.0f mode 0%o for file %s\n", (double)dev,
6942 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6944 /* Ok - do the mknod. */
6945 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6946 return map_nt_error_from_unix(errno);
6949 /* If any of the other "set" calls fail we
6950 * don't want to end up with a half-constructed mknod.
6953 if (lp_inherit_perms(SNUM(conn))) {
6954 char *parent;
6955 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6956 &parent, NULL)) {
6957 return NT_STATUS_NO_MEMORY;
6959 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6960 unixmode);
6961 TALLOC_FREE(parent);
6964 return NT_STATUS_OK;
6967 /****************************************************************************
6968 Deal with SMB_SET_FILE_UNIX_BASIC.
6969 ****************************************************************************/
6971 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6972 struct smb_request *req,
6973 const char *pdata,
6974 int total_data,
6975 files_struct *fsp,
6976 const struct smb_filename *smb_fname)
6978 struct smb_file_time ft;
6979 uint32 raw_unixmode;
6980 mode_t unixmode;
6981 off_t size = 0;
6982 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6983 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6984 NTSTATUS status = NT_STATUS_OK;
6985 bool delete_on_fail = False;
6986 enum perm_type ptype;
6987 files_struct *all_fsps = NULL;
6988 bool modify_mtime = true;
6989 struct file_id id;
6990 struct smb_filename *smb_fname_tmp = NULL;
6991 SMB_STRUCT_STAT sbuf;
6993 ZERO_STRUCT(ft);
6995 if (total_data < 100) {
6996 return NT_STATUS_INVALID_PARAMETER;
6999 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7000 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7001 size=IVAL(pdata,0); /* first 8 Bytes are size */
7002 size |= (((off_t)IVAL(pdata,4)) << 32);
7005 ft.atime = interpret_long_date(pdata+24); /* access_time */
7006 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7007 set_owner = (uid_t)IVAL(pdata,40);
7008 set_grp = (gid_t)IVAL(pdata,48);
7009 raw_unixmode = IVAL(pdata,84);
7011 if (VALID_STAT(smb_fname->st)) {
7012 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7013 ptype = PERM_EXISTING_DIR;
7014 } else {
7015 ptype = PERM_EXISTING_FILE;
7017 } else {
7018 ptype = PERM_NEW_FILE;
7021 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7022 ptype, &unixmode);
7023 if (!NT_STATUS_IS_OK(status)) {
7024 return status;
7027 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7028 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7029 smb_fname_str_dbg(smb_fname), (double)size,
7030 (unsigned int)set_owner, (unsigned int)set_grp,
7031 (int)raw_unixmode));
7033 sbuf = smb_fname->st;
7035 if (!VALID_STAT(sbuf)) {
7037 * The only valid use of this is to create character and block
7038 * devices, and named pipes. This is deprecated (IMHO) and
7039 * a new info level should be used for mknod. JRA.
7042 status = smb_unix_mknod(conn,
7043 pdata,
7044 total_data,
7045 smb_fname);
7046 if (!NT_STATUS_IS_OK(status)) {
7047 return status;
7050 status = copy_smb_filename(talloc_tos(), smb_fname,
7051 &smb_fname_tmp);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return status;
7056 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7057 status = map_nt_error_from_unix(errno);
7058 TALLOC_FREE(smb_fname_tmp);
7059 SMB_VFS_UNLINK(conn, smb_fname);
7060 return status;
7063 sbuf = smb_fname_tmp->st;
7064 smb_fname = smb_fname_tmp;
7066 /* Ensure we don't try and change anything else. */
7067 raw_unixmode = SMB_MODE_NO_CHANGE;
7068 size = get_file_size_stat(&sbuf);
7069 ft.atime = sbuf.st_ex_atime;
7070 ft.mtime = sbuf.st_ex_mtime;
7072 * We continue here as we might want to change the
7073 * owner uid/gid.
7075 delete_on_fail = True;
7078 #if 1
7079 /* Horrible backwards compatibility hack as an old server bug
7080 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7081 * */
7083 if (!size) {
7084 size = get_file_size_stat(&sbuf);
7086 #endif
7089 * Deal with the UNIX specific mode set.
7092 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7093 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7094 "setting mode 0%o for file %s\n",
7095 (unsigned int)unixmode,
7096 smb_fname_str_dbg(smb_fname)));
7097 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7098 return map_nt_error_from_unix(errno);
7103 * Deal with the UNIX specific uid set.
7106 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7107 (sbuf.st_ex_uid != set_owner)) {
7108 int ret;
7110 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7111 "changing owner %u for path %s\n",
7112 (unsigned int)set_owner,
7113 smb_fname_str_dbg(smb_fname)));
7115 if (S_ISLNK(sbuf.st_ex_mode)) {
7116 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7117 set_owner, (gid_t)-1);
7118 } else {
7119 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7120 set_owner, (gid_t)-1);
7123 if (ret != 0) {
7124 status = map_nt_error_from_unix(errno);
7125 if (delete_on_fail) {
7126 SMB_VFS_UNLINK(conn, smb_fname);
7128 return status;
7133 * Deal with the UNIX specific gid set.
7136 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7137 (sbuf.st_ex_gid != set_grp)) {
7138 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7139 "changing group %u for file %s\n",
7140 (unsigned int)set_owner,
7141 smb_fname_str_dbg(smb_fname)));
7142 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7143 set_grp) != 0) {
7144 status = map_nt_error_from_unix(errno);
7145 if (delete_on_fail) {
7146 SMB_VFS_UNLINK(conn, smb_fname);
7148 return status;
7152 /* Deal with any size changes. */
7154 status = smb_set_file_size(conn, req,
7155 fsp,
7156 smb_fname,
7157 &sbuf,
7158 size,
7159 false);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 return status;
7164 /* Deal with any time changes. */
7165 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7166 /* No change, don't cancel anything. */
7167 return status;
7170 id = vfs_file_id_from_sbuf(conn, &sbuf);
7171 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7172 all_fsps = file_find_di_next(all_fsps)) {
7174 * We're setting the time explicitly for UNIX.
7175 * Cancel any pending changes over all handles.
7177 all_fsps->update_write_time_on_close = false;
7178 TALLOC_FREE(all_fsps->update_write_time_event);
7182 * Override the "setting_write_time"
7183 * parameter here as it almost does what
7184 * we need. Just remember if we modified
7185 * mtime and send the notify ourselves.
7187 if (null_timespec(ft.mtime)) {
7188 modify_mtime = false;
7191 status = smb_set_file_time(conn,
7192 fsp,
7193 smb_fname,
7194 &ft,
7195 false);
7196 if (modify_mtime) {
7197 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7198 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7200 return status;
7203 /****************************************************************************
7204 Deal with SMB_SET_FILE_UNIX_INFO2.
7205 ****************************************************************************/
7207 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7208 struct smb_request *req,
7209 const char *pdata,
7210 int total_data,
7211 files_struct *fsp,
7212 const struct smb_filename *smb_fname)
7214 NTSTATUS status;
7215 uint32 smb_fflags;
7216 uint32 smb_fmask;
7218 if (total_data < 116) {
7219 return NT_STATUS_INVALID_PARAMETER;
7222 /* Start by setting all the fields that are common between UNIX_BASIC
7223 * and UNIX_INFO2.
7225 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7226 fsp, smb_fname);
7227 if (!NT_STATUS_IS_OK(status)) {
7228 return status;
7231 smb_fflags = IVAL(pdata, 108);
7232 smb_fmask = IVAL(pdata, 112);
7234 /* NB: We should only attempt to alter the file flags if the client
7235 * sends a non-zero mask.
7237 if (smb_fmask != 0) {
7238 int stat_fflags = 0;
7240 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7241 smb_fmask, &stat_fflags)) {
7242 /* Client asked to alter a flag we don't understand. */
7243 return NT_STATUS_INVALID_PARAMETER;
7246 if (fsp && fsp->fh->fd != -1) {
7247 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7248 return NT_STATUS_NOT_SUPPORTED;
7249 } else {
7250 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7251 stat_fflags) != 0) {
7252 return map_nt_error_from_unix(errno);
7257 /* XXX: need to add support for changing the create_time here. You
7258 * can do this for paths on Darwin with setattrlist(2). The right way
7259 * to hook this up is probably by extending the VFS utimes interface.
7262 return NT_STATUS_OK;
7265 /****************************************************************************
7266 Create a directory with POSIX semantics.
7267 ****************************************************************************/
7269 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7270 struct smb_request *req,
7271 char **ppdata,
7272 int total_data,
7273 struct smb_filename *smb_fname,
7274 int *pdata_return_size)
7276 NTSTATUS status = NT_STATUS_OK;
7277 uint32 raw_unixmode = 0;
7278 uint32 mod_unixmode = 0;
7279 mode_t unixmode = (mode_t)0;
7280 files_struct *fsp = NULL;
7281 uint16 info_level_return = 0;
7282 int info;
7283 char *pdata = *ppdata;
7285 if (total_data < 18) {
7286 return NT_STATUS_INVALID_PARAMETER;
7289 raw_unixmode = IVAL(pdata,8);
7290 /* Next 4 bytes are not yet defined. */
7292 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7293 PERM_NEW_DIR, &unixmode);
7294 if (!NT_STATUS_IS_OK(status)) {
7295 return status;
7298 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7300 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7301 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7303 status = SMB_VFS_CREATE_FILE(
7304 conn, /* conn */
7305 req, /* req */
7306 0, /* root_dir_fid */
7307 smb_fname, /* fname */
7308 FILE_READ_ATTRIBUTES, /* access_mask */
7309 FILE_SHARE_NONE, /* share_access */
7310 FILE_CREATE, /* create_disposition*/
7311 FILE_DIRECTORY_FILE, /* create_options */
7312 mod_unixmode, /* file_attributes */
7313 0, /* oplock_request */
7314 0, /* allocation_size */
7315 0, /* private_flags */
7316 NULL, /* sd */
7317 NULL, /* ea_list */
7318 &fsp, /* result */
7319 &info); /* pinfo */
7321 if (NT_STATUS_IS_OK(status)) {
7322 close_file(req, fsp, NORMAL_CLOSE);
7325 info_level_return = SVAL(pdata,16);
7327 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7328 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7329 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7330 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7331 } else {
7332 *pdata_return_size = 12;
7335 /* Realloc the data size */
7336 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7337 if (*ppdata == NULL) {
7338 *pdata_return_size = 0;
7339 return NT_STATUS_NO_MEMORY;
7341 pdata = *ppdata;
7343 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7344 SSVAL(pdata,2,0); /* No fnum. */
7345 SIVAL(pdata,4,info); /* Was directory created. */
7347 switch (info_level_return) {
7348 case SMB_QUERY_FILE_UNIX_BASIC:
7349 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7350 SSVAL(pdata,10,0); /* Padding. */
7351 store_file_unix_basic(conn, pdata + 12, fsp,
7352 &smb_fname->st);
7353 break;
7354 case SMB_QUERY_FILE_UNIX_INFO2:
7355 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7356 SSVAL(pdata,10,0); /* Padding. */
7357 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7358 &smb_fname->st);
7359 break;
7360 default:
7361 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7362 SSVAL(pdata,10,0); /* Padding. */
7363 break;
7366 return status;
7369 /****************************************************************************
7370 Open/Create a file with POSIX semantics.
7371 ****************************************************************************/
7373 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7374 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7376 static NTSTATUS smb_posix_open(connection_struct *conn,
7377 struct smb_request *req,
7378 char **ppdata,
7379 int total_data,
7380 struct smb_filename *smb_fname,
7381 int *pdata_return_size)
7383 bool extended_oplock_granted = False;
7384 char *pdata = *ppdata;
7385 uint32 flags = 0;
7386 uint32 wire_open_mode = 0;
7387 uint32 raw_unixmode = 0;
7388 uint32 mod_unixmode = 0;
7389 uint32 create_disp = 0;
7390 uint32 access_mask = 0;
7391 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7392 NTSTATUS status = NT_STATUS_OK;
7393 mode_t unixmode = (mode_t)0;
7394 files_struct *fsp = NULL;
7395 int oplock_request = 0;
7396 int info = 0;
7397 uint16 info_level_return = 0;
7399 if (total_data < 18) {
7400 return NT_STATUS_INVALID_PARAMETER;
7403 flags = IVAL(pdata,0);
7404 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7405 if (oplock_request) {
7406 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7409 wire_open_mode = IVAL(pdata,4);
7411 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7412 return smb_posix_mkdir(conn, req,
7413 ppdata,
7414 total_data,
7415 smb_fname,
7416 pdata_return_size);
7419 switch (wire_open_mode & SMB_ACCMODE) {
7420 case SMB_O_RDONLY:
7421 access_mask = SMB_O_RDONLY_MAPPING;
7422 break;
7423 case SMB_O_WRONLY:
7424 access_mask = SMB_O_WRONLY_MAPPING;
7425 break;
7426 case SMB_O_RDWR:
7427 access_mask = (SMB_O_RDONLY_MAPPING|
7428 SMB_O_WRONLY_MAPPING);
7429 break;
7430 default:
7431 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7432 (unsigned int)wire_open_mode ));
7433 return NT_STATUS_INVALID_PARAMETER;
7436 wire_open_mode &= ~SMB_ACCMODE;
7438 /* First take care of O_CREAT|O_EXCL interactions. */
7439 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7440 case (SMB_O_CREAT | SMB_O_EXCL):
7441 /* File exists fail. File not exist create. */
7442 create_disp = FILE_CREATE;
7443 break;
7444 case SMB_O_CREAT:
7445 /* File exists open. File not exist create. */
7446 create_disp = FILE_OPEN_IF;
7447 break;
7448 case SMB_O_EXCL:
7449 /* O_EXCL on its own without O_CREAT is undefined.
7450 We deliberately ignore it as some versions of
7451 Linux CIFSFS can send a bare O_EXCL on the
7452 wire which other filesystems in the kernel
7453 ignore. See bug 9519 for details. */
7455 /* Fallthrough. */
7457 case 0:
7458 /* File exists open. File not exist fail. */
7459 create_disp = FILE_OPEN;
7460 break;
7461 default:
7462 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7463 (unsigned int)wire_open_mode ));
7464 return NT_STATUS_INVALID_PARAMETER;
7467 /* Next factor in the effects of O_TRUNC. */
7468 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7470 if (wire_open_mode & SMB_O_TRUNC) {
7471 switch (create_disp) {
7472 case FILE_CREATE:
7473 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7474 /* Leave create_disp alone as
7475 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7477 /* File exists fail. File not exist create. */
7478 break;
7479 case FILE_OPEN_IF:
7480 /* SMB_O_CREAT | SMB_O_TRUNC */
7481 /* File exists overwrite. File not exist create. */
7482 create_disp = FILE_OVERWRITE_IF;
7483 break;
7484 case FILE_OPEN:
7485 /* SMB_O_TRUNC */
7486 /* File exists overwrite. File not exist fail. */
7487 create_disp = FILE_OVERWRITE;
7488 break;
7489 default:
7490 /* Cannot get here. */
7491 smb_panic("smb_posix_open: logic error");
7492 return NT_STATUS_INVALID_PARAMETER;
7496 raw_unixmode = IVAL(pdata,8);
7497 /* Next 4 bytes are not yet defined. */
7499 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7500 (VALID_STAT(smb_fname->st) ?
7501 PERM_EXISTING_FILE : PERM_NEW_FILE),
7502 &unixmode);
7504 if (!NT_STATUS_IS_OK(status)) {
7505 return status;
7508 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7510 if (wire_open_mode & SMB_O_SYNC) {
7511 create_options |= FILE_WRITE_THROUGH;
7513 if (wire_open_mode & SMB_O_APPEND) {
7514 access_mask |= FILE_APPEND_DATA;
7516 if (wire_open_mode & SMB_O_DIRECT) {
7517 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7520 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7521 VALID_STAT_OF_DIR(smb_fname->st)) {
7522 if (access_mask != SMB_O_RDONLY_MAPPING) {
7523 return NT_STATUS_FILE_IS_A_DIRECTORY;
7525 create_options &= ~FILE_NON_DIRECTORY_FILE;
7526 create_options |= FILE_DIRECTORY_FILE;
7529 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7530 smb_fname_str_dbg(smb_fname),
7531 (unsigned int)wire_open_mode,
7532 (unsigned int)unixmode ));
7534 status = SMB_VFS_CREATE_FILE(
7535 conn, /* conn */
7536 req, /* req */
7537 0, /* root_dir_fid */
7538 smb_fname, /* fname */
7539 access_mask, /* access_mask */
7540 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7541 FILE_SHARE_DELETE),
7542 create_disp, /* create_disposition*/
7543 create_options, /* create_options */
7544 mod_unixmode, /* file_attributes */
7545 oplock_request, /* oplock_request */
7546 0, /* allocation_size */
7547 0, /* private_flags */
7548 NULL, /* sd */
7549 NULL, /* ea_list */
7550 &fsp, /* result */
7551 &info); /* pinfo */
7553 if (!NT_STATUS_IS_OK(status)) {
7554 return status;
7557 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7558 extended_oplock_granted = True;
7561 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7562 extended_oplock_granted = True;
7565 info_level_return = SVAL(pdata,16);
7567 /* Allocate the correct return size. */
7569 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7570 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7571 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7572 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7573 } else {
7574 *pdata_return_size = 12;
7577 /* Realloc the data size */
7578 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7579 if (*ppdata == NULL) {
7580 close_file(req, fsp, ERROR_CLOSE);
7581 *pdata_return_size = 0;
7582 return NT_STATUS_NO_MEMORY;
7584 pdata = *ppdata;
7586 if (extended_oplock_granted) {
7587 if (flags & REQUEST_BATCH_OPLOCK) {
7588 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7589 } else {
7590 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7592 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7593 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7594 } else {
7595 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7598 SSVAL(pdata,2,fsp->fnum);
7599 SIVAL(pdata,4,info); /* Was file created etc. */
7601 switch (info_level_return) {
7602 case SMB_QUERY_FILE_UNIX_BASIC:
7603 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7604 SSVAL(pdata,10,0); /* padding. */
7605 store_file_unix_basic(conn, pdata + 12, fsp,
7606 &smb_fname->st);
7607 break;
7608 case SMB_QUERY_FILE_UNIX_INFO2:
7609 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7610 SSVAL(pdata,10,0); /* padding. */
7611 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7612 &smb_fname->st);
7613 break;
7614 default:
7615 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7616 SSVAL(pdata,10,0); /* padding. */
7617 break;
7619 return NT_STATUS_OK;
7622 /****************************************************************************
7623 Delete a file with POSIX semantics.
7624 ****************************************************************************/
7626 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7627 struct smb_request *req,
7628 const char *pdata,
7629 int total_data,
7630 struct smb_filename *smb_fname)
7632 NTSTATUS status = NT_STATUS_OK;
7633 files_struct *fsp = NULL;
7634 uint16 flags = 0;
7635 char del = 1;
7636 int info = 0;
7637 int create_options = 0;
7638 int i;
7639 struct share_mode_lock *lck = NULL;
7641 if (total_data < 2) {
7642 return NT_STATUS_INVALID_PARAMETER;
7645 flags = SVAL(pdata,0);
7647 if (!VALID_STAT(smb_fname->st)) {
7648 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7651 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7652 !VALID_STAT_OF_DIR(smb_fname->st)) {
7653 return NT_STATUS_NOT_A_DIRECTORY;
7656 DEBUG(10,("smb_posix_unlink: %s %s\n",
7657 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7658 smb_fname_str_dbg(smb_fname)));
7660 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7661 create_options |= FILE_DIRECTORY_FILE;
7664 status = SMB_VFS_CREATE_FILE(
7665 conn, /* conn */
7666 req, /* req */
7667 0, /* root_dir_fid */
7668 smb_fname, /* fname */
7669 DELETE_ACCESS, /* access_mask */
7670 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7671 FILE_SHARE_DELETE),
7672 FILE_OPEN, /* create_disposition*/
7673 create_options, /* create_options */
7674 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7675 0, /* oplock_request */
7676 0, /* allocation_size */
7677 0, /* private_flags */
7678 NULL, /* sd */
7679 NULL, /* ea_list */
7680 &fsp, /* result */
7681 &info); /* pinfo */
7683 if (!NT_STATUS_IS_OK(status)) {
7684 return status;
7688 * Don't lie to client. If we can't really delete due to
7689 * non-POSIX opens return SHARING_VIOLATION.
7692 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7693 if (lck == NULL) {
7694 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7695 "lock for file %s\n", fsp_str_dbg(fsp)));
7696 close_file(req, fsp, NORMAL_CLOSE);
7697 return NT_STATUS_INVALID_PARAMETER;
7701 * See if others still have the file open. If this is the case, then
7702 * don't delete. If all opens are POSIX delete we can set the delete
7703 * on close disposition.
7705 for (i=0; i<lck->data->num_share_modes; i++) {
7706 struct share_mode_entry *e = &lck->data->share_modes[i];
7707 if (is_valid_share_mode_entry(e)) {
7708 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7709 continue;
7711 if (share_mode_stale_pid(lck->data, i)) {
7712 continue;
7714 /* Fail with sharing violation. */
7715 TALLOC_FREE(lck);
7716 close_file(req, fsp, NORMAL_CLOSE);
7717 return NT_STATUS_SHARING_VIOLATION;
7722 * Set the delete on close.
7724 status = smb_set_file_disposition_info(conn,
7725 &del,
7727 fsp,
7728 smb_fname);
7730 TALLOC_FREE(lck);
7732 if (!NT_STATUS_IS_OK(status)) {
7733 close_file(req, fsp, NORMAL_CLOSE);
7734 return status;
7736 return close_file(req, fsp, NORMAL_CLOSE);
7739 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7740 struct smb_request *req,
7741 TALLOC_CTX *mem_ctx,
7742 uint16_t info_level,
7743 files_struct *fsp,
7744 struct smb_filename *smb_fname,
7745 char **ppdata, int total_data,
7746 int *ret_data_size)
7748 char *pdata = *ppdata;
7749 NTSTATUS status = NT_STATUS_OK;
7750 int data_return_size = 0;
7752 *ret_data_size = 0;
7754 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7755 return NT_STATUS_INVALID_LEVEL;
7758 if (!CAN_WRITE(conn)) {
7759 /* Allow POSIX opens. The open path will deny
7760 * any non-readonly opens. */
7761 if (info_level != SMB_POSIX_PATH_OPEN) {
7762 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7766 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7767 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7768 fsp_fnum_dbg(fsp),
7769 info_level, total_data));
7771 switch (info_level) {
7773 case SMB_INFO_STANDARD:
7775 status = smb_set_info_standard(conn,
7776 pdata,
7777 total_data,
7778 fsp,
7779 smb_fname);
7780 break;
7783 case SMB_INFO_SET_EA:
7785 status = smb_info_set_ea(conn,
7786 pdata,
7787 total_data,
7788 fsp,
7789 smb_fname);
7790 break;
7793 case SMB_SET_FILE_BASIC_INFO:
7794 case SMB_FILE_BASIC_INFORMATION:
7796 status = smb_set_file_basic_info(conn,
7797 pdata,
7798 total_data,
7799 fsp,
7800 smb_fname);
7801 break;
7804 case SMB_FILE_ALLOCATION_INFORMATION:
7805 case SMB_SET_FILE_ALLOCATION_INFO:
7807 status = smb_set_file_allocation_info(conn, req,
7808 pdata,
7809 total_data,
7810 fsp,
7811 smb_fname);
7812 break;
7815 case SMB_FILE_END_OF_FILE_INFORMATION:
7816 case SMB_SET_FILE_END_OF_FILE_INFO:
7819 * XP/Win7 both fail after the createfile with
7820 * SMB_SET_FILE_END_OF_FILE_INFO but not
7821 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7822 * The level is known here, so pass it down
7823 * appropriately.
7825 bool should_fail =
7826 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7828 status = smb_set_file_end_of_file_info(conn, req,
7829 pdata,
7830 total_data,
7831 fsp,
7832 smb_fname,
7833 should_fail);
7834 break;
7837 case SMB_FILE_DISPOSITION_INFORMATION:
7838 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7840 #if 0
7841 /* JRA - We used to just ignore this on a path ?
7842 * Shouldn't this be invalid level on a pathname
7843 * based call ?
7845 if (tran_call != TRANSACT2_SETFILEINFO) {
7846 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7848 #endif
7849 status = smb_set_file_disposition_info(conn,
7850 pdata,
7851 total_data,
7852 fsp,
7853 smb_fname);
7854 break;
7857 case SMB_FILE_POSITION_INFORMATION:
7859 status = smb_file_position_information(conn,
7860 pdata,
7861 total_data,
7862 fsp);
7863 break;
7866 case SMB_FILE_FULL_EA_INFORMATION:
7868 status = smb_set_file_full_ea_info(conn,
7869 pdata,
7870 total_data,
7871 fsp);
7872 break;
7875 /* From tridge Samba4 :
7876 * MODE_INFORMATION in setfileinfo (I have no
7877 * idea what "mode information" on a file is - it takes a value of 0,
7878 * 2, 4 or 6. What could it be?).
7881 case SMB_FILE_MODE_INFORMATION:
7883 status = smb_file_mode_information(conn,
7884 pdata,
7885 total_data);
7886 break;
7890 * CIFS UNIX extensions.
7893 case SMB_SET_FILE_UNIX_BASIC:
7895 status = smb_set_file_unix_basic(conn, req,
7896 pdata,
7897 total_data,
7898 fsp,
7899 smb_fname);
7900 break;
7903 case SMB_SET_FILE_UNIX_INFO2:
7905 status = smb_set_file_unix_info2(conn, req,
7906 pdata,
7907 total_data,
7908 fsp,
7909 smb_fname);
7910 break;
7913 case SMB_SET_FILE_UNIX_LINK:
7915 if (fsp) {
7916 /* We must have a pathname for this. */
7917 return NT_STATUS_INVALID_LEVEL;
7919 status = smb_set_file_unix_link(conn, req, pdata,
7920 total_data, smb_fname);
7921 break;
7924 case SMB_SET_FILE_UNIX_HLINK:
7926 if (fsp) {
7927 /* We must have a pathname for this. */
7928 return NT_STATUS_INVALID_LEVEL;
7930 status = smb_set_file_unix_hlink(conn, req,
7931 pdata, total_data,
7932 smb_fname);
7933 break;
7936 case SMB_FILE_RENAME_INFORMATION:
7938 status = smb_file_rename_information(conn, req,
7939 pdata, total_data,
7940 fsp, smb_fname);
7941 break;
7944 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7946 /* SMB2 rename information. */
7947 status = smb2_file_rename_information(conn, req,
7948 pdata, total_data,
7949 fsp, smb_fname);
7950 break;
7953 case SMB_FILE_LINK_INFORMATION:
7955 status = smb_file_link_information(conn, req,
7956 pdata, total_data,
7957 fsp, smb_fname);
7958 break;
7961 #if defined(HAVE_POSIX_ACLS)
7962 case SMB_SET_POSIX_ACL:
7964 status = smb_set_posix_acl(conn,
7965 pdata,
7966 total_data,
7967 fsp,
7968 smb_fname);
7969 break;
7971 #endif
7973 case SMB_SET_POSIX_LOCK:
7975 if (!fsp) {
7976 return NT_STATUS_INVALID_LEVEL;
7978 status = smb_set_posix_lock(conn, req,
7979 pdata, total_data, fsp);
7980 break;
7983 case SMB_POSIX_PATH_OPEN:
7985 if (fsp) {
7986 /* We must have a pathname for this. */
7987 return NT_STATUS_INVALID_LEVEL;
7990 status = smb_posix_open(conn, req,
7991 ppdata,
7992 total_data,
7993 smb_fname,
7994 &data_return_size);
7995 break;
7998 case SMB_POSIX_PATH_UNLINK:
8000 if (fsp) {
8001 /* We must have a pathname for this. */
8002 return NT_STATUS_INVALID_LEVEL;
8005 status = smb_posix_unlink(conn, req,
8006 pdata,
8007 total_data,
8008 smb_fname);
8009 break;
8012 default:
8013 return NT_STATUS_INVALID_LEVEL;
8016 if (!NT_STATUS_IS_OK(status)) {
8017 return status;
8020 *ret_data_size = data_return_size;
8021 return NT_STATUS_OK;
8024 /****************************************************************************
8025 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8026 ****************************************************************************/
8028 static void call_trans2setfilepathinfo(connection_struct *conn,
8029 struct smb_request *req,
8030 unsigned int tran_call,
8031 char **pparams, int total_params,
8032 char **ppdata, int total_data,
8033 unsigned int max_data_bytes)
8035 char *params = *pparams;
8036 char *pdata = *ppdata;
8037 uint16 info_level;
8038 struct smb_filename *smb_fname = NULL;
8039 files_struct *fsp = NULL;
8040 NTSTATUS status = NT_STATUS_OK;
8041 int data_return_size = 0;
8043 if (!params) {
8044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8045 return;
8048 if (tran_call == TRANSACT2_SETFILEINFO) {
8049 if (total_params < 4) {
8050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8051 return;
8054 fsp = file_fsp(req, SVAL(params,0));
8055 /* Basic check for non-null fsp. */
8056 if (!check_fsp_open(conn, req, fsp)) {
8057 return;
8059 info_level = SVAL(params,2);
8061 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8062 &smb_fname);
8063 if (!NT_STATUS_IS_OK(status)) {
8064 reply_nterror(req, status);
8065 return;
8068 if(fsp->fh->fd == -1) {
8070 * This is actually a SETFILEINFO on a directory
8071 * handle (returned from an NT SMB). NT5.0 seems
8072 * to do this call. JRA.
8074 if (INFO_LEVEL_IS_UNIX(info_level)) {
8075 /* Always do lstat for UNIX calls. */
8076 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8077 DEBUG(3,("call_trans2setfilepathinfo: "
8078 "SMB_VFS_LSTAT of %s failed "
8079 "(%s)\n",
8080 smb_fname_str_dbg(smb_fname),
8081 strerror(errno)));
8082 reply_nterror(req, map_nt_error_from_unix(errno));
8083 return;
8085 } else {
8086 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8087 DEBUG(3,("call_trans2setfilepathinfo: "
8088 "fileinfo of %s failed (%s)\n",
8089 smb_fname_str_dbg(smb_fname),
8090 strerror(errno)));
8091 reply_nterror(req, map_nt_error_from_unix(errno));
8092 return;
8095 } else if (fsp->print_file) {
8097 * Doing a DELETE_ON_CLOSE should cancel a print job.
8099 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8100 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8102 DEBUG(3,("call_trans2setfilepathinfo: "
8103 "Cancelling print job (%s)\n",
8104 fsp_str_dbg(fsp)));
8106 SSVAL(params,0,0);
8107 send_trans2_replies(conn, req, params, 2,
8108 *ppdata, 0,
8109 max_data_bytes);
8110 return;
8111 } else {
8112 reply_nterror(req,
8113 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8114 return;
8116 } else {
8118 * Original code - this is an open file.
8120 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8121 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8122 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8123 strerror(errno)));
8124 reply_nterror(req, map_nt_error_from_unix(errno));
8125 return;
8128 } else {
8129 char *fname = NULL;
8130 uint32_t ucf_flags = 0;
8132 /* set path info */
8133 if (total_params < 7) {
8134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8135 return;
8138 info_level = SVAL(params,0);
8139 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8140 total_params - 6, STR_TERMINATE,
8141 &status);
8142 if (!NT_STATUS_IS_OK(status)) {
8143 reply_nterror(req, status);
8144 return;
8147 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8148 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8149 info_level == SMB_FILE_RENAME_INFORMATION ||
8150 info_level == SMB_POSIX_PATH_UNLINK) {
8151 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8154 status = filename_convert(req, conn,
8155 req->flags2 & FLAGS2_DFS_PATHNAMES,
8156 fname,
8157 ucf_flags,
8158 NULL,
8159 &smb_fname);
8160 if (!NT_STATUS_IS_OK(status)) {
8161 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8162 reply_botherror(req,
8163 NT_STATUS_PATH_NOT_COVERED,
8164 ERRSRV, ERRbadpath);
8165 return;
8167 reply_nterror(req, status);
8168 return;
8171 if (INFO_LEVEL_IS_UNIX(info_level)) {
8173 * For CIFS UNIX extensions the target name may not exist.
8176 /* Always do lstat for UNIX calls. */
8177 SMB_VFS_LSTAT(conn, smb_fname);
8179 } else if (!VALID_STAT(smb_fname->st) &&
8180 SMB_VFS_STAT(conn, smb_fname)) {
8181 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8182 "%s failed (%s)\n",
8183 smb_fname_str_dbg(smb_fname),
8184 strerror(errno)));
8185 reply_nterror(req, map_nt_error_from_unix(errno));
8186 return;
8190 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8191 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8192 fsp_fnum_dbg(fsp),
8193 info_level,total_data));
8195 /* Realloc the parameter size */
8196 *pparams = (char *)SMB_REALLOC(*pparams,2);
8197 if (*pparams == NULL) {
8198 reply_nterror(req, NT_STATUS_NO_MEMORY);
8199 return;
8201 params = *pparams;
8203 SSVAL(params,0,0);
8205 status = smbd_do_setfilepathinfo(conn, req, req,
8206 info_level,
8207 fsp,
8208 smb_fname,
8209 ppdata, total_data,
8210 &data_return_size);
8211 if (!NT_STATUS_IS_OK(status)) {
8212 if (open_was_deferred(req->sconn, req->mid)) {
8213 /* We have re-scheduled this call. */
8214 return;
8216 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8217 /* We have re-scheduled this call. */
8218 return;
8220 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8221 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8222 ERRSRV, ERRbadpath);
8223 return;
8225 if (info_level == SMB_POSIX_PATH_OPEN) {
8226 reply_openerror(req, status);
8227 return;
8230 reply_nterror(req, status);
8231 return;
8234 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8235 max_data_bytes);
8237 return;
8240 /****************************************************************************
8241 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8242 ****************************************************************************/
8244 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8245 char **pparams, int total_params,
8246 char **ppdata, int total_data,
8247 unsigned int max_data_bytes)
8249 struct smb_filename *smb_dname = NULL;
8250 char *params = *pparams;
8251 char *pdata = *ppdata;
8252 char *directory = NULL;
8253 NTSTATUS status = NT_STATUS_OK;
8254 struct ea_list *ea_list = NULL;
8255 TALLOC_CTX *ctx = talloc_tos();
8257 if (!CAN_WRITE(conn)) {
8258 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8259 return;
8262 if (total_params < 5) {
8263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8264 return;
8267 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8268 total_params - 4, STR_TERMINATE,
8269 &status);
8270 if (!NT_STATUS_IS_OK(status)) {
8271 reply_nterror(req, status);
8272 return;
8275 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8277 status = filename_convert(ctx,
8278 conn,
8279 req->flags2 & FLAGS2_DFS_PATHNAMES,
8280 directory,
8282 NULL,
8283 &smb_dname);
8285 if (!NT_STATUS_IS_OK(status)) {
8286 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8287 reply_botherror(req,
8288 NT_STATUS_PATH_NOT_COVERED,
8289 ERRSRV, ERRbadpath);
8290 return;
8292 reply_nterror(req, status);
8293 return;
8297 * OS/2 workplace shell seems to send SET_EA requests of "null"
8298 * length (4 bytes containing IVAL 4).
8299 * They seem to have no effect. Bug #3212. JRA.
8302 if (total_data && (total_data != 4)) {
8303 /* Any data in this call is an EA list. */
8304 if (total_data < 10) {
8305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8306 goto out;
8309 if (IVAL(pdata,0) > total_data) {
8310 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8311 IVAL(pdata,0), (unsigned int)total_data));
8312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8313 goto out;
8316 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8317 total_data - 4);
8318 if (!ea_list) {
8319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8320 goto out;
8323 if (!lp_ea_support(SNUM(conn))) {
8324 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8325 goto out;
8328 /* If total_data == 4 Windows doesn't care what values
8329 * are placed in that field, it just ignores them.
8330 * The System i QNTC IBM SMB client puts bad values here,
8331 * so ignore them. */
8333 status = create_directory(conn, req, smb_dname);
8335 if (!NT_STATUS_IS_OK(status)) {
8336 reply_nterror(req, status);
8337 goto out;
8340 /* Try and set any given EA. */
8341 if (ea_list) {
8342 status = set_ea(conn, NULL, smb_dname, ea_list);
8343 if (!NT_STATUS_IS_OK(status)) {
8344 reply_nterror(req, status);
8345 goto out;
8349 /* Realloc the parameter and data sizes */
8350 *pparams = (char *)SMB_REALLOC(*pparams,2);
8351 if(*pparams == NULL) {
8352 reply_nterror(req, NT_STATUS_NO_MEMORY);
8353 goto out;
8355 params = *pparams;
8357 SSVAL(params,0,0);
8359 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8361 out:
8362 TALLOC_FREE(smb_dname);
8363 return;
8366 /****************************************************************************
8367 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8368 We don't actually do this - we just send a null response.
8369 ****************************************************************************/
8371 static void call_trans2findnotifyfirst(connection_struct *conn,
8372 struct smb_request *req,
8373 char **pparams, int total_params,
8374 char **ppdata, int total_data,
8375 unsigned int max_data_bytes)
8377 char *params = *pparams;
8378 uint16 info_level;
8380 if (total_params < 6) {
8381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8382 return;
8385 info_level = SVAL(params,4);
8386 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8388 switch (info_level) {
8389 case 1:
8390 case 2:
8391 break;
8392 default:
8393 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8394 return;
8397 /* Realloc the parameter and data sizes */
8398 *pparams = (char *)SMB_REALLOC(*pparams,6);
8399 if (*pparams == NULL) {
8400 reply_nterror(req, NT_STATUS_NO_MEMORY);
8401 return;
8403 params = *pparams;
8405 SSVAL(params,0,fnf_handle);
8406 SSVAL(params,2,0); /* No changes */
8407 SSVAL(params,4,0); /* No EA errors */
8409 fnf_handle++;
8411 if(fnf_handle == 0)
8412 fnf_handle = 257;
8414 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8416 return;
8419 /****************************************************************************
8420 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8421 changes). Currently this does nothing.
8422 ****************************************************************************/
8424 static void call_trans2findnotifynext(connection_struct *conn,
8425 struct smb_request *req,
8426 char **pparams, int total_params,
8427 char **ppdata, int total_data,
8428 unsigned int max_data_bytes)
8430 char *params = *pparams;
8432 DEBUG(3,("call_trans2findnotifynext\n"));
8434 /* Realloc the parameter and data sizes */
8435 *pparams = (char *)SMB_REALLOC(*pparams,4);
8436 if (*pparams == NULL) {
8437 reply_nterror(req, NT_STATUS_NO_MEMORY);
8438 return;
8440 params = *pparams;
8442 SSVAL(params,0,0); /* No changes */
8443 SSVAL(params,2,0); /* No EA errors */
8445 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8447 return;
8450 /****************************************************************************
8451 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8452 ****************************************************************************/
8454 static void call_trans2getdfsreferral(connection_struct *conn,
8455 struct smb_request *req,
8456 char **pparams, int total_params,
8457 char **ppdata, int total_data,
8458 unsigned int max_data_bytes)
8460 char *params = *pparams;
8461 char *pathname = NULL;
8462 int reply_size = 0;
8463 int max_referral_level;
8464 NTSTATUS status = NT_STATUS_OK;
8465 TALLOC_CTX *ctx = talloc_tos();
8467 DEBUG(10,("call_trans2getdfsreferral\n"));
8469 if (total_params < 3) {
8470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8471 return;
8474 max_referral_level = SVAL(params,0);
8476 if(!lp_host_msdfs()) {
8477 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8478 return;
8481 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8482 total_params - 2, STR_TERMINATE);
8483 if (!pathname) {
8484 reply_nterror(req, NT_STATUS_NOT_FOUND);
8485 return;
8487 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8488 ppdata,&status)) < 0) {
8489 reply_nterror(req, status);
8490 return;
8493 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8494 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8495 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8497 return;
8500 #define LMCAT_SPL 0x53
8501 #define LMFUNC_GETJOBID 0x60
8503 /****************************************************************************
8504 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8505 ****************************************************************************/
8507 static void call_trans2ioctl(connection_struct *conn,
8508 struct smb_request *req,
8509 char **pparams, int total_params,
8510 char **ppdata, int total_data,
8511 unsigned int max_data_bytes)
8513 char *pdata = *ppdata;
8514 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8516 /* check for an invalid fid before proceeding */
8518 if (!fsp) {
8519 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8520 return;
8523 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8524 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8525 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8526 if (*ppdata == NULL) {
8527 reply_nterror(req, NT_STATUS_NO_MEMORY);
8528 return;
8530 pdata = *ppdata;
8532 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8533 CAN ACCEPT THIS IN UNICODE. JRA. */
8535 /* Job number */
8536 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8538 srvstr_push(pdata, req->flags2, pdata + 2,
8539 lp_netbios_name(), 15,
8540 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8541 srvstr_push(pdata, req->flags2, pdata+18,
8542 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8543 STR_ASCII|STR_TERMINATE); /* Service name */
8544 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8545 max_data_bytes);
8546 return;
8549 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8550 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8553 /****************************************************************************
8554 Reply to a SMBfindclose (stop trans2 directory search).
8555 ****************************************************************************/
8557 void reply_findclose(struct smb_request *req)
8559 int dptr_num;
8560 struct smbd_server_connection *sconn = req->sconn;
8562 START_PROFILE(SMBfindclose);
8564 if (req->wct < 1) {
8565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8566 END_PROFILE(SMBfindclose);
8567 return;
8570 dptr_num = SVALS(req->vwv+0, 0);
8572 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8574 dptr_close(sconn, &dptr_num);
8576 reply_outbuf(req, 0, 0);
8578 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8580 END_PROFILE(SMBfindclose);
8581 return;
8584 /****************************************************************************
8585 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8586 ****************************************************************************/
8588 void reply_findnclose(struct smb_request *req)
8590 int dptr_num;
8592 START_PROFILE(SMBfindnclose);
8594 if (req->wct < 1) {
8595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8596 END_PROFILE(SMBfindnclose);
8597 return;
8600 dptr_num = SVAL(req->vwv+0, 0);
8602 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8604 /* We never give out valid handles for a
8605 findnotifyfirst - so any dptr_num is ok here.
8606 Just ignore it. */
8608 reply_outbuf(req, 0, 0);
8610 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8612 END_PROFILE(SMBfindnclose);
8613 return;
8616 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8617 struct trans_state *state)
8619 if (get_Protocol() >= PROTOCOL_NT1) {
8620 req->flags2 |= 0x40; /* IS_LONG_NAME */
8621 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8624 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8625 if (state->call != TRANSACT2_QFSINFO &&
8626 state->call != TRANSACT2_SETFSINFO) {
8627 DEBUG(0,("handle_trans2: encryption required "
8628 "with call 0x%x\n",
8629 (unsigned int)state->call));
8630 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8631 return;
8635 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8637 /* Now we must call the relevant TRANS2 function */
8638 switch(state->call) {
8639 case TRANSACT2_OPEN:
8641 START_PROFILE(Trans2_open);
8642 call_trans2open(conn, req,
8643 &state->param, state->total_param,
8644 &state->data, state->total_data,
8645 state->max_data_return);
8646 END_PROFILE(Trans2_open);
8647 break;
8650 case TRANSACT2_FINDFIRST:
8652 START_PROFILE(Trans2_findfirst);
8653 call_trans2findfirst(conn, req,
8654 &state->param, state->total_param,
8655 &state->data, state->total_data,
8656 state->max_data_return);
8657 END_PROFILE(Trans2_findfirst);
8658 break;
8661 case TRANSACT2_FINDNEXT:
8663 START_PROFILE(Trans2_findnext);
8664 call_trans2findnext(conn, req,
8665 &state->param, state->total_param,
8666 &state->data, state->total_data,
8667 state->max_data_return);
8668 END_PROFILE(Trans2_findnext);
8669 break;
8672 case TRANSACT2_QFSINFO:
8674 START_PROFILE(Trans2_qfsinfo);
8675 call_trans2qfsinfo(conn, req,
8676 &state->param, state->total_param,
8677 &state->data, state->total_data,
8678 state->max_data_return);
8679 END_PROFILE(Trans2_qfsinfo);
8680 break;
8683 case TRANSACT2_SETFSINFO:
8685 START_PROFILE(Trans2_setfsinfo);
8686 call_trans2setfsinfo(conn, req,
8687 &state->param, state->total_param,
8688 &state->data, state->total_data,
8689 state->max_data_return);
8690 END_PROFILE(Trans2_setfsinfo);
8691 break;
8694 case TRANSACT2_QPATHINFO:
8695 case TRANSACT2_QFILEINFO:
8697 START_PROFILE(Trans2_qpathinfo);
8698 call_trans2qfilepathinfo(conn, req, state->call,
8699 &state->param, state->total_param,
8700 &state->data, state->total_data,
8701 state->max_data_return);
8702 END_PROFILE(Trans2_qpathinfo);
8703 break;
8706 case TRANSACT2_SETPATHINFO:
8707 case TRANSACT2_SETFILEINFO:
8709 START_PROFILE(Trans2_setpathinfo);
8710 call_trans2setfilepathinfo(conn, req, state->call,
8711 &state->param, state->total_param,
8712 &state->data, state->total_data,
8713 state->max_data_return);
8714 END_PROFILE(Trans2_setpathinfo);
8715 break;
8718 case TRANSACT2_FINDNOTIFYFIRST:
8720 START_PROFILE(Trans2_findnotifyfirst);
8721 call_trans2findnotifyfirst(conn, req,
8722 &state->param, state->total_param,
8723 &state->data, state->total_data,
8724 state->max_data_return);
8725 END_PROFILE(Trans2_findnotifyfirst);
8726 break;
8729 case TRANSACT2_FINDNOTIFYNEXT:
8731 START_PROFILE(Trans2_findnotifynext);
8732 call_trans2findnotifynext(conn, req,
8733 &state->param, state->total_param,
8734 &state->data, state->total_data,
8735 state->max_data_return);
8736 END_PROFILE(Trans2_findnotifynext);
8737 break;
8740 case TRANSACT2_MKDIR:
8742 START_PROFILE(Trans2_mkdir);
8743 call_trans2mkdir(conn, req,
8744 &state->param, state->total_param,
8745 &state->data, state->total_data,
8746 state->max_data_return);
8747 END_PROFILE(Trans2_mkdir);
8748 break;
8751 case TRANSACT2_GET_DFS_REFERRAL:
8753 START_PROFILE(Trans2_get_dfs_referral);
8754 call_trans2getdfsreferral(conn, req,
8755 &state->param, state->total_param,
8756 &state->data, state->total_data,
8757 state->max_data_return);
8758 END_PROFILE(Trans2_get_dfs_referral);
8759 break;
8762 case TRANSACT2_IOCTL:
8764 START_PROFILE(Trans2_ioctl);
8765 call_trans2ioctl(conn, req,
8766 &state->param, state->total_param,
8767 &state->data, state->total_data,
8768 state->max_data_return);
8769 END_PROFILE(Trans2_ioctl);
8770 break;
8773 default:
8774 /* Error in request */
8775 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8776 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8780 /****************************************************************************
8781 Reply to a SMBtrans2.
8782 ****************************************************************************/
8784 void reply_trans2(struct smb_request *req)
8786 connection_struct *conn = req->conn;
8787 unsigned int dsoff;
8788 unsigned int dscnt;
8789 unsigned int psoff;
8790 unsigned int pscnt;
8791 unsigned int tran_call;
8792 struct trans_state *state;
8793 NTSTATUS result;
8795 START_PROFILE(SMBtrans2);
8797 if (req->wct < 14) {
8798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8799 END_PROFILE(SMBtrans2);
8800 return;
8803 dsoff = SVAL(req->vwv+12, 0);
8804 dscnt = SVAL(req->vwv+11, 0);
8805 psoff = SVAL(req->vwv+10, 0);
8806 pscnt = SVAL(req->vwv+9, 0);
8807 tran_call = SVAL(req->vwv+14, 0);
8809 result = allow_new_trans(conn->pending_trans, req->mid);
8810 if (!NT_STATUS_IS_OK(result)) {
8811 DEBUG(2, ("Got invalid trans2 request: %s\n",
8812 nt_errstr(result)));
8813 reply_nterror(req, result);
8814 END_PROFILE(SMBtrans2);
8815 return;
8818 if (IS_IPC(conn)) {
8819 switch (tran_call) {
8820 /* List the allowed trans2 calls on IPC$ */
8821 case TRANSACT2_OPEN:
8822 case TRANSACT2_GET_DFS_REFERRAL:
8823 case TRANSACT2_QFILEINFO:
8824 case TRANSACT2_QFSINFO:
8825 case TRANSACT2_SETFSINFO:
8826 break;
8827 default:
8828 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8829 END_PROFILE(SMBtrans2);
8830 return;
8834 if ((state = talloc(conn, struct trans_state)) == NULL) {
8835 DEBUG(0, ("talloc failed\n"));
8836 reply_nterror(req, NT_STATUS_NO_MEMORY);
8837 END_PROFILE(SMBtrans2);
8838 return;
8841 state->cmd = SMBtrans2;
8843 state->mid = req->mid;
8844 state->vuid = req->vuid;
8845 state->setup_count = SVAL(req->vwv+13, 0);
8846 state->setup = NULL;
8847 state->total_param = SVAL(req->vwv+0, 0);
8848 state->param = NULL;
8849 state->total_data = SVAL(req->vwv+1, 0);
8850 state->data = NULL;
8851 state->max_param_return = SVAL(req->vwv+2, 0);
8852 state->max_data_return = SVAL(req->vwv+3, 0);
8853 state->max_setup_return = SVAL(req->vwv+4, 0);
8854 state->close_on_completion = BITSETW(req->vwv+5, 0);
8855 state->one_way = BITSETW(req->vwv+5, 1);
8857 state->call = tran_call;
8859 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8860 is so as a sanity check */
8861 if (state->setup_count != 1) {
8863 * Need to have rc=0 for ioctl to get job id for OS/2.
8864 * Network printing will fail if function is not successful.
8865 * Similar function in reply.c will be used if protocol
8866 * is LANMAN1.0 instead of LM1.2X002.
8867 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8868 * outbuf doesn't have to be set(only job id is used).
8870 if ( (state->setup_count == 4)
8871 && (tran_call == TRANSACT2_IOCTL)
8872 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8873 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8874 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8875 } else {
8876 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8877 DEBUG(2,("Transaction is %d\n",tran_call));
8878 TALLOC_FREE(state);
8879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8880 END_PROFILE(SMBtrans2);
8881 return;
8885 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8886 goto bad_param;
8888 if (state->total_data) {
8890 if (trans_oob(state->total_data, 0, dscnt)
8891 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8892 goto bad_param;
8895 /* Can't use talloc here, the core routines do realloc on the
8896 * params and data. */
8897 state->data = (char *)SMB_MALLOC(state->total_data);
8898 if (state->data == NULL) {
8899 DEBUG(0,("reply_trans2: data malloc fail for %u "
8900 "bytes !\n", (unsigned int)state->total_data));
8901 TALLOC_FREE(state);
8902 reply_nterror(req, NT_STATUS_NO_MEMORY);
8903 END_PROFILE(SMBtrans2);
8904 return;
8907 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8910 if (state->total_param) {
8912 if (trans_oob(state->total_param, 0, pscnt)
8913 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8914 goto bad_param;
8917 /* Can't use talloc here, the core routines do realloc on the
8918 * params and data. */
8919 state->param = (char *)SMB_MALLOC(state->total_param);
8920 if (state->param == NULL) {
8921 DEBUG(0,("reply_trans: param malloc fail for %u "
8922 "bytes !\n", (unsigned int)state->total_param));
8923 SAFE_FREE(state->data);
8924 TALLOC_FREE(state);
8925 reply_nterror(req, NT_STATUS_NO_MEMORY);
8926 END_PROFILE(SMBtrans2);
8927 return;
8930 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8933 state->received_data = dscnt;
8934 state->received_param = pscnt;
8936 if ((state->received_param == state->total_param) &&
8937 (state->received_data == state->total_data)) {
8939 handle_trans2(conn, req, state);
8941 SAFE_FREE(state->data);
8942 SAFE_FREE(state->param);
8943 TALLOC_FREE(state);
8944 END_PROFILE(SMBtrans2);
8945 return;
8948 DLIST_ADD(conn->pending_trans, state);
8950 /* We need to send an interim response then receive the rest
8951 of the parameter/data bytes */
8952 reply_outbuf(req, 0, 0);
8953 show_msg((char *)req->outbuf);
8954 END_PROFILE(SMBtrans2);
8955 return;
8957 bad_param:
8959 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8960 SAFE_FREE(state->data);
8961 SAFE_FREE(state->param);
8962 TALLOC_FREE(state);
8963 END_PROFILE(SMBtrans2);
8964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8968 /****************************************************************************
8969 Reply to a SMBtranss2
8970 ****************************************************************************/
8972 void reply_transs2(struct smb_request *req)
8974 connection_struct *conn = req->conn;
8975 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8976 struct trans_state *state;
8978 START_PROFILE(SMBtranss2);
8980 show_msg((const char *)req->inbuf);
8982 /* Windows clients expect all replies to
8983 a transact secondary (SMBtranss2 0x33)
8984 to have a command code of transact
8985 (SMBtrans2 0x32). See bug #8989
8986 and also [MS-CIFS] section 2.2.4.47.2
8987 for details.
8989 req->cmd = SMBtrans2;
8991 if (req->wct < 8) {
8992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8993 END_PROFILE(SMBtranss2);
8994 return;
8997 for (state = conn->pending_trans; state != NULL;
8998 state = state->next) {
8999 if (state->mid == req->mid) {
9000 break;
9004 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9006 END_PROFILE(SMBtranss2);
9007 return;
9010 /* Revise state->total_param and state->total_data in case they have
9011 changed downwards */
9013 if (SVAL(req->vwv+0, 0) < state->total_param)
9014 state->total_param = SVAL(req->vwv+0, 0);
9015 if (SVAL(req->vwv+1, 0) < state->total_data)
9016 state->total_data = SVAL(req->vwv+1, 0);
9018 pcnt = SVAL(req->vwv+2, 0);
9019 poff = SVAL(req->vwv+3, 0);
9020 pdisp = SVAL(req->vwv+4, 0);
9022 dcnt = SVAL(req->vwv+5, 0);
9023 doff = SVAL(req->vwv+6, 0);
9024 ddisp = SVAL(req->vwv+7, 0);
9026 state->received_param += pcnt;
9027 state->received_data += dcnt;
9029 if ((state->received_data > state->total_data) ||
9030 (state->received_param > state->total_param))
9031 goto bad_param;
9033 if (pcnt) {
9034 if (trans_oob(state->total_param, pdisp, pcnt)
9035 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9036 goto bad_param;
9038 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9041 if (dcnt) {
9042 if (trans_oob(state->total_data, ddisp, dcnt)
9043 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9044 goto bad_param;
9046 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9049 if ((state->received_param < state->total_param) ||
9050 (state->received_data < state->total_data)) {
9051 END_PROFILE(SMBtranss2);
9052 return;
9055 handle_trans2(conn, req, state);
9057 DLIST_REMOVE(conn->pending_trans, state);
9058 SAFE_FREE(state->data);
9059 SAFE_FREE(state->param);
9060 TALLOC_FREE(state);
9062 END_PROFILE(SMBtranss2);
9063 return;
9065 bad_param:
9067 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9068 DLIST_REMOVE(conn->pending_trans, state);
9069 SAFE_FREE(state->data);
9070 SAFE_FREE(state->param);
9071 TALLOC_FREE(state);
9072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9073 END_PROFILE(SMBtranss2);
9074 return;