s3:smbd: allow info class SMB_QUERY_FS_ATTRIBUTE_INFO to return partial data
[Samba.git] / source3 / smbd / trans2.c
blob63318ac56f3d29321363039388f0d2781c276d2c
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
882 uint8_t eclass;
883 uint32_t ecode;
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
887 __LINE__,__FILE__);
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
891 (char *)req->outbuf,
892 true, req->seqnum+1,
893 IS_CONN_ENCRYPTED(conn),
894 &req->pcd)) {
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
898 return;
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
913 + 2 * 10 /* wct */
914 + alignment_offset
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
966 else
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
974 } else {
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1014 if (overflow) {
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1018 __LINE__,__FILE__);
1019 } else if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1034 &req->pcd))
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1045 /* Sanity check */
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1049 return;
1053 return;
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1069 int deny_mode;
1070 int32 open_attr;
1071 bool oplock_request;
1072 #if 0
1073 bool return_additional_info;
1074 int16 open_sattr;
1075 time_t open_time;
1076 #endif
1077 int open_ofun;
1078 uint32 open_size;
1079 char *pname;
1080 char *fname = NULL;
1081 off_t size=0;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1084 int smb_action = 0;
1085 files_struct *fsp;
1086 struct ea_list *ea_list = NULL;
1087 uint16 flags = 0;
1088 NTSTATUS status;
1089 uint32 access_mask;
1090 uint32 share_mode;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 goto out;
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1113 #if 0
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1117 #endif
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = &params[28];
1122 if (IS_IPC(conn)) {
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1124 goto out;
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1129 &status);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1132 goto out;
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1159 goto out;
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1163 open_ofun,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1166 &create_options,
1167 &private_flags)) {
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1169 goto out;
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 goto out;
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 goto out;
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1187 total_data - 4);
1188 if (!ea_list) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1195 goto out;
1198 if (ea_list_has_invalid_name(ea_list)) {
1199 int param_len = 30;
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1203 goto out;
1205 params = *pparams;
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1209 goto out;
1213 status = SMB_VFS_CREATE_FILE(
1214 conn, /* conn */
1215 req, /* req */
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1225 private_flags,
1226 NULL, /* sd */
1227 ea_list, /* ea_list */
1228 &fsp, /* result */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1234 goto out;
1236 reply_openerror(req, status);
1237 goto out;
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 goto out;
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1254 goto out;
1256 params = *pparams;
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1277 if (flags & 8) {
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1279 smb_fname);
1280 SIVAL(params, 26, ea_size);
1281 } else {
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1287 out:
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1300 const char *str,
1301 const char *mask)
1303 if (mask[0] == '.' && mask[1] == 0) {
1304 return false;
1307 if (has_wild) {
1308 return false;
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1313 } else {
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1324 if(S_ISREG(mode))
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1328 #ifdef S_ISLNK
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1331 #endif
1332 #ifdef S_ISCHR
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1335 #endif
1336 #ifdef S_ISBLK
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1339 #endif
1340 #ifdef S_ISFIFO
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1343 #endif
1344 #ifdef S_ISSOCK
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1347 #endif
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1361 uint32 perms,
1362 enum perm_type ptype,
1363 mode_t *ret_perms)
1365 mode_t ret = 0;
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1370 } else {
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1385 #ifdef S_ISVTX
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1387 #endif
1388 #ifdef S_ISGID
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1390 #endif
1391 #ifdef S_ISUID
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1393 #endif
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1413 *ret_perms = ret;
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 "as a directory\n",
1433 pathname));
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1436 return true;
1438 errno = saved_errno;
1439 return false;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1451 bool has_wild;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1456 void *private_data,
1457 const char *dname,
1458 const char *mask,
1459 char **_fname)
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1463 bool ok;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1465 bool got_match;
1466 const char *fname;
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1472 if (!ok) {
1473 return false;
1475 fname = mangled_name;
1476 } else {
1477 fname = dname;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1482 fname, mask);
1483 state->got_exact_match = got_match;
1484 if (!got_match) {
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1500 if (!ok) {
1501 return false;
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1508 if (!got_match) {
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1514 if (!got_match) {
1515 return false;
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1520 return false;
1523 return true;
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1527 void *private_data,
1528 struct smb_filename *smb_fname,
1529 uint32_t *_mode)
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1534 uint32_t mode = 0;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1541 strerror(errno)));
1542 return false;
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1547 * directories */
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1551 &smb_fname->st);
1552 if (!ms_dfs_link) {
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1556 strerror(errno)));
1557 return false;
1561 if (ms_dfs_link) {
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1563 } else {
1564 mode = dos_mode(state->conn, smb_fname);
1567 *_mode = mode;
1568 return true;
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1573 uint16_t flags2,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1578 uint32_t mode,
1579 const char *fname,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1582 uint8_t align,
1583 bool do_pad,
1584 char *base_data,
1585 char **ppdata,
1586 char *end_data,
1587 bool *out_of_space,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1591 uint32_t reskey=0;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1595 uint32_t len;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1598 char *nameptr;
1599 char *last_entry_ptr;
1600 bool was_8_3;
1601 int off;
1602 int pad = 0;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1639 pad -= off;
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1645 (unsigned int)pad,
1646 space_remaining ));
1647 return false; /* Not finished - just out of space */
1650 off += pad;
1651 /* initialize padding to 0 */
1652 if (pad) {
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1658 space_remaining ));
1660 pdata += pad;
1661 p = pdata;
1662 last_entry_ptr = p;
1664 pad = 0;
1665 off = 0;
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 23;
1681 nameptr = p;
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE);
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1689 if (len > 2) {
1690 SCVAL(nameptr, -1, len - 2);
1691 } else {
1692 SCVAL(nameptr, -1, 0);
1694 } else {
1695 if (len > 1) {
1696 SCVAL(nameptr, -1, len - 1);
1697 } else {
1698 SCVAL(nameptr, -1, 0);
1701 p += len;
1702 break;
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key) {
1707 SIVAL(p,0,reskey);
1708 p += 4;
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1715 SSVAL(p,20,mode);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1718 smb_fname);
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1721 p += 27;
1722 nameptr = p - 1;
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1747 size_t ea_len = 0;
1748 NTSTATUS status;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1751 if (!name_list) {
1752 return false;
1754 if (requires_resume_key) {
1755 SIVAL(p,0,reskey);
1756 p += 4;
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1763 SSVAL(p,20,mode);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1767 smb_fname,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 file_list = NULL;
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1781 space_remaining ));
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1787 nameptr = p;
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1792 if (len > 2) {
1793 len -= 2;
1794 } else {
1795 len = 0;
1797 } else {
1798 if (len > 1) {
1799 len -= 1;
1800 } else {
1801 len = 0;
1804 SCVAL(nameptr,0,len);
1805 p += len + 1;
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1807 break;
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1813 p += 4;
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1825 } else {
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1830 p += 4;
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1838 conn->params)) {
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1846 if (len < 24) {
1847 memset(p + 2 + len,'\0',24 - len);
1849 SSVAL(p, 0, len);
1850 } else {
1851 memset(p,'\0',26);
1853 p += 2 + 24;
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1857 SIVAL(q,0,len);
1858 p += len;
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1867 SIVAL(pdata,0,pad);
1869 * set padding to zero
1871 if (do_pad) {
1872 memset(p, 0, pad - len);
1873 p = pdata + pad;
1874 } else {
1875 p = pdata + len;
1877 break;
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1881 p += 4;
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1893 SIVAL(p,0,len);
1894 p += 4 + len;
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1903 SIVAL(pdata,0,pad);
1905 * set padding to zero
1907 if (do_pad) {
1908 memset(p, 0, pad - len);
1909 p = pdata + pad;
1910 } else {
1911 p = pdata + len;
1913 break;
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1936 SIVAL(q, 0, len);
1937 p += len;
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1946 SIVAL(pdata,0,pad);
1948 * set padding to zero
1950 if (do_pad) {
1951 memset(p, 0, pad - len);
1952 p = pdata + pad;
1953 } else {
1954 p = pdata + len;
1956 break;
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1960 p += 4;
1961 SIVAL(p,0,reskey); p += 4;
1962 p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1968 SIVAL(p, -4, len);
1969 p += len;
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1978 SIVAL(pdata,0,pad);
1980 * set padding to zero
1982 if (do_pad) {
1983 memset(p, 0, pad - len);
1984 p = pdata + pad;
1985 } else {
1986 p = pdata + len;
1988 break;
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1992 p += 4;
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2004 } else {
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2006 smb_fname);
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2009 p += 4;
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2015 SIVAL(q, 0, len);
2016 p += len;
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2025 SIVAL(pdata,0,pad);
2027 * set padding to zero
2029 if (do_pad) {
2030 memset(p, 0, pad - len);
2031 p = pdata + pad;
2032 } else {
2033 p = pdata + len;
2035 break;
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2040 p += 4;
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2052 } else {
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2054 smb_fname);
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2057 p += 4;
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2065 conn->params)) {
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2073 SSVAL(p, 0, len);
2074 if (len < 24) {
2075 memset(p + 2 + len,'\0',24 - len);
2077 SSVAL(p, 0, len);
2078 } else {
2079 memset(p,'\0',26);
2081 p += 26;
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
2087 SIVAL(q,0,len);
2088 p += len;
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2097 SIVAL(pdata,0,pad);
2099 * set padding to zero
2101 if (do_pad) {
2102 memset(p, 0, pad - len);
2103 p = pdata + pad;
2104 } else {
2105 p = pdata + len;
2107 break;
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2113 p+= 4;
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2124 STR_TERMINATE);
2125 } else {
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2129 nameptr = p;
2130 p += 4;
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2136 p += len;
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2145 SIVAL(pdata,0,pad);
2147 * set padding to zero
2149 if (do_pad) {
2150 memset(p, 0, pad - len);
2151 p = pdata + pad;
2152 } else {
2153 p = pdata + len;
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2157 break;
2159 default:
2160 return false;
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2168 space_remaining ));
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2175 *ppdata = p;
2177 return true;
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 int requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 uint8_t align,
2191 bool do_pad,
2192 char **ppdata,
2193 char *base_data,
2194 char *end_data,
2195 int space_remaining,
2196 bool *out_of_space,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2201 const char *p;
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2204 uint32_t mode = 0;
2205 char *fname = NULL;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2208 bool ok;
2209 uint64_t last_entry_off = 0;
2211 ZERO_STRUCT(state);
2212 state.conn = conn;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2222 if(p != NULL) {
2223 if(p[1] == '\0') {
2224 mask = "*.*";
2225 } else {
2226 mask = p+1;
2228 } else {
2229 mask = path_mask;
2232 ok = smbd_dirptr_get_entry(ctx,
2233 dirptr,
2234 mask,
2235 dirtype,
2236 dont_descend,
2237 ask_sharemode,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2240 &state,
2241 &fname,
2242 &smb_fname,
2243 &mode,
2244 &prev_dirpos);
2245 if (!ok) {
2246 return false;
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2252 conn,
2253 flags2,
2254 info_level,
2255 name_list,
2256 state.check_mangled_names,
2257 requires_resume_key,
2258 mode,
2259 fname,
2260 smb_fname,
2261 space_remaining,
2262 align,
2263 do_pad,
2264 base_data,
2265 ppdata,
2266 end_data,
2267 out_of_space,
2268 &last_entry_off);
2269 TALLOC_FREE(fname);
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2273 return false;
2275 if (!ok) {
2276 return false;
2279 *_last_entry_off = last_entry_off;
2280 return true;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2286 uint16 flags2,
2287 const char *path_mask,
2288 uint32 dirtype,
2289 int info_level,
2290 bool requires_resume_key,
2291 bool dont_descend,
2292 bool ask_sharemode,
2293 char **ppdata,
2294 char *base_data,
2295 char *end_data,
2296 int space_remaining,
2297 bool *out_of_space,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2302 uint8_t align = 4;
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2307 align = 1;
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2313 align, do_pad,
2314 ppdata, base_data, end_data,
2315 space_remaining,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2334 requested. */
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2338 char *data_end;
2339 uint32 dirtype;
2340 int maxentries;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2343 bool close_if_end;
2344 bool requires_resume_key;
2345 int info_level;
2346 char *directory = NULL;
2347 char *mask = NULL;
2348 char *p;
2349 int last_entry_off=0;
2350 int dptr_num = -1;
2351 int numentries = 0;
2352 int i;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2367 if (total_params < 13) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2372 dirtype = SVAL(params,0);
2373 maxentries = SVAL(params,2);
2374 findfirst_flags = SVAL(params,4);
2375 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2376 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2377 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2378 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2379 security_token_has_privilege(get_current_nttok(conn),
2380 SEC_PRIV_BACKUP));
2382 info_level = SVAL(params,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2387 (int)backup_priv,
2388 info_level, max_data_bytes));
2390 if (!maxentries) {
2391 /* W2K3 seems to treat zero as 1. */
2392 maxentries = 1;
2395 switch (info_level) {
2396 case SMB_FIND_INFO_STANDARD:
2397 case SMB_FIND_EA_SIZE:
2398 case SMB_FIND_EA_LIST:
2399 case SMB_FIND_FILE_DIRECTORY_INFO:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_NAMES_INFO:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2405 break;
2406 case SMB_FIND_FILE_UNIX:
2407 case SMB_FIND_FILE_UNIX_INFO2:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode = false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 goto out;
2414 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 break;
2416 default:
2417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2418 goto out;
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2422 params+12, total_params - 12,
2423 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2424 if (!NT_STATUS_IS_OK(ntstatus)) {
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 if (backup_priv) {
2430 become_root();
2431 ntstatus = filename_convert_with_privilege(ctx,
2432 conn,
2433 req,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2438 } else {
2439 ntstatus = filename_convert(ctx, conn,
2440 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 directory,
2442 ucf_flags,
2443 &mask_contains_wcard,
2444 &smb_dname);
2447 if (!NT_STATUS_IS_OK(ntstatus)) {
2448 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2450 ERRSRV, ERRbadpath);
2451 goto out;
2453 reply_nterror(req, ntstatus);
2454 goto out;
2457 mask = smb_dname->original_lcomp;
2459 directory = smb_dname->base_name;
2461 p = strrchr_m(directory,'/');
2462 if(p == NULL) {
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory[0] == '.') && (directory[1] == '\0')) {
2465 mask = talloc_strdup(ctx,"*");
2466 if (!mask) {
2467 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 goto out;
2470 mask_contains_wcard = True;
2472 } else {
2473 *p = 0;
2476 if (p == NULL || p == directory) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory = talloc_strdup(talloc_tos(), ".");
2479 if (!directory) {
2480 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 goto out;
2485 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2487 if (info_level == SMB_FIND_EA_LIST) {
2488 uint32 ea_size;
2490 if (total_data < 4) {
2491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2492 goto out;
2495 ea_size = IVAL(pdata,0);
2496 if (ea_size != total_data) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 goto out;
2503 if (!lp_ea_support(SNUM(conn))) {
2504 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2505 goto out;
2508 /* Pull out the list of names. */
2509 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2510 if (!ea_list) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2516 *ppdata = (char *)SMB_REALLOC(
2517 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2518 if(*ppdata == NULL ) {
2519 reply_nterror(req, NT_STATUS_NO_MEMORY);
2520 goto out;
2522 pdata = *ppdata;
2523 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2525 /* Realloc the params space */
2526 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2527 if (*pparams == NULL) {
2528 reply_nterror(req, NT_STATUS_NO_MEMORY);
2529 goto out;
2531 params = *pparams;
2533 /* Save the wildcard match and attribs we are using on this directory -
2534 needed as lanman2 assumes these are being saved between calls */
2536 ntstatus = dptr_create(conn,
2537 req,
2538 NULL, /* fsp */
2539 directory,
2540 False,
2541 True,
2542 req->smbpid,
2543 mask,
2544 mask_contains_wcard,
2545 dirtype,
2546 &dirptr);
2548 if (!NT_STATUS_IS_OK(ntstatus)) {
2549 reply_nterror(req, ntstatus);
2550 goto out;
2553 if (backup_priv) {
2554 /* Remember this in case we have
2555 to do a findnext. */
2556 dptr_set_priv(dirptr);
2559 dptr_num = dptr_dnum(dirptr);
2560 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2562 /* Initialize per TRANS2_FIND_FIRST operation data */
2563 dptr_init_search_op(dirptr);
2565 /* We don't need to check for VOL here as this is returned by
2566 a different TRANS2 call. */
2568 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2569 directory,lp_dontdescend(ctx, SNUM(conn))));
2570 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2571 dont_descend = True;
2573 p = pdata;
2574 space_remaining = max_data_bytes;
2575 out_of_space = False;
2577 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2578 bool got_exact_match = False;
2580 /* this is a heuristic to avoid seeking the dirptr except when
2581 absolutely necessary. It allows for a filename of about 40 chars */
2582 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2583 out_of_space = True;
2584 finished = False;
2585 } else {
2586 finished = !get_lanman2_dir_entry(ctx,
2587 conn,
2588 dirptr,
2589 req->flags2,
2590 mask,dirtype,info_level,
2591 requires_resume_key,dont_descend,
2592 ask_sharemode,
2593 &p,pdata,data_end,
2594 space_remaining, &out_of_space,
2595 &got_exact_match,
2596 &last_entry_off, ea_list);
2599 if (finished && out_of_space)
2600 finished = False;
2602 if (!finished && !out_of_space)
2603 numentries++;
2606 * As an optimisation if we know we aren't looking
2607 * for a wildcard name (ie. the name matches the wildcard exactly)
2608 * then we can finish on any (first) match.
2609 * This speeds up large directory searches. JRA.
2612 if(got_exact_match)
2613 finished = True;
2615 /* Ensure space_remaining never goes -ve. */
2616 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2617 space_remaining = 0;
2618 out_of_space = true;
2619 } else {
2620 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2624 /* Check if we can close the dirptr */
2625 if(close_after_first || (finished && close_if_end)) {
2626 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2627 dptr_close(sconn, &dptr_num);
2631 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2632 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2633 * the protocol level is less than NT1. Tested with smbclient. JRA.
2634 * This should fix the OS/2 client bug #2335.
2637 if(numentries == 0) {
2638 dptr_close(sconn, &dptr_num);
2639 if (get_Protocol() < PROTOCOL_NT1) {
2640 reply_force_doserror(req, ERRDOS, ERRnofiles);
2641 goto out;
2642 } else {
2643 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2644 ERRDOS, ERRbadfile);
2645 goto out;
2649 /* At this point pdata points to numentries directory entries. */
2651 /* Set up the return parameter block */
2652 SSVAL(params,0,dptr_num);
2653 SSVAL(params,2,numentries);
2654 SSVAL(params,4,finished);
2655 SSVAL(params,6,0); /* Never an EA error */
2656 SSVAL(params,8,last_entry_off);
2658 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2659 max_data_bytes);
2661 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2662 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2663 if (!directory) {
2664 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2669 smb_fn_name(req->cmd),
2670 mask, directory, dirtype, numentries ) );
2673 * Force a name mangle here to ensure that the
2674 * mask as an 8.3 name is top of the mangled cache.
2675 * The reasons for this are subtle. Don't remove
2676 * this code unless you know what you are doing
2677 * (see PR#13758). JRA.
2680 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2681 char mangled_name[13];
2682 name_to_8_3(mask, mangled_name, True, conn->params);
2684 out:
2686 if (backup_priv) {
2687 unbecome_root();
2690 TALLOC_FREE(smb_dname);
2691 return;
2694 /****************************************************************************
2695 Reply to a TRANS2_FINDNEXT.
2696 ****************************************************************************/
2698 static void call_trans2findnext(connection_struct *conn,
2699 struct smb_request *req,
2700 char **pparams, int total_params,
2701 char **ppdata, int total_data,
2702 unsigned int max_data_bytes)
2704 /* We must be careful here that we don't return more than the
2705 allowed number of data bytes. If this means returning fewer than
2706 maxentries then so be it. We assume that the redirector has
2707 enough room for the fixed number of parameter bytes it has
2708 requested. */
2709 char *params = *pparams;
2710 char *pdata = *ppdata;
2711 char *data_end;
2712 int dptr_num;
2713 int maxentries;
2714 uint16 info_level;
2715 uint32 resume_key;
2716 uint16 findnext_flags;
2717 bool close_after_request;
2718 bool close_if_end;
2719 bool requires_resume_key;
2720 bool continue_bit;
2721 bool mask_contains_wcard = False;
2722 char *resume_name = NULL;
2723 const char *mask = NULL;
2724 const char *directory = NULL;
2725 char *p = NULL;
2726 uint16 dirtype;
2727 int numentries = 0;
2728 int i, last_entry_off=0;
2729 bool finished = False;
2730 bool dont_descend = False;
2731 bool out_of_space = False;
2732 int space_remaining;
2733 struct ea_list *ea_list = NULL;
2734 NTSTATUS ntstatus = NT_STATUS_OK;
2735 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2736 TALLOC_CTX *ctx = talloc_tos();
2737 struct dptr_struct *dirptr;
2738 struct smbd_server_connection *sconn = req->sconn;
2739 bool backup_priv = false;
2741 if (total_params < 13) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2743 return;
2746 dptr_num = SVAL(params,0);
2747 maxentries = SVAL(params,2);
2748 info_level = SVAL(params,4);
2749 resume_key = IVAL(params,6);
2750 findnext_flags = SVAL(params,10);
2751 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2752 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2753 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2754 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2756 if (!continue_bit) {
2757 /* We only need resume_name if continue_bit is zero. */
2758 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2759 params+12,
2760 total_params - 12, STR_TERMINATE, &ntstatus,
2761 &mask_contains_wcard);
2762 if (!NT_STATUS_IS_OK(ntstatus)) {
2763 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2764 complain (it thinks we're asking for the directory above the shared
2765 path or an invalid name). Catch this as the resume name is only compared, never used in
2766 a file access. JRA. */
2767 srvstr_pull_talloc(ctx, params, req->flags2,
2768 &resume_name, params+12,
2769 total_params - 12,
2770 STR_TERMINATE);
2772 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2773 reply_nterror(req, ntstatus);
2774 return;
2779 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2780 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2781 resume_key = %d resume name = %s continue=%d level = %d\n",
2782 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2783 requires_resume_key, resume_key,
2784 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2786 if (!maxentries) {
2787 /* W2K3 seems to treat zero as 1. */
2788 maxentries = 1;
2791 switch (info_level) {
2792 case SMB_FIND_INFO_STANDARD:
2793 case SMB_FIND_EA_SIZE:
2794 case SMB_FIND_EA_LIST:
2795 case SMB_FIND_FILE_DIRECTORY_INFO:
2796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2797 case SMB_FIND_FILE_NAMES_INFO:
2798 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2799 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2801 break;
2802 case SMB_FIND_FILE_UNIX:
2803 case SMB_FIND_FILE_UNIX_INFO2:
2804 /* Always use filesystem for UNIX mtime query. */
2805 ask_sharemode = false;
2806 if (!lp_unix_extensions()) {
2807 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2808 return;
2810 break;
2811 default:
2812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 return;
2816 if (info_level == SMB_FIND_EA_LIST) {
2817 uint32 ea_size;
2819 if (total_data < 4) {
2820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 return;
2824 ea_size = IVAL(pdata,0);
2825 if (ea_size != total_data) {
2826 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2827 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2829 return;
2832 if (!lp_ea_support(SNUM(conn))) {
2833 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2834 return;
2837 /* Pull out the list of names. */
2838 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2839 if (!ea_list) {
2840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2841 return;
2845 *ppdata = (char *)SMB_REALLOC(
2846 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2847 if(*ppdata == NULL) {
2848 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 return;
2852 pdata = *ppdata;
2853 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2855 /* Realloc the params space */
2856 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2857 if(*pparams == NULL ) {
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 return;
2862 params = *pparams;
2864 /* Check that the dptr is valid */
2865 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2866 reply_nterror(req, STATUS_NO_MORE_FILES);
2867 return;
2870 directory = dptr_path(sconn, dptr_num);
2872 /* Get the wildcard mask from the dptr */
2873 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2874 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2875 reply_nterror(req, STATUS_NO_MORE_FILES);
2876 return;
2879 /* Get the attr mask from the dptr */
2880 dirtype = dptr_attr(sconn, dptr_num);
2882 backup_priv = dptr_get_priv(dirptr);
2884 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2885 "backup_priv = %d\n",
2886 dptr_num, mask, dirtype,
2887 (long)dirptr,
2888 dptr_TellDir(dirptr),
2889 (int)backup_priv));
2891 /* Initialize per TRANS2_FIND_NEXT operation data */
2892 dptr_init_search_op(dirptr);
2894 /* We don't need to check for VOL here as this is returned by
2895 a different TRANS2 call. */
2897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2898 directory,lp_dontdescend(ctx, SNUM(conn))));
2899 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2900 dont_descend = True;
2902 p = pdata;
2903 space_remaining = max_data_bytes;
2904 out_of_space = False;
2906 if (backup_priv) {
2907 become_root();
2911 * Seek to the correct position. We no longer use the resume key but
2912 * depend on the last file name instead.
2915 if(!continue_bit && resume_name && *resume_name) {
2916 SMB_STRUCT_STAT st;
2918 long current_pos = 0;
2920 * Remember, name_to_8_3 is called by
2921 * get_lanman2_dir_entry(), so the resume name
2922 * could be mangled. Ensure we check the unmangled name.
2925 if (mangle_is_mangled(resume_name, conn->params)) {
2926 char *new_resume_name = NULL;
2927 mangle_lookup_name_from_8_3(ctx,
2928 resume_name,
2929 &new_resume_name,
2930 conn->params);
2931 if (new_resume_name) {
2932 resume_name = new_resume_name;
2937 * Fix for NT redirector problem triggered by resume key indexes
2938 * changing between directory scans. We now return a resume key of 0
2939 * and instead look for the filename to continue from (also given
2940 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2941 * findfirst/findnext (as is usual) then the directory pointer
2942 * should already be at the correct place.
2945 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2946 } /* end if resume_name && !continue_bit */
2948 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2949 bool got_exact_match = False;
2951 /* this is a heuristic to avoid seeking the dirptr except when
2952 absolutely necessary. It allows for a filename of about 40 chars */
2953 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2954 out_of_space = True;
2955 finished = False;
2956 } else {
2957 finished = !get_lanman2_dir_entry(ctx,
2958 conn,
2959 dirptr,
2960 req->flags2,
2961 mask,dirtype,info_level,
2962 requires_resume_key,dont_descend,
2963 ask_sharemode,
2964 &p,pdata,data_end,
2965 space_remaining, &out_of_space,
2966 &got_exact_match,
2967 &last_entry_off, ea_list);
2970 if (finished && out_of_space)
2971 finished = False;
2973 if (!finished && !out_of_space)
2974 numentries++;
2977 * As an optimisation if we know we aren't looking
2978 * for a wildcard name (ie. the name matches the wildcard exactly)
2979 * then we can finish on any (first) match.
2980 * This speeds up large directory searches. JRA.
2983 if(got_exact_match)
2984 finished = True;
2986 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2989 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req->cmd),
2991 mask, directory, dirtype, numentries ) );
2993 /* Check if we can close the dirptr */
2994 if(close_after_request || (finished && close_if_end)) {
2995 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2996 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2999 if (backup_priv) {
3000 unbecome_root();
3003 /* Set up the return parameter block */
3004 SSVAL(params,0,numentries);
3005 SSVAL(params,2,finished);
3006 SSVAL(params,4,0); /* Never an EA error */
3007 SSVAL(params,6,last_entry_off);
3009 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3010 max_data_bytes);
3012 return;
3015 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3017 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3018 return objid;
3021 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3023 SMB_ASSERT(extended_info != NULL);
3025 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3026 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3027 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3028 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3029 #ifdef SAMBA_VERSION_REVISION
3030 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3031 #endif
3032 extended_info->samba_subversion = 0;
3033 #ifdef SAMBA_VERSION_RC_RELEASE
3034 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3035 #else
3036 #ifdef SAMBA_VERSION_PRE_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3038 #endif
3039 #endif
3040 #ifdef SAMBA_VERSION_VENDOR_PATCH
3041 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3042 #endif
3043 extended_info->samba_gitcommitdate = 0;
3044 #ifdef SAMBA_VERSION_COMMIT_TIME
3045 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3046 #endif
3048 memset(extended_info->samba_version_string, 0,
3049 sizeof(extended_info->samba_version_string));
3051 snprintf (extended_info->samba_version_string,
3052 sizeof(extended_info->samba_version_string),
3053 "%s", samba_version_string());
3056 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3057 TALLOC_CTX *mem_ctx,
3058 uint16_t info_level,
3059 uint16_t flags2,
3060 unsigned int max_data_bytes,
3061 struct smb_filename *fname,
3062 char **ppdata,
3063 int *ret_data_len)
3065 char *pdata, *end_data;
3066 int data_len = 0, len;
3067 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3068 int snum = SNUM(conn);
3069 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3070 char *filename = NULL;
3071 uint32 additional_flags = 0;
3072 struct smb_filename smb_fname;
3073 SMB_STRUCT_STAT st;
3074 NTSTATUS status = NT_STATUS_OK;
3076 if (fname == NULL || fname->base_name == NULL) {
3077 filename = ".";
3078 } else {
3079 filename = fname->base_name;
3082 if (IS_IPC(conn)) {
3083 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3084 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3085 "info level (0x%x) on IPC$.\n",
3086 (unsigned int)info_level));
3087 return NT_STATUS_ACCESS_DENIED;
3091 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3093 ZERO_STRUCT(smb_fname);
3094 smb_fname.base_name = discard_const_p(char, filename);
3096 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3097 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3098 return map_nt_error_from_unix(errno);
3101 st = smb_fname.st;
3103 *ppdata = (char *)SMB_REALLOC(
3104 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3105 if (*ppdata == NULL) {
3106 return NT_STATUS_NO_MEMORY;
3109 pdata = *ppdata;
3110 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3111 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3113 switch (info_level) {
3114 case SMB_INFO_ALLOCATION:
3116 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3117 data_len = 18;
3118 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3119 return map_nt_error_from_unix(errno);
3122 block_size = lp_block_size(snum);
3123 if (bsize < block_size) {
3124 uint64_t factor = block_size/bsize;
3125 bsize = block_size;
3126 dsize /= factor;
3127 dfree /= factor;
3129 if (bsize > block_size) {
3130 uint64_t factor = bsize/block_size;
3131 bsize = block_size;
3132 dsize *= factor;
3133 dfree *= factor;
3135 bytes_per_sector = 512;
3136 sectors_per_unit = bsize/bytes_per_sector;
3138 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3139 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3140 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3142 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3143 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3144 SIVAL(pdata,l1_cUnit,dsize);
3145 SIVAL(pdata,l1_cUnitAvail,dfree);
3146 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3147 break;
3150 case SMB_INFO_VOLUME:
3151 /* Return volume name */
3153 * Add volume serial number - hash of a combination of
3154 * the called hostname and the service name.
3156 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3158 * Win2k3 and previous mess this up by sending a name length
3159 * one byte short. I believe only older clients (OS/2 Win9x) use
3160 * this call so try fixing this by adding a terminating null to
3161 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3163 len = srvstr_push(
3164 pdata, flags2,
3165 pdata+l2_vol_szVolLabel, vname,
3166 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3167 STR_NOALIGN|STR_TERMINATE);
3168 SCVAL(pdata,l2_vol_cch,len);
3169 data_len = l2_vol_szVolLabel + len;
3170 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3171 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3172 len, vname));
3173 break;
3175 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3176 case SMB_FS_ATTRIBUTE_INFORMATION:
3178 additional_flags = 0;
3179 #if defined(HAVE_SYS_QUOTAS)
3180 additional_flags |= FILE_VOLUME_QUOTAS;
3181 #endif
3183 if(lp_nt_acl_support(SNUM(conn))) {
3184 additional_flags |= FILE_PERSISTENT_ACLS;
3187 /* Capabilities are filled in at connection time through STATVFS call */
3188 additional_flags |= conn->fs_capabilities;
3189 additional_flags |= lp_parm_int(conn->params->service,
3190 "share", "fake_fscaps",
3193 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3194 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3195 additional_flags); /* FS ATTRIBUTES */
3197 SIVAL(pdata,4,255); /* Max filename component length */
3198 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3199 and will think we can't do long filenames */
3200 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3201 PTR_DIFF(end_data, pdata+12),
3202 STR_UNICODE);
3203 SIVAL(pdata,8,len);
3204 data_len = 12 + len;
3205 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3206 /* the client only requested a portion of the
3207 file system name */
3208 data_len = max_data_bytes;
3209 status = STATUS_BUFFER_OVERFLOW;
3211 break;
3213 case SMB_QUERY_FS_LABEL_INFO:
3214 case SMB_FS_LABEL_INFORMATION:
3215 len = srvstr_push(pdata, flags2, pdata+4, vname,
3216 PTR_DIFF(end_data, pdata+4), 0);
3217 data_len = 4 + len;
3218 SIVAL(pdata,0,len);
3219 break;
3221 case SMB_QUERY_FS_VOLUME_INFO:
3222 case SMB_FS_VOLUME_INFORMATION:
3225 * Add volume serial number - hash of a combination of
3226 * the called hostname and the service name.
3228 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3229 (str_checksum(get_local_machine_name())<<16));
3231 /* Max label len is 32 characters. */
3232 len = srvstr_push(pdata, flags2, pdata+18, vname,
3233 PTR_DIFF(end_data, pdata+18),
3234 STR_UNICODE);
3235 SIVAL(pdata,12,len);
3236 data_len = 18+len;
3238 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3239 (int)strlen(vname),vname,
3240 lp_servicename(talloc_tos(), snum)));
3241 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3242 /* the client only requested a portion of the
3243 volume label */
3244 data_len = max_data_bytes;
3245 status = STATUS_BUFFER_OVERFLOW;
3247 break;
3249 case SMB_QUERY_FS_SIZE_INFO:
3250 case SMB_FS_SIZE_INFORMATION:
3252 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3253 data_len = 24;
3254 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3255 return map_nt_error_from_unix(errno);
3257 block_size = lp_block_size(snum);
3258 if (bsize < block_size) {
3259 uint64_t factor = block_size/bsize;
3260 bsize = block_size;
3261 dsize /= factor;
3262 dfree /= factor;
3264 if (bsize > block_size) {
3265 uint64_t factor = bsize/block_size;
3266 bsize = block_size;
3267 dsize *= factor;
3268 dfree *= factor;
3270 bytes_per_sector = 512;
3271 sectors_per_unit = bsize/bytes_per_sector;
3272 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3273 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3274 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3275 SBIG_UINT(pdata,0,dsize);
3276 SBIG_UINT(pdata,8,dfree);
3277 SIVAL(pdata,16,sectors_per_unit);
3278 SIVAL(pdata,20,bytes_per_sector);
3279 break;
3282 case SMB_FS_FULL_SIZE_INFORMATION:
3284 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3285 data_len = 32;
3286 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3287 return map_nt_error_from_unix(errno);
3289 block_size = lp_block_size(snum);
3290 if (bsize < block_size) {
3291 uint64_t factor = block_size/bsize;
3292 bsize = block_size;
3293 dsize /= factor;
3294 dfree /= factor;
3296 if (bsize > block_size) {
3297 uint64_t factor = bsize/block_size;
3298 bsize = block_size;
3299 dsize *= factor;
3300 dfree *= factor;
3302 bytes_per_sector = 512;
3303 sectors_per_unit = bsize/bytes_per_sector;
3304 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3305 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3306 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3307 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3308 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3309 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3310 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3311 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3312 break;
3315 case SMB_QUERY_FS_DEVICE_INFO:
3316 case SMB_FS_DEVICE_INFORMATION:
3318 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3320 if (!CAN_WRITE(conn)) {
3321 characteristics |= FILE_READ_ONLY_DEVICE;
3323 data_len = 8;
3324 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3325 SIVAL(pdata,4,characteristics);
3326 break;
3329 #ifdef HAVE_SYS_QUOTAS
3330 case SMB_FS_QUOTA_INFORMATION:
3332 * what we have to send --metze:
3334 * Unknown1: 24 NULL bytes
3335 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3336 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3337 * Quota Flags: 2 byte :
3338 * Unknown3: 6 NULL bytes
3340 * 48 bytes total
3342 * details for Quota Flags:
3344 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3345 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3346 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3347 * 0x0001 Enable Quotas: enable quota for this fs
3351 /* we need to fake up a fsp here,
3352 * because its not send in this call
3354 files_struct fsp;
3355 SMB_NTQUOTA_STRUCT quotas;
3357 ZERO_STRUCT(fsp);
3358 ZERO_STRUCT(quotas);
3360 fsp.conn = conn;
3361 fsp.fnum = FNUM_FIELD_INVALID;
3363 /* access check */
3364 if (get_current_uid(conn) != 0) {
3365 DEBUG(0,("set_user_quota: access_denied "
3366 "service [%s] user [%s]\n",
3367 lp_servicename(talloc_tos(), SNUM(conn)),
3368 conn->session_info->unix_info->unix_name));
3369 return NT_STATUS_ACCESS_DENIED;
3372 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3373 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3374 return map_nt_error_from_unix(errno);
3377 data_len = 48;
3379 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3380 lp_servicename(talloc_tos(), SNUM(conn))));
3382 /* Unknown1 24 NULL bytes*/
3383 SBIG_UINT(pdata,0,(uint64_t)0);
3384 SBIG_UINT(pdata,8,(uint64_t)0);
3385 SBIG_UINT(pdata,16,(uint64_t)0);
3387 /* Default Soft Quota 8 bytes */
3388 SBIG_UINT(pdata,24,quotas.softlim);
3390 /* Default Hard Quota 8 bytes */
3391 SBIG_UINT(pdata,32,quotas.hardlim);
3393 /* Quota flag 2 bytes */
3394 SSVAL(pdata,40,quotas.qflags);
3396 /* Unknown3 6 NULL bytes */
3397 SSVAL(pdata,42,0);
3398 SIVAL(pdata,44,0);
3400 break;
3402 #endif /* HAVE_SYS_QUOTAS */
3403 case SMB_FS_OBJECTID_INFORMATION:
3405 unsigned char objid[16];
3406 struct smb_extended_info extended_info;
3407 memcpy(pdata,create_volume_objectid(conn, objid),16);
3408 samba_extended_info_version (&extended_info);
3409 SIVAL(pdata,16,extended_info.samba_magic);
3410 SIVAL(pdata,20,extended_info.samba_version);
3411 SIVAL(pdata,24,extended_info.samba_subversion);
3412 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3413 memcpy(pdata+36,extended_info.samba_version_string,28);
3414 data_len = 64;
3415 break;
3419 * Query the version and capabilities of the CIFS UNIX extensions
3420 * in use.
3423 case SMB_QUERY_CIFS_UNIX_INFO:
3425 bool large_write = lp_min_receive_file_size() &&
3426 !srv_is_signing_active(conn->sconn);
3427 bool large_read = !srv_is_signing_active(conn->sconn);
3428 int encrypt_caps = 0;
3430 if (!lp_unix_extensions()) {
3431 return NT_STATUS_INVALID_LEVEL;
3434 switch (conn->encrypt_level) {
3435 case SMB_SIGNING_OFF:
3436 encrypt_caps = 0;
3437 break;
3438 case SMB_SIGNING_IF_REQUIRED:
3439 case SMB_SIGNING_DEFAULT:
3440 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3441 break;
3442 case SMB_SIGNING_REQUIRED:
3443 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3444 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3445 large_write = false;
3446 large_read = false;
3447 break;
3450 data_len = 12;
3451 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3452 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3454 /* We have POSIX ACLs, pathname, encryption,
3455 * large read/write, and locking capability. */
3457 SBIG_UINT(pdata,4,((uint64_t)(
3458 CIFS_UNIX_POSIX_ACLS_CAP|
3459 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3460 CIFS_UNIX_FCNTL_LOCKS_CAP|
3461 CIFS_UNIX_EXTATTR_CAP|
3462 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3463 encrypt_caps|
3464 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3465 (large_write ?
3466 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3467 break;
3470 case SMB_QUERY_POSIX_FS_INFO:
3472 int rc;
3473 vfs_statvfs_struct svfs;
3475 if (!lp_unix_extensions()) {
3476 return NT_STATUS_INVALID_LEVEL;
3479 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3481 if (!rc) {
3482 data_len = 56;
3483 SIVAL(pdata,0,svfs.OptimalTransferSize);
3484 SIVAL(pdata,4,svfs.BlockSize);
3485 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3486 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3487 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3488 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3489 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3490 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3491 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3492 #ifdef EOPNOTSUPP
3493 } else if (rc == EOPNOTSUPP) {
3494 return NT_STATUS_INVALID_LEVEL;
3495 #endif /* EOPNOTSUPP */
3496 } else {
3497 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3498 return NT_STATUS_DOS(ERRSRV, ERRerror);
3500 break;
3503 case SMB_QUERY_POSIX_WHOAMI:
3505 uint32_t flags = 0;
3506 uint32_t sid_bytes;
3507 int i;
3509 if (!lp_unix_extensions()) {
3510 return NT_STATUS_INVALID_LEVEL;
3513 if (max_data_bytes < 40) {
3514 return NT_STATUS_BUFFER_TOO_SMALL;
3517 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3518 flags |= SMB_WHOAMI_GUEST;
3521 /* NOTE: 8 bytes for UID/GID, irrespective of native
3522 * platform size. This matches
3523 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3525 data_len = 4 /* flags */
3526 + 4 /* flag mask */
3527 + 8 /* uid */
3528 + 8 /* gid */
3529 + 4 /* ngroups */
3530 + 4 /* num_sids */
3531 + 4 /* SID bytes */
3532 + 4 /* pad/reserved */
3533 + (conn->session_info->unix_token->ngroups * 8)
3534 /* groups list */
3535 + (conn->session_info->security_token->num_sids *
3536 SID_MAX_SIZE)
3537 /* SID list */;
3539 SIVAL(pdata, 0, flags);
3540 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3541 SBIG_UINT(pdata, 8,
3542 (uint64_t)conn->session_info->unix_token->uid);
3543 SBIG_UINT(pdata, 16,
3544 (uint64_t)conn->session_info->unix_token->gid);
3547 if (data_len >= max_data_bytes) {
3548 /* Potential overflow, skip the GIDs and SIDs. */
3550 SIVAL(pdata, 24, 0); /* num_groups */
3551 SIVAL(pdata, 28, 0); /* num_sids */
3552 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3553 SIVAL(pdata, 36, 0); /* reserved */
3555 data_len = 40;
3556 break;
3559 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3560 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3562 /* We walk the SID list twice, but this call is fairly
3563 * infrequent, and I don't expect that it's performance
3564 * sensitive -- jpeach
3566 for (i = 0, sid_bytes = 0;
3567 i < conn->session_info->security_token->num_sids; ++i) {
3568 sid_bytes += ndr_size_dom_sid(
3569 &conn->session_info->security_token->sids[i],
3573 /* SID list byte count */
3574 SIVAL(pdata, 32, sid_bytes);
3576 /* 4 bytes pad/reserved - must be zero */
3577 SIVAL(pdata, 36, 0);
3578 data_len = 40;
3580 /* GID list */
3581 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3582 SBIG_UINT(pdata, data_len,
3583 (uint64_t)conn->session_info->unix_token->groups[i]);
3584 data_len += 8;
3587 /* SID list */
3588 for (i = 0;
3589 i < conn->session_info->security_token->num_sids; ++i) {
3590 int sid_len = ndr_size_dom_sid(
3591 &conn->session_info->security_token->sids[i],
3594 sid_linearize(pdata + data_len, sid_len,
3595 &conn->session_info->security_token->sids[i]);
3596 data_len += sid_len;
3599 break;
3602 case SMB_MAC_QUERY_FS_INFO:
3604 * Thursby MAC extension... ONLY on NTFS filesystems
3605 * once we do streams then we don't need this
3607 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3608 data_len = 88;
3609 SIVAL(pdata,84,0x100); /* Don't support mac... */
3610 break;
3612 /* drop through */
3613 default:
3614 return NT_STATUS_INVALID_LEVEL;
3617 *ret_data_len = data_len;
3618 return status;
3621 /****************************************************************************
3622 Reply to a TRANS2_QFSINFO (query filesystem info).
3623 ****************************************************************************/
3625 static void call_trans2qfsinfo(connection_struct *conn,
3626 struct smb_request *req,
3627 char **pparams, int total_params,
3628 char **ppdata, int total_data,
3629 unsigned int max_data_bytes)
3631 char *params = *pparams;
3632 uint16_t info_level;
3633 int data_len = 0;
3634 NTSTATUS status;
3636 if (total_params < 2) {
3637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3638 return;
3641 info_level = SVAL(params,0);
3643 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3644 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3645 DEBUG(0,("call_trans2qfsinfo: encryption required "
3646 "and info level 0x%x sent.\n",
3647 (unsigned int)info_level));
3648 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3649 return;
3653 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3655 status = smbd_do_qfsinfo(conn, req,
3656 info_level,
3657 req->flags2,
3658 max_data_bytes,
3659 NULL,
3660 ppdata, &data_len);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 reply_nterror(req, status);
3663 return;
3666 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3667 max_data_bytes);
3669 DEBUG( 4, ( "%s info_level = %d\n",
3670 smb_fn_name(req->cmd), info_level) );
3672 return;
3675 /****************************************************************************
3676 Reply to a TRANS2_SETFSINFO (set filesystem info).
3677 ****************************************************************************/
3679 static void call_trans2setfsinfo(connection_struct *conn,
3680 struct smb_request *req,
3681 char **pparams, int total_params,
3682 char **ppdata, int total_data,
3683 unsigned int max_data_bytes)
3685 struct smbd_server_connection *sconn = req->sconn;
3686 char *pdata = *ppdata;
3687 char *params = *pparams;
3688 uint16 info_level;
3690 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3691 lp_servicename(talloc_tos(), SNUM(conn))));
3693 /* */
3694 if (total_params < 4) {
3695 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3696 total_params));
3697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3698 return;
3701 info_level = SVAL(params,2);
3703 if (IS_IPC(conn)) {
3704 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3705 info_level != SMB_SET_CIFS_UNIX_INFO) {
3706 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3707 "info level (0x%x) on IPC$.\n",
3708 (unsigned int)info_level));
3709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3710 return;
3714 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3715 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3716 DEBUG(0,("call_trans2setfsinfo: encryption required "
3717 "and info level 0x%x sent.\n",
3718 (unsigned int)info_level));
3719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3720 return;
3724 switch(info_level) {
3725 case SMB_SET_CIFS_UNIX_INFO:
3726 if (!lp_unix_extensions()) {
3727 DEBUG(2,("call_trans2setfsinfo: "
3728 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3729 "unix extensions off\n"));
3730 reply_nterror(req,
3731 NT_STATUS_INVALID_LEVEL);
3732 return;
3735 /* There should be 12 bytes of capabilities set. */
3736 if (total_data < 12) {
3737 reply_nterror(
3738 req,
3739 NT_STATUS_INVALID_PARAMETER);
3740 return;
3742 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3743 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3744 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3745 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3746 /* Just print these values for now. */
3747 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3748 "major = %u, minor = %u cap_low = 0x%x, "
3749 "cap_high = 0x%xn",
3750 (unsigned int)sconn->
3751 smb1.unix_info.client_major,
3752 (unsigned int)sconn->
3753 smb1.unix_info.client_minor,
3754 (unsigned int)sconn->
3755 smb1.unix_info.client_cap_low,
3756 (unsigned int)sconn->
3757 smb1.unix_info.client_cap_high));
3759 /* Here is where we must switch to posix pathname processing... */
3760 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3761 lp_set_posix_pathnames();
3762 mangle_change_to_posix();
3765 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3766 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3767 /* Client that knows how to do posix locks,
3768 * but not posix open/mkdir operations. Set a
3769 * default type for read/write checks. */
3771 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3774 break;
3776 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3778 NTSTATUS status;
3779 size_t param_len = 0;
3780 size_t data_len = total_data;
3782 if (!lp_unix_extensions()) {
3783 reply_nterror(
3784 req,
3785 NT_STATUS_INVALID_LEVEL);
3786 return;
3789 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3790 reply_nterror(
3791 req,
3792 NT_STATUS_NOT_SUPPORTED);
3793 return;
3796 if (req->sconn->smb1.echo_handler.trusted_fde) {
3797 DEBUG( 2,("call_trans2setfsinfo: "
3798 "request transport encryption disabled"
3799 "with 'fork echo handler = yes'\n"));
3800 reply_nterror(
3801 req,
3802 NT_STATUS_NOT_SUPPORTED);
3803 return;
3806 DEBUG( 4,("call_trans2setfsinfo: "
3807 "request transport encryption.\n"));
3809 status = srv_request_encryption_setup(conn,
3810 (unsigned char **)ppdata,
3811 &data_len,
3812 (unsigned char **)pparams,
3813 &param_len);
3815 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3816 !NT_STATUS_IS_OK(status)) {
3817 reply_nterror(req, status);
3818 return;
3821 send_trans2_replies(conn, req,
3822 NT_STATUS_OK,
3823 *pparams,
3824 param_len,
3825 *ppdata,
3826 data_len,
3827 max_data_bytes);
3829 if (NT_STATUS_IS_OK(status)) {
3830 /* Server-side transport
3831 * encryption is now *on*. */
3832 status = srv_encryption_start(conn);
3833 if (!NT_STATUS_IS_OK(status)) {
3834 char *reason = talloc_asprintf(talloc_tos(),
3835 "Failure in setting "
3836 "up encrypted transport: %s",
3837 nt_errstr(status));
3838 exit_server_cleanly(reason);
3841 return;
3844 case SMB_FS_QUOTA_INFORMATION:
3846 files_struct *fsp = NULL;
3847 SMB_NTQUOTA_STRUCT quotas;
3849 ZERO_STRUCT(quotas);
3851 /* access check */
3852 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3853 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3854 lp_servicename(talloc_tos(), SNUM(conn)),
3855 conn->session_info->unix_info->unix_name));
3856 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3857 return;
3860 /* note: normaly there're 48 bytes,
3861 * but we didn't use the last 6 bytes for now
3862 * --metze
3864 fsp = file_fsp(req, SVAL(params,0));
3866 if (!check_fsp_ntquota_handle(conn, req,
3867 fsp)) {
3868 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3869 reply_nterror(
3870 req, NT_STATUS_INVALID_HANDLE);
3871 return;
3874 if (total_data < 42) {
3875 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3876 total_data));
3877 reply_nterror(
3878 req,
3879 NT_STATUS_INVALID_PARAMETER);
3880 return;
3883 /* unknown_1 24 NULL bytes in pdata*/
3885 /* the soft quotas 8 bytes (uint64_t)*/
3886 quotas.softlim = BVAL(pdata,24);
3888 /* the hard quotas 8 bytes (uint64_t)*/
3889 quotas.hardlim = BVAL(pdata,32);
3891 /* quota_flags 2 bytes **/
3892 quotas.qflags = SVAL(pdata,40);
3894 /* unknown_2 6 NULL bytes follow*/
3896 /* now set the quotas */
3897 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3898 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3899 reply_nterror(req, map_nt_error_from_unix(errno));
3900 return;
3903 break;
3905 default:
3906 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3907 info_level));
3908 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3909 return;
3910 break;
3914 * sending this reply works fine,
3915 * but I'm not sure it's the same
3916 * like windows do...
3917 * --metze
3919 reply_outbuf(req, 10, 0);
3922 #if defined(HAVE_POSIX_ACLS)
3923 /****************************************************************************
3924 Utility function to count the number of entries in a POSIX acl.
3925 ****************************************************************************/
3927 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3929 unsigned int ace_count = 0;
3930 int entry_id = SMB_ACL_FIRST_ENTRY;
3931 SMB_ACL_ENTRY_T entry;
3933 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3934 /* get_next... */
3935 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3936 entry_id = SMB_ACL_NEXT_ENTRY;
3938 ace_count++;
3940 return ace_count;
3943 /****************************************************************************
3944 Utility function to marshall a POSIX acl into wire format.
3945 ****************************************************************************/
3947 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3949 int entry_id = SMB_ACL_FIRST_ENTRY;
3950 SMB_ACL_ENTRY_T entry;
3952 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3953 SMB_ACL_TAG_T tagtype;
3954 SMB_ACL_PERMSET_T permset;
3955 unsigned char perms = 0;
3956 unsigned int own_grp;
3958 /* get_next... */
3959 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3960 entry_id = SMB_ACL_NEXT_ENTRY;
3963 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3964 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3965 return False;
3968 if (sys_acl_get_permset(entry, &permset) == -1) {
3969 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3970 return False;
3973 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3974 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3975 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3977 SCVAL(pdata,1,perms);
3979 switch (tagtype) {
3980 case SMB_ACL_USER_OBJ:
3981 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3982 own_grp = (unsigned int)pst->st_ex_uid;
3983 SIVAL(pdata,2,own_grp);
3984 SIVAL(pdata,6,0);
3985 break;
3986 case SMB_ACL_USER:
3988 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3989 if (!puid) {
3990 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3991 return False;
3993 own_grp = (unsigned int)*puid;
3994 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3995 SIVAL(pdata,2,own_grp);
3996 SIVAL(pdata,6,0);
3997 break;
3999 case SMB_ACL_GROUP_OBJ:
4000 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4001 own_grp = (unsigned int)pst->st_ex_gid;
4002 SIVAL(pdata,2,own_grp);
4003 SIVAL(pdata,6,0);
4004 break;
4005 case SMB_ACL_GROUP:
4007 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4008 if (!pgid) {
4009 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4010 return False;
4012 own_grp = (unsigned int)*pgid;
4013 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4014 SIVAL(pdata,2,own_grp);
4015 SIVAL(pdata,6,0);
4016 break;
4018 case SMB_ACL_MASK:
4019 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4020 SIVAL(pdata,2,0xFFFFFFFF);
4021 SIVAL(pdata,6,0xFFFFFFFF);
4022 break;
4023 case SMB_ACL_OTHER:
4024 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4025 SIVAL(pdata,2,0xFFFFFFFF);
4026 SIVAL(pdata,6,0xFFFFFFFF);
4027 break;
4028 default:
4029 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4030 return False;
4032 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4035 return True;
4037 #endif
4039 /****************************************************************************
4040 Store the FILE_UNIX_BASIC info.
4041 ****************************************************************************/
4043 static char *store_file_unix_basic(connection_struct *conn,
4044 char *pdata,
4045 files_struct *fsp,
4046 const SMB_STRUCT_STAT *psbuf)
4048 uint64_t file_index = get_FileIndex(conn, psbuf);
4049 dev_t devno;
4051 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4052 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4054 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4055 pdata += 8;
4057 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4058 pdata += 8;
4060 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4061 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4062 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4063 pdata += 24;
4065 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4066 SIVAL(pdata,4,0);
4067 pdata += 8;
4069 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4070 SIVAL(pdata,4,0);
4071 pdata += 8;
4073 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4074 pdata += 4;
4076 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4077 devno = psbuf->st_ex_rdev;
4078 } else {
4079 devno = psbuf->st_ex_dev;
4082 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4083 SIVAL(pdata,4,0);
4084 pdata += 8;
4086 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4087 SIVAL(pdata,4,0);
4088 pdata += 8;
4090 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4091 pdata += 8;
4093 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4094 SIVAL(pdata,4,0);
4095 pdata += 8;
4097 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4098 SIVAL(pdata,4,0);
4099 pdata += 8;
4101 return pdata;
4104 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4105 * the chflags(2) (or equivalent) flags.
4107 * XXX: this really should be behind the VFS interface. To do this, we would
4108 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4109 * Each VFS module could then implement its own mapping as appropriate for the
4110 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4112 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4113 info2_flags_map[] =
4115 #ifdef UF_NODUMP
4116 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4117 #endif
4119 #ifdef UF_IMMUTABLE
4120 { UF_IMMUTABLE, EXT_IMMUTABLE },
4121 #endif
4123 #ifdef UF_APPEND
4124 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4125 #endif
4127 #ifdef UF_HIDDEN
4128 { UF_HIDDEN, EXT_HIDDEN },
4129 #endif
4131 /* Do not remove. We need to guarantee that this array has at least one
4132 * entry to build on HP-UX.
4134 { 0, 0 }
4138 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4139 uint32 *smb_fflags, uint32 *smb_fmask)
4141 int i;
4143 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4144 *smb_fmask |= info2_flags_map[i].smb_fflag;
4145 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4146 *smb_fflags |= info2_flags_map[i].smb_fflag;
4151 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4152 const uint32 smb_fflags,
4153 const uint32 smb_fmask,
4154 int *stat_fflags)
4156 uint32 max_fmask = 0;
4157 int i;
4159 *stat_fflags = psbuf->st_ex_flags;
4161 /* For each flags requested in smb_fmask, check the state of the
4162 * corresponding flag in smb_fflags and set or clear the matching
4163 * stat flag.
4166 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4167 max_fmask |= info2_flags_map[i].smb_fflag;
4168 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4169 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4170 *stat_fflags |= info2_flags_map[i].stat_fflag;
4171 } else {
4172 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4177 /* If smb_fmask is asking to set any bits that are not supported by
4178 * our flag mappings, we should fail.
4180 if ((smb_fmask & max_fmask) != smb_fmask) {
4181 return False;
4184 return True;
4188 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4189 * of file flags and birth (create) time.
4191 static char *store_file_unix_basic_info2(connection_struct *conn,
4192 char *pdata,
4193 files_struct *fsp,
4194 const SMB_STRUCT_STAT *psbuf)
4196 uint32 file_flags = 0;
4197 uint32 flags_mask = 0;
4199 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4201 /* Create (birth) time 64 bit */
4202 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4203 pdata += 8;
4205 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4206 SIVAL(pdata, 0, file_flags); /* flags */
4207 SIVAL(pdata, 4, flags_mask); /* mask */
4208 pdata += 8;
4210 return pdata;
4213 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4214 const struct stream_struct *streams,
4215 char *data,
4216 unsigned int max_data_bytes,
4217 unsigned int *data_size)
4219 unsigned int i;
4220 unsigned int ofs = 0;
4222 for (i = 0; i < num_streams; i++) {
4223 unsigned int next_offset;
4224 size_t namelen;
4225 smb_ucs2_t *namebuf;
4227 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4228 streams[i].name, &namelen) ||
4229 namelen <= 2)
4231 return NT_STATUS_INVALID_PARAMETER;
4235 * name_buf is now null-terminated, we need to marshall as not
4236 * terminated
4239 namelen -= 2;
4242 * We cannot overflow ...
4244 if ((ofs + 24 + namelen) > max_data_bytes) {
4245 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4246 i));
4247 TALLOC_FREE(namebuf);
4248 return STATUS_BUFFER_OVERFLOW;
4251 SIVAL(data, ofs+4, namelen);
4252 SOFF_T(data, ofs+8, streams[i].size);
4253 SOFF_T(data, ofs+16, streams[i].alloc_size);
4254 memcpy(data+ofs+24, namebuf, namelen);
4255 TALLOC_FREE(namebuf);
4257 next_offset = ofs + 24 + namelen;
4259 if (i == num_streams-1) {
4260 SIVAL(data, ofs, 0);
4262 else {
4263 unsigned int align = ndr_align_size(next_offset, 8);
4265 if ((next_offset + align) > max_data_bytes) {
4266 DEBUG(10, ("refusing to overflow align "
4267 "reply at stream %u\n",
4268 i));
4269 TALLOC_FREE(namebuf);
4270 return STATUS_BUFFER_OVERFLOW;
4273 memset(data+next_offset, 0, align);
4274 next_offset += align;
4276 SIVAL(data, ofs, next_offset - ofs);
4277 ofs = next_offset;
4280 ofs = next_offset;
4283 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4285 *data_size = ofs;
4287 return NT_STATUS_OK;
4290 /****************************************************************************
4291 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4292 ****************************************************************************/
4294 static void call_trans2qpipeinfo(connection_struct *conn,
4295 struct smb_request *req,
4296 unsigned int tran_call,
4297 char **pparams, int total_params,
4298 char **ppdata, int total_data,
4299 unsigned int max_data_bytes)
4301 char *params = *pparams;
4302 char *pdata = *ppdata;
4303 unsigned int data_size = 0;
4304 unsigned int param_size = 2;
4305 uint16 info_level;
4306 files_struct *fsp;
4308 if (!params) {
4309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4310 return;
4313 if (total_params < 4) {
4314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4315 return;
4318 fsp = file_fsp(req, SVAL(params,0));
4319 if (!fsp_is_np(fsp)) {
4320 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4321 return;
4324 info_level = SVAL(params,2);
4326 *pparams = (char *)SMB_REALLOC(*pparams,2);
4327 if (*pparams == NULL) {
4328 reply_nterror(req, NT_STATUS_NO_MEMORY);
4329 return;
4331 params = *pparams;
4332 SSVAL(params,0,0);
4333 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4334 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4335 if (*ppdata == NULL ) {
4336 reply_nterror(req, NT_STATUS_NO_MEMORY);
4337 return;
4339 pdata = *ppdata;
4341 switch (info_level) {
4342 case SMB_FILE_STANDARD_INFORMATION:
4343 memset(pdata,0,24);
4344 SOFF_T(pdata,0,4096LL);
4345 SIVAL(pdata,16,1);
4346 SIVAL(pdata,20,1);
4347 data_size = 24;
4348 break;
4350 default:
4351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4352 return;
4355 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4356 max_data_bytes);
4358 return;
4361 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4362 TALLOC_CTX *mem_ctx,
4363 uint16_t info_level,
4364 files_struct *fsp,
4365 struct smb_filename *smb_fname,
4366 bool delete_pending,
4367 struct timespec write_time_ts,
4368 struct ea_list *ea_list,
4369 int lock_data_count,
4370 char *lock_data,
4371 uint16_t flags2,
4372 unsigned int max_data_bytes,
4373 char **ppdata,
4374 unsigned int *pdata_size)
4376 char *pdata = *ppdata;
4377 char *dstart, *dend;
4378 unsigned int data_size;
4379 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4380 time_t create_time, mtime, atime, c_time;
4381 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4382 char *p;
4383 char *base_name;
4384 char *dos_fname;
4385 int mode;
4386 int nlink;
4387 NTSTATUS status;
4388 uint64_t file_size = 0;
4389 uint64_t pos = 0;
4390 uint64_t allocation_size = 0;
4391 uint64_t file_index = 0;
4392 uint32_t access_mask = 0;
4394 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4395 return NT_STATUS_INVALID_LEVEL;
4398 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4399 smb_fname_str_dbg(smb_fname),
4400 fsp_fnum_dbg(fsp),
4401 info_level, max_data_bytes));
4403 mode = dos_mode(conn, smb_fname);
4404 nlink = psbuf->st_ex_nlink;
4406 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4407 nlink = 1;
4410 if ((nlink > 0) && delete_pending) {
4411 nlink -= 1;
4414 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4415 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4416 if (*ppdata == NULL) {
4417 return NT_STATUS_NO_MEMORY;
4419 pdata = *ppdata;
4420 dstart = pdata;
4421 dend = dstart + data_size - 1;
4423 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4424 update_stat_ex_mtime(psbuf, write_time_ts);
4427 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4428 mtime_ts = psbuf->st_ex_mtime;
4429 atime_ts = psbuf->st_ex_atime;
4430 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4432 if (lp_dos_filetime_resolution(SNUM(conn))) {
4433 dos_filetime_timespec(&create_time_ts);
4434 dos_filetime_timespec(&mtime_ts);
4435 dos_filetime_timespec(&atime_ts);
4436 dos_filetime_timespec(&ctime_ts);
4439 create_time = convert_timespec_to_time_t(create_time_ts);
4440 mtime = convert_timespec_to_time_t(mtime_ts);
4441 atime = convert_timespec_to_time_t(atime_ts);
4442 c_time = convert_timespec_to_time_t(ctime_ts);
4444 p = strrchr_m(smb_fname->base_name,'/');
4445 if (!p)
4446 base_name = smb_fname->base_name;
4447 else
4448 base_name = p+1;
4450 /* NT expects the name to be in an exact form of the *full*
4451 filename. See the trans2 torture test */
4452 if (ISDOT(base_name)) {
4453 dos_fname = talloc_strdup(mem_ctx, "\\");
4454 if (!dos_fname) {
4455 return NT_STATUS_NO_MEMORY;
4457 } else {
4458 dos_fname = talloc_asprintf(mem_ctx,
4459 "\\%s",
4460 smb_fname->base_name);
4461 if (!dos_fname) {
4462 return NT_STATUS_NO_MEMORY;
4464 if (is_ntfs_stream_smb_fname(smb_fname)) {
4465 dos_fname = talloc_asprintf(dos_fname, "%s",
4466 smb_fname->stream_name);
4467 if (!dos_fname) {
4468 return NT_STATUS_NO_MEMORY;
4472 string_replace(dos_fname, '/', '\\');
4475 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4477 if (!fsp) {
4478 /* Do we have this path open ? */
4479 files_struct *fsp1;
4480 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4481 fsp1 = file_find_di_first(conn->sconn, fileid);
4482 if (fsp1 && fsp1->initial_allocation_size) {
4483 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4487 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4488 file_size = get_file_size_stat(psbuf);
4491 if (fsp) {
4492 pos = fsp->fh->position_information;
4495 if (fsp) {
4496 access_mask = fsp->access_mask;
4497 } else {
4498 /* GENERIC_EXECUTE mapping from Windows */
4499 access_mask = 0x12019F;
4502 /* This should be an index number - looks like
4503 dev/ino to me :-)
4505 I think this causes us to fail the IFSKIT
4506 BasicFileInformationTest. -tpot */
4507 file_index = get_FileIndex(conn, psbuf);
4509 switch (info_level) {
4510 case SMB_INFO_STANDARD:
4511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4512 data_size = 22;
4513 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4514 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4515 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4516 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4517 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4518 SSVAL(pdata,l1_attrFile,mode);
4519 break;
4521 case SMB_INFO_QUERY_EA_SIZE:
4523 unsigned int ea_size =
4524 estimate_ea_size(conn, fsp,
4525 smb_fname);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4527 data_size = 26;
4528 srv_put_dos_date2(pdata,0,create_time);
4529 srv_put_dos_date2(pdata,4,atime);
4530 srv_put_dos_date2(pdata,8,mtime); /* write time */
4531 SIVAL(pdata,12,(uint32)file_size);
4532 SIVAL(pdata,16,(uint32)allocation_size);
4533 SSVAL(pdata,20,mode);
4534 SIVAL(pdata,22,ea_size);
4535 break;
4538 case SMB_INFO_IS_NAME_VALID:
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4540 if (fsp) {
4541 /* os/2 needs this ? really ?*/
4542 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4544 /* This is only reached for qpathinfo */
4545 data_size = 0;
4546 break;
4548 case SMB_INFO_QUERY_EAS_FROM_LIST:
4550 size_t total_ea_len = 0;
4551 struct ea_list *ea_file_list = NULL;
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4554 status =
4555 get_ea_list_from_file(mem_ctx, conn, fsp,
4556 smb_fname,
4557 &total_ea_len, &ea_file_list);
4558 if (!NT_STATUS_IS_OK(status)) {
4559 return status;
4562 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4564 if (!ea_list || (total_ea_len > data_size)) {
4565 data_size = 4;
4566 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4567 break;
4570 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4571 break;
4574 case SMB_INFO_QUERY_ALL_EAS:
4576 /* We have data_size bytes to put EA's into. */
4577 size_t total_ea_len = 0;
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4580 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4581 smb_fname,
4582 &total_ea_len, &ea_list);
4583 if (!NT_STATUS_IS_OK(status)) {
4584 return status;
4587 if (!ea_list || (total_ea_len > data_size)) {
4588 data_size = 4;
4589 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4590 break;
4593 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4594 break;
4597 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4599 /* This is FileFullEaInformation - 0xF which maps to
4600 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4602 /* We have data_size bytes to put EA's into. */
4603 size_t total_ea_len = 0;
4604 struct ea_list *ea_file_list = NULL;
4606 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4608 /*TODO: add filtering and index handling */
4610 status =
4611 get_ea_list_from_file(mem_ctx, conn, fsp,
4612 smb_fname,
4613 &total_ea_len, &ea_file_list);
4614 if (!NT_STATUS_IS_OK(status)) {
4615 return status;
4617 if (!ea_file_list) {
4618 return NT_STATUS_NO_EAS_ON_FILE;
4621 status = fill_ea_chained_buffer(mem_ctx,
4622 pdata,
4623 data_size,
4624 &data_size,
4625 conn, ea_file_list);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 return status;
4629 break;
4632 case SMB_FILE_BASIC_INFORMATION:
4633 case SMB_QUERY_FILE_BASIC_INFO:
4635 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4637 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4638 } else {
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4640 data_size = 40;
4641 SIVAL(pdata,36,0);
4643 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4644 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4645 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4646 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4647 SIVAL(pdata,32,mode);
4649 DEBUG(5,("SMB_QFBI - "));
4650 DEBUG(5,("create: %s ", ctime(&create_time)));
4651 DEBUG(5,("access: %s ", ctime(&atime)));
4652 DEBUG(5,("write: %s ", ctime(&mtime)));
4653 DEBUG(5,("change: %s ", ctime(&c_time)));
4654 DEBUG(5,("mode: %x\n", mode));
4655 break;
4657 case SMB_FILE_STANDARD_INFORMATION:
4658 case SMB_QUERY_FILE_STANDARD_INFO:
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4661 data_size = 24;
4662 SOFF_T(pdata,0,allocation_size);
4663 SOFF_T(pdata,8,file_size);
4664 SIVAL(pdata,16,nlink);
4665 SCVAL(pdata,20,delete_pending?1:0);
4666 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4667 SSVAL(pdata,22,0); /* Padding. */
4668 break;
4670 case SMB_FILE_EA_INFORMATION:
4671 case SMB_QUERY_FILE_EA_INFO:
4673 unsigned int ea_size =
4674 estimate_ea_size(conn, fsp, smb_fname);
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4676 data_size = 4;
4677 SIVAL(pdata,0,ea_size);
4678 break;
4681 /* Get the 8.3 name - used if NT SMB was negotiated. */
4682 case SMB_QUERY_FILE_ALT_NAME_INFO:
4683 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4685 int len;
4686 char mangled_name[13];
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4688 if (!name_to_8_3(base_name,mangled_name,
4689 True,conn->params)) {
4690 return NT_STATUS_NO_MEMORY;
4692 len = srvstr_push(dstart, flags2,
4693 pdata+4, mangled_name,
4694 PTR_DIFF(dend, pdata+4),
4695 STR_UNICODE);
4696 data_size = 4 + len;
4697 SIVAL(pdata,0,len);
4698 break;
4701 case SMB_QUERY_FILE_NAME_INFO:
4703 int len;
4705 this must be *exactly* right for ACLs on mapped drives to work
4707 len = srvstr_push(dstart, flags2,
4708 pdata+4, dos_fname,
4709 PTR_DIFF(dend, pdata+4),
4710 STR_UNICODE);
4711 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4712 data_size = 4 + len;
4713 SIVAL(pdata,0,len);
4714 break;
4717 case SMB_FILE_ALLOCATION_INFORMATION:
4718 case SMB_QUERY_FILE_ALLOCATION_INFO:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4720 data_size = 8;
4721 SOFF_T(pdata,0,allocation_size);
4722 break;
4724 case SMB_FILE_END_OF_FILE_INFORMATION:
4725 case SMB_QUERY_FILE_END_OF_FILEINFO:
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4727 data_size = 8;
4728 SOFF_T(pdata,0,file_size);
4729 break;
4731 case SMB_QUERY_FILE_ALL_INFO:
4732 case SMB_FILE_ALL_INFORMATION:
4734 int len;
4735 unsigned int ea_size =
4736 estimate_ea_size(conn, fsp, smb_fname);
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4738 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4739 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4740 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4741 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4742 SIVAL(pdata,32,mode);
4743 SIVAL(pdata,36,0); /* padding. */
4744 pdata += 40;
4745 SOFF_T(pdata,0,allocation_size);
4746 SOFF_T(pdata,8,file_size);
4747 SIVAL(pdata,16,nlink);
4748 SCVAL(pdata,20,delete_pending);
4749 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4750 SSVAL(pdata,22,0);
4751 pdata += 24;
4752 SIVAL(pdata,0,ea_size);
4753 pdata += 4; /* EA info */
4754 len = srvstr_push(dstart, flags2,
4755 pdata+4, dos_fname,
4756 PTR_DIFF(dend, pdata+4),
4757 STR_UNICODE);
4758 SIVAL(pdata,0,len);
4759 pdata += 4 + len;
4760 data_size = PTR_DIFF(pdata,(*ppdata));
4761 break;
4764 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4766 int len;
4767 unsigned int ea_size =
4768 estimate_ea_size(conn, fsp, smb_fname);
4769 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4770 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4771 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4772 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4773 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4774 SIVAL(pdata, 0x20, mode);
4775 SIVAL(pdata, 0x24, 0); /* padding. */
4776 SBVAL(pdata, 0x28, allocation_size);
4777 SBVAL(pdata, 0x30, file_size);
4778 SIVAL(pdata, 0x38, nlink);
4779 SCVAL(pdata, 0x3C, delete_pending);
4780 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4781 SSVAL(pdata, 0x3E, 0); /* padding */
4782 SBVAL(pdata, 0x40, file_index);
4783 SIVAL(pdata, 0x48, ea_size);
4784 SIVAL(pdata, 0x4C, access_mask);
4785 SBVAL(pdata, 0x50, pos);
4786 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4787 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4789 pdata += 0x60;
4791 len = srvstr_push(dstart, flags2,
4792 pdata+4, dos_fname,
4793 PTR_DIFF(dend, pdata+4),
4794 STR_UNICODE);
4795 SIVAL(pdata,0,len);
4796 pdata += 4 + len;
4797 data_size = PTR_DIFF(pdata,(*ppdata));
4798 break;
4800 case SMB_FILE_INTERNAL_INFORMATION:
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4803 SBVAL(pdata, 0, file_index);
4804 data_size = 8;
4805 break;
4807 case SMB_FILE_ACCESS_INFORMATION:
4808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4809 SIVAL(pdata, 0, access_mask);
4810 data_size = 4;
4811 break;
4813 case SMB_FILE_NAME_INFORMATION:
4814 /* Pathname with leading '\'. */
4816 size_t byte_len;
4817 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4818 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4819 SIVAL(pdata,0,byte_len);
4820 data_size = 4 + byte_len;
4821 break;
4824 case SMB_FILE_DISPOSITION_INFORMATION:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4826 data_size = 1;
4827 SCVAL(pdata,0,delete_pending);
4828 break;
4830 case SMB_FILE_POSITION_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4832 data_size = 8;
4833 SOFF_T(pdata,0,pos);
4834 break;
4836 case SMB_FILE_MODE_INFORMATION:
4837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4838 SIVAL(pdata,0,mode);
4839 data_size = 4;
4840 break;
4842 case SMB_FILE_ALIGNMENT_INFORMATION:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4844 SIVAL(pdata,0,0); /* No alignment needed. */
4845 data_size = 4;
4846 break;
4849 * NT4 server just returns "invalid query" to this - if we try
4850 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4851 * want this. JRA.
4853 /* The first statement above is false - verified using Thursby
4854 * client against NT4 -- gcolley.
4856 case SMB_QUERY_FILE_STREAM_INFO:
4857 case SMB_FILE_STREAM_INFORMATION: {
4858 unsigned int num_streams = 0;
4859 struct stream_struct *streams = NULL;
4861 DEBUG(10,("smbd_do_qfilepathinfo: "
4862 "SMB_FILE_STREAM_INFORMATION\n"));
4864 if (is_ntfs_stream_smb_fname(smb_fname)) {
4865 return NT_STATUS_INVALID_PARAMETER;
4868 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4869 talloc_tos(), &num_streams, &streams);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 DEBUG(10, ("could not get stream info: %s\n",
4873 nt_errstr(status)));
4874 return status;
4877 status = marshall_stream_info(num_streams, streams,
4878 pdata, max_data_bytes,
4879 &data_size);
4881 if (!NT_STATUS_IS_OK(status)) {
4882 DEBUG(10, ("marshall_stream_info failed: %s\n",
4883 nt_errstr(status)));
4884 TALLOC_FREE(streams);
4885 return status;
4888 TALLOC_FREE(streams);
4890 break;
4892 case SMB_QUERY_COMPRESSION_INFO:
4893 case SMB_FILE_COMPRESSION_INFORMATION:
4894 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4895 SOFF_T(pdata,0,file_size);
4896 SIVAL(pdata,8,0); /* ??? */
4897 SIVAL(pdata,12,0); /* ??? */
4898 data_size = 16;
4899 break;
4901 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4902 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4903 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4904 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4905 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4906 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4907 SOFF_T(pdata,32,allocation_size);
4908 SOFF_T(pdata,40,file_size);
4909 SIVAL(pdata,48,mode);
4910 SIVAL(pdata,52,0); /* ??? */
4911 data_size = 56;
4912 break;
4914 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4915 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4916 SIVAL(pdata,0,mode);
4917 SIVAL(pdata,4,0);
4918 data_size = 8;
4919 break;
4922 * CIFS UNIX Extensions.
4925 case SMB_QUERY_FILE_UNIX_BASIC:
4927 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4928 data_size = PTR_DIFF(pdata,(*ppdata));
4930 DEBUG(4,("smbd_do_qfilepathinfo: "
4931 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4932 dump_data(4, (uint8_t *)(*ppdata), data_size);
4934 break;
4936 case SMB_QUERY_FILE_UNIX_INFO2:
4938 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4939 data_size = PTR_DIFF(pdata,(*ppdata));
4942 int i;
4943 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4945 for (i=0; i<100; i++)
4946 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4947 DEBUG(4,("\n"));
4950 break;
4952 case SMB_QUERY_FILE_UNIX_LINK:
4954 int len;
4955 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4957 if (!buffer) {
4958 return NT_STATUS_NO_MEMORY;
4961 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4962 #ifdef S_ISLNK
4963 if(!S_ISLNK(psbuf->st_ex_mode)) {
4964 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4966 #else
4967 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4968 #endif
4969 len = SMB_VFS_READLINK(conn,
4970 smb_fname->base_name,
4971 buffer, PATH_MAX);
4972 if (len == -1) {
4973 return map_nt_error_from_unix(errno);
4975 buffer[len] = 0;
4976 len = srvstr_push(dstart, flags2,
4977 pdata, buffer,
4978 PTR_DIFF(dend, pdata),
4979 STR_TERMINATE);
4980 pdata += len;
4981 data_size = PTR_DIFF(pdata,(*ppdata));
4983 break;
4986 #if defined(HAVE_POSIX_ACLS)
4987 case SMB_QUERY_POSIX_ACL:
4989 SMB_ACL_T file_acl = NULL;
4990 SMB_ACL_T def_acl = NULL;
4991 uint16 num_file_acls = 0;
4992 uint16 num_def_acls = 0;
4994 if (fsp && fsp->fh->fd != -1) {
4995 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4996 talloc_tos());
4997 } else {
4998 file_acl =
4999 SMB_VFS_SYS_ACL_GET_FILE(conn,
5000 smb_fname->base_name,
5001 SMB_ACL_TYPE_ACCESS,
5002 talloc_tos());
5005 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5006 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5007 "not implemented on "
5008 "filesystem containing %s\n",
5009 smb_fname->base_name));
5010 return NT_STATUS_NOT_IMPLEMENTED;
5013 if (S_ISDIR(psbuf->st_ex_mode)) {
5014 if (fsp && fsp->is_directory) {
5015 def_acl =
5016 SMB_VFS_SYS_ACL_GET_FILE(
5017 conn,
5018 fsp->fsp_name->base_name,
5019 SMB_ACL_TYPE_DEFAULT,
5020 talloc_tos());
5021 } else {
5022 def_acl =
5023 SMB_VFS_SYS_ACL_GET_FILE(
5024 conn,
5025 smb_fname->base_name,
5026 SMB_ACL_TYPE_DEFAULT,
5027 talloc_tos());
5029 def_acl = free_empty_sys_acl(conn, def_acl);
5032 num_file_acls = count_acl_entries(conn, file_acl);
5033 num_def_acls = count_acl_entries(conn, def_acl);
5035 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5036 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5037 data_size,
5038 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5039 SMB_POSIX_ACL_HEADER_SIZE) ));
5040 if (file_acl) {
5041 TALLOC_FREE(file_acl);
5043 if (def_acl) {
5044 TALLOC_FREE(def_acl);
5046 return NT_STATUS_BUFFER_TOO_SMALL;
5049 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5050 SSVAL(pdata,2,num_file_acls);
5051 SSVAL(pdata,4,num_def_acls);
5052 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5053 if (file_acl) {
5054 TALLOC_FREE(file_acl);
5056 if (def_acl) {
5057 TALLOC_FREE(def_acl);
5059 return NT_STATUS_INTERNAL_ERROR;
5061 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5062 if (file_acl) {
5063 TALLOC_FREE(file_acl);
5065 if (def_acl) {
5066 TALLOC_FREE(def_acl);
5068 return NT_STATUS_INTERNAL_ERROR;
5071 if (file_acl) {
5072 TALLOC_FREE(file_acl);
5074 if (def_acl) {
5075 TALLOC_FREE(def_acl);
5077 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5078 break;
5080 #endif
5083 case SMB_QUERY_POSIX_LOCK:
5085 uint64_t count;
5086 uint64_t offset;
5087 uint64_t smblctx;
5088 enum brl_type lock_type;
5090 /* We need an open file with a real fd for this. */
5091 if (!fsp || fsp->fh->fd == -1) {
5092 return NT_STATUS_INVALID_LEVEL;
5095 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5096 return NT_STATUS_INVALID_PARAMETER;
5099 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5100 case POSIX_LOCK_TYPE_READ:
5101 lock_type = READ_LOCK;
5102 break;
5103 case POSIX_LOCK_TYPE_WRITE:
5104 lock_type = WRITE_LOCK;
5105 break;
5106 case POSIX_LOCK_TYPE_UNLOCK:
5107 default:
5108 /* There's no point in asking for an unlock... */
5109 return NT_STATUS_INVALID_PARAMETER;
5112 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5113 #if defined(HAVE_LONGLONG)
5114 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5115 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5116 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5117 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5118 #else /* HAVE_LONGLONG */
5119 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5120 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5121 #endif /* HAVE_LONGLONG */
5123 status = query_lock(fsp,
5124 &smblctx,
5125 &count,
5126 &offset,
5127 &lock_type,
5128 POSIX_LOCK);
5130 if (ERROR_WAS_LOCK_DENIED(status)) {
5131 /* Here we need to report who has it locked... */
5132 data_size = POSIX_LOCK_DATA_SIZE;
5134 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5135 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5136 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5137 #if defined(HAVE_LONGLONG)
5138 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5139 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5140 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5141 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5142 #else /* HAVE_LONGLONG */
5143 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5144 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5145 #endif /* HAVE_LONGLONG */
5147 } else if (NT_STATUS_IS_OK(status)) {
5148 /* For success we just return a copy of what we sent
5149 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5150 data_size = POSIX_LOCK_DATA_SIZE;
5151 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5152 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5153 } else {
5154 return status;
5156 break;
5159 default:
5160 return NT_STATUS_INVALID_LEVEL;
5163 *pdata_size = data_size;
5164 return NT_STATUS_OK;
5167 /****************************************************************************
5168 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5169 file name or file id).
5170 ****************************************************************************/
5172 static void call_trans2qfilepathinfo(connection_struct *conn,
5173 struct smb_request *req,
5174 unsigned int tran_call,
5175 char **pparams, int total_params,
5176 char **ppdata, int total_data,
5177 unsigned int max_data_bytes)
5179 char *params = *pparams;
5180 char *pdata = *ppdata;
5181 uint16 info_level;
5182 unsigned int data_size = 0;
5183 unsigned int param_size = 2;
5184 struct smb_filename *smb_fname = NULL;
5185 bool delete_pending = False;
5186 struct timespec write_time_ts;
5187 files_struct *fsp = NULL;
5188 struct file_id fileid;
5189 struct ea_list *ea_list = NULL;
5190 int lock_data_count = 0;
5191 char *lock_data = NULL;
5192 NTSTATUS status = NT_STATUS_OK;
5194 if (!params) {
5195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5196 return;
5199 ZERO_STRUCT(write_time_ts);
5201 if (tran_call == TRANSACT2_QFILEINFO) {
5202 if (total_params < 4) {
5203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5204 return;
5207 if (IS_IPC(conn)) {
5208 call_trans2qpipeinfo(conn, req, tran_call,
5209 pparams, total_params,
5210 ppdata, total_data,
5211 max_data_bytes);
5212 return;
5215 fsp = file_fsp(req, SVAL(params,0));
5216 info_level = SVAL(params,2);
5218 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5220 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5221 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5222 return;
5225 /* Initial check for valid fsp ptr. */
5226 if (!check_fsp_open(conn, req, fsp)) {
5227 return;
5230 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5231 if (smb_fname == NULL) {
5232 reply_nterror(req, NT_STATUS_NO_MEMORY);
5233 return;
5236 if(fsp->fake_file_handle) {
5238 * This is actually for the QUOTA_FAKE_FILE --metze
5241 /* We know this name is ok, it's already passed the checks. */
5243 } else if(fsp->fh->fd == -1) {
5245 * This is actually a QFILEINFO on a directory
5246 * handle (returned from an NT SMB). NT5.0 seems
5247 * to do this call. JRA.
5250 if (INFO_LEVEL_IS_UNIX(info_level)) {
5251 /* Always do lstat for UNIX calls. */
5252 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5253 DEBUG(3,("call_trans2qfilepathinfo: "
5254 "SMB_VFS_LSTAT of %s failed "
5255 "(%s)\n",
5256 smb_fname_str_dbg(smb_fname),
5257 strerror(errno)));
5258 reply_nterror(req,
5259 map_nt_error_from_unix(errno));
5260 return;
5262 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5263 DEBUG(3,("call_trans2qfilepathinfo: "
5264 "SMB_VFS_STAT of %s failed (%s)\n",
5265 smb_fname_str_dbg(smb_fname),
5266 strerror(errno)));
5267 reply_nterror(req,
5268 map_nt_error_from_unix(errno));
5269 return;
5272 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5273 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5274 } else {
5276 * Original code - this is an open file.
5278 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5279 DEBUG(3, ("fstat of %s failed (%s)\n",
5280 fsp_fnum_dbg(fsp), strerror(errno)));
5281 reply_nterror(req,
5282 map_nt_error_from_unix(errno));
5283 return;
5285 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5286 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5289 } else {
5290 uint32_t name_hash;
5291 char *fname = NULL;
5292 uint32_t ucf_flags = 0;
5294 /* qpathinfo */
5295 if (total_params < 7) {
5296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5297 return;
5300 info_level = SVAL(params,0);
5302 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5304 if (INFO_LEVEL_IS_UNIX(info_level)) {
5305 if (!lp_unix_extensions()) {
5306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5307 return;
5309 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5310 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5311 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5312 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5316 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5317 total_params - 6,
5318 STR_TERMINATE, &status);
5319 if (!NT_STATUS_IS_OK(status)) {
5320 reply_nterror(req, status);
5321 return;
5324 status = filename_convert(req,
5325 conn,
5326 req->flags2 & FLAGS2_DFS_PATHNAMES,
5327 fname,
5328 ucf_flags,
5329 NULL,
5330 &smb_fname);
5331 if (!NT_STATUS_IS_OK(status)) {
5332 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5333 reply_botherror(req,
5334 NT_STATUS_PATH_NOT_COVERED,
5335 ERRSRV, ERRbadpath);
5336 return;
5338 reply_nterror(req, status);
5339 return;
5342 /* If this is a stream, check if there is a delete_pending. */
5343 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5344 && is_ntfs_stream_smb_fname(smb_fname)) {
5345 struct smb_filename *smb_fname_base;
5347 /* Create an smb_filename with stream_name == NULL. */
5348 smb_fname_base = synthetic_smb_fname(
5349 talloc_tos(), smb_fname->base_name,
5350 NULL, NULL);
5351 if (smb_fname_base == NULL) {
5352 reply_nterror(req, NT_STATUS_NO_MEMORY);
5353 return;
5356 if (INFO_LEVEL_IS_UNIX(info_level)) {
5357 /* Always do lstat for UNIX calls. */
5358 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5359 DEBUG(3,("call_trans2qfilepathinfo: "
5360 "SMB_VFS_LSTAT of %s failed "
5361 "(%s)\n",
5362 smb_fname_str_dbg(smb_fname_base),
5363 strerror(errno)));
5364 TALLOC_FREE(smb_fname_base);
5365 reply_nterror(req,
5366 map_nt_error_from_unix(errno));
5367 return;
5369 } else {
5370 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5371 DEBUG(3,("call_trans2qfilepathinfo: "
5372 "fileinfo of %s failed "
5373 "(%s)\n",
5374 smb_fname_str_dbg(smb_fname_base),
5375 strerror(errno)));
5376 TALLOC_FREE(smb_fname_base);
5377 reply_nterror(req,
5378 map_nt_error_from_unix(errno));
5379 return;
5383 status = file_name_hash(conn,
5384 smb_fname_str_dbg(smb_fname_base),
5385 &name_hash);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 TALLOC_FREE(smb_fname_base);
5388 reply_nterror(req, status);
5389 return;
5392 fileid = vfs_file_id_from_sbuf(conn,
5393 &smb_fname_base->st);
5394 TALLOC_FREE(smb_fname_base);
5395 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5396 if (delete_pending) {
5397 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5398 return;
5402 if (INFO_LEVEL_IS_UNIX(info_level)) {
5403 /* Always do lstat for UNIX calls. */
5404 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5405 DEBUG(3,("call_trans2qfilepathinfo: "
5406 "SMB_VFS_LSTAT of %s failed (%s)\n",
5407 smb_fname_str_dbg(smb_fname),
5408 strerror(errno)));
5409 reply_nterror(req,
5410 map_nt_error_from_unix(errno));
5411 return;
5414 } else {
5415 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5416 DEBUG(3,("call_trans2qfilepathinfo: "
5417 "SMB_VFS_STAT of %s failed (%s)\n",
5418 smb_fname_str_dbg(smb_fname),
5419 strerror(errno)));
5420 reply_nterror(req,
5421 map_nt_error_from_unix(errno));
5422 return;
5426 status = file_name_hash(conn,
5427 smb_fname_str_dbg(smb_fname),
5428 &name_hash);
5429 if (!NT_STATUS_IS_OK(status)) {
5430 reply_nterror(req, status);
5431 return;
5434 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5435 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5436 if (delete_pending) {
5437 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5438 return;
5442 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5443 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5444 fsp_fnum_dbg(fsp),
5445 info_level,tran_call,total_data));
5447 /* Pull out any data sent here before we realloc. */
5448 switch (info_level) {
5449 case SMB_INFO_QUERY_EAS_FROM_LIST:
5451 /* Pull any EA list from the data portion. */
5452 uint32 ea_size;
5454 if (total_data < 4) {
5455 reply_nterror(
5456 req, NT_STATUS_INVALID_PARAMETER);
5457 return;
5459 ea_size = IVAL(pdata,0);
5461 if (total_data > 0 && ea_size != total_data) {
5462 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5463 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5464 reply_nterror(
5465 req, NT_STATUS_INVALID_PARAMETER);
5466 return;
5469 if (!lp_ea_support(SNUM(conn))) {
5470 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5471 return;
5474 /* Pull out the list of names. */
5475 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5476 if (!ea_list) {
5477 reply_nterror(
5478 req, NT_STATUS_INVALID_PARAMETER);
5479 return;
5481 break;
5484 case SMB_QUERY_POSIX_LOCK:
5486 if (fsp == NULL || fsp->fh->fd == -1) {
5487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5488 return;
5491 if (total_data != POSIX_LOCK_DATA_SIZE) {
5492 reply_nterror(
5493 req, NT_STATUS_INVALID_PARAMETER);
5494 return;
5497 /* Copy the lock range data. */
5498 lock_data = (char *)talloc_memdup(
5499 req, pdata, total_data);
5500 if (!lock_data) {
5501 reply_nterror(req, NT_STATUS_NO_MEMORY);
5502 return;
5504 lock_data_count = total_data;
5506 default:
5507 break;
5510 *pparams = (char *)SMB_REALLOC(*pparams,2);
5511 if (*pparams == NULL) {
5512 reply_nterror(req, NT_STATUS_NO_MEMORY);
5513 return;
5515 params = *pparams;
5516 SSVAL(params,0,0);
5519 * draft-leach-cifs-v1-spec-02.txt
5520 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5521 * says:
5523 * The requested information is placed in the Data portion of the
5524 * transaction response. For the information levels greater than 0x100,
5525 * the transaction response has 1 parameter word which should be
5526 * ignored by the client.
5528 * However Windows only follows this rule for the IS_NAME_VALID call.
5530 switch (info_level) {
5531 case SMB_INFO_IS_NAME_VALID:
5532 param_size = 0;
5533 break;
5536 if ((info_level & 0xFF00) == 0xFF00) {
5538 * We use levels that start with 0xFF00
5539 * internally to represent SMB2 specific levels
5541 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5542 return;
5545 status = smbd_do_qfilepathinfo(conn, req, info_level,
5546 fsp, smb_fname,
5547 delete_pending, write_time_ts,
5548 ea_list,
5549 lock_data_count, lock_data,
5550 req->flags2, max_data_bytes,
5551 ppdata, &data_size);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 reply_nterror(req, status);
5554 return;
5557 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5558 max_data_bytes);
5560 return;
5563 /****************************************************************************
5564 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5565 code.
5566 ****************************************************************************/
5568 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5569 connection_struct *conn,
5570 struct smb_request *req,
5571 bool overwrite_if_exists,
5572 const struct smb_filename *smb_fname_old,
5573 struct smb_filename *smb_fname_new)
5575 NTSTATUS status = NT_STATUS_OK;
5577 /* source must already exist. */
5578 if (!VALID_STAT(smb_fname_old->st)) {
5579 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5582 if (VALID_STAT(smb_fname_new->st)) {
5583 if (overwrite_if_exists) {
5584 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5585 return NT_STATUS_FILE_IS_A_DIRECTORY;
5587 status = unlink_internals(conn,
5588 req,
5589 FILE_ATTRIBUTE_NORMAL,
5590 smb_fname_new,
5591 false);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 return status;
5595 } else {
5596 /* Disallow if newname already exists. */
5597 return NT_STATUS_OBJECT_NAME_COLLISION;
5601 /* No links from a directory. */
5602 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5603 return NT_STATUS_FILE_IS_A_DIRECTORY;
5606 /* Setting a hardlink to/from a stream isn't currently supported. */
5607 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5608 is_ntfs_stream_smb_fname(smb_fname_new)) {
5609 return NT_STATUS_INVALID_PARAMETER;
5612 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5613 smb_fname_old->base_name, smb_fname_new->base_name));
5615 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5616 smb_fname_new->base_name) != 0) {
5617 status = map_nt_error_from_unix(errno);
5618 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5619 nt_errstr(status), smb_fname_old->base_name,
5620 smb_fname_new->base_name));
5622 return status;
5625 /****************************************************************************
5626 Deal with setting the time from any of the setfilepathinfo functions.
5627 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5628 calling this function.
5629 ****************************************************************************/
5631 NTSTATUS smb_set_file_time(connection_struct *conn,
5632 files_struct *fsp,
5633 const struct smb_filename *smb_fname,
5634 struct smb_file_time *ft,
5635 bool setting_write_time)
5637 struct smb_filename smb_fname_base;
5638 uint32 action =
5639 FILE_NOTIFY_CHANGE_LAST_ACCESS
5640 |FILE_NOTIFY_CHANGE_LAST_WRITE
5641 |FILE_NOTIFY_CHANGE_CREATION;
5643 if (!VALID_STAT(smb_fname->st)) {
5644 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5647 /* get some defaults (no modifications) if any info is zero or -1. */
5648 if (null_timespec(ft->create_time)) {
5649 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5652 if (null_timespec(ft->atime)) {
5653 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5656 if (null_timespec(ft->mtime)) {
5657 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5660 if (!setting_write_time) {
5661 /* ft->mtime comes from change time, not write time. */
5662 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5665 /* Ensure the resolution is the correct for
5666 * what we can store on this filesystem. */
5668 round_timespec(conn->ts_res, &ft->create_time);
5669 round_timespec(conn->ts_res, &ft->ctime);
5670 round_timespec(conn->ts_res, &ft->atime);
5671 round_timespec(conn->ts_res, &ft->mtime);
5673 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5674 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5675 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5676 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5677 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5678 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5679 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5680 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5682 if (setting_write_time) {
5684 * This was a Windows setfileinfo on an open file.
5685 * NT does this a lot. We also need to
5686 * set the time here, as it can be read by
5687 * FindFirst/FindNext and with the patch for bug #2045
5688 * in smbd/fileio.c it ensures that this timestamp is
5689 * kept sticky even after a write. We save the request
5690 * away and will set it on file close and after a write. JRA.
5693 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5694 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5696 if (fsp != NULL) {
5697 if (fsp->base_fsp) {
5698 set_sticky_write_time_fsp(fsp->base_fsp,
5699 ft->mtime);
5700 } else {
5701 set_sticky_write_time_fsp(fsp, ft->mtime);
5703 } else {
5704 set_sticky_write_time_path(
5705 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5706 ft->mtime);
5710 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5712 /* Always call ntimes on the base, even if a stream was passed in. */
5713 smb_fname_base = *smb_fname;
5714 smb_fname_base.stream_name = NULL;
5716 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5717 return map_nt_error_from_unix(errno);
5720 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5721 smb_fname->base_name);
5722 return NT_STATUS_OK;
5725 /****************************************************************************
5726 Deal with setting the dosmode from any of the setfilepathinfo functions.
5727 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5728 done before calling this function.
5729 ****************************************************************************/
5731 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5732 const struct smb_filename *smb_fname,
5733 uint32 dosmode)
5735 struct smb_filename *smb_fname_base;
5736 NTSTATUS status;
5738 if (!VALID_STAT(smb_fname->st)) {
5739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5742 /* Always operate on the base_name, even if a stream was passed in. */
5743 smb_fname_base = synthetic_smb_fname(
5744 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5745 if (smb_fname_base == NULL) {
5746 return NT_STATUS_NO_MEMORY;
5749 if (dosmode) {
5750 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5751 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5752 } else {
5753 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5757 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5759 /* check the mode isn't different, before changing it */
5760 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5761 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5762 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5763 (unsigned int)dosmode));
5765 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5766 false)) {
5767 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5768 "%s failed (%s)\n",
5769 smb_fname_str_dbg(smb_fname_base),
5770 strerror(errno)));
5771 status = map_nt_error_from_unix(errno);
5772 goto out;
5775 status = NT_STATUS_OK;
5776 out:
5777 TALLOC_FREE(smb_fname_base);
5778 return status;
5781 /****************************************************************************
5782 Deal with setting the size from any of the setfilepathinfo functions.
5783 ****************************************************************************/
5785 static NTSTATUS smb_set_file_size(connection_struct *conn,
5786 struct smb_request *req,
5787 files_struct *fsp,
5788 const struct smb_filename *smb_fname,
5789 const SMB_STRUCT_STAT *psbuf,
5790 off_t size,
5791 bool fail_after_createfile)
5793 NTSTATUS status = NT_STATUS_OK;
5794 struct smb_filename *smb_fname_tmp = NULL;
5795 files_struct *new_fsp = NULL;
5797 if (!VALID_STAT(*psbuf)) {
5798 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5801 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5803 if (size == get_file_size_stat(psbuf)) {
5804 return NT_STATUS_OK;
5807 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5808 smb_fname_str_dbg(smb_fname), (double)size));
5810 if (fsp && fsp->fh->fd != -1) {
5811 /* Handle based call. */
5812 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5813 return NT_STATUS_ACCESS_DENIED;
5816 if (vfs_set_filelen(fsp, size) == -1) {
5817 return map_nt_error_from_unix(errno);
5819 trigger_write_time_update_immediate(fsp);
5820 return NT_STATUS_OK;
5823 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5824 if (smb_fname_tmp == NULL) {
5825 return NT_STATUS_NO_MEMORY;
5828 smb_fname_tmp->st = *psbuf;
5830 status = SMB_VFS_CREATE_FILE(
5831 conn, /* conn */
5832 req, /* req */
5833 0, /* root_dir_fid */
5834 smb_fname_tmp, /* fname */
5835 FILE_WRITE_DATA, /* access_mask */
5836 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5837 FILE_SHARE_DELETE),
5838 FILE_OPEN, /* create_disposition*/
5839 0, /* create_options */
5840 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5841 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5842 0, /* allocation_size */
5843 0, /* private_flags */
5844 NULL, /* sd */
5845 NULL, /* ea_list */
5846 &new_fsp, /* result */
5847 NULL); /* pinfo */
5849 TALLOC_FREE(smb_fname_tmp);
5851 if (!NT_STATUS_IS_OK(status)) {
5852 /* NB. We check for open_was_deferred in the caller. */
5853 return status;
5856 /* See RAW-SFILEINFO-END-OF-FILE */
5857 if (fail_after_createfile) {
5858 close_file(req, new_fsp,NORMAL_CLOSE);
5859 return NT_STATUS_INVALID_LEVEL;
5862 if (vfs_set_filelen(new_fsp, size) == -1) {
5863 status = map_nt_error_from_unix(errno);
5864 close_file(req, new_fsp,NORMAL_CLOSE);
5865 return status;
5868 trigger_write_time_update_immediate(new_fsp);
5869 close_file(req, new_fsp,NORMAL_CLOSE);
5870 return NT_STATUS_OK;
5873 /****************************************************************************
5874 Deal with SMB_INFO_SET_EA.
5875 ****************************************************************************/
5877 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5878 const char *pdata,
5879 int total_data,
5880 files_struct *fsp,
5881 const struct smb_filename *smb_fname)
5883 struct ea_list *ea_list = NULL;
5884 TALLOC_CTX *ctx = NULL;
5885 NTSTATUS status = NT_STATUS_OK;
5887 if (total_data < 10) {
5889 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5890 length. They seem to have no effect. Bug #3212. JRA */
5892 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5893 /* We're done. We only get EA info in this call. */
5894 return NT_STATUS_OK;
5897 return NT_STATUS_INVALID_PARAMETER;
5900 if (IVAL(pdata,0) > total_data) {
5901 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5902 IVAL(pdata,0), (unsigned int)total_data));
5903 return NT_STATUS_INVALID_PARAMETER;
5906 ctx = talloc_tos();
5907 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5908 if (!ea_list) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 status = set_ea(conn, fsp, smb_fname, ea_list);
5914 return status;
5917 /****************************************************************************
5918 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5919 ****************************************************************************/
5921 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5922 const char *pdata,
5923 int total_data,
5924 files_struct *fsp)
5926 struct ea_list *ea_list = NULL;
5927 NTSTATUS status;
5929 if (!fsp) {
5930 return NT_STATUS_INVALID_HANDLE;
5933 if (!lp_ea_support(SNUM(conn))) {
5934 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5935 "EA's not supported.\n",
5936 (unsigned int)total_data));
5937 return NT_STATUS_EAS_NOT_SUPPORTED;
5940 if (total_data < 10) {
5941 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5942 "too small.\n",
5943 (unsigned int)total_data));
5944 return NT_STATUS_INVALID_PARAMETER;
5947 ea_list = read_nttrans_ea_list(talloc_tos(),
5948 pdata,
5949 total_data);
5951 if (!ea_list) {
5952 return NT_STATUS_INVALID_PARAMETER;
5955 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5957 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5958 smb_fname_str_dbg(fsp->fsp_name),
5959 nt_errstr(status) ));
5961 return status;
5965 /****************************************************************************
5966 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5967 ****************************************************************************/
5969 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5970 const char *pdata,
5971 int total_data,
5972 files_struct *fsp,
5973 struct smb_filename *smb_fname)
5975 NTSTATUS status = NT_STATUS_OK;
5976 bool delete_on_close;
5977 uint32 dosmode = 0;
5979 if (total_data < 1) {
5980 return NT_STATUS_INVALID_PARAMETER;
5983 if (fsp == NULL) {
5984 return NT_STATUS_INVALID_HANDLE;
5987 delete_on_close = (CVAL(pdata,0) ? True : False);
5988 dosmode = dos_mode(conn, smb_fname);
5990 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5991 "delete_on_close = %u\n",
5992 smb_fname_str_dbg(smb_fname),
5993 (unsigned int)dosmode,
5994 (unsigned int)delete_on_close ));
5996 if (delete_on_close) {
5997 status = can_set_delete_on_close(fsp, dosmode);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 return status;
6003 /* The set is across all open files on this dev/inode pair. */
6004 if (!set_delete_on_close(fsp, delete_on_close,
6005 conn->session_info->security_token,
6006 conn->session_info->unix_token)) {
6007 return NT_STATUS_ACCESS_DENIED;
6009 return NT_STATUS_OK;
6012 /****************************************************************************
6013 Deal with SMB_FILE_POSITION_INFORMATION.
6014 ****************************************************************************/
6016 static NTSTATUS smb_file_position_information(connection_struct *conn,
6017 const char *pdata,
6018 int total_data,
6019 files_struct *fsp)
6021 uint64_t position_information;
6023 if (total_data < 8) {
6024 return NT_STATUS_INVALID_PARAMETER;
6027 if (fsp == NULL) {
6028 /* Ignore on pathname based set. */
6029 return NT_STATUS_OK;
6032 position_information = (uint64_t)IVAL(pdata,0);
6033 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6035 DEBUG(10,("smb_file_position_information: Set file position "
6036 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6037 (double)position_information));
6038 fsp->fh->position_information = position_information;
6039 return NT_STATUS_OK;
6042 /****************************************************************************
6043 Deal with SMB_FILE_MODE_INFORMATION.
6044 ****************************************************************************/
6046 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6047 const char *pdata,
6048 int total_data)
6050 uint32 mode;
6052 if (total_data < 4) {
6053 return NT_STATUS_INVALID_PARAMETER;
6055 mode = IVAL(pdata,0);
6056 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6057 return NT_STATUS_INVALID_PARAMETER;
6059 return NT_STATUS_OK;
6062 /****************************************************************************
6063 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6064 ****************************************************************************/
6066 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6067 struct smb_request *req,
6068 const char *pdata,
6069 int total_data,
6070 const struct smb_filename *smb_fname)
6072 char *link_target = NULL;
6073 const char *newname = smb_fname->base_name;
6074 TALLOC_CTX *ctx = talloc_tos();
6076 /* Set a symbolic link. */
6077 /* Don't allow this if follow links is false. */
6079 if (total_data == 0) {
6080 return NT_STATUS_INVALID_PARAMETER;
6083 if (!lp_symlinks(SNUM(conn))) {
6084 return NT_STATUS_ACCESS_DENIED;
6087 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6088 total_data, STR_TERMINATE);
6090 if (!link_target) {
6091 return NT_STATUS_INVALID_PARAMETER;
6094 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6095 newname, link_target ));
6097 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6098 return map_nt_error_from_unix(errno);
6101 return NT_STATUS_OK;
6104 /****************************************************************************
6105 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6106 ****************************************************************************/
6108 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6109 struct smb_request *req,
6110 const char *pdata, int total_data,
6111 struct smb_filename *smb_fname_new)
6113 char *oldname = NULL;
6114 struct smb_filename *smb_fname_old = NULL;
6115 TALLOC_CTX *ctx = talloc_tos();
6116 NTSTATUS status = NT_STATUS_OK;
6118 /* Set a hard link. */
6119 if (total_data == 0) {
6120 return NT_STATUS_INVALID_PARAMETER;
6123 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6124 total_data, STR_TERMINATE, &status);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 return status;
6129 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6130 smb_fname_str_dbg(smb_fname_new), oldname));
6132 status = filename_convert(ctx,
6133 conn,
6134 req->flags2 & FLAGS2_DFS_PATHNAMES,
6135 oldname,
6137 NULL,
6138 &smb_fname_old);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 return status;
6143 return hardlink_internals(ctx, conn, req, false,
6144 smb_fname_old, smb_fname_new);
6147 /****************************************************************************
6148 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6149 ****************************************************************************/
6151 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6152 struct smb_request *req,
6153 const char *pdata,
6154 int total_data,
6155 files_struct *fsp,
6156 struct smb_filename *smb_fname_src)
6158 bool overwrite;
6159 uint32_t len;
6160 char *newname = NULL;
6161 struct smb_filename *smb_fname_dst = NULL;
6162 NTSTATUS status = NT_STATUS_OK;
6163 TALLOC_CTX *ctx = talloc_tos();
6165 if (!fsp) {
6166 return NT_STATUS_INVALID_HANDLE;
6169 if (total_data < 20) {
6170 return NT_STATUS_INVALID_PARAMETER;
6173 overwrite = (CVAL(pdata,0) ? True : False);
6174 len = IVAL(pdata,16);
6176 if (len > (total_data - 20) || (len == 0)) {
6177 return NT_STATUS_INVALID_PARAMETER;
6180 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6181 &pdata[20], len, STR_TERMINATE,
6182 &status);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 return status;
6187 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6188 newname));
6190 status = filename_convert(ctx,
6191 conn,
6192 req->flags2 & FLAGS2_DFS_PATHNAMES,
6193 newname,
6194 UCF_SAVE_LCOMP,
6195 NULL,
6196 &smb_fname_dst);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 return status;
6201 if (fsp->base_fsp) {
6202 /* newname must be a stream name. */
6203 if (newname[0] != ':') {
6204 return NT_STATUS_NOT_SUPPORTED;
6207 /* Create an smb_fname to call rename_internals_fsp() with. */
6208 smb_fname_dst = synthetic_smb_fname(
6209 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6210 newname, NULL);
6211 if (smb_fname_dst == NULL) {
6212 status = NT_STATUS_NO_MEMORY;
6213 goto out;
6217 * Set the original last component, since
6218 * rename_internals_fsp() requires it.
6220 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6221 newname);
6222 if (smb_fname_dst->original_lcomp == NULL) {
6223 status = NT_STATUS_NO_MEMORY;
6224 goto out;
6229 DEBUG(10,("smb2_file_rename_information: "
6230 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6231 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6232 smb_fname_str_dbg(smb_fname_dst)));
6233 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6234 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6235 overwrite);
6237 out:
6238 TALLOC_FREE(smb_fname_dst);
6239 return status;
6242 static NTSTATUS smb_file_link_information(connection_struct *conn,
6243 struct smb_request *req,
6244 const char *pdata,
6245 int total_data,
6246 files_struct *fsp,
6247 struct smb_filename *smb_fname_src)
6249 bool overwrite;
6250 uint32_t len;
6251 char *newname = NULL;
6252 struct smb_filename *smb_fname_dst = NULL;
6253 NTSTATUS status = NT_STATUS_OK;
6254 TALLOC_CTX *ctx = talloc_tos();
6256 if (!fsp) {
6257 return NT_STATUS_INVALID_HANDLE;
6260 if (total_data < 20) {
6261 return NT_STATUS_INVALID_PARAMETER;
6264 overwrite = (CVAL(pdata,0) ? true : false);
6265 len = IVAL(pdata,16);
6267 if (len > (total_data - 20) || (len == 0)) {
6268 return NT_STATUS_INVALID_PARAMETER;
6271 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6272 &pdata[20], len, STR_TERMINATE,
6273 &status);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 return status;
6278 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6279 newname));
6281 status = filename_convert(ctx,
6282 conn,
6283 req->flags2 & FLAGS2_DFS_PATHNAMES,
6284 newname,
6285 UCF_SAVE_LCOMP,
6286 NULL,
6287 &smb_fname_dst);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 return status;
6292 if (fsp->base_fsp) {
6293 /* No stream names. */
6294 return NT_STATUS_NOT_SUPPORTED;
6297 DEBUG(10,("smb_file_link_information: "
6298 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6299 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6300 smb_fname_str_dbg(smb_fname_dst)));
6301 status = hardlink_internals(ctx,
6302 conn,
6303 req,
6304 overwrite,
6305 fsp->fsp_name,
6306 smb_fname_dst);
6308 TALLOC_FREE(smb_fname_dst);
6309 return status;
6312 /****************************************************************************
6313 Deal with SMB_FILE_RENAME_INFORMATION.
6314 ****************************************************************************/
6316 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6317 struct smb_request *req,
6318 const char *pdata,
6319 int total_data,
6320 files_struct *fsp,
6321 struct smb_filename *smb_fname_src)
6323 bool overwrite;
6324 uint32 root_fid;
6325 uint32 len;
6326 char *newname = NULL;
6327 struct smb_filename *smb_fname_dst = NULL;
6328 bool dest_has_wcard = False;
6329 NTSTATUS status = NT_STATUS_OK;
6330 char *p;
6331 TALLOC_CTX *ctx = talloc_tos();
6333 if (total_data < 13) {
6334 return NT_STATUS_INVALID_PARAMETER;
6337 overwrite = (CVAL(pdata,0) ? True : False);
6338 root_fid = IVAL(pdata,4);
6339 len = IVAL(pdata,8);
6341 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6342 return NT_STATUS_INVALID_PARAMETER;
6345 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6346 len, 0, &status,
6347 &dest_has_wcard);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 return status;
6352 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6353 newname));
6355 status = resolve_dfspath_wcard(ctx, conn,
6356 req->flags2 & FLAGS2_DFS_PATHNAMES,
6357 newname,
6358 true,
6359 !conn->sconn->using_smb2,
6360 &newname,
6361 &dest_has_wcard);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 return status;
6366 /* Check the new name has no '/' characters. */
6367 if (strchr_m(newname, '/')) {
6368 return NT_STATUS_NOT_SUPPORTED;
6371 if (fsp && fsp->base_fsp) {
6372 /* newname must be a stream name. */
6373 if (newname[0] != ':') {
6374 return NT_STATUS_NOT_SUPPORTED;
6377 /* Create an smb_fname to call rename_internals_fsp() with. */
6378 smb_fname_dst = synthetic_smb_fname(
6379 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6380 newname, NULL);
6381 if (smb_fname_dst == NULL) {
6382 status = NT_STATUS_NO_MEMORY;
6383 goto out;
6387 * Set the original last component, since
6388 * rename_internals_fsp() requires it.
6390 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6391 newname);
6392 if (smb_fname_dst->original_lcomp == NULL) {
6393 status = NT_STATUS_NO_MEMORY;
6394 goto out;
6397 } else {
6399 * Build up an smb_fname_dst based on the filename passed in.
6400 * We basically just strip off the last component, and put on
6401 * the newname instead.
6403 char *base_name = NULL;
6405 /* newname must *not* be a stream name. */
6406 if (newname[0] == ':') {
6407 return NT_STATUS_NOT_SUPPORTED;
6411 * Strip off the last component (filename) of the path passed
6412 * in.
6414 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6415 if (!base_name) {
6416 return NT_STATUS_NO_MEMORY;
6418 p = strrchr_m(base_name, '/');
6419 if (p) {
6420 p[1] = '\0';
6421 } else {
6422 base_name = talloc_strdup(ctx, "");
6423 if (!base_name) {
6424 return NT_STATUS_NO_MEMORY;
6427 /* Append the new name. */
6428 base_name = talloc_asprintf_append(base_name,
6429 "%s",
6430 newname);
6431 if (!base_name) {
6432 return NT_STATUS_NO_MEMORY;
6435 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6436 (UCF_SAVE_LCOMP |
6437 (dest_has_wcard ?
6438 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6439 0)));
6441 /* If an error we expect this to be
6442 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6444 if (!NT_STATUS_IS_OK(status)) {
6445 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6446 status)) {
6447 goto out;
6449 /* Create an smb_fname to call rename_internals_fsp() */
6450 smb_fname_dst = synthetic_smb_fname(
6451 ctx, base_name, NULL, NULL);
6452 if (smb_fname_dst == NULL) {
6453 status = NT_STATUS_NO_MEMORY;
6454 goto out;
6459 if (fsp) {
6460 DEBUG(10,("smb_file_rename_information: "
6461 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6462 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6463 smb_fname_str_dbg(smb_fname_dst)));
6464 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6465 overwrite);
6466 } else {
6467 DEBUG(10,("smb_file_rename_information: "
6468 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6469 smb_fname_str_dbg(smb_fname_src),
6470 smb_fname_str_dbg(smb_fname_dst)));
6471 status = rename_internals(ctx, conn, req, smb_fname_src,
6472 smb_fname_dst, 0, overwrite, false,
6473 dest_has_wcard,
6474 FILE_WRITE_ATTRIBUTES);
6476 out:
6477 TALLOC_FREE(smb_fname_dst);
6478 return status;
6481 /****************************************************************************
6482 Deal with SMB_SET_POSIX_ACL.
6483 ****************************************************************************/
6485 #if defined(HAVE_POSIX_ACLS)
6486 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6487 const char *pdata,
6488 int total_data,
6489 files_struct *fsp,
6490 const struct smb_filename *smb_fname)
6492 uint16 posix_acl_version;
6493 uint16 num_file_acls;
6494 uint16 num_def_acls;
6495 bool valid_file_acls = True;
6496 bool valid_def_acls = True;
6498 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6499 return NT_STATUS_INVALID_PARAMETER;
6501 posix_acl_version = SVAL(pdata,0);
6502 num_file_acls = SVAL(pdata,2);
6503 num_def_acls = SVAL(pdata,4);
6505 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6506 valid_file_acls = False;
6507 num_file_acls = 0;
6510 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6511 valid_def_acls = False;
6512 num_def_acls = 0;
6515 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6516 return NT_STATUS_INVALID_PARAMETER;
6519 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6520 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6521 return NT_STATUS_INVALID_PARAMETER;
6524 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6525 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6526 (unsigned int)num_file_acls,
6527 (unsigned int)num_def_acls));
6529 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6530 smb_fname->base_name, num_file_acls,
6531 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6532 return map_nt_error_from_unix(errno);
6535 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6536 smb_fname->base_name, &smb_fname->st, num_def_acls,
6537 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6538 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6539 return map_nt_error_from_unix(errno);
6541 return NT_STATUS_OK;
6543 #endif
6545 /****************************************************************************
6546 Deal with SMB_SET_POSIX_LOCK.
6547 ****************************************************************************/
6549 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6550 struct smb_request *req,
6551 const char *pdata,
6552 int total_data,
6553 files_struct *fsp)
6555 uint64_t count;
6556 uint64_t offset;
6557 uint64_t smblctx;
6558 bool blocking_lock = False;
6559 enum brl_type lock_type;
6561 NTSTATUS status = NT_STATUS_OK;
6563 if (fsp == NULL || fsp->fh->fd == -1) {
6564 return NT_STATUS_INVALID_HANDLE;
6567 if (total_data != POSIX_LOCK_DATA_SIZE) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6572 case POSIX_LOCK_TYPE_READ:
6573 lock_type = READ_LOCK;
6574 break;
6575 case POSIX_LOCK_TYPE_WRITE:
6576 /* Return the right POSIX-mappable error code for files opened read-only. */
6577 if (!fsp->can_write) {
6578 return NT_STATUS_INVALID_HANDLE;
6580 lock_type = WRITE_LOCK;
6581 break;
6582 case POSIX_LOCK_TYPE_UNLOCK:
6583 lock_type = UNLOCK_LOCK;
6584 break;
6585 default:
6586 return NT_STATUS_INVALID_PARAMETER;
6589 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6590 blocking_lock = False;
6591 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6592 blocking_lock = True;
6593 } else {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 if (!lp_blocking_locks(SNUM(conn))) {
6598 blocking_lock = False;
6601 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6602 #if defined(HAVE_LONGLONG)
6603 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6604 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6605 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6606 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6607 #else /* HAVE_LONGLONG */
6608 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6609 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6610 #endif /* HAVE_LONGLONG */
6612 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6613 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6614 fsp_str_dbg(fsp),
6615 (unsigned int)lock_type,
6616 (unsigned long long)smblctx,
6617 (double)count,
6618 (double)offset ));
6620 if (lock_type == UNLOCK_LOCK) {
6621 status = do_unlock(req->sconn->msg_ctx,
6622 fsp,
6623 smblctx,
6624 count,
6625 offset,
6626 POSIX_LOCK);
6627 } else {
6628 uint64_t block_smblctx;
6630 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6631 fsp,
6632 smblctx,
6633 count,
6634 offset,
6635 lock_type,
6636 POSIX_LOCK,
6637 blocking_lock,
6638 &status,
6639 &block_smblctx,
6640 NULL);
6642 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6644 * A blocking lock was requested. Package up
6645 * this smb into a queued request and push it
6646 * onto the blocking lock queue.
6648 if(push_blocking_lock_request(br_lck,
6649 req,
6650 fsp,
6651 -1, /* infinite timeout. */
6653 smblctx,
6654 lock_type,
6655 POSIX_LOCK,
6656 offset,
6657 count,
6658 block_smblctx)) {
6659 TALLOC_FREE(br_lck);
6660 return status;
6663 TALLOC_FREE(br_lck);
6666 return status;
6669 /****************************************************************************
6670 Deal with SMB_SET_FILE_BASIC_INFO.
6671 ****************************************************************************/
6673 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6674 const char *pdata,
6675 int total_data,
6676 files_struct *fsp,
6677 const struct smb_filename *smb_fname)
6679 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6680 struct smb_file_time ft;
6681 uint32 dosmode = 0;
6682 NTSTATUS status = NT_STATUS_OK;
6684 ZERO_STRUCT(ft);
6686 if (total_data < 36) {
6687 return NT_STATUS_INVALID_PARAMETER;
6690 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 return status;
6695 /* Set the attributes */
6696 dosmode = IVAL(pdata,32);
6697 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 return status;
6702 /* create time */
6703 ft.create_time = interpret_long_date(pdata);
6705 /* access time */
6706 ft.atime = interpret_long_date(pdata+8);
6708 /* write time. */
6709 ft.mtime = interpret_long_date(pdata+16);
6711 /* change time. */
6712 ft.ctime = interpret_long_date(pdata+24);
6714 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6715 smb_fname_str_dbg(smb_fname)));
6717 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6718 true);
6721 /****************************************************************************
6722 Deal with SMB_INFO_STANDARD.
6723 ****************************************************************************/
6725 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6726 const char *pdata,
6727 int total_data,
6728 files_struct *fsp,
6729 const struct smb_filename *smb_fname)
6731 NTSTATUS status;
6732 struct smb_file_time ft;
6734 ZERO_STRUCT(ft);
6736 if (total_data < 12) {
6737 return NT_STATUS_INVALID_PARAMETER;
6740 /* create time */
6741 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6742 /* access time */
6743 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6744 /* write time */
6745 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6747 DEBUG(10,("smb_set_info_standard: file %s\n",
6748 smb_fname_str_dbg(smb_fname)));
6750 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6751 if (!NT_STATUS_IS_OK(status)) {
6752 return status;
6755 return smb_set_file_time(conn,
6756 fsp,
6757 smb_fname,
6758 &ft,
6759 true);
6762 /****************************************************************************
6763 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6764 ****************************************************************************/
6766 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6767 struct smb_request *req,
6768 const char *pdata,
6769 int total_data,
6770 files_struct *fsp,
6771 struct smb_filename *smb_fname)
6773 uint64_t allocation_size = 0;
6774 NTSTATUS status = NT_STATUS_OK;
6775 files_struct *new_fsp = NULL;
6777 if (!VALID_STAT(smb_fname->st)) {
6778 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6781 if (total_data < 8) {
6782 return NT_STATUS_INVALID_PARAMETER;
6785 allocation_size = (uint64_t)IVAL(pdata,0);
6786 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6787 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6788 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6789 (double)allocation_size));
6791 if (allocation_size) {
6792 allocation_size = smb_roundup(conn, allocation_size);
6795 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6796 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6797 (double)allocation_size));
6799 if (fsp && fsp->fh->fd != -1) {
6800 /* Open file handle. */
6801 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6802 return NT_STATUS_ACCESS_DENIED;
6805 /* Only change if needed. */
6806 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6807 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6808 return map_nt_error_from_unix(errno);
6811 /* But always update the time. */
6813 * This is equivalent to a write. Ensure it's seen immediately
6814 * if there are no pending writes.
6816 trigger_write_time_update_immediate(fsp);
6817 return NT_STATUS_OK;
6820 /* Pathname or stat or directory file. */
6821 status = SMB_VFS_CREATE_FILE(
6822 conn, /* conn */
6823 req, /* req */
6824 0, /* root_dir_fid */
6825 smb_fname, /* fname */
6826 FILE_WRITE_DATA, /* access_mask */
6827 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6828 FILE_SHARE_DELETE),
6829 FILE_OPEN, /* create_disposition*/
6830 0, /* create_options */
6831 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6832 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6833 0, /* allocation_size */
6834 0, /* private_flags */
6835 NULL, /* sd */
6836 NULL, /* ea_list */
6837 &new_fsp, /* result */
6838 NULL); /* pinfo */
6840 if (!NT_STATUS_IS_OK(status)) {
6841 /* NB. We check for open_was_deferred in the caller. */
6842 return status;
6845 /* Only change if needed. */
6846 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6847 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6848 status = map_nt_error_from_unix(errno);
6849 close_file(req, new_fsp, NORMAL_CLOSE);
6850 return status;
6854 /* Changing the allocation size should set the last mod time. */
6856 * This is equivalent to a write. Ensure it's seen immediately
6857 * if there are no pending writes.
6859 trigger_write_time_update_immediate(new_fsp);
6861 close_file(req, new_fsp, NORMAL_CLOSE);
6862 return NT_STATUS_OK;
6865 /****************************************************************************
6866 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6867 ****************************************************************************/
6869 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6870 struct smb_request *req,
6871 const char *pdata,
6872 int total_data,
6873 files_struct *fsp,
6874 const struct smb_filename *smb_fname,
6875 bool fail_after_createfile)
6877 off_t size;
6879 if (total_data < 8) {
6880 return NT_STATUS_INVALID_PARAMETER;
6883 size = IVAL(pdata,0);
6884 size |= (((off_t)IVAL(pdata,4)) << 32);
6885 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6886 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6887 (double)size));
6889 return smb_set_file_size(conn, req,
6890 fsp,
6891 smb_fname,
6892 &smb_fname->st,
6893 size,
6894 fail_after_createfile);
6897 /****************************************************************************
6898 Allow a UNIX info mknod.
6899 ****************************************************************************/
6901 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6902 const char *pdata,
6903 int total_data,
6904 const struct smb_filename *smb_fname)
6906 uint32 file_type = IVAL(pdata,56);
6907 #if defined(HAVE_MAKEDEV)
6908 uint32 dev_major = IVAL(pdata,60);
6909 uint32 dev_minor = IVAL(pdata,68);
6910 #endif
6911 SMB_DEV_T dev = (SMB_DEV_T)0;
6912 uint32 raw_unixmode = IVAL(pdata,84);
6913 NTSTATUS status;
6914 mode_t unixmode;
6916 if (total_data < 100) {
6917 return NT_STATUS_INVALID_PARAMETER;
6920 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6921 PERM_NEW_FILE, &unixmode);
6922 if (!NT_STATUS_IS_OK(status)) {
6923 return status;
6926 #if defined(HAVE_MAKEDEV)
6927 dev = makedev(dev_major, dev_minor);
6928 #endif
6930 switch (file_type) {
6931 #if defined(S_IFIFO)
6932 case UNIX_TYPE_FIFO:
6933 unixmode |= S_IFIFO;
6934 break;
6935 #endif
6936 #if defined(S_IFSOCK)
6937 case UNIX_TYPE_SOCKET:
6938 unixmode |= S_IFSOCK;
6939 break;
6940 #endif
6941 #if defined(S_IFCHR)
6942 case UNIX_TYPE_CHARDEV:
6943 unixmode |= S_IFCHR;
6944 break;
6945 #endif
6946 #if defined(S_IFBLK)
6947 case UNIX_TYPE_BLKDEV:
6948 unixmode |= S_IFBLK;
6949 break;
6950 #endif
6951 default:
6952 return NT_STATUS_INVALID_PARAMETER;
6955 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6956 "%.0f mode 0%o for file %s\n", (double)dev,
6957 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6959 /* Ok - do the mknod. */
6960 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6961 return map_nt_error_from_unix(errno);
6964 /* If any of the other "set" calls fail we
6965 * don't want to end up with a half-constructed mknod.
6968 if (lp_inherit_perms(SNUM(conn))) {
6969 char *parent;
6970 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6971 &parent, NULL)) {
6972 return NT_STATUS_NO_MEMORY;
6974 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6975 unixmode);
6976 TALLOC_FREE(parent);
6979 return NT_STATUS_OK;
6982 /****************************************************************************
6983 Deal with SMB_SET_FILE_UNIX_BASIC.
6984 ****************************************************************************/
6986 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6987 struct smb_request *req,
6988 const char *pdata,
6989 int total_data,
6990 files_struct *fsp,
6991 const struct smb_filename *smb_fname)
6993 struct smb_file_time ft;
6994 uint32 raw_unixmode;
6995 mode_t unixmode;
6996 off_t size = 0;
6997 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6998 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6999 NTSTATUS status = NT_STATUS_OK;
7000 bool delete_on_fail = False;
7001 enum perm_type ptype;
7002 files_struct *all_fsps = NULL;
7003 bool modify_mtime = true;
7004 struct file_id id;
7005 struct smb_filename *smb_fname_tmp = NULL;
7006 SMB_STRUCT_STAT sbuf;
7008 ZERO_STRUCT(ft);
7010 if (total_data < 100) {
7011 return NT_STATUS_INVALID_PARAMETER;
7014 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7015 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7016 size=IVAL(pdata,0); /* first 8 Bytes are size */
7017 size |= (((off_t)IVAL(pdata,4)) << 32);
7020 ft.atime = interpret_long_date(pdata+24); /* access_time */
7021 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7022 set_owner = (uid_t)IVAL(pdata,40);
7023 set_grp = (gid_t)IVAL(pdata,48);
7024 raw_unixmode = IVAL(pdata,84);
7026 if (VALID_STAT(smb_fname->st)) {
7027 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7028 ptype = PERM_EXISTING_DIR;
7029 } else {
7030 ptype = PERM_EXISTING_FILE;
7032 } else {
7033 ptype = PERM_NEW_FILE;
7036 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7037 ptype, &unixmode);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 return status;
7042 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7043 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7044 smb_fname_str_dbg(smb_fname), (double)size,
7045 (unsigned int)set_owner, (unsigned int)set_grp,
7046 (int)raw_unixmode));
7048 sbuf = smb_fname->st;
7050 if (!VALID_STAT(sbuf)) {
7052 * The only valid use of this is to create character and block
7053 * devices, and named pipes. This is deprecated (IMHO) and
7054 * a new info level should be used for mknod. JRA.
7057 status = smb_unix_mknod(conn,
7058 pdata,
7059 total_data,
7060 smb_fname);
7061 if (!NT_STATUS_IS_OK(status)) {
7062 return status;
7065 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7066 if (smb_fname_tmp == NULL) {
7067 return NT_STATUS_NO_MEMORY;
7070 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7071 status = map_nt_error_from_unix(errno);
7072 TALLOC_FREE(smb_fname_tmp);
7073 SMB_VFS_UNLINK(conn, smb_fname);
7074 return status;
7077 sbuf = smb_fname_tmp->st;
7078 smb_fname = smb_fname_tmp;
7080 /* Ensure we don't try and change anything else. */
7081 raw_unixmode = SMB_MODE_NO_CHANGE;
7082 size = get_file_size_stat(&sbuf);
7083 ft.atime = sbuf.st_ex_atime;
7084 ft.mtime = sbuf.st_ex_mtime;
7086 * We continue here as we might want to change the
7087 * owner uid/gid.
7089 delete_on_fail = True;
7092 #if 1
7093 /* Horrible backwards compatibility hack as an old server bug
7094 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7095 * */
7097 if (!size) {
7098 size = get_file_size_stat(&sbuf);
7100 #endif
7103 * Deal with the UNIX specific mode set.
7106 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7107 int ret;
7109 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7110 "setting mode 0%o for file %s\n",
7111 (unsigned int)unixmode,
7112 smb_fname_str_dbg(smb_fname)));
7113 if (fsp && fsp->fh->fd != -1) {
7114 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7115 } else {
7116 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7118 if (ret != 0) {
7119 return map_nt_error_from_unix(errno);
7124 * Deal with the UNIX specific uid set.
7127 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7128 (sbuf.st_ex_uid != set_owner)) {
7129 int ret;
7131 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7132 "changing owner %u for path %s\n",
7133 (unsigned int)set_owner,
7134 smb_fname_str_dbg(smb_fname)));
7136 if (fsp && fsp->fh->fd != -1) {
7137 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7138 } else {
7140 * UNIX extensions calls must always operate
7141 * on symlinks.
7143 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7144 set_owner, (gid_t)-1);
7147 if (ret != 0) {
7148 status = map_nt_error_from_unix(errno);
7149 if (delete_on_fail) {
7150 SMB_VFS_UNLINK(conn, smb_fname);
7152 return status;
7157 * Deal with the UNIX specific gid set.
7160 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7161 (sbuf.st_ex_gid != set_grp)) {
7162 int ret;
7164 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7165 "changing group %u for file %s\n",
7166 (unsigned int)set_owner,
7167 smb_fname_str_dbg(smb_fname)));
7168 if (fsp && fsp->fh->fd != -1) {
7169 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7170 } else {
7172 * UNIX extensions calls must always operate
7173 * on symlinks.
7175 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7176 set_grp);
7178 if (ret != 0) {
7179 status = map_nt_error_from_unix(errno);
7180 if (delete_on_fail) {
7181 SMB_VFS_UNLINK(conn, smb_fname);
7183 return status;
7187 /* Deal with any size changes. */
7189 status = smb_set_file_size(conn, req,
7190 fsp,
7191 smb_fname,
7192 &sbuf,
7193 size,
7194 false);
7195 if (!NT_STATUS_IS_OK(status)) {
7196 return status;
7199 /* Deal with any time changes. */
7200 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7201 /* No change, don't cancel anything. */
7202 return status;
7205 id = vfs_file_id_from_sbuf(conn, &sbuf);
7206 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7207 all_fsps = file_find_di_next(all_fsps)) {
7209 * We're setting the time explicitly for UNIX.
7210 * Cancel any pending changes over all handles.
7212 all_fsps->update_write_time_on_close = false;
7213 TALLOC_FREE(all_fsps->update_write_time_event);
7217 * Override the "setting_write_time"
7218 * parameter here as it almost does what
7219 * we need. Just remember if we modified
7220 * mtime and send the notify ourselves.
7222 if (null_timespec(ft.mtime)) {
7223 modify_mtime = false;
7226 status = smb_set_file_time(conn,
7227 fsp,
7228 smb_fname,
7229 &ft,
7230 false);
7231 if (modify_mtime) {
7232 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7233 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7235 return status;
7238 /****************************************************************************
7239 Deal with SMB_SET_FILE_UNIX_INFO2.
7240 ****************************************************************************/
7242 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7243 struct smb_request *req,
7244 const char *pdata,
7245 int total_data,
7246 files_struct *fsp,
7247 const struct smb_filename *smb_fname)
7249 NTSTATUS status;
7250 uint32 smb_fflags;
7251 uint32 smb_fmask;
7253 if (total_data < 116) {
7254 return NT_STATUS_INVALID_PARAMETER;
7257 /* Start by setting all the fields that are common between UNIX_BASIC
7258 * and UNIX_INFO2.
7260 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7261 fsp, smb_fname);
7262 if (!NT_STATUS_IS_OK(status)) {
7263 return status;
7266 smb_fflags = IVAL(pdata, 108);
7267 smb_fmask = IVAL(pdata, 112);
7269 /* NB: We should only attempt to alter the file flags if the client
7270 * sends a non-zero mask.
7272 if (smb_fmask != 0) {
7273 int stat_fflags = 0;
7275 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7276 smb_fmask, &stat_fflags)) {
7277 /* Client asked to alter a flag we don't understand. */
7278 return NT_STATUS_INVALID_PARAMETER;
7281 if (fsp && fsp->fh->fd != -1) {
7282 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7283 return NT_STATUS_NOT_SUPPORTED;
7284 } else {
7285 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7286 stat_fflags) != 0) {
7287 return map_nt_error_from_unix(errno);
7292 /* XXX: need to add support for changing the create_time here. You
7293 * can do this for paths on Darwin with setattrlist(2). The right way
7294 * to hook this up is probably by extending the VFS utimes interface.
7297 return NT_STATUS_OK;
7300 /****************************************************************************
7301 Create a directory with POSIX semantics.
7302 ****************************************************************************/
7304 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7305 struct smb_request *req,
7306 char **ppdata,
7307 int total_data,
7308 struct smb_filename *smb_fname,
7309 int *pdata_return_size)
7311 NTSTATUS status = NT_STATUS_OK;
7312 uint32 raw_unixmode = 0;
7313 uint32 mod_unixmode = 0;
7314 mode_t unixmode = (mode_t)0;
7315 files_struct *fsp = NULL;
7316 uint16 info_level_return = 0;
7317 int info;
7318 char *pdata = *ppdata;
7320 if (total_data < 18) {
7321 return NT_STATUS_INVALID_PARAMETER;
7324 raw_unixmode = IVAL(pdata,8);
7325 /* Next 4 bytes are not yet defined. */
7327 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7328 PERM_NEW_DIR, &unixmode);
7329 if (!NT_STATUS_IS_OK(status)) {
7330 return status;
7333 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7335 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7336 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7338 status = SMB_VFS_CREATE_FILE(
7339 conn, /* conn */
7340 req, /* req */
7341 0, /* root_dir_fid */
7342 smb_fname, /* fname */
7343 FILE_READ_ATTRIBUTES, /* access_mask */
7344 FILE_SHARE_NONE, /* share_access */
7345 FILE_CREATE, /* create_disposition*/
7346 FILE_DIRECTORY_FILE, /* create_options */
7347 mod_unixmode, /* file_attributes */
7348 0, /* oplock_request */
7349 0, /* allocation_size */
7350 0, /* private_flags */
7351 NULL, /* sd */
7352 NULL, /* ea_list */
7353 &fsp, /* result */
7354 &info); /* pinfo */
7356 if (NT_STATUS_IS_OK(status)) {
7357 close_file(req, fsp, NORMAL_CLOSE);
7360 info_level_return = SVAL(pdata,16);
7362 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7363 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7364 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7365 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7366 } else {
7367 *pdata_return_size = 12;
7370 /* Realloc the data size */
7371 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7372 if (*ppdata == NULL) {
7373 *pdata_return_size = 0;
7374 return NT_STATUS_NO_MEMORY;
7376 pdata = *ppdata;
7378 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7379 SSVAL(pdata,2,0); /* No fnum. */
7380 SIVAL(pdata,4,info); /* Was directory created. */
7382 switch (info_level_return) {
7383 case SMB_QUERY_FILE_UNIX_BASIC:
7384 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7385 SSVAL(pdata,10,0); /* Padding. */
7386 store_file_unix_basic(conn, pdata + 12, fsp,
7387 &smb_fname->st);
7388 break;
7389 case SMB_QUERY_FILE_UNIX_INFO2:
7390 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7391 SSVAL(pdata,10,0); /* Padding. */
7392 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7393 &smb_fname->st);
7394 break;
7395 default:
7396 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7397 SSVAL(pdata,10,0); /* Padding. */
7398 break;
7401 return status;
7404 /****************************************************************************
7405 Open/Create a file with POSIX semantics.
7406 ****************************************************************************/
7408 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7409 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7411 static NTSTATUS smb_posix_open(connection_struct *conn,
7412 struct smb_request *req,
7413 char **ppdata,
7414 int total_data,
7415 struct smb_filename *smb_fname,
7416 int *pdata_return_size)
7418 bool extended_oplock_granted = False;
7419 char *pdata = *ppdata;
7420 uint32 flags = 0;
7421 uint32 wire_open_mode = 0;
7422 uint32 raw_unixmode = 0;
7423 uint32 mod_unixmode = 0;
7424 uint32 create_disp = 0;
7425 uint32 access_mask = 0;
7426 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7427 NTSTATUS status = NT_STATUS_OK;
7428 mode_t unixmode = (mode_t)0;
7429 files_struct *fsp = NULL;
7430 int oplock_request = 0;
7431 int info = 0;
7432 uint16 info_level_return = 0;
7434 if (total_data < 18) {
7435 return NT_STATUS_INVALID_PARAMETER;
7438 flags = IVAL(pdata,0);
7439 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7440 if (oplock_request) {
7441 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7444 wire_open_mode = IVAL(pdata,4);
7446 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7447 return smb_posix_mkdir(conn, req,
7448 ppdata,
7449 total_data,
7450 smb_fname,
7451 pdata_return_size);
7454 switch (wire_open_mode & SMB_ACCMODE) {
7455 case SMB_O_RDONLY:
7456 access_mask = SMB_O_RDONLY_MAPPING;
7457 break;
7458 case SMB_O_WRONLY:
7459 access_mask = SMB_O_WRONLY_MAPPING;
7460 break;
7461 case SMB_O_RDWR:
7462 access_mask = (SMB_O_RDONLY_MAPPING|
7463 SMB_O_WRONLY_MAPPING);
7464 break;
7465 default:
7466 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7467 (unsigned int)wire_open_mode ));
7468 return NT_STATUS_INVALID_PARAMETER;
7471 wire_open_mode &= ~SMB_ACCMODE;
7473 /* First take care of O_CREAT|O_EXCL interactions. */
7474 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7475 case (SMB_O_CREAT | SMB_O_EXCL):
7476 /* File exists fail. File not exist create. */
7477 create_disp = FILE_CREATE;
7478 break;
7479 case SMB_O_CREAT:
7480 /* File exists open. File not exist create. */
7481 create_disp = FILE_OPEN_IF;
7482 break;
7483 case SMB_O_EXCL:
7484 /* O_EXCL on its own without O_CREAT is undefined.
7485 We deliberately ignore it as some versions of
7486 Linux CIFSFS can send a bare O_EXCL on the
7487 wire which other filesystems in the kernel
7488 ignore. See bug 9519 for details. */
7490 /* Fallthrough. */
7492 case 0:
7493 /* File exists open. File not exist fail. */
7494 create_disp = FILE_OPEN;
7495 break;
7496 default:
7497 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7498 (unsigned int)wire_open_mode ));
7499 return NT_STATUS_INVALID_PARAMETER;
7502 /* Next factor in the effects of O_TRUNC. */
7503 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7505 if (wire_open_mode & SMB_O_TRUNC) {
7506 switch (create_disp) {
7507 case FILE_CREATE:
7508 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7509 /* Leave create_disp alone as
7510 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7512 /* File exists fail. File not exist create. */
7513 break;
7514 case FILE_OPEN_IF:
7515 /* SMB_O_CREAT | SMB_O_TRUNC */
7516 /* File exists overwrite. File not exist create. */
7517 create_disp = FILE_OVERWRITE_IF;
7518 break;
7519 case FILE_OPEN:
7520 /* SMB_O_TRUNC */
7521 /* File exists overwrite. File not exist fail. */
7522 create_disp = FILE_OVERWRITE;
7523 break;
7524 default:
7525 /* Cannot get here. */
7526 smb_panic("smb_posix_open: logic error");
7527 return NT_STATUS_INVALID_PARAMETER;
7531 raw_unixmode = IVAL(pdata,8);
7532 /* Next 4 bytes are not yet defined. */
7534 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7535 (VALID_STAT(smb_fname->st) ?
7536 PERM_EXISTING_FILE : PERM_NEW_FILE),
7537 &unixmode);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 return status;
7543 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7545 if (wire_open_mode & SMB_O_SYNC) {
7546 create_options |= FILE_WRITE_THROUGH;
7548 if (wire_open_mode & SMB_O_APPEND) {
7549 access_mask |= FILE_APPEND_DATA;
7551 if (wire_open_mode & SMB_O_DIRECT) {
7552 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7555 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7556 VALID_STAT_OF_DIR(smb_fname->st)) {
7557 if (access_mask != SMB_O_RDONLY_MAPPING) {
7558 return NT_STATUS_FILE_IS_A_DIRECTORY;
7560 create_options &= ~FILE_NON_DIRECTORY_FILE;
7561 create_options |= FILE_DIRECTORY_FILE;
7564 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7565 smb_fname_str_dbg(smb_fname),
7566 (unsigned int)wire_open_mode,
7567 (unsigned int)unixmode ));
7569 status = SMB_VFS_CREATE_FILE(
7570 conn, /* conn */
7571 req, /* req */
7572 0, /* root_dir_fid */
7573 smb_fname, /* fname */
7574 access_mask, /* access_mask */
7575 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7576 FILE_SHARE_DELETE),
7577 create_disp, /* create_disposition*/
7578 create_options, /* create_options */
7579 mod_unixmode, /* file_attributes */
7580 oplock_request, /* oplock_request */
7581 0, /* allocation_size */
7582 0, /* private_flags */
7583 NULL, /* sd */
7584 NULL, /* ea_list */
7585 &fsp, /* result */
7586 &info); /* pinfo */
7588 if (!NT_STATUS_IS_OK(status)) {
7589 return status;
7592 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7593 extended_oplock_granted = True;
7596 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7597 extended_oplock_granted = True;
7600 info_level_return = SVAL(pdata,16);
7602 /* Allocate the correct return size. */
7604 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7605 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7606 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7607 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7608 } else {
7609 *pdata_return_size = 12;
7612 /* Realloc the data size */
7613 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7614 if (*ppdata == NULL) {
7615 close_file(req, fsp, ERROR_CLOSE);
7616 *pdata_return_size = 0;
7617 return NT_STATUS_NO_MEMORY;
7619 pdata = *ppdata;
7621 if (extended_oplock_granted) {
7622 if (flags & REQUEST_BATCH_OPLOCK) {
7623 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7624 } else {
7625 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7627 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7628 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7629 } else {
7630 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7633 SSVAL(pdata,2,fsp->fnum);
7634 SIVAL(pdata,4,info); /* Was file created etc. */
7636 switch (info_level_return) {
7637 case SMB_QUERY_FILE_UNIX_BASIC:
7638 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7639 SSVAL(pdata,10,0); /* padding. */
7640 store_file_unix_basic(conn, pdata + 12, fsp,
7641 &smb_fname->st);
7642 break;
7643 case SMB_QUERY_FILE_UNIX_INFO2:
7644 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7645 SSVAL(pdata,10,0); /* padding. */
7646 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7647 &smb_fname->st);
7648 break;
7649 default:
7650 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7651 SSVAL(pdata,10,0); /* padding. */
7652 break;
7654 return NT_STATUS_OK;
7657 /****************************************************************************
7658 Delete a file with POSIX semantics.
7659 ****************************************************************************/
7661 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7662 struct smb_request *req,
7663 const char *pdata,
7664 int total_data,
7665 struct smb_filename *smb_fname)
7667 NTSTATUS status = NT_STATUS_OK;
7668 files_struct *fsp = NULL;
7669 uint16 flags = 0;
7670 char del = 1;
7671 int info = 0;
7672 int create_options = 0;
7673 int i;
7674 struct share_mode_lock *lck = NULL;
7676 if (total_data < 2) {
7677 return NT_STATUS_INVALID_PARAMETER;
7680 flags = SVAL(pdata,0);
7682 if (!VALID_STAT(smb_fname->st)) {
7683 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7686 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7687 !VALID_STAT_OF_DIR(smb_fname->st)) {
7688 return NT_STATUS_NOT_A_DIRECTORY;
7691 DEBUG(10,("smb_posix_unlink: %s %s\n",
7692 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7693 smb_fname_str_dbg(smb_fname)));
7695 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7696 create_options |= FILE_DIRECTORY_FILE;
7699 status = SMB_VFS_CREATE_FILE(
7700 conn, /* conn */
7701 req, /* req */
7702 0, /* root_dir_fid */
7703 smb_fname, /* fname */
7704 DELETE_ACCESS, /* access_mask */
7705 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7706 FILE_SHARE_DELETE),
7707 FILE_OPEN, /* create_disposition*/
7708 create_options, /* create_options */
7709 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7710 0, /* oplock_request */
7711 0, /* allocation_size */
7712 0, /* private_flags */
7713 NULL, /* sd */
7714 NULL, /* ea_list */
7715 &fsp, /* result */
7716 &info); /* pinfo */
7718 if (!NT_STATUS_IS_OK(status)) {
7719 return status;
7723 * Don't lie to client. If we can't really delete due to
7724 * non-POSIX opens return SHARING_VIOLATION.
7727 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7728 if (lck == NULL) {
7729 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7730 "lock for file %s\n", fsp_str_dbg(fsp)));
7731 close_file(req, fsp, NORMAL_CLOSE);
7732 return NT_STATUS_INVALID_PARAMETER;
7736 * See if others still have the file open. If this is the case, then
7737 * don't delete. If all opens are POSIX delete we can set the delete
7738 * on close disposition.
7740 for (i=0; i<lck->data->num_share_modes; i++) {
7741 struct share_mode_entry *e = &lck->data->share_modes[i];
7742 if (is_valid_share_mode_entry(e)) {
7743 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7744 continue;
7746 if (share_mode_stale_pid(lck->data, i)) {
7747 continue;
7749 /* Fail with sharing violation. */
7750 TALLOC_FREE(lck);
7751 close_file(req, fsp, NORMAL_CLOSE);
7752 return NT_STATUS_SHARING_VIOLATION;
7757 * Set the delete on close.
7759 status = smb_set_file_disposition_info(conn,
7760 &del,
7762 fsp,
7763 smb_fname);
7765 TALLOC_FREE(lck);
7767 if (!NT_STATUS_IS_OK(status)) {
7768 close_file(req, fsp, NORMAL_CLOSE);
7769 return status;
7771 return close_file(req, fsp, NORMAL_CLOSE);
7774 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7775 struct smb_request *req,
7776 TALLOC_CTX *mem_ctx,
7777 uint16_t info_level,
7778 files_struct *fsp,
7779 struct smb_filename *smb_fname,
7780 char **ppdata, int total_data,
7781 int *ret_data_size)
7783 char *pdata = *ppdata;
7784 NTSTATUS status = NT_STATUS_OK;
7785 int data_return_size = 0;
7787 *ret_data_size = 0;
7789 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7790 return NT_STATUS_INVALID_LEVEL;
7793 if (!CAN_WRITE(conn)) {
7794 /* Allow POSIX opens. The open path will deny
7795 * any non-readonly opens. */
7796 if (info_level != SMB_POSIX_PATH_OPEN) {
7797 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7801 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7802 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7803 fsp_fnum_dbg(fsp),
7804 info_level, total_data));
7806 switch (info_level) {
7808 case SMB_INFO_STANDARD:
7810 status = smb_set_info_standard(conn,
7811 pdata,
7812 total_data,
7813 fsp,
7814 smb_fname);
7815 break;
7818 case SMB_INFO_SET_EA:
7820 status = smb_info_set_ea(conn,
7821 pdata,
7822 total_data,
7823 fsp,
7824 smb_fname);
7825 break;
7828 case SMB_SET_FILE_BASIC_INFO:
7829 case SMB_FILE_BASIC_INFORMATION:
7831 status = smb_set_file_basic_info(conn,
7832 pdata,
7833 total_data,
7834 fsp,
7835 smb_fname);
7836 break;
7839 case SMB_FILE_ALLOCATION_INFORMATION:
7840 case SMB_SET_FILE_ALLOCATION_INFO:
7842 status = smb_set_file_allocation_info(conn, req,
7843 pdata,
7844 total_data,
7845 fsp,
7846 smb_fname);
7847 break;
7850 case SMB_FILE_END_OF_FILE_INFORMATION:
7851 case SMB_SET_FILE_END_OF_FILE_INFO:
7854 * XP/Win7 both fail after the createfile with
7855 * SMB_SET_FILE_END_OF_FILE_INFO but not
7856 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7857 * The level is known here, so pass it down
7858 * appropriately.
7860 bool should_fail =
7861 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7863 status = smb_set_file_end_of_file_info(conn, req,
7864 pdata,
7865 total_data,
7866 fsp,
7867 smb_fname,
7868 should_fail);
7869 break;
7872 case SMB_FILE_DISPOSITION_INFORMATION:
7873 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7875 #if 0
7876 /* JRA - We used to just ignore this on a path ?
7877 * Shouldn't this be invalid level on a pathname
7878 * based call ?
7880 if (tran_call != TRANSACT2_SETFILEINFO) {
7881 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7883 #endif
7884 status = smb_set_file_disposition_info(conn,
7885 pdata,
7886 total_data,
7887 fsp,
7888 smb_fname);
7889 break;
7892 case SMB_FILE_POSITION_INFORMATION:
7894 status = smb_file_position_information(conn,
7895 pdata,
7896 total_data,
7897 fsp);
7898 break;
7901 case SMB_FILE_FULL_EA_INFORMATION:
7903 status = smb_set_file_full_ea_info(conn,
7904 pdata,
7905 total_data,
7906 fsp);
7907 break;
7910 /* From tridge Samba4 :
7911 * MODE_INFORMATION in setfileinfo (I have no
7912 * idea what "mode information" on a file is - it takes a value of 0,
7913 * 2, 4 or 6. What could it be?).
7916 case SMB_FILE_MODE_INFORMATION:
7918 status = smb_file_mode_information(conn,
7919 pdata,
7920 total_data);
7921 break;
7925 * CIFS UNIX extensions.
7928 case SMB_SET_FILE_UNIX_BASIC:
7930 status = smb_set_file_unix_basic(conn, req,
7931 pdata,
7932 total_data,
7933 fsp,
7934 smb_fname);
7935 break;
7938 case SMB_SET_FILE_UNIX_INFO2:
7940 status = smb_set_file_unix_info2(conn, req,
7941 pdata,
7942 total_data,
7943 fsp,
7944 smb_fname);
7945 break;
7948 case SMB_SET_FILE_UNIX_LINK:
7950 if (fsp) {
7951 /* We must have a pathname for this. */
7952 return NT_STATUS_INVALID_LEVEL;
7954 status = smb_set_file_unix_link(conn, req, pdata,
7955 total_data, smb_fname);
7956 break;
7959 case SMB_SET_FILE_UNIX_HLINK:
7961 if (fsp) {
7962 /* We must have a pathname for this. */
7963 return NT_STATUS_INVALID_LEVEL;
7965 status = smb_set_file_unix_hlink(conn, req,
7966 pdata, total_data,
7967 smb_fname);
7968 break;
7971 case SMB_FILE_RENAME_INFORMATION:
7973 status = smb_file_rename_information(conn, req,
7974 pdata, total_data,
7975 fsp, smb_fname);
7976 break;
7979 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7981 /* SMB2 rename information. */
7982 status = smb2_file_rename_information(conn, req,
7983 pdata, total_data,
7984 fsp, smb_fname);
7985 break;
7988 case SMB_FILE_LINK_INFORMATION:
7990 status = smb_file_link_information(conn, req,
7991 pdata, total_data,
7992 fsp, smb_fname);
7993 break;
7996 #if defined(HAVE_POSIX_ACLS)
7997 case SMB_SET_POSIX_ACL:
7999 status = smb_set_posix_acl(conn,
8000 pdata,
8001 total_data,
8002 fsp,
8003 smb_fname);
8004 break;
8006 #endif
8008 case SMB_SET_POSIX_LOCK:
8010 if (!fsp) {
8011 return NT_STATUS_INVALID_LEVEL;
8013 status = smb_set_posix_lock(conn, req,
8014 pdata, total_data, fsp);
8015 break;
8018 case SMB_POSIX_PATH_OPEN:
8020 if (fsp) {
8021 /* We must have a pathname for this. */
8022 return NT_STATUS_INVALID_LEVEL;
8025 status = smb_posix_open(conn, req,
8026 ppdata,
8027 total_data,
8028 smb_fname,
8029 &data_return_size);
8030 break;
8033 case SMB_POSIX_PATH_UNLINK:
8035 if (fsp) {
8036 /* We must have a pathname for this. */
8037 return NT_STATUS_INVALID_LEVEL;
8040 status = smb_posix_unlink(conn, req,
8041 pdata,
8042 total_data,
8043 smb_fname);
8044 break;
8047 default:
8048 return NT_STATUS_INVALID_LEVEL;
8051 if (!NT_STATUS_IS_OK(status)) {
8052 return status;
8055 *ret_data_size = data_return_size;
8056 return NT_STATUS_OK;
8059 /****************************************************************************
8060 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8061 ****************************************************************************/
8063 static void call_trans2setfilepathinfo(connection_struct *conn,
8064 struct smb_request *req,
8065 unsigned int tran_call,
8066 char **pparams, int total_params,
8067 char **ppdata, int total_data,
8068 unsigned int max_data_bytes)
8070 char *params = *pparams;
8071 char *pdata = *ppdata;
8072 uint16 info_level;
8073 struct smb_filename *smb_fname = NULL;
8074 files_struct *fsp = NULL;
8075 NTSTATUS status = NT_STATUS_OK;
8076 int data_return_size = 0;
8078 if (!params) {
8079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8080 return;
8083 if (tran_call == TRANSACT2_SETFILEINFO) {
8084 if (total_params < 4) {
8085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8086 return;
8089 fsp = file_fsp(req, SVAL(params,0));
8090 /* Basic check for non-null fsp. */
8091 if (!check_fsp_open(conn, req, fsp)) {
8092 return;
8094 info_level = SVAL(params,2);
8096 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8097 if (smb_fname == NULL) {
8098 reply_nterror(req, NT_STATUS_NO_MEMORY);
8099 return;
8102 if(fsp->fh->fd == -1) {
8104 * This is actually a SETFILEINFO on a directory
8105 * handle (returned from an NT SMB). NT5.0 seems
8106 * to do this call. JRA.
8108 if (INFO_LEVEL_IS_UNIX(info_level)) {
8109 /* Always do lstat for UNIX calls. */
8110 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8111 DEBUG(3,("call_trans2setfilepathinfo: "
8112 "SMB_VFS_LSTAT of %s failed "
8113 "(%s)\n",
8114 smb_fname_str_dbg(smb_fname),
8115 strerror(errno)));
8116 reply_nterror(req, map_nt_error_from_unix(errno));
8117 return;
8119 } else {
8120 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8121 DEBUG(3,("call_trans2setfilepathinfo: "
8122 "fileinfo of %s failed (%s)\n",
8123 smb_fname_str_dbg(smb_fname),
8124 strerror(errno)));
8125 reply_nterror(req, map_nt_error_from_unix(errno));
8126 return;
8129 } else if (fsp->print_file) {
8131 * Doing a DELETE_ON_CLOSE should cancel a print job.
8133 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8134 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8136 DEBUG(3,("call_trans2setfilepathinfo: "
8137 "Cancelling print job (%s)\n",
8138 fsp_str_dbg(fsp)));
8140 SSVAL(params,0,0);
8141 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8142 *ppdata, 0,
8143 max_data_bytes);
8144 return;
8145 } else {
8146 reply_nterror(req,
8147 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8148 return;
8150 } else {
8152 * Original code - this is an open file.
8154 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8155 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8156 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8157 strerror(errno)));
8158 reply_nterror(req, map_nt_error_from_unix(errno));
8159 return;
8162 } else {
8163 char *fname = NULL;
8164 uint32_t ucf_flags = 0;
8166 /* set path info */
8167 if (total_params < 7) {
8168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8169 return;
8172 info_level = SVAL(params,0);
8173 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8174 total_params - 6, STR_TERMINATE,
8175 &status);
8176 if (!NT_STATUS_IS_OK(status)) {
8177 reply_nterror(req, status);
8178 return;
8181 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8182 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8183 info_level == SMB_FILE_RENAME_INFORMATION ||
8184 info_level == SMB_POSIX_PATH_UNLINK) {
8185 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8188 status = filename_convert(req, conn,
8189 req->flags2 & FLAGS2_DFS_PATHNAMES,
8190 fname,
8191 ucf_flags,
8192 NULL,
8193 &smb_fname);
8194 if (!NT_STATUS_IS_OK(status)) {
8195 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8196 reply_botherror(req,
8197 NT_STATUS_PATH_NOT_COVERED,
8198 ERRSRV, ERRbadpath);
8199 return;
8201 reply_nterror(req, status);
8202 return;
8205 if (INFO_LEVEL_IS_UNIX(info_level)) {
8207 * For CIFS UNIX extensions the target name may not exist.
8210 /* Always do lstat for UNIX calls. */
8211 SMB_VFS_LSTAT(conn, smb_fname);
8213 } else if (!VALID_STAT(smb_fname->st) &&
8214 SMB_VFS_STAT(conn, smb_fname)) {
8215 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8216 "%s failed (%s)\n",
8217 smb_fname_str_dbg(smb_fname),
8218 strerror(errno)));
8219 reply_nterror(req, map_nt_error_from_unix(errno));
8220 return;
8224 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8225 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8226 fsp_fnum_dbg(fsp),
8227 info_level,total_data));
8229 /* Realloc the parameter size */
8230 *pparams = (char *)SMB_REALLOC(*pparams,2);
8231 if (*pparams == NULL) {
8232 reply_nterror(req, NT_STATUS_NO_MEMORY);
8233 return;
8235 params = *pparams;
8237 SSVAL(params,0,0);
8239 status = smbd_do_setfilepathinfo(conn, req, req,
8240 info_level,
8241 fsp,
8242 smb_fname,
8243 ppdata, total_data,
8244 &data_return_size);
8245 if (!NT_STATUS_IS_OK(status)) {
8246 if (open_was_deferred(req->sconn, req->mid)) {
8247 /* We have re-scheduled this call. */
8248 return;
8250 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8251 /* We have re-scheduled this call. */
8252 return;
8254 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8255 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8256 ERRSRV, ERRbadpath);
8257 return;
8259 if (info_level == SMB_POSIX_PATH_OPEN) {
8260 reply_openerror(req, status);
8261 return;
8265 * Invalid EA name needs to return 2 param bytes,
8266 * not a zero-length error packet.
8268 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8269 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8270 max_data_bytes);
8271 } else {
8272 reply_nterror(req, status);
8274 return;
8277 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8278 max_data_bytes);
8280 return;
8283 /****************************************************************************
8284 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8285 ****************************************************************************/
8287 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8288 char **pparams, int total_params,
8289 char **ppdata, int total_data,
8290 unsigned int max_data_bytes)
8292 struct smb_filename *smb_dname = NULL;
8293 char *params = *pparams;
8294 char *pdata = *ppdata;
8295 char *directory = NULL;
8296 NTSTATUS status = NT_STATUS_OK;
8297 struct ea_list *ea_list = NULL;
8298 TALLOC_CTX *ctx = talloc_tos();
8300 if (!CAN_WRITE(conn)) {
8301 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8302 return;
8305 if (total_params < 5) {
8306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8307 return;
8310 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8311 total_params - 4, STR_TERMINATE,
8312 &status);
8313 if (!NT_STATUS_IS_OK(status)) {
8314 reply_nterror(req, status);
8315 return;
8318 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8320 status = filename_convert(ctx,
8321 conn,
8322 req->flags2 & FLAGS2_DFS_PATHNAMES,
8323 directory,
8325 NULL,
8326 &smb_dname);
8328 if (!NT_STATUS_IS_OK(status)) {
8329 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8330 reply_botherror(req,
8331 NT_STATUS_PATH_NOT_COVERED,
8332 ERRSRV, ERRbadpath);
8333 return;
8335 reply_nterror(req, status);
8336 return;
8340 * OS/2 workplace shell seems to send SET_EA requests of "null"
8341 * length (4 bytes containing IVAL 4).
8342 * They seem to have no effect. Bug #3212. JRA.
8345 if (total_data && (total_data != 4)) {
8346 /* Any data in this call is an EA list. */
8347 if (total_data < 10) {
8348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8349 goto out;
8352 if (IVAL(pdata,0) > total_data) {
8353 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8354 IVAL(pdata,0), (unsigned int)total_data));
8355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8356 goto out;
8359 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8360 total_data - 4);
8361 if (!ea_list) {
8362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8363 goto out;
8366 if (!lp_ea_support(SNUM(conn))) {
8367 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8368 goto out;
8371 /* If total_data == 4 Windows doesn't care what values
8372 * are placed in that field, it just ignores them.
8373 * The System i QNTC IBM SMB client puts bad values here,
8374 * so ignore them. */
8376 status = create_directory(conn, req, smb_dname);
8378 if (!NT_STATUS_IS_OK(status)) {
8379 reply_nterror(req, status);
8380 goto out;
8383 /* Try and set any given EA. */
8384 if (ea_list) {
8385 status = set_ea(conn, NULL, smb_dname, ea_list);
8386 if (!NT_STATUS_IS_OK(status)) {
8387 reply_nterror(req, status);
8388 goto out;
8392 /* Realloc the parameter and data sizes */
8393 *pparams = (char *)SMB_REALLOC(*pparams,2);
8394 if(*pparams == NULL) {
8395 reply_nterror(req, NT_STATUS_NO_MEMORY);
8396 goto out;
8398 params = *pparams;
8400 SSVAL(params,0,0);
8402 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8404 out:
8405 TALLOC_FREE(smb_dname);
8406 return;
8409 /****************************************************************************
8410 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8411 We don't actually do this - we just send a null response.
8412 ****************************************************************************/
8414 static void call_trans2findnotifyfirst(connection_struct *conn,
8415 struct smb_request *req,
8416 char **pparams, int total_params,
8417 char **ppdata, int total_data,
8418 unsigned int max_data_bytes)
8420 char *params = *pparams;
8421 uint16 info_level;
8423 if (total_params < 6) {
8424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8425 return;
8428 info_level = SVAL(params,4);
8429 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8431 switch (info_level) {
8432 case 1:
8433 case 2:
8434 break;
8435 default:
8436 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8437 return;
8440 /* Realloc the parameter and data sizes */
8441 *pparams = (char *)SMB_REALLOC(*pparams,6);
8442 if (*pparams == NULL) {
8443 reply_nterror(req, NT_STATUS_NO_MEMORY);
8444 return;
8446 params = *pparams;
8448 SSVAL(params,0,fnf_handle);
8449 SSVAL(params,2,0); /* No changes */
8450 SSVAL(params,4,0); /* No EA errors */
8452 fnf_handle++;
8454 if(fnf_handle == 0)
8455 fnf_handle = 257;
8457 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8459 return;
8462 /****************************************************************************
8463 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8464 changes). Currently this does nothing.
8465 ****************************************************************************/
8467 static void call_trans2findnotifynext(connection_struct *conn,
8468 struct smb_request *req,
8469 char **pparams, int total_params,
8470 char **ppdata, int total_data,
8471 unsigned int max_data_bytes)
8473 char *params = *pparams;
8475 DEBUG(3,("call_trans2findnotifynext\n"));
8477 /* Realloc the parameter and data sizes */
8478 *pparams = (char *)SMB_REALLOC(*pparams,4);
8479 if (*pparams == NULL) {
8480 reply_nterror(req, NT_STATUS_NO_MEMORY);
8481 return;
8483 params = *pparams;
8485 SSVAL(params,0,0); /* No changes */
8486 SSVAL(params,2,0); /* No EA errors */
8488 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8490 return;
8493 /****************************************************************************
8494 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8495 ****************************************************************************/
8497 static void call_trans2getdfsreferral(connection_struct *conn,
8498 struct smb_request *req,
8499 char **pparams, int total_params,
8500 char **ppdata, int total_data,
8501 unsigned int max_data_bytes)
8503 char *params = *pparams;
8504 char *pathname = NULL;
8505 int reply_size = 0;
8506 int max_referral_level;
8507 NTSTATUS status = NT_STATUS_OK;
8508 TALLOC_CTX *ctx = talloc_tos();
8510 DEBUG(10,("call_trans2getdfsreferral\n"));
8512 if (total_params < 3) {
8513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8514 return;
8517 max_referral_level = SVAL(params,0);
8519 if(!lp_host_msdfs()) {
8520 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8521 return;
8524 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8525 total_params - 2, STR_TERMINATE);
8526 if (!pathname) {
8527 reply_nterror(req, NT_STATUS_NOT_FOUND);
8528 return;
8530 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8531 ppdata,&status)) < 0) {
8532 reply_nterror(req, status);
8533 return;
8536 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8537 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8538 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8540 return;
8543 #define LMCAT_SPL 0x53
8544 #define LMFUNC_GETJOBID 0x60
8546 /****************************************************************************
8547 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8548 ****************************************************************************/
8550 static void call_trans2ioctl(connection_struct *conn,
8551 struct smb_request *req,
8552 char **pparams, int total_params,
8553 char **ppdata, int total_data,
8554 unsigned int max_data_bytes)
8556 char *pdata = *ppdata;
8557 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8559 /* check for an invalid fid before proceeding */
8561 if (!fsp) {
8562 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8563 return;
8566 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8567 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8568 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8569 if (*ppdata == NULL) {
8570 reply_nterror(req, NT_STATUS_NO_MEMORY);
8571 return;
8573 pdata = *ppdata;
8575 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8576 CAN ACCEPT THIS IN UNICODE. JRA. */
8578 /* Job number */
8579 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8581 srvstr_push(pdata, req->flags2, pdata + 2,
8582 lp_netbios_name(), 15,
8583 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8584 srvstr_push(pdata, req->flags2, pdata+18,
8585 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8586 STR_ASCII|STR_TERMINATE); /* Service name */
8587 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8588 max_data_bytes);
8589 return;
8592 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8593 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8596 /****************************************************************************
8597 Reply to a SMBfindclose (stop trans2 directory search).
8598 ****************************************************************************/
8600 void reply_findclose(struct smb_request *req)
8602 int dptr_num;
8603 struct smbd_server_connection *sconn = req->sconn;
8605 START_PROFILE(SMBfindclose);
8607 if (req->wct < 1) {
8608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8609 END_PROFILE(SMBfindclose);
8610 return;
8613 dptr_num = SVALS(req->vwv+0, 0);
8615 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8617 dptr_close(sconn, &dptr_num);
8619 reply_outbuf(req, 0, 0);
8621 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8623 END_PROFILE(SMBfindclose);
8624 return;
8627 /****************************************************************************
8628 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8629 ****************************************************************************/
8631 void reply_findnclose(struct smb_request *req)
8633 int dptr_num;
8635 START_PROFILE(SMBfindnclose);
8637 if (req->wct < 1) {
8638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8639 END_PROFILE(SMBfindnclose);
8640 return;
8643 dptr_num = SVAL(req->vwv+0, 0);
8645 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8647 /* We never give out valid handles for a
8648 findnotifyfirst - so any dptr_num is ok here.
8649 Just ignore it. */
8651 reply_outbuf(req, 0, 0);
8653 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8655 END_PROFILE(SMBfindnclose);
8656 return;
8659 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8660 struct trans_state *state)
8662 if (get_Protocol() >= PROTOCOL_NT1) {
8663 req->flags2 |= 0x40; /* IS_LONG_NAME */
8664 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8667 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8668 if (state->call != TRANSACT2_QFSINFO &&
8669 state->call != TRANSACT2_SETFSINFO) {
8670 DEBUG(0,("handle_trans2: encryption required "
8671 "with call 0x%x\n",
8672 (unsigned int)state->call));
8673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8674 return;
8678 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8680 /* Now we must call the relevant TRANS2 function */
8681 switch(state->call) {
8682 case TRANSACT2_OPEN:
8684 START_PROFILE(Trans2_open);
8685 call_trans2open(conn, req,
8686 &state->param, state->total_param,
8687 &state->data, state->total_data,
8688 state->max_data_return);
8689 END_PROFILE(Trans2_open);
8690 break;
8693 case TRANSACT2_FINDFIRST:
8695 START_PROFILE(Trans2_findfirst);
8696 call_trans2findfirst(conn, req,
8697 &state->param, state->total_param,
8698 &state->data, state->total_data,
8699 state->max_data_return);
8700 END_PROFILE(Trans2_findfirst);
8701 break;
8704 case TRANSACT2_FINDNEXT:
8706 START_PROFILE(Trans2_findnext);
8707 call_trans2findnext(conn, req,
8708 &state->param, state->total_param,
8709 &state->data, state->total_data,
8710 state->max_data_return);
8711 END_PROFILE(Trans2_findnext);
8712 break;
8715 case TRANSACT2_QFSINFO:
8717 START_PROFILE(Trans2_qfsinfo);
8718 call_trans2qfsinfo(conn, req,
8719 &state->param, state->total_param,
8720 &state->data, state->total_data,
8721 state->max_data_return);
8722 END_PROFILE(Trans2_qfsinfo);
8723 break;
8726 case TRANSACT2_SETFSINFO:
8728 START_PROFILE(Trans2_setfsinfo);
8729 call_trans2setfsinfo(conn, req,
8730 &state->param, state->total_param,
8731 &state->data, state->total_data,
8732 state->max_data_return);
8733 END_PROFILE(Trans2_setfsinfo);
8734 break;
8737 case TRANSACT2_QPATHINFO:
8738 case TRANSACT2_QFILEINFO:
8740 START_PROFILE(Trans2_qpathinfo);
8741 call_trans2qfilepathinfo(conn, req, state->call,
8742 &state->param, state->total_param,
8743 &state->data, state->total_data,
8744 state->max_data_return);
8745 END_PROFILE(Trans2_qpathinfo);
8746 break;
8749 case TRANSACT2_SETPATHINFO:
8750 case TRANSACT2_SETFILEINFO:
8752 START_PROFILE(Trans2_setpathinfo);
8753 call_trans2setfilepathinfo(conn, req, state->call,
8754 &state->param, state->total_param,
8755 &state->data, state->total_data,
8756 state->max_data_return);
8757 END_PROFILE(Trans2_setpathinfo);
8758 break;
8761 case TRANSACT2_FINDNOTIFYFIRST:
8763 START_PROFILE(Trans2_findnotifyfirst);
8764 call_trans2findnotifyfirst(conn, req,
8765 &state->param, state->total_param,
8766 &state->data, state->total_data,
8767 state->max_data_return);
8768 END_PROFILE(Trans2_findnotifyfirst);
8769 break;
8772 case TRANSACT2_FINDNOTIFYNEXT:
8774 START_PROFILE(Trans2_findnotifynext);
8775 call_trans2findnotifynext(conn, req,
8776 &state->param, state->total_param,
8777 &state->data, state->total_data,
8778 state->max_data_return);
8779 END_PROFILE(Trans2_findnotifynext);
8780 break;
8783 case TRANSACT2_MKDIR:
8785 START_PROFILE(Trans2_mkdir);
8786 call_trans2mkdir(conn, req,
8787 &state->param, state->total_param,
8788 &state->data, state->total_data,
8789 state->max_data_return);
8790 END_PROFILE(Trans2_mkdir);
8791 break;
8794 case TRANSACT2_GET_DFS_REFERRAL:
8796 START_PROFILE(Trans2_get_dfs_referral);
8797 call_trans2getdfsreferral(conn, req,
8798 &state->param, state->total_param,
8799 &state->data, state->total_data,
8800 state->max_data_return);
8801 END_PROFILE(Trans2_get_dfs_referral);
8802 break;
8805 case TRANSACT2_IOCTL:
8807 START_PROFILE(Trans2_ioctl);
8808 call_trans2ioctl(conn, req,
8809 &state->param, state->total_param,
8810 &state->data, state->total_data,
8811 state->max_data_return);
8812 END_PROFILE(Trans2_ioctl);
8813 break;
8816 default:
8817 /* Error in request */
8818 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8819 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8823 /****************************************************************************
8824 Reply to a SMBtrans2.
8825 ****************************************************************************/
8827 void reply_trans2(struct smb_request *req)
8829 connection_struct *conn = req->conn;
8830 unsigned int dsoff;
8831 unsigned int dscnt;
8832 unsigned int psoff;
8833 unsigned int pscnt;
8834 unsigned int tran_call;
8835 struct trans_state *state;
8836 NTSTATUS result;
8838 START_PROFILE(SMBtrans2);
8840 if (req->wct < 14) {
8841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8842 END_PROFILE(SMBtrans2);
8843 return;
8846 dsoff = SVAL(req->vwv+12, 0);
8847 dscnt = SVAL(req->vwv+11, 0);
8848 psoff = SVAL(req->vwv+10, 0);
8849 pscnt = SVAL(req->vwv+9, 0);
8850 tran_call = SVAL(req->vwv+14, 0);
8852 result = allow_new_trans(conn->pending_trans, req->mid);
8853 if (!NT_STATUS_IS_OK(result)) {
8854 DEBUG(2, ("Got invalid trans2 request: %s\n",
8855 nt_errstr(result)));
8856 reply_nterror(req, result);
8857 END_PROFILE(SMBtrans2);
8858 return;
8861 if (IS_IPC(conn)) {
8862 switch (tran_call) {
8863 /* List the allowed trans2 calls on IPC$ */
8864 case TRANSACT2_OPEN:
8865 case TRANSACT2_GET_DFS_REFERRAL:
8866 case TRANSACT2_QFILEINFO:
8867 case TRANSACT2_QFSINFO:
8868 case TRANSACT2_SETFSINFO:
8869 break;
8870 default:
8871 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8872 END_PROFILE(SMBtrans2);
8873 return;
8877 if ((state = talloc(conn, struct trans_state)) == NULL) {
8878 DEBUG(0, ("talloc failed\n"));
8879 reply_nterror(req, NT_STATUS_NO_MEMORY);
8880 END_PROFILE(SMBtrans2);
8881 return;
8884 state->cmd = SMBtrans2;
8886 state->mid = req->mid;
8887 state->vuid = req->vuid;
8888 state->setup_count = SVAL(req->vwv+13, 0);
8889 state->setup = NULL;
8890 state->total_param = SVAL(req->vwv+0, 0);
8891 state->param = NULL;
8892 state->total_data = SVAL(req->vwv+1, 0);
8893 state->data = NULL;
8894 state->max_param_return = SVAL(req->vwv+2, 0);
8895 state->max_data_return = SVAL(req->vwv+3, 0);
8896 state->max_setup_return = SVAL(req->vwv+4, 0);
8897 state->close_on_completion = BITSETW(req->vwv+5, 0);
8898 state->one_way = BITSETW(req->vwv+5, 1);
8900 state->call = tran_call;
8902 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8903 is so as a sanity check */
8904 if (state->setup_count != 1) {
8906 * Need to have rc=0 for ioctl to get job id for OS/2.
8907 * Network printing will fail if function is not successful.
8908 * Similar function in reply.c will be used if protocol
8909 * is LANMAN1.0 instead of LM1.2X002.
8910 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8911 * outbuf doesn't have to be set(only job id is used).
8913 if ( (state->setup_count == 4)
8914 && (tran_call == TRANSACT2_IOCTL)
8915 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8916 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8917 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8918 } else {
8919 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8920 DEBUG(2,("Transaction is %d\n",tran_call));
8921 TALLOC_FREE(state);
8922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8923 END_PROFILE(SMBtrans2);
8924 return;
8928 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8929 goto bad_param;
8931 if (state->total_data) {
8933 if (trans_oob(state->total_data, 0, dscnt)
8934 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8935 goto bad_param;
8938 /* Can't use talloc here, the core routines do realloc on the
8939 * params and data. */
8940 state->data = (char *)SMB_MALLOC(state->total_data);
8941 if (state->data == NULL) {
8942 DEBUG(0,("reply_trans2: data malloc fail for %u "
8943 "bytes !\n", (unsigned int)state->total_data));
8944 TALLOC_FREE(state);
8945 reply_nterror(req, NT_STATUS_NO_MEMORY);
8946 END_PROFILE(SMBtrans2);
8947 return;
8950 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8953 if (state->total_param) {
8955 if (trans_oob(state->total_param, 0, pscnt)
8956 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8957 goto bad_param;
8960 /* Can't use talloc here, the core routines do realloc on the
8961 * params and data. */
8962 state->param = (char *)SMB_MALLOC(state->total_param);
8963 if (state->param == NULL) {
8964 DEBUG(0,("reply_trans: param malloc fail for %u "
8965 "bytes !\n", (unsigned int)state->total_param));
8966 SAFE_FREE(state->data);
8967 TALLOC_FREE(state);
8968 reply_nterror(req, NT_STATUS_NO_MEMORY);
8969 END_PROFILE(SMBtrans2);
8970 return;
8973 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8976 state->received_data = dscnt;
8977 state->received_param = pscnt;
8979 if ((state->received_param == state->total_param) &&
8980 (state->received_data == state->total_data)) {
8982 handle_trans2(conn, req, state);
8984 SAFE_FREE(state->data);
8985 SAFE_FREE(state->param);
8986 TALLOC_FREE(state);
8987 END_PROFILE(SMBtrans2);
8988 return;
8991 DLIST_ADD(conn->pending_trans, state);
8993 /* We need to send an interim response then receive the rest
8994 of the parameter/data bytes */
8995 reply_outbuf(req, 0, 0);
8996 show_msg((char *)req->outbuf);
8997 END_PROFILE(SMBtrans2);
8998 return;
9000 bad_param:
9002 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9003 SAFE_FREE(state->data);
9004 SAFE_FREE(state->param);
9005 TALLOC_FREE(state);
9006 END_PROFILE(SMBtrans2);
9007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9011 /****************************************************************************
9012 Reply to a SMBtranss2
9013 ****************************************************************************/
9015 void reply_transs2(struct smb_request *req)
9017 connection_struct *conn = req->conn;
9018 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9019 struct trans_state *state;
9021 START_PROFILE(SMBtranss2);
9023 show_msg((const char *)req->inbuf);
9025 /* Windows clients expect all replies to
9026 a transact secondary (SMBtranss2 0x33)
9027 to have a command code of transact
9028 (SMBtrans2 0x32). See bug #8989
9029 and also [MS-CIFS] section 2.2.4.47.2
9030 for details.
9032 req->cmd = SMBtrans2;
9034 if (req->wct < 8) {
9035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9036 END_PROFILE(SMBtranss2);
9037 return;
9040 for (state = conn->pending_trans; state != NULL;
9041 state = state->next) {
9042 if (state->mid == req->mid) {
9043 break;
9047 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9049 END_PROFILE(SMBtranss2);
9050 return;
9053 /* Revise state->total_param and state->total_data in case they have
9054 changed downwards */
9056 if (SVAL(req->vwv+0, 0) < state->total_param)
9057 state->total_param = SVAL(req->vwv+0, 0);
9058 if (SVAL(req->vwv+1, 0) < state->total_data)
9059 state->total_data = SVAL(req->vwv+1, 0);
9061 pcnt = SVAL(req->vwv+2, 0);
9062 poff = SVAL(req->vwv+3, 0);
9063 pdisp = SVAL(req->vwv+4, 0);
9065 dcnt = SVAL(req->vwv+5, 0);
9066 doff = SVAL(req->vwv+6, 0);
9067 ddisp = SVAL(req->vwv+7, 0);
9069 state->received_param += pcnt;
9070 state->received_data += dcnt;
9072 if ((state->received_data > state->total_data) ||
9073 (state->received_param > state->total_param))
9074 goto bad_param;
9076 if (pcnt) {
9077 if (trans_oob(state->total_param, pdisp, pcnt)
9078 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9079 goto bad_param;
9081 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9084 if (dcnt) {
9085 if (trans_oob(state->total_data, ddisp, dcnt)
9086 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9087 goto bad_param;
9089 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9092 if ((state->received_param < state->total_param) ||
9093 (state->received_data < state->total_data)) {
9094 END_PROFILE(SMBtranss2);
9095 return;
9098 handle_trans2(conn, req, state);
9100 DLIST_REMOVE(conn->pending_trans, state);
9101 SAFE_FREE(state->data);
9102 SAFE_FREE(state->param);
9103 TALLOC_FREE(state);
9105 END_PROFILE(SMBtranss2);
9106 return;
9108 bad_param:
9110 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9111 DLIST_REMOVE(conn->pending_trans, state);
9112 SAFE_FREE(state->data);
9113 SAFE_FREE(state->param);
9114 TALLOC_FREE(state);
9115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9116 END_PROFILE(SMBtranss2);
9117 return;