Fix the erroneous masking of chmod requests via the UNIX extensions.
[Samba/wip.git] / source3 / smbd / trans2.c
blobbafd3f76dd29e3a9f66038d0ba00f978c7bcee92
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) {
1396 /* Apply mode mask */
1397 ret &= lp_create_mask(SNUM(conn));
1398 /* Add in force bits */
1399 ret |= lp_force_create_mode(SNUM(conn));
1400 } else if (ptype == PERM_NEW_DIR) {
1401 ret &= lp_dir_mask(SNUM(conn));
1402 /* Add in force bits */
1403 ret |= lp_force_dir_mode(SNUM(conn));
1406 *ret_perms = ret;
1407 return NT_STATUS_OK;
1410 /****************************************************************************
1411 Needed to show the msdfs symlinks as directories. Modifies psbuf
1412 to be a directory if it's a msdfs link.
1413 ****************************************************************************/
1415 static bool check_msdfs_link(connection_struct *conn,
1416 const char *pathname,
1417 SMB_STRUCT_STAT *psbuf)
1419 int saved_errno = errno;
1420 if(lp_host_msdfs() &&
1421 lp_msdfs_root(SNUM(conn)) &&
1422 is_msdfs_link(conn, pathname, psbuf)) {
1424 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1425 "as a directory\n",
1426 pathname));
1427 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1428 errno = saved_errno;
1429 return true;
1431 errno = saved_errno;
1432 return false;
1436 /****************************************************************************
1437 Get a level dependent lanman2 dir entry.
1438 ****************************************************************************/
1440 struct smbd_dirptr_lanman2_state {
1441 connection_struct *conn;
1442 uint32_t info_level;
1443 bool check_mangled_names;
1444 bool has_wild;
1445 bool got_exact_match;
1448 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1449 void *private_data,
1450 const char *dname,
1451 const char *mask,
1452 char **_fname)
1454 struct smbd_dirptr_lanman2_state *state =
1455 (struct smbd_dirptr_lanman2_state *)private_data;
1456 bool ok;
1457 char mangled_name[13]; /* mangled 8.3 name. */
1458 bool got_match;
1459 const char *fname;
1461 /* Mangle fname if it's an illegal name. */
1462 if (mangle_must_mangle(dname, state->conn->params)) {
1463 ok = name_to_8_3(dname, mangled_name,
1464 true, state->conn->params);
1465 if (!ok) {
1466 return false;
1468 fname = mangled_name;
1469 } else {
1470 fname = dname;
1473 got_match = exact_match(state->has_wild,
1474 state->conn->case_sensitive,
1475 fname, mask);
1476 state->got_exact_match = got_match;
1477 if (!got_match) {
1478 got_match = mask_match(fname, mask,
1479 state->conn->case_sensitive);
1482 if(!got_match && state->check_mangled_names &&
1483 !mangle_is_8_3(fname, false, state->conn->params)) {
1485 * It turns out that NT matches wildcards against
1486 * both long *and* short names. This may explain some
1487 * of the wildcard wierdness from old DOS clients
1488 * that some people have been seeing.... JRA.
1490 /* Force the mangling into 8.3. */
1491 ok = name_to_8_3(fname, mangled_name,
1492 false, state->conn->params);
1493 if (!ok) {
1494 return false;
1497 got_match = exact_match(state->has_wild,
1498 state->conn->case_sensitive,
1499 mangled_name, mask);
1500 state->got_exact_match = got_match;
1501 if (!got_match) {
1502 got_match = mask_match(mangled_name, mask,
1503 state->conn->case_sensitive);
1507 if (!got_match) {
1508 return false;
1511 *_fname = talloc_strdup(ctx, fname);
1512 if (*_fname == NULL) {
1513 return false;
1516 return true;
1519 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1520 void *private_data,
1521 struct smb_filename *smb_fname,
1522 uint32_t *_mode)
1524 struct smbd_dirptr_lanman2_state *state =
1525 (struct smbd_dirptr_lanman2_state *)private_data;
1526 bool ms_dfs_link = false;
1527 uint32_t mode = 0;
1529 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1530 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1531 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1532 "Couldn't lstat [%s] (%s)\n",
1533 smb_fname_str_dbg(smb_fname),
1534 strerror(errno)));
1535 return false;
1537 } else if (!VALID_STAT(smb_fname->st) &&
1538 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1539 /* Needed to show the msdfs symlinks as
1540 * directories */
1542 ms_dfs_link = check_msdfs_link(state->conn,
1543 smb_fname->base_name,
1544 &smb_fname->st);
1545 if (!ms_dfs_link) {
1546 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1547 "Couldn't stat [%s] (%s)\n",
1548 smb_fname_str_dbg(smb_fname),
1549 strerror(errno)));
1550 return false;
1554 if (ms_dfs_link) {
1555 mode = dos_mode_msdfs(state->conn, smb_fname);
1556 } else {
1557 mode = dos_mode(state->conn, smb_fname);
1560 *_mode = mode;
1561 return true;
1564 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1565 connection_struct *conn,
1566 uint16_t flags2,
1567 uint32_t info_level,
1568 struct ea_list *name_list,
1569 bool check_mangled_names,
1570 bool requires_resume_key,
1571 uint32_t mode,
1572 const char *fname,
1573 const struct smb_filename *smb_fname,
1574 int space_remaining,
1575 uint8_t align,
1576 bool do_pad,
1577 char *base_data,
1578 char **ppdata,
1579 char *end_data,
1580 bool *out_of_space,
1581 uint64_t *last_entry_off)
1583 char *p, *q, *pdata = *ppdata;
1584 uint32_t reskey=0;
1585 uint64_t file_size = 0;
1586 uint64_t allocation_size = 0;
1587 uint64_t file_index = 0;
1588 uint32_t len;
1589 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1590 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1591 char *nameptr;
1592 char *last_entry_ptr;
1593 bool was_8_3;
1594 int off;
1595 int pad = 0;
1597 *out_of_space = false;
1599 ZERO_STRUCT(mdate_ts);
1600 ZERO_STRUCT(adate_ts);
1601 ZERO_STRUCT(create_date_ts);
1602 ZERO_STRUCT(cdate_ts);
1604 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1605 file_size = get_file_size_stat(&smb_fname->st);
1607 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1609 file_index = get_FileIndex(conn, &smb_fname->st);
1611 mdate_ts = smb_fname->st.st_ex_mtime;
1612 adate_ts = smb_fname->st.st_ex_atime;
1613 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1614 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1616 if (lp_dos_filetime_resolution(SNUM(conn))) {
1617 dos_filetime_timespec(&create_date_ts);
1618 dos_filetime_timespec(&mdate_ts);
1619 dos_filetime_timespec(&adate_ts);
1620 dos_filetime_timespec(&cdate_ts);
1623 create_date = convert_timespec_to_time_t(create_date_ts);
1624 mdate = convert_timespec_to_time_t(mdate_ts);
1625 adate = convert_timespec_to_time_t(adate_ts);
1627 /* align the record */
1628 SMB_ASSERT(align >= 1);
1630 off = (int)PTR_DIFF(pdata, base_data);
1631 pad = (off + (align-1)) & ~(align-1);
1632 pad -= off;
1634 if (pad && pad > space_remaining) {
1635 *out_of_space = true;
1636 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1637 "for padding (wanted %u, had %d)\n",
1638 (unsigned int)pad,
1639 space_remaining ));
1640 return false; /* Not finished - just out of space */
1643 off += pad;
1644 /* initialize padding to 0 */
1645 if (pad) {
1646 memset(pdata, 0, pad);
1648 space_remaining -= pad;
1650 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1651 space_remaining ));
1653 pdata += pad;
1654 p = pdata;
1655 last_entry_ptr = p;
1657 pad = 0;
1658 off = 0;
1660 switch (info_level) {
1661 case SMB_FIND_INFO_STANDARD:
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1663 if(requires_resume_key) {
1664 SIVAL(p,0,reskey);
1665 p += 4;
1667 srv_put_dos_date2(p,0,create_date);
1668 srv_put_dos_date2(p,4,adate);
1669 srv_put_dos_date2(p,8,mdate);
1670 SIVAL(p,12,(uint32)file_size);
1671 SIVAL(p,16,(uint32)allocation_size);
1672 SSVAL(p,20,mode);
1673 p += 23;
1674 nameptr = p;
1675 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1676 p += ucs2_align(base_data, p, 0);
1678 len = srvstr_push(base_data, flags2, p,
1679 fname, PTR_DIFF(end_data, p),
1680 STR_TERMINATE);
1681 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1682 if (len > 2) {
1683 SCVAL(nameptr, -1, len - 2);
1684 } else {
1685 SCVAL(nameptr, -1, 0);
1687 } else {
1688 if (len > 1) {
1689 SCVAL(nameptr, -1, len - 1);
1690 } else {
1691 SCVAL(nameptr, -1, 0);
1694 p += len;
1695 break;
1697 case SMB_FIND_EA_SIZE:
1698 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1699 if (requires_resume_key) {
1700 SIVAL(p,0,reskey);
1701 p += 4;
1703 srv_put_dos_date2(p,0,create_date);
1704 srv_put_dos_date2(p,4,adate);
1705 srv_put_dos_date2(p,8,mdate);
1706 SIVAL(p,12,(uint32)file_size);
1707 SIVAL(p,16,(uint32)allocation_size);
1708 SSVAL(p,20,mode);
1710 unsigned int ea_size = estimate_ea_size(conn, NULL,
1711 smb_fname);
1712 SIVAL(p,22,ea_size); /* Extended attributes */
1714 p += 27;
1715 nameptr = p - 1;
1716 len = srvstr_push(base_data, flags2,
1717 p, fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE | STR_NOALIGN);
1719 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1720 if (len > 2) {
1721 len -= 2;
1722 } else {
1723 len = 0;
1725 } else {
1726 if (len > 1) {
1727 len -= 1;
1728 } else {
1729 len = 0;
1732 SCVAL(nameptr,0,len);
1733 p += len;
1734 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1735 break;
1737 case SMB_FIND_EA_LIST:
1739 struct ea_list *file_list = NULL;
1740 size_t ea_len = 0;
1741 NTSTATUS status;
1743 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1744 if (!name_list) {
1745 return false;
1747 if (requires_resume_key) {
1748 SIVAL(p,0,reskey);
1749 p += 4;
1751 srv_put_dos_date2(p,0,create_date);
1752 srv_put_dos_date2(p,4,adate);
1753 srv_put_dos_date2(p,8,mdate);
1754 SIVAL(p,12,(uint32)file_size);
1755 SIVAL(p,16,(uint32)allocation_size);
1756 SSVAL(p,20,mode);
1757 p += 22; /* p now points to the EA area. */
1759 status = get_ea_list_from_file(ctx, conn, NULL,
1760 smb_fname,
1761 &ea_len, &file_list);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 file_list = NULL;
1765 name_list = ea_list_union(name_list, file_list, &ea_len);
1767 /* We need to determine if this entry will fit in the space available. */
1768 /* Max string size is 255 bytes. */
1769 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1770 *out_of_space = true;
1771 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1772 "(wanted %u, had %d)\n",
1773 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1774 space_remaining ));
1775 return False; /* Not finished - just out of space */
1778 /* Push the ea_data followed by the name. */
1779 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1780 nameptr = p;
1781 len = srvstr_push(base_data, flags2,
1782 p + 1, fname, PTR_DIFF(end_data, p+1),
1783 STR_TERMINATE | STR_NOALIGN);
1784 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1785 if (len > 2) {
1786 len -= 2;
1787 } else {
1788 len = 0;
1790 } else {
1791 if (len > 1) {
1792 len -= 1;
1793 } else {
1794 len = 0;
1797 SCVAL(nameptr,0,len);
1798 p += len + 1;
1799 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1800 break;
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1805 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1806 p += 4;
1807 SIVAL(p,0,reskey); p += 4;
1808 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1809 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1810 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1811 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1812 SOFF_T(p,0,file_size); p += 8;
1813 SOFF_T(p,0,allocation_size); p += 8;
1814 SIVAL(p,0,mode); p += 4;
1815 q = p; p += 4; /* q is placeholder for name length. */
1816 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1817 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1818 } else {
1819 unsigned int ea_size = estimate_ea_size(conn, NULL,
1820 smb_fname);
1821 SIVAL(p,0,ea_size); /* Extended attributes */
1823 p += 4;
1824 /* Clear the short name buffer. This is
1825 * IMPORTANT as not doing so will trigger
1826 * a Win2k client bug. JRA.
1828 if (!was_8_3 && check_mangled_names) {
1829 char mangled_name[13]; /* mangled 8.3 name. */
1830 if (!name_to_8_3(fname,mangled_name,True,
1831 conn->params)) {
1832 /* Error - mangle failed ! */
1833 memset(mangled_name,'\0',12);
1835 mangled_name[12] = 0;
1836 len = srvstr_push(base_data, flags2,
1837 p+2, mangled_name, 24,
1838 STR_UPPER|STR_UNICODE);
1839 if (len < 24) {
1840 memset(p + 2 + len,'\0',24 - len);
1842 SSVAL(p, 0, len);
1843 } else {
1844 memset(p,'\0',26);
1846 p += 2 + 24;
1847 len = srvstr_push(base_data, flags2, p,
1848 fname, PTR_DIFF(end_data, p),
1849 STR_TERMINATE_ASCII);
1850 SIVAL(q,0,len);
1851 p += len;
1853 len = PTR_DIFF(p, pdata);
1854 pad = (len + (align-1)) & ~(align-1);
1856 * offset to the next entry, the caller
1857 * will overwrite it for the last entry
1858 * that's why we always include the padding
1860 SIVAL(pdata,0,pad);
1862 * set padding to zero
1864 if (do_pad) {
1865 memset(p, 0, pad - len);
1866 p = pdata + pad;
1867 } else {
1868 p = pdata + len;
1870 break;
1872 case SMB_FIND_FILE_DIRECTORY_INFO:
1873 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1874 p += 4;
1875 SIVAL(p,0,reskey); p += 4;
1876 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1878 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1879 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1880 SOFF_T(p,0,file_size); p += 8;
1881 SOFF_T(p,0,allocation_size); p += 8;
1882 SIVAL(p,0,mode); p += 4;
1883 len = srvstr_push(base_data, flags2,
1884 p + 4, fname, PTR_DIFF(end_data, p+4),
1885 STR_TERMINATE_ASCII);
1886 SIVAL(p,0,len);
1887 p += 4 + len;
1889 len = PTR_DIFF(p, pdata);
1890 pad = (len + (align-1)) & ~(align-1);
1892 * offset to the next entry, the caller
1893 * will overwrite it for the last entry
1894 * that's why we always include the padding
1896 SIVAL(pdata,0,pad);
1898 * set padding to zero
1900 if (do_pad) {
1901 memset(p, 0, pad - len);
1902 p = pdata + pad;
1903 } else {
1904 p = pdata + len;
1906 break;
1908 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1909 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1910 p += 4;
1911 SIVAL(p,0,reskey); p += 4;
1912 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1913 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1914 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1915 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1916 SOFF_T(p,0,file_size); p += 8;
1917 SOFF_T(p,0,allocation_size); p += 8;
1918 SIVAL(p,0,mode); p += 4;
1919 q = p; p += 4; /* q is placeholder for name length. */
1921 unsigned int ea_size = estimate_ea_size(conn, NULL,
1922 smb_fname);
1923 SIVAL(p,0,ea_size); /* Extended attributes */
1924 p +=4;
1926 len = srvstr_push(base_data, flags2, p,
1927 fname, PTR_DIFF(end_data, p),
1928 STR_TERMINATE_ASCII);
1929 SIVAL(q, 0, len);
1930 p += len;
1932 len = PTR_DIFF(p, pdata);
1933 pad = (len + (align-1)) & ~(align-1);
1935 * offset to the next entry, the caller
1936 * will overwrite it for the last entry
1937 * that's why we always include the padding
1939 SIVAL(pdata,0,pad);
1941 * set padding to zero
1943 if (do_pad) {
1944 memset(p, 0, pad - len);
1945 p = pdata + pad;
1946 } else {
1947 p = pdata + len;
1949 break;
1951 case SMB_FIND_FILE_NAMES_INFO:
1952 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1953 p += 4;
1954 SIVAL(p,0,reskey); p += 4;
1955 p += 4;
1956 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1957 acl on a dir (tridge) */
1958 len = srvstr_push(base_data, flags2, p,
1959 fname, PTR_DIFF(end_data, p),
1960 STR_TERMINATE_ASCII);
1961 SIVAL(p, -4, len);
1962 p += len;
1964 len = PTR_DIFF(p, pdata);
1965 pad = (len + (align-1)) & ~(align-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1971 SIVAL(pdata,0,pad);
1973 * set padding to zero
1975 if (do_pad) {
1976 memset(p, 0, pad - len);
1977 p = pdata + pad;
1978 } else {
1979 p = pdata + len;
1981 break;
1983 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1985 p += 4;
1986 SIVAL(p,0,reskey); p += 4;
1987 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1988 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1989 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1990 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1991 SOFF_T(p,0,file_size); p += 8;
1992 SOFF_T(p,0,allocation_size); p += 8;
1993 SIVAL(p,0,mode); p += 4;
1994 q = p; p += 4; /* q is placeholder for name length. */
1995 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1996 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1997 } else {
1998 unsigned int ea_size = estimate_ea_size(conn, NULL,
1999 smb_fname);
2000 SIVAL(p,0,ea_size); /* Extended attributes */
2002 p += 4;
2003 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2004 SBVAL(p,0,file_index); p += 8;
2005 len = srvstr_push(base_data, flags2, p,
2006 fname, PTR_DIFF(end_data, p),
2007 STR_TERMINATE_ASCII);
2008 SIVAL(q, 0, len);
2009 p += len;
2011 len = PTR_DIFF(p, pdata);
2012 pad = (len + (align-1)) & ~(align-1);
2014 * offset to the next entry, the caller
2015 * will overwrite it for the last entry
2016 * that's why we always include the padding
2018 SIVAL(pdata,0,pad);
2020 * set padding to zero
2022 if (do_pad) {
2023 memset(p, 0, pad - len);
2024 p = pdata + pad;
2025 } else {
2026 p = pdata + len;
2028 break;
2030 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2031 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2032 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2033 p += 4;
2034 SIVAL(p,0,reskey); p += 4;
2035 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2036 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2037 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2038 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2039 SOFF_T(p,0,file_size); p += 8;
2040 SOFF_T(p,0,allocation_size); p += 8;
2041 SIVAL(p,0,mode); p += 4;
2042 q = p; p += 4; /* q is placeholder for name length */
2043 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2044 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2045 } else {
2046 unsigned int ea_size = estimate_ea_size(conn, NULL,
2047 smb_fname);
2048 SIVAL(p,0,ea_size); /* Extended attributes */
2050 p += 4;
2051 /* Clear the short name buffer. This is
2052 * IMPORTANT as not doing so will trigger
2053 * a Win2k client bug. JRA.
2055 if (!was_8_3 && check_mangled_names) {
2056 char mangled_name[13]; /* mangled 8.3 name. */
2057 if (!name_to_8_3(fname,mangled_name,True,
2058 conn->params)) {
2059 /* Error - mangle failed ! */
2060 memset(mangled_name,'\0',12);
2062 mangled_name[12] = 0;
2063 len = srvstr_push(base_data, flags2,
2064 p+2, mangled_name, 24,
2065 STR_UPPER|STR_UNICODE);
2066 SSVAL(p, 0, len);
2067 if (len < 24) {
2068 memset(p + 2 + len,'\0',24 - len);
2070 SSVAL(p, 0, len);
2071 } else {
2072 memset(p,'\0',26);
2074 p += 26;
2075 SSVAL(p,0,0); p += 2; /* Reserved ? */
2076 SBVAL(p,0,file_index); p += 8;
2077 len = srvstr_push(base_data, flags2, p,
2078 fname, PTR_DIFF(end_data, p),
2079 STR_TERMINATE_ASCII);
2080 SIVAL(q,0,len);
2081 p += len;
2083 len = PTR_DIFF(p, pdata);
2084 pad = (len + (align-1)) & ~(align-1);
2086 * offset to the next entry, the caller
2087 * will overwrite it for the last entry
2088 * that's why we always include the padding
2090 SIVAL(pdata,0,pad);
2092 * set padding to zero
2094 if (do_pad) {
2095 memset(p, 0, pad - len);
2096 p = pdata + pad;
2097 } else {
2098 p = pdata + len;
2100 break;
2102 /* CIFS UNIX Extension. */
2104 case SMB_FIND_FILE_UNIX:
2105 case SMB_FIND_FILE_UNIX_INFO2:
2106 p+= 4;
2107 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2109 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2111 if (info_level == SMB_FIND_FILE_UNIX) {
2112 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2113 p = store_file_unix_basic(conn, p,
2114 NULL, &smb_fname->st);
2115 len = srvstr_push(base_data, flags2, p,
2116 fname, PTR_DIFF(end_data, p),
2117 STR_TERMINATE);
2118 } else {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2120 p = store_file_unix_basic_info2(conn, p,
2121 NULL, &smb_fname->st);
2122 nameptr = p;
2123 p += 4;
2124 len = srvstr_push(base_data, flags2, p, fname,
2125 PTR_DIFF(end_data, p), 0);
2126 SIVAL(nameptr, 0, len);
2129 p += len;
2131 len = PTR_DIFF(p, pdata);
2132 pad = (len + (align-1)) & ~(align-1);
2134 * offset to the next entry, the caller
2135 * will overwrite it for the last entry
2136 * that's why we always include the padding
2138 SIVAL(pdata,0,pad);
2140 * set padding to zero
2142 if (do_pad) {
2143 memset(p, 0, pad - len);
2144 p = pdata + pad;
2145 } else {
2146 p = pdata + len;
2148 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2150 break;
2152 default:
2153 return false;
2156 if (PTR_DIFF(p,pdata) > space_remaining) {
2157 *out_of_space = true;
2158 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2159 "(wanted %u, had %d)\n",
2160 (unsigned int)PTR_DIFF(p,pdata),
2161 space_remaining ));
2162 return false; /* Not finished - just out of space */
2165 /* Setup the last entry pointer, as an offset from base_data */
2166 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2167 /* Advance the data pointer to the next slot */
2168 *ppdata = p;
2170 return true;
2173 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2174 connection_struct *conn,
2175 struct dptr_struct *dirptr,
2176 uint16 flags2,
2177 const char *path_mask,
2178 uint32 dirtype,
2179 int info_level,
2180 int requires_resume_key,
2181 bool dont_descend,
2182 bool ask_sharemode,
2183 uint8_t align,
2184 bool do_pad,
2185 char **ppdata,
2186 char *base_data,
2187 char *end_data,
2188 int space_remaining,
2189 bool *out_of_space,
2190 bool *got_exact_match,
2191 int *_last_entry_off,
2192 struct ea_list *name_list)
2194 const char *p;
2195 const char *mask = NULL;
2196 long prev_dirpos = 0;
2197 uint32_t mode = 0;
2198 char *fname = NULL;
2199 struct smb_filename *smb_fname = NULL;
2200 struct smbd_dirptr_lanman2_state state;
2201 bool ok;
2202 uint64_t last_entry_off = 0;
2204 ZERO_STRUCT(state);
2205 state.conn = conn;
2206 state.info_level = info_level;
2207 state.check_mangled_names = lp_manglednames(conn->params);
2208 state.has_wild = dptr_has_wild(dirptr);
2209 state.got_exact_match = false;
2211 *out_of_space = false;
2212 *got_exact_match = false;
2214 p = strrchr_m(path_mask,'/');
2215 if(p != NULL) {
2216 if(p[1] == '\0') {
2217 mask = "*.*";
2218 } else {
2219 mask = p+1;
2221 } else {
2222 mask = path_mask;
2225 ok = smbd_dirptr_get_entry(ctx,
2226 dirptr,
2227 mask,
2228 dirtype,
2229 dont_descend,
2230 ask_sharemode,
2231 smbd_dirptr_lanman2_match_fn,
2232 smbd_dirptr_lanman2_mode_fn,
2233 &state,
2234 &fname,
2235 &smb_fname,
2236 &mode,
2237 &prev_dirpos);
2238 if (!ok) {
2239 return false;
2242 *got_exact_match = state.got_exact_match;
2244 ok = smbd_marshall_dir_entry(ctx,
2245 conn,
2246 flags2,
2247 info_level,
2248 name_list,
2249 state.check_mangled_names,
2250 requires_resume_key,
2251 mode,
2252 fname,
2253 smb_fname,
2254 space_remaining,
2255 align,
2256 do_pad,
2257 base_data,
2258 ppdata,
2259 end_data,
2260 out_of_space,
2261 &last_entry_off);
2262 TALLOC_FREE(fname);
2263 TALLOC_FREE(smb_fname);
2264 if (*out_of_space) {
2265 dptr_SeekDir(dirptr, prev_dirpos);
2266 return false;
2268 if (!ok) {
2269 return false;
2272 *_last_entry_off = last_entry_off;
2273 return true;
2276 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2277 connection_struct *conn,
2278 struct dptr_struct *dirptr,
2279 uint16 flags2,
2280 const char *path_mask,
2281 uint32 dirtype,
2282 int info_level,
2283 bool requires_resume_key,
2284 bool dont_descend,
2285 bool ask_sharemode,
2286 char **ppdata,
2287 char *base_data,
2288 char *end_data,
2289 int space_remaining,
2290 bool *out_of_space,
2291 bool *got_exact_match,
2292 int *last_entry_off,
2293 struct ea_list *name_list)
2295 uint8_t align = 4;
2296 const bool do_pad = true;
2298 if (info_level >= 1 && info_level <= 3) {
2299 /* No alignment on earlier info levels. */
2300 align = 1;
2303 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2304 path_mask, dirtype, info_level,
2305 requires_resume_key, dont_descend, ask_sharemode,
2306 align, do_pad,
2307 ppdata, base_data, end_data,
2308 space_remaining,
2309 out_of_space, got_exact_match,
2310 last_entry_off, name_list);
2313 /****************************************************************************
2314 Reply to a TRANS2_FINDFIRST.
2315 ****************************************************************************/
2317 static void call_trans2findfirst(connection_struct *conn,
2318 struct smb_request *req,
2319 char **pparams, int total_params,
2320 char **ppdata, int total_data,
2321 unsigned int max_data_bytes)
2323 /* We must be careful here that we don't return more than the
2324 allowed number of data bytes. If this means returning fewer than
2325 maxentries then so be it. We assume that the redirector has
2326 enough room for the fixed number of parameter bytes it has
2327 requested. */
2328 struct smb_filename *smb_dname = NULL;
2329 char *params = *pparams;
2330 char *pdata = *ppdata;
2331 char *data_end;
2332 uint32 dirtype;
2333 int maxentries;
2334 uint16 findfirst_flags;
2335 bool close_after_first;
2336 bool close_if_end;
2337 bool requires_resume_key;
2338 int info_level;
2339 char *directory = NULL;
2340 char *mask = NULL;
2341 char *p;
2342 int last_entry_off=0;
2343 int dptr_num = -1;
2344 int numentries = 0;
2345 int i;
2346 bool finished = False;
2347 bool dont_descend = False;
2348 bool out_of_space = False;
2349 int space_remaining;
2350 bool mask_contains_wcard = False;
2351 struct ea_list *ea_list = NULL;
2352 NTSTATUS ntstatus = NT_STATUS_OK;
2353 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2354 TALLOC_CTX *ctx = talloc_tos();
2355 struct dptr_struct *dirptr = NULL;
2356 struct smbd_server_connection *sconn = req->sconn;
2357 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2358 bool backup_priv = false;
2360 if (total_params < 13) {
2361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2362 goto out;
2365 dirtype = SVAL(params,0);
2366 maxentries = SVAL(params,2);
2367 findfirst_flags = SVAL(params,4);
2368 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2369 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2370 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2371 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2372 security_token_has_privilege(get_current_nttok(conn),
2373 SEC_PRIV_BACKUP));
2375 info_level = SVAL(params,6);
2377 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2378 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2379 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2380 (int)backup_priv,
2381 info_level, max_data_bytes));
2383 if (!maxentries) {
2384 /* W2K3 seems to treat zero as 1. */
2385 maxentries = 1;
2388 switch (info_level) {
2389 case SMB_FIND_INFO_STANDARD:
2390 case SMB_FIND_EA_SIZE:
2391 case SMB_FIND_EA_LIST:
2392 case SMB_FIND_FILE_DIRECTORY_INFO:
2393 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2394 case SMB_FIND_FILE_NAMES_INFO:
2395 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2396 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2397 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2398 break;
2399 case SMB_FIND_FILE_UNIX:
2400 case SMB_FIND_FILE_UNIX_INFO2:
2401 /* Always use filesystem for UNIX mtime query. */
2402 ask_sharemode = false;
2403 if (!lp_unix_extensions()) {
2404 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2405 goto out;
2407 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2408 break;
2409 default:
2410 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2411 goto out;
2414 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2415 params+12, total_params - 12,
2416 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2417 if (!NT_STATUS_IS_OK(ntstatus)) {
2418 reply_nterror(req, ntstatus);
2419 goto out;
2422 if (backup_priv) {
2423 become_root();
2424 ntstatus = filename_convert_with_privilege(ctx,
2425 conn,
2426 req,
2427 directory,
2428 ucf_flags,
2429 &mask_contains_wcard,
2430 &smb_dname);
2431 } else {
2432 ntstatus = filename_convert(ctx, conn,
2433 req->flags2 & FLAGS2_DFS_PATHNAMES,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2440 if (!NT_STATUS_IS_OK(ntstatus)) {
2441 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2442 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2443 ERRSRV, ERRbadpath);
2444 goto out;
2446 reply_nterror(req, ntstatus);
2447 goto out;
2450 mask = smb_dname->original_lcomp;
2452 directory = smb_dname->base_name;
2454 p = strrchr_m(directory,'/');
2455 if(p == NULL) {
2456 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2457 if((directory[0] == '.') && (directory[1] == '\0')) {
2458 mask = talloc_strdup(ctx,"*");
2459 if (!mask) {
2460 reply_nterror(req, NT_STATUS_NO_MEMORY);
2461 goto out;
2463 mask_contains_wcard = True;
2465 } else {
2466 *p = 0;
2469 if (p == NULL || p == directory) {
2470 /* Ensure we don't have a directory name of "". */
2471 directory = talloc_strdup(talloc_tos(), ".");
2472 if (!directory) {
2473 reply_nterror(req, NT_STATUS_NO_MEMORY);
2474 goto out;
2478 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2480 if (info_level == SMB_FIND_EA_LIST) {
2481 uint32 ea_size;
2483 if (total_data < 4) {
2484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2485 goto out;
2488 ea_size = IVAL(pdata,0);
2489 if (ea_size != total_data) {
2490 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2491 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2493 goto out;
2496 if (!lp_ea_support(SNUM(conn))) {
2497 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2498 goto out;
2501 /* Pull out the list of names. */
2502 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2503 if (!ea_list) {
2504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2505 goto out;
2509 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2511 goto out;
2514 *ppdata = (char *)SMB_REALLOC(
2515 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2516 if(*ppdata == NULL ) {
2517 reply_nterror(req, NT_STATUS_NO_MEMORY);
2518 goto out;
2520 pdata = *ppdata;
2521 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2523 /* Realloc the params space */
2524 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2525 if (*pparams == NULL) {
2526 reply_nterror(req, NT_STATUS_NO_MEMORY);
2527 goto out;
2529 params = *pparams;
2531 /* Save the wildcard match and attribs we are using on this directory -
2532 needed as lanman2 assumes these are being saved between calls */
2534 ntstatus = dptr_create(conn,
2535 req,
2536 NULL, /* fsp */
2537 directory,
2538 False,
2539 True,
2540 req->smbpid,
2541 mask,
2542 mask_contains_wcard,
2543 dirtype,
2544 &dirptr);
2546 if (!NT_STATUS_IS_OK(ntstatus)) {
2547 reply_nterror(req, ntstatus);
2548 goto out;
2551 if (backup_priv) {
2552 /* Remember this in case we have
2553 to do a findnext. */
2554 dptr_set_priv(dirptr);
2557 dptr_num = dptr_dnum(dirptr);
2558 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2560 /* Initialize per TRANS2_FIND_FIRST operation data */
2561 dptr_init_search_op(dirptr);
2563 /* We don't need to check for VOL here as this is returned by
2564 a different TRANS2 call. */
2566 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2567 directory,lp_dontdescend(ctx, SNUM(conn))));
2568 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2569 dont_descend = True;
2571 p = pdata;
2572 space_remaining = max_data_bytes;
2573 out_of_space = False;
2575 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2576 bool got_exact_match = False;
2578 /* this is a heuristic to avoid seeking the dirptr except when
2579 absolutely necessary. It allows for a filename of about 40 chars */
2580 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2581 out_of_space = True;
2582 finished = False;
2583 } else {
2584 finished = !get_lanman2_dir_entry(ctx,
2585 conn,
2586 dirptr,
2587 req->flags2,
2588 mask,dirtype,info_level,
2589 requires_resume_key,dont_descend,
2590 ask_sharemode,
2591 &p,pdata,data_end,
2592 space_remaining, &out_of_space,
2593 &got_exact_match,
2594 &last_entry_off, ea_list);
2597 if (finished && out_of_space)
2598 finished = False;
2600 if (!finished && !out_of_space)
2601 numentries++;
2604 * As an optimisation if we know we aren't looking
2605 * for a wildcard name (ie. the name matches the wildcard exactly)
2606 * then we can finish on any (first) match.
2607 * This speeds up large directory searches. JRA.
2610 if(got_exact_match)
2611 finished = True;
2613 /* Ensure space_remaining never goes -ve. */
2614 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2615 space_remaining = 0;
2616 out_of_space = true;
2617 } else {
2618 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2622 /* Check if we can close the dirptr */
2623 if(close_after_first || (finished && close_if_end)) {
2624 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2625 dptr_close(sconn, &dptr_num);
2629 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2630 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2631 * the protocol level is less than NT1. Tested with smbclient. JRA.
2632 * This should fix the OS/2 client bug #2335.
2635 if(numentries == 0) {
2636 dptr_close(sconn, &dptr_num);
2637 if (get_Protocol() < PROTOCOL_NT1) {
2638 reply_force_doserror(req, ERRDOS, ERRnofiles);
2639 goto out;
2640 } else {
2641 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2642 ERRDOS, ERRbadfile);
2643 goto out;
2647 /* At this point pdata points to numentries directory entries. */
2649 /* Set up the return parameter block */
2650 SSVAL(params,0,dptr_num);
2651 SSVAL(params,2,numentries);
2652 SSVAL(params,4,finished);
2653 SSVAL(params,6,0); /* Never an EA error */
2654 SSVAL(params,8,last_entry_off);
2656 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2657 max_data_bytes);
2659 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2660 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2661 if (!directory) {
2662 reply_nterror(req, NT_STATUS_NO_MEMORY);
2666 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2667 smb_fn_name(req->cmd),
2668 mask, directory, dirtype, numentries ) );
2671 * Force a name mangle here to ensure that the
2672 * mask as an 8.3 name is top of the mangled cache.
2673 * The reasons for this are subtle. Don't remove
2674 * this code unless you know what you are doing
2675 * (see PR#13758). JRA.
2678 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2679 char mangled_name[13];
2680 name_to_8_3(mask, mangled_name, True, conn->params);
2682 out:
2684 if (backup_priv) {
2685 unbecome_root();
2688 TALLOC_FREE(smb_dname);
2689 return;
2692 /****************************************************************************
2693 Reply to a TRANS2_FINDNEXT.
2694 ****************************************************************************/
2696 static void call_trans2findnext(connection_struct *conn,
2697 struct smb_request *req,
2698 char **pparams, int total_params,
2699 char **ppdata, int total_data,
2700 unsigned int max_data_bytes)
2702 /* We must be careful here that we don't return more than the
2703 allowed number of data bytes. If this means returning fewer than
2704 maxentries then so be it. We assume that the redirector has
2705 enough room for the fixed number of parameter bytes it has
2706 requested. */
2707 char *params = *pparams;
2708 char *pdata = *ppdata;
2709 char *data_end;
2710 int dptr_num;
2711 int maxentries;
2712 uint16 info_level;
2713 uint32 resume_key;
2714 uint16 findnext_flags;
2715 bool close_after_request;
2716 bool close_if_end;
2717 bool requires_resume_key;
2718 bool continue_bit;
2719 bool mask_contains_wcard = False;
2720 char *resume_name = NULL;
2721 const char *mask = NULL;
2722 const char *directory = NULL;
2723 char *p = NULL;
2724 uint16 dirtype;
2725 int numentries = 0;
2726 int i, last_entry_off=0;
2727 bool finished = False;
2728 bool dont_descend = False;
2729 bool out_of_space = False;
2730 int space_remaining;
2731 struct ea_list *ea_list = NULL;
2732 NTSTATUS ntstatus = NT_STATUS_OK;
2733 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2734 TALLOC_CTX *ctx = talloc_tos();
2735 struct dptr_struct *dirptr;
2736 struct smbd_server_connection *sconn = req->sconn;
2737 bool backup_priv = false;
2739 if (total_params < 13) {
2740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2741 return;
2744 dptr_num = SVAL(params,0);
2745 maxentries = SVAL(params,2);
2746 info_level = SVAL(params,4);
2747 resume_key = IVAL(params,6);
2748 findnext_flags = SVAL(params,10);
2749 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2750 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2751 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2752 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2754 if (!continue_bit) {
2755 /* We only need resume_name if continue_bit is zero. */
2756 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2757 params+12,
2758 total_params - 12, STR_TERMINATE, &ntstatus,
2759 &mask_contains_wcard);
2760 if (!NT_STATUS_IS_OK(ntstatus)) {
2761 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2762 complain (it thinks we're asking for the directory above the shared
2763 path or an invalid name). Catch this as the resume name is only compared, never used in
2764 a file access. JRA. */
2765 srvstr_pull_talloc(ctx, params, req->flags2,
2766 &resume_name, params+12,
2767 total_params - 12,
2768 STR_TERMINATE);
2770 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2771 reply_nterror(req, ntstatus);
2772 return;
2777 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2778 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2779 resume_key = %d resume name = %s continue=%d level = %d\n",
2780 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2781 requires_resume_key, resume_key,
2782 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2784 if (!maxentries) {
2785 /* W2K3 seems to treat zero as 1. */
2786 maxentries = 1;
2789 switch (info_level) {
2790 case SMB_FIND_INFO_STANDARD:
2791 case SMB_FIND_EA_SIZE:
2792 case SMB_FIND_EA_LIST:
2793 case SMB_FIND_FILE_DIRECTORY_INFO:
2794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2795 case SMB_FIND_FILE_NAMES_INFO:
2796 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2797 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2798 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2799 break;
2800 case SMB_FIND_FILE_UNIX:
2801 case SMB_FIND_FILE_UNIX_INFO2:
2802 /* Always use filesystem for UNIX mtime query. */
2803 ask_sharemode = false;
2804 if (!lp_unix_extensions()) {
2805 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2806 return;
2808 break;
2809 default:
2810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2811 return;
2814 if (info_level == SMB_FIND_EA_LIST) {
2815 uint32 ea_size;
2817 if (total_data < 4) {
2818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2819 return;
2822 ea_size = IVAL(pdata,0);
2823 if (ea_size != total_data) {
2824 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2825 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 return;
2830 if (!lp_ea_support(SNUM(conn))) {
2831 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2832 return;
2835 /* Pull out the list of names. */
2836 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2837 if (!ea_list) {
2838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2839 return;
2843 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2845 return;
2848 *ppdata = (char *)SMB_REALLOC(
2849 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2850 if(*ppdata == NULL) {
2851 reply_nterror(req, NT_STATUS_NO_MEMORY);
2852 return;
2855 pdata = *ppdata;
2856 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2858 /* Realloc the params space */
2859 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2860 if(*pparams == NULL ) {
2861 reply_nterror(req, NT_STATUS_NO_MEMORY);
2862 return;
2865 params = *pparams;
2867 /* Check that the dptr is valid */
2868 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2869 reply_nterror(req, STATUS_NO_MORE_FILES);
2870 return;
2873 directory = dptr_path(sconn, dptr_num);
2875 /* Get the wildcard mask from the dptr */
2876 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2877 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2878 reply_nterror(req, STATUS_NO_MORE_FILES);
2879 return;
2882 /* Get the attr mask from the dptr */
2883 dirtype = dptr_attr(sconn, dptr_num);
2885 backup_priv = dptr_get_priv(dirptr);
2887 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2888 "backup_priv = %d\n",
2889 dptr_num, mask, dirtype,
2890 (long)dirptr,
2891 dptr_TellDir(dirptr),
2892 (int)backup_priv));
2894 /* Initialize per TRANS2_FIND_NEXT operation data */
2895 dptr_init_search_op(dirptr);
2897 /* We don't need to check for VOL here as this is returned by
2898 a different TRANS2 call. */
2900 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2901 directory,lp_dontdescend(ctx, SNUM(conn))));
2902 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2903 dont_descend = True;
2905 p = pdata;
2906 space_remaining = max_data_bytes;
2907 out_of_space = False;
2909 if (backup_priv) {
2910 become_root();
2914 * Seek to the correct position. We no longer use the resume key but
2915 * depend on the last file name instead.
2918 if(!continue_bit && resume_name && *resume_name) {
2919 SMB_STRUCT_STAT st;
2921 long current_pos = 0;
2923 * Remember, name_to_8_3 is called by
2924 * get_lanman2_dir_entry(), so the resume name
2925 * could be mangled. Ensure we check the unmangled name.
2928 if (mangle_is_mangled(resume_name, conn->params)) {
2929 char *new_resume_name = NULL;
2930 mangle_lookup_name_from_8_3(ctx,
2931 resume_name,
2932 &new_resume_name,
2933 conn->params);
2934 if (new_resume_name) {
2935 resume_name = new_resume_name;
2940 * Fix for NT redirector problem triggered by resume key indexes
2941 * changing between directory scans. We now return a resume key of 0
2942 * and instead look for the filename to continue from (also given
2943 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2944 * findfirst/findnext (as is usual) then the directory pointer
2945 * should already be at the correct place.
2948 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2949 } /* end if resume_name && !continue_bit */
2951 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2952 bool got_exact_match = False;
2954 /* this is a heuristic to avoid seeking the dirptr except when
2955 absolutely necessary. It allows for a filename of about 40 chars */
2956 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2957 out_of_space = True;
2958 finished = False;
2959 } else {
2960 finished = !get_lanman2_dir_entry(ctx,
2961 conn,
2962 dirptr,
2963 req->flags2,
2964 mask,dirtype,info_level,
2965 requires_resume_key,dont_descend,
2966 ask_sharemode,
2967 &p,pdata,data_end,
2968 space_remaining, &out_of_space,
2969 &got_exact_match,
2970 &last_entry_off, ea_list);
2973 if (finished && out_of_space)
2974 finished = False;
2976 if (!finished && !out_of_space)
2977 numentries++;
2980 * As an optimisation if we know we aren't looking
2981 * for a wildcard name (ie. the name matches the wildcard exactly)
2982 * then we can finish on any (first) match.
2983 * This speeds up large directory searches. JRA.
2986 if(got_exact_match)
2987 finished = True;
2989 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2992 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2993 smb_fn_name(req->cmd),
2994 mask, directory, dirtype, numentries ) );
2996 /* Check if we can close the dirptr */
2997 if(close_after_request || (finished && close_if_end)) {
2998 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2999 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3002 if (backup_priv) {
3003 unbecome_root();
3006 /* Set up the return parameter block */
3007 SSVAL(params,0,numentries);
3008 SSVAL(params,2,finished);
3009 SSVAL(params,4,0); /* Never an EA error */
3010 SSVAL(params,6,last_entry_off);
3012 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3013 max_data_bytes);
3015 return;
3018 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3020 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3021 return objid;
3024 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3026 SMB_ASSERT(extended_info != NULL);
3028 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3029 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3030 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3031 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3032 #ifdef SAMBA_VERSION_REVISION
3033 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3034 #endif
3035 extended_info->samba_subversion = 0;
3036 #ifdef SAMBA_VERSION_RC_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3038 #else
3039 #ifdef SAMBA_VERSION_PRE_RELEASE
3040 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3041 #endif
3042 #endif
3043 #ifdef SAMBA_VERSION_VENDOR_PATCH
3044 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3045 #endif
3046 extended_info->samba_gitcommitdate = 0;
3047 #ifdef SAMBA_VERSION_COMMIT_TIME
3048 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3049 #endif
3051 memset(extended_info->samba_version_string, 0,
3052 sizeof(extended_info->samba_version_string));
3054 snprintf (extended_info->samba_version_string,
3055 sizeof(extended_info->samba_version_string),
3056 "%s", samba_version_string());
3059 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3060 TALLOC_CTX *mem_ctx,
3061 uint16_t info_level,
3062 uint16_t flags2,
3063 unsigned int max_data_bytes,
3064 struct smb_filename *fname,
3065 char **ppdata,
3066 int *ret_data_len)
3068 char *pdata, *end_data;
3069 int data_len = 0, len;
3070 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3071 int snum = SNUM(conn);
3072 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3073 char *filename = NULL;
3074 uint32 additional_flags = 0;
3075 struct smb_filename smb_fname;
3076 SMB_STRUCT_STAT st;
3077 NTSTATUS status = NT_STATUS_OK;
3079 if (fname == NULL || fname->base_name == NULL) {
3080 filename = ".";
3081 } else {
3082 filename = fname->base_name;
3085 if (IS_IPC(conn)) {
3086 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3087 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3088 "info level (0x%x) on IPC$.\n",
3089 (unsigned int)info_level));
3090 return NT_STATUS_ACCESS_DENIED;
3094 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3096 ZERO_STRUCT(smb_fname);
3097 smb_fname.base_name = discard_const_p(char, filename);
3099 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3100 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3101 return map_nt_error_from_unix(errno);
3104 st = smb_fname.st;
3106 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3107 return NT_STATUS_INVALID_PARAMETER;
3110 *ppdata = (char *)SMB_REALLOC(
3111 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3112 if (*ppdata == NULL) {
3113 return NT_STATUS_NO_MEMORY;
3116 pdata = *ppdata;
3117 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3118 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3120 switch (info_level) {
3121 case SMB_INFO_ALLOCATION:
3123 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3124 data_len = 18;
3125 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3126 return map_nt_error_from_unix(errno);
3129 block_size = lp_block_size(snum);
3130 if (bsize < block_size) {
3131 uint64_t factor = block_size/bsize;
3132 bsize = block_size;
3133 dsize /= factor;
3134 dfree /= factor;
3136 if (bsize > block_size) {
3137 uint64_t factor = bsize/block_size;
3138 bsize = block_size;
3139 dsize *= factor;
3140 dfree *= factor;
3142 bytes_per_sector = 512;
3143 sectors_per_unit = bsize/bytes_per_sector;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3147 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3149 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3150 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3151 SIVAL(pdata,l1_cUnit,dsize);
3152 SIVAL(pdata,l1_cUnitAvail,dfree);
3153 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3154 break;
3157 case SMB_INFO_VOLUME:
3158 /* Return volume name */
3160 * Add volume serial number - hash of a combination of
3161 * the called hostname and the service name.
3163 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3165 * Win2k3 and previous mess this up by sending a name length
3166 * one byte short. I believe only older clients (OS/2 Win9x) use
3167 * this call so try fixing this by adding a terminating null to
3168 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3170 len = srvstr_push(
3171 pdata, flags2,
3172 pdata+l2_vol_szVolLabel, vname,
3173 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3174 STR_NOALIGN|STR_TERMINATE);
3175 SCVAL(pdata,l2_vol_cch,len);
3176 data_len = l2_vol_szVolLabel + len;
3177 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3178 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3179 len, vname));
3180 break;
3182 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3183 case SMB_FS_ATTRIBUTE_INFORMATION:
3185 additional_flags = 0;
3186 #if defined(HAVE_SYS_QUOTAS)
3187 additional_flags |= FILE_VOLUME_QUOTAS;
3188 #endif
3190 if(lp_nt_acl_support(SNUM(conn))) {
3191 additional_flags |= FILE_PERSISTENT_ACLS;
3194 /* Capabilities are filled in at connection time through STATVFS call */
3195 additional_flags |= conn->fs_capabilities;
3196 additional_flags |= lp_parm_int(conn->params->service,
3197 "share", "fake_fscaps",
3200 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3201 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3202 additional_flags); /* FS ATTRIBUTES */
3204 SIVAL(pdata,4,255); /* Max filename component length */
3205 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3206 and will think we can't do long filenames */
3207 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3208 PTR_DIFF(end_data, pdata+12),
3209 STR_UNICODE);
3210 SIVAL(pdata,8,len);
3211 data_len = 12 + len;
3212 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3213 /* the client only requested a portion of the
3214 file system name */
3215 data_len = max_data_bytes;
3216 status = STATUS_BUFFER_OVERFLOW;
3218 break;
3220 case SMB_QUERY_FS_LABEL_INFO:
3221 case SMB_FS_LABEL_INFORMATION:
3222 len = srvstr_push(pdata, flags2, pdata+4, vname,
3223 PTR_DIFF(end_data, pdata+4), 0);
3224 data_len = 4 + len;
3225 SIVAL(pdata,0,len);
3226 break;
3228 case SMB_QUERY_FS_VOLUME_INFO:
3229 case SMB_FS_VOLUME_INFORMATION:
3232 * Add volume serial number - hash of a combination of
3233 * the called hostname and the service name.
3235 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3236 (str_checksum(get_local_machine_name())<<16));
3238 /* Max label len is 32 characters. */
3239 len = srvstr_push(pdata, flags2, pdata+18, vname,
3240 PTR_DIFF(end_data, pdata+18),
3241 STR_UNICODE);
3242 SIVAL(pdata,12,len);
3243 data_len = 18+len;
3245 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3246 (int)strlen(vname),vname,
3247 lp_servicename(talloc_tos(), snum)));
3248 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3249 /* the client only requested a portion of the
3250 volume label */
3251 data_len = max_data_bytes;
3252 status = STATUS_BUFFER_OVERFLOW;
3254 break;
3256 case SMB_QUERY_FS_SIZE_INFO:
3257 case SMB_FS_SIZE_INFORMATION:
3259 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3260 data_len = 24;
3261 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3262 return map_nt_error_from_unix(errno);
3264 block_size = lp_block_size(snum);
3265 if (bsize < block_size) {
3266 uint64_t factor = block_size/bsize;
3267 bsize = block_size;
3268 dsize /= factor;
3269 dfree /= factor;
3271 if (bsize > block_size) {
3272 uint64_t factor = bsize/block_size;
3273 bsize = block_size;
3274 dsize *= factor;
3275 dfree *= factor;
3277 bytes_per_sector = 512;
3278 sectors_per_unit = bsize/bytes_per_sector;
3279 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3280 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3281 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3282 SBIG_UINT(pdata,0,dsize);
3283 SBIG_UINT(pdata,8,dfree);
3284 SIVAL(pdata,16,sectors_per_unit);
3285 SIVAL(pdata,20,bytes_per_sector);
3286 break;
3289 case SMB_FS_FULL_SIZE_INFORMATION:
3291 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3292 data_len = 32;
3293 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3294 return map_nt_error_from_unix(errno);
3296 block_size = lp_block_size(snum);
3297 if (bsize < block_size) {
3298 uint64_t factor = block_size/bsize;
3299 bsize = block_size;
3300 dsize /= factor;
3301 dfree /= factor;
3303 if (bsize > block_size) {
3304 uint64_t factor = bsize/block_size;
3305 bsize = block_size;
3306 dsize *= factor;
3307 dfree *= factor;
3309 bytes_per_sector = 512;
3310 sectors_per_unit = bsize/bytes_per_sector;
3311 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3312 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3313 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3314 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3315 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3316 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3317 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3318 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3319 break;
3322 case SMB_QUERY_FS_DEVICE_INFO:
3323 case SMB_FS_DEVICE_INFORMATION:
3325 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3327 if (!CAN_WRITE(conn)) {
3328 characteristics |= FILE_READ_ONLY_DEVICE;
3330 data_len = 8;
3331 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3332 SIVAL(pdata,4,characteristics);
3333 break;
3336 #ifdef HAVE_SYS_QUOTAS
3337 case SMB_FS_QUOTA_INFORMATION:
3339 * what we have to send --metze:
3341 * Unknown1: 24 NULL bytes
3342 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3344 * Quota Flags: 2 byte :
3345 * Unknown3: 6 NULL bytes
3347 * 48 bytes total
3349 * details for Quota Flags:
3351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3354 * 0x0001 Enable Quotas: enable quota for this fs
3358 /* we need to fake up a fsp here,
3359 * because its not send in this call
3361 files_struct fsp;
3362 SMB_NTQUOTA_STRUCT quotas;
3364 ZERO_STRUCT(fsp);
3365 ZERO_STRUCT(quotas);
3367 fsp.conn = conn;
3368 fsp.fnum = FNUM_FIELD_INVALID;
3370 /* access check */
3371 if (get_current_uid(conn) != 0) {
3372 DEBUG(0,("get_user_quota: access_denied "
3373 "service [%s] user [%s]\n",
3374 lp_servicename(talloc_tos(), SNUM(conn)),
3375 conn->session_info->unix_info->unix_name));
3376 return NT_STATUS_ACCESS_DENIED;
3379 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3380 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3381 return map_nt_error_from_unix(errno);
3384 data_len = 48;
3386 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3387 lp_servicename(talloc_tos(), SNUM(conn))));
3389 /* Unknown1 24 NULL bytes*/
3390 SBIG_UINT(pdata,0,(uint64_t)0);
3391 SBIG_UINT(pdata,8,(uint64_t)0);
3392 SBIG_UINT(pdata,16,(uint64_t)0);
3394 /* Default Soft Quota 8 bytes */
3395 SBIG_UINT(pdata,24,quotas.softlim);
3397 /* Default Hard Quota 8 bytes */
3398 SBIG_UINT(pdata,32,quotas.hardlim);
3400 /* Quota flag 2 bytes */
3401 SSVAL(pdata,40,quotas.qflags);
3403 /* Unknown3 6 NULL bytes */
3404 SSVAL(pdata,42,0);
3405 SIVAL(pdata,44,0);
3407 break;
3409 #endif /* HAVE_SYS_QUOTAS */
3410 case SMB_FS_OBJECTID_INFORMATION:
3412 unsigned char objid[16];
3413 struct smb_extended_info extended_info;
3414 memcpy(pdata,create_volume_objectid(conn, objid),16);
3415 samba_extended_info_version (&extended_info);
3416 SIVAL(pdata,16,extended_info.samba_magic);
3417 SIVAL(pdata,20,extended_info.samba_version);
3418 SIVAL(pdata,24,extended_info.samba_subversion);
3419 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3420 memcpy(pdata+36,extended_info.samba_version_string,28);
3421 data_len = 64;
3422 break;
3426 * Query the version and capabilities of the CIFS UNIX extensions
3427 * in use.
3430 case SMB_QUERY_CIFS_UNIX_INFO:
3432 bool large_write = lp_min_receive_file_size() &&
3433 !srv_is_signing_active(conn->sconn);
3434 bool large_read = !srv_is_signing_active(conn->sconn);
3435 int encrypt_caps = 0;
3437 if (!lp_unix_extensions()) {
3438 return NT_STATUS_INVALID_LEVEL;
3441 switch (conn->encrypt_level) {
3442 case SMB_SIGNING_OFF:
3443 encrypt_caps = 0;
3444 break;
3445 case SMB_SIGNING_IF_REQUIRED:
3446 case SMB_SIGNING_DEFAULT:
3447 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3448 break;
3449 case SMB_SIGNING_REQUIRED:
3450 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3451 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3452 large_write = false;
3453 large_read = false;
3454 break;
3457 data_len = 12;
3458 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3459 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3461 /* We have POSIX ACLs, pathname, encryption,
3462 * large read/write, and locking capability. */
3464 SBIG_UINT(pdata,4,((uint64_t)(
3465 CIFS_UNIX_POSIX_ACLS_CAP|
3466 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3467 CIFS_UNIX_FCNTL_LOCKS_CAP|
3468 CIFS_UNIX_EXTATTR_CAP|
3469 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3470 encrypt_caps|
3471 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3472 (large_write ?
3473 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3474 break;
3477 case SMB_QUERY_POSIX_FS_INFO:
3479 int rc;
3480 vfs_statvfs_struct svfs;
3482 if (!lp_unix_extensions()) {
3483 return NT_STATUS_INVALID_LEVEL;
3486 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3488 if (!rc) {
3489 data_len = 56;
3490 SIVAL(pdata,0,svfs.OptimalTransferSize);
3491 SIVAL(pdata,4,svfs.BlockSize);
3492 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3493 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3494 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3495 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3496 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3497 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3499 #ifdef EOPNOTSUPP
3500 } else if (rc == EOPNOTSUPP) {
3501 return NT_STATUS_INVALID_LEVEL;
3502 #endif /* EOPNOTSUPP */
3503 } else {
3504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3505 return NT_STATUS_DOS(ERRSRV, ERRerror);
3507 break;
3510 case SMB_QUERY_POSIX_WHOAMI:
3512 uint32_t flags = 0;
3513 uint32_t sid_bytes;
3514 int i;
3516 if (!lp_unix_extensions()) {
3517 return NT_STATUS_INVALID_LEVEL;
3520 if (max_data_bytes < 40) {
3521 return NT_STATUS_BUFFER_TOO_SMALL;
3524 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3525 flags |= SMB_WHOAMI_GUEST;
3528 /* NOTE: 8 bytes for UID/GID, irrespective of native
3529 * platform size. This matches
3530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3532 data_len = 4 /* flags */
3533 + 4 /* flag mask */
3534 + 8 /* uid */
3535 + 8 /* gid */
3536 + 4 /* ngroups */
3537 + 4 /* num_sids */
3538 + 4 /* SID bytes */
3539 + 4 /* pad/reserved */
3540 + (conn->session_info->unix_token->ngroups * 8)
3541 /* groups list */
3542 + (conn->session_info->security_token->num_sids *
3543 SID_MAX_SIZE)
3544 /* SID list */;
3546 SIVAL(pdata, 0, flags);
3547 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3548 SBIG_UINT(pdata, 8,
3549 (uint64_t)conn->session_info->unix_token->uid);
3550 SBIG_UINT(pdata, 16,
3551 (uint64_t)conn->session_info->unix_token->gid);
3554 if (data_len >= max_data_bytes) {
3555 /* Potential overflow, skip the GIDs and SIDs. */
3557 SIVAL(pdata, 24, 0); /* num_groups */
3558 SIVAL(pdata, 28, 0); /* num_sids */
3559 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3560 SIVAL(pdata, 36, 0); /* reserved */
3562 data_len = 40;
3563 break;
3566 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3567 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3569 /* We walk the SID list twice, but this call is fairly
3570 * infrequent, and I don't expect that it's performance
3571 * sensitive -- jpeach
3573 for (i = 0, sid_bytes = 0;
3574 i < conn->session_info->security_token->num_sids; ++i) {
3575 sid_bytes += ndr_size_dom_sid(
3576 &conn->session_info->security_token->sids[i],
3580 /* SID list byte count */
3581 SIVAL(pdata, 32, sid_bytes);
3583 /* 4 bytes pad/reserved - must be zero */
3584 SIVAL(pdata, 36, 0);
3585 data_len = 40;
3587 /* GID list */
3588 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3589 SBIG_UINT(pdata, data_len,
3590 (uint64_t)conn->session_info->unix_token->groups[i]);
3591 data_len += 8;
3594 /* SID list */
3595 for (i = 0;
3596 i < conn->session_info->security_token->num_sids; ++i) {
3597 int sid_len = ndr_size_dom_sid(
3598 &conn->session_info->security_token->sids[i],
3601 sid_linearize(pdata + data_len, sid_len,
3602 &conn->session_info->security_token->sids[i]);
3603 data_len += sid_len;
3606 break;
3609 case SMB_MAC_QUERY_FS_INFO:
3611 * Thursby MAC extension... ONLY on NTFS filesystems
3612 * once we do streams then we don't need this
3614 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3615 data_len = 88;
3616 SIVAL(pdata,84,0x100); /* Don't support mac... */
3617 break;
3619 /* drop through */
3620 default:
3621 return NT_STATUS_INVALID_LEVEL;
3624 *ret_data_len = data_len;
3625 return status;
3628 /****************************************************************************
3629 Reply to a TRANS2_QFSINFO (query filesystem info).
3630 ****************************************************************************/
3632 static void call_trans2qfsinfo(connection_struct *conn,
3633 struct smb_request *req,
3634 char **pparams, int total_params,
3635 char **ppdata, int total_data,
3636 unsigned int max_data_bytes)
3638 char *params = *pparams;
3639 uint16_t info_level;
3640 int data_len = 0;
3641 NTSTATUS status;
3643 if (total_params < 2) {
3644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3645 return;
3648 info_level = SVAL(params,0);
3650 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3651 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3652 DEBUG(0,("call_trans2qfsinfo: encryption required "
3653 "and info level 0x%x sent.\n",
3654 (unsigned int)info_level));
3655 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3656 return;
3660 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3662 status = smbd_do_qfsinfo(conn, req,
3663 info_level,
3664 req->flags2,
3665 max_data_bytes,
3666 NULL,
3667 ppdata, &data_len);
3668 if (!NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3670 return;
3673 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3674 max_data_bytes);
3676 DEBUG( 4, ( "%s info_level = %d\n",
3677 smb_fn_name(req->cmd), info_level) );
3679 return;
3682 /****************************************************************************
3683 Reply to a TRANS2_SETFSINFO (set filesystem info).
3684 ****************************************************************************/
3686 static void call_trans2setfsinfo(connection_struct *conn,
3687 struct smb_request *req,
3688 char **pparams, int total_params,
3689 char **ppdata, int total_data,
3690 unsigned int max_data_bytes)
3692 struct smbd_server_connection *sconn = req->sconn;
3693 char *pdata = *ppdata;
3694 char *params = *pparams;
3695 uint16 info_level;
3697 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3698 lp_servicename(talloc_tos(), SNUM(conn))));
3700 /* */
3701 if (total_params < 4) {
3702 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3703 total_params));
3704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3705 return;
3708 info_level = SVAL(params,2);
3710 if (IS_IPC(conn)) {
3711 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3712 info_level != SMB_SET_CIFS_UNIX_INFO) {
3713 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3714 "info level (0x%x) on IPC$.\n",
3715 (unsigned int)info_level));
3716 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3717 return;
3721 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3722 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3723 DEBUG(0,("call_trans2setfsinfo: encryption required "
3724 "and info level 0x%x sent.\n",
3725 (unsigned int)info_level));
3726 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3727 return;
3731 switch(info_level) {
3732 case SMB_SET_CIFS_UNIX_INFO:
3733 if (!lp_unix_extensions()) {
3734 DEBUG(2,("call_trans2setfsinfo: "
3735 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3736 "unix extensions off\n"));
3737 reply_nterror(req,
3738 NT_STATUS_INVALID_LEVEL);
3739 return;
3742 /* There should be 12 bytes of capabilities set. */
3743 if (total_data < 12) {
3744 reply_nterror(
3745 req,
3746 NT_STATUS_INVALID_PARAMETER);
3747 return;
3749 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3750 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3751 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3752 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3753 /* Just print these values for now. */
3754 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3755 "major = %u, minor = %u cap_low = 0x%x, "
3756 "cap_high = 0x%xn",
3757 (unsigned int)sconn->
3758 smb1.unix_info.client_major,
3759 (unsigned int)sconn->
3760 smb1.unix_info.client_minor,
3761 (unsigned int)sconn->
3762 smb1.unix_info.client_cap_low,
3763 (unsigned int)sconn->
3764 smb1.unix_info.client_cap_high));
3766 /* Here is where we must switch to posix pathname processing... */
3767 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3768 lp_set_posix_pathnames();
3769 mangle_change_to_posix();
3772 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3773 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3774 /* Client that knows how to do posix locks,
3775 * but not posix open/mkdir operations. Set a
3776 * default type for read/write checks. */
3778 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3781 break;
3783 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3785 NTSTATUS status;
3786 size_t param_len = 0;
3787 size_t data_len = total_data;
3789 if (!lp_unix_extensions()) {
3790 reply_nterror(
3791 req,
3792 NT_STATUS_INVALID_LEVEL);
3793 return;
3796 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3797 reply_nterror(
3798 req,
3799 NT_STATUS_NOT_SUPPORTED);
3800 return;
3803 if (req->sconn->smb1.echo_handler.trusted_fde) {
3804 DEBUG( 2,("call_trans2setfsinfo: "
3805 "request transport encryption disabled"
3806 "with 'fork echo handler = yes'\n"));
3807 reply_nterror(
3808 req,
3809 NT_STATUS_NOT_SUPPORTED);
3810 return;
3813 DEBUG( 4,("call_trans2setfsinfo: "
3814 "request transport encryption.\n"));
3816 status = srv_request_encryption_setup(conn,
3817 (unsigned char **)ppdata,
3818 &data_len,
3819 (unsigned char **)pparams,
3820 &param_len);
3822 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3823 !NT_STATUS_IS_OK(status)) {
3824 reply_nterror(req, status);
3825 return;
3828 send_trans2_replies(conn, req,
3829 NT_STATUS_OK,
3830 *pparams,
3831 param_len,
3832 *ppdata,
3833 data_len,
3834 max_data_bytes);
3836 if (NT_STATUS_IS_OK(status)) {
3837 /* Server-side transport
3838 * encryption is now *on*. */
3839 status = srv_encryption_start(conn);
3840 if (!NT_STATUS_IS_OK(status)) {
3841 char *reason = talloc_asprintf(talloc_tos(),
3842 "Failure in setting "
3843 "up encrypted transport: %s",
3844 nt_errstr(status));
3845 exit_server_cleanly(reason);
3848 return;
3851 case SMB_FS_QUOTA_INFORMATION:
3853 files_struct *fsp = NULL;
3854 SMB_NTQUOTA_STRUCT quotas;
3856 ZERO_STRUCT(quotas);
3858 /* access check */
3859 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3860 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3861 lp_servicename(talloc_tos(), SNUM(conn)),
3862 conn->session_info->unix_info->unix_name));
3863 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3864 return;
3867 /* note: normaly there're 48 bytes,
3868 * but we didn't use the last 6 bytes for now
3869 * --metze
3871 fsp = file_fsp(req, SVAL(params,0));
3873 if (!check_fsp_ntquota_handle(conn, req,
3874 fsp)) {
3875 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3876 reply_nterror(
3877 req, NT_STATUS_INVALID_HANDLE);
3878 return;
3881 if (total_data < 42) {
3882 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3883 total_data));
3884 reply_nterror(
3885 req,
3886 NT_STATUS_INVALID_PARAMETER);
3887 return;
3890 /* unknown_1 24 NULL bytes in pdata*/
3892 /* the soft quotas 8 bytes (uint64_t)*/
3893 quotas.softlim = BVAL(pdata,24);
3895 /* the hard quotas 8 bytes (uint64_t)*/
3896 quotas.hardlim = BVAL(pdata,32);
3898 /* quota_flags 2 bytes **/
3899 quotas.qflags = SVAL(pdata,40);
3901 /* unknown_2 6 NULL bytes follow*/
3903 /* now set the quotas */
3904 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3905 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3906 reply_nterror(req, map_nt_error_from_unix(errno));
3907 return;
3910 break;
3912 default:
3913 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3914 info_level));
3915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3916 return;
3917 break;
3921 * sending this reply works fine,
3922 * but I'm not sure it's the same
3923 * like windows do...
3924 * --metze
3926 reply_outbuf(req, 10, 0);
3929 #if defined(HAVE_POSIX_ACLS)
3930 /****************************************************************************
3931 Utility function to count the number of entries in a POSIX acl.
3932 ****************************************************************************/
3934 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3936 unsigned int ace_count = 0;
3937 int entry_id = SMB_ACL_FIRST_ENTRY;
3938 SMB_ACL_ENTRY_T entry;
3940 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3941 /* get_next... */
3942 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3943 entry_id = SMB_ACL_NEXT_ENTRY;
3945 ace_count++;
3947 return ace_count;
3950 /****************************************************************************
3951 Utility function to marshall a POSIX acl into wire format.
3952 ****************************************************************************/
3954 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3956 int entry_id = SMB_ACL_FIRST_ENTRY;
3957 SMB_ACL_ENTRY_T entry;
3959 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3960 SMB_ACL_TAG_T tagtype;
3961 SMB_ACL_PERMSET_T permset;
3962 unsigned char perms = 0;
3963 unsigned int own_grp;
3965 /* get_next... */
3966 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3967 entry_id = SMB_ACL_NEXT_ENTRY;
3970 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3971 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3972 return False;
3975 if (sys_acl_get_permset(entry, &permset) == -1) {
3976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3977 return False;
3980 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3981 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3982 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3984 SCVAL(pdata,1,perms);
3986 switch (tagtype) {
3987 case SMB_ACL_USER_OBJ:
3988 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3989 own_grp = (unsigned int)pst->st_ex_uid;
3990 SIVAL(pdata,2,own_grp);
3991 SIVAL(pdata,6,0);
3992 break;
3993 case SMB_ACL_USER:
3995 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3996 if (!puid) {
3997 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3998 return False;
4000 own_grp = (unsigned int)*puid;
4001 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4002 SIVAL(pdata,2,own_grp);
4003 SIVAL(pdata,6,0);
4004 break;
4006 case SMB_ACL_GROUP_OBJ:
4007 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4008 own_grp = (unsigned int)pst->st_ex_gid;
4009 SIVAL(pdata,2,own_grp);
4010 SIVAL(pdata,6,0);
4011 break;
4012 case SMB_ACL_GROUP:
4014 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4015 if (!pgid) {
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4017 return False;
4019 own_grp = (unsigned int)*pgid;
4020 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4021 SIVAL(pdata,2,own_grp);
4022 SIVAL(pdata,6,0);
4023 break;
4025 case SMB_ACL_MASK:
4026 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4027 SIVAL(pdata,2,0xFFFFFFFF);
4028 SIVAL(pdata,6,0xFFFFFFFF);
4029 break;
4030 case SMB_ACL_OTHER:
4031 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4032 SIVAL(pdata,2,0xFFFFFFFF);
4033 SIVAL(pdata,6,0xFFFFFFFF);
4034 break;
4035 default:
4036 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4037 return False;
4039 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4042 return True;
4044 #endif
4046 /****************************************************************************
4047 Store the FILE_UNIX_BASIC info.
4048 ****************************************************************************/
4050 static char *store_file_unix_basic(connection_struct *conn,
4051 char *pdata,
4052 files_struct *fsp,
4053 const SMB_STRUCT_STAT *psbuf)
4055 uint64_t file_index = get_FileIndex(conn, psbuf);
4056 dev_t devno;
4058 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4059 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4061 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4062 pdata += 8;
4064 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4065 pdata += 8;
4067 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4068 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4069 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4070 pdata += 24;
4072 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4073 SIVAL(pdata,4,0);
4074 pdata += 8;
4076 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4077 SIVAL(pdata,4,0);
4078 pdata += 8;
4080 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4081 pdata += 4;
4083 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4084 devno = psbuf->st_ex_rdev;
4085 } else {
4086 devno = psbuf->st_ex_dev;
4089 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4090 SIVAL(pdata,4,0);
4091 pdata += 8;
4093 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4094 SIVAL(pdata,4,0);
4095 pdata += 8;
4097 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4098 pdata += 8;
4100 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4101 SIVAL(pdata,4,0);
4102 pdata += 8;
4104 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4105 SIVAL(pdata,4,0);
4106 pdata += 8;
4108 return pdata;
4111 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4112 * the chflags(2) (or equivalent) flags.
4114 * XXX: this really should be behind the VFS interface. To do this, we would
4115 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4116 * Each VFS module could then implement its own mapping as appropriate for the
4117 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4119 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4120 info2_flags_map[] =
4122 #ifdef UF_NODUMP
4123 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4124 #endif
4126 #ifdef UF_IMMUTABLE
4127 { UF_IMMUTABLE, EXT_IMMUTABLE },
4128 #endif
4130 #ifdef UF_APPEND
4131 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4132 #endif
4134 #ifdef UF_HIDDEN
4135 { UF_HIDDEN, EXT_HIDDEN },
4136 #endif
4138 /* Do not remove. We need to guarantee that this array has at least one
4139 * entry to build on HP-UX.
4141 { 0, 0 }
4145 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4146 uint32 *smb_fflags, uint32 *smb_fmask)
4148 int i;
4150 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4151 *smb_fmask |= info2_flags_map[i].smb_fflag;
4152 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4153 *smb_fflags |= info2_flags_map[i].smb_fflag;
4158 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4159 const uint32 smb_fflags,
4160 const uint32 smb_fmask,
4161 int *stat_fflags)
4163 uint32 max_fmask = 0;
4164 int i;
4166 *stat_fflags = psbuf->st_ex_flags;
4168 /* For each flags requested in smb_fmask, check the state of the
4169 * corresponding flag in smb_fflags and set or clear the matching
4170 * stat flag.
4173 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4174 max_fmask |= info2_flags_map[i].smb_fflag;
4175 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4176 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4177 *stat_fflags |= info2_flags_map[i].stat_fflag;
4178 } else {
4179 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4184 /* If smb_fmask is asking to set any bits that are not supported by
4185 * our flag mappings, we should fail.
4187 if ((smb_fmask & max_fmask) != smb_fmask) {
4188 return False;
4191 return True;
4195 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4196 * of file flags and birth (create) time.
4198 static char *store_file_unix_basic_info2(connection_struct *conn,
4199 char *pdata,
4200 files_struct *fsp,
4201 const SMB_STRUCT_STAT *psbuf)
4203 uint32 file_flags = 0;
4204 uint32 flags_mask = 0;
4206 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4208 /* Create (birth) time 64 bit */
4209 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4210 pdata += 8;
4212 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4213 SIVAL(pdata, 0, file_flags); /* flags */
4214 SIVAL(pdata, 4, flags_mask); /* mask */
4215 pdata += 8;
4217 return pdata;
4220 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4221 const struct stream_struct *streams,
4222 char *data,
4223 unsigned int max_data_bytes,
4224 unsigned int *data_size)
4226 unsigned int i;
4227 unsigned int ofs = 0;
4229 for (i = 0; i < num_streams; i++) {
4230 unsigned int next_offset;
4231 size_t namelen;
4232 smb_ucs2_t *namebuf;
4234 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4235 streams[i].name, &namelen) ||
4236 namelen <= 2)
4238 return NT_STATUS_INVALID_PARAMETER;
4242 * name_buf is now null-terminated, we need to marshall as not
4243 * terminated
4246 namelen -= 2;
4249 * We cannot overflow ...
4251 if ((ofs + 24 + namelen) > max_data_bytes) {
4252 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4253 i));
4254 TALLOC_FREE(namebuf);
4255 return STATUS_BUFFER_OVERFLOW;
4258 SIVAL(data, ofs+4, namelen);
4259 SOFF_T(data, ofs+8, streams[i].size);
4260 SOFF_T(data, ofs+16, streams[i].alloc_size);
4261 memcpy(data+ofs+24, namebuf, namelen);
4262 TALLOC_FREE(namebuf);
4264 next_offset = ofs + 24 + namelen;
4266 if (i == num_streams-1) {
4267 SIVAL(data, ofs, 0);
4269 else {
4270 unsigned int align = ndr_align_size(next_offset, 8);
4272 if ((next_offset + align) > max_data_bytes) {
4273 DEBUG(10, ("refusing to overflow align "
4274 "reply at stream %u\n",
4275 i));
4276 TALLOC_FREE(namebuf);
4277 return STATUS_BUFFER_OVERFLOW;
4280 memset(data+next_offset, 0, align);
4281 next_offset += align;
4283 SIVAL(data, ofs, next_offset - ofs);
4284 ofs = next_offset;
4287 ofs = next_offset;
4290 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4292 *data_size = ofs;
4294 return NT_STATUS_OK;
4297 /****************************************************************************
4298 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4299 ****************************************************************************/
4301 static void call_trans2qpipeinfo(connection_struct *conn,
4302 struct smb_request *req,
4303 unsigned int tran_call,
4304 char **pparams, int total_params,
4305 char **ppdata, int total_data,
4306 unsigned int max_data_bytes)
4308 char *params = *pparams;
4309 char *pdata = *ppdata;
4310 unsigned int data_size = 0;
4311 unsigned int param_size = 2;
4312 uint16 info_level;
4313 files_struct *fsp;
4315 if (!params) {
4316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4317 return;
4320 if (total_params < 4) {
4321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4322 return;
4325 fsp = file_fsp(req, SVAL(params,0));
4326 if (!fsp_is_np(fsp)) {
4327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4328 return;
4331 info_level = SVAL(params,2);
4333 *pparams = (char *)SMB_REALLOC(*pparams,2);
4334 if (*pparams == NULL) {
4335 reply_nterror(req, NT_STATUS_NO_MEMORY);
4336 return;
4338 params = *pparams;
4339 SSVAL(params,0,0);
4340 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4342 return;
4344 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4345 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4346 if (*ppdata == NULL ) {
4347 reply_nterror(req, NT_STATUS_NO_MEMORY);
4348 return;
4350 pdata = *ppdata;
4352 switch (info_level) {
4353 case SMB_FILE_STANDARD_INFORMATION:
4354 memset(pdata,0,24);
4355 SOFF_T(pdata,0,4096LL);
4356 SIVAL(pdata,16,1);
4357 SIVAL(pdata,20,1);
4358 data_size = 24;
4359 break;
4361 default:
4362 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4363 return;
4366 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4367 max_data_bytes);
4369 return;
4372 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4373 TALLOC_CTX *mem_ctx,
4374 uint16_t info_level,
4375 files_struct *fsp,
4376 struct smb_filename *smb_fname,
4377 bool delete_pending,
4378 struct timespec write_time_ts,
4379 struct ea_list *ea_list,
4380 int lock_data_count,
4381 char *lock_data,
4382 uint16_t flags2,
4383 unsigned int max_data_bytes,
4384 char **ppdata,
4385 unsigned int *pdata_size)
4387 char *pdata = *ppdata;
4388 char *dstart, *dend;
4389 unsigned int data_size;
4390 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4391 time_t create_time, mtime, atime, c_time;
4392 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4393 char *p;
4394 char *base_name;
4395 char *dos_fname;
4396 int mode;
4397 int nlink;
4398 NTSTATUS status;
4399 uint64_t file_size = 0;
4400 uint64_t pos = 0;
4401 uint64_t allocation_size = 0;
4402 uint64_t file_index = 0;
4403 uint32_t access_mask = 0;
4405 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4406 return NT_STATUS_INVALID_LEVEL;
4409 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4410 smb_fname_str_dbg(smb_fname),
4411 fsp_fnum_dbg(fsp),
4412 info_level, max_data_bytes));
4414 mode = dos_mode(conn, smb_fname);
4415 nlink = psbuf->st_ex_nlink;
4417 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4418 nlink = 1;
4421 if ((nlink > 0) && delete_pending) {
4422 nlink -= 1;
4425 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4426 return NT_STATUS_INVALID_PARAMETER;
4429 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4430 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4431 if (*ppdata == NULL) {
4432 return NT_STATUS_NO_MEMORY;
4434 pdata = *ppdata;
4435 dstart = pdata;
4436 dend = dstart + data_size - 1;
4438 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4439 update_stat_ex_mtime(psbuf, write_time_ts);
4442 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4443 mtime_ts = psbuf->st_ex_mtime;
4444 atime_ts = psbuf->st_ex_atime;
4445 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4447 if (lp_dos_filetime_resolution(SNUM(conn))) {
4448 dos_filetime_timespec(&create_time_ts);
4449 dos_filetime_timespec(&mtime_ts);
4450 dos_filetime_timespec(&atime_ts);
4451 dos_filetime_timespec(&ctime_ts);
4454 create_time = convert_timespec_to_time_t(create_time_ts);
4455 mtime = convert_timespec_to_time_t(mtime_ts);
4456 atime = convert_timespec_to_time_t(atime_ts);
4457 c_time = convert_timespec_to_time_t(ctime_ts);
4459 p = strrchr_m(smb_fname->base_name,'/');
4460 if (!p)
4461 base_name = smb_fname->base_name;
4462 else
4463 base_name = p+1;
4465 /* NT expects the name to be in an exact form of the *full*
4466 filename. See the trans2 torture test */
4467 if (ISDOT(base_name)) {
4468 dos_fname = talloc_strdup(mem_ctx, "\\");
4469 if (!dos_fname) {
4470 return NT_STATUS_NO_MEMORY;
4472 } else {
4473 dos_fname = talloc_asprintf(mem_ctx,
4474 "\\%s",
4475 smb_fname->base_name);
4476 if (!dos_fname) {
4477 return NT_STATUS_NO_MEMORY;
4479 if (is_ntfs_stream_smb_fname(smb_fname)) {
4480 dos_fname = talloc_asprintf(dos_fname, "%s",
4481 smb_fname->stream_name);
4482 if (!dos_fname) {
4483 return NT_STATUS_NO_MEMORY;
4487 string_replace(dos_fname, '/', '\\');
4490 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4492 if (!fsp) {
4493 /* Do we have this path open ? */
4494 files_struct *fsp1;
4495 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4496 fsp1 = file_find_di_first(conn->sconn, fileid);
4497 if (fsp1 && fsp1->initial_allocation_size) {
4498 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4502 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4503 file_size = get_file_size_stat(psbuf);
4506 if (fsp) {
4507 pos = fsp->fh->position_information;
4510 if (fsp) {
4511 access_mask = fsp->access_mask;
4512 } else {
4513 /* GENERIC_EXECUTE mapping from Windows */
4514 access_mask = 0x12019F;
4517 /* This should be an index number - looks like
4518 dev/ino to me :-)
4520 I think this causes us to fail the IFSKIT
4521 BasicFileInformationTest. -tpot */
4522 file_index = get_FileIndex(conn, psbuf);
4524 switch (info_level) {
4525 case SMB_INFO_STANDARD:
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4527 data_size = 22;
4528 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4529 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4530 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4531 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4532 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4533 SSVAL(pdata,l1_attrFile,mode);
4534 break;
4536 case SMB_INFO_QUERY_EA_SIZE:
4538 unsigned int ea_size =
4539 estimate_ea_size(conn, fsp,
4540 smb_fname);
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4542 data_size = 26;
4543 srv_put_dos_date2(pdata,0,create_time);
4544 srv_put_dos_date2(pdata,4,atime);
4545 srv_put_dos_date2(pdata,8,mtime); /* write time */
4546 SIVAL(pdata,12,(uint32)file_size);
4547 SIVAL(pdata,16,(uint32)allocation_size);
4548 SSVAL(pdata,20,mode);
4549 SIVAL(pdata,22,ea_size);
4550 break;
4553 case SMB_INFO_IS_NAME_VALID:
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4555 if (fsp) {
4556 /* os/2 needs this ? really ?*/
4557 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4559 /* This is only reached for qpathinfo */
4560 data_size = 0;
4561 break;
4563 case SMB_INFO_QUERY_EAS_FROM_LIST:
4565 size_t total_ea_len = 0;
4566 struct ea_list *ea_file_list = NULL;
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4569 status =
4570 get_ea_list_from_file(mem_ctx, conn, fsp,
4571 smb_fname,
4572 &total_ea_len, &ea_file_list);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 return status;
4577 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4579 if (!ea_list || (total_ea_len > data_size)) {
4580 data_size = 4;
4581 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4582 break;
4585 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4586 break;
4589 case SMB_INFO_QUERY_ALL_EAS:
4591 /* We have data_size bytes to put EA's into. */
4592 size_t total_ea_len = 0;
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4595 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4596 smb_fname,
4597 &total_ea_len, &ea_list);
4598 if (!NT_STATUS_IS_OK(status)) {
4599 return status;
4602 if (!ea_list || (total_ea_len > data_size)) {
4603 data_size = 4;
4604 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4605 break;
4608 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4609 break;
4612 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4614 /* This is FileFullEaInformation - 0xF which maps to
4615 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4617 /* We have data_size bytes to put EA's into. */
4618 size_t total_ea_len = 0;
4619 struct ea_list *ea_file_list = NULL;
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4623 /*TODO: add filtering and index handling */
4625 status =
4626 get_ea_list_from_file(mem_ctx, conn, fsp,
4627 smb_fname,
4628 &total_ea_len, &ea_file_list);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 return status;
4632 if (!ea_file_list) {
4633 return NT_STATUS_NO_EAS_ON_FILE;
4636 status = fill_ea_chained_buffer(mem_ctx,
4637 pdata,
4638 data_size,
4639 &data_size,
4640 conn, ea_file_list);
4641 if (!NT_STATUS_IS_OK(status)) {
4642 return status;
4644 break;
4647 case SMB_FILE_BASIC_INFORMATION:
4648 case SMB_QUERY_FILE_BASIC_INFO:
4650 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4652 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4653 } else {
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4655 data_size = 40;
4656 SIVAL(pdata,36,0);
4658 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4659 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4660 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4661 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4662 SIVAL(pdata,32,mode);
4664 DEBUG(5,("SMB_QFBI - "));
4665 DEBUG(5,("create: %s ", ctime(&create_time)));
4666 DEBUG(5,("access: %s ", ctime(&atime)));
4667 DEBUG(5,("write: %s ", ctime(&mtime)));
4668 DEBUG(5,("change: %s ", ctime(&c_time)));
4669 DEBUG(5,("mode: %x\n", mode));
4670 break;
4672 case SMB_FILE_STANDARD_INFORMATION:
4673 case SMB_QUERY_FILE_STANDARD_INFO:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4676 data_size = 24;
4677 SOFF_T(pdata,0,allocation_size);
4678 SOFF_T(pdata,8,file_size);
4679 SIVAL(pdata,16,nlink);
4680 SCVAL(pdata,20,delete_pending?1:0);
4681 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4682 SSVAL(pdata,22,0); /* Padding. */
4683 break;
4685 case SMB_FILE_EA_INFORMATION:
4686 case SMB_QUERY_FILE_EA_INFO:
4688 unsigned int ea_size =
4689 estimate_ea_size(conn, fsp, smb_fname);
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4691 data_size = 4;
4692 SIVAL(pdata,0,ea_size);
4693 break;
4696 /* Get the 8.3 name - used if NT SMB was negotiated. */
4697 case SMB_QUERY_FILE_ALT_NAME_INFO:
4698 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4700 int len;
4701 char mangled_name[13];
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4703 if (!name_to_8_3(base_name,mangled_name,
4704 True,conn->params)) {
4705 return NT_STATUS_NO_MEMORY;
4707 len = srvstr_push(dstart, flags2,
4708 pdata+4, mangled_name,
4709 PTR_DIFF(dend, pdata+4),
4710 STR_UNICODE);
4711 data_size = 4 + len;
4712 SIVAL(pdata,0,len);
4713 break;
4716 case SMB_QUERY_FILE_NAME_INFO:
4718 int len;
4720 this must be *exactly* right for ACLs on mapped drives to work
4722 len = srvstr_push(dstart, flags2,
4723 pdata+4, dos_fname,
4724 PTR_DIFF(dend, pdata+4),
4725 STR_UNICODE);
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4727 data_size = 4 + len;
4728 SIVAL(pdata,0,len);
4729 break;
4732 case SMB_FILE_ALLOCATION_INFORMATION:
4733 case SMB_QUERY_FILE_ALLOCATION_INFO:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4735 data_size = 8;
4736 SOFF_T(pdata,0,allocation_size);
4737 break;
4739 case SMB_FILE_END_OF_FILE_INFORMATION:
4740 case SMB_QUERY_FILE_END_OF_FILEINFO:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4742 data_size = 8;
4743 SOFF_T(pdata,0,file_size);
4744 break;
4746 case SMB_QUERY_FILE_ALL_INFO:
4747 case SMB_FILE_ALL_INFORMATION:
4749 int len;
4750 unsigned int ea_size =
4751 estimate_ea_size(conn, fsp, smb_fname);
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4753 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4754 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4755 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4756 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4757 SIVAL(pdata,32,mode);
4758 SIVAL(pdata,36,0); /* padding. */
4759 pdata += 40;
4760 SOFF_T(pdata,0,allocation_size);
4761 SOFF_T(pdata,8,file_size);
4762 SIVAL(pdata,16,nlink);
4763 SCVAL(pdata,20,delete_pending);
4764 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4765 SSVAL(pdata,22,0);
4766 pdata += 24;
4767 SIVAL(pdata,0,ea_size);
4768 pdata += 4; /* EA info */
4769 len = srvstr_push(dstart, flags2,
4770 pdata+4, dos_fname,
4771 PTR_DIFF(dend, pdata+4),
4772 STR_UNICODE);
4773 SIVAL(pdata,0,len);
4774 pdata += 4 + len;
4775 data_size = PTR_DIFF(pdata,(*ppdata));
4776 break;
4779 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4781 int len;
4782 unsigned int ea_size =
4783 estimate_ea_size(conn, fsp, smb_fname);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4786 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4787 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4788 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4789 SIVAL(pdata, 0x20, mode);
4790 SIVAL(pdata, 0x24, 0); /* padding. */
4791 SBVAL(pdata, 0x28, allocation_size);
4792 SBVAL(pdata, 0x30, file_size);
4793 SIVAL(pdata, 0x38, nlink);
4794 SCVAL(pdata, 0x3C, delete_pending);
4795 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4796 SSVAL(pdata, 0x3E, 0); /* padding */
4797 SBVAL(pdata, 0x40, file_index);
4798 SIVAL(pdata, 0x48, ea_size);
4799 SIVAL(pdata, 0x4C, access_mask);
4800 SBVAL(pdata, 0x50, pos);
4801 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4802 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4804 pdata += 0x60;
4806 len = srvstr_push(dstart, flags2,
4807 pdata+4, dos_fname,
4808 PTR_DIFF(dend, pdata+4),
4809 STR_UNICODE);
4810 SIVAL(pdata,0,len);
4811 pdata += 4 + len;
4812 data_size = PTR_DIFF(pdata,(*ppdata));
4813 break;
4815 case SMB_FILE_INTERNAL_INFORMATION:
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4818 SBVAL(pdata, 0, file_index);
4819 data_size = 8;
4820 break;
4822 case SMB_FILE_ACCESS_INFORMATION:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4824 SIVAL(pdata, 0, access_mask);
4825 data_size = 4;
4826 break;
4828 case SMB_FILE_NAME_INFORMATION:
4829 /* Pathname with leading '\'. */
4831 size_t byte_len;
4832 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4833 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4834 SIVAL(pdata,0,byte_len);
4835 data_size = 4 + byte_len;
4836 break;
4839 case SMB_FILE_DISPOSITION_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4841 data_size = 1;
4842 SCVAL(pdata,0,delete_pending);
4843 break;
4845 case SMB_FILE_POSITION_INFORMATION:
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4847 data_size = 8;
4848 SOFF_T(pdata,0,pos);
4849 break;
4851 case SMB_FILE_MODE_INFORMATION:
4852 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4853 SIVAL(pdata,0,mode);
4854 data_size = 4;
4855 break;
4857 case SMB_FILE_ALIGNMENT_INFORMATION:
4858 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4859 SIVAL(pdata,0,0); /* No alignment needed. */
4860 data_size = 4;
4861 break;
4864 * NT4 server just returns "invalid query" to this - if we try
4865 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4866 * want this. JRA.
4868 /* The first statement above is false - verified using Thursby
4869 * client against NT4 -- gcolley.
4871 case SMB_QUERY_FILE_STREAM_INFO:
4872 case SMB_FILE_STREAM_INFORMATION: {
4873 unsigned int num_streams = 0;
4874 struct stream_struct *streams = NULL;
4876 DEBUG(10,("smbd_do_qfilepathinfo: "
4877 "SMB_FILE_STREAM_INFORMATION\n"));
4879 if (is_ntfs_stream_smb_fname(smb_fname)) {
4880 return NT_STATUS_INVALID_PARAMETER;
4883 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4884 talloc_tos(), &num_streams, &streams);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 DEBUG(10, ("could not get stream info: %s\n",
4888 nt_errstr(status)));
4889 return status;
4892 status = marshall_stream_info(num_streams, streams,
4893 pdata, max_data_bytes,
4894 &data_size);
4896 if (!NT_STATUS_IS_OK(status)) {
4897 DEBUG(10, ("marshall_stream_info failed: %s\n",
4898 nt_errstr(status)));
4899 TALLOC_FREE(streams);
4900 return status;
4903 TALLOC_FREE(streams);
4905 break;
4907 case SMB_QUERY_COMPRESSION_INFO:
4908 case SMB_FILE_COMPRESSION_INFORMATION:
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4910 SOFF_T(pdata,0,file_size);
4911 SIVAL(pdata,8,0); /* ??? */
4912 SIVAL(pdata,12,0); /* ??? */
4913 data_size = 16;
4914 break;
4916 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4918 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4919 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4920 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4921 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4922 SOFF_T(pdata,32,allocation_size);
4923 SOFF_T(pdata,40,file_size);
4924 SIVAL(pdata,48,mode);
4925 SIVAL(pdata,52,0); /* ??? */
4926 data_size = 56;
4927 break;
4929 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4930 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4931 SIVAL(pdata,0,mode);
4932 SIVAL(pdata,4,0);
4933 data_size = 8;
4934 break;
4937 * CIFS UNIX Extensions.
4940 case SMB_QUERY_FILE_UNIX_BASIC:
4942 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4943 data_size = PTR_DIFF(pdata,(*ppdata));
4945 DEBUG(4,("smbd_do_qfilepathinfo: "
4946 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4947 dump_data(4, (uint8_t *)(*ppdata), data_size);
4949 break;
4951 case SMB_QUERY_FILE_UNIX_INFO2:
4953 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4954 data_size = PTR_DIFF(pdata,(*ppdata));
4957 int i;
4958 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4960 for (i=0; i<100; i++)
4961 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4962 DEBUG(4,("\n"));
4965 break;
4967 case SMB_QUERY_FILE_UNIX_LINK:
4969 int len;
4970 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4972 if (!buffer) {
4973 return NT_STATUS_NO_MEMORY;
4976 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4977 #ifdef S_ISLNK
4978 if(!S_ISLNK(psbuf->st_ex_mode)) {
4979 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4981 #else
4982 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4983 #endif
4984 len = SMB_VFS_READLINK(conn,
4985 smb_fname->base_name,
4986 buffer, PATH_MAX);
4987 if (len == -1) {
4988 return map_nt_error_from_unix(errno);
4990 buffer[len] = 0;
4991 len = srvstr_push(dstart, flags2,
4992 pdata, buffer,
4993 PTR_DIFF(dend, pdata),
4994 STR_TERMINATE);
4995 pdata += len;
4996 data_size = PTR_DIFF(pdata,(*ppdata));
4998 break;
5001 #if defined(HAVE_POSIX_ACLS)
5002 case SMB_QUERY_POSIX_ACL:
5004 SMB_ACL_T file_acl = NULL;
5005 SMB_ACL_T def_acl = NULL;
5006 uint16 num_file_acls = 0;
5007 uint16 num_def_acls = 0;
5009 if (fsp && fsp->fh->fd != -1) {
5010 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5011 talloc_tos());
5012 } else {
5013 file_acl =
5014 SMB_VFS_SYS_ACL_GET_FILE(conn,
5015 smb_fname->base_name,
5016 SMB_ACL_TYPE_ACCESS,
5017 talloc_tos());
5020 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5021 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5022 "not implemented on "
5023 "filesystem containing %s\n",
5024 smb_fname->base_name));
5025 return NT_STATUS_NOT_IMPLEMENTED;
5028 if (S_ISDIR(psbuf->st_ex_mode)) {
5029 if (fsp && fsp->is_directory) {
5030 def_acl =
5031 SMB_VFS_SYS_ACL_GET_FILE(
5032 conn,
5033 fsp->fsp_name->base_name,
5034 SMB_ACL_TYPE_DEFAULT,
5035 talloc_tos());
5036 } else {
5037 def_acl =
5038 SMB_VFS_SYS_ACL_GET_FILE(
5039 conn,
5040 smb_fname->base_name,
5041 SMB_ACL_TYPE_DEFAULT,
5042 talloc_tos());
5044 def_acl = free_empty_sys_acl(conn, def_acl);
5047 num_file_acls = count_acl_entries(conn, file_acl);
5048 num_def_acls = count_acl_entries(conn, def_acl);
5050 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5051 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5052 data_size,
5053 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5054 SMB_POSIX_ACL_HEADER_SIZE) ));
5055 if (file_acl) {
5056 TALLOC_FREE(file_acl);
5058 if (def_acl) {
5059 TALLOC_FREE(def_acl);
5061 return NT_STATUS_BUFFER_TOO_SMALL;
5064 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5065 SSVAL(pdata,2,num_file_acls);
5066 SSVAL(pdata,4,num_def_acls);
5067 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5068 if (file_acl) {
5069 TALLOC_FREE(file_acl);
5071 if (def_acl) {
5072 TALLOC_FREE(def_acl);
5074 return NT_STATUS_INTERNAL_ERROR;
5076 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5077 if (file_acl) {
5078 TALLOC_FREE(file_acl);
5080 if (def_acl) {
5081 TALLOC_FREE(def_acl);
5083 return NT_STATUS_INTERNAL_ERROR;
5086 if (file_acl) {
5087 TALLOC_FREE(file_acl);
5089 if (def_acl) {
5090 TALLOC_FREE(def_acl);
5092 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5093 break;
5095 #endif
5098 case SMB_QUERY_POSIX_LOCK:
5100 uint64_t count;
5101 uint64_t offset;
5102 uint64_t smblctx;
5103 enum brl_type lock_type;
5105 /* We need an open file with a real fd for this. */
5106 if (!fsp || fsp->fh->fd == -1) {
5107 return NT_STATUS_INVALID_LEVEL;
5110 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5111 return NT_STATUS_INVALID_PARAMETER;
5114 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5115 case POSIX_LOCK_TYPE_READ:
5116 lock_type = READ_LOCK;
5117 break;
5118 case POSIX_LOCK_TYPE_WRITE:
5119 lock_type = WRITE_LOCK;
5120 break;
5121 case POSIX_LOCK_TYPE_UNLOCK:
5122 default:
5123 /* There's no point in asking for an unlock... */
5124 return NT_STATUS_INVALID_PARAMETER;
5127 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5128 #if defined(HAVE_LONGLONG)
5129 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5130 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5131 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5132 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5133 #else /* HAVE_LONGLONG */
5134 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5135 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5136 #endif /* HAVE_LONGLONG */
5138 status = query_lock(fsp,
5139 &smblctx,
5140 &count,
5141 &offset,
5142 &lock_type,
5143 POSIX_LOCK);
5145 if (ERROR_WAS_LOCK_DENIED(status)) {
5146 /* Here we need to report who has it locked... */
5147 data_size = POSIX_LOCK_DATA_SIZE;
5149 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5150 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5151 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5152 #if defined(HAVE_LONGLONG)
5153 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5154 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5155 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5156 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5157 #else /* HAVE_LONGLONG */
5158 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5159 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5160 #endif /* HAVE_LONGLONG */
5162 } else if (NT_STATUS_IS_OK(status)) {
5163 /* For success we just return a copy of what we sent
5164 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5165 data_size = POSIX_LOCK_DATA_SIZE;
5166 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5167 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5168 } else {
5169 return status;
5171 break;
5174 default:
5175 return NT_STATUS_INVALID_LEVEL;
5178 *pdata_size = data_size;
5179 return NT_STATUS_OK;
5182 /****************************************************************************
5183 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5184 file name or file id).
5185 ****************************************************************************/
5187 static void call_trans2qfilepathinfo(connection_struct *conn,
5188 struct smb_request *req,
5189 unsigned int tran_call,
5190 char **pparams, int total_params,
5191 char **ppdata, int total_data,
5192 unsigned int max_data_bytes)
5194 char *params = *pparams;
5195 char *pdata = *ppdata;
5196 uint16 info_level;
5197 unsigned int data_size = 0;
5198 unsigned int param_size = 2;
5199 struct smb_filename *smb_fname = NULL;
5200 bool delete_pending = False;
5201 struct timespec write_time_ts;
5202 files_struct *fsp = NULL;
5203 struct file_id fileid;
5204 struct ea_list *ea_list = NULL;
5205 int lock_data_count = 0;
5206 char *lock_data = NULL;
5207 NTSTATUS status = NT_STATUS_OK;
5209 if (!params) {
5210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5211 return;
5214 ZERO_STRUCT(write_time_ts);
5216 if (tran_call == TRANSACT2_QFILEINFO) {
5217 if (total_params < 4) {
5218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5219 return;
5222 if (IS_IPC(conn)) {
5223 call_trans2qpipeinfo(conn, req, tran_call,
5224 pparams, total_params,
5225 ppdata, total_data,
5226 max_data_bytes);
5227 return;
5230 fsp = file_fsp(req, SVAL(params,0));
5231 info_level = SVAL(params,2);
5233 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5235 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5236 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5237 return;
5240 /* Initial check for valid fsp ptr. */
5241 if (!check_fsp_open(conn, req, fsp)) {
5242 return;
5245 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5246 if (smb_fname == NULL) {
5247 reply_nterror(req, NT_STATUS_NO_MEMORY);
5248 return;
5251 if(fsp->fake_file_handle) {
5253 * This is actually for the QUOTA_FAKE_FILE --metze
5256 /* We know this name is ok, it's already passed the checks. */
5258 } else if(fsp->fh->fd == -1) {
5260 * This is actually a QFILEINFO on a directory
5261 * handle (returned from an NT SMB). NT5.0 seems
5262 * to do this call. JRA.
5265 if (INFO_LEVEL_IS_UNIX(info_level)) {
5266 /* Always do lstat for UNIX calls. */
5267 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5268 DEBUG(3,("call_trans2qfilepathinfo: "
5269 "SMB_VFS_LSTAT of %s failed "
5270 "(%s)\n",
5271 smb_fname_str_dbg(smb_fname),
5272 strerror(errno)));
5273 reply_nterror(req,
5274 map_nt_error_from_unix(errno));
5275 return;
5277 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5278 DEBUG(3,("call_trans2qfilepathinfo: "
5279 "SMB_VFS_STAT of %s failed (%s)\n",
5280 smb_fname_str_dbg(smb_fname),
5281 strerror(errno)));
5282 reply_nterror(req,
5283 map_nt_error_from_unix(errno));
5284 return;
5287 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5288 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5289 } else {
5291 * Original code - this is an open file.
5293 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5294 DEBUG(3, ("fstat of %s failed (%s)\n",
5295 fsp_fnum_dbg(fsp), strerror(errno)));
5296 reply_nterror(req,
5297 map_nt_error_from_unix(errno));
5298 return;
5300 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5301 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5304 } else {
5305 uint32_t name_hash;
5306 char *fname = NULL;
5307 uint32_t ucf_flags = 0;
5309 /* qpathinfo */
5310 if (total_params < 7) {
5311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5312 return;
5315 info_level = SVAL(params,0);
5317 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5319 if (INFO_LEVEL_IS_UNIX(info_level)) {
5320 if (!lp_unix_extensions()) {
5321 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5322 return;
5324 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5325 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5326 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5327 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5331 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5332 total_params - 6,
5333 STR_TERMINATE, &status);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 reply_nterror(req, status);
5336 return;
5339 status = filename_convert(req,
5340 conn,
5341 req->flags2 & FLAGS2_DFS_PATHNAMES,
5342 fname,
5343 ucf_flags,
5344 NULL,
5345 &smb_fname);
5346 if (!NT_STATUS_IS_OK(status)) {
5347 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5348 reply_botherror(req,
5349 NT_STATUS_PATH_NOT_COVERED,
5350 ERRSRV, ERRbadpath);
5351 return;
5353 reply_nterror(req, status);
5354 return;
5357 /* If this is a stream, check if there is a delete_pending. */
5358 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5359 && is_ntfs_stream_smb_fname(smb_fname)) {
5360 struct smb_filename *smb_fname_base;
5362 /* Create an smb_filename with stream_name == NULL. */
5363 smb_fname_base = synthetic_smb_fname(
5364 talloc_tos(), smb_fname->base_name,
5365 NULL, NULL);
5366 if (smb_fname_base == NULL) {
5367 reply_nterror(req, NT_STATUS_NO_MEMORY);
5368 return;
5371 if (INFO_LEVEL_IS_UNIX(info_level)) {
5372 /* Always do lstat for UNIX calls. */
5373 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5374 DEBUG(3,("call_trans2qfilepathinfo: "
5375 "SMB_VFS_LSTAT of %s failed "
5376 "(%s)\n",
5377 smb_fname_str_dbg(smb_fname_base),
5378 strerror(errno)));
5379 TALLOC_FREE(smb_fname_base);
5380 reply_nterror(req,
5381 map_nt_error_from_unix(errno));
5382 return;
5384 } else {
5385 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5386 DEBUG(3,("call_trans2qfilepathinfo: "
5387 "fileinfo of %s failed "
5388 "(%s)\n",
5389 smb_fname_str_dbg(smb_fname_base),
5390 strerror(errno)));
5391 TALLOC_FREE(smb_fname_base);
5392 reply_nterror(req,
5393 map_nt_error_from_unix(errno));
5394 return;
5398 status = file_name_hash(conn,
5399 smb_fname_str_dbg(smb_fname_base),
5400 &name_hash);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 TALLOC_FREE(smb_fname_base);
5403 reply_nterror(req, status);
5404 return;
5407 fileid = vfs_file_id_from_sbuf(conn,
5408 &smb_fname_base->st);
5409 TALLOC_FREE(smb_fname_base);
5410 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5411 if (delete_pending) {
5412 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5413 return;
5417 if (INFO_LEVEL_IS_UNIX(info_level)) {
5418 /* Always do lstat for UNIX calls. */
5419 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5420 DEBUG(3,("call_trans2qfilepathinfo: "
5421 "SMB_VFS_LSTAT of %s failed (%s)\n",
5422 smb_fname_str_dbg(smb_fname),
5423 strerror(errno)));
5424 reply_nterror(req,
5425 map_nt_error_from_unix(errno));
5426 return;
5429 } else {
5430 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5431 DEBUG(3,("call_trans2qfilepathinfo: "
5432 "SMB_VFS_STAT of %s failed (%s)\n",
5433 smb_fname_str_dbg(smb_fname),
5434 strerror(errno)));
5435 reply_nterror(req,
5436 map_nt_error_from_unix(errno));
5437 return;
5441 status = file_name_hash(conn,
5442 smb_fname_str_dbg(smb_fname),
5443 &name_hash);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 reply_nterror(req, status);
5446 return;
5449 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5450 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5451 if (delete_pending) {
5452 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5453 return;
5457 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5458 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5459 fsp_fnum_dbg(fsp),
5460 info_level,tran_call,total_data));
5462 /* Pull out any data sent here before we realloc. */
5463 switch (info_level) {
5464 case SMB_INFO_QUERY_EAS_FROM_LIST:
5466 /* Pull any EA list from the data portion. */
5467 uint32 ea_size;
5469 if (total_data < 4) {
5470 reply_nterror(
5471 req, NT_STATUS_INVALID_PARAMETER);
5472 return;
5474 ea_size = IVAL(pdata,0);
5476 if (total_data > 0 && ea_size != total_data) {
5477 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5478 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5479 reply_nterror(
5480 req, NT_STATUS_INVALID_PARAMETER);
5481 return;
5484 if (!lp_ea_support(SNUM(conn))) {
5485 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5486 return;
5489 /* Pull out the list of names. */
5490 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5491 if (!ea_list) {
5492 reply_nterror(
5493 req, NT_STATUS_INVALID_PARAMETER);
5494 return;
5496 break;
5499 case SMB_QUERY_POSIX_LOCK:
5501 if (fsp == NULL || fsp->fh->fd == -1) {
5502 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5503 return;
5506 if (total_data != POSIX_LOCK_DATA_SIZE) {
5507 reply_nterror(
5508 req, NT_STATUS_INVALID_PARAMETER);
5509 return;
5512 /* Copy the lock range data. */
5513 lock_data = (char *)talloc_memdup(
5514 req, pdata, total_data);
5515 if (!lock_data) {
5516 reply_nterror(req, NT_STATUS_NO_MEMORY);
5517 return;
5519 lock_data_count = total_data;
5521 default:
5522 break;
5525 *pparams = (char *)SMB_REALLOC(*pparams,2);
5526 if (*pparams == NULL) {
5527 reply_nterror(req, NT_STATUS_NO_MEMORY);
5528 return;
5530 params = *pparams;
5531 SSVAL(params,0,0);
5534 * draft-leach-cifs-v1-spec-02.txt
5535 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5536 * says:
5538 * The requested information is placed in the Data portion of the
5539 * transaction response. For the information levels greater than 0x100,
5540 * the transaction response has 1 parameter word which should be
5541 * ignored by the client.
5543 * However Windows only follows this rule for the IS_NAME_VALID call.
5545 switch (info_level) {
5546 case SMB_INFO_IS_NAME_VALID:
5547 param_size = 0;
5548 break;
5551 if ((info_level & 0xFF00) == 0xFF00) {
5553 * We use levels that start with 0xFF00
5554 * internally to represent SMB2 specific levels
5556 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5557 return;
5560 status = smbd_do_qfilepathinfo(conn, req, info_level,
5561 fsp, smb_fname,
5562 delete_pending, write_time_ts,
5563 ea_list,
5564 lock_data_count, lock_data,
5565 req->flags2, max_data_bytes,
5566 ppdata, &data_size);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 reply_nterror(req, status);
5569 return;
5572 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5573 max_data_bytes);
5575 return;
5578 /****************************************************************************
5579 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5580 code.
5581 ****************************************************************************/
5583 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5584 connection_struct *conn,
5585 struct smb_request *req,
5586 bool overwrite_if_exists,
5587 const struct smb_filename *smb_fname_old,
5588 struct smb_filename *smb_fname_new)
5590 NTSTATUS status = NT_STATUS_OK;
5592 /* source must already exist. */
5593 if (!VALID_STAT(smb_fname_old->st)) {
5594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5597 if (VALID_STAT(smb_fname_new->st)) {
5598 if (overwrite_if_exists) {
5599 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5600 return NT_STATUS_FILE_IS_A_DIRECTORY;
5602 status = unlink_internals(conn,
5603 req,
5604 FILE_ATTRIBUTE_NORMAL,
5605 smb_fname_new,
5606 false);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 return status;
5610 } else {
5611 /* Disallow if newname already exists. */
5612 return NT_STATUS_OBJECT_NAME_COLLISION;
5616 /* No links from a directory. */
5617 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5618 return NT_STATUS_FILE_IS_A_DIRECTORY;
5621 /* Setting a hardlink to/from a stream isn't currently supported. */
5622 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5623 is_ntfs_stream_smb_fname(smb_fname_new)) {
5624 return NT_STATUS_INVALID_PARAMETER;
5627 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5628 smb_fname_old->base_name, smb_fname_new->base_name));
5630 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5631 smb_fname_new->base_name) != 0) {
5632 status = map_nt_error_from_unix(errno);
5633 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5634 nt_errstr(status), smb_fname_old->base_name,
5635 smb_fname_new->base_name));
5637 return status;
5640 /****************************************************************************
5641 Deal with setting the time from any of the setfilepathinfo functions.
5642 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5643 calling this function.
5644 ****************************************************************************/
5646 NTSTATUS smb_set_file_time(connection_struct *conn,
5647 files_struct *fsp,
5648 const struct smb_filename *smb_fname,
5649 struct smb_file_time *ft,
5650 bool setting_write_time)
5652 struct smb_filename smb_fname_base;
5653 uint32 action =
5654 FILE_NOTIFY_CHANGE_LAST_ACCESS
5655 |FILE_NOTIFY_CHANGE_LAST_WRITE
5656 |FILE_NOTIFY_CHANGE_CREATION;
5658 if (!VALID_STAT(smb_fname->st)) {
5659 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5662 /* get some defaults (no modifications) if any info is zero or -1. */
5663 if (null_timespec(ft->create_time)) {
5664 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5667 if (null_timespec(ft->atime)) {
5668 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5671 if (null_timespec(ft->mtime)) {
5672 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5675 if (!setting_write_time) {
5676 /* ft->mtime comes from change time, not write time. */
5677 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5680 /* Ensure the resolution is the correct for
5681 * what we can store on this filesystem. */
5683 round_timespec(conn->ts_res, &ft->create_time);
5684 round_timespec(conn->ts_res, &ft->ctime);
5685 round_timespec(conn->ts_res, &ft->atime);
5686 round_timespec(conn->ts_res, &ft->mtime);
5688 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5689 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5690 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5691 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5692 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5693 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5694 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5695 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5697 if (setting_write_time) {
5699 * This was a Windows setfileinfo on an open file.
5700 * NT does this a lot. We also need to
5701 * set the time here, as it can be read by
5702 * FindFirst/FindNext and with the patch for bug #2045
5703 * in smbd/fileio.c it ensures that this timestamp is
5704 * kept sticky even after a write. We save the request
5705 * away and will set it on file close and after a write. JRA.
5708 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5709 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5711 if (fsp != NULL) {
5712 if (fsp->base_fsp) {
5713 set_sticky_write_time_fsp(fsp->base_fsp,
5714 ft->mtime);
5715 } else {
5716 set_sticky_write_time_fsp(fsp, ft->mtime);
5718 } else {
5719 set_sticky_write_time_path(
5720 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5721 ft->mtime);
5725 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5727 /* Always call ntimes on the base, even if a stream was passed in. */
5728 smb_fname_base = *smb_fname;
5729 smb_fname_base.stream_name = NULL;
5731 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5732 return map_nt_error_from_unix(errno);
5735 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5736 smb_fname->base_name);
5737 return NT_STATUS_OK;
5740 /****************************************************************************
5741 Deal with setting the dosmode from any of the setfilepathinfo functions.
5742 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5743 done before calling this function.
5744 ****************************************************************************/
5746 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5747 const struct smb_filename *smb_fname,
5748 uint32 dosmode)
5750 struct smb_filename *smb_fname_base;
5751 NTSTATUS status;
5753 if (!VALID_STAT(smb_fname->st)) {
5754 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5757 /* Always operate on the base_name, even if a stream was passed in. */
5758 smb_fname_base = synthetic_smb_fname(
5759 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5760 if (smb_fname_base == NULL) {
5761 return NT_STATUS_NO_MEMORY;
5764 if (dosmode) {
5765 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5766 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5767 } else {
5768 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5772 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5774 /* check the mode isn't different, before changing it */
5775 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5776 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5777 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5778 (unsigned int)dosmode));
5780 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5781 false)) {
5782 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5783 "%s failed (%s)\n",
5784 smb_fname_str_dbg(smb_fname_base),
5785 strerror(errno)));
5786 status = map_nt_error_from_unix(errno);
5787 goto out;
5790 status = NT_STATUS_OK;
5791 out:
5792 TALLOC_FREE(smb_fname_base);
5793 return status;
5796 /****************************************************************************
5797 Deal with setting the size from any of the setfilepathinfo functions.
5798 ****************************************************************************/
5800 static NTSTATUS smb_set_file_size(connection_struct *conn,
5801 struct smb_request *req,
5802 files_struct *fsp,
5803 const struct smb_filename *smb_fname,
5804 const SMB_STRUCT_STAT *psbuf,
5805 off_t size,
5806 bool fail_after_createfile)
5808 NTSTATUS status = NT_STATUS_OK;
5809 struct smb_filename *smb_fname_tmp = NULL;
5810 files_struct *new_fsp = NULL;
5812 if (!VALID_STAT(*psbuf)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5816 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5818 if (size == get_file_size_stat(psbuf)) {
5819 return NT_STATUS_OK;
5822 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5823 smb_fname_str_dbg(smb_fname), (double)size));
5825 if (fsp && fsp->fh->fd != -1) {
5826 /* Handle based call. */
5827 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5828 return NT_STATUS_ACCESS_DENIED;
5831 if (vfs_set_filelen(fsp, size) == -1) {
5832 return map_nt_error_from_unix(errno);
5834 trigger_write_time_update_immediate(fsp);
5835 return NT_STATUS_OK;
5838 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5839 if (smb_fname_tmp == NULL) {
5840 return NT_STATUS_NO_MEMORY;
5843 smb_fname_tmp->st = *psbuf;
5845 status = SMB_VFS_CREATE_FILE(
5846 conn, /* conn */
5847 req, /* req */
5848 0, /* root_dir_fid */
5849 smb_fname_tmp, /* fname */
5850 FILE_WRITE_DATA, /* access_mask */
5851 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5852 FILE_SHARE_DELETE),
5853 FILE_OPEN, /* create_disposition*/
5854 0, /* create_options */
5855 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5856 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5857 0, /* allocation_size */
5858 0, /* private_flags */
5859 NULL, /* sd */
5860 NULL, /* ea_list */
5861 &new_fsp, /* result */
5862 NULL); /* pinfo */
5864 TALLOC_FREE(smb_fname_tmp);
5866 if (!NT_STATUS_IS_OK(status)) {
5867 /* NB. We check for open_was_deferred in the caller. */
5868 return status;
5871 /* See RAW-SFILEINFO-END-OF-FILE */
5872 if (fail_after_createfile) {
5873 close_file(req, new_fsp,NORMAL_CLOSE);
5874 return NT_STATUS_INVALID_LEVEL;
5877 if (vfs_set_filelen(new_fsp, size) == -1) {
5878 status = map_nt_error_from_unix(errno);
5879 close_file(req, new_fsp,NORMAL_CLOSE);
5880 return status;
5883 trigger_write_time_update_immediate(new_fsp);
5884 close_file(req, new_fsp,NORMAL_CLOSE);
5885 return NT_STATUS_OK;
5888 /****************************************************************************
5889 Deal with SMB_INFO_SET_EA.
5890 ****************************************************************************/
5892 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5893 const char *pdata,
5894 int total_data,
5895 files_struct *fsp,
5896 const struct smb_filename *smb_fname)
5898 struct ea_list *ea_list = NULL;
5899 TALLOC_CTX *ctx = NULL;
5900 NTSTATUS status = NT_STATUS_OK;
5902 if (total_data < 10) {
5904 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5905 length. They seem to have no effect. Bug #3212. JRA */
5907 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5908 /* We're done. We only get EA info in this call. */
5909 return NT_STATUS_OK;
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if (IVAL(pdata,0) > total_data) {
5916 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5917 IVAL(pdata,0), (unsigned int)total_data));
5918 return NT_STATUS_INVALID_PARAMETER;
5921 ctx = talloc_tos();
5922 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5923 if (!ea_list) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 status = set_ea(conn, fsp, smb_fname, ea_list);
5929 return status;
5932 /****************************************************************************
5933 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5934 ****************************************************************************/
5936 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5937 const char *pdata,
5938 int total_data,
5939 files_struct *fsp)
5941 struct ea_list *ea_list = NULL;
5942 NTSTATUS status;
5944 if (!fsp) {
5945 return NT_STATUS_INVALID_HANDLE;
5948 if (!lp_ea_support(SNUM(conn))) {
5949 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5950 "EA's not supported.\n",
5951 (unsigned int)total_data));
5952 return NT_STATUS_EAS_NOT_SUPPORTED;
5955 if (total_data < 10) {
5956 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5957 "too small.\n",
5958 (unsigned int)total_data));
5959 return NT_STATUS_INVALID_PARAMETER;
5962 ea_list = read_nttrans_ea_list(talloc_tos(),
5963 pdata,
5964 total_data);
5966 if (!ea_list) {
5967 return NT_STATUS_INVALID_PARAMETER;
5970 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5972 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5973 smb_fname_str_dbg(fsp->fsp_name),
5974 nt_errstr(status) ));
5976 return status;
5980 /****************************************************************************
5981 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5982 ****************************************************************************/
5984 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5985 const char *pdata,
5986 int total_data,
5987 files_struct *fsp,
5988 struct smb_filename *smb_fname)
5990 NTSTATUS status = NT_STATUS_OK;
5991 bool delete_on_close;
5992 uint32 dosmode = 0;
5994 if (total_data < 1) {
5995 return NT_STATUS_INVALID_PARAMETER;
5998 if (fsp == NULL) {
5999 return NT_STATUS_INVALID_HANDLE;
6002 delete_on_close = (CVAL(pdata,0) ? True : False);
6003 dosmode = dos_mode(conn, smb_fname);
6005 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6006 "delete_on_close = %u\n",
6007 smb_fname_str_dbg(smb_fname),
6008 (unsigned int)dosmode,
6009 (unsigned int)delete_on_close ));
6011 if (delete_on_close) {
6012 status = can_set_delete_on_close(fsp, dosmode);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 return status;
6018 /* The set is across all open files on this dev/inode pair. */
6019 if (!set_delete_on_close(fsp, delete_on_close,
6020 conn->session_info->security_token,
6021 conn->session_info->unix_token)) {
6022 return NT_STATUS_ACCESS_DENIED;
6024 return NT_STATUS_OK;
6027 /****************************************************************************
6028 Deal with SMB_FILE_POSITION_INFORMATION.
6029 ****************************************************************************/
6031 static NTSTATUS smb_file_position_information(connection_struct *conn,
6032 const char *pdata,
6033 int total_data,
6034 files_struct *fsp)
6036 uint64_t position_information;
6038 if (total_data < 8) {
6039 return NT_STATUS_INVALID_PARAMETER;
6042 if (fsp == NULL) {
6043 /* Ignore on pathname based set. */
6044 return NT_STATUS_OK;
6047 position_information = (uint64_t)IVAL(pdata,0);
6048 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6050 DEBUG(10,("smb_file_position_information: Set file position "
6051 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6052 (double)position_information));
6053 fsp->fh->position_information = position_information;
6054 return NT_STATUS_OK;
6057 /****************************************************************************
6058 Deal with SMB_FILE_MODE_INFORMATION.
6059 ****************************************************************************/
6061 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6062 const char *pdata,
6063 int total_data)
6065 uint32 mode;
6067 if (total_data < 4) {
6068 return NT_STATUS_INVALID_PARAMETER;
6070 mode = IVAL(pdata,0);
6071 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6072 return NT_STATUS_INVALID_PARAMETER;
6074 return NT_STATUS_OK;
6077 /****************************************************************************
6078 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6079 ****************************************************************************/
6081 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6082 struct smb_request *req,
6083 const char *pdata,
6084 int total_data,
6085 const struct smb_filename *smb_fname)
6087 char *link_target = NULL;
6088 const char *newname = smb_fname->base_name;
6089 TALLOC_CTX *ctx = talloc_tos();
6091 /* Set a symbolic link. */
6092 /* Don't allow this if follow links is false. */
6094 if (total_data == 0) {
6095 return NT_STATUS_INVALID_PARAMETER;
6098 if (!lp_symlinks(SNUM(conn))) {
6099 return NT_STATUS_ACCESS_DENIED;
6102 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6103 total_data, STR_TERMINATE);
6105 if (!link_target) {
6106 return NT_STATUS_INVALID_PARAMETER;
6109 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6110 newname, link_target ));
6112 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6113 return map_nt_error_from_unix(errno);
6116 return NT_STATUS_OK;
6119 /****************************************************************************
6120 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6121 ****************************************************************************/
6123 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6124 struct smb_request *req,
6125 const char *pdata, int total_data,
6126 struct smb_filename *smb_fname_new)
6128 char *oldname = NULL;
6129 struct smb_filename *smb_fname_old = NULL;
6130 TALLOC_CTX *ctx = talloc_tos();
6131 NTSTATUS status = NT_STATUS_OK;
6133 /* Set a hard link. */
6134 if (total_data == 0) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6139 total_data, STR_TERMINATE, &status);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 return status;
6144 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6145 smb_fname_str_dbg(smb_fname_new), oldname));
6147 status = filename_convert(ctx,
6148 conn,
6149 req->flags2 & FLAGS2_DFS_PATHNAMES,
6150 oldname,
6152 NULL,
6153 &smb_fname_old);
6154 if (!NT_STATUS_IS_OK(status)) {
6155 return status;
6158 return hardlink_internals(ctx, conn, req, false,
6159 smb_fname_old, smb_fname_new);
6162 /****************************************************************************
6163 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6164 ****************************************************************************/
6166 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6167 struct smb_request *req,
6168 const char *pdata,
6169 int total_data,
6170 files_struct *fsp,
6171 struct smb_filename *smb_fname_src)
6173 bool overwrite;
6174 uint32_t len;
6175 char *newname = NULL;
6176 struct smb_filename *smb_fname_dst = NULL;
6177 NTSTATUS status = NT_STATUS_OK;
6178 TALLOC_CTX *ctx = talloc_tos();
6180 if (!fsp) {
6181 return NT_STATUS_INVALID_HANDLE;
6184 if (total_data < 20) {
6185 return NT_STATUS_INVALID_PARAMETER;
6188 overwrite = (CVAL(pdata,0) ? True : False);
6189 len = IVAL(pdata,16);
6191 if (len > (total_data - 20) || (len == 0)) {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6196 &pdata[20], len, STR_TERMINATE,
6197 &status);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 return status;
6202 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6203 newname));
6205 status = filename_convert(ctx,
6206 conn,
6207 req->flags2 & FLAGS2_DFS_PATHNAMES,
6208 newname,
6209 UCF_SAVE_LCOMP,
6210 NULL,
6211 &smb_fname_dst);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 return status;
6216 if (fsp->base_fsp) {
6217 /* newname must be a stream name. */
6218 if (newname[0] != ':') {
6219 return NT_STATUS_NOT_SUPPORTED;
6222 /* Create an smb_fname to call rename_internals_fsp() with. */
6223 smb_fname_dst = synthetic_smb_fname(
6224 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6225 newname, NULL);
6226 if (smb_fname_dst == NULL) {
6227 status = NT_STATUS_NO_MEMORY;
6228 goto out;
6232 * Set the original last component, since
6233 * rename_internals_fsp() requires it.
6235 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6236 newname);
6237 if (smb_fname_dst->original_lcomp == NULL) {
6238 status = NT_STATUS_NO_MEMORY;
6239 goto out;
6244 DEBUG(10,("smb2_file_rename_information: "
6245 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6246 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6247 smb_fname_str_dbg(smb_fname_dst)));
6248 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6249 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6250 overwrite);
6252 out:
6253 TALLOC_FREE(smb_fname_dst);
6254 return status;
6257 static NTSTATUS smb_file_link_information(connection_struct *conn,
6258 struct smb_request *req,
6259 const char *pdata,
6260 int total_data,
6261 files_struct *fsp,
6262 struct smb_filename *smb_fname_src)
6264 bool overwrite;
6265 uint32_t len;
6266 char *newname = NULL;
6267 struct smb_filename *smb_fname_dst = NULL;
6268 NTSTATUS status = NT_STATUS_OK;
6269 TALLOC_CTX *ctx = talloc_tos();
6271 if (!fsp) {
6272 return NT_STATUS_INVALID_HANDLE;
6275 if (total_data < 20) {
6276 return NT_STATUS_INVALID_PARAMETER;
6279 overwrite = (CVAL(pdata,0) ? true : false);
6280 len = IVAL(pdata,16);
6282 if (len > (total_data - 20) || (len == 0)) {
6283 return NT_STATUS_INVALID_PARAMETER;
6286 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6287 &pdata[20], len, STR_TERMINATE,
6288 &status);
6289 if (!NT_STATUS_IS_OK(status)) {
6290 return status;
6293 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6294 newname));
6296 status = filename_convert(ctx,
6297 conn,
6298 req->flags2 & FLAGS2_DFS_PATHNAMES,
6299 newname,
6300 UCF_SAVE_LCOMP,
6301 NULL,
6302 &smb_fname_dst);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 return status;
6307 if (fsp->base_fsp) {
6308 /* No stream names. */
6309 return NT_STATUS_NOT_SUPPORTED;
6312 DEBUG(10,("smb_file_link_information: "
6313 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6314 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6315 smb_fname_str_dbg(smb_fname_dst)));
6316 status = hardlink_internals(ctx,
6317 conn,
6318 req,
6319 overwrite,
6320 fsp->fsp_name,
6321 smb_fname_dst);
6323 TALLOC_FREE(smb_fname_dst);
6324 return status;
6327 /****************************************************************************
6328 Deal with SMB_FILE_RENAME_INFORMATION.
6329 ****************************************************************************/
6331 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6332 struct smb_request *req,
6333 const char *pdata,
6334 int total_data,
6335 files_struct *fsp,
6336 struct smb_filename *smb_fname_src)
6338 bool overwrite;
6339 uint32 root_fid;
6340 uint32 len;
6341 char *newname = NULL;
6342 struct smb_filename *smb_fname_dst = NULL;
6343 bool dest_has_wcard = False;
6344 NTSTATUS status = NT_STATUS_OK;
6345 char *p;
6346 TALLOC_CTX *ctx = talloc_tos();
6348 if (total_data < 13) {
6349 return NT_STATUS_INVALID_PARAMETER;
6352 overwrite = (CVAL(pdata,0) ? True : False);
6353 root_fid = IVAL(pdata,4);
6354 len = IVAL(pdata,8);
6356 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6357 return NT_STATUS_INVALID_PARAMETER;
6360 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6361 len, 0, &status,
6362 &dest_has_wcard);
6363 if (!NT_STATUS_IS_OK(status)) {
6364 return status;
6367 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6368 newname));
6370 status = resolve_dfspath_wcard(ctx, conn,
6371 req->flags2 & FLAGS2_DFS_PATHNAMES,
6372 newname,
6373 true,
6374 !conn->sconn->using_smb2,
6375 &newname,
6376 &dest_has_wcard);
6377 if (!NT_STATUS_IS_OK(status)) {
6378 return status;
6381 /* Check the new name has no '/' characters. */
6382 if (strchr_m(newname, '/')) {
6383 return NT_STATUS_NOT_SUPPORTED;
6386 if (fsp && fsp->base_fsp) {
6387 /* newname must be a stream name. */
6388 if (newname[0] != ':') {
6389 return NT_STATUS_NOT_SUPPORTED;
6392 /* Create an smb_fname to call rename_internals_fsp() with. */
6393 smb_fname_dst = synthetic_smb_fname(
6394 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6395 newname, NULL);
6396 if (smb_fname_dst == NULL) {
6397 status = NT_STATUS_NO_MEMORY;
6398 goto out;
6402 * Set the original last component, since
6403 * rename_internals_fsp() requires it.
6405 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6406 newname);
6407 if (smb_fname_dst->original_lcomp == NULL) {
6408 status = NT_STATUS_NO_MEMORY;
6409 goto out;
6412 } else {
6414 * Build up an smb_fname_dst based on the filename passed in.
6415 * We basically just strip off the last component, and put on
6416 * the newname instead.
6418 char *base_name = NULL;
6420 /* newname must *not* be a stream name. */
6421 if (newname[0] == ':') {
6422 return NT_STATUS_NOT_SUPPORTED;
6426 * Strip off the last component (filename) of the path passed
6427 * in.
6429 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6430 if (!base_name) {
6431 return NT_STATUS_NO_MEMORY;
6433 p = strrchr_m(base_name, '/');
6434 if (p) {
6435 p[1] = '\0';
6436 } else {
6437 base_name = talloc_strdup(ctx, "");
6438 if (!base_name) {
6439 return NT_STATUS_NO_MEMORY;
6442 /* Append the new name. */
6443 base_name = talloc_asprintf_append(base_name,
6444 "%s",
6445 newname);
6446 if (!base_name) {
6447 return NT_STATUS_NO_MEMORY;
6450 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6451 (UCF_SAVE_LCOMP |
6452 (dest_has_wcard ?
6453 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6454 0)));
6456 /* If an error we expect this to be
6457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6459 if (!NT_STATUS_IS_OK(status)) {
6460 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6461 status)) {
6462 goto out;
6464 /* Create an smb_fname to call rename_internals_fsp() */
6465 smb_fname_dst = synthetic_smb_fname(
6466 ctx, base_name, NULL, NULL);
6467 if (smb_fname_dst == NULL) {
6468 status = NT_STATUS_NO_MEMORY;
6469 goto out;
6474 if (fsp) {
6475 DEBUG(10,("smb_file_rename_information: "
6476 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6477 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6478 smb_fname_str_dbg(smb_fname_dst)));
6479 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6480 overwrite);
6481 } else {
6482 DEBUG(10,("smb_file_rename_information: "
6483 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6484 smb_fname_str_dbg(smb_fname_src),
6485 smb_fname_str_dbg(smb_fname_dst)));
6486 status = rename_internals(ctx, conn, req, smb_fname_src,
6487 smb_fname_dst, 0, overwrite, false,
6488 dest_has_wcard,
6489 FILE_WRITE_ATTRIBUTES);
6491 out:
6492 TALLOC_FREE(smb_fname_dst);
6493 return status;
6496 /****************************************************************************
6497 Deal with SMB_SET_POSIX_ACL.
6498 ****************************************************************************/
6500 #if defined(HAVE_POSIX_ACLS)
6501 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6502 const char *pdata,
6503 int total_data,
6504 files_struct *fsp,
6505 const struct smb_filename *smb_fname)
6507 uint16 posix_acl_version;
6508 uint16 num_file_acls;
6509 uint16 num_def_acls;
6510 bool valid_file_acls = True;
6511 bool valid_def_acls = True;
6513 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6514 return NT_STATUS_INVALID_PARAMETER;
6516 posix_acl_version = SVAL(pdata,0);
6517 num_file_acls = SVAL(pdata,2);
6518 num_def_acls = SVAL(pdata,4);
6520 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6521 valid_file_acls = False;
6522 num_file_acls = 0;
6525 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6526 valid_def_acls = False;
6527 num_def_acls = 0;
6530 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6531 return NT_STATUS_INVALID_PARAMETER;
6534 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6535 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6536 return NT_STATUS_INVALID_PARAMETER;
6539 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6540 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6541 (unsigned int)num_file_acls,
6542 (unsigned int)num_def_acls));
6544 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6545 smb_fname->base_name, num_file_acls,
6546 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6547 return map_nt_error_from_unix(errno);
6550 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6551 smb_fname->base_name, &smb_fname->st, num_def_acls,
6552 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6553 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6554 return map_nt_error_from_unix(errno);
6556 return NT_STATUS_OK;
6558 #endif
6560 /****************************************************************************
6561 Deal with SMB_SET_POSIX_LOCK.
6562 ****************************************************************************/
6564 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6565 struct smb_request *req,
6566 const char *pdata,
6567 int total_data,
6568 files_struct *fsp)
6570 uint64_t count;
6571 uint64_t offset;
6572 uint64_t smblctx;
6573 bool blocking_lock = False;
6574 enum brl_type lock_type;
6576 NTSTATUS status = NT_STATUS_OK;
6578 if (fsp == NULL || fsp->fh->fd == -1) {
6579 return NT_STATUS_INVALID_HANDLE;
6582 if (total_data != POSIX_LOCK_DATA_SIZE) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6587 case POSIX_LOCK_TYPE_READ:
6588 lock_type = READ_LOCK;
6589 break;
6590 case POSIX_LOCK_TYPE_WRITE:
6591 /* Return the right POSIX-mappable error code for files opened read-only. */
6592 if (!fsp->can_write) {
6593 return NT_STATUS_INVALID_HANDLE;
6595 lock_type = WRITE_LOCK;
6596 break;
6597 case POSIX_LOCK_TYPE_UNLOCK:
6598 lock_type = UNLOCK_LOCK;
6599 break;
6600 default:
6601 return NT_STATUS_INVALID_PARAMETER;
6604 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6605 blocking_lock = False;
6606 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6607 blocking_lock = True;
6608 } else {
6609 return NT_STATUS_INVALID_PARAMETER;
6612 if (!lp_blocking_locks(SNUM(conn))) {
6613 blocking_lock = False;
6616 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6617 #if defined(HAVE_LONGLONG)
6618 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6619 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6620 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6621 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6622 #else /* HAVE_LONGLONG */
6623 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6624 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6625 #endif /* HAVE_LONGLONG */
6627 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6628 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6629 fsp_str_dbg(fsp),
6630 (unsigned int)lock_type,
6631 (unsigned long long)smblctx,
6632 (double)count,
6633 (double)offset ));
6635 if (lock_type == UNLOCK_LOCK) {
6636 status = do_unlock(req->sconn->msg_ctx,
6637 fsp,
6638 smblctx,
6639 count,
6640 offset,
6641 POSIX_LOCK);
6642 } else {
6643 uint64_t block_smblctx;
6645 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6646 fsp,
6647 smblctx,
6648 count,
6649 offset,
6650 lock_type,
6651 POSIX_LOCK,
6652 blocking_lock,
6653 &status,
6654 &block_smblctx,
6655 NULL);
6657 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6659 * A blocking lock was requested. Package up
6660 * this smb into a queued request and push it
6661 * onto the blocking lock queue.
6663 if(push_blocking_lock_request(br_lck,
6664 req,
6665 fsp,
6666 -1, /* infinite timeout. */
6668 smblctx,
6669 lock_type,
6670 POSIX_LOCK,
6671 offset,
6672 count,
6673 block_smblctx)) {
6674 TALLOC_FREE(br_lck);
6675 return status;
6678 TALLOC_FREE(br_lck);
6681 return status;
6684 /****************************************************************************
6685 Deal with SMB_SET_FILE_BASIC_INFO.
6686 ****************************************************************************/
6688 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6689 const char *pdata,
6690 int total_data,
6691 files_struct *fsp,
6692 const struct smb_filename *smb_fname)
6694 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6695 struct smb_file_time ft;
6696 uint32 dosmode = 0;
6697 NTSTATUS status = NT_STATUS_OK;
6699 ZERO_STRUCT(ft);
6701 if (total_data < 36) {
6702 return NT_STATUS_INVALID_PARAMETER;
6705 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6706 if (!NT_STATUS_IS_OK(status)) {
6707 return status;
6710 /* Set the attributes */
6711 dosmode = IVAL(pdata,32);
6712 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6713 if (!NT_STATUS_IS_OK(status)) {
6714 return status;
6717 /* create time */
6718 ft.create_time = interpret_long_date(pdata);
6720 /* access time */
6721 ft.atime = interpret_long_date(pdata+8);
6723 /* write time. */
6724 ft.mtime = interpret_long_date(pdata+16);
6726 /* change time. */
6727 ft.ctime = interpret_long_date(pdata+24);
6729 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6730 smb_fname_str_dbg(smb_fname)));
6732 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6733 true);
6736 /****************************************************************************
6737 Deal with SMB_INFO_STANDARD.
6738 ****************************************************************************/
6740 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6741 const char *pdata,
6742 int total_data,
6743 files_struct *fsp,
6744 const struct smb_filename *smb_fname)
6746 NTSTATUS status;
6747 struct smb_file_time ft;
6749 ZERO_STRUCT(ft);
6751 if (total_data < 12) {
6752 return NT_STATUS_INVALID_PARAMETER;
6755 /* create time */
6756 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6757 /* access time */
6758 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6759 /* write time */
6760 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6762 DEBUG(10,("smb_set_info_standard: file %s\n",
6763 smb_fname_str_dbg(smb_fname)));
6765 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6766 if (!NT_STATUS_IS_OK(status)) {
6767 return status;
6770 return smb_set_file_time(conn,
6771 fsp,
6772 smb_fname,
6773 &ft,
6774 true);
6777 /****************************************************************************
6778 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6779 ****************************************************************************/
6781 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6782 struct smb_request *req,
6783 const char *pdata,
6784 int total_data,
6785 files_struct *fsp,
6786 struct smb_filename *smb_fname)
6788 uint64_t allocation_size = 0;
6789 NTSTATUS status = NT_STATUS_OK;
6790 files_struct *new_fsp = NULL;
6792 if (!VALID_STAT(smb_fname->st)) {
6793 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6796 if (total_data < 8) {
6797 return NT_STATUS_INVALID_PARAMETER;
6800 allocation_size = (uint64_t)IVAL(pdata,0);
6801 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6802 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6803 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6804 (double)allocation_size));
6806 if (allocation_size) {
6807 allocation_size = smb_roundup(conn, allocation_size);
6810 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6811 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6812 (double)allocation_size));
6814 if (fsp && fsp->fh->fd != -1) {
6815 /* Open file handle. */
6816 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6817 return NT_STATUS_ACCESS_DENIED;
6820 /* Only change if needed. */
6821 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6822 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6823 return map_nt_error_from_unix(errno);
6826 /* But always update the time. */
6828 * This is equivalent to a write. Ensure it's seen immediately
6829 * if there are no pending writes.
6831 trigger_write_time_update_immediate(fsp);
6832 return NT_STATUS_OK;
6835 /* Pathname or stat or directory file. */
6836 status = SMB_VFS_CREATE_FILE(
6837 conn, /* conn */
6838 req, /* req */
6839 0, /* root_dir_fid */
6840 smb_fname, /* fname */
6841 FILE_WRITE_DATA, /* access_mask */
6842 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6843 FILE_SHARE_DELETE),
6844 FILE_OPEN, /* create_disposition*/
6845 0, /* create_options */
6846 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6847 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6848 0, /* allocation_size */
6849 0, /* private_flags */
6850 NULL, /* sd */
6851 NULL, /* ea_list */
6852 &new_fsp, /* result */
6853 NULL); /* pinfo */
6855 if (!NT_STATUS_IS_OK(status)) {
6856 /* NB. We check for open_was_deferred in the caller. */
6857 return status;
6860 /* Only change if needed. */
6861 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6862 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6863 status = map_nt_error_from_unix(errno);
6864 close_file(req, new_fsp, NORMAL_CLOSE);
6865 return status;
6869 /* Changing the allocation size should set the last mod time. */
6871 * This is equivalent to a write. Ensure it's seen immediately
6872 * if there are no pending writes.
6874 trigger_write_time_update_immediate(new_fsp);
6876 close_file(req, new_fsp, NORMAL_CLOSE);
6877 return NT_STATUS_OK;
6880 /****************************************************************************
6881 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6882 ****************************************************************************/
6884 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6885 struct smb_request *req,
6886 const char *pdata,
6887 int total_data,
6888 files_struct *fsp,
6889 const struct smb_filename *smb_fname,
6890 bool fail_after_createfile)
6892 off_t size;
6894 if (total_data < 8) {
6895 return NT_STATUS_INVALID_PARAMETER;
6898 size = IVAL(pdata,0);
6899 size |= (((off_t)IVAL(pdata,4)) << 32);
6900 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6901 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6902 (double)size));
6904 return smb_set_file_size(conn, req,
6905 fsp,
6906 smb_fname,
6907 &smb_fname->st,
6908 size,
6909 fail_after_createfile);
6912 /****************************************************************************
6913 Allow a UNIX info mknod.
6914 ****************************************************************************/
6916 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6917 const char *pdata,
6918 int total_data,
6919 const struct smb_filename *smb_fname)
6921 uint32 file_type = IVAL(pdata,56);
6922 #if defined(HAVE_MAKEDEV)
6923 uint32 dev_major = IVAL(pdata,60);
6924 uint32 dev_minor = IVAL(pdata,68);
6925 #endif
6926 SMB_DEV_T dev = (SMB_DEV_T)0;
6927 uint32 raw_unixmode = IVAL(pdata,84);
6928 NTSTATUS status;
6929 mode_t unixmode;
6931 if (total_data < 100) {
6932 return NT_STATUS_INVALID_PARAMETER;
6935 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6936 PERM_NEW_FILE, &unixmode);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 return status;
6941 #if defined(HAVE_MAKEDEV)
6942 dev = makedev(dev_major, dev_minor);
6943 #endif
6945 switch (file_type) {
6946 #if defined(S_IFIFO)
6947 case UNIX_TYPE_FIFO:
6948 unixmode |= S_IFIFO;
6949 break;
6950 #endif
6951 #if defined(S_IFSOCK)
6952 case UNIX_TYPE_SOCKET:
6953 unixmode |= S_IFSOCK;
6954 break;
6955 #endif
6956 #if defined(S_IFCHR)
6957 case UNIX_TYPE_CHARDEV:
6958 unixmode |= S_IFCHR;
6959 break;
6960 #endif
6961 #if defined(S_IFBLK)
6962 case UNIX_TYPE_BLKDEV:
6963 unixmode |= S_IFBLK;
6964 break;
6965 #endif
6966 default:
6967 return NT_STATUS_INVALID_PARAMETER;
6970 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6971 "%.0f mode 0%o for file %s\n", (double)dev,
6972 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6974 /* Ok - do the mknod. */
6975 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6976 return map_nt_error_from_unix(errno);
6979 /* If any of the other "set" calls fail we
6980 * don't want to end up with a half-constructed mknod.
6983 if (lp_inherit_perms(SNUM(conn))) {
6984 char *parent;
6985 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6986 &parent, NULL)) {
6987 return NT_STATUS_NO_MEMORY;
6989 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6990 unixmode);
6991 TALLOC_FREE(parent);
6994 return NT_STATUS_OK;
6997 /****************************************************************************
6998 Deal with SMB_SET_FILE_UNIX_BASIC.
6999 ****************************************************************************/
7001 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7002 struct smb_request *req,
7003 const char *pdata,
7004 int total_data,
7005 files_struct *fsp,
7006 const struct smb_filename *smb_fname)
7008 struct smb_file_time ft;
7009 uint32 raw_unixmode;
7010 mode_t unixmode;
7011 off_t size = 0;
7012 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7013 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7014 NTSTATUS status = NT_STATUS_OK;
7015 bool delete_on_fail = False;
7016 enum perm_type ptype;
7017 files_struct *all_fsps = NULL;
7018 bool modify_mtime = true;
7019 struct file_id id;
7020 struct smb_filename *smb_fname_tmp = NULL;
7021 SMB_STRUCT_STAT sbuf;
7023 ZERO_STRUCT(ft);
7025 if (total_data < 100) {
7026 return NT_STATUS_INVALID_PARAMETER;
7029 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7030 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7031 size=IVAL(pdata,0); /* first 8 Bytes are size */
7032 size |= (((off_t)IVAL(pdata,4)) << 32);
7035 ft.atime = interpret_long_date(pdata+24); /* access_time */
7036 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7037 set_owner = (uid_t)IVAL(pdata,40);
7038 set_grp = (gid_t)IVAL(pdata,48);
7039 raw_unixmode = IVAL(pdata,84);
7041 if (VALID_STAT(smb_fname->st)) {
7042 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7043 ptype = PERM_EXISTING_DIR;
7044 } else {
7045 ptype = PERM_EXISTING_FILE;
7047 } else {
7048 ptype = PERM_NEW_FILE;
7051 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7052 ptype, &unixmode);
7053 if (!NT_STATUS_IS_OK(status)) {
7054 return status;
7057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7058 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7059 smb_fname_str_dbg(smb_fname), (double)size,
7060 (unsigned int)set_owner, (unsigned int)set_grp,
7061 (int)raw_unixmode));
7063 sbuf = smb_fname->st;
7065 if (!VALID_STAT(sbuf)) {
7067 * The only valid use of this is to create character and block
7068 * devices, and named pipes. This is deprecated (IMHO) and
7069 * a new info level should be used for mknod. JRA.
7072 status = smb_unix_mknod(conn,
7073 pdata,
7074 total_data,
7075 smb_fname);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 return status;
7080 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7081 if (smb_fname_tmp == NULL) {
7082 return NT_STATUS_NO_MEMORY;
7085 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7086 status = map_nt_error_from_unix(errno);
7087 TALLOC_FREE(smb_fname_tmp);
7088 SMB_VFS_UNLINK(conn, smb_fname);
7089 return status;
7092 sbuf = smb_fname_tmp->st;
7093 smb_fname = smb_fname_tmp;
7095 /* Ensure we don't try and change anything else. */
7096 raw_unixmode = SMB_MODE_NO_CHANGE;
7097 size = get_file_size_stat(&sbuf);
7098 ft.atime = sbuf.st_ex_atime;
7099 ft.mtime = sbuf.st_ex_mtime;
7101 * We continue here as we might want to change the
7102 * owner uid/gid.
7104 delete_on_fail = True;
7107 #if 1
7108 /* Horrible backwards compatibility hack as an old server bug
7109 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7110 * */
7112 if (!size) {
7113 size = get_file_size_stat(&sbuf);
7115 #endif
7118 * Deal with the UNIX specific mode set.
7121 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7123 "setting mode 0%o for file %s\n",
7124 (unsigned int)unixmode,
7125 smb_fname_str_dbg(smb_fname)));
7126 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7127 return map_nt_error_from_unix(errno);
7132 * Deal with the UNIX specific uid set.
7135 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7136 (sbuf.st_ex_uid != set_owner)) {
7137 int ret;
7139 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7140 "changing owner %u for path %s\n",
7141 (unsigned int)set_owner,
7142 smb_fname_str_dbg(smb_fname)));
7144 if (S_ISLNK(sbuf.st_ex_mode)) {
7145 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7146 set_owner, (gid_t)-1);
7147 } else {
7148 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7149 set_owner, (gid_t)-1);
7152 if (ret != 0) {
7153 status = map_nt_error_from_unix(errno);
7154 if (delete_on_fail) {
7155 SMB_VFS_UNLINK(conn, smb_fname);
7157 return status;
7162 * Deal with the UNIX specific gid set.
7165 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7166 (sbuf.st_ex_gid != set_grp)) {
7167 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7168 "changing group %u for file %s\n",
7169 (unsigned int)set_owner,
7170 smb_fname_str_dbg(smb_fname)));
7171 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7172 set_grp) != 0) {
7173 status = map_nt_error_from_unix(errno);
7174 if (delete_on_fail) {
7175 SMB_VFS_UNLINK(conn, smb_fname);
7177 return status;
7181 /* Deal with any size changes. */
7183 status = smb_set_file_size(conn, req,
7184 fsp,
7185 smb_fname,
7186 &sbuf,
7187 size,
7188 false);
7189 if (!NT_STATUS_IS_OK(status)) {
7190 return status;
7193 /* Deal with any time changes. */
7194 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7195 /* No change, don't cancel anything. */
7196 return status;
7199 id = vfs_file_id_from_sbuf(conn, &sbuf);
7200 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7201 all_fsps = file_find_di_next(all_fsps)) {
7203 * We're setting the time explicitly for UNIX.
7204 * Cancel any pending changes over all handles.
7206 all_fsps->update_write_time_on_close = false;
7207 TALLOC_FREE(all_fsps->update_write_time_event);
7211 * Override the "setting_write_time"
7212 * parameter here as it almost does what
7213 * we need. Just remember if we modified
7214 * mtime and send the notify ourselves.
7216 if (null_timespec(ft.mtime)) {
7217 modify_mtime = false;
7220 status = smb_set_file_time(conn,
7221 fsp,
7222 smb_fname,
7223 &ft,
7224 false);
7225 if (modify_mtime) {
7226 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7227 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7229 return status;
7232 /****************************************************************************
7233 Deal with SMB_SET_FILE_UNIX_INFO2.
7234 ****************************************************************************/
7236 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7237 struct smb_request *req,
7238 const char *pdata,
7239 int total_data,
7240 files_struct *fsp,
7241 const struct smb_filename *smb_fname)
7243 NTSTATUS status;
7244 uint32 smb_fflags;
7245 uint32 smb_fmask;
7247 if (total_data < 116) {
7248 return NT_STATUS_INVALID_PARAMETER;
7251 /* Start by setting all the fields that are common between UNIX_BASIC
7252 * and UNIX_INFO2.
7254 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7255 fsp, smb_fname);
7256 if (!NT_STATUS_IS_OK(status)) {
7257 return status;
7260 smb_fflags = IVAL(pdata, 108);
7261 smb_fmask = IVAL(pdata, 112);
7263 /* NB: We should only attempt to alter the file flags if the client
7264 * sends a non-zero mask.
7266 if (smb_fmask != 0) {
7267 int stat_fflags = 0;
7269 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7270 smb_fmask, &stat_fflags)) {
7271 /* Client asked to alter a flag we don't understand. */
7272 return NT_STATUS_INVALID_PARAMETER;
7275 if (fsp && fsp->fh->fd != -1) {
7276 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7277 return NT_STATUS_NOT_SUPPORTED;
7278 } else {
7279 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7280 stat_fflags) != 0) {
7281 return map_nt_error_from_unix(errno);
7286 /* XXX: need to add support for changing the create_time here. You
7287 * can do this for paths on Darwin with setattrlist(2). The right way
7288 * to hook this up is probably by extending the VFS utimes interface.
7291 return NT_STATUS_OK;
7294 /****************************************************************************
7295 Create a directory with POSIX semantics.
7296 ****************************************************************************/
7298 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7299 struct smb_request *req,
7300 char **ppdata,
7301 int total_data,
7302 struct smb_filename *smb_fname,
7303 int *pdata_return_size)
7305 NTSTATUS status = NT_STATUS_OK;
7306 uint32 raw_unixmode = 0;
7307 uint32 mod_unixmode = 0;
7308 mode_t unixmode = (mode_t)0;
7309 files_struct *fsp = NULL;
7310 uint16 info_level_return = 0;
7311 int info;
7312 char *pdata = *ppdata;
7314 if (total_data < 18) {
7315 return NT_STATUS_INVALID_PARAMETER;
7318 raw_unixmode = IVAL(pdata,8);
7319 /* Next 4 bytes are not yet defined. */
7321 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7322 PERM_NEW_DIR, &unixmode);
7323 if (!NT_STATUS_IS_OK(status)) {
7324 return status;
7327 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7329 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7330 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7332 status = SMB_VFS_CREATE_FILE(
7333 conn, /* conn */
7334 req, /* req */
7335 0, /* root_dir_fid */
7336 smb_fname, /* fname */
7337 FILE_READ_ATTRIBUTES, /* access_mask */
7338 FILE_SHARE_NONE, /* share_access */
7339 FILE_CREATE, /* create_disposition*/
7340 FILE_DIRECTORY_FILE, /* create_options */
7341 mod_unixmode, /* file_attributes */
7342 0, /* oplock_request */
7343 0, /* allocation_size */
7344 0, /* private_flags */
7345 NULL, /* sd */
7346 NULL, /* ea_list */
7347 &fsp, /* result */
7348 &info); /* pinfo */
7350 if (NT_STATUS_IS_OK(status)) {
7351 close_file(req, fsp, NORMAL_CLOSE);
7354 info_level_return = SVAL(pdata,16);
7356 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7357 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7358 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7359 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7360 } else {
7361 *pdata_return_size = 12;
7364 /* Realloc the data size */
7365 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7366 if (*ppdata == NULL) {
7367 *pdata_return_size = 0;
7368 return NT_STATUS_NO_MEMORY;
7370 pdata = *ppdata;
7372 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7373 SSVAL(pdata,2,0); /* No fnum. */
7374 SIVAL(pdata,4,info); /* Was directory created. */
7376 switch (info_level_return) {
7377 case SMB_QUERY_FILE_UNIX_BASIC:
7378 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7379 SSVAL(pdata,10,0); /* Padding. */
7380 store_file_unix_basic(conn, pdata + 12, fsp,
7381 &smb_fname->st);
7382 break;
7383 case SMB_QUERY_FILE_UNIX_INFO2:
7384 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7385 SSVAL(pdata,10,0); /* Padding. */
7386 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7387 &smb_fname->st);
7388 break;
7389 default:
7390 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7391 SSVAL(pdata,10,0); /* Padding. */
7392 break;
7395 return status;
7398 /****************************************************************************
7399 Open/Create a file with POSIX semantics.
7400 ****************************************************************************/
7402 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7403 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7405 static NTSTATUS smb_posix_open(connection_struct *conn,
7406 struct smb_request *req,
7407 char **ppdata,
7408 int total_data,
7409 struct smb_filename *smb_fname,
7410 int *pdata_return_size)
7412 bool extended_oplock_granted = False;
7413 char *pdata = *ppdata;
7414 uint32 flags = 0;
7415 uint32 wire_open_mode = 0;
7416 uint32 raw_unixmode = 0;
7417 uint32 mod_unixmode = 0;
7418 uint32 create_disp = 0;
7419 uint32 access_mask = 0;
7420 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7421 NTSTATUS status = NT_STATUS_OK;
7422 mode_t unixmode = (mode_t)0;
7423 files_struct *fsp = NULL;
7424 int oplock_request = 0;
7425 int info = 0;
7426 uint16 info_level_return = 0;
7428 if (total_data < 18) {
7429 return NT_STATUS_INVALID_PARAMETER;
7432 flags = IVAL(pdata,0);
7433 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7434 if (oplock_request) {
7435 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7438 wire_open_mode = IVAL(pdata,4);
7440 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7441 return smb_posix_mkdir(conn, req,
7442 ppdata,
7443 total_data,
7444 smb_fname,
7445 pdata_return_size);
7448 switch (wire_open_mode & SMB_ACCMODE) {
7449 case SMB_O_RDONLY:
7450 access_mask = SMB_O_RDONLY_MAPPING;
7451 break;
7452 case SMB_O_WRONLY:
7453 access_mask = SMB_O_WRONLY_MAPPING;
7454 break;
7455 case SMB_O_RDWR:
7456 access_mask = (SMB_O_RDONLY_MAPPING|
7457 SMB_O_WRONLY_MAPPING);
7458 break;
7459 default:
7460 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7461 (unsigned int)wire_open_mode ));
7462 return NT_STATUS_INVALID_PARAMETER;
7465 wire_open_mode &= ~SMB_ACCMODE;
7467 /* First take care of O_CREAT|O_EXCL interactions. */
7468 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7469 case (SMB_O_CREAT | SMB_O_EXCL):
7470 /* File exists fail. File not exist create. */
7471 create_disp = FILE_CREATE;
7472 break;
7473 case SMB_O_CREAT:
7474 /* File exists open. File not exist create. */
7475 create_disp = FILE_OPEN_IF;
7476 break;
7477 case SMB_O_EXCL:
7478 /* O_EXCL on its own without O_CREAT is undefined.
7479 We deliberately ignore it as some versions of
7480 Linux CIFSFS can send a bare O_EXCL on the
7481 wire which other filesystems in the kernel
7482 ignore. See bug 9519 for details. */
7484 /* Fallthrough. */
7486 case 0:
7487 /* File exists open. File not exist fail. */
7488 create_disp = FILE_OPEN;
7489 break;
7490 default:
7491 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7492 (unsigned int)wire_open_mode ));
7493 return NT_STATUS_INVALID_PARAMETER;
7496 /* Next factor in the effects of O_TRUNC. */
7497 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7499 if (wire_open_mode & SMB_O_TRUNC) {
7500 switch (create_disp) {
7501 case FILE_CREATE:
7502 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7503 /* Leave create_disp alone as
7504 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7506 /* File exists fail. File not exist create. */
7507 break;
7508 case FILE_OPEN_IF:
7509 /* SMB_O_CREAT | SMB_O_TRUNC */
7510 /* File exists overwrite. File not exist create. */
7511 create_disp = FILE_OVERWRITE_IF;
7512 break;
7513 case FILE_OPEN:
7514 /* SMB_O_TRUNC */
7515 /* File exists overwrite. File not exist fail. */
7516 create_disp = FILE_OVERWRITE;
7517 break;
7518 default:
7519 /* Cannot get here. */
7520 smb_panic("smb_posix_open: logic error");
7521 return NT_STATUS_INVALID_PARAMETER;
7525 raw_unixmode = IVAL(pdata,8);
7526 /* Next 4 bytes are not yet defined. */
7528 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7529 (VALID_STAT(smb_fname->st) ?
7530 PERM_EXISTING_FILE : PERM_NEW_FILE),
7531 &unixmode);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 return status;
7537 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7539 if (wire_open_mode & SMB_O_SYNC) {
7540 create_options |= FILE_WRITE_THROUGH;
7542 if (wire_open_mode & SMB_O_APPEND) {
7543 access_mask |= FILE_APPEND_DATA;
7545 if (wire_open_mode & SMB_O_DIRECT) {
7546 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7549 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7550 VALID_STAT_OF_DIR(smb_fname->st)) {
7551 if (access_mask != SMB_O_RDONLY_MAPPING) {
7552 return NT_STATUS_FILE_IS_A_DIRECTORY;
7554 create_options &= ~FILE_NON_DIRECTORY_FILE;
7555 create_options |= FILE_DIRECTORY_FILE;
7558 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7559 smb_fname_str_dbg(smb_fname),
7560 (unsigned int)wire_open_mode,
7561 (unsigned int)unixmode ));
7563 status = SMB_VFS_CREATE_FILE(
7564 conn, /* conn */
7565 req, /* req */
7566 0, /* root_dir_fid */
7567 smb_fname, /* fname */
7568 access_mask, /* access_mask */
7569 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7570 FILE_SHARE_DELETE),
7571 create_disp, /* create_disposition*/
7572 create_options, /* create_options */
7573 mod_unixmode, /* file_attributes */
7574 oplock_request, /* oplock_request */
7575 0, /* allocation_size */
7576 0, /* private_flags */
7577 NULL, /* sd */
7578 NULL, /* ea_list */
7579 &fsp, /* result */
7580 &info); /* pinfo */
7582 if (!NT_STATUS_IS_OK(status)) {
7583 return status;
7586 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7587 extended_oplock_granted = True;
7590 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7591 extended_oplock_granted = True;
7594 info_level_return = SVAL(pdata,16);
7596 /* Allocate the correct return size. */
7598 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7599 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7600 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7601 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7602 } else {
7603 *pdata_return_size = 12;
7606 /* Realloc the data size */
7607 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7608 if (*ppdata == NULL) {
7609 close_file(req, fsp, ERROR_CLOSE);
7610 *pdata_return_size = 0;
7611 return NT_STATUS_NO_MEMORY;
7613 pdata = *ppdata;
7615 if (extended_oplock_granted) {
7616 if (flags & REQUEST_BATCH_OPLOCK) {
7617 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7618 } else {
7619 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7621 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7622 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7623 } else {
7624 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7627 SSVAL(pdata,2,fsp->fnum);
7628 SIVAL(pdata,4,info); /* Was file created etc. */
7630 switch (info_level_return) {
7631 case SMB_QUERY_FILE_UNIX_BASIC:
7632 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7633 SSVAL(pdata,10,0); /* padding. */
7634 store_file_unix_basic(conn, pdata + 12, fsp,
7635 &smb_fname->st);
7636 break;
7637 case SMB_QUERY_FILE_UNIX_INFO2:
7638 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7639 SSVAL(pdata,10,0); /* padding. */
7640 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7641 &smb_fname->st);
7642 break;
7643 default:
7644 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7645 SSVAL(pdata,10,0); /* padding. */
7646 break;
7648 return NT_STATUS_OK;
7651 /****************************************************************************
7652 Delete a file with POSIX semantics.
7653 ****************************************************************************/
7655 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7656 struct smb_request *req,
7657 const char *pdata,
7658 int total_data,
7659 struct smb_filename *smb_fname)
7661 NTSTATUS status = NT_STATUS_OK;
7662 files_struct *fsp = NULL;
7663 uint16 flags = 0;
7664 char del = 1;
7665 int info = 0;
7666 int create_options = 0;
7667 int i;
7668 struct share_mode_lock *lck = NULL;
7670 if (total_data < 2) {
7671 return NT_STATUS_INVALID_PARAMETER;
7674 flags = SVAL(pdata,0);
7676 if (!VALID_STAT(smb_fname->st)) {
7677 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7680 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7681 !VALID_STAT_OF_DIR(smb_fname->st)) {
7682 return NT_STATUS_NOT_A_DIRECTORY;
7685 DEBUG(10,("smb_posix_unlink: %s %s\n",
7686 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7687 smb_fname_str_dbg(smb_fname)));
7689 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7690 create_options |= FILE_DIRECTORY_FILE;
7693 status = SMB_VFS_CREATE_FILE(
7694 conn, /* conn */
7695 req, /* req */
7696 0, /* root_dir_fid */
7697 smb_fname, /* fname */
7698 DELETE_ACCESS, /* access_mask */
7699 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7700 FILE_SHARE_DELETE),
7701 FILE_OPEN, /* create_disposition*/
7702 create_options, /* create_options */
7703 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7704 0, /* oplock_request */
7705 0, /* allocation_size */
7706 0, /* private_flags */
7707 NULL, /* sd */
7708 NULL, /* ea_list */
7709 &fsp, /* result */
7710 &info); /* pinfo */
7712 if (!NT_STATUS_IS_OK(status)) {
7713 return status;
7717 * Don't lie to client. If we can't really delete due to
7718 * non-POSIX opens return SHARING_VIOLATION.
7721 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7722 if (lck == NULL) {
7723 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7724 "lock for file %s\n", fsp_str_dbg(fsp)));
7725 close_file(req, fsp, NORMAL_CLOSE);
7726 return NT_STATUS_INVALID_PARAMETER;
7730 * See if others still have the file open. If this is the case, then
7731 * don't delete. If all opens are POSIX delete we can set the delete
7732 * on close disposition.
7734 for (i=0; i<lck->data->num_share_modes; i++) {
7735 struct share_mode_entry *e = &lck->data->share_modes[i];
7736 if (is_valid_share_mode_entry(e)) {
7737 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7738 continue;
7740 if (share_mode_stale_pid(lck->data, i)) {
7741 continue;
7743 /* Fail with sharing violation. */
7744 TALLOC_FREE(lck);
7745 close_file(req, fsp, NORMAL_CLOSE);
7746 return NT_STATUS_SHARING_VIOLATION;
7751 * Set the delete on close.
7753 status = smb_set_file_disposition_info(conn,
7754 &del,
7756 fsp,
7757 smb_fname);
7759 TALLOC_FREE(lck);
7761 if (!NT_STATUS_IS_OK(status)) {
7762 close_file(req, fsp, NORMAL_CLOSE);
7763 return status;
7765 return close_file(req, fsp, NORMAL_CLOSE);
7768 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7769 struct smb_request *req,
7770 TALLOC_CTX *mem_ctx,
7771 uint16_t info_level,
7772 files_struct *fsp,
7773 struct smb_filename *smb_fname,
7774 char **ppdata, int total_data,
7775 int *ret_data_size)
7777 char *pdata = *ppdata;
7778 NTSTATUS status = NT_STATUS_OK;
7779 int data_return_size = 0;
7781 *ret_data_size = 0;
7783 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7784 return NT_STATUS_INVALID_LEVEL;
7787 if (!CAN_WRITE(conn)) {
7788 /* Allow POSIX opens. The open path will deny
7789 * any non-readonly opens. */
7790 if (info_level != SMB_POSIX_PATH_OPEN) {
7791 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7795 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7796 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7797 fsp_fnum_dbg(fsp),
7798 info_level, total_data));
7800 switch (info_level) {
7802 case SMB_INFO_STANDARD:
7804 status = smb_set_info_standard(conn,
7805 pdata,
7806 total_data,
7807 fsp,
7808 smb_fname);
7809 break;
7812 case SMB_INFO_SET_EA:
7814 status = smb_info_set_ea(conn,
7815 pdata,
7816 total_data,
7817 fsp,
7818 smb_fname);
7819 break;
7822 case SMB_SET_FILE_BASIC_INFO:
7823 case SMB_FILE_BASIC_INFORMATION:
7825 status = smb_set_file_basic_info(conn,
7826 pdata,
7827 total_data,
7828 fsp,
7829 smb_fname);
7830 break;
7833 case SMB_FILE_ALLOCATION_INFORMATION:
7834 case SMB_SET_FILE_ALLOCATION_INFO:
7836 status = smb_set_file_allocation_info(conn, req,
7837 pdata,
7838 total_data,
7839 fsp,
7840 smb_fname);
7841 break;
7844 case SMB_FILE_END_OF_FILE_INFORMATION:
7845 case SMB_SET_FILE_END_OF_FILE_INFO:
7848 * XP/Win7 both fail after the createfile with
7849 * SMB_SET_FILE_END_OF_FILE_INFO but not
7850 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7851 * The level is known here, so pass it down
7852 * appropriately.
7854 bool should_fail =
7855 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7857 status = smb_set_file_end_of_file_info(conn, req,
7858 pdata,
7859 total_data,
7860 fsp,
7861 smb_fname,
7862 should_fail);
7863 break;
7866 case SMB_FILE_DISPOSITION_INFORMATION:
7867 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7869 #if 0
7870 /* JRA - We used to just ignore this on a path ?
7871 * Shouldn't this be invalid level on a pathname
7872 * based call ?
7874 if (tran_call != TRANSACT2_SETFILEINFO) {
7875 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7877 #endif
7878 status = smb_set_file_disposition_info(conn,
7879 pdata,
7880 total_data,
7881 fsp,
7882 smb_fname);
7883 break;
7886 case SMB_FILE_POSITION_INFORMATION:
7888 status = smb_file_position_information(conn,
7889 pdata,
7890 total_data,
7891 fsp);
7892 break;
7895 case SMB_FILE_FULL_EA_INFORMATION:
7897 status = smb_set_file_full_ea_info(conn,
7898 pdata,
7899 total_data,
7900 fsp);
7901 break;
7904 /* From tridge Samba4 :
7905 * MODE_INFORMATION in setfileinfo (I have no
7906 * idea what "mode information" on a file is - it takes a value of 0,
7907 * 2, 4 or 6. What could it be?).
7910 case SMB_FILE_MODE_INFORMATION:
7912 status = smb_file_mode_information(conn,
7913 pdata,
7914 total_data);
7915 break;
7919 * CIFS UNIX extensions.
7922 case SMB_SET_FILE_UNIX_BASIC:
7924 status = smb_set_file_unix_basic(conn, req,
7925 pdata,
7926 total_data,
7927 fsp,
7928 smb_fname);
7929 break;
7932 case SMB_SET_FILE_UNIX_INFO2:
7934 status = smb_set_file_unix_info2(conn, req,
7935 pdata,
7936 total_data,
7937 fsp,
7938 smb_fname);
7939 break;
7942 case SMB_SET_FILE_UNIX_LINK:
7944 if (fsp) {
7945 /* We must have a pathname for this. */
7946 return NT_STATUS_INVALID_LEVEL;
7948 status = smb_set_file_unix_link(conn, req, pdata,
7949 total_data, smb_fname);
7950 break;
7953 case SMB_SET_FILE_UNIX_HLINK:
7955 if (fsp) {
7956 /* We must have a pathname for this. */
7957 return NT_STATUS_INVALID_LEVEL;
7959 status = smb_set_file_unix_hlink(conn, req,
7960 pdata, total_data,
7961 smb_fname);
7962 break;
7965 case SMB_FILE_RENAME_INFORMATION:
7967 status = smb_file_rename_information(conn, req,
7968 pdata, total_data,
7969 fsp, smb_fname);
7970 break;
7973 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7975 /* SMB2 rename information. */
7976 status = smb2_file_rename_information(conn, req,
7977 pdata, total_data,
7978 fsp, smb_fname);
7979 break;
7982 case SMB_FILE_LINK_INFORMATION:
7984 status = smb_file_link_information(conn, req,
7985 pdata, total_data,
7986 fsp, smb_fname);
7987 break;
7990 #if defined(HAVE_POSIX_ACLS)
7991 case SMB_SET_POSIX_ACL:
7993 status = smb_set_posix_acl(conn,
7994 pdata,
7995 total_data,
7996 fsp,
7997 smb_fname);
7998 break;
8000 #endif
8002 case SMB_SET_POSIX_LOCK:
8004 if (!fsp) {
8005 return NT_STATUS_INVALID_LEVEL;
8007 status = smb_set_posix_lock(conn, req,
8008 pdata, total_data, fsp);
8009 break;
8012 case SMB_POSIX_PATH_OPEN:
8014 if (fsp) {
8015 /* We must have a pathname for this. */
8016 return NT_STATUS_INVALID_LEVEL;
8019 status = smb_posix_open(conn, req,
8020 ppdata,
8021 total_data,
8022 smb_fname,
8023 &data_return_size);
8024 break;
8027 case SMB_POSIX_PATH_UNLINK:
8029 if (fsp) {
8030 /* We must have a pathname for this. */
8031 return NT_STATUS_INVALID_LEVEL;
8034 status = smb_posix_unlink(conn, req,
8035 pdata,
8036 total_data,
8037 smb_fname);
8038 break;
8041 default:
8042 return NT_STATUS_INVALID_LEVEL;
8045 if (!NT_STATUS_IS_OK(status)) {
8046 return status;
8049 *ret_data_size = data_return_size;
8050 return NT_STATUS_OK;
8053 /****************************************************************************
8054 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8055 ****************************************************************************/
8057 static void call_trans2setfilepathinfo(connection_struct *conn,
8058 struct smb_request *req,
8059 unsigned int tran_call,
8060 char **pparams, int total_params,
8061 char **ppdata, int total_data,
8062 unsigned int max_data_bytes)
8064 char *params = *pparams;
8065 char *pdata = *ppdata;
8066 uint16 info_level;
8067 struct smb_filename *smb_fname = NULL;
8068 files_struct *fsp = NULL;
8069 NTSTATUS status = NT_STATUS_OK;
8070 int data_return_size = 0;
8072 if (!params) {
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 return;
8077 if (tran_call == TRANSACT2_SETFILEINFO) {
8078 if (total_params < 4) {
8079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8080 return;
8083 fsp = file_fsp(req, SVAL(params,0));
8084 /* Basic check for non-null fsp. */
8085 if (!check_fsp_open(conn, req, fsp)) {
8086 return;
8088 info_level = SVAL(params,2);
8090 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8091 if (smb_fname == NULL) {
8092 reply_nterror(req, NT_STATUS_NO_MEMORY);
8093 return;
8096 if(fsp->fh->fd == -1) {
8098 * This is actually a SETFILEINFO on a directory
8099 * handle (returned from an NT SMB). NT5.0 seems
8100 * to do this call. JRA.
8102 if (INFO_LEVEL_IS_UNIX(info_level)) {
8103 /* Always do lstat for UNIX calls. */
8104 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8105 DEBUG(3,("call_trans2setfilepathinfo: "
8106 "SMB_VFS_LSTAT of %s failed "
8107 "(%s)\n",
8108 smb_fname_str_dbg(smb_fname),
8109 strerror(errno)));
8110 reply_nterror(req, map_nt_error_from_unix(errno));
8111 return;
8113 } else {
8114 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8115 DEBUG(3,("call_trans2setfilepathinfo: "
8116 "fileinfo of %s failed (%s)\n",
8117 smb_fname_str_dbg(smb_fname),
8118 strerror(errno)));
8119 reply_nterror(req, map_nt_error_from_unix(errno));
8120 return;
8123 } else if (fsp->print_file) {
8125 * Doing a DELETE_ON_CLOSE should cancel a print job.
8127 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8128 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8130 DEBUG(3,("call_trans2setfilepathinfo: "
8131 "Cancelling print job (%s)\n",
8132 fsp_str_dbg(fsp)));
8134 SSVAL(params,0,0);
8135 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8136 *ppdata, 0,
8137 max_data_bytes);
8138 return;
8139 } else {
8140 reply_nterror(req,
8141 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8142 return;
8144 } else {
8146 * Original code - this is an open file.
8148 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8149 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8150 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8151 strerror(errno)));
8152 reply_nterror(req, map_nt_error_from_unix(errno));
8153 return;
8156 } else {
8157 char *fname = NULL;
8158 uint32_t ucf_flags = 0;
8160 /* set path info */
8161 if (total_params < 7) {
8162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8163 return;
8166 info_level = SVAL(params,0);
8167 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8168 total_params - 6, STR_TERMINATE,
8169 &status);
8170 if (!NT_STATUS_IS_OK(status)) {
8171 reply_nterror(req, status);
8172 return;
8175 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8176 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8177 info_level == SMB_FILE_RENAME_INFORMATION ||
8178 info_level == SMB_POSIX_PATH_UNLINK) {
8179 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8182 status = filename_convert(req, conn,
8183 req->flags2 & FLAGS2_DFS_PATHNAMES,
8184 fname,
8185 ucf_flags,
8186 NULL,
8187 &smb_fname);
8188 if (!NT_STATUS_IS_OK(status)) {
8189 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8190 reply_botherror(req,
8191 NT_STATUS_PATH_NOT_COVERED,
8192 ERRSRV, ERRbadpath);
8193 return;
8195 reply_nterror(req, status);
8196 return;
8199 if (INFO_LEVEL_IS_UNIX(info_level)) {
8201 * For CIFS UNIX extensions the target name may not exist.
8204 /* Always do lstat for UNIX calls. */
8205 SMB_VFS_LSTAT(conn, smb_fname);
8207 } else if (!VALID_STAT(smb_fname->st) &&
8208 SMB_VFS_STAT(conn, smb_fname)) {
8209 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8210 "%s failed (%s)\n",
8211 smb_fname_str_dbg(smb_fname),
8212 strerror(errno)));
8213 reply_nterror(req, map_nt_error_from_unix(errno));
8214 return;
8218 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8219 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8220 fsp_fnum_dbg(fsp),
8221 info_level,total_data));
8223 /* Realloc the parameter size */
8224 *pparams = (char *)SMB_REALLOC(*pparams,2);
8225 if (*pparams == NULL) {
8226 reply_nterror(req, NT_STATUS_NO_MEMORY);
8227 return;
8229 params = *pparams;
8231 SSVAL(params,0,0);
8233 status = smbd_do_setfilepathinfo(conn, req, req,
8234 info_level,
8235 fsp,
8236 smb_fname,
8237 ppdata, total_data,
8238 &data_return_size);
8239 if (!NT_STATUS_IS_OK(status)) {
8240 if (open_was_deferred(req->sconn, req->mid)) {
8241 /* We have re-scheduled this call. */
8242 return;
8244 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8245 /* We have re-scheduled this call. */
8246 return;
8248 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8249 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8250 ERRSRV, ERRbadpath);
8251 return;
8253 if (info_level == SMB_POSIX_PATH_OPEN) {
8254 reply_openerror(req, status);
8255 return;
8259 * Invalid EA name needs to return 2 param bytes,
8260 * not a zero-length error packet.
8262 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8263 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8264 max_data_bytes);
8265 } else {
8266 reply_nterror(req, status);
8268 return;
8271 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8272 max_data_bytes);
8274 return;
8277 /****************************************************************************
8278 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8279 ****************************************************************************/
8281 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8282 char **pparams, int total_params,
8283 char **ppdata, int total_data,
8284 unsigned int max_data_bytes)
8286 struct smb_filename *smb_dname = NULL;
8287 char *params = *pparams;
8288 char *pdata = *ppdata;
8289 char *directory = NULL;
8290 NTSTATUS status = NT_STATUS_OK;
8291 struct ea_list *ea_list = NULL;
8292 TALLOC_CTX *ctx = talloc_tos();
8294 if (!CAN_WRITE(conn)) {
8295 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8296 return;
8299 if (total_params < 5) {
8300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8301 return;
8304 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8305 total_params - 4, STR_TERMINATE,
8306 &status);
8307 if (!NT_STATUS_IS_OK(status)) {
8308 reply_nterror(req, status);
8309 return;
8312 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8314 status = filename_convert(ctx,
8315 conn,
8316 req->flags2 & FLAGS2_DFS_PATHNAMES,
8317 directory,
8319 NULL,
8320 &smb_dname);
8322 if (!NT_STATUS_IS_OK(status)) {
8323 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8324 reply_botherror(req,
8325 NT_STATUS_PATH_NOT_COVERED,
8326 ERRSRV, ERRbadpath);
8327 return;
8329 reply_nterror(req, status);
8330 return;
8334 * OS/2 workplace shell seems to send SET_EA requests of "null"
8335 * length (4 bytes containing IVAL 4).
8336 * They seem to have no effect. Bug #3212. JRA.
8339 if (total_data && (total_data != 4)) {
8340 /* Any data in this call is an EA list. */
8341 if (total_data < 10) {
8342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8343 goto out;
8346 if (IVAL(pdata,0) > total_data) {
8347 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8348 IVAL(pdata,0), (unsigned int)total_data));
8349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8350 goto out;
8353 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8354 total_data - 4);
8355 if (!ea_list) {
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 goto out;
8360 if (!lp_ea_support(SNUM(conn))) {
8361 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8362 goto out;
8365 /* If total_data == 4 Windows doesn't care what values
8366 * are placed in that field, it just ignores them.
8367 * The System i QNTC IBM SMB client puts bad values here,
8368 * so ignore them. */
8370 status = create_directory(conn, req, smb_dname);
8372 if (!NT_STATUS_IS_OK(status)) {
8373 reply_nterror(req, status);
8374 goto out;
8377 /* Try and set any given EA. */
8378 if (ea_list) {
8379 status = set_ea(conn, NULL, smb_dname, ea_list);
8380 if (!NT_STATUS_IS_OK(status)) {
8381 reply_nterror(req, status);
8382 goto out;
8386 /* Realloc the parameter and data sizes */
8387 *pparams = (char *)SMB_REALLOC(*pparams,2);
8388 if(*pparams == NULL) {
8389 reply_nterror(req, NT_STATUS_NO_MEMORY);
8390 goto out;
8392 params = *pparams;
8394 SSVAL(params,0,0);
8396 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8398 out:
8399 TALLOC_FREE(smb_dname);
8400 return;
8403 /****************************************************************************
8404 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8405 We don't actually do this - we just send a null response.
8406 ****************************************************************************/
8408 static void call_trans2findnotifyfirst(connection_struct *conn,
8409 struct smb_request *req,
8410 char **pparams, int total_params,
8411 char **ppdata, int total_data,
8412 unsigned int max_data_bytes)
8414 char *params = *pparams;
8415 uint16 info_level;
8417 if (total_params < 6) {
8418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8419 return;
8422 info_level = SVAL(params,4);
8423 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8425 switch (info_level) {
8426 case 1:
8427 case 2:
8428 break;
8429 default:
8430 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8431 return;
8434 /* Realloc the parameter and data sizes */
8435 *pparams = (char *)SMB_REALLOC(*pparams,6);
8436 if (*pparams == NULL) {
8437 reply_nterror(req, NT_STATUS_NO_MEMORY);
8438 return;
8440 params = *pparams;
8442 SSVAL(params,0,fnf_handle);
8443 SSVAL(params,2,0); /* No changes */
8444 SSVAL(params,4,0); /* No EA errors */
8446 fnf_handle++;
8448 if(fnf_handle == 0)
8449 fnf_handle = 257;
8451 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8453 return;
8456 /****************************************************************************
8457 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8458 changes). Currently this does nothing.
8459 ****************************************************************************/
8461 static void call_trans2findnotifynext(connection_struct *conn,
8462 struct smb_request *req,
8463 char **pparams, int total_params,
8464 char **ppdata, int total_data,
8465 unsigned int max_data_bytes)
8467 char *params = *pparams;
8469 DEBUG(3,("call_trans2findnotifynext\n"));
8471 /* Realloc the parameter and data sizes */
8472 *pparams = (char *)SMB_REALLOC(*pparams,4);
8473 if (*pparams == NULL) {
8474 reply_nterror(req, NT_STATUS_NO_MEMORY);
8475 return;
8477 params = *pparams;
8479 SSVAL(params,0,0); /* No changes */
8480 SSVAL(params,2,0); /* No EA errors */
8482 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8484 return;
8487 /****************************************************************************
8488 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8489 ****************************************************************************/
8491 static void call_trans2getdfsreferral(connection_struct *conn,
8492 struct smb_request *req,
8493 char **pparams, int total_params,
8494 char **ppdata, int total_data,
8495 unsigned int max_data_bytes)
8497 char *params = *pparams;
8498 char *pathname = NULL;
8499 int reply_size = 0;
8500 int max_referral_level;
8501 NTSTATUS status = NT_STATUS_OK;
8502 TALLOC_CTX *ctx = talloc_tos();
8504 DEBUG(10,("call_trans2getdfsreferral\n"));
8506 if (total_params < 3) {
8507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8508 return;
8511 max_referral_level = SVAL(params,0);
8513 if(!lp_host_msdfs()) {
8514 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8515 return;
8518 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8519 total_params - 2, STR_TERMINATE);
8520 if (!pathname) {
8521 reply_nterror(req, NT_STATUS_NOT_FOUND);
8522 return;
8524 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8525 ppdata,&status)) < 0) {
8526 reply_nterror(req, status);
8527 return;
8530 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8531 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8532 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8534 return;
8537 #define LMCAT_SPL 0x53
8538 #define LMFUNC_GETJOBID 0x60
8540 /****************************************************************************
8541 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8542 ****************************************************************************/
8544 static void call_trans2ioctl(connection_struct *conn,
8545 struct smb_request *req,
8546 char **pparams, int total_params,
8547 char **ppdata, int total_data,
8548 unsigned int max_data_bytes)
8550 char *pdata = *ppdata;
8551 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8553 /* check for an invalid fid before proceeding */
8555 if (!fsp) {
8556 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8557 return;
8560 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8561 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8562 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8563 if (*ppdata == NULL) {
8564 reply_nterror(req, NT_STATUS_NO_MEMORY);
8565 return;
8567 pdata = *ppdata;
8569 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8570 CAN ACCEPT THIS IN UNICODE. JRA. */
8572 /* Job number */
8573 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8575 srvstr_push(pdata, req->flags2, pdata + 2,
8576 lp_netbios_name(), 15,
8577 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8578 srvstr_push(pdata, req->flags2, pdata+18,
8579 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8580 STR_ASCII|STR_TERMINATE); /* Service name */
8581 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8582 max_data_bytes);
8583 return;
8586 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8587 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8590 /****************************************************************************
8591 Reply to a SMBfindclose (stop trans2 directory search).
8592 ****************************************************************************/
8594 void reply_findclose(struct smb_request *req)
8596 int dptr_num;
8597 struct smbd_server_connection *sconn = req->sconn;
8599 START_PROFILE(SMBfindclose);
8601 if (req->wct < 1) {
8602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8603 END_PROFILE(SMBfindclose);
8604 return;
8607 dptr_num = SVALS(req->vwv+0, 0);
8609 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8611 dptr_close(sconn, &dptr_num);
8613 reply_outbuf(req, 0, 0);
8615 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8617 END_PROFILE(SMBfindclose);
8618 return;
8621 /****************************************************************************
8622 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8623 ****************************************************************************/
8625 void reply_findnclose(struct smb_request *req)
8627 int dptr_num;
8629 START_PROFILE(SMBfindnclose);
8631 if (req->wct < 1) {
8632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8633 END_PROFILE(SMBfindnclose);
8634 return;
8637 dptr_num = SVAL(req->vwv+0, 0);
8639 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8641 /* We never give out valid handles for a
8642 findnotifyfirst - so any dptr_num is ok here.
8643 Just ignore it. */
8645 reply_outbuf(req, 0, 0);
8647 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8649 END_PROFILE(SMBfindnclose);
8650 return;
8653 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8654 struct trans_state *state)
8656 if (get_Protocol() >= PROTOCOL_NT1) {
8657 req->flags2 |= 0x40; /* IS_LONG_NAME */
8658 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8661 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8662 if (state->call != TRANSACT2_QFSINFO &&
8663 state->call != TRANSACT2_SETFSINFO) {
8664 DEBUG(0,("handle_trans2: encryption required "
8665 "with call 0x%x\n",
8666 (unsigned int)state->call));
8667 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8668 return;
8672 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8674 /* Now we must call the relevant TRANS2 function */
8675 switch(state->call) {
8676 case TRANSACT2_OPEN:
8678 START_PROFILE(Trans2_open);
8679 call_trans2open(conn, req,
8680 &state->param, state->total_param,
8681 &state->data, state->total_data,
8682 state->max_data_return);
8683 END_PROFILE(Trans2_open);
8684 break;
8687 case TRANSACT2_FINDFIRST:
8689 START_PROFILE(Trans2_findfirst);
8690 call_trans2findfirst(conn, req,
8691 &state->param, state->total_param,
8692 &state->data, state->total_data,
8693 state->max_data_return);
8694 END_PROFILE(Trans2_findfirst);
8695 break;
8698 case TRANSACT2_FINDNEXT:
8700 START_PROFILE(Trans2_findnext);
8701 call_trans2findnext(conn, req,
8702 &state->param, state->total_param,
8703 &state->data, state->total_data,
8704 state->max_data_return);
8705 END_PROFILE(Trans2_findnext);
8706 break;
8709 case TRANSACT2_QFSINFO:
8711 START_PROFILE(Trans2_qfsinfo);
8712 call_trans2qfsinfo(conn, req,
8713 &state->param, state->total_param,
8714 &state->data, state->total_data,
8715 state->max_data_return);
8716 END_PROFILE(Trans2_qfsinfo);
8717 break;
8720 case TRANSACT2_SETFSINFO:
8722 START_PROFILE(Trans2_setfsinfo);
8723 call_trans2setfsinfo(conn, req,
8724 &state->param, state->total_param,
8725 &state->data, state->total_data,
8726 state->max_data_return);
8727 END_PROFILE(Trans2_setfsinfo);
8728 break;
8731 case TRANSACT2_QPATHINFO:
8732 case TRANSACT2_QFILEINFO:
8734 START_PROFILE(Trans2_qpathinfo);
8735 call_trans2qfilepathinfo(conn, req, state->call,
8736 &state->param, state->total_param,
8737 &state->data, state->total_data,
8738 state->max_data_return);
8739 END_PROFILE(Trans2_qpathinfo);
8740 break;
8743 case TRANSACT2_SETPATHINFO:
8744 case TRANSACT2_SETFILEINFO:
8746 START_PROFILE(Trans2_setpathinfo);
8747 call_trans2setfilepathinfo(conn, req, state->call,
8748 &state->param, state->total_param,
8749 &state->data, state->total_data,
8750 state->max_data_return);
8751 END_PROFILE(Trans2_setpathinfo);
8752 break;
8755 case TRANSACT2_FINDNOTIFYFIRST:
8757 START_PROFILE(Trans2_findnotifyfirst);
8758 call_trans2findnotifyfirst(conn, req,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_findnotifyfirst);
8763 break;
8766 case TRANSACT2_FINDNOTIFYNEXT:
8768 START_PROFILE(Trans2_findnotifynext);
8769 call_trans2findnotifynext(conn, req,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_findnotifynext);
8774 break;
8777 case TRANSACT2_MKDIR:
8779 START_PROFILE(Trans2_mkdir);
8780 call_trans2mkdir(conn, req,
8781 &state->param, state->total_param,
8782 &state->data, state->total_data,
8783 state->max_data_return);
8784 END_PROFILE(Trans2_mkdir);
8785 break;
8788 case TRANSACT2_GET_DFS_REFERRAL:
8790 START_PROFILE(Trans2_get_dfs_referral);
8791 call_trans2getdfsreferral(conn, req,
8792 &state->param, state->total_param,
8793 &state->data, state->total_data,
8794 state->max_data_return);
8795 END_PROFILE(Trans2_get_dfs_referral);
8796 break;
8799 case TRANSACT2_IOCTL:
8801 START_PROFILE(Trans2_ioctl);
8802 call_trans2ioctl(conn, req,
8803 &state->param, state->total_param,
8804 &state->data, state->total_data,
8805 state->max_data_return);
8806 END_PROFILE(Trans2_ioctl);
8807 break;
8810 default:
8811 /* Error in request */
8812 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8813 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8817 /****************************************************************************
8818 Reply to a SMBtrans2.
8819 ****************************************************************************/
8821 void reply_trans2(struct smb_request *req)
8823 connection_struct *conn = req->conn;
8824 unsigned int dsoff;
8825 unsigned int dscnt;
8826 unsigned int psoff;
8827 unsigned int pscnt;
8828 unsigned int tran_call;
8829 struct trans_state *state;
8830 NTSTATUS result;
8832 START_PROFILE(SMBtrans2);
8834 if (req->wct < 14) {
8835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8836 END_PROFILE(SMBtrans2);
8837 return;
8840 dsoff = SVAL(req->vwv+12, 0);
8841 dscnt = SVAL(req->vwv+11, 0);
8842 psoff = SVAL(req->vwv+10, 0);
8843 pscnt = SVAL(req->vwv+9, 0);
8844 tran_call = SVAL(req->vwv+14, 0);
8846 result = allow_new_trans(conn->pending_trans, req->mid);
8847 if (!NT_STATUS_IS_OK(result)) {
8848 DEBUG(2, ("Got invalid trans2 request: %s\n",
8849 nt_errstr(result)));
8850 reply_nterror(req, result);
8851 END_PROFILE(SMBtrans2);
8852 return;
8855 if (IS_IPC(conn)) {
8856 switch (tran_call) {
8857 /* List the allowed trans2 calls on IPC$ */
8858 case TRANSACT2_OPEN:
8859 case TRANSACT2_GET_DFS_REFERRAL:
8860 case TRANSACT2_QFILEINFO:
8861 case TRANSACT2_QFSINFO:
8862 case TRANSACT2_SETFSINFO:
8863 break;
8864 default:
8865 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8866 END_PROFILE(SMBtrans2);
8867 return;
8871 if ((state = talloc(conn, struct trans_state)) == NULL) {
8872 DEBUG(0, ("talloc failed\n"));
8873 reply_nterror(req, NT_STATUS_NO_MEMORY);
8874 END_PROFILE(SMBtrans2);
8875 return;
8878 state->cmd = SMBtrans2;
8880 state->mid = req->mid;
8881 state->vuid = req->vuid;
8882 state->setup_count = SVAL(req->vwv+13, 0);
8883 state->setup = NULL;
8884 state->total_param = SVAL(req->vwv+0, 0);
8885 state->param = NULL;
8886 state->total_data = SVAL(req->vwv+1, 0);
8887 state->data = NULL;
8888 state->max_param_return = SVAL(req->vwv+2, 0);
8889 state->max_data_return = SVAL(req->vwv+3, 0);
8890 state->max_setup_return = SVAL(req->vwv+4, 0);
8891 state->close_on_completion = BITSETW(req->vwv+5, 0);
8892 state->one_way = BITSETW(req->vwv+5, 1);
8894 state->call = tran_call;
8896 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8897 is so as a sanity check */
8898 if (state->setup_count != 1) {
8900 * Need to have rc=0 for ioctl to get job id for OS/2.
8901 * Network printing will fail if function is not successful.
8902 * Similar function in reply.c will be used if protocol
8903 * is LANMAN1.0 instead of LM1.2X002.
8904 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8905 * outbuf doesn't have to be set(only job id is used).
8907 if ( (state->setup_count == 4)
8908 && (tran_call == TRANSACT2_IOCTL)
8909 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8910 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8911 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8912 } else {
8913 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8914 DEBUG(2,("Transaction is %d\n",tran_call));
8915 TALLOC_FREE(state);
8916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8917 END_PROFILE(SMBtrans2);
8918 return;
8922 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8923 goto bad_param;
8925 if (state->total_data) {
8927 if (trans_oob(state->total_data, 0, dscnt)
8928 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8929 goto bad_param;
8932 /* Can't use talloc here, the core routines do realloc on the
8933 * params and data. */
8934 state->data = (char *)SMB_MALLOC(state->total_data);
8935 if (state->data == NULL) {
8936 DEBUG(0,("reply_trans2: data malloc fail for %u "
8937 "bytes !\n", (unsigned int)state->total_data));
8938 TALLOC_FREE(state);
8939 reply_nterror(req, NT_STATUS_NO_MEMORY);
8940 END_PROFILE(SMBtrans2);
8941 return;
8944 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8947 if (state->total_param) {
8949 if (trans_oob(state->total_param, 0, pscnt)
8950 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8951 goto bad_param;
8954 /* Can't use talloc here, the core routines do realloc on the
8955 * params and data. */
8956 state->param = (char *)SMB_MALLOC(state->total_param);
8957 if (state->param == NULL) {
8958 DEBUG(0,("reply_trans: param malloc fail for %u "
8959 "bytes !\n", (unsigned int)state->total_param));
8960 SAFE_FREE(state->data);
8961 TALLOC_FREE(state);
8962 reply_nterror(req, NT_STATUS_NO_MEMORY);
8963 END_PROFILE(SMBtrans2);
8964 return;
8967 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8970 state->received_data = dscnt;
8971 state->received_param = pscnt;
8973 if ((state->received_param == state->total_param) &&
8974 (state->received_data == state->total_data)) {
8976 handle_trans2(conn, req, state);
8978 SAFE_FREE(state->data);
8979 SAFE_FREE(state->param);
8980 TALLOC_FREE(state);
8981 END_PROFILE(SMBtrans2);
8982 return;
8985 DLIST_ADD(conn->pending_trans, state);
8987 /* We need to send an interim response then receive the rest
8988 of the parameter/data bytes */
8989 reply_outbuf(req, 0, 0);
8990 show_msg((char *)req->outbuf);
8991 END_PROFILE(SMBtrans2);
8992 return;
8994 bad_param:
8996 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8997 SAFE_FREE(state->data);
8998 SAFE_FREE(state->param);
8999 TALLOC_FREE(state);
9000 END_PROFILE(SMBtrans2);
9001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9005 /****************************************************************************
9006 Reply to a SMBtranss2
9007 ****************************************************************************/
9009 void reply_transs2(struct smb_request *req)
9011 connection_struct *conn = req->conn;
9012 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9013 struct trans_state *state;
9015 START_PROFILE(SMBtranss2);
9017 show_msg((const char *)req->inbuf);
9019 /* Windows clients expect all replies to
9020 a transact secondary (SMBtranss2 0x33)
9021 to have a command code of transact
9022 (SMBtrans2 0x32). See bug #8989
9023 and also [MS-CIFS] section 2.2.4.47.2
9024 for details.
9026 req->cmd = SMBtrans2;
9028 if (req->wct < 8) {
9029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9030 END_PROFILE(SMBtranss2);
9031 return;
9034 for (state = conn->pending_trans; state != NULL;
9035 state = state->next) {
9036 if (state->mid == req->mid) {
9037 break;
9041 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9043 END_PROFILE(SMBtranss2);
9044 return;
9047 /* Revise state->total_param and state->total_data in case they have
9048 changed downwards */
9050 if (SVAL(req->vwv+0, 0) < state->total_param)
9051 state->total_param = SVAL(req->vwv+0, 0);
9052 if (SVAL(req->vwv+1, 0) < state->total_data)
9053 state->total_data = SVAL(req->vwv+1, 0);
9055 pcnt = SVAL(req->vwv+2, 0);
9056 poff = SVAL(req->vwv+3, 0);
9057 pdisp = SVAL(req->vwv+4, 0);
9059 dcnt = SVAL(req->vwv+5, 0);
9060 doff = SVAL(req->vwv+6, 0);
9061 ddisp = SVAL(req->vwv+7, 0);
9063 state->received_param += pcnt;
9064 state->received_data += dcnt;
9066 if ((state->received_data > state->total_data) ||
9067 (state->received_param > state->total_param))
9068 goto bad_param;
9070 if (pcnt) {
9071 if (trans_oob(state->total_param, pdisp, pcnt)
9072 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9073 goto bad_param;
9075 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9078 if (dcnt) {
9079 if (trans_oob(state->total_data, ddisp, dcnt)
9080 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9081 goto bad_param;
9083 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9086 if ((state->received_param < state->total_param) ||
9087 (state->received_data < state->total_data)) {
9088 END_PROFILE(SMBtranss2);
9089 return;
9092 handle_trans2(conn, req, state);
9094 DLIST_REMOVE(conn->pending_trans, state);
9095 SAFE_FREE(state->data);
9096 SAFE_FREE(state->param);
9097 TALLOC_FREE(state);
9099 END_PROFILE(SMBtranss2);
9100 return;
9102 bad_param:
9104 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9105 DLIST_REMOVE(conn->pending_trans, state);
9106 SAFE_FREE(state->data);
9107 SAFE_FREE(state->param);
9108 TALLOC_FREE(state);
9109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9110 END_PROFILE(SMBtranss2);
9111 return;