smbd: Correctly return INFO_LENGTH_MISMATCH for smb1
[Samba.git] / source3 / smbd / trans2.c
blobaaf0e6228968aea5c1287f130bee2cce1d5010c3
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 "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
882 uint8_t eclass;
883 uint32_t ecode;
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
887 __LINE__,__FILE__);
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
891 (char *)req->outbuf,
892 true, req->seqnum+1,
893 IS_CONN_ENCRYPTED(conn),
894 &req->pcd)) {
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
898 return;
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
913 + 2 * 10 /* wct */
914 + alignment_offset
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
966 else
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
974 } else {
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1014 if (overflow) {
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1018 __LINE__,__FILE__);
1019 } else if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1034 &req->pcd))
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1045 /* Sanity check */
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1049 return;
1053 return;
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1069 int deny_mode;
1070 int32 open_attr;
1071 bool oplock_request;
1072 #if 0
1073 bool return_additional_info;
1074 int16 open_sattr;
1075 time_t open_time;
1076 #endif
1077 int open_ofun;
1078 uint32 open_size;
1079 char *pname;
1080 char *fname = NULL;
1081 off_t size=0;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1084 int smb_action = 0;
1085 files_struct *fsp;
1086 struct ea_list *ea_list = NULL;
1087 uint16 flags = 0;
1088 NTSTATUS status;
1089 uint32 access_mask;
1090 uint32 share_mode;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 goto out;
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1113 #if 0
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1117 #endif
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = &params[28];
1122 if (IS_IPC(conn)) {
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1124 goto out;
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1129 &status);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1132 goto out;
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1159 goto out;
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1163 open_ofun,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1166 &create_options,
1167 &private_flags)) {
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1169 goto out;
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 goto out;
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 goto out;
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1187 total_data - 4);
1188 if (!ea_list) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1195 goto out;
1198 if (ea_list_has_invalid_name(ea_list)) {
1199 int param_len = 30;
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1203 goto out;
1205 params = *pparams;
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1209 goto out;
1213 status = SMB_VFS_CREATE_FILE(
1214 conn, /* conn */
1215 req, /* req */
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1225 private_flags,
1226 NULL, /* sd */
1227 ea_list, /* ea_list */
1228 &fsp, /* result */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1234 goto out;
1236 reply_openerror(req, status);
1237 goto out;
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 goto out;
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1254 goto out;
1256 params = *pparams;
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1277 if (flags & 8) {
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1279 smb_fname);
1280 SIVAL(params, 26, ea_size);
1281 } else {
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1287 out:
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1300 const char *str,
1301 const char *mask)
1303 if (mask[0] == '.' && mask[1] == 0) {
1304 return false;
1307 if (has_wild) {
1308 return false;
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1313 } else {
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1324 if(S_ISREG(mode))
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1328 #ifdef S_ISLNK
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1331 #endif
1332 #ifdef S_ISCHR
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1335 #endif
1336 #ifdef S_ISBLK
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1339 #endif
1340 #ifdef S_ISFIFO
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1343 #endif
1344 #ifdef S_ISSOCK
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1347 #endif
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1361 uint32 perms,
1362 enum perm_type ptype,
1363 mode_t *ret_perms)
1365 mode_t ret = 0;
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1370 } else {
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1385 #ifdef S_ISVTX
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1387 #endif
1388 #ifdef S_ISGID
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1390 #endif
1391 #ifdef S_ISUID
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1393 #endif
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1413 *ret_perms = ret;
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 "as a directory\n",
1433 pathname));
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1436 return true;
1438 errno = saved_errno;
1439 return false;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1451 bool has_wild;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1456 void *private_data,
1457 const char *dname,
1458 const char *mask,
1459 char **_fname)
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1463 bool ok;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1465 bool got_match;
1466 const char *fname;
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1472 if (!ok) {
1473 return false;
1475 fname = mangled_name;
1476 } else {
1477 fname = dname;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1482 fname, mask);
1483 state->got_exact_match = got_match;
1484 if (!got_match) {
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1500 if (!ok) {
1501 return false;
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1508 if (!got_match) {
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1514 if (!got_match) {
1515 return false;
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1520 return false;
1523 return true;
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1527 void *private_data,
1528 struct smb_filename *smb_fname,
1529 uint32_t *_mode)
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1534 uint32_t mode = 0;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1541 strerror(errno)));
1542 return false;
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1547 * directories */
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1551 &smb_fname->st);
1552 if (!ms_dfs_link) {
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1556 strerror(errno)));
1557 return false;
1561 if (ms_dfs_link) {
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1563 } else {
1564 mode = dos_mode(state->conn, smb_fname);
1567 *_mode = mode;
1568 return true;
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1573 uint16_t flags2,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1578 uint32_t mode,
1579 const char *fname,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1582 uint8_t align,
1583 bool do_pad,
1584 char *base_data,
1585 char **ppdata,
1586 char *end_data,
1587 bool *out_of_space,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1591 uint32_t reskey=0;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1595 uint32_t len;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1598 char *nameptr;
1599 char *last_entry_ptr;
1600 bool was_8_3;
1601 int off;
1602 int pad = 0;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1639 pad -= off;
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1645 (unsigned int)pad,
1646 space_remaining ));
1647 return false; /* Not finished - just out of space */
1650 off += pad;
1651 /* initialize padding to 0 */
1652 if (pad) {
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1658 space_remaining ));
1660 pdata += pad;
1661 p = pdata;
1662 last_entry_ptr = p;
1664 pad = 0;
1665 off = 0;
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 23;
1681 nameptr = p;
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE);
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1689 if (len > 2) {
1690 SCVAL(nameptr, -1, len - 2);
1691 } else {
1692 SCVAL(nameptr, -1, 0);
1694 } else {
1695 if (len > 1) {
1696 SCVAL(nameptr, -1, len - 1);
1697 } else {
1698 SCVAL(nameptr, -1, 0);
1701 p += len;
1702 break;
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key) {
1707 SIVAL(p,0,reskey);
1708 p += 4;
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1715 SSVAL(p,20,mode);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1718 smb_fname);
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1721 p += 27;
1722 nameptr = p - 1;
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1747 size_t ea_len = 0;
1748 NTSTATUS status;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1751 if (!name_list) {
1752 return false;
1754 if (requires_resume_key) {
1755 SIVAL(p,0,reskey);
1756 p += 4;
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1763 SSVAL(p,20,mode);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1767 smb_fname,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 file_list = NULL;
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1781 space_remaining ));
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1787 nameptr = p;
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1792 if (len > 2) {
1793 len -= 2;
1794 } else {
1795 len = 0;
1797 } else {
1798 if (len > 1) {
1799 len -= 1;
1800 } else {
1801 len = 0;
1804 SCVAL(nameptr,0,len);
1805 p += len + 1;
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1807 break;
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1813 p += 4;
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1825 } else {
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1830 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. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2004 } else {
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2006 smb_fname);
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2009 p += 4;
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2015 SIVAL(q, 0, len);
2016 p += len;
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2025 SIVAL(pdata,0,pad);
2027 * set padding to zero
2029 if (do_pad) {
2030 memset(p, 0, pad - len);
2031 p = pdata + pad;
2032 } else {
2033 p = pdata + len;
2035 break;
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2040 p += 4;
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2052 } else {
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2054 smb_fname);
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2057 p += 4;
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2065 conn->params)) {
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2073 SSVAL(p, 0, len);
2074 if (len < 24) {
2075 memset(p + 2 + len,'\0',24 - len);
2077 SSVAL(p, 0, len);
2078 } else {
2079 memset(p,'\0',26);
2081 p += 26;
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
2087 SIVAL(q,0,len);
2088 p += len;
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2097 SIVAL(pdata,0,pad);
2099 * set padding to zero
2101 if (do_pad) {
2102 memset(p, 0, pad - len);
2103 p = pdata + pad;
2104 } else {
2105 p = pdata + len;
2107 break;
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2113 p+= 4;
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2124 STR_TERMINATE);
2125 } else {
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2129 nameptr = p;
2130 p += 4;
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2136 p += len;
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2145 SIVAL(pdata,0,pad);
2147 * set padding to zero
2149 if (do_pad) {
2150 memset(p, 0, pad - len);
2151 p = pdata + pad;
2152 } else {
2153 p = pdata + len;
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2157 break;
2159 default:
2160 return false;
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2168 space_remaining ));
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2175 *ppdata = p;
2177 return true;
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 int requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 uint8_t align,
2191 bool do_pad,
2192 char **ppdata,
2193 char *base_data,
2194 char *end_data,
2195 int space_remaining,
2196 bool *out_of_space,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2201 const char *p;
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2204 uint32_t mode = 0;
2205 char *fname = NULL;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2208 bool ok;
2209 uint64_t last_entry_off = 0;
2211 ZERO_STRUCT(state);
2212 state.conn = conn;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2222 if(p != NULL) {
2223 if(p[1] == '\0') {
2224 mask = "*.*";
2225 } else {
2226 mask = p+1;
2228 } else {
2229 mask = path_mask;
2232 ok = smbd_dirptr_get_entry(ctx,
2233 dirptr,
2234 mask,
2235 dirtype,
2236 dont_descend,
2237 ask_sharemode,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2240 &state,
2241 &fname,
2242 &smb_fname,
2243 &mode,
2244 &prev_dirpos);
2245 if (!ok) {
2246 return false;
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2252 conn,
2253 flags2,
2254 info_level,
2255 name_list,
2256 state.check_mangled_names,
2257 requires_resume_key,
2258 mode,
2259 fname,
2260 smb_fname,
2261 space_remaining,
2262 align,
2263 do_pad,
2264 base_data,
2265 ppdata,
2266 end_data,
2267 out_of_space,
2268 &last_entry_off);
2269 TALLOC_FREE(fname);
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2273 return false;
2275 if (!ok) {
2276 return false;
2279 *_last_entry_off = last_entry_off;
2280 return true;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2286 uint16 flags2,
2287 const char *path_mask,
2288 uint32 dirtype,
2289 int info_level,
2290 bool requires_resume_key,
2291 bool dont_descend,
2292 bool ask_sharemode,
2293 char **ppdata,
2294 char *base_data,
2295 char *end_data,
2296 int space_remaining,
2297 bool *out_of_space,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2302 uint8_t align = 4;
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2307 align = 1;
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2313 align, do_pad,
2314 ppdata, base_data, end_data,
2315 space_remaining,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2334 requested. */
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2338 char *data_end;
2339 uint32 dirtype;
2340 int maxentries;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2343 bool close_if_end;
2344 bool requires_resume_key;
2345 int info_level;
2346 char *directory = NULL;
2347 char *mask = NULL;
2348 char *p;
2349 int last_entry_off=0;
2350 int dptr_num = -1;
2351 int numentries = 0;
2352 int i;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2367 if (total_params < 13) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2372 dirtype = SVAL(params,0);
2373 maxentries = SVAL(params,2);
2374 findfirst_flags = SVAL(params,4);
2375 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2376 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2377 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2378 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2379 security_token_has_privilege(get_current_nttok(conn),
2380 SEC_PRIV_BACKUP));
2382 info_level = SVAL(params,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2387 (int)backup_priv,
2388 info_level, max_data_bytes));
2390 if (!maxentries) {
2391 /* W2K3 seems to treat zero as 1. */
2392 maxentries = 1;
2395 switch (info_level) {
2396 case SMB_FIND_INFO_STANDARD:
2397 case SMB_FIND_EA_SIZE:
2398 case SMB_FIND_EA_LIST:
2399 case SMB_FIND_FILE_DIRECTORY_INFO:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_NAMES_INFO:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2405 break;
2406 case SMB_FIND_FILE_UNIX:
2407 case SMB_FIND_FILE_UNIX_INFO2:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode = false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 goto out;
2414 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 break;
2416 default:
2417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2418 goto out;
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2422 params+12, total_params - 12,
2423 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2424 if (!NT_STATUS_IS_OK(ntstatus)) {
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 if (backup_priv) {
2430 become_root();
2431 ntstatus = filename_convert_with_privilege(ctx,
2432 conn,
2433 req,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2438 } else {
2439 ntstatus = filename_convert(ctx, conn,
2440 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 directory,
2442 ucf_flags,
2443 &mask_contains_wcard,
2444 &smb_dname);
2447 if (!NT_STATUS_IS_OK(ntstatus)) {
2448 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2450 ERRSRV, ERRbadpath);
2451 goto out;
2453 reply_nterror(req, ntstatus);
2454 goto out;
2457 mask = smb_dname->original_lcomp;
2459 directory = smb_dname->base_name;
2461 p = strrchr_m(directory,'/');
2462 if(p == NULL) {
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory[0] == '.') && (directory[1] == '\0')) {
2465 mask = talloc_strdup(ctx,"*");
2466 if (!mask) {
2467 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 goto out;
2470 mask_contains_wcard = True;
2472 } else {
2473 *p = 0;
2476 if (p == NULL || p == directory) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory = talloc_strdup(talloc_tos(), ".");
2479 if (!directory) {
2480 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 goto out;
2485 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2487 if (info_level == SMB_FIND_EA_LIST) {
2488 uint32 ea_size;
2490 if (total_data < 4) {
2491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2492 goto out;
2495 ea_size = IVAL(pdata,0);
2496 if (ea_size != total_data) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 goto out;
2503 if (!lp_ea_support(SNUM(conn))) {
2504 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2505 goto out;
2508 /* Pull out the list of names. */
2509 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2510 if (!ea_list) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2516 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2518 goto out;
2521 *ppdata = (char *)SMB_REALLOC(
2522 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2523 if(*ppdata == NULL ) {
2524 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 goto out;
2527 pdata = *ppdata;
2528 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2530 /* Realloc the params space */
2531 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2532 if (*pparams == NULL) {
2533 reply_nterror(req, NT_STATUS_NO_MEMORY);
2534 goto out;
2536 params = *pparams;
2538 /* Save the wildcard match and attribs we are using on this directory -
2539 needed as lanman2 assumes these are being saved between calls */
2541 ntstatus = dptr_create(conn,
2542 req,
2543 NULL, /* fsp */
2544 directory,
2545 False,
2546 True,
2547 req->smbpid,
2548 mask,
2549 mask_contains_wcard,
2550 dirtype,
2551 &dirptr);
2553 if (!NT_STATUS_IS_OK(ntstatus)) {
2554 reply_nterror(req, ntstatus);
2555 goto out;
2558 if (backup_priv) {
2559 /* Remember this in case we have
2560 to do a findnext. */
2561 dptr_set_priv(dirptr);
2564 dptr_num = dptr_dnum(dirptr);
2565 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2567 /* Initialize per TRANS2_FIND_FIRST operation data */
2568 dptr_init_search_op(dirptr);
2570 /* We don't need to check for VOL here as this is returned by
2571 a different TRANS2 call. */
2573 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2574 directory,lp_dontdescend(ctx, SNUM(conn))));
2575 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2576 dont_descend = True;
2578 p = pdata;
2579 space_remaining = max_data_bytes;
2580 out_of_space = False;
2582 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2583 bool got_exact_match = False;
2585 /* this is a heuristic to avoid seeking the dirptr except when
2586 absolutely necessary. It allows for a filename of about 40 chars */
2587 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2588 out_of_space = True;
2589 finished = False;
2590 } else {
2591 finished = !get_lanman2_dir_entry(ctx,
2592 conn,
2593 dirptr,
2594 req->flags2,
2595 mask,dirtype,info_level,
2596 requires_resume_key,dont_descend,
2597 ask_sharemode,
2598 &p,pdata,data_end,
2599 space_remaining, &out_of_space,
2600 &got_exact_match,
2601 &last_entry_off, ea_list);
2604 if (finished && out_of_space)
2605 finished = False;
2607 if (!finished && !out_of_space)
2608 numentries++;
2611 * As an optimisation if we know we aren't looking
2612 * for a wildcard name (ie. the name matches the wildcard exactly)
2613 * then we can finish on any (first) match.
2614 * This speeds up large directory searches. JRA.
2617 if(got_exact_match)
2618 finished = True;
2620 /* Ensure space_remaining never goes -ve. */
2621 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2622 space_remaining = 0;
2623 out_of_space = true;
2624 } else {
2625 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2629 /* Check if we can close the dirptr */
2630 if(close_after_first || (finished && close_if_end)) {
2631 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2632 dptr_close(sconn, &dptr_num);
2636 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2637 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2638 * the protocol level is less than NT1. Tested with smbclient. JRA.
2639 * This should fix the OS/2 client bug #2335.
2642 if(numentries == 0) {
2643 dptr_close(sconn, &dptr_num);
2644 if (get_Protocol() < PROTOCOL_NT1) {
2645 reply_force_doserror(req, ERRDOS, ERRnofiles);
2646 goto out;
2647 } else {
2648 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2649 ERRDOS, ERRbadfile);
2650 goto out;
2654 /* At this point pdata points to numentries directory entries. */
2656 /* Set up the return parameter block */
2657 SSVAL(params,0,dptr_num);
2658 SSVAL(params,2,numentries);
2659 SSVAL(params,4,finished);
2660 SSVAL(params,6,0); /* Never an EA error */
2661 SSVAL(params,8,last_entry_off);
2663 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2664 max_data_bytes);
2666 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2667 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2668 if (!directory) {
2669 reply_nterror(req, NT_STATUS_NO_MEMORY);
2673 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2674 smb_fn_name(req->cmd),
2675 mask, directory, dirtype, numentries ) );
2678 * Force a name mangle here to ensure that the
2679 * mask as an 8.3 name is top of the mangled cache.
2680 * The reasons for this are subtle. Don't remove
2681 * this code unless you know what you are doing
2682 * (see PR#13758). JRA.
2685 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2686 char mangled_name[13];
2687 name_to_8_3(mask, mangled_name, True, conn->params);
2689 out:
2691 if (backup_priv) {
2692 unbecome_root();
2695 TALLOC_FREE(smb_dname);
2696 return;
2699 /****************************************************************************
2700 Reply to a TRANS2_FINDNEXT.
2701 ****************************************************************************/
2703 static void call_trans2findnext(connection_struct *conn,
2704 struct smb_request *req,
2705 char **pparams, int total_params,
2706 char **ppdata, int total_data,
2707 unsigned int max_data_bytes)
2709 /* We must be careful here that we don't return more than the
2710 allowed number of data bytes. If this means returning fewer than
2711 maxentries then so be it. We assume that the redirector has
2712 enough room for the fixed number of parameter bytes it has
2713 requested. */
2714 char *params = *pparams;
2715 char *pdata = *ppdata;
2716 char *data_end;
2717 int dptr_num;
2718 int maxentries;
2719 uint16 info_level;
2720 uint32 resume_key;
2721 uint16 findnext_flags;
2722 bool close_after_request;
2723 bool close_if_end;
2724 bool requires_resume_key;
2725 bool continue_bit;
2726 bool mask_contains_wcard = False;
2727 char *resume_name = NULL;
2728 const char *mask = NULL;
2729 const char *directory = NULL;
2730 char *p = NULL;
2731 uint16 dirtype;
2732 int numentries = 0;
2733 int i, last_entry_off=0;
2734 bool finished = False;
2735 bool dont_descend = False;
2736 bool out_of_space = False;
2737 int space_remaining;
2738 struct ea_list *ea_list = NULL;
2739 NTSTATUS ntstatus = NT_STATUS_OK;
2740 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2741 TALLOC_CTX *ctx = talloc_tos();
2742 struct dptr_struct *dirptr;
2743 struct smbd_server_connection *sconn = req->sconn;
2744 bool backup_priv = false;
2746 if (total_params < 13) {
2747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2748 return;
2751 dptr_num = SVAL(params,0);
2752 maxentries = SVAL(params,2);
2753 info_level = SVAL(params,4);
2754 resume_key = IVAL(params,6);
2755 findnext_flags = SVAL(params,10);
2756 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2757 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2758 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2759 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2761 if (!continue_bit) {
2762 /* We only need resume_name if continue_bit is zero. */
2763 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2764 params+12,
2765 total_params - 12, STR_TERMINATE, &ntstatus,
2766 &mask_contains_wcard);
2767 if (!NT_STATUS_IS_OK(ntstatus)) {
2768 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2769 complain (it thinks we're asking for the directory above the shared
2770 path or an invalid name). Catch this as the resume name is only compared, never used in
2771 a file access. JRA. */
2772 srvstr_pull_talloc(ctx, params, req->flags2,
2773 &resume_name, params+12,
2774 total_params - 12,
2775 STR_TERMINATE);
2777 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2778 reply_nterror(req, ntstatus);
2779 return;
2784 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2785 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2786 resume_key = %d resume name = %s continue=%d level = %d\n",
2787 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2788 requires_resume_key, resume_key,
2789 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2791 if (!maxentries) {
2792 /* W2K3 seems to treat zero as 1. */
2793 maxentries = 1;
2796 switch (info_level) {
2797 case SMB_FIND_INFO_STANDARD:
2798 case SMB_FIND_EA_SIZE:
2799 case SMB_FIND_EA_LIST:
2800 case SMB_FIND_FILE_DIRECTORY_INFO:
2801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2802 case SMB_FIND_FILE_NAMES_INFO:
2803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2804 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2806 break;
2807 case SMB_FIND_FILE_UNIX:
2808 case SMB_FIND_FILE_UNIX_INFO2:
2809 /* Always use filesystem for UNIX mtime query. */
2810 ask_sharemode = false;
2811 if (!lp_unix_extensions()) {
2812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 return;
2815 break;
2816 default:
2817 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2818 return;
2821 if (info_level == SMB_FIND_EA_LIST) {
2822 uint32 ea_size;
2824 if (total_data < 4) {
2825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2826 return;
2829 ea_size = IVAL(pdata,0);
2830 if (ea_size != total_data) {
2831 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2832 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2834 return;
2837 if (!lp_ea_support(SNUM(conn))) {
2838 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2839 return;
2842 /* Pull out the list of names. */
2843 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2844 if (!ea_list) {
2845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2846 return;
2850 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2852 return;
2855 *ppdata = (char *)SMB_REALLOC(
2856 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2857 if(*ppdata == NULL) {
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 return;
2862 pdata = *ppdata;
2863 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2865 /* Realloc the params space */
2866 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2867 if(*pparams == NULL ) {
2868 reply_nterror(req, NT_STATUS_NO_MEMORY);
2869 return;
2872 params = *pparams;
2874 /* Check that the dptr is valid */
2875 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2876 reply_nterror(req, STATUS_NO_MORE_FILES);
2877 return;
2880 directory = dptr_path(sconn, dptr_num);
2882 /* Get the wildcard mask from the dptr */
2883 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2884 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2885 reply_nterror(req, STATUS_NO_MORE_FILES);
2886 return;
2889 /* Get the attr mask from the dptr */
2890 dirtype = dptr_attr(sconn, dptr_num);
2892 backup_priv = dptr_get_priv(dirptr);
2894 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2895 "backup_priv = %d\n",
2896 dptr_num, mask, dirtype,
2897 (long)dirptr,
2898 dptr_TellDir(dirptr),
2899 (int)backup_priv));
2901 /* Initialize per TRANS2_FIND_NEXT operation data */
2902 dptr_init_search_op(dirptr);
2904 /* We don't need to check for VOL here as this is returned by
2905 a different TRANS2 call. */
2907 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2908 directory,lp_dontdescend(ctx, SNUM(conn))));
2909 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2910 dont_descend = True;
2912 p = pdata;
2913 space_remaining = max_data_bytes;
2914 out_of_space = False;
2916 if (backup_priv) {
2917 become_root();
2921 * Seek to the correct position. We no longer use the resume key but
2922 * depend on the last file name instead.
2925 if(!continue_bit && resume_name && *resume_name) {
2926 SMB_STRUCT_STAT st;
2928 long current_pos = 0;
2930 * Remember, name_to_8_3 is called by
2931 * get_lanman2_dir_entry(), so the resume name
2932 * could be mangled. Ensure we check the unmangled name.
2935 if (mangle_is_mangled(resume_name, conn->params)) {
2936 char *new_resume_name = NULL;
2937 mangle_lookup_name_from_8_3(ctx,
2938 resume_name,
2939 &new_resume_name,
2940 conn->params);
2941 if (new_resume_name) {
2942 resume_name = new_resume_name;
2947 * Fix for NT redirector problem triggered by resume key indexes
2948 * changing between directory scans. We now return a resume key of 0
2949 * and instead look for the filename to continue from (also given
2950 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2951 * findfirst/findnext (as is usual) then the directory pointer
2952 * should already be at the correct place.
2955 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2956 } /* end if resume_name && !continue_bit */
2958 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2959 bool got_exact_match = False;
2961 /* this is a heuristic to avoid seeking the dirptr except when
2962 absolutely necessary. It allows for a filename of about 40 chars */
2963 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2964 out_of_space = True;
2965 finished = False;
2966 } else {
2967 finished = !get_lanman2_dir_entry(ctx,
2968 conn,
2969 dirptr,
2970 req->flags2,
2971 mask,dirtype,info_level,
2972 requires_resume_key,dont_descend,
2973 ask_sharemode,
2974 &p,pdata,data_end,
2975 space_remaining, &out_of_space,
2976 &got_exact_match,
2977 &last_entry_off, ea_list);
2980 if (finished && out_of_space)
2981 finished = False;
2983 if (!finished && !out_of_space)
2984 numentries++;
2987 * As an optimisation if we know we aren't looking
2988 * for a wildcard name (ie. the name matches the wildcard exactly)
2989 * then we can finish on any (first) match.
2990 * This speeds up large directory searches. JRA.
2993 if(got_exact_match)
2994 finished = True;
2996 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2999 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3000 smb_fn_name(req->cmd),
3001 mask, directory, dirtype, numentries ) );
3003 /* Check if we can close the dirptr */
3004 if(close_after_request || (finished && close_if_end)) {
3005 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3006 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3009 if (backup_priv) {
3010 unbecome_root();
3013 /* Set up the return parameter block */
3014 SSVAL(params,0,numentries);
3015 SSVAL(params,2,finished);
3016 SSVAL(params,4,0); /* Never an EA error */
3017 SSVAL(params,6,last_entry_off);
3019 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3020 max_data_bytes);
3022 return;
3025 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3027 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3028 return objid;
3031 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3033 SMB_ASSERT(extended_info != NULL);
3035 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3036 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3037 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3038 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3039 #ifdef SAMBA_VERSION_REVISION
3040 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3041 #endif
3042 extended_info->samba_subversion = 0;
3043 #ifdef SAMBA_VERSION_RC_RELEASE
3044 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3045 #else
3046 #ifdef SAMBA_VERSION_PRE_RELEASE
3047 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3048 #endif
3049 #endif
3050 #ifdef SAMBA_VERSION_VENDOR_PATCH
3051 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3052 #endif
3053 extended_info->samba_gitcommitdate = 0;
3054 #ifdef SAMBA_VERSION_COMMIT_TIME
3055 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3056 #endif
3058 memset(extended_info->samba_version_string, 0,
3059 sizeof(extended_info->samba_version_string));
3061 snprintf (extended_info->samba_version_string,
3062 sizeof(extended_info->samba_version_string),
3063 "%s", samba_version_string());
3066 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3067 TALLOC_CTX *mem_ctx,
3068 uint16_t info_level,
3069 uint16_t flags2,
3070 unsigned int max_data_bytes,
3071 size_t *fixed_portion,
3072 struct smb_filename *fname,
3073 char **ppdata,
3074 int *ret_data_len)
3076 char *pdata, *end_data;
3077 int data_len = 0, len;
3078 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3079 int snum = SNUM(conn);
3080 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3081 char *filename = NULL;
3082 uint32 additional_flags = 0;
3083 struct smb_filename smb_fname;
3084 SMB_STRUCT_STAT st;
3085 NTSTATUS status = NT_STATUS_OK;
3087 if (fname == NULL || fname->base_name == NULL) {
3088 filename = ".";
3089 } else {
3090 filename = fname->base_name;
3093 if (IS_IPC(conn)) {
3094 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3095 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3096 "info level (0x%x) on IPC$.\n",
3097 (unsigned int)info_level));
3098 return NT_STATUS_ACCESS_DENIED;
3102 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3104 ZERO_STRUCT(smb_fname);
3105 smb_fname.base_name = discard_const_p(char, filename);
3107 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3108 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3109 return map_nt_error_from_unix(errno);
3112 st = smb_fname.st;
3114 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3115 return NT_STATUS_INVALID_PARAMETER;
3118 *ppdata = (char *)SMB_REALLOC(
3119 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3120 if (*ppdata == NULL) {
3121 return NT_STATUS_NO_MEMORY;
3124 pdata = *ppdata;
3125 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3126 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3128 *fixed_portion = 0;
3130 switch (info_level) {
3131 case SMB_INFO_ALLOCATION:
3133 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3134 data_len = 18;
3135 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3136 return map_nt_error_from_unix(errno);
3139 block_size = lp_block_size(snum);
3140 if (bsize < block_size) {
3141 uint64_t factor = block_size/bsize;
3142 bsize = block_size;
3143 dsize /= factor;
3144 dfree /= factor;
3146 if (bsize > block_size) {
3147 uint64_t factor = bsize/block_size;
3148 bsize = block_size;
3149 dsize *= factor;
3150 dfree *= factor;
3152 bytes_per_sector = 512;
3153 sectors_per_unit = bsize/bytes_per_sector;
3155 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3156 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3157 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3159 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3160 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3161 SIVAL(pdata,l1_cUnit,dsize);
3162 SIVAL(pdata,l1_cUnitAvail,dfree);
3163 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3164 break;
3167 case SMB_INFO_VOLUME:
3168 /* Return volume name */
3170 * Add volume serial number - hash of a combination of
3171 * the called hostname and the service name.
3173 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3175 * Win2k3 and previous mess this up by sending a name length
3176 * one byte short. I believe only older clients (OS/2 Win9x) use
3177 * this call so try fixing this by adding a terminating null to
3178 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3180 len = srvstr_push(
3181 pdata, flags2,
3182 pdata+l2_vol_szVolLabel, vname,
3183 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3184 STR_NOALIGN|STR_TERMINATE);
3185 SCVAL(pdata,l2_vol_cch,len);
3186 data_len = l2_vol_szVolLabel + len;
3187 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3188 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3189 len, vname));
3190 break;
3192 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3193 case SMB_FS_ATTRIBUTE_INFORMATION:
3195 additional_flags = 0;
3196 #if defined(HAVE_SYS_QUOTAS)
3197 additional_flags |= FILE_VOLUME_QUOTAS;
3198 #endif
3200 if(lp_nt_acl_support(SNUM(conn))) {
3201 additional_flags |= FILE_PERSISTENT_ACLS;
3204 /* Capabilities are filled in at connection time through STATVFS call */
3205 additional_flags |= conn->fs_capabilities;
3206 additional_flags |= lp_parm_int(conn->params->service,
3207 "share", "fake_fscaps",
3210 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3211 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3212 additional_flags); /* FS ATTRIBUTES */
3214 SIVAL(pdata,4,255); /* Max filename component length */
3215 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3216 and will think we can't do long filenames */
3217 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3218 PTR_DIFF(end_data, pdata+12),
3219 STR_UNICODE);
3220 SIVAL(pdata,8,len);
3221 data_len = 12 + len;
3222 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3223 /* the client only requested a portion of the
3224 file system name */
3225 data_len = max_data_bytes;
3226 status = STATUS_BUFFER_OVERFLOW;
3228 *fixed_portion = 16;
3229 break;
3231 case SMB_QUERY_FS_LABEL_INFO:
3232 case SMB_FS_LABEL_INFORMATION:
3233 len = srvstr_push(pdata, flags2, pdata+4, vname,
3234 PTR_DIFF(end_data, pdata+4), 0);
3235 data_len = 4 + len;
3236 SIVAL(pdata,0,len);
3237 break;
3239 case SMB_QUERY_FS_VOLUME_INFO:
3240 case SMB_FS_VOLUME_INFORMATION:
3243 * Add volume serial number - hash of a combination of
3244 * the called hostname and the service name.
3246 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3247 (str_checksum(get_local_machine_name())<<16));
3249 /* Max label len is 32 characters. */
3250 len = srvstr_push(pdata, flags2, pdata+18, vname,
3251 PTR_DIFF(end_data, pdata+18),
3252 STR_UNICODE);
3253 SIVAL(pdata,12,len);
3254 data_len = 18+len;
3256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3257 (int)strlen(vname),vname,
3258 lp_servicename(talloc_tos(), snum)));
3259 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3260 /* the client only requested a portion of the
3261 volume label */
3262 data_len = max_data_bytes;
3263 status = STATUS_BUFFER_OVERFLOW;
3265 *fixed_portion = 24;
3266 break;
3268 case SMB_QUERY_FS_SIZE_INFO:
3269 case SMB_FS_SIZE_INFORMATION:
3271 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3272 data_len = 24;
3273 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3274 return map_nt_error_from_unix(errno);
3276 block_size = lp_block_size(snum);
3277 if (bsize < block_size) {
3278 uint64_t factor = block_size/bsize;
3279 bsize = block_size;
3280 dsize /= factor;
3281 dfree /= factor;
3283 if (bsize > block_size) {
3284 uint64_t factor = bsize/block_size;
3285 bsize = block_size;
3286 dsize *= factor;
3287 dfree *= factor;
3289 bytes_per_sector = 512;
3290 sectors_per_unit = bsize/bytes_per_sector;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3292 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3293 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3294 SBIG_UINT(pdata,0,dsize);
3295 SBIG_UINT(pdata,8,dfree);
3296 SIVAL(pdata,16,sectors_per_unit);
3297 SIVAL(pdata,20,bytes_per_sector);
3298 *fixed_portion = 24;
3299 break;
3302 case SMB_FS_FULL_SIZE_INFORMATION:
3304 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3305 data_len = 32;
3306 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3307 return map_nt_error_from_unix(errno);
3309 block_size = lp_block_size(snum);
3310 if (bsize < block_size) {
3311 uint64_t factor = block_size/bsize;
3312 bsize = block_size;
3313 dsize /= factor;
3314 dfree /= factor;
3316 if (bsize > block_size) {
3317 uint64_t factor = bsize/block_size;
3318 bsize = block_size;
3319 dsize *= factor;
3320 dfree *= factor;
3322 bytes_per_sector = 512;
3323 sectors_per_unit = bsize/bytes_per_sector;
3324 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3325 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3326 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3327 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3328 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3329 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3330 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3331 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3332 *fixed_portion = 32;
3333 break;
3336 case SMB_QUERY_FS_DEVICE_INFO:
3337 case SMB_FS_DEVICE_INFORMATION:
3339 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3341 if (!CAN_WRITE(conn)) {
3342 characteristics |= FILE_READ_ONLY_DEVICE;
3344 data_len = 8;
3345 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3346 SIVAL(pdata,4,characteristics);
3347 *fixed_portion = 8;
3348 break;
3351 #ifdef HAVE_SYS_QUOTAS
3352 case SMB_FS_QUOTA_INFORMATION:
3354 * what we have to send --metze:
3356 * Unknown1: 24 NULL bytes
3357 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3358 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3359 * Quota Flags: 2 byte :
3360 * Unknown3: 6 NULL bytes
3362 * 48 bytes total
3364 * details for Quota Flags:
3366 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3367 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3368 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3369 * 0x0001 Enable Quotas: enable quota for this fs
3373 /* we need to fake up a fsp here,
3374 * because its not send in this call
3376 files_struct fsp;
3377 SMB_NTQUOTA_STRUCT quotas;
3379 ZERO_STRUCT(fsp);
3380 ZERO_STRUCT(quotas);
3382 fsp.conn = conn;
3383 fsp.fnum = FNUM_FIELD_INVALID;
3385 /* access check */
3386 if (get_current_uid(conn) != 0) {
3387 DEBUG(0,("get_user_quota: access_denied "
3388 "service [%s] user [%s]\n",
3389 lp_servicename(talloc_tos(), SNUM(conn)),
3390 conn->session_info->unix_info->unix_name));
3391 return NT_STATUS_ACCESS_DENIED;
3394 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3395 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3396 return map_nt_error_from_unix(errno);
3399 data_len = 48;
3401 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3402 lp_servicename(talloc_tos(), SNUM(conn))));
3404 /* Unknown1 24 NULL bytes*/
3405 SBIG_UINT(pdata,0,(uint64_t)0);
3406 SBIG_UINT(pdata,8,(uint64_t)0);
3407 SBIG_UINT(pdata,16,(uint64_t)0);
3409 /* Default Soft Quota 8 bytes */
3410 SBIG_UINT(pdata,24,quotas.softlim);
3412 /* Default Hard Quota 8 bytes */
3413 SBIG_UINT(pdata,32,quotas.hardlim);
3415 /* Quota flag 2 bytes */
3416 SSVAL(pdata,40,quotas.qflags);
3418 /* Unknown3 6 NULL bytes */
3419 SSVAL(pdata,42,0);
3420 SIVAL(pdata,44,0);
3422 break;
3424 #endif /* HAVE_SYS_QUOTAS */
3425 case SMB_FS_OBJECTID_INFORMATION:
3427 unsigned char objid[16];
3428 struct smb_extended_info extended_info;
3429 memcpy(pdata,create_volume_objectid(conn, objid),16);
3430 samba_extended_info_version (&extended_info);
3431 SIVAL(pdata,16,extended_info.samba_magic);
3432 SIVAL(pdata,20,extended_info.samba_version);
3433 SIVAL(pdata,24,extended_info.samba_subversion);
3434 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3435 memcpy(pdata+36,extended_info.samba_version_string,28);
3436 data_len = 64;
3437 break;
3441 * Query the version and capabilities of the CIFS UNIX extensions
3442 * in use.
3445 case SMB_QUERY_CIFS_UNIX_INFO:
3447 bool large_write = lp_min_receive_file_size() &&
3448 !srv_is_signing_active(conn->sconn);
3449 bool large_read = !srv_is_signing_active(conn->sconn);
3450 int encrypt_caps = 0;
3452 if (!lp_unix_extensions()) {
3453 return NT_STATUS_INVALID_LEVEL;
3456 switch (conn->encrypt_level) {
3457 case SMB_SIGNING_OFF:
3458 encrypt_caps = 0;
3459 break;
3460 case SMB_SIGNING_IF_REQUIRED:
3461 case SMB_SIGNING_DEFAULT:
3462 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3463 break;
3464 case SMB_SIGNING_REQUIRED:
3465 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3466 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3467 large_write = false;
3468 large_read = false;
3469 break;
3472 data_len = 12;
3473 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3474 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3476 /* We have POSIX ACLs, pathname, encryption,
3477 * large read/write, and locking capability. */
3479 SBIG_UINT(pdata,4,((uint64_t)(
3480 CIFS_UNIX_POSIX_ACLS_CAP|
3481 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3482 CIFS_UNIX_FCNTL_LOCKS_CAP|
3483 CIFS_UNIX_EXTATTR_CAP|
3484 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3485 encrypt_caps|
3486 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3487 (large_write ?
3488 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3489 break;
3492 case SMB_QUERY_POSIX_FS_INFO:
3494 int rc;
3495 vfs_statvfs_struct svfs;
3497 if (!lp_unix_extensions()) {
3498 return NT_STATUS_INVALID_LEVEL;
3501 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3503 if (!rc) {
3504 data_len = 56;
3505 SIVAL(pdata,0,svfs.OptimalTransferSize);
3506 SIVAL(pdata,4,svfs.BlockSize);
3507 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3508 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3509 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3510 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3511 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3512 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3513 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3514 #ifdef EOPNOTSUPP
3515 } else if (rc == EOPNOTSUPP) {
3516 return NT_STATUS_INVALID_LEVEL;
3517 #endif /* EOPNOTSUPP */
3518 } else {
3519 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3520 return NT_STATUS_DOS(ERRSRV, ERRerror);
3522 break;
3525 case SMB_QUERY_POSIX_WHOAMI:
3527 uint32_t flags = 0;
3528 uint32_t sid_bytes;
3529 int i;
3531 if (!lp_unix_extensions()) {
3532 return NT_STATUS_INVALID_LEVEL;
3535 if (max_data_bytes < 40) {
3536 return NT_STATUS_BUFFER_TOO_SMALL;
3539 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3540 flags |= SMB_WHOAMI_GUEST;
3543 /* NOTE: 8 bytes for UID/GID, irrespective of native
3544 * platform size. This matches
3545 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3547 data_len = 4 /* flags */
3548 + 4 /* flag mask */
3549 + 8 /* uid */
3550 + 8 /* gid */
3551 + 4 /* ngroups */
3552 + 4 /* num_sids */
3553 + 4 /* SID bytes */
3554 + 4 /* pad/reserved */
3555 + (conn->session_info->unix_token->ngroups * 8)
3556 /* groups list */
3557 + (conn->session_info->security_token->num_sids *
3558 SID_MAX_SIZE)
3559 /* SID list */;
3561 SIVAL(pdata, 0, flags);
3562 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3563 SBIG_UINT(pdata, 8,
3564 (uint64_t)conn->session_info->unix_token->uid);
3565 SBIG_UINT(pdata, 16,
3566 (uint64_t)conn->session_info->unix_token->gid);
3569 if (data_len >= max_data_bytes) {
3570 /* Potential overflow, skip the GIDs and SIDs. */
3572 SIVAL(pdata, 24, 0); /* num_groups */
3573 SIVAL(pdata, 28, 0); /* num_sids */
3574 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3575 SIVAL(pdata, 36, 0); /* reserved */
3577 data_len = 40;
3578 break;
3581 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3582 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3584 /* We walk the SID list twice, but this call is fairly
3585 * infrequent, and I don't expect that it's performance
3586 * sensitive -- jpeach
3588 for (i = 0, sid_bytes = 0;
3589 i < conn->session_info->security_token->num_sids; ++i) {
3590 sid_bytes += ndr_size_dom_sid(
3591 &conn->session_info->security_token->sids[i],
3595 /* SID list byte count */
3596 SIVAL(pdata, 32, sid_bytes);
3598 /* 4 bytes pad/reserved - must be zero */
3599 SIVAL(pdata, 36, 0);
3600 data_len = 40;
3602 /* GID list */
3603 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3604 SBIG_UINT(pdata, data_len,
3605 (uint64_t)conn->session_info->unix_token->groups[i]);
3606 data_len += 8;
3609 /* SID list */
3610 for (i = 0;
3611 i < conn->session_info->security_token->num_sids; ++i) {
3612 int sid_len = ndr_size_dom_sid(
3613 &conn->session_info->security_token->sids[i],
3616 sid_linearize(pdata + data_len, sid_len,
3617 &conn->session_info->security_token->sids[i]);
3618 data_len += sid_len;
3621 break;
3624 case SMB_MAC_QUERY_FS_INFO:
3626 * Thursby MAC extension... ONLY on NTFS filesystems
3627 * once we do streams then we don't need this
3629 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3630 data_len = 88;
3631 SIVAL(pdata,84,0x100); /* Don't support mac... */
3632 break;
3634 /* drop through */
3635 default:
3636 return NT_STATUS_INVALID_LEVEL;
3639 *ret_data_len = data_len;
3640 return status;
3643 /****************************************************************************
3644 Reply to a TRANS2_QFSINFO (query filesystem info).
3645 ****************************************************************************/
3647 static void call_trans2qfsinfo(connection_struct *conn,
3648 struct smb_request *req,
3649 char **pparams, int total_params,
3650 char **ppdata, int total_data,
3651 unsigned int max_data_bytes)
3653 char *params = *pparams;
3654 uint16_t info_level;
3655 int data_len = 0;
3656 size_t fixed_portion;
3657 NTSTATUS status;
3659 if (total_params < 2) {
3660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3661 return;
3664 info_level = SVAL(params,0);
3666 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3667 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3668 DEBUG(0,("call_trans2qfsinfo: encryption required "
3669 "and info level 0x%x sent.\n",
3670 (unsigned int)info_level));
3671 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3672 return;
3676 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3678 status = smbd_do_qfsinfo(conn, req,
3679 info_level,
3680 req->flags2,
3681 max_data_bytes,
3682 &fixed_portion,
3683 NULL,
3684 ppdata, &data_len);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 reply_nterror(req, status);
3687 return;
3690 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3691 max_data_bytes);
3693 DEBUG( 4, ( "%s info_level = %d\n",
3694 smb_fn_name(req->cmd), info_level) );
3696 return;
3699 /****************************************************************************
3700 Reply to a TRANS2_SETFSINFO (set filesystem info).
3701 ****************************************************************************/
3703 static void call_trans2setfsinfo(connection_struct *conn,
3704 struct smb_request *req,
3705 char **pparams, int total_params,
3706 char **ppdata, int total_data,
3707 unsigned int max_data_bytes)
3709 struct smbd_server_connection *sconn = req->sconn;
3710 char *pdata = *ppdata;
3711 char *params = *pparams;
3712 uint16 info_level;
3714 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3715 lp_servicename(talloc_tos(), SNUM(conn))));
3717 /* */
3718 if (total_params < 4) {
3719 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3720 total_params));
3721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3722 return;
3725 info_level = SVAL(params,2);
3727 if (IS_IPC(conn)) {
3728 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3729 info_level != SMB_SET_CIFS_UNIX_INFO) {
3730 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3731 "info level (0x%x) on IPC$.\n",
3732 (unsigned int)info_level));
3733 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3734 return;
3738 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3739 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3740 DEBUG(0,("call_trans2setfsinfo: encryption required "
3741 "and info level 0x%x sent.\n",
3742 (unsigned int)info_level));
3743 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3744 return;
3748 switch(info_level) {
3749 case SMB_SET_CIFS_UNIX_INFO:
3750 if (!lp_unix_extensions()) {
3751 DEBUG(2,("call_trans2setfsinfo: "
3752 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3753 "unix extensions off\n"));
3754 reply_nterror(req,
3755 NT_STATUS_INVALID_LEVEL);
3756 return;
3759 /* There should be 12 bytes of capabilities set. */
3760 if (total_data < 12) {
3761 reply_nterror(
3762 req,
3763 NT_STATUS_INVALID_PARAMETER);
3764 return;
3766 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3767 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3768 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3769 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3770 /* Just print these values for now. */
3771 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3772 "major = %u, minor = %u cap_low = 0x%x, "
3773 "cap_high = 0x%xn",
3774 (unsigned int)sconn->
3775 smb1.unix_info.client_major,
3776 (unsigned int)sconn->
3777 smb1.unix_info.client_minor,
3778 (unsigned int)sconn->
3779 smb1.unix_info.client_cap_low,
3780 (unsigned int)sconn->
3781 smb1.unix_info.client_cap_high));
3783 /* Here is where we must switch to posix pathname processing... */
3784 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3785 lp_set_posix_pathnames();
3786 mangle_change_to_posix();
3789 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3790 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3791 /* Client that knows how to do posix locks,
3792 * but not posix open/mkdir operations. Set a
3793 * default type for read/write checks. */
3795 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3798 break;
3800 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3802 NTSTATUS status;
3803 size_t param_len = 0;
3804 size_t data_len = total_data;
3806 if (!lp_unix_extensions()) {
3807 reply_nterror(
3808 req,
3809 NT_STATUS_INVALID_LEVEL);
3810 return;
3813 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3814 reply_nterror(
3815 req,
3816 NT_STATUS_NOT_SUPPORTED);
3817 return;
3820 if (req->sconn->smb1.echo_handler.trusted_fde) {
3821 DEBUG( 2,("call_trans2setfsinfo: "
3822 "request transport encryption disabled"
3823 "with 'fork echo handler = yes'\n"));
3824 reply_nterror(
3825 req,
3826 NT_STATUS_NOT_SUPPORTED);
3827 return;
3830 DEBUG( 4,("call_trans2setfsinfo: "
3831 "request transport encryption.\n"));
3833 status = srv_request_encryption_setup(conn,
3834 (unsigned char **)ppdata,
3835 &data_len,
3836 (unsigned char **)pparams,
3837 &param_len);
3839 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3840 !NT_STATUS_IS_OK(status)) {
3841 reply_nterror(req, status);
3842 return;
3845 send_trans2_replies(conn, req,
3846 NT_STATUS_OK,
3847 *pparams,
3848 param_len,
3849 *ppdata,
3850 data_len,
3851 max_data_bytes);
3853 if (NT_STATUS_IS_OK(status)) {
3854 /* Server-side transport
3855 * encryption is now *on*. */
3856 status = srv_encryption_start(conn);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 char *reason = talloc_asprintf(talloc_tos(),
3859 "Failure in setting "
3860 "up encrypted transport: %s",
3861 nt_errstr(status));
3862 exit_server_cleanly(reason);
3865 return;
3868 case SMB_FS_QUOTA_INFORMATION:
3870 files_struct *fsp = NULL;
3871 SMB_NTQUOTA_STRUCT quotas;
3873 ZERO_STRUCT(quotas);
3875 /* access check */
3876 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3877 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3878 lp_servicename(talloc_tos(), SNUM(conn)),
3879 conn->session_info->unix_info->unix_name));
3880 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3881 return;
3884 /* note: normaly there're 48 bytes,
3885 * but we didn't use the last 6 bytes for now
3886 * --metze
3888 fsp = file_fsp(req, SVAL(params,0));
3890 if (!check_fsp_ntquota_handle(conn, req,
3891 fsp)) {
3892 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3893 reply_nterror(
3894 req, NT_STATUS_INVALID_HANDLE);
3895 return;
3898 if (total_data < 42) {
3899 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3900 total_data));
3901 reply_nterror(
3902 req,
3903 NT_STATUS_INVALID_PARAMETER);
3904 return;
3907 /* unknown_1 24 NULL bytes in pdata*/
3909 /* the soft quotas 8 bytes (uint64_t)*/
3910 quotas.softlim = BVAL(pdata,24);
3912 /* the hard quotas 8 bytes (uint64_t)*/
3913 quotas.hardlim = BVAL(pdata,32);
3915 /* quota_flags 2 bytes **/
3916 quotas.qflags = SVAL(pdata,40);
3918 /* unknown_2 6 NULL bytes follow*/
3920 /* now set the quotas */
3921 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3922 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3923 reply_nterror(req, map_nt_error_from_unix(errno));
3924 return;
3927 break;
3929 default:
3930 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3931 info_level));
3932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3933 return;
3934 break;
3938 * sending this reply works fine,
3939 * but I'm not sure it's the same
3940 * like windows do...
3941 * --metze
3943 reply_outbuf(req, 10, 0);
3946 #if defined(HAVE_POSIX_ACLS)
3947 /****************************************************************************
3948 Utility function to count the number of entries in a POSIX acl.
3949 ****************************************************************************/
3951 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3953 unsigned int ace_count = 0;
3954 int entry_id = SMB_ACL_FIRST_ENTRY;
3955 SMB_ACL_ENTRY_T entry;
3957 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3958 /* get_next... */
3959 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3960 entry_id = SMB_ACL_NEXT_ENTRY;
3962 ace_count++;
3964 return ace_count;
3967 /****************************************************************************
3968 Utility function to marshall a POSIX acl into wire format.
3969 ****************************************************************************/
3971 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3973 int entry_id = SMB_ACL_FIRST_ENTRY;
3974 SMB_ACL_ENTRY_T entry;
3976 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3977 SMB_ACL_TAG_T tagtype;
3978 SMB_ACL_PERMSET_T permset;
3979 unsigned char perms = 0;
3980 unsigned int own_grp;
3982 /* get_next... */
3983 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3984 entry_id = SMB_ACL_NEXT_ENTRY;
3987 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3988 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3989 return False;
3992 if (sys_acl_get_permset(entry, &permset) == -1) {
3993 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3994 return False;
3997 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3998 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3999 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4001 SCVAL(pdata,1,perms);
4003 switch (tagtype) {
4004 case SMB_ACL_USER_OBJ:
4005 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4006 own_grp = (unsigned int)pst->st_ex_uid;
4007 SIVAL(pdata,2,own_grp);
4008 SIVAL(pdata,6,0);
4009 break;
4010 case SMB_ACL_USER:
4012 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4013 if (!puid) {
4014 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4015 return False;
4017 own_grp = (unsigned int)*puid;
4018 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4019 SIVAL(pdata,2,own_grp);
4020 SIVAL(pdata,6,0);
4021 break;
4023 case SMB_ACL_GROUP_OBJ:
4024 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4025 own_grp = (unsigned int)pst->st_ex_gid;
4026 SIVAL(pdata,2,own_grp);
4027 SIVAL(pdata,6,0);
4028 break;
4029 case SMB_ACL_GROUP:
4031 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4032 if (!pgid) {
4033 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4034 return False;
4036 own_grp = (unsigned int)*pgid;
4037 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4038 SIVAL(pdata,2,own_grp);
4039 SIVAL(pdata,6,0);
4040 break;
4042 case SMB_ACL_MASK:
4043 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4044 SIVAL(pdata,2,0xFFFFFFFF);
4045 SIVAL(pdata,6,0xFFFFFFFF);
4046 break;
4047 case SMB_ACL_OTHER:
4048 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4049 SIVAL(pdata,2,0xFFFFFFFF);
4050 SIVAL(pdata,6,0xFFFFFFFF);
4051 break;
4052 default:
4053 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4054 return False;
4056 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4059 return True;
4061 #endif
4063 /****************************************************************************
4064 Store the FILE_UNIX_BASIC info.
4065 ****************************************************************************/
4067 static char *store_file_unix_basic(connection_struct *conn,
4068 char *pdata,
4069 files_struct *fsp,
4070 const SMB_STRUCT_STAT *psbuf)
4072 uint64_t file_index = get_FileIndex(conn, psbuf);
4073 dev_t devno;
4075 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4076 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4078 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4079 pdata += 8;
4081 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4082 pdata += 8;
4084 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4085 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4086 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4087 pdata += 24;
4089 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4090 SIVAL(pdata,4,0);
4091 pdata += 8;
4093 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4094 SIVAL(pdata,4,0);
4095 pdata += 8;
4097 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4098 pdata += 4;
4100 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4101 devno = psbuf->st_ex_rdev;
4102 } else {
4103 devno = psbuf->st_ex_dev;
4106 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4107 SIVAL(pdata,4,0);
4108 pdata += 8;
4110 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4111 SIVAL(pdata,4,0);
4112 pdata += 8;
4114 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4115 pdata += 8;
4117 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4118 SIVAL(pdata,4,0);
4119 pdata += 8;
4121 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4122 SIVAL(pdata,4,0);
4123 pdata += 8;
4125 return pdata;
4128 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4129 * the chflags(2) (or equivalent) flags.
4131 * XXX: this really should be behind the VFS interface. To do this, we would
4132 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4133 * Each VFS module could then implement its own mapping as appropriate for the
4134 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4136 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4137 info2_flags_map[] =
4139 #ifdef UF_NODUMP
4140 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4141 #endif
4143 #ifdef UF_IMMUTABLE
4144 { UF_IMMUTABLE, EXT_IMMUTABLE },
4145 #endif
4147 #ifdef UF_APPEND
4148 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4149 #endif
4151 #ifdef UF_HIDDEN
4152 { UF_HIDDEN, EXT_HIDDEN },
4153 #endif
4155 /* Do not remove. We need to guarantee that this array has at least one
4156 * entry to build on HP-UX.
4158 { 0, 0 }
4162 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4163 uint32 *smb_fflags, uint32 *smb_fmask)
4165 int i;
4167 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4168 *smb_fmask |= info2_flags_map[i].smb_fflag;
4169 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4170 *smb_fflags |= info2_flags_map[i].smb_fflag;
4175 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4176 const uint32 smb_fflags,
4177 const uint32 smb_fmask,
4178 int *stat_fflags)
4180 uint32 max_fmask = 0;
4181 int i;
4183 *stat_fflags = psbuf->st_ex_flags;
4185 /* For each flags requested in smb_fmask, check the state of the
4186 * corresponding flag in smb_fflags and set or clear the matching
4187 * stat flag.
4190 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4191 max_fmask |= info2_flags_map[i].smb_fflag;
4192 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4193 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4194 *stat_fflags |= info2_flags_map[i].stat_fflag;
4195 } else {
4196 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4201 /* If smb_fmask is asking to set any bits that are not supported by
4202 * our flag mappings, we should fail.
4204 if ((smb_fmask & max_fmask) != smb_fmask) {
4205 return False;
4208 return True;
4212 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4213 * of file flags and birth (create) time.
4215 static char *store_file_unix_basic_info2(connection_struct *conn,
4216 char *pdata,
4217 files_struct *fsp,
4218 const SMB_STRUCT_STAT *psbuf)
4220 uint32 file_flags = 0;
4221 uint32 flags_mask = 0;
4223 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4225 /* Create (birth) time 64 bit */
4226 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4227 pdata += 8;
4229 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4230 SIVAL(pdata, 0, file_flags); /* flags */
4231 SIVAL(pdata, 4, flags_mask); /* mask */
4232 pdata += 8;
4234 return pdata;
4237 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4238 const struct stream_struct *streams,
4239 char *data,
4240 unsigned int max_data_bytes,
4241 unsigned int *data_size)
4243 unsigned int i;
4244 unsigned int ofs = 0;
4246 if (max_data_bytes < 32) {
4247 return NT_STATUS_INFO_LENGTH_MISMATCH;
4250 for (i = 0; i < num_streams; i++) {
4251 unsigned int next_offset;
4252 size_t namelen;
4253 smb_ucs2_t *namebuf;
4255 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4256 streams[i].name, &namelen) ||
4257 namelen <= 2)
4259 return NT_STATUS_INVALID_PARAMETER;
4263 * name_buf is now null-terminated, we need to marshall as not
4264 * terminated
4267 namelen -= 2;
4270 * We cannot overflow ...
4272 if ((ofs + 24 + namelen) > max_data_bytes) {
4273 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4274 i));
4275 TALLOC_FREE(namebuf);
4276 return STATUS_BUFFER_OVERFLOW;
4279 SIVAL(data, ofs+4, namelen);
4280 SOFF_T(data, ofs+8, streams[i].size);
4281 SOFF_T(data, ofs+16, streams[i].alloc_size);
4282 memcpy(data+ofs+24, namebuf, namelen);
4283 TALLOC_FREE(namebuf);
4285 next_offset = ofs + 24 + namelen;
4287 if (i == num_streams-1) {
4288 SIVAL(data, ofs, 0);
4290 else {
4291 unsigned int align = ndr_align_size(next_offset, 8);
4293 if ((next_offset + align) > max_data_bytes) {
4294 DEBUG(10, ("refusing to overflow align "
4295 "reply at stream %u\n",
4296 i));
4297 TALLOC_FREE(namebuf);
4298 return STATUS_BUFFER_OVERFLOW;
4301 memset(data+next_offset, 0, align);
4302 next_offset += align;
4304 SIVAL(data, ofs, next_offset - ofs);
4305 ofs = next_offset;
4308 ofs = next_offset;
4311 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4313 *data_size = ofs;
4315 return NT_STATUS_OK;
4318 /****************************************************************************
4319 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4320 ****************************************************************************/
4322 static void call_trans2qpipeinfo(connection_struct *conn,
4323 struct smb_request *req,
4324 unsigned int tran_call,
4325 char **pparams, int total_params,
4326 char **ppdata, int total_data,
4327 unsigned int max_data_bytes)
4329 char *params = *pparams;
4330 char *pdata = *ppdata;
4331 unsigned int data_size = 0;
4332 unsigned int param_size = 2;
4333 uint16 info_level;
4334 files_struct *fsp;
4336 if (!params) {
4337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4338 return;
4341 if (total_params < 4) {
4342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4343 return;
4346 fsp = file_fsp(req, SVAL(params,0));
4347 if (!fsp_is_np(fsp)) {
4348 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4349 return;
4352 info_level = SVAL(params,2);
4354 *pparams = (char *)SMB_REALLOC(*pparams,2);
4355 if (*pparams == NULL) {
4356 reply_nterror(req, NT_STATUS_NO_MEMORY);
4357 return;
4359 params = *pparams;
4360 SSVAL(params,0,0);
4361 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4363 return;
4365 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4366 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4367 if (*ppdata == NULL ) {
4368 reply_nterror(req, NT_STATUS_NO_MEMORY);
4369 return;
4371 pdata = *ppdata;
4373 switch (info_level) {
4374 case SMB_FILE_STANDARD_INFORMATION:
4375 memset(pdata,0,24);
4376 SOFF_T(pdata,0,4096LL);
4377 SIVAL(pdata,16,1);
4378 SIVAL(pdata,20,1);
4379 data_size = 24;
4380 break;
4382 default:
4383 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4384 return;
4387 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4388 max_data_bytes);
4390 return;
4393 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4394 TALLOC_CTX *mem_ctx,
4395 uint16_t info_level,
4396 files_struct *fsp,
4397 struct smb_filename *smb_fname,
4398 bool delete_pending,
4399 struct timespec write_time_ts,
4400 struct ea_list *ea_list,
4401 int lock_data_count,
4402 char *lock_data,
4403 uint16_t flags2,
4404 unsigned int max_data_bytes,
4405 size_t *fixed_portion,
4406 char **ppdata,
4407 unsigned int *pdata_size)
4409 char *pdata = *ppdata;
4410 char *dstart, *dend;
4411 unsigned int data_size;
4412 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4413 time_t create_time, mtime, atime, c_time;
4414 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4415 char *p;
4416 char *base_name;
4417 char *dos_fname;
4418 int mode;
4419 int nlink;
4420 NTSTATUS status;
4421 uint64_t file_size = 0;
4422 uint64_t pos = 0;
4423 uint64_t allocation_size = 0;
4424 uint64_t file_index = 0;
4425 uint32_t access_mask = 0;
4427 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4428 return NT_STATUS_INVALID_LEVEL;
4431 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4432 smb_fname_str_dbg(smb_fname),
4433 fsp_fnum_dbg(fsp),
4434 info_level, max_data_bytes));
4436 mode = dos_mode(conn, smb_fname);
4437 nlink = psbuf->st_ex_nlink;
4439 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4440 nlink = 1;
4443 if ((nlink > 0) && delete_pending) {
4444 nlink -= 1;
4447 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4448 return NT_STATUS_INVALID_PARAMETER;
4451 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4452 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4453 if (*ppdata == NULL) {
4454 return NT_STATUS_NO_MEMORY;
4456 pdata = *ppdata;
4457 dstart = pdata;
4458 dend = dstart + data_size - 1;
4460 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4461 update_stat_ex_mtime(psbuf, write_time_ts);
4464 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4465 mtime_ts = psbuf->st_ex_mtime;
4466 atime_ts = psbuf->st_ex_atime;
4467 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4469 if (lp_dos_filetime_resolution(SNUM(conn))) {
4470 dos_filetime_timespec(&create_time_ts);
4471 dos_filetime_timespec(&mtime_ts);
4472 dos_filetime_timespec(&atime_ts);
4473 dos_filetime_timespec(&ctime_ts);
4476 create_time = convert_timespec_to_time_t(create_time_ts);
4477 mtime = convert_timespec_to_time_t(mtime_ts);
4478 atime = convert_timespec_to_time_t(atime_ts);
4479 c_time = convert_timespec_to_time_t(ctime_ts);
4481 p = strrchr_m(smb_fname->base_name,'/');
4482 if (!p)
4483 base_name = smb_fname->base_name;
4484 else
4485 base_name = p+1;
4487 /* NT expects the name to be in an exact form of the *full*
4488 filename. See the trans2 torture test */
4489 if (ISDOT(base_name)) {
4490 dos_fname = talloc_strdup(mem_ctx, "\\");
4491 if (!dos_fname) {
4492 return NT_STATUS_NO_MEMORY;
4494 } else {
4495 dos_fname = talloc_asprintf(mem_ctx,
4496 "\\%s",
4497 smb_fname->base_name);
4498 if (!dos_fname) {
4499 return NT_STATUS_NO_MEMORY;
4501 if (is_ntfs_stream_smb_fname(smb_fname)) {
4502 dos_fname = talloc_asprintf(dos_fname, "%s",
4503 smb_fname->stream_name);
4504 if (!dos_fname) {
4505 return NT_STATUS_NO_MEMORY;
4509 string_replace(dos_fname, '/', '\\');
4512 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4514 if (!fsp) {
4515 /* Do we have this path open ? */
4516 files_struct *fsp1;
4517 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4518 fsp1 = file_find_di_first(conn->sconn, fileid);
4519 if (fsp1 && fsp1->initial_allocation_size) {
4520 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4524 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4525 file_size = get_file_size_stat(psbuf);
4528 if (fsp) {
4529 pos = fsp->fh->position_information;
4532 if (fsp) {
4533 access_mask = fsp->access_mask;
4534 } else {
4535 /* GENERIC_EXECUTE mapping from Windows */
4536 access_mask = 0x12019F;
4539 /* This should be an index number - looks like
4540 dev/ino to me :-)
4542 I think this causes us to fail the IFSKIT
4543 BasicFileInformationTest. -tpot */
4544 file_index = get_FileIndex(conn, psbuf);
4546 *fixed_portion = 0;
4548 switch (info_level) {
4549 case SMB_INFO_STANDARD:
4550 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4551 data_size = 22;
4552 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4553 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4554 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4555 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4556 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4557 SSVAL(pdata,l1_attrFile,mode);
4558 break;
4560 case SMB_INFO_QUERY_EA_SIZE:
4562 unsigned int ea_size =
4563 estimate_ea_size(conn, fsp,
4564 smb_fname);
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4566 data_size = 26;
4567 srv_put_dos_date2(pdata,0,create_time);
4568 srv_put_dos_date2(pdata,4,atime);
4569 srv_put_dos_date2(pdata,8,mtime); /* write time */
4570 SIVAL(pdata,12,(uint32)file_size);
4571 SIVAL(pdata,16,(uint32)allocation_size);
4572 SSVAL(pdata,20,mode);
4573 SIVAL(pdata,22,ea_size);
4574 break;
4577 case SMB_INFO_IS_NAME_VALID:
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4579 if (fsp) {
4580 /* os/2 needs this ? really ?*/
4581 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4583 /* This is only reached for qpathinfo */
4584 data_size = 0;
4585 break;
4587 case SMB_INFO_QUERY_EAS_FROM_LIST:
4589 size_t total_ea_len = 0;
4590 struct ea_list *ea_file_list = NULL;
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4593 status =
4594 get_ea_list_from_file(mem_ctx, conn, fsp,
4595 smb_fname,
4596 &total_ea_len, &ea_file_list);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 return status;
4601 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4603 if (!ea_list || (total_ea_len > data_size)) {
4604 data_size = 4;
4605 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4606 break;
4609 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4610 break;
4613 case SMB_INFO_QUERY_ALL_EAS:
4615 /* We have data_size bytes to put EA's into. */
4616 size_t total_ea_len = 0;
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4619 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4620 smb_fname,
4621 &total_ea_len, &ea_list);
4622 if (!NT_STATUS_IS_OK(status)) {
4623 return status;
4626 if (!ea_list || (total_ea_len > data_size)) {
4627 data_size = 4;
4628 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4629 break;
4632 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4633 break;
4636 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4638 /* This is FileFullEaInformation - 0xF which maps to
4639 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4641 /* We have data_size bytes to put EA's into. */
4642 size_t total_ea_len = 0;
4643 struct ea_list *ea_file_list = NULL;
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4647 /*TODO: add filtering and index handling */
4649 status =
4650 get_ea_list_from_file(mem_ctx, conn, fsp,
4651 smb_fname,
4652 &total_ea_len, &ea_file_list);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 return status;
4656 if (!ea_file_list) {
4657 return NT_STATUS_NO_EAS_ON_FILE;
4660 status = fill_ea_chained_buffer(mem_ctx,
4661 pdata,
4662 data_size,
4663 &data_size,
4664 conn, ea_file_list);
4665 if (!NT_STATUS_IS_OK(status)) {
4666 return status;
4668 break;
4671 case SMB_FILE_BASIC_INFORMATION:
4672 case SMB_QUERY_FILE_BASIC_INFO:
4674 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4676 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4677 } else {
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4679 data_size = 40;
4680 SIVAL(pdata,36,0);
4682 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4683 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4684 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4685 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4686 SIVAL(pdata,32,mode);
4688 DEBUG(5,("SMB_QFBI - "));
4689 DEBUG(5,("create: %s ", ctime(&create_time)));
4690 DEBUG(5,("access: %s ", ctime(&atime)));
4691 DEBUG(5,("write: %s ", ctime(&mtime)));
4692 DEBUG(5,("change: %s ", ctime(&c_time)));
4693 DEBUG(5,("mode: %x\n", mode));
4694 *fixed_portion = data_size;
4695 break;
4697 case SMB_FILE_STANDARD_INFORMATION:
4698 case SMB_QUERY_FILE_STANDARD_INFO:
4700 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4701 data_size = 24;
4702 SOFF_T(pdata,0,allocation_size);
4703 SOFF_T(pdata,8,file_size);
4704 SIVAL(pdata,16,nlink);
4705 SCVAL(pdata,20,delete_pending?1:0);
4706 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4707 SSVAL(pdata,22,0); /* Padding. */
4708 *fixed_portion = 24;
4709 break;
4711 case SMB_FILE_EA_INFORMATION:
4712 case SMB_QUERY_FILE_EA_INFO:
4714 unsigned int ea_size =
4715 estimate_ea_size(conn, fsp, smb_fname);
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4717 data_size = 4;
4718 *fixed_portion = 4;
4719 SIVAL(pdata,0,ea_size);
4720 break;
4723 /* Get the 8.3 name - used if NT SMB was negotiated. */
4724 case SMB_QUERY_FILE_ALT_NAME_INFO:
4725 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4727 int len;
4728 char mangled_name[13];
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4730 if (!name_to_8_3(base_name,mangled_name,
4731 True,conn->params)) {
4732 return NT_STATUS_NO_MEMORY;
4734 len = srvstr_push(dstart, flags2,
4735 pdata+4, mangled_name,
4736 PTR_DIFF(dend, pdata+4),
4737 STR_UNICODE);
4738 data_size = 4 + len;
4739 SIVAL(pdata,0,len);
4740 *fixed_portion = 8;
4741 break;
4744 case SMB_QUERY_FILE_NAME_INFO:
4746 int len;
4748 this must be *exactly* right for ACLs on mapped drives to work
4750 len = srvstr_push(dstart, flags2,
4751 pdata+4, dos_fname,
4752 PTR_DIFF(dend, pdata+4),
4753 STR_UNICODE);
4754 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4755 data_size = 4 + len;
4756 SIVAL(pdata,0,len);
4757 break;
4760 case SMB_FILE_ALLOCATION_INFORMATION:
4761 case SMB_QUERY_FILE_ALLOCATION_INFO:
4762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4763 data_size = 8;
4764 SOFF_T(pdata,0,allocation_size);
4765 break;
4767 case SMB_FILE_END_OF_FILE_INFORMATION:
4768 case SMB_QUERY_FILE_END_OF_FILEINFO:
4769 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4770 data_size = 8;
4771 SOFF_T(pdata,0,file_size);
4772 break;
4774 case SMB_QUERY_FILE_ALL_INFO:
4775 case SMB_FILE_ALL_INFORMATION:
4777 int len;
4778 unsigned int ea_size =
4779 estimate_ea_size(conn, fsp, smb_fname);
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4781 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4782 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4783 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4784 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4785 SIVAL(pdata,32,mode);
4786 SIVAL(pdata,36,0); /* padding. */
4787 pdata += 40;
4788 SOFF_T(pdata,0,allocation_size);
4789 SOFF_T(pdata,8,file_size);
4790 SIVAL(pdata,16,nlink);
4791 SCVAL(pdata,20,delete_pending);
4792 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4793 SSVAL(pdata,22,0);
4794 pdata += 24;
4795 SIVAL(pdata,0,ea_size);
4796 pdata += 4; /* EA info */
4797 len = srvstr_push(dstart, flags2,
4798 pdata+4, dos_fname,
4799 PTR_DIFF(dend, pdata+4),
4800 STR_UNICODE);
4801 SIVAL(pdata,0,len);
4802 pdata += 4 + len;
4803 data_size = PTR_DIFF(pdata,(*ppdata));
4804 *fixed_portion = 10;
4805 break;
4808 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4810 int len;
4811 unsigned int ea_size =
4812 estimate_ea_size(conn, fsp, smb_fname);
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4814 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4815 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4816 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4817 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4818 SIVAL(pdata, 0x20, mode);
4819 SIVAL(pdata, 0x24, 0); /* padding. */
4820 SBVAL(pdata, 0x28, allocation_size);
4821 SBVAL(pdata, 0x30, file_size);
4822 SIVAL(pdata, 0x38, nlink);
4823 SCVAL(pdata, 0x3C, delete_pending);
4824 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4825 SSVAL(pdata, 0x3E, 0); /* padding */
4826 SBVAL(pdata, 0x40, file_index);
4827 SIVAL(pdata, 0x48, ea_size);
4828 SIVAL(pdata, 0x4C, access_mask);
4829 SBVAL(pdata, 0x50, pos);
4830 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4831 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4833 pdata += 0x60;
4835 len = srvstr_push(dstart, flags2,
4836 pdata+4, dos_fname,
4837 PTR_DIFF(dend, pdata+4),
4838 STR_UNICODE);
4839 SIVAL(pdata,0,len);
4840 pdata += 4 + len;
4841 data_size = PTR_DIFF(pdata,(*ppdata));
4842 *fixed_portion = 104;
4843 break;
4845 case SMB_FILE_INTERNAL_INFORMATION:
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4848 SBVAL(pdata, 0, file_index);
4849 data_size = 8;
4850 *fixed_portion = 8;
4851 break;
4853 case SMB_FILE_ACCESS_INFORMATION:
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4855 SIVAL(pdata, 0, access_mask);
4856 data_size = 4;
4857 *fixed_portion = 4;
4858 break;
4860 case SMB_FILE_NAME_INFORMATION:
4861 /* Pathname with leading '\'. */
4863 size_t byte_len;
4864 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4866 SIVAL(pdata,0,byte_len);
4867 data_size = 4 + byte_len;
4868 break;
4871 case SMB_FILE_DISPOSITION_INFORMATION:
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4873 data_size = 1;
4874 SCVAL(pdata,0,delete_pending);
4875 *fixed_portion = 1;
4876 break;
4878 case SMB_FILE_POSITION_INFORMATION:
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4880 data_size = 8;
4881 SOFF_T(pdata,0,pos);
4882 *fixed_portion = 8;
4883 break;
4885 case SMB_FILE_MODE_INFORMATION:
4886 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4887 SIVAL(pdata,0,mode);
4888 data_size = 4;
4889 *fixed_portion = 4;
4890 break;
4892 case SMB_FILE_ALIGNMENT_INFORMATION:
4893 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4894 SIVAL(pdata,0,0); /* No alignment needed. */
4895 data_size = 4;
4896 *fixed_portion = 4;
4897 break;
4900 * NT4 server just returns "invalid query" to this - if we try
4901 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4902 * want this. JRA.
4904 /* The first statement above is false - verified using Thursby
4905 * client against NT4 -- gcolley.
4907 case SMB_QUERY_FILE_STREAM_INFO:
4908 case SMB_FILE_STREAM_INFORMATION: {
4909 unsigned int num_streams = 0;
4910 struct stream_struct *streams = NULL;
4912 DEBUG(10,("smbd_do_qfilepathinfo: "
4913 "SMB_FILE_STREAM_INFORMATION\n"));
4915 if (is_ntfs_stream_smb_fname(smb_fname)) {
4916 return NT_STATUS_INVALID_PARAMETER;
4919 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4920 talloc_tos(), &num_streams, &streams);
4922 if (!NT_STATUS_IS_OK(status)) {
4923 DEBUG(10, ("could not get stream info: %s\n",
4924 nt_errstr(status)));
4925 return status;
4928 status = marshall_stream_info(num_streams, streams,
4929 pdata, max_data_bytes,
4930 &data_size);
4932 if (!NT_STATUS_IS_OK(status)) {
4933 DEBUG(10, ("marshall_stream_info failed: %s\n",
4934 nt_errstr(status)));
4935 TALLOC_FREE(streams);
4936 return status;
4939 TALLOC_FREE(streams);
4941 *fixed_portion = 32;
4943 break;
4945 case SMB_QUERY_COMPRESSION_INFO:
4946 case SMB_FILE_COMPRESSION_INFORMATION:
4947 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4948 SOFF_T(pdata,0,file_size);
4949 SIVAL(pdata,8,0); /* ??? */
4950 SIVAL(pdata,12,0); /* ??? */
4951 data_size = 16;
4952 *fixed_portion = 16;
4953 break;
4955 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4956 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4957 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4958 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4959 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4960 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4961 SOFF_T(pdata,32,allocation_size);
4962 SOFF_T(pdata,40,file_size);
4963 SIVAL(pdata,48,mode);
4964 SIVAL(pdata,52,0); /* ??? */
4965 data_size = 56;
4966 *fixed_portion = 56;
4967 break;
4969 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4970 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4971 SIVAL(pdata,0,mode);
4972 SIVAL(pdata,4,0);
4973 data_size = 8;
4974 *fixed_portion = 8;
4975 break;
4978 * CIFS UNIX Extensions.
4981 case SMB_QUERY_FILE_UNIX_BASIC:
4983 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4984 data_size = PTR_DIFF(pdata,(*ppdata));
4986 DEBUG(4,("smbd_do_qfilepathinfo: "
4987 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4988 dump_data(4, (uint8_t *)(*ppdata), data_size);
4990 break;
4992 case SMB_QUERY_FILE_UNIX_INFO2:
4994 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4995 data_size = PTR_DIFF(pdata,(*ppdata));
4998 int i;
4999 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5001 for (i=0; i<100; i++)
5002 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5003 DEBUG(4,("\n"));
5006 break;
5008 case SMB_QUERY_FILE_UNIX_LINK:
5010 int len;
5011 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5013 if (!buffer) {
5014 return NT_STATUS_NO_MEMORY;
5017 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5018 #ifdef S_ISLNK
5019 if(!S_ISLNK(psbuf->st_ex_mode)) {
5020 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5022 #else
5023 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5024 #endif
5025 len = SMB_VFS_READLINK(conn,
5026 smb_fname->base_name,
5027 buffer, PATH_MAX);
5028 if (len == -1) {
5029 return map_nt_error_from_unix(errno);
5031 buffer[len] = 0;
5032 len = srvstr_push(dstart, flags2,
5033 pdata, buffer,
5034 PTR_DIFF(dend, pdata),
5035 STR_TERMINATE);
5036 pdata += len;
5037 data_size = PTR_DIFF(pdata,(*ppdata));
5039 break;
5042 #if defined(HAVE_POSIX_ACLS)
5043 case SMB_QUERY_POSIX_ACL:
5045 SMB_ACL_T file_acl = NULL;
5046 SMB_ACL_T def_acl = NULL;
5047 uint16 num_file_acls = 0;
5048 uint16 num_def_acls = 0;
5050 if (fsp && fsp->fh->fd != -1) {
5051 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5052 talloc_tos());
5053 } else {
5054 file_acl =
5055 SMB_VFS_SYS_ACL_GET_FILE(conn,
5056 smb_fname->base_name,
5057 SMB_ACL_TYPE_ACCESS,
5058 talloc_tos());
5061 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5062 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5063 "not implemented on "
5064 "filesystem containing %s\n",
5065 smb_fname->base_name));
5066 return NT_STATUS_NOT_IMPLEMENTED;
5069 if (S_ISDIR(psbuf->st_ex_mode)) {
5070 if (fsp && fsp->is_directory) {
5071 def_acl =
5072 SMB_VFS_SYS_ACL_GET_FILE(
5073 conn,
5074 fsp->fsp_name->base_name,
5075 SMB_ACL_TYPE_DEFAULT,
5076 talloc_tos());
5077 } else {
5078 def_acl =
5079 SMB_VFS_SYS_ACL_GET_FILE(
5080 conn,
5081 smb_fname->base_name,
5082 SMB_ACL_TYPE_DEFAULT,
5083 talloc_tos());
5085 def_acl = free_empty_sys_acl(conn, def_acl);
5088 num_file_acls = count_acl_entries(conn, file_acl);
5089 num_def_acls = count_acl_entries(conn, def_acl);
5091 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5092 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5093 data_size,
5094 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5095 SMB_POSIX_ACL_HEADER_SIZE) ));
5096 if (file_acl) {
5097 TALLOC_FREE(file_acl);
5099 if (def_acl) {
5100 TALLOC_FREE(def_acl);
5102 return NT_STATUS_BUFFER_TOO_SMALL;
5105 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5106 SSVAL(pdata,2,num_file_acls);
5107 SSVAL(pdata,4,num_def_acls);
5108 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5109 if (file_acl) {
5110 TALLOC_FREE(file_acl);
5112 if (def_acl) {
5113 TALLOC_FREE(def_acl);
5115 return NT_STATUS_INTERNAL_ERROR;
5117 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5118 if (file_acl) {
5119 TALLOC_FREE(file_acl);
5121 if (def_acl) {
5122 TALLOC_FREE(def_acl);
5124 return NT_STATUS_INTERNAL_ERROR;
5127 if (file_acl) {
5128 TALLOC_FREE(file_acl);
5130 if (def_acl) {
5131 TALLOC_FREE(def_acl);
5133 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5134 break;
5136 #endif
5139 case SMB_QUERY_POSIX_LOCK:
5141 uint64_t count;
5142 uint64_t offset;
5143 uint64_t smblctx;
5144 enum brl_type lock_type;
5146 /* We need an open file with a real fd for this. */
5147 if (!fsp || fsp->fh->fd == -1) {
5148 return NT_STATUS_INVALID_LEVEL;
5151 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5152 return NT_STATUS_INVALID_PARAMETER;
5155 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5156 case POSIX_LOCK_TYPE_READ:
5157 lock_type = READ_LOCK;
5158 break;
5159 case POSIX_LOCK_TYPE_WRITE:
5160 lock_type = WRITE_LOCK;
5161 break;
5162 case POSIX_LOCK_TYPE_UNLOCK:
5163 default:
5164 /* There's no point in asking for an unlock... */
5165 return NT_STATUS_INVALID_PARAMETER;
5168 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5169 #if defined(HAVE_LONGLONG)
5170 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5171 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5172 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5173 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5174 #else /* HAVE_LONGLONG */
5175 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5176 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5177 #endif /* HAVE_LONGLONG */
5179 status = query_lock(fsp,
5180 &smblctx,
5181 &count,
5182 &offset,
5183 &lock_type,
5184 POSIX_LOCK);
5186 if (ERROR_WAS_LOCK_DENIED(status)) {
5187 /* Here we need to report who has it locked... */
5188 data_size = POSIX_LOCK_DATA_SIZE;
5190 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5191 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5192 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5193 #if defined(HAVE_LONGLONG)
5194 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5195 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5196 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5197 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5198 #else /* HAVE_LONGLONG */
5199 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5200 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5201 #endif /* HAVE_LONGLONG */
5203 } else if (NT_STATUS_IS_OK(status)) {
5204 /* For success we just return a copy of what we sent
5205 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5206 data_size = POSIX_LOCK_DATA_SIZE;
5207 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5208 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5209 } else {
5210 return status;
5212 break;
5215 default:
5216 return NT_STATUS_INVALID_LEVEL;
5219 *pdata_size = data_size;
5220 return NT_STATUS_OK;
5223 /****************************************************************************
5224 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5225 file name or file id).
5226 ****************************************************************************/
5228 static void call_trans2qfilepathinfo(connection_struct *conn,
5229 struct smb_request *req,
5230 unsigned int tran_call,
5231 char **pparams, int total_params,
5232 char **ppdata, int total_data,
5233 unsigned int max_data_bytes)
5235 char *params = *pparams;
5236 char *pdata = *ppdata;
5237 uint16 info_level;
5238 unsigned int data_size = 0;
5239 unsigned int param_size = 2;
5240 struct smb_filename *smb_fname = NULL;
5241 bool delete_pending = False;
5242 struct timespec write_time_ts;
5243 files_struct *fsp = NULL;
5244 struct file_id fileid;
5245 struct ea_list *ea_list = NULL;
5246 int lock_data_count = 0;
5247 char *lock_data = NULL;
5248 size_t fixed_portion;
5249 NTSTATUS status = NT_STATUS_OK;
5251 if (!params) {
5252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5253 return;
5256 ZERO_STRUCT(write_time_ts);
5258 if (tran_call == TRANSACT2_QFILEINFO) {
5259 if (total_params < 4) {
5260 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5261 return;
5264 if (IS_IPC(conn)) {
5265 call_trans2qpipeinfo(conn, req, tran_call,
5266 pparams, total_params,
5267 ppdata, total_data,
5268 max_data_bytes);
5269 return;
5272 fsp = file_fsp(req, SVAL(params,0));
5273 info_level = SVAL(params,2);
5275 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5277 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5278 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5279 return;
5282 /* Initial check for valid fsp ptr. */
5283 if (!check_fsp_open(conn, req, fsp)) {
5284 return;
5287 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5288 if (smb_fname == NULL) {
5289 reply_nterror(req, NT_STATUS_NO_MEMORY);
5290 return;
5293 if(fsp->fake_file_handle) {
5295 * This is actually for the QUOTA_FAKE_FILE --metze
5298 /* We know this name is ok, it's already passed the checks. */
5300 } else if(fsp->fh->fd == -1) {
5302 * This is actually a QFILEINFO on a directory
5303 * handle (returned from an NT SMB). NT5.0 seems
5304 * to do this call. JRA.
5307 if (INFO_LEVEL_IS_UNIX(info_level)) {
5308 /* Always do lstat for UNIX calls. */
5309 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5310 DEBUG(3,("call_trans2qfilepathinfo: "
5311 "SMB_VFS_LSTAT of %s failed "
5312 "(%s)\n",
5313 smb_fname_str_dbg(smb_fname),
5314 strerror(errno)));
5315 reply_nterror(req,
5316 map_nt_error_from_unix(errno));
5317 return;
5319 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5320 DEBUG(3,("call_trans2qfilepathinfo: "
5321 "SMB_VFS_STAT of %s failed (%s)\n",
5322 smb_fname_str_dbg(smb_fname),
5323 strerror(errno)));
5324 reply_nterror(req,
5325 map_nt_error_from_unix(errno));
5326 return;
5329 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5330 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5331 } else {
5333 * Original code - this is an open file.
5335 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5336 DEBUG(3, ("fstat of %s failed (%s)\n",
5337 fsp_fnum_dbg(fsp), strerror(errno)));
5338 reply_nterror(req,
5339 map_nt_error_from_unix(errno));
5340 return;
5342 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5343 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5346 } else {
5347 uint32_t name_hash;
5348 char *fname = NULL;
5349 uint32_t ucf_flags = 0;
5351 /* qpathinfo */
5352 if (total_params < 7) {
5353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5354 return;
5357 info_level = SVAL(params,0);
5359 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5361 if (INFO_LEVEL_IS_UNIX(info_level)) {
5362 if (!lp_unix_extensions()) {
5363 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5364 return;
5366 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5367 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5368 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5369 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5373 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5374 total_params - 6,
5375 STR_TERMINATE, &status);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 reply_nterror(req, status);
5378 return;
5381 status = filename_convert(req,
5382 conn,
5383 req->flags2 & FLAGS2_DFS_PATHNAMES,
5384 fname,
5385 ucf_flags,
5386 NULL,
5387 &smb_fname);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5390 reply_botherror(req,
5391 NT_STATUS_PATH_NOT_COVERED,
5392 ERRSRV, ERRbadpath);
5393 return;
5395 reply_nterror(req, status);
5396 return;
5399 /* If this is a stream, check if there is a delete_pending. */
5400 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5401 && is_ntfs_stream_smb_fname(smb_fname)) {
5402 struct smb_filename *smb_fname_base;
5404 /* Create an smb_filename with stream_name == NULL. */
5405 smb_fname_base = synthetic_smb_fname(
5406 talloc_tos(), smb_fname->base_name,
5407 NULL, NULL);
5408 if (smb_fname_base == NULL) {
5409 reply_nterror(req, NT_STATUS_NO_MEMORY);
5410 return;
5413 if (INFO_LEVEL_IS_UNIX(info_level)) {
5414 /* Always do lstat for UNIX calls. */
5415 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5416 DEBUG(3,("call_trans2qfilepathinfo: "
5417 "SMB_VFS_LSTAT of %s failed "
5418 "(%s)\n",
5419 smb_fname_str_dbg(smb_fname_base),
5420 strerror(errno)));
5421 TALLOC_FREE(smb_fname_base);
5422 reply_nterror(req,
5423 map_nt_error_from_unix(errno));
5424 return;
5426 } else {
5427 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5428 DEBUG(3,("call_trans2qfilepathinfo: "
5429 "fileinfo of %s failed "
5430 "(%s)\n",
5431 smb_fname_str_dbg(smb_fname_base),
5432 strerror(errno)));
5433 TALLOC_FREE(smb_fname_base);
5434 reply_nterror(req,
5435 map_nt_error_from_unix(errno));
5436 return;
5440 status = file_name_hash(conn,
5441 smb_fname_str_dbg(smb_fname_base),
5442 &name_hash);
5443 if (!NT_STATUS_IS_OK(status)) {
5444 TALLOC_FREE(smb_fname_base);
5445 reply_nterror(req, status);
5446 return;
5449 fileid = vfs_file_id_from_sbuf(conn,
5450 &smb_fname_base->st);
5451 TALLOC_FREE(smb_fname_base);
5452 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5453 if (delete_pending) {
5454 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5455 return;
5459 if (INFO_LEVEL_IS_UNIX(info_level)) {
5460 /* Always do lstat for UNIX calls. */
5461 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5462 DEBUG(3,("call_trans2qfilepathinfo: "
5463 "SMB_VFS_LSTAT of %s failed (%s)\n",
5464 smb_fname_str_dbg(smb_fname),
5465 strerror(errno)));
5466 reply_nterror(req,
5467 map_nt_error_from_unix(errno));
5468 return;
5471 } else {
5472 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5473 DEBUG(3,("call_trans2qfilepathinfo: "
5474 "SMB_VFS_STAT of %s failed (%s)\n",
5475 smb_fname_str_dbg(smb_fname),
5476 strerror(errno)));
5477 reply_nterror(req,
5478 map_nt_error_from_unix(errno));
5479 return;
5483 status = file_name_hash(conn,
5484 smb_fname_str_dbg(smb_fname),
5485 &name_hash);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 reply_nterror(req, status);
5488 return;
5491 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5492 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5493 if (delete_pending) {
5494 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5495 return;
5499 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5500 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5501 fsp_fnum_dbg(fsp),
5502 info_level,tran_call,total_data));
5504 /* Pull out any data sent here before we realloc. */
5505 switch (info_level) {
5506 case SMB_INFO_QUERY_EAS_FROM_LIST:
5508 /* Pull any EA list from the data portion. */
5509 uint32 ea_size;
5511 if (total_data < 4) {
5512 reply_nterror(
5513 req, NT_STATUS_INVALID_PARAMETER);
5514 return;
5516 ea_size = IVAL(pdata,0);
5518 if (total_data > 0 && ea_size != total_data) {
5519 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5520 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5521 reply_nterror(
5522 req, NT_STATUS_INVALID_PARAMETER);
5523 return;
5526 if (!lp_ea_support(SNUM(conn))) {
5527 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5528 return;
5531 /* Pull out the list of names. */
5532 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5533 if (!ea_list) {
5534 reply_nterror(
5535 req, NT_STATUS_INVALID_PARAMETER);
5536 return;
5538 break;
5541 case SMB_QUERY_POSIX_LOCK:
5543 if (fsp == NULL || fsp->fh->fd == -1) {
5544 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5545 return;
5548 if (total_data != POSIX_LOCK_DATA_SIZE) {
5549 reply_nterror(
5550 req, NT_STATUS_INVALID_PARAMETER);
5551 return;
5554 /* Copy the lock range data. */
5555 lock_data = (char *)talloc_memdup(
5556 req, pdata, total_data);
5557 if (!lock_data) {
5558 reply_nterror(req, NT_STATUS_NO_MEMORY);
5559 return;
5561 lock_data_count = total_data;
5563 default:
5564 break;
5567 *pparams = (char *)SMB_REALLOC(*pparams,2);
5568 if (*pparams == NULL) {
5569 reply_nterror(req, NT_STATUS_NO_MEMORY);
5570 return;
5572 params = *pparams;
5573 SSVAL(params,0,0);
5576 * draft-leach-cifs-v1-spec-02.txt
5577 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5578 * says:
5580 * The requested information is placed in the Data portion of the
5581 * transaction response. For the information levels greater than 0x100,
5582 * the transaction response has 1 parameter word which should be
5583 * ignored by the client.
5585 * However Windows only follows this rule for the IS_NAME_VALID call.
5587 switch (info_level) {
5588 case SMB_INFO_IS_NAME_VALID:
5589 param_size = 0;
5590 break;
5593 if ((info_level & 0xFF00) == 0xFF00) {
5595 * We use levels that start with 0xFF00
5596 * internally to represent SMB2 specific levels
5598 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5599 return;
5602 status = smbd_do_qfilepathinfo(conn, req, info_level,
5603 fsp, smb_fname,
5604 delete_pending, write_time_ts,
5605 ea_list,
5606 lock_data_count, lock_data,
5607 req->flags2, max_data_bytes,
5608 &fixed_portion,
5609 ppdata, &data_size);
5610 if (!NT_STATUS_IS_OK(status)) {
5611 reply_nterror(req, status);
5612 return;
5614 if (fixed_portion > max_data_bytes) {
5615 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5616 return;
5619 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5620 max_data_bytes);
5622 return;
5625 /****************************************************************************
5626 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5627 code.
5628 ****************************************************************************/
5630 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5631 connection_struct *conn,
5632 struct smb_request *req,
5633 bool overwrite_if_exists,
5634 const struct smb_filename *smb_fname_old,
5635 struct smb_filename *smb_fname_new)
5637 NTSTATUS status = NT_STATUS_OK;
5639 /* source must already exist. */
5640 if (!VALID_STAT(smb_fname_old->st)) {
5641 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5644 if (VALID_STAT(smb_fname_new->st)) {
5645 if (overwrite_if_exists) {
5646 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5647 return NT_STATUS_FILE_IS_A_DIRECTORY;
5649 status = unlink_internals(conn,
5650 req,
5651 FILE_ATTRIBUTE_NORMAL,
5652 smb_fname_new,
5653 false);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 return status;
5657 } else {
5658 /* Disallow if newname already exists. */
5659 return NT_STATUS_OBJECT_NAME_COLLISION;
5663 /* No links from a directory. */
5664 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5665 return NT_STATUS_FILE_IS_A_DIRECTORY;
5668 /* Setting a hardlink to/from a stream isn't currently supported. */
5669 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5670 is_ntfs_stream_smb_fname(smb_fname_new)) {
5671 return NT_STATUS_INVALID_PARAMETER;
5674 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5675 smb_fname_old->base_name, smb_fname_new->base_name));
5677 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5678 smb_fname_new->base_name) != 0) {
5679 status = map_nt_error_from_unix(errno);
5680 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5681 nt_errstr(status), smb_fname_old->base_name,
5682 smb_fname_new->base_name));
5684 return status;
5687 /****************************************************************************
5688 Deal with setting the time from any of the setfilepathinfo functions.
5689 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5690 calling this function.
5691 ****************************************************************************/
5693 NTSTATUS smb_set_file_time(connection_struct *conn,
5694 files_struct *fsp,
5695 const struct smb_filename *smb_fname,
5696 struct smb_file_time *ft,
5697 bool setting_write_time)
5699 struct smb_filename smb_fname_base;
5700 uint32 action =
5701 FILE_NOTIFY_CHANGE_LAST_ACCESS
5702 |FILE_NOTIFY_CHANGE_LAST_WRITE
5703 |FILE_NOTIFY_CHANGE_CREATION;
5705 if (!VALID_STAT(smb_fname->st)) {
5706 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5709 /* get some defaults (no modifications) if any info is zero or -1. */
5710 if (null_timespec(ft->create_time)) {
5711 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5714 if (null_timespec(ft->atime)) {
5715 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5718 if (null_timespec(ft->mtime)) {
5719 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5722 if (!setting_write_time) {
5723 /* ft->mtime comes from change time, not write time. */
5724 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5727 /* Ensure the resolution is the correct for
5728 * what we can store on this filesystem. */
5730 round_timespec(conn->ts_res, &ft->create_time);
5731 round_timespec(conn->ts_res, &ft->ctime);
5732 round_timespec(conn->ts_res, &ft->atime);
5733 round_timespec(conn->ts_res, &ft->mtime);
5735 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5736 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5737 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5738 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5739 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5740 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5741 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5742 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5744 if (setting_write_time) {
5746 * This was a Windows setfileinfo on an open file.
5747 * NT does this a lot. We also need to
5748 * set the time here, as it can be read by
5749 * FindFirst/FindNext and with the patch for bug #2045
5750 * in smbd/fileio.c it ensures that this timestamp is
5751 * kept sticky even after a write. We save the request
5752 * away and will set it on file close and after a write. JRA.
5755 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5756 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5758 if (fsp != NULL) {
5759 if (fsp->base_fsp) {
5760 set_sticky_write_time_fsp(fsp->base_fsp,
5761 ft->mtime);
5762 } else {
5763 set_sticky_write_time_fsp(fsp, ft->mtime);
5765 } else {
5766 set_sticky_write_time_path(
5767 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5768 ft->mtime);
5772 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5774 /* Always call ntimes on the base, even if a stream was passed in. */
5775 smb_fname_base = *smb_fname;
5776 smb_fname_base.stream_name = NULL;
5778 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5779 return map_nt_error_from_unix(errno);
5782 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5783 smb_fname->base_name);
5784 return NT_STATUS_OK;
5787 /****************************************************************************
5788 Deal with setting the dosmode from any of the setfilepathinfo functions.
5789 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5790 done before calling this function.
5791 ****************************************************************************/
5793 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5794 const struct smb_filename *smb_fname,
5795 uint32 dosmode)
5797 struct smb_filename *smb_fname_base;
5798 NTSTATUS status;
5800 if (!VALID_STAT(smb_fname->st)) {
5801 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5804 /* Always operate on the base_name, even if a stream was passed in. */
5805 smb_fname_base = synthetic_smb_fname(
5806 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5807 if (smb_fname_base == NULL) {
5808 return NT_STATUS_NO_MEMORY;
5811 if (dosmode) {
5812 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5813 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5814 } else {
5815 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5819 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5821 /* check the mode isn't different, before changing it */
5822 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5823 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5824 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5825 (unsigned int)dosmode));
5827 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5828 false)) {
5829 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5830 "%s failed (%s)\n",
5831 smb_fname_str_dbg(smb_fname_base),
5832 strerror(errno)));
5833 status = map_nt_error_from_unix(errno);
5834 goto out;
5837 status = NT_STATUS_OK;
5838 out:
5839 TALLOC_FREE(smb_fname_base);
5840 return status;
5843 /****************************************************************************
5844 Deal with setting the size from any of the setfilepathinfo functions.
5845 ****************************************************************************/
5847 static NTSTATUS smb_set_file_size(connection_struct *conn,
5848 struct smb_request *req,
5849 files_struct *fsp,
5850 const struct smb_filename *smb_fname,
5851 const SMB_STRUCT_STAT *psbuf,
5852 off_t size,
5853 bool fail_after_createfile)
5855 NTSTATUS status = NT_STATUS_OK;
5856 struct smb_filename *smb_fname_tmp = NULL;
5857 files_struct *new_fsp = NULL;
5859 if (!VALID_STAT(*psbuf)) {
5860 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5863 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5865 if (size == get_file_size_stat(psbuf)) {
5866 return NT_STATUS_OK;
5869 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5870 smb_fname_str_dbg(smb_fname), (double)size));
5872 if (fsp && fsp->fh->fd != -1) {
5873 /* Handle based call. */
5874 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5875 return NT_STATUS_ACCESS_DENIED;
5878 if (vfs_set_filelen(fsp, size) == -1) {
5879 return map_nt_error_from_unix(errno);
5881 trigger_write_time_update_immediate(fsp);
5882 return NT_STATUS_OK;
5885 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5886 if (smb_fname_tmp == NULL) {
5887 return NT_STATUS_NO_MEMORY;
5890 smb_fname_tmp->st = *psbuf;
5892 status = SMB_VFS_CREATE_FILE(
5893 conn, /* conn */
5894 req, /* req */
5895 0, /* root_dir_fid */
5896 smb_fname_tmp, /* fname */
5897 FILE_WRITE_DATA, /* access_mask */
5898 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5899 FILE_SHARE_DELETE),
5900 FILE_OPEN, /* create_disposition*/
5901 0, /* create_options */
5902 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5903 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5904 0, /* allocation_size */
5905 0, /* private_flags */
5906 NULL, /* sd */
5907 NULL, /* ea_list */
5908 &new_fsp, /* result */
5909 NULL); /* pinfo */
5911 TALLOC_FREE(smb_fname_tmp);
5913 if (!NT_STATUS_IS_OK(status)) {
5914 /* NB. We check for open_was_deferred in the caller. */
5915 return status;
5918 /* See RAW-SFILEINFO-END-OF-FILE */
5919 if (fail_after_createfile) {
5920 close_file(req, new_fsp,NORMAL_CLOSE);
5921 return NT_STATUS_INVALID_LEVEL;
5924 if (vfs_set_filelen(new_fsp, size) == -1) {
5925 status = map_nt_error_from_unix(errno);
5926 close_file(req, new_fsp,NORMAL_CLOSE);
5927 return status;
5930 trigger_write_time_update_immediate(new_fsp);
5931 close_file(req, new_fsp,NORMAL_CLOSE);
5932 return NT_STATUS_OK;
5935 /****************************************************************************
5936 Deal with SMB_INFO_SET_EA.
5937 ****************************************************************************/
5939 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5940 const char *pdata,
5941 int total_data,
5942 files_struct *fsp,
5943 const struct smb_filename *smb_fname)
5945 struct ea_list *ea_list = NULL;
5946 TALLOC_CTX *ctx = NULL;
5947 NTSTATUS status = NT_STATUS_OK;
5949 if (total_data < 10) {
5951 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5952 length. They seem to have no effect. Bug #3212. JRA */
5954 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5955 /* We're done. We only get EA info in this call. */
5956 return NT_STATUS_OK;
5959 return NT_STATUS_INVALID_PARAMETER;
5962 if (IVAL(pdata,0) > total_data) {
5963 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5964 IVAL(pdata,0), (unsigned int)total_data));
5965 return NT_STATUS_INVALID_PARAMETER;
5968 ctx = talloc_tos();
5969 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5970 if (!ea_list) {
5971 return NT_STATUS_INVALID_PARAMETER;
5974 status = set_ea(conn, fsp, smb_fname, ea_list);
5976 return status;
5979 /****************************************************************************
5980 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5981 ****************************************************************************/
5983 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5984 const char *pdata,
5985 int total_data,
5986 files_struct *fsp)
5988 struct ea_list *ea_list = NULL;
5989 NTSTATUS status;
5991 if (!fsp) {
5992 return NT_STATUS_INVALID_HANDLE;
5995 if (!lp_ea_support(SNUM(conn))) {
5996 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5997 "EA's not supported.\n",
5998 (unsigned int)total_data));
5999 return NT_STATUS_EAS_NOT_SUPPORTED;
6002 if (total_data < 10) {
6003 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6004 "too small.\n",
6005 (unsigned int)total_data));
6006 return NT_STATUS_INVALID_PARAMETER;
6009 ea_list = read_nttrans_ea_list(talloc_tos(),
6010 pdata,
6011 total_data);
6013 if (!ea_list) {
6014 return NT_STATUS_INVALID_PARAMETER;
6017 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6019 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6020 smb_fname_str_dbg(fsp->fsp_name),
6021 nt_errstr(status) ));
6023 return status;
6027 /****************************************************************************
6028 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6029 ****************************************************************************/
6031 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6032 const char *pdata,
6033 int total_data,
6034 files_struct *fsp,
6035 struct smb_filename *smb_fname)
6037 NTSTATUS status = NT_STATUS_OK;
6038 bool delete_on_close;
6039 uint32 dosmode = 0;
6041 if (total_data < 1) {
6042 return NT_STATUS_INVALID_PARAMETER;
6045 if (fsp == NULL) {
6046 return NT_STATUS_INVALID_HANDLE;
6049 delete_on_close = (CVAL(pdata,0) ? True : False);
6050 dosmode = dos_mode(conn, smb_fname);
6052 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6053 "delete_on_close = %u\n",
6054 smb_fname_str_dbg(smb_fname),
6055 (unsigned int)dosmode,
6056 (unsigned int)delete_on_close ));
6058 if (delete_on_close) {
6059 status = can_set_delete_on_close(fsp, dosmode);
6060 if (!NT_STATUS_IS_OK(status)) {
6061 return status;
6065 /* The set is across all open files on this dev/inode pair. */
6066 if (!set_delete_on_close(fsp, delete_on_close,
6067 conn->session_info->security_token,
6068 conn->session_info->unix_token)) {
6069 return NT_STATUS_ACCESS_DENIED;
6071 return NT_STATUS_OK;
6074 /****************************************************************************
6075 Deal with SMB_FILE_POSITION_INFORMATION.
6076 ****************************************************************************/
6078 static NTSTATUS smb_file_position_information(connection_struct *conn,
6079 const char *pdata,
6080 int total_data,
6081 files_struct *fsp)
6083 uint64_t position_information;
6085 if (total_data < 8) {
6086 return NT_STATUS_INVALID_PARAMETER;
6089 if (fsp == NULL) {
6090 /* Ignore on pathname based set. */
6091 return NT_STATUS_OK;
6094 position_information = (uint64_t)IVAL(pdata,0);
6095 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6097 DEBUG(10,("smb_file_position_information: Set file position "
6098 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6099 (double)position_information));
6100 fsp->fh->position_information = position_information;
6101 return NT_STATUS_OK;
6104 /****************************************************************************
6105 Deal with SMB_FILE_MODE_INFORMATION.
6106 ****************************************************************************/
6108 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6109 const char *pdata,
6110 int total_data)
6112 uint32 mode;
6114 if (total_data < 4) {
6115 return NT_STATUS_INVALID_PARAMETER;
6117 mode = IVAL(pdata,0);
6118 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6119 return NT_STATUS_INVALID_PARAMETER;
6121 return NT_STATUS_OK;
6124 /****************************************************************************
6125 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6126 ****************************************************************************/
6128 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6129 struct smb_request *req,
6130 const char *pdata,
6131 int total_data,
6132 const struct smb_filename *smb_fname)
6134 char *link_target = NULL;
6135 const char *newname = smb_fname->base_name;
6136 TALLOC_CTX *ctx = talloc_tos();
6138 /* Set a symbolic link. */
6139 /* Don't allow this if follow links is false. */
6141 if (total_data == 0) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 if (!lp_symlinks(SNUM(conn))) {
6146 return NT_STATUS_ACCESS_DENIED;
6149 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6150 total_data, STR_TERMINATE);
6152 if (!link_target) {
6153 return NT_STATUS_INVALID_PARAMETER;
6156 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6157 newname, link_target ));
6159 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6160 return map_nt_error_from_unix(errno);
6163 return NT_STATUS_OK;
6166 /****************************************************************************
6167 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6168 ****************************************************************************/
6170 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6171 struct smb_request *req,
6172 const char *pdata, int total_data,
6173 struct smb_filename *smb_fname_new)
6175 char *oldname = NULL;
6176 struct smb_filename *smb_fname_old = NULL;
6177 TALLOC_CTX *ctx = talloc_tos();
6178 NTSTATUS status = NT_STATUS_OK;
6180 /* Set a hard link. */
6181 if (total_data == 0) {
6182 return NT_STATUS_INVALID_PARAMETER;
6185 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6186 total_data, STR_TERMINATE, &status);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 return status;
6191 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6192 smb_fname_str_dbg(smb_fname_new), oldname));
6194 status = filename_convert(ctx,
6195 conn,
6196 req->flags2 & FLAGS2_DFS_PATHNAMES,
6197 oldname,
6199 NULL,
6200 &smb_fname_old);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 return status;
6205 return hardlink_internals(ctx, conn, req, false,
6206 smb_fname_old, smb_fname_new);
6209 /****************************************************************************
6210 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6211 ****************************************************************************/
6213 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6214 struct smb_request *req,
6215 const char *pdata,
6216 int total_data,
6217 files_struct *fsp,
6218 struct smb_filename *smb_fname_src)
6220 bool overwrite;
6221 uint32_t len;
6222 char *newname = NULL;
6223 struct smb_filename *smb_fname_dst = NULL;
6224 NTSTATUS status = NT_STATUS_OK;
6225 TALLOC_CTX *ctx = talloc_tos();
6227 if (!fsp) {
6228 return NT_STATUS_INVALID_HANDLE;
6231 if (total_data < 20) {
6232 return NT_STATUS_INVALID_PARAMETER;
6235 overwrite = (CVAL(pdata,0) ? True : False);
6236 len = IVAL(pdata,16);
6238 if (len > (total_data - 20) || (len == 0)) {
6239 return NT_STATUS_INVALID_PARAMETER;
6242 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6243 &pdata[20], len, STR_TERMINATE,
6244 &status);
6245 if (!NT_STATUS_IS_OK(status)) {
6246 return status;
6249 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6250 newname));
6252 status = filename_convert(ctx,
6253 conn,
6254 req->flags2 & FLAGS2_DFS_PATHNAMES,
6255 newname,
6256 UCF_SAVE_LCOMP,
6257 NULL,
6258 &smb_fname_dst);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 return status;
6263 if (fsp->base_fsp) {
6264 /* newname must be a stream name. */
6265 if (newname[0] != ':') {
6266 return NT_STATUS_NOT_SUPPORTED;
6269 /* Create an smb_fname to call rename_internals_fsp() with. */
6270 smb_fname_dst = synthetic_smb_fname(
6271 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6272 newname, NULL);
6273 if (smb_fname_dst == NULL) {
6274 status = NT_STATUS_NO_MEMORY;
6275 goto out;
6279 * Set the original last component, since
6280 * rename_internals_fsp() requires it.
6282 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6283 newname);
6284 if (smb_fname_dst->original_lcomp == NULL) {
6285 status = NT_STATUS_NO_MEMORY;
6286 goto out;
6291 DEBUG(10,("smb2_file_rename_information: "
6292 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6293 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6294 smb_fname_str_dbg(smb_fname_dst)));
6295 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6296 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6297 overwrite);
6299 out:
6300 TALLOC_FREE(smb_fname_dst);
6301 return status;
6304 static NTSTATUS smb_file_link_information(connection_struct *conn,
6305 struct smb_request *req,
6306 const char *pdata,
6307 int total_data,
6308 files_struct *fsp,
6309 struct smb_filename *smb_fname_src)
6311 bool overwrite;
6312 uint32_t len;
6313 char *newname = NULL;
6314 struct smb_filename *smb_fname_dst = NULL;
6315 NTSTATUS status = NT_STATUS_OK;
6316 TALLOC_CTX *ctx = talloc_tos();
6318 if (!fsp) {
6319 return NT_STATUS_INVALID_HANDLE;
6322 if (total_data < 20) {
6323 return NT_STATUS_INVALID_PARAMETER;
6326 overwrite = (CVAL(pdata,0) ? true : false);
6327 len = IVAL(pdata,16);
6329 if (len > (total_data - 20) || (len == 0)) {
6330 return NT_STATUS_INVALID_PARAMETER;
6333 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6334 &pdata[20], len, STR_TERMINATE,
6335 &status);
6336 if (!NT_STATUS_IS_OK(status)) {
6337 return status;
6340 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6341 newname));
6343 status = filename_convert(ctx,
6344 conn,
6345 req->flags2 & FLAGS2_DFS_PATHNAMES,
6346 newname,
6347 UCF_SAVE_LCOMP,
6348 NULL,
6349 &smb_fname_dst);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 return status;
6354 if (fsp->base_fsp) {
6355 /* No stream names. */
6356 return NT_STATUS_NOT_SUPPORTED;
6359 DEBUG(10,("smb_file_link_information: "
6360 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6361 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6362 smb_fname_str_dbg(smb_fname_dst)));
6363 status = hardlink_internals(ctx,
6364 conn,
6365 req,
6366 overwrite,
6367 fsp->fsp_name,
6368 smb_fname_dst);
6370 TALLOC_FREE(smb_fname_dst);
6371 return status;
6374 /****************************************************************************
6375 Deal with SMB_FILE_RENAME_INFORMATION.
6376 ****************************************************************************/
6378 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6379 struct smb_request *req,
6380 const char *pdata,
6381 int total_data,
6382 files_struct *fsp,
6383 struct smb_filename *smb_fname_src)
6385 bool overwrite;
6386 uint32 root_fid;
6387 uint32 len;
6388 char *newname = NULL;
6389 struct smb_filename *smb_fname_dst = NULL;
6390 bool dest_has_wcard = False;
6391 NTSTATUS status = NT_STATUS_OK;
6392 char *p;
6393 TALLOC_CTX *ctx = talloc_tos();
6395 if (total_data < 13) {
6396 return NT_STATUS_INVALID_PARAMETER;
6399 overwrite = (CVAL(pdata,0) ? True : False);
6400 root_fid = IVAL(pdata,4);
6401 len = IVAL(pdata,8);
6403 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6404 return NT_STATUS_INVALID_PARAMETER;
6407 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6408 len, 0, &status,
6409 &dest_has_wcard);
6410 if (!NT_STATUS_IS_OK(status)) {
6411 return status;
6414 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6415 newname));
6417 status = resolve_dfspath_wcard(ctx, conn,
6418 req->flags2 & FLAGS2_DFS_PATHNAMES,
6419 newname,
6420 true,
6421 !conn->sconn->using_smb2,
6422 &newname,
6423 &dest_has_wcard);
6424 if (!NT_STATUS_IS_OK(status)) {
6425 return status;
6428 /* Check the new name has no '/' characters. */
6429 if (strchr_m(newname, '/')) {
6430 return NT_STATUS_NOT_SUPPORTED;
6433 if (fsp && fsp->base_fsp) {
6434 /* newname must be a stream name. */
6435 if (newname[0] != ':') {
6436 return NT_STATUS_NOT_SUPPORTED;
6439 /* Create an smb_fname to call rename_internals_fsp() with. */
6440 smb_fname_dst = synthetic_smb_fname(
6441 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6442 newname, NULL);
6443 if (smb_fname_dst == NULL) {
6444 status = NT_STATUS_NO_MEMORY;
6445 goto out;
6449 * Set the original last component, since
6450 * rename_internals_fsp() requires it.
6452 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6453 newname);
6454 if (smb_fname_dst->original_lcomp == NULL) {
6455 status = NT_STATUS_NO_MEMORY;
6456 goto out;
6459 } else {
6461 * Build up an smb_fname_dst based on the filename passed in.
6462 * We basically just strip off the last component, and put on
6463 * the newname instead.
6465 char *base_name = NULL;
6467 /* newname must *not* be a stream name. */
6468 if (newname[0] == ':') {
6469 return NT_STATUS_NOT_SUPPORTED;
6473 * Strip off the last component (filename) of the path passed
6474 * in.
6476 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6477 if (!base_name) {
6478 return NT_STATUS_NO_MEMORY;
6480 p = strrchr_m(base_name, '/');
6481 if (p) {
6482 p[1] = '\0';
6483 } else {
6484 base_name = talloc_strdup(ctx, "");
6485 if (!base_name) {
6486 return NT_STATUS_NO_MEMORY;
6489 /* Append the new name. */
6490 base_name = talloc_asprintf_append(base_name,
6491 "%s",
6492 newname);
6493 if (!base_name) {
6494 return NT_STATUS_NO_MEMORY;
6497 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6498 (UCF_SAVE_LCOMP |
6499 (dest_has_wcard ?
6500 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6501 0)));
6503 /* If an error we expect this to be
6504 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6506 if (!NT_STATUS_IS_OK(status)) {
6507 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6508 status)) {
6509 goto out;
6511 /* Create an smb_fname to call rename_internals_fsp() */
6512 smb_fname_dst = synthetic_smb_fname(
6513 ctx, base_name, NULL, NULL);
6514 if (smb_fname_dst == NULL) {
6515 status = NT_STATUS_NO_MEMORY;
6516 goto out;
6521 if (fsp) {
6522 DEBUG(10,("smb_file_rename_information: "
6523 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6524 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6525 smb_fname_str_dbg(smb_fname_dst)));
6526 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6527 overwrite);
6528 } else {
6529 DEBUG(10,("smb_file_rename_information: "
6530 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6531 smb_fname_str_dbg(smb_fname_src),
6532 smb_fname_str_dbg(smb_fname_dst)));
6533 status = rename_internals(ctx, conn, req, smb_fname_src,
6534 smb_fname_dst, 0, overwrite, false,
6535 dest_has_wcard,
6536 FILE_WRITE_ATTRIBUTES);
6538 out:
6539 TALLOC_FREE(smb_fname_dst);
6540 return status;
6543 /****************************************************************************
6544 Deal with SMB_SET_POSIX_ACL.
6545 ****************************************************************************/
6547 #if defined(HAVE_POSIX_ACLS)
6548 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6549 const char *pdata,
6550 int total_data,
6551 files_struct *fsp,
6552 const struct smb_filename *smb_fname)
6554 uint16 posix_acl_version;
6555 uint16 num_file_acls;
6556 uint16 num_def_acls;
6557 bool valid_file_acls = True;
6558 bool valid_def_acls = True;
6560 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6561 return NT_STATUS_INVALID_PARAMETER;
6563 posix_acl_version = SVAL(pdata,0);
6564 num_file_acls = SVAL(pdata,2);
6565 num_def_acls = SVAL(pdata,4);
6567 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6568 valid_file_acls = False;
6569 num_file_acls = 0;
6572 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6573 valid_def_acls = False;
6574 num_def_acls = 0;
6577 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6578 return NT_STATUS_INVALID_PARAMETER;
6581 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6582 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6587 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6588 (unsigned int)num_file_acls,
6589 (unsigned int)num_def_acls));
6591 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6592 smb_fname->base_name, num_file_acls,
6593 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6594 return map_nt_error_from_unix(errno);
6597 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6598 smb_fname->base_name, &smb_fname->st, num_def_acls,
6599 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6600 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6601 return map_nt_error_from_unix(errno);
6603 return NT_STATUS_OK;
6605 #endif
6607 /****************************************************************************
6608 Deal with SMB_SET_POSIX_LOCK.
6609 ****************************************************************************/
6611 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6612 struct smb_request *req,
6613 const char *pdata,
6614 int total_data,
6615 files_struct *fsp)
6617 uint64_t count;
6618 uint64_t offset;
6619 uint64_t smblctx;
6620 bool blocking_lock = False;
6621 enum brl_type lock_type;
6623 NTSTATUS status = NT_STATUS_OK;
6625 if (fsp == NULL || fsp->fh->fd == -1) {
6626 return NT_STATUS_INVALID_HANDLE;
6629 if (total_data != POSIX_LOCK_DATA_SIZE) {
6630 return NT_STATUS_INVALID_PARAMETER;
6633 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6634 case POSIX_LOCK_TYPE_READ:
6635 lock_type = READ_LOCK;
6636 break;
6637 case POSIX_LOCK_TYPE_WRITE:
6638 /* Return the right POSIX-mappable error code for files opened read-only. */
6639 if (!fsp->can_write) {
6640 return NT_STATUS_INVALID_HANDLE;
6642 lock_type = WRITE_LOCK;
6643 break;
6644 case POSIX_LOCK_TYPE_UNLOCK:
6645 lock_type = UNLOCK_LOCK;
6646 break;
6647 default:
6648 return NT_STATUS_INVALID_PARAMETER;
6651 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6652 blocking_lock = False;
6653 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6654 blocking_lock = True;
6655 } else {
6656 return NT_STATUS_INVALID_PARAMETER;
6659 if (!lp_blocking_locks(SNUM(conn))) {
6660 blocking_lock = False;
6663 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6664 #if defined(HAVE_LONGLONG)
6665 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6666 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6667 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6668 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6669 #else /* HAVE_LONGLONG */
6670 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6671 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6672 #endif /* HAVE_LONGLONG */
6674 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6675 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6676 fsp_str_dbg(fsp),
6677 (unsigned int)lock_type,
6678 (unsigned long long)smblctx,
6679 (double)count,
6680 (double)offset ));
6682 if (lock_type == UNLOCK_LOCK) {
6683 status = do_unlock(req->sconn->msg_ctx,
6684 fsp,
6685 smblctx,
6686 count,
6687 offset,
6688 POSIX_LOCK);
6689 } else {
6690 uint64_t block_smblctx;
6692 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6693 fsp,
6694 smblctx,
6695 count,
6696 offset,
6697 lock_type,
6698 POSIX_LOCK,
6699 blocking_lock,
6700 &status,
6701 &block_smblctx,
6702 NULL);
6704 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6706 * A blocking lock was requested. Package up
6707 * this smb into a queued request and push it
6708 * onto the blocking lock queue.
6710 if(push_blocking_lock_request(br_lck,
6711 req,
6712 fsp,
6713 -1, /* infinite timeout. */
6715 smblctx,
6716 lock_type,
6717 POSIX_LOCK,
6718 offset,
6719 count,
6720 block_smblctx)) {
6721 TALLOC_FREE(br_lck);
6722 return status;
6725 TALLOC_FREE(br_lck);
6728 return status;
6731 /****************************************************************************
6732 Deal with SMB_SET_FILE_BASIC_INFO.
6733 ****************************************************************************/
6735 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6736 const char *pdata,
6737 int total_data,
6738 files_struct *fsp,
6739 const struct smb_filename *smb_fname)
6741 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6742 struct smb_file_time ft;
6743 uint32 dosmode = 0;
6744 NTSTATUS status = NT_STATUS_OK;
6746 ZERO_STRUCT(ft);
6748 if (total_data < 36) {
6749 return NT_STATUS_INVALID_PARAMETER;
6752 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6753 if (!NT_STATUS_IS_OK(status)) {
6754 return status;
6757 /* Set the attributes */
6758 dosmode = IVAL(pdata,32);
6759 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6760 if (!NT_STATUS_IS_OK(status)) {
6761 return status;
6764 /* create time */
6765 ft.create_time = interpret_long_date(pdata);
6767 /* access time */
6768 ft.atime = interpret_long_date(pdata+8);
6770 /* write time. */
6771 ft.mtime = interpret_long_date(pdata+16);
6773 /* change time. */
6774 ft.ctime = interpret_long_date(pdata+24);
6776 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6777 smb_fname_str_dbg(smb_fname)));
6779 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6780 true);
6783 /****************************************************************************
6784 Deal with SMB_INFO_STANDARD.
6785 ****************************************************************************/
6787 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6788 const char *pdata,
6789 int total_data,
6790 files_struct *fsp,
6791 const struct smb_filename *smb_fname)
6793 NTSTATUS status;
6794 struct smb_file_time ft;
6796 ZERO_STRUCT(ft);
6798 if (total_data < 12) {
6799 return NT_STATUS_INVALID_PARAMETER;
6802 /* create time */
6803 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6804 /* access time */
6805 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6806 /* write time */
6807 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6809 DEBUG(10,("smb_set_info_standard: file %s\n",
6810 smb_fname_str_dbg(smb_fname)));
6812 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6813 if (!NT_STATUS_IS_OK(status)) {
6814 return status;
6817 return smb_set_file_time(conn,
6818 fsp,
6819 smb_fname,
6820 &ft,
6821 true);
6824 /****************************************************************************
6825 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6826 ****************************************************************************/
6828 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6829 struct smb_request *req,
6830 const char *pdata,
6831 int total_data,
6832 files_struct *fsp,
6833 struct smb_filename *smb_fname)
6835 uint64_t allocation_size = 0;
6836 NTSTATUS status = NT_STATUS_OK;
6837 files_struct *new_fsp = NULL;
6839 if (!VALID_STAT(smb_fname->st)) {
6840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6843 if (total_data < 8) {
6844 return NT_STATUS_INVALID_PARAMETER;
6847 allocation_size = (uint64_t)IVAL(pdata,0);
6848 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6849 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6850 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6851 (double)allocation_size));
6853 if (allocation_size) {
6854 allocation_size = smb_roundup(conn, allocation_size);
6857 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6858 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6859 (double)allocation_size));
6861 if (fsp && fsp->fh->fd != -1) {
6862 /* Open file handle. */
6863 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6864 return NT_STATUS_ACCESS_DENIED;
6867 /* Only change if needed. */
6868 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6869 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6870 return map_nt_error_from_unix(errno);
6873 /* But always update the time. */
6875 * This is equivalent to a write. Ensure it's seen immediately
6876 * if there are no pending writes.
6878 trigger_write_time_update_immediate(fsp);
6879 return NT_STATUS_OK;
6882 /* Pathname or stat or directory file. */
6883 status = SMB_VFS_CREATE_FILE(
6884 conn, /* conn */
6885 req, /* req */
6886 0, /* root_dir_fid */
6887 smb_fname, /* fname */
6888 FILE_WRITE_DATA, /* access_mask */
6889 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6890 FILE_SHARE_DELETE),
6891 FILE_OPEN, /* create_disposition*/
6892 0, /* create_options */
6893 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6894 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6895 0, /* allocation_size */
6896 0, /* private_flags */
6897 NULL, /* sd */
6898 NULL, /* ea_list */
6899 &new_fsp, /* result */
6900 NULL); /* pinfo */
6902 if (!NT_STATUS_IS_OK(status)) {
6903 /* NB. We check for open_was_deferred in the caller. */
6904 return status;
6907 /* Only change if needed. */
6908 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6909 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6910 status = map_nt_error_from_unix(errno);
6911 close_file(req, new_fsp, NORMAL_CLOSE);
6912 return status;
6916 /* Changing the allocation size should set the last mod time. */
6918 * This is equivalent to a write. Ensure it's seen immediately
6919 * if there are no pending writes.
6921 trigger_write_time_update_immediate(new_fsp);
6923 close_file(req, new_fsp, NORMAL_CLOSE);
6924 return NT_STATUS_OK;
6927 /****************************************************************************
6928 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6929 ****************************************************************************/
6931 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6932 struct smb_request *req,
6933 const char *pdata,
6934 int total_data,
6935 files_struct *fsp,
6936 const struct smb_filename *smb_fname,
6937 bool fail_after_createfile)
6939 off_t size;
6941 if (total_data < 8) {
6942 return NT_STATUS_INVALID_PARAMETER;
6945 size = IVAL(pdata,0);
6946 size |= (((off_t)IVAL(pdata,4)) << 32);
6947 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6948 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6949 (double)size));
6951 return smb_set_file_size(conn, req,
6952 fsp,
6953 smb_fname,
6954 &smb_fname->st,
6955 size,
6956 fail_after_createfile);
6959 /****************************************************************************
6960 Allow a UNIX info mknod.
6961 ****************************************************************************/
6963 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6964 const char *pdata,
6965 int total_data,
6966 const struct smb_filename *smb_fname)
6968 uint32 file_type = IVAL(pdata,56);
6969 #if defined(HAVE_MAKEDEV)
6970 uint32 dev_major = IVAL(pdata,60);
6971 uint32 dev_minor = IVAL(pdata,68);
6972 #endif
6973 SMB_DEV_T dev = (SMB_DEV_T)0;
6974 uint32 raw_unixmode = IVAL(pdata,84);
6975 NTSTATUS status;
6976 mode_t unixmode;
6978 if (total_data < 100) {
6979 return NT_STATUS_INVALID_PARAMETER;
6982 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6983 PERM_NEW_FILE, &unixmode);
6984 if (!NT_STATUS_IS_OK(status)) {
6985 return status;
6988 #if defined(HAVE_MAKEDEV)
6989 dev = makedev(dev_major, dev_minor);
6990 #endif
6992 switch (file_type) {
6993 #if defined(S_IFIFO)
6994 case UNIX_TYPE_FIFO:
6995 unixmode |= S_IFIFO;
6996 break;
6997 #endif
6998 #if defined(S_IFSOCK)
6999 case UNIX_TYPE_SOCKET:
7000 unixmode |= S_IFSOCK;
7001 break;
7002 #endif
7003 #if defined(S_IFCHR)
7004 case UNIX_TYPE_CHARDEV:
7005 unixmode |= S_IFCHR;
7006 break;
7007 #endif
7008 #if defined(S_IFBLK)
7009 case UNIX_TYPE_BLKDEV:
7010 unixmode |= S_IFBLK;
7011 break;
7012 #endif
7013 default:
7014 return NT_STATUS_INVALID_PARAMETER;
7017 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7018 "%.0f mode 0%o for file %s\n", (double)dev,
7019 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7021 /* Ok - do the mknod. */
7022 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7023 return map_nt_error_from_unix(errno);
7026 /* If any of the other "set" calls fail we
7027 * don't want to end up with a half-constructed mknod.
7030 if (lp_inherit_perms(SNUM(conn))) {
7031 char *parent;
7032 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7033 &parent, NULL)) {
7034 return NT_STATUS_NO_MEMORY;
7036 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7037 unixmode);
7038 TALLOC_FREE(parent);
7041 return NT_STATUS_OK;
7044 /****************************************************************************
7045 Deal with SMB_SET_FILE_UNIX_BASIC.
7046 ****************************************************************************/
7048 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7049 struct smb_request *req,
7050 const char *pdata,
7051 int total_data,
7052 files_struct *fsp,
7053 const struct smb_filename *smb_fname)
7055 struct smb_file_time ft;
7056 uint32 raw_unixmode;
7057 mode_t unixmode;
7058 off_t size = 0;
7059 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7060 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7061 NTSTATUS status = NT_STATUS_OK;
7062 bool delete_on_fail = False;
7063 enum perm_type ptype;
7064 files_struct *all_fsps = NULL;
7065 bool modify_mtime = true;
7066 struct file_id id;
7067 struct smb_filename *smb_fname_tmp = NULL;
7068 SMB_STRUCT_STAT sbuf;
7070 ZERO_STRUCT(ft);
7072 if (total_data < 100) {
7073 return NT_STATUS_INVALID_PARAMETER;
7076 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7077 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7078 size=IVAL(pdata,0); /* first 8 Bytes are size */
7079 size |= (((off_t)IVAL(pdata,4)) << 32);
7082 ft.atime = interpret_long_date(pdata+24); /* access_time */
7083 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7084 set_owner = (uid_t)IVAL(pdata,40);
7085 set_grp = (gid_t)IVAL(pdata,48);
7086 raw_unixmode = IVAL(pdata,84);
7088 if (VALID_STAT(smb_fname->st)) {
7089 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7090 ptype = PERM_EXISTING_DIR;
7091 } else {
7092 ptype = PERM_EXISTING_FILE;
7094 } else {
7095 ptype = PERM_NEW_FILE;
7098 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7099 ptype, &unixmode);
7100 if (!NT_STATUS_IS_OK(status)) {
7101 return status;
7104 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7105 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7106 smb_fname_str_dbg(smb_fname), (double)size,
7107 (unsigned int)set_owner, (unsigned int)set_grp,
7108 (int)raw_unixmode));
7110 sbuf = smb_fname->st;
7112 if (!VALID_STAT(sbuf)) {
7114 * The only valid use of this is to create character and block
7115 * devices, and named pipes. This is deprecated (IMHO) and
7116 * a new info level should be used for mknod. JRA.
7119 status = smb_unix_mknod(conn,
7120 pdata,
7121 total_data,
7122 smb_fname);
7123 if (!NT_STATUS_IS_OK(status)) {
7124 return status;
7127 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7128 if (smb_fname_tmp == NULL) {
7129 return NT_STATUS_NO_MEMORY;
7132 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7133 status = map_nt_error_from_unix(errno);
7134 TALLOC_FREE(smb_fname_tmp);
7135 SMB_VFS_UNLINK(conn, smb_fname);
7136 return status;
7139 sbuf = smb_fname_tmp->st;
7140 smb_fname = smb_fname_tmp;
7142 /* Ensure we don't try and change anything else. */
7143 raw_unixmode = SMB_MODE_NO_CHANGE;
7144 size = get_file_size_stat(&sbuf);
7145 ft.atime = sbuf.st_ex_atime;
7146 ft.mtime = sbuf.st_ex_mtime;
7148 * We continue here as we might want to change the
7149 * owner uid/gid.
7151 delete_on_fail = True;
7154 #if 1
7155 /* Horrible backwards compatibility hack as an old server bug
7156 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7157 * */
7159 if (!size) {
7160 size = get_file_size_stat(&sbuf);
7162 #endif
7165 * Deal with the UNIX specific mode set.
7168 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7169 int ret;
7171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7172 "setting mode 0%o for file %s\n",
7173 (unsigned int)unixmode,
7174 smb_fname_str_dbg(smb_fname)));
7175 if (fsp && fsp->fh->fd != -1) {
7176 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7177 } else {
7178 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7180 if (ret != 0) {
7181 return map_nt_error_from_unix(errno);
7186 * Deal with the UNIX specific uid set.
7189 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7190 (sbuf.st_ex_uid != set_owner)) {
7191 int ret;
7193 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7194 "changing owner %u for path %s\n",
7195 (unsigned int)set_owner,
7196 smb_fname_str_dbg(smb_fname)));
7198 if (fsp && fsp->fh->fd != -1) {
7199 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7200 } else {
7202 * UNIX extensions calls must always operate
7203 * on symlinks.
7205 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7206 set_owner, (gid_t)-1);
7209 if (ret != 0) {
7210 status = map_nt_error_from_unix(errno);
7211 if (delete_on_fail) {
7212 SMB_VFS_UNLINK(conn, smb_fname);
7214 return status;
7219 * Deal with the UNIX specific gid set.
7222 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7223 (sbuf.st_ex_gid != set_grp)) {
7224 int ret;
7226 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7227 "changing group %u for file %s\n",
7228 (unsigned int)set_owner,
7229 smb_fname_str_dbg(smb_fname)));
7230 if (fsp && fsp->fh->fd != -1) {
7231 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7232 } else {
7234 * UNIX extensions calls must always operate
7235 * on symlinks.
7237 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7238 set_grp);
7240 if (ret != 0) {
7241 status = map_nt_error_from_unix(errno);
7242 if (delete_on_fail) {
7243 SMB_VFS_UNLINK(conn, smb_fname);
7245 return status;
7249 /* Deal with any size changes. */
7251 status = smb_set_file_size(conn, req,
7252 fsp,
7253 smb_fname,
7254 &sbuf,
7255 size,
7256 false);
7257 if (!NT_STATUS_IS_OK(status)) {
7258 return status;
7261 /* Deal with any time changes. */
7262 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7263 /* No change, don't cancel anything. */
7264 return status;
7267 id = vfs_file_id_from_sbuf(conn, &sbuf);
7268 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7269 all_fsps = file_find_di_next(all_fsps)) {
7271 * We're setting the time explicitly for UNIX.
7272 * Cancel any pending changes over all handles.
7274 all_fsps->update_write_time_on_close = false;
7275 TALLOC_FREE(all_fsps->update_write_time_event);
7279 * Override the "setting_write_time"
7280 * parameter here as it almost does what
7281 * we need. Just remember if we modified
7282 * mtime and send the notify ourselves.
7284 if (null_timespec(ft.mtime)) {
7285 modify_mtime = false;
7288 status = smb_set_file_time(conn,
7289 fsp,
7290 smb_fname,
7291 &ft,
7292 false);
7293 if (modify_mtime) {
7294 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7295 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7297 return status;
7300 /****************************************************************************
7301 Deal with SMB_SET_FILE_UNIX_INFO2.
7302 ****************************************************************************/
7304 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7305 struct smb_request *req,
7306 const char *pdata,
7307 int total_data,
7308 files_struct *fsp,
7309 const struct smb_filename *smb_fname)
7311 NTSTATUS status;
7312 uint32 smb_fflags;
7313 uint32 smb_fmask;
7315 if (total_data < 116) {
7316 return NT_STATUS_INVALID_PARAMETER;
7319 /* Start by setting all the fields that are common between UNIX_BASIC
7320 * and UNIX_INFO2.
7322 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7323 fsp, smb_fname);
7324 if (!NT_STATUS_IS_OK(status)) {
7325 return status;
7328 smb_fflags = IVAL(pdata, 108);
7329 smb_fmask = IVAL(pdata, 112);
7331 /* NB: We should only attempt to alter the file flags if the client
7332 * sends a non-zero mask.
7334 if (smb_fmask != 0) {
7335 int stat_fflags = 0;
7337 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7338 smb_fmask, &stat_fflags)) {
7339 /* Client asked to alter a flag we don't understand. */
7340 return NT_STATUS_INVALID_PARAMETER;
7343 if (fsp && fsp->fh->fd != -1) {
7344 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7345 return NT_STATUS_NOT_SUPPORTED;
7346 } else {
7347 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7348 stat_fflags) != 0) {
7349 return map_nt_error_from_unix(errno);
7354 /* XXX: need to add support for changing the create_time here. You
7355 * can do this for paths on Darwin with setattrlist(2). The right way
7356 * to hook this up is probably by extending the VFS utimes interface.
7359 return NT_STATUS_OK;
7362 /****************************************************************************
7363 Create a directory with POSIX semantics.
7364 ****************************************************************************/
7366 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7367 struct smb_request *req,
7368 char **ppdata,
7369 int total_data,
7370 struct smb_filename *smb_fname,
7371 int *pdata_return_size)
7373 NTSTATUS status = NT_STATUS_OK;
7374 uint32 raw_unixmode = 0;
7375 uint32 mod_unixmode = 0;
7376 mode_t unixmode = (mode_t)0;
7377 files_struct *fsp = NULL;
7378 uint16 info_level_return = 0;
7379 int info;
7380 char *pdata = *ppdata;
7382 if (total_data < 18) {
7383 return NT_STATUS_INVALID_PARAMETER;
7386 raw_unixmode = IVAL(pdata,8);
7387 /* Next 4 bytes are not yet defined. */
7389 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7390 PERM_NEW_DIR, &unixmode);
7391 if (!NT_STATUS_IS_OK(status)) {
7392 return status;
7395 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7397 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7398 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7400 status = SMB_VFS_CREATE_FILE(
7401 conn, /* conn */
7402 req, /* req */
7403 0, /* root_dir_fid */
7404 smb_fname, /* fname */
7405 FILE_READ_ATTRIBUTES, /* access_mask */
7406 FILE_SHARE_NONE, /* share_access */
7407 FILE_CREATE, /* create_disposition*/
7408 FILE_DIRECTORY_FILE, /* create_options */
7409 mod_unixmode, /* file_attributes */
7410 0, /* oplock_request */
7411 0, /* allocation_size */
7412 0, /* private_flags */
7413 NULL, /* sd */
7414 NULL, /* ea_list */
7415 &fsp, /* result */
7416 &info); /* pinfo */
7418 if (NT_STATUS_IS_OK(status)) {
7419 close_file(req, fsp, NORMAL_CLOSE);
7422 info_level_return = SVAL(pdata,16);
7424 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7425 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7426 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7427 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7428 } else {
7429 *pdata_return_size = 12;
7432 /* Realloc the data size */
7433 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7434 if (*ppdata == NULL) {
7435 *pdata_return_size = 0;
7436 return NT_STATUS_NO_MEMORY;
7438 pdata = *ppdata;
7440 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7441 SSVAL(pdata,2,0); /* No fnum. */
7442 SIVAL(pdata,4,info); /* Was directory created. */
7444 switch (info_level_return) {
7445 case SMB_QUERY_FILE_UNIX_BASIC:
7446 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7447 SSVAL(pdata,10,0); /* Padding. */
7448 store_file_unix_basic(conn, pdata + 12, fsp,
7449 &smb_fname->st);
7450 break;
7451 case SMB_QUERY_FILE_UNIX_INFO2:
7452 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7453 SSVAL(pdata,10,0); /* Padding. */
7454 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7455 &smb_fname->st);
7456 break;
7457 default:
7458 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7459 SSVAL(pdata,10,0); /* Padding. */
7460 break;
7463 return status;
7466 /****************************************************************************
7467 Open/Create a file with POSIX semantics.
7468 ****************************************************************************/
7470 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7471 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7473 static NTSTATUS smb_posix_open(connection_struct *conn,
7474 struct smb_request *req,
7475 char **ppdata,
7476 int total_data,
7477 struct smb_filename *smb_fname,
7478 int *pdata_return_size)
7480 bool extended_oplock_granted = False;
7481 char *pdata = *ppdata;
7482 uint32 flags = 0;
7483 uint32 wire_open_mode = 0;
7484 uint32 raw_unixmode = 0;
7485 uint32 mod_unixmode = 0;
7486 uint32 create_disp = 0;
7487 uint32 access_mask = 0;
7488 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7489 NTSTATUS status = NT_STATUS_OK;
7490 mode_t unixmode = (mode_t)0;
7491 files_struct *fsp = NULL;
7492 int oplock_request = 0;
7493 int info = 0;
7494 uint16 info_level_return = 0;
7496 if (total_data < 18) {
7497 return NT_STATUS_INVALID_PARAMETER;
7500 flags = IVAL(pdata,0);
7501 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7502 if (oplock_request) {
7503 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7506 wire_open_mode = IVAL(pdata,4);
7508 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7509 return smb_posix_mkdir(conn, req,
7510 ppdata,
7511 total_data,
7512 smb_fname,
7513 pdata_return_size);
7516 switch (wire_open_mode & SMB_ACCMODE) {
7517 case SMB_O_RDONLY:
7518 access_mask = SMB_O_RDONLY_MAPPING;
7519 break;
7520 case SMB_O_WRONLY:
7521 access_mask = SMB_O_WRONLY_MAPPING;
7522 break;
7523 case SMB_O_RDWR:
7524 access_mask = (SMB_O_RDONLY_MAPPING|
7525 SMB_O_WRONLY_MAPPING);
7526 break;
7527 default:
7528 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7529 (unsigned int)wire_open_mode ));
7530 return NT_STATUS_INVALID_PARAMETER;
7533 wire_open_mode &= ~SMB_ACCMODE;
7535 /* First take care of O_CREAT|O_EXCL interactions. */
7536 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7537 case (SMB_O_CREAT | SMB_O_EXCL):
7538 /* File exists fail. File not exist create. */
7539 create_disp = FILE_CREATE;
7540 break;
7541 case SMB_O_CREAT:
7542 /* File exists open. File not exist create. */
7543 create_disp = FILE_OPEN_IF;
7544 break;
7545 case SMB_O_EXCL:
7546 /* O_EXCL on its own without O_CREAT is undefined.
7547 We deliberately ignore it as some versions of
7548 Linux CIFSFS can send a bare O_EXCL on the
7549 wire which other filesystems in the kernel
7550 ignore. See bug 9519 for details. */
7552 /* Fallthrough. */
7554 case 0:
7555 /* File exists open. File not exist fail. */
7556 create_disp = FILE_OPEN;
7557 break;
7558 default:
7559 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7560 (unsigned int)wire_open_mode ));
7561 return NT_STATUS_INVALID_PARAMETER;
7564 /* Next factor in the effects of O_TRUNC. */
7565 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7567 if (wire_open_mode & SMB_O_TRUNC) {
7568 switch (create_disp) {
7569 case FILE_CREATE:
7570 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7571 /* Leave create_disp alone as
7572 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7574 /* File exists fail. File not exist create. */
7575 break;
7576 case FILE_OPEN_IF:
7577 /* SMB_O_CREAT | SMB_O_TRUNC */
7578 /* File exists overwrite. File not exist create. */
7579 create_disp = FILE_OVERWRITE_IF;
7580 break;
7581 case FILE_OPEN:
7582 /* SMB_O_TRUNC */
7583 /* File exists overwrite. File not exist fail. */
7584 create_disp = FILE_OVERWRITE;
7585 break;
7586 default:
7587 /* Cannot get here. */
7588 smb_panic("smb_posix_open: logic error");
7589 return NT_STATUS_INVALID_PARAMETER;
7593 raw_unixmode = IVAL(pdata,8);
7594 /* Next 4 bytes are not yet defined. */
7596 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7597 (VALID_STAT(smb_fname->st) ?
7598 PERM_EXISTING_FILE : PERM_NEW_FILE),
7599 &unixmode);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 return status;
7605 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7607 if (wire_open_mode & SMB_O_SYNC) {
7608 create_options |= FILE_WRITE_THROUGH;
7610 if (wire_open_mode & SMB_O_APPEND) {
7611 access_mask |= FILE_APPEND_DATA;
7613 if (wire_open_mode & SMB_O_DIRECT) {
7614 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7617 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7618 VALID_STAT_OF_DIR(smb_fname->st)) {
7619 if (access_mask != SMB_O_RDONLY_MAPPING) {
7620 return NT_STATUS_FILE_IS_A_DIRECTORY;
7622 create_options &= ~FILE_NON_DIRECTORY_FILE;
7623 create_options |= FILE_DIRECTORY_FILE;
7626 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7627 smb_fname_str_dbg(smb_fname),
7628 (unsigned int)wire_open_mode,
7629 (unsigned int)unixmode ));
7631 status = SMB_VFS_CREATE_FILE(
7632 conn, /* conn */
7633 req, /* req */
7634 0, /* root_dir_fid */
7635 smb_fname, /* fname */
7636 access_mask, /* access_mask */
7637 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7638 FILE_SHARE_DELETE),
7639 create_disp, /* create_disposition*/
7640 create_options, /* create_options */
7641 mod_unixmode, /* file_attributes */
7642 oplock_request, /* oplock_request */
7643 0, /* allocation_size */
7644 0, /* private_flags */
7645 NULL, /* sd */
7646 NULL, /* ea_list */
7647 &fsp, /* result */
7648 &info); /* pinfo */
7650 if (!NT_STATUS_IS_OK(status)) {
7651 return status;
7654 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7655 extended_oplock_granted = True;
7658 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7659 extended_oplock_granted = True;
7662 info_level_return = SVAL(pdata,16);
7664 /* Allocate the correct return size. */
7666 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7667 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7668 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7669 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7670 } else {
7671 *pdata_return_size = 12;
7674 /* Realloc the data size */
7675 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7676 if (*ppdata == NULL) {
7677 close_file(req, fsp, ERROR_CLOSE);
7678 *pdata_return_size = 0;
7679 return NT_STATUS_NO_MEMORY;
7681 pdata = *ppdata;
7683 if (extended_oplock_granted) {
7684 if (flags & REQUEST_BATCH_OPLOCK) {
7685 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7686 } else {
7687 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7689 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7690 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7691 } else {
7692 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7695 SSVAL(pdata,2,fsp->fnum);
7696 SIVAL(pdata,4,info); /* Was file created etc. */
7698 switch (info_level_return) {
7699 case SMB_QUERY_FILE_UNIX_BASIC:
7700 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7701 SSVAL(pdata,10,0); /* padding. */
7702 store_file_unix_basic(conn, pdata + 12, fsp,
7703 &smb_fname->st);
7704 break;
7705 case SMB_QUERY_FILE_UNIX_INFO2:
7706 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7707 SSVAL(pdata,10,0); /* padding. */
7708 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7709 &smb_fname->st);
7710 break;
7711 default:
7712 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7713 SSVAL(pdata,10,0); /* padding. */
7714 break;
7716 return NT_STATUS_OK;
7719 /****************************************************************************
7720 Delete a file with POSIX semantics.
7721 ****************************************************************************/
7723 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7724 struct smb_request *req,
7725 const char *pdata,
7726 int total_data,
7727 struct smb_filename *smb_fname)
7729 NTSTATUS status = NT_STATUS_OK;
7730 files_struct *fsp = NULL;
7731 uint16 flags = 0;
7732 char del = 1;
7733 int info = 0;
7734 int create_options = 0;
7735 int i;
7736 struct share_mode_lock *lck = NULL;
7738 if (total_data < 2) {
7739 return NT_STATUS_INVALID_PARAMETER;
7742 flags = SVAL(pdata,0);
7744 if (!VALID_STAT(smb_fname->st)) {
7745 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7748 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7749 !VALID_STAT_OF_DIR(smb_fname->st)) {
7750 return NT_STATUS_NOT_A_DIRECTORY;
7753 DEBUG(10,("smb_posix_unlink: %s %s\n",
7754 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7755 smb_fname_str_dbg(smb_fname)));
7757 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7758 create_options |= FILE_DIRECTORY_FILE;
7761 status = SMB_VFS_CREATE_FILE(
7762 conn, /* conn */
7763 req, /* req */
7764 0, /* root_dir_fid */
7765 smb_fname, /* fname */
7766 DELETE_ACCESS, /* access_mask */
7767 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7768 FILE_SHARE_DELETE),
7769 FILE_OPEN, /* create_disposition*/
7770 create_options, /* create_options */
7771 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7772 0, /* oplock_request */
7773 0, /* allocation_size */
7774 0, /* private_flags */
7775 NULL, /* sd */
7776 NULL, /* ea_list */
7777 &fsp, /* result */
7778 &info); /* pinfo */
7780 if (!NT_STATUS_IS_OK(status)) {
7781 return status;
7785 * Don't lie to client. If we can't really delete due to
7786 * non-POSIX opens return SHARING_VIOLATION.
7789 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7790 if (lck == NULL) {
7791 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7792 "lock for file %s\n", fsp_str_dbg(fsp)));
7793 close_file(req, fsp, NORMAL_CLOSE);
7794 return NT_STATUS_INVALID_PARAMETER;
7798 * See if others still have the file open. If this is the case, then
7799 * don't delete. If all opens are POSIX delete we can set the delete
7800 * on close disposition.
7802 for (i=0; i<lck->data->num_share_modes; i++) {
7803 struct share_mode_entry *e = &lck->data->share_modes[i];
7804 if (is_valid_share_mode_entry(e)) {
7805 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7806 continue;
7808 if (share_mode_stale_pid(lck->data, i)) {
7809 continue;
7811 /* Fail with sharing violation. */
7812 TALLOC_FREE(lck);
7813 close_file(req, fsp, NORMAL_CLOSE);
7814 return NT_STATUS_SHARING_VIOLATION;
7819 * Set the delete on close.
7821 status = smb_set_file_disposition_info(conn,
7822 &del,
7824 fsp,
7825 smb_fname);
7827 TALLOC_FREE(lck);
7829 if (!NT_STATUS_IS_OK(status)) {
7830 close_file(req, fsp, NORMAL_CLOSE);
7831 return status;
7833 return close_file(req, fsp, NORMAL_CLOSE);
7836 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7837 struct smb_request *req,
7838 TALLOC_CTX *mem_ctx,
7839 uint16_t info_level,
7840 files_struct *fsp,
7841 struct smb_filename *smb_fname,
7842 char **ppdata, int total_data,
7843 int *ret_data_size)
7845 char *pdata = *ppdata;
7846 NTSTATUS status = NT_STATUS_OK;
7847 int data_return_size = 0;
7849 *ret_data_size = 0;
7851 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7852 return NT_STATUS_INVALID_LEVEL;
7855 if (!CAN_WRITE(conn)) {
7856 /* Allow POSIX opens. The open path will deny
7857 * any non-readonly opens. */
7858 if (info_level != SMB_POSIX_PATH_OPEN) {
7859 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7863 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7864 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7865 fsp_fnum_dbg(fsp),
7866 info_level, total_data));
7868 switch (info_level) {
7870 case SMB_INFO_STANDARD:
7872 status = smb_set_info_standard(conn,
7873 pdata,
7874 total_data,
7875 fsp,
7876 smb_fname);
7877 break;
7880 case SMB_INFO_SET_EA:
7882 status = smb_info_set_ea(conn,
7883 pdata,
7884 total_data,
7885 fsp,
7886 smb_fname);
7887 break;
7890 case SMB_SET_FILE_BASIC_INFO:
7891 case SMB_FILE_BASIC_INFORMATION:
7893 status = smb_set_file_basic_info(conn,
7894 pdata,
7895 total_data,
7896 fsp,
7897 smb_fname);
7898 break;
7901 case SMB_FILE_ALLOCATION_INFORMATION:
7902 case SMB_SET_FILE_ALLOCATION_INFO:
7904 status = smb_set_file_allocation_info(conn, req,
7905 pdata,
7906 total_data,
7907 fsp,
7908 smb_fname);
7909 break;
7912 case SMB_FILE_END_OF_FILE_INFORMATION:
7913 case SMB_SET_FILE_END_OF_FILE_INFO:
7916 * XP/Win7 both fail after the createfile with
7917 * SMB_SET_FILE_END_OF_FILE_INFO but not
7918 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7919 * The level is known here, so pass it down
7920 * appropriately.
7922 bool should_fail =
7923 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7925 status = smb_set_file_end_of_file_info(conn, req,
7926 pdata,
7927 total_data,
7928 fsp,
7929 smb_fname,
7930 should_fail);
7931 break;
7934 case SMB_FILE_DISPOSITION_INFORMATION:
7935 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7937 #if 0
7938 /* JRA - We used to just ignore this on a path ?
7939 * Shouldn't this be invalid level on a pathname
7940 * based call ?
7942 if (tran_call != TRANSACT2_SETFILEINFO) {
7943 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7945 #endif
7946 status = smb_set_file_disposition_info(conn,
7947 pdata,
7948 total_data,
7949 fsp,
7950 smb_fname);
7951 break;
7954 case SMB_FILE_POSITION_INFORMATION:
7956 status = smb_file_position_information(conn,
7957 pdata,
7958 total_data,
7959 fsp);
7960 break;
7963 case SMB_FILE_FULL_EA_INFORMATION:
7965 status = smb_set_file_full_ea_info(conn,
7966 pdata,
7967 total_data,
7968 fsp);
7969 break;
7972 /* From tridge Samba4 :
7973 * MODE_INFORMATION in setfileinfo (I have no
7974 * idea what "mode information" on a file is - it takes a value of 0,
7975 * 2, 4 or 6. What could it be?).
7978 case SMB_FILE_MODE_INFORMATION:
7980 status = smb_file_mode_information(conn,
7981 pdata,
7982 total_data);
7983 break;
7987 * CIFS UNIX extensions.
7990 case SMB_SET_FILE_UNIX_BASIC:
7992 status = smb_set_file_unix_basic(conn, req,
7993 pdata,
7994 total_data,
7995 fsp,
7996 smb_fname);
7997 break;
8000 case SMB_SET_FILE_UNIX_INFO2:
8002 status = smb_set_file_unix_info2(conn, req,
8003 pdata,
8004 total_data,
8005 fsp,
8006 smb_fname);
8007 break;
8010 case SMB_SET_FILE_UNIX_LINK:
8012 if (fsp) {
8013 /* We must have a pathname for this. */
8014 return NT_STATUS_INVALID_LEVEL;
8016 status = smb_set_file_unix_link(conn, req, pdata,
8017 total_data, smb_fname);
8018 break;
8021 case SMB_SET_FILE_UNIX_HLINK:
8023 if (fsp) {
8024 /* We must have a pathname for this. */
8025 return NT_STATUS_INVALID_LEVEL;
8027 status = smb_set_file_unix_hlink(conn, req,
8028 pdata, total_data,
8029 smb_fname);
8030 break;
8033 case SMB_FILE_RENAME_INFORMATION:
8035 status = smb_file_rename_information(conn, req,
8036 pdata, total_data,
8037 fsp, smb_fname);
8038 break;
8041 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8043 /* SMB2 rename information. */
8044 status = smb2_file_rename_information(conn, req,
8045 pdata, total_data,
8046 fsp, smb_fname);
8047 break;
8050 case SMB_FILE_LINK_INFORMATION:
8052 status = smb_file_link_information(conn, req,
8053 pdata, total_data,
8054 fsp, smb_fname);
8055 break;
8058 #if defined(HAVE_POSIX_ACLS)
8059 case SMB_SET_POSIX_ACL:
8061 status = smb_set_posix_acl(conn,
8062 pdata,
8063 total_data,
8064 fsp,
8065 smb_fname);
8066 break;
8068 #endif
8070 case SMB_SET_POSIX_LOCK:
8072 if (!fsp) {
8073 return NT_STATUS_INVALID_LEVEL;
8075 status = smb_set_posix_lock(conn, req,
8076 pdata, total_data, fsp);
8077 break;
8080 case SMB_POSIX_PATH_OPEN:
8082 if (fsp) {
8083 /* We must have a pathname for this. */
8084 return NT_STATUS_INVALID_LEVEL;
8087 status = smb_posix_open(conn, req,
8088 ppdata,
8089 total_data,
8090 smb_fname,
8091 &data_return_size);
8092 break;
8095 case SMB_POSIX_PATH_UNLINK:
8097 if (fsp) {
8098 /* We must have a pathname for this. */
8099 return NT_STATUS_INVALID_LEVEL;
8102 status = smb_posix_unlink(conn, req,
8103 pdata,
8104 total_data,
8105 smb_fname);
8106 break;
8109 default:
8110 return NT_STATUS_INVALID_LEVEL;
8113 if (!NT_STATUS_IS_OK(status)) {
8114 return status;
8117 *ret_data_size = data_return_size;
8118 return NT_STATUS_OK;
8121 /****************************************************************************
8122 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8123 ****************************************************************************/
8125 static void call_trans2setfilepathinfo(connection_struct *conn,
8126 struct smb_request *req,
8127 unsigned int tran_call,
8128 char **pparams, int total_params,
8129 char **ppdata, int total_data,
8130 unsigned int max_data_bytes)
8132 char *params = *pparams;
8133 char *pdata = *ppdata;
8134 uint16 info_level;
8135 struct smb_filename *smb_fname = NULL;
8136 files_struct *fsp = NULL;
8137 NTSTATUS status = NT_STATUS_OK;
8138 int data_return_size = 0;
8140 if (!params) {
8141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8142 return;
8145 if (tran_call == TRANSACT2_SETFILEINFO) {
8146 if (total_params < 4) {
8147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8148 return;
8151 fsp = file_fsp(req, SVAL(params,0));
8152 /* Basic check for non-null fsp. */
8153 if (!check_fsp_open(conn, req, fsp)) {
8154 return;
8156 info_level = SVAL(params,2);
8158 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8159 if (smb_fname == NULL) {
8160 reply_nterror(req, NT_STATUS_NO_MEMORY);
8161 return;
8164 if(fsp->fh->fd == -1) {
8166 * This is actually a SETFILEINFO on a directory
8167 * handle (returned from an NT SMB). NT5.0 seems
8168 * to do this call. JRA.
8170 if (INFO_LEVEL_IS_UNIX(info_level)) {
8171 /* Always do lstat for UNIX calls. */
8172 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8173 DEBUG(3,("call_trans2setfilepathinfo: "
8174 "SMB_VFS_LSTAT of %s failed "
8175 "(%s)\n",
8176 smb_fname_str_dbg(smb_fname),
8177 strerror(errno)));
8178 reply_nterror(req, map_nt_error_from_unix(errno));
8179 return;
8181 } else {
8182 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8183 DEBUG(3,("call_trans2setfilepathinfo: "
8184 "fileinfo of %s failed (%s)\n",
8185 smb_fname_str_dbg(smb_fname),
8186 strerror(errno)));
8187 reply_nterror(req, map_nt_error_from_unix(errno));
8188 return;
8191 } else if (fsp->print_file) {
8193 * Doing a DELETE_ON_CLOSE should cancel a print job.
8195 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8196 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8198 DEBUG(3,("call_trans2setfilepathinfo: "
8199 "Cancelling print job (%s)\n",
8200 fsp_str_dbg(fsp)));
8202 SSVAL(params,0,0);
8203 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8204 *ppdata, 0,
8205 max_data_bytes);
8206 return;
8207 } else {
8208 reply_nterror(req,
8209 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8210 return;
8212 } else {
8214 * Original code - this is an open file.
8216 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8217 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8218 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8219 strerror(errno)));
8220 reply_nterror(req, map_nt_error_from_unix(errno));
8221 return;
8224 } else {
8225 char *fname = NULL;
8226 uint32_t ucf_flags = 0;
8228 /* set path info */
8229 if (total_params < 7) {
8230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8231 return;
8234 info_level = SVAL(params,0);
8235 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8236 total_params - 6, STR_TERMINATE,
8237 &status);
8238 if (!NT_STATUS_IS_OK(status)) {
8239 reply_nterror(req, status);
8240 return;
8243 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8244 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8245 info_level == SMB_FILE_RENAME_INFORMATION ||
8246 info_level == SMB_POSIX_PATH_UNLINK) {
8247 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8250 status = filename_convert(req, conn,
8251 req->flags2 & FLAGS2_DFS_PATHNAMES,
8252 fname,
8253 ucf_flags,
8254 NULL,
8255 &smb_fname);
8256 if (!NT_STATUS_IS_OK(status)) {
8257 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8258 reply_botherror(req,
8259 NT_STATUS_PATH_NOT_COVERED,
8260 ERRSRV, ERRbadpath);
8261 return;
8263 reply_nterror(req, status);
8264 return;
8267 if (INFO_LEVEL_IS_UNIX(info_level)) {
8269 * For CIFS UNIX extensions the target name may not exist.
8272 /* Always do lstat for UNIX calls. */
8273 SMB_VFS_LSTAT(conn, smb_fname);
8275 } else if (!VALID_STAT(smb_fname->st) &&
8276 SMB_VFS_STAT(conn, smb_fname)) {
8277 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8278 "%s failed (%s)\n",
8279 smb_fname_str_dbg(smb_fname),
8280 strerror(errno)));
8281 reply_nterror(req, map_nt_error_from_unix(errno));
8282 return;
8286 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8287 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8288 fsp_fnum_dbg(fsp),
8289 info_level,total_data));
8291 /* Realloc the parameter size */
8292 *pparams = (char *)SMB_REALLOC(*pparams,2);
8293 if (*pparams == NULL) {
8294 reply_nterror(req, NT_STATUS_NO_MEMORY);
8295 return;
8297 params = *pparams;
8299 SSVAL(params,0,0);
8301 status = smbd_do_setfilepathinfo(conn, req, req,
8302 info_level,
8303 fsp,
8304 smb_fname,
8305 ppdata, total_data,
8306 &data_return_size);
8307 if (!NT_STATUS_IS_OK(status)) {
8308 if (open_was_deferred(req->sconn, req->mid)) {
8309 /* We have re-scheduled this call. */
8310 return;
8312 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8313 /* We have re-scheduled this call. */
8314 return;
8316 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8317 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8318 ERRSRV, ERRbadpath);
8319 return;
8321 if (info_level == SMB_POSIX_PATH_OPEN) {
8322 reply_openerror(req, status);
8323 return;
8327 * Invalid EA name needs to return 2 param bytes,
8328 * not a zero-length error packet.
8330 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8331 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8332 max_data_bytes);
8333 } else {
8334 reply_nterror(req, status);
8336 return;
8339 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8340 max_data_bytes);
8342 return;
8345 /****************************************************************************
8346 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8347 ****************************************************************************/
8349 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8350 char **pparams, int total_params,
8351 char **ppdata, int total_data,
8352 unsigned int max_data_bytes)
8354 struct smb_filename *smb_dname = NULL;
8355 char *params = *pparams;
8356 char *pdata = *ppdata;
8357 char *directory = NULL;
8358 NTSTATUS status = NT_STATUS_OK;
8359 struct ea_list *ea_list = NULL;
8360 TALLOC_CTX *ctx = talloc_tos();
8362 if (!CAN_WRITE(conn)) {
8363 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8364 return;
8367 if (total_params < 5) {
8368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8369 return;
8372 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8373 total_params - 4, STR_TERMINATE,
8374 &status);
8375 if (!NT_STATUS_IS_OK(status)) {
8376 reply_nterror(req, status);
8377 return;
8380 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8382 status = filename_convert(ctx,
8383 conn,
8384 req->flags2 & FLAGS2_DFS_PATHNAMES,
8385 directory,
8387 NULL,
8388 &smb_dname);
8390 if (!NT_STATUS_IS_OK(status)) {
8391 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8392 reply_botherror(req,
8393 NT_STATUS_PATH_NOT_COVERED,
8394 ERRSRV, ERRbadpath);
8395 return;
8397 reply_nterror(req, status);
8398 return;
8402 * OS/2 workplace shell seems to send SET_EA requests of "null"
8403 * length (4 bytes containing IVAL 4).
8404 * They seem to have no effect. Bug #3212. JRA.
8407 if (total_data && (total_data != 4)) {
8408 /* Any data in this call is an EA list. */
8409 if (total_data < 10) {
8410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8411 goto out;
8414 if (IVAL(pdata,0) > total_data) {
8415 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8416 IVAL(pdata,0), (unsigned int)total_data));
8417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8418 goto out;
8421 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8422 total_data - 4);
8423 if (!ea_list) {
8424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8425 goto out;
8428 if (!lp_ea_support(SNUM(conn))) {
8429 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8430 goto out;
8433 /* If total_data == 4 Windows doesn't care what values
8434 * are placed in that field, it just ignores them.
8435 * The System i QNTC IBM SMB client puts bad values here,
8436 * so ignore them. */
8438 status = create_directory(conn, req, smb_dname);
8440 if (!NT_STATUS_IS_OK(status)) {
8441 reply_nterror(req, status);
8442 goto out;
8445 /* Try and set any given EA. */
8446 if (ea_list) {
8447 status = set_ea(conn, NULL, smb_dname, ea_list);
8448 if (!NT_STATUS_IS_OK(status)) {
8449 reply_nterror(req, status);
8450 goto out;
8454 /* Realloc the parameter and data sizes */
8455 *pparams = (char *)SMB_REALLOC(*pparams,2);
8456 if(*pparams == NULL) {
8457 reply_nterror(req, NT_STATUS_NO_MEMORY);
8458 goto out;
8460 params = *pparams;
8462 SSVAL(params,0,0);
8464 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8466 out:
8467 TALLOC_FREE(smb_dname);
8468 return;
8471 /****************************************************************************
8472 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8473 We don't actually do this - we just send a null response.
8474 ****************************************************************************/
8476 static void call_trans2findnotifyfirst(connection_struct *conn,
8477 struct smb_request *req,
8478 char **pparams, int total_params,
8479 char **ppdata, int total_data,
8480 unsigned int max_data_bytes)
8482 char *params = *pparams;
8483 uint16 info_level;
8485 if (total_params < 6) {
8486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8487 return;
8490 info_level = SVAL(params,4);
8491 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8493 switch (info_level) {
8494 case 1:
8495 case 2:
8496 break;
8497 default:
8498 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8499 return;
8502 /* Realloc the parameter and data sizes */
8503 *pparams = (char *)SMB_REALLOC(*pparams,6);
8504 if (*pparams == NULL) {
8505 reply_nterror(req, NT_STATUS_NO_MEMORY);
8506 return;
8508 params = *pparams;
8510 SSVAL(params,0,fnf_handle);
8511 SSVAL(params,2,0); /* No changes */
8512 SSVAL(params,4,0); /* No EA errors */
8514 fnf_handle++;
8516 if(fnf_handle == 0)
8517 fnf_handle = 257;
8519 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8521 return;
8524 /****************************************************************************
8525 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8526 changes). Currently this does nothing.
8527 ****************************************************************************/
8529 static void call_trans2findnotifynext(connection_struct *conn,
8530 struct smb_request *req,
8531 char **pparams, int total_params,
8532 char **ppdata, int total_data,
8533 unsigned int max_data_bytes)
8535 char *params = *pparams;
8537 DEBUG(3,("call_trans2findnotifynext\n"));
8539 /* Realloc the parameter and data sizes */
8540 *pparams = (char *)SMB_REALLOC(*pparams,4);
8541 if (*pparams == NULL) {
8542 reply_nterror(req, NT_STATUS_NO_MEMORY);
8543 return;
8545 params = *pparams;
8547 SSVAL(params,0,0); /* No changes */
8548 SSVAL(params,2,0); /* No EA errors */
8550 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8552 return;
8555 /****************************************************************************
8556 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8557 ****************************************************************************/
8559 static void call_trans2getdfsreferral(connection_struct *conn,
8560 struct smb_request *req,
8561 char **pparams, int total_params,
8562 char **ppdata, int total_data,
8563 unsigned int max_data_bytes)
8565 char *params = *pparams;
8566 char *pathname = NULL;
8567 int reply_size = 0;
8568 int max_referral_level;
8569 NTSTATUS status = NT_STATUS_OK;
8570 TALLOC_CTX *ctx = talloc_tos();
8572 DEBUG(10,("call_trans2getdfsreferral\n"));
8574 if (total_params < 3) {
8575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8576 return;
8579 max_referral_level = SVAL(params,0);
8581 if(!lp_host_msdfs()) {
8582 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8583 return;
8586 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8587 total_params - 2, STR_TERMINATE);
8588 if (!pathname) {
8589 reply_nterror(req, NT_STATUS_NOT_FOUND);
8590 return;
8592 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8593 ppdata,&status)) < 0) {
8594 reply_nterror(req, status);
8595 return;
8598 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8599 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8600 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8602 return;
8605 #define LMCAT_SPL 0x53
8606 #define LMFUNC_GETJOBID 0x60
8608 /****************************************************************************
8609 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8610 ****************************************************************************/
8612 static void call_trans2ioctl(connection_struct *conn,
8613 struct smb_request *req,
8614 char **pparams, int total_params,
8615 char **ppdata, int total_data,
8616 unsigned int max_data_bytes)
8618 char *pdata = *ppdata;
8619 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8621 /* check for an invalid fid before proceeding */
8623 if (!fsp) {
8624 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8625 return;
8628 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8629 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8630 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8631 if (*ppdata == NULL) {
8632 reply_nterror(req, NT_STATUS_NO_MEMORY);
8633 return;
8635 pdata = *ppdata;
8637 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8638 CAN ACCEPT THIS IN UNICODE. JRA. */
8640 /* Job number */
8641 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8643 srvstr_push(pdata, req->flags2, pdata + 2,
8644 lp_netbios_name(), 15,
8645 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8646 srvstr_push(pdata, req->flags2, pdata+18,
8647 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8648 STR_ASCII|STR_TERMINATE); /* Service name */
8649 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8650 max_data_bytes);
8651 return;
8654 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8655 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8658 /****************************************************************************
8659 Reply to a SMBfindclose (stop trans2 directory search).
8660 ****************************************************************************/
8662 void reply_findclose(struct smb_request *req)
8664 int dptr_num;
8665 struct smbd_server_connection *sconn = req->sconn;
8667 START_PROFILE(SMBfindclose);
8669 if (req->wct < 1) {
8670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8671 END_PROFILE(SMBfindclose);
8672 return;
8675 dptr_num = SVALS(req->vwv+0, 0);
8677 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8679 dptr_close(sconn, &dptr_num);
8681 reply_outbuf(req, 0, 0);
8683 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8685 END_PROFILE(SMBfindclose);
8686 return;
8689 /****************************************************************************
8690 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8691 ****************************************************************************/
8693 void reply_findnclose(struct smb_request *req)
8695 int dptr_num;
8697 START_PROFILE(SMBfindnclose);
8699 if (req->wct < 1) {
8700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8701 END_PROFILE(SMBfindnclose);
8702 return;
8705 dptr_num = SVAL(req->vwv+0, 0);
8707 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8709 /* We never give out valid handles for a
8710 findnotifyfirst - so any dptr_num is ok here.
8711 Just ignore it. */
8713 reply_outbuf(req, 0, 0);
8715 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8717 END_PROFILE(SMBfindnclose);
8718 return;
8721 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8722 struct trans_state *state)
8724 if (get_Protocol() >= PROTOCOL_NT1) {
8725 req->flags2 |= 0x40; /* IS_LONG_NAME */
8726 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8729 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8730 if (state->call != TRANSACT2_QFSINFO &&
8731 state->call != TRANSACT2_SETFSINFO) {
8732 DEBUG(0,("handle_trans2: encryption required "
8733 "with call 0x%x\n",
8734 (unsigned int)state->call));
8735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8736 return;
8740 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8742 /* Now we must call the relevant TRANS2 function */
8743 switch(state->call) {
8744 case TRANSACT2_OPEN:
8746 START_PROFILE(Trans2_open);
8747 call_trans2open(conn, req,
8748 &state->param, state->total_param,
8749 &state->data, state->total_data,
8750 state->max_data_return);
8751 END_PROFILE(Trans2_open);
8752 break;
8755 case TRANSACT2_FINDFIRST:
8757 START_PROFILE(Trans2_findfirst);
8758 call_trans2findfirst(conn, req,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_findfirst);
8763 break;
8766 case TRANSACT2_FINDNEXT:
8768 START_PROFILE(Trans2_findnext);
8769 call_trans2findnext(conn, req,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_findnext);
8774 break;
8777 case TRANSACT2_QFSINFO:
8779 START_PROFILE(Trans2_qfsinfo);
8780 call_trans2qfsinfo(conn, req,
8781 &state->param, state->total_param,
8782 &state->data, state->total_data,
8783 state->max_data_return);
8784 END_PROFILE(Trans2_qfsinfo);
8785 break;
8788 case TRANSACT2_SETFSINFO:
8790 START_PROFILE(Trans2_setfsinfo);
8791 call_trans2setfsinfo(conn, req,
8792 &state->param, state->total_param,
8793 &state->data, state->total_data,
8794 state->max_data_return);
8795 END_PROFILE(Trans2_setfsinfo);
8796 break;
8799 case TRANSACT2_QPATHINFO:
8800 case TRANSACT2_QFILEINFO:
8802 START_PROFILE(Trans2_qpathinfo);
8803 call_trans2qfilepathinfo(conn, req, state->call,
8804 &state->param, state->total_param,
8805 &state->data, state->total_data,
8806 state->max_data_return);
8807 END_PROFILE(Trans2_qpathinfo);
8808 break;
8811 case TRANSACT2_SETPATHINFO:
8812 case TRANSACT2_SETFILEINFO:
8814 START_PROFILE(Trans2_setpathinfo);
8815 call_trans2setfilepathinfo(conn, req, state->call,
8816 &state->param, state->total_param,
8817 &state->data, state->total_data,
8818 state->max_data_return);
8819 END_PROFILE(Trans2_setpathinfo);
8820 break;
8823 case TRANSACT2_FINDNOTIFYFIRST:
8825 START_PROFILE(Trans2_findnotifyfirst);
8826 call_trans2findnotifyfirst(conn, req,
8827 &state->param, state->total_param,
8828 &state->data, state->total_data,
8829 state->max_data_return);
8830 END_PROFILE(Trans2_findnotifyfirst);
8831 break;
8834 case TRANSACT2_FINDNOTIFYNEXT:
8836 START_PROFILE(Trans2_findnotifynext);
8837 call_trans2findnotifynext(conn, req,
8838 &state->param, state->total_param,
8839 &state->data, state->total_data,
8840 state->max_data_return);
8841 END_PROFILE(Trans2_findnotifynext);
8842 break;
8845 case TRANSACT2_MKDIR:
8847 START_PROFILE(Trans2_mkdir);
8848 call_trans2mkdir(conn, req,
8849 &state->param, state->total_param,
8850 &state->data, state->total_data,
8851 state->max_data_return);
8852 END_PROFILE(Trans2_mkdir);
8853 break;
8856 case TRANSACT2_GET_DFS_REFERRAL:
8858 START_PROFILE(Trans2_get_dfs_referral);
8859 call_trans2getdfsreferral(conn, req,
8860 &state->param, state->total_param,
8861 &state->data, state->total_data,
8862 state->max_data_return);
8863 END_PROFILE(Trans2_get_dfs_referral);
8864 break;
8867 case TRANSACT2_IOCTL:
8869 START_PROFILE(Trans2_ioctl);
8870 call_trans2ioctl(conn, req,
8871 &state->param, state->total_param,
8872 &state->data, state->total_data,
8873 state->max_data_return);
8874 END_PROFILE(Trans2_ioctl);
8875 break;
8878 default:
8879 /* Error in request */
8880 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8881 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8885 /****************************************************************************
8886 Reply to a SMBtrans2.
8887 ****************************************************************************/
8889 void reply_trans2(struct smb_request *req)
8891 connection_struct *conn = req->conn;
8892 unsigned int dsoff;
8893 unsigned int dscnt;
8894 unsigned int psoff;
8895 unsigned int pscnt;
8896 unsigned int tran_call;
8897 struct trans_state *state;
8898 NTSTATUS result;
8900 START_PROFILE(SMBtrans2);
8902 if (req->wct < 14) {
8903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8904 END_PROFILE(SMBtrans2);
8905 return;
8908 dsoff = SVAL(req->vwv+12, 0);
8909 dscnt = SVAL(req->vwv+11, 0);
8910 psoff = SVAL(req->vwv+10, 0);
8911 pscnt = SVAL(req->vwv+9, 0);
8912 tran_call = SVAL(req->vwv+14, 0);
8914 result = allow_new_trans(conn->pending_trans, req->mid);
8915 if (!NT_STATUS_IS_OK(result)) {
8916 DEBUG(2, ("Got invalid trans2 request: %s\n",
8917 nt_errstr(result)));
8918 reply_nterror(req, result);
8919 END_PROFILE(SMBtrans2);
8920 return;
8923 if (IS_IPC(conn)) {
8924 switch (tran_call) {
8925 /* List the allowed trans2 calls on IPC$ */
8926 case TRANSACT2_OPEN:
8927 case TRANSACT2_GET_DFS_REFERRAL:
8928 case TRANSACT2_QFILEINFO:
8929 case TRANSACT2_QFSINFO:
8930 case TRANSACT2_SETFSINFO:
8931 break;
8932 default:
8933 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8934 END_PROFILE(SMBtrans2);
8935 return;
8939 if ((state = talloc(conn, struct trans_state)) == NULL) {
8940 DEBUG(0, ("talloc failed\n"));
8941 reply_nterror(req, NT_STATUS_NO_MEMORY);
8942 END_PROFILE(SMBtrans2);
8943 return;
8946 state->cmd = SMBtrans2;
8948 state->mid = req->mid;
8949 state->vuid = req->vuid;
8950 state->setup_count = SVAL(req->vwv+13, 0);
8951 state->setup = NULL;
8952 state->total_param = SVAL(req->vwv+0, 0);
8953 state->param = NULL;
8954 state->total_data = SVAL(req->vwv+1, 0);
8955 state->data = NULL;
8956 state->max_param_return = SVAL(req->vwv+2, 0);
8957 state->max_data_return = SVAL(req->vwv+3, 0);
8958 state->max_setup_return = SVAL(req->vwv+4, 0);
8959 state->close_on_completion = BITSETW(req->vwv+5, 0);
8960 state->one_way = BITSETW(req->vwv+5, 1);
8962 state->call = tran_call;
8964 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8965 is so as a sanity check */
8966 if (state->setup_count != 1) {
8968 * Need to have rc=0 for ioctl to get job id for OS/2.
8969 * Network printing will fail if function is not successful.
8970 * Similar function in reply.c will be used if protocol
8971 * is LANMAN1.0 instead of LM1.2X002.
8972 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8973 * outbuf doesn't have to be set(only job id is used).
8975 if ( (state->setup_count == 4)
8976 && (tran_call == TRANSACT2_IOCTL)
8977 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8978 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8979 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8980 } else {
8981 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8982 DEBUG(2,("Transaction is %d\n",tran_call));
8983 TALLOC_FREE(state);
8984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8985 END_PROFILE(SMBtrans2);
8986 return;
8990 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8991 goto bad_param;
8993 if (state->total_data) {
8995 if (trans_oob(state->total_data, 0, dscnt)
8996 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8997 goto bad_param;
9000 /* Can't use talloc here, the core routines do realloc on the
9001 * params and data. */
9002 state->data = (char *)SMB_MALLOC(state->total_data);
9003 if (state->data == NULL) {
9004 DEBUG(0,("reply_trans2: data malloc fail for %u "
9005 "bytes !\n", (unsigned int)state->total_data));
9006 TALLOC_FREE(state);
9007 reply_nterror(req, NT_STATUS_NO_MEMORY);
9008 END_PROFILE(SMBtrans2);
9009 return;
9012 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9015 if (state->total_param) {
9017 if (trans_oob(state->total_param, 0, pscnt)
9018 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9019 goto bad_param;
9022 /* Can't use talloc here, the core routines do realloc on the
9023 * params and data. */
9024 state->param = (char *)SMB_MALLOC(state->total_param);
9025 if (state->param == NULL) {
9026 DEBUG(0,("reply_trans: param malloc fail for %u "
9027 "bytes !\n", (unsigned int)state->total_param));
9028 SAFE_FREE(state->data);
9029 TALLOC_FREE(state);
9030 reply_nterror(req, NT_STATUS_NO_MEMORY);
9031 END_PROFILE(SMBtrans2);
9032 return;
9035 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9038 state->received_data = dscnt;
9039 state->received_param = pscnt;
9041 if ((state->received_param == state->total_param) &&
9042 (state->received_data == state->total_data)) {
9044 handle_trans2(conn, req, state);
9046 SAFE_FREE(state->data);
9047 SAFE_FREE(state->param);
9048 TALLOC_FREE(state);
9049 END_PROFILE(SMBtrans2);
9050 return;
9053 DLIST_ADD(conn->pending_trans, state);
9055 /* We need to send an interim response then receive the rest
9056 of the parameter/data bytes */
9057 reply_outbuf(req, 0, 0);
9058 show_msg((char *)req->outbuf);
9059 END_PROFILE(SMBtrans2);
9060 return;
9062 bad_param:
9064 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9065 SAFE_FREE(state->data);
9066 SAFE_FREE(state->param);
9067 TALLOC_FREE(state);
9068 END_PROFILE(SMBtrans2);
9069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9073 /****************************************************************************
9074 Reply to a SMBtranss2
9075 ****************************************************************************/
9077 void reply_transs2(struct smb_request *req)
9079 connection_struct *conn = req->conn;
9080 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9081 struct trans_state *state;
9083 START_PROFILE(SMBtranss2);
9085 show_msg((const char *)req->inbuf);
9087 /* Windows clients expect all replies to
9088 a transact secondary (SMBtranss2 0x33)
9089 to have a command code of transact
9090 (SMBtrans2 0x32). See bug #8989
9091 and also [MS-CIFS] section 2.2.4.47.2
9092 for details.
9094 req->cmd = SMBtrans2;
9096 if (req->wct < 8) {
9097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9098 END_PROFILE(SMBtranss2);
9099 return;
9102 for (state = conn->pending_trans; state != NULL;
9103 state = state->next) {
9104 if (state->mid == req->mid) {
9105 break;
9109 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9111 END_PROFILE(SMBtranss2);
9112 return;
9115 /* Revise state->total_param and state->total_data in case they have
9116 changed downwards */
9118 if (SVAL(req->vwv+0, 0) < state->total_param)
9119 state->total_param = SVAL(req->vwv+0, 0);
9120 if (SVAL(req->vwv+1, 0) < state->total_data)
9121 state->total_data = SVAL(req->vwv+1, 0);
9123 pcnt = SVAL(req->vwv+2, 0);
9124 poff = SVAL(req->vwv+3, 0);
9125 pdisp = SVAL(req->vwv+4, 0);
9127 dcnt = SVAL(req->vwv+5, 0);
9128 doff = SVAL(req->vwv+6, 0);
9129 ddisp = SVAL(req->vwv+7, 0);
9131 state->received_param += pcnt;
9132 state->received_data += dcnt;
9134 if ((state->received_data > state->total_data) ||
9135 (state->received_param > state->total_param))
9136 goto bad_param;
9138 if (pcnt) {
9139 if (trans_oob(state->total_param, pdisp, pcnt)
9140 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9141 goto bad_param;
9143 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9146 if (dcnt) {
9147 if (trans_oob(state->total_data, ddisp, dcnt)
9148 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9149 goto bad_param;
9151 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9154 if ((state->received_param < state->total_param) ||
9155 (state->received_data < state->total_data)) {
9156 END_PROFILE(SMBtranss2);
9157 return;
9160 handle_trans2(conn, req, state);
9162 DLIST_REMOVE(conn->pending_trans, state);
9163 SAFE_FREE(state->data);
9164 SAFE_FREE(state->param);
9165 TALLOC_FREE(state);
9167 END_PROFILE(SMBtranss2);
9168 return;
9170 bad_param:
9172 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9173 DLIST_REMOVE(conn->pending_trans, state);
9174 SAFE_FREE(state->data);
9175 SAFE_FREE(state->param);
9176 TALLOC_FREE(state);
9177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9178 END_PROFILE(SMBtranss2);
9179 return;