s3:lib: Factor read_ea_list_entry() and read_nttrans_ea_list() out so they can be...
[Samba.git] / source3 / smbd / trans2.c
blob25de505e416390fe1757724ff6a8e27345cb16a9
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;
3075 if (fname == NULL || fname->base_name == NULL) {
3076 filename = ".";
3077 } else {
3078 filename = fname->base_name;
3081 if (IS_IPC(conn)) {
3082 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3083 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3084 "info level (0x%x) on IPC$.\n",
3085 (unsigned int)info_level));
3086 return NT_STATUS_ACCESS_DENIED;
3090 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3092 ZERO_STRUCT(smb_fname);
3093 smb_fname.base_name = discard_const_p(char, filename);
3095 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3096 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3097 return map_nt_error_from_unix(errno);
3100 st = smb_fname.st;
3102 *ppdata = (char *)SMB_REALLOC(
3103 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3104 if (*ppdata == NULL) {
3105 return NT_STATUS_NO_MEMORY;
3108 pdata = *ppdata;
3109 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3110 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3112 switch (info_level) {
3113 case SMB_INFO_ALLOCATION:
3115 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3116 data_len = 18;
3117 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3118 return map_nt_error_from_unix(errno);
3121 block_size = lp_block_size(snum);
3122 if (bsize < block_size) {
3123 uint64_t factor = block_size/bsize;
3124 bsize = block_size;
3125 dsize /= factor;
3126 dfree /= factor;
3128 if (bsize > block_size) {
3129 uint64_t factor = bsize/block_size;
3130 bsize = block_size;
3131 dsize *= factor;
3132 dfree *= factor;
3134 bytes_per_sector = 512;
3135 sectors_per_unit = bsize/bytes_per_sector;
3137 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3138 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3139 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3141 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3142 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3143 SIVAL(pdata,l1_cUnit,dsize);
3144 SIVAL(pdata,l1_cUnitAvail,dfree);
3145 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3146 break;
3149 case SMB_INFO_VOLUME:
3150 /* Return volume name */
3152 * Add volume serial number - hash of a combination of
3153 * the called hostname and the service name.
3155 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3157 * Win2k3 and previous mess this up by sending a name length
3158 * one byte short. I believe only older clients (OS/2 Win9x) use
3159 * this call so try fixing this by adding a terminating null to
3160 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3162 len = srvstr_push(
3163 pdata, flags2,
3164 pdata+l2_vol_szVolLabel, vname,
3165 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3166 STR_NOALIGN|STR_TERMINATE);
3167 SCVAL(pdata,l2_vol_cch,len);
3168 data_len = l2_vol_szVolLabel + len;
3169 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3170 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3171 len, vname));
3172 break;
3174 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3175 case SMB_FS_ATTRIBUTE_INFORMATION:
3177 additional_flags = 0;
3178 #if defined(HAVE_SYS_QUOTAS)
3179 additional_flags |= FILE_VOLUME_QUOTAS;
3180 #endif
3182 if(lp_nt_acl_support(SNUM(conn))) {
3183 additional_flags |= FILE_PERSISTENT_ACLS;
3186 /* Capabilities are filled in at connection time through STATVFS call */
3187 additional_flags |= conn->fs_capabilities;
3188 additional_flags |= lp_parm_int(conn->params->service,
3189 "share", "fake_fscaps",
3192 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3193 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3194 additional_flags); /* FS ATTRIBUTES */
3196 SIVAL(pdata,4,255); /* Max filename component length */
3197 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3198 and will think we can't do long filenames */
3199 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3200 PTR_DIFF(end_data, pdata+12),
3201 STR_UNICODE);
3202 SIVAL(pdata,8,len);
3203 data_len = 12 + len;
3204 break;
3206 case SMB_QUERY_FS_LABEL_INFO:
3207 case SMB_FS_LABEL_INFORMATION:
3208 len = srvstr_push(pdata, flags2, pdata+4, vname,
3209 PTR_DIFF(end_data, pdata+4), 0);
3210 data_len = 4 + len;
3211 SIVAL(pdata,0,len);
3212 break;
3214 case SMB_QUERY_FS_VOLUME_INFO:
3215 case SMB_FS_VOLUME_INFORMATION:
3218 * Add volume serial number - hash of a combination of
3219 * the called hostname and the service name.
3221 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3222 (str_checksum(get_local_machine_name())<<16));
3224 /* Max label len is 32 characters. */
3225 len = srvstr_push(pdata, flags2, pdata+18, vname,
3226 PTR_DIFF(end_data, pdata+18),
3227 STR_UNICODE);
3228 SIVAL(pdata,12,len);
3229 data_len = 18+len;
3231 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3232 (int)strlen(vname),vname,
3233 lp_servicename(talloc_tos(), snum)));
3234 break;
3236 case SMB_QUERY_FS_SIZE_INFO:
3237 case SMB_FS_SIZE_INFORMATION:
3239 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3240 data_len = 24;
3241 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3242 return map_nt_error_from_unix(errno);
3244 block_size = lp_block_size(snum);
3245 if (bsize < block_size) {
3246 uint64_t factor = block_size/bsize;
3247 bsize = block_size;
3248 dsize /= factor;
3249 dfree /= factor;
3251 if (bsize > block_size) {
3252 uint64_t factor = bsize/block_size;
3253 bsize = block_size;
3254 dsize *= factor;
3255 dfree *= factor;
3257 bytes_per_sector = 512;
3258 sectors_per_unit = bsize/bytes_per_sector;
3259 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3260 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3261 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3262 SBIG_UINT(pdata,0,dsize);
3263 SBIG_UINT(pdata,8,dfree);
3264 SIVAL(pdata,16,sectors_per_unit);
3265 SIVAL(pdata,20,bytes_per_sector);
3266 break;
3269 case SMB_FS_FULL_SIZE_INFORMATION:
3271 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3272 data_len = 32;
3273 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3274 return map_nt_error_from_unix(errno);
3276 block_size = lp_block_size(snum);
3277 if (bsize < block_size) {
3278 uint64_t factor = block_size/bsize;
3279 bsize = block_size;
3280 dsize /= factor;
3281 dfree /= factor;
3283 if (bsize > block_size) {
3284 uint64_t factor = bsize/block_size;
3285 bsize = block_size;
3286 dsize *= factor;
3287 dfree *= factor;
3289 bytes_per_sector = 512;
3290 sectors_per_unit = bsize/bytes_per_sector;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3292 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3293 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3294 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3295 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3296 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3297 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3298 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3299 break;
3302 case SMB_QUERY_FS_DEVICE_INFO:
3303 case SMB_FS_DEVICE_INFORMATION:
3305 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3307 if (!CAN_WRITE(conn)) {
3308 characteristics |= FILE_READ_ONLY_DEVICE;
3310 data_len = 8;
3311 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3312 SIVAL(pdata,4,characteristics);
3313 break;
3316 #ifdef HAVE_SYS_QUOTAS
3317 case SMB_FS_QUOTA_INFORMATION:
3319 * what we have to send --metze:
3321 * Unknown1: 24 NULL bytes
3322 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3323 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3324 * Quota Flags: 2 byte :
3325 * Unknown3: 6 NULL bytes
3327 * 48 bytes total
3329 * details for Quota Flags:
3331 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3332 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3333 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3334 * 0x0001 Enable Quotas: enable quota for this fs
3338 /* we need to fake up a fsp here,
3339 * because its not send in this call
3341 files_struct fsp;
3342 SMB_NTQUOTA_STRUCT quotas;
3344 ZERO_STRUCT(fsp);
3345 ZERO_STRUCT(quotas);
3347 fsp.conn = conn;
3348 fsp.fnum = FNUM_FIELD_INVALID;
3350 /* access check */
3351 if (get_current_uid(conn) != 0) {
3352 DEBUG(0,("set_user_quota: access_denied "
3353 "service [%s] user [%s]\n",
3354 lp_servicename(talloc_tos(), SNUM(conn)),
3355 conn->session_info->unix_info->unix_name));
3356 return NT_STATUS_ACCESS_DENIED;
3359 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3360 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3361 return map_nt_error_from_unix(errno);
3364 data_len = 48;
3366 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3367 lp_servicename(talloc_tos(), SNUM(conn))));
3369 /* Unknown1 24 NULL bytes*/
3370 SBIG_UINT(pdata,0,(uint64_t)0);
3371 SBIG_UINT(pdata,8,(uint64_t)0);
3372 SBIG_UINT(pdata,16,(uint64_t)0);
3374 /* Default Soft Quota 8 bytes */
3375 SBIG_UINT(pdata,24,quotas.softlim);
3377 /* Default Hard Quota 8 bytes */
3378 SBIG_UINT(pdata,32,quotas.hardlim);
3380 /* Quota flag 2 bytes */
3381 SSVAL(pdata,40,quotas.qflags);
3383 /* Unknown3 6 NULL bytes */
3384 SSVAL(pdata,42,0);
3385 SIVAL(pdata,44,0);
3387 break;
3389 #endif /* HAVE_SYS_QUOTAS */
3390 case SMB_FS_OBJECTID_INFORMATION:
3392 unsigned char objid[16];
3393 struct smb_extended_info extended_info;
3394 memcpy(pdata,create_volume_objectid(conn, objid),16);
3395 samba_extended_info_version (&extended_info);
3396 SIVAL(pdata,16,extended_info.samba_magic);
3397 SIVAL(pdata,20,extended_info.samba_version);
3398 SIVAL(pdata,24,extended_info.samba_subversion);
3399 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3400 memcpy(pdata+36,extended_info.samba_version_string,28);
3401 data_len = 64;
3402 break;
3406 * Query the version and capabilities of the CIFS UNIX extensions
3407 * in use.
3410 case SMB_QUERY_CIFS_UNIX_INFO:
3412 bool large_write = lp_min_receive_file_size() &&
3413 !srv_is_signing_active(conn->sconn);
3414 bool large_read = !srv_is_signing_active(conn->sconn);
3415 int encrypt_caps = 0;
3417 if (!lp_unix_extensions()) {
3418 return NT_STATUS_INVALID_LEVEL;
3421 switch (conn->encrypt_level) {
3422 case SMB_SIGNING_OFF:
3423 encrypt_caps = 0;
3424 break;
3425 case SMB_SIGNING_IF_REQUIRED:
3426 case SMB_SIGNING_DEFAULT:
3427 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3428 break;
3429 case SMB_SIGNING_REQUIRED:
3430 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3431 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3432 large_write = false;
3433 large_read = false;
3434 break;
3437 data_len = 12;
3438 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3439 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3441 /* We have POSIX ACLs, pathname, encryption,
3442 * large read/write, and locking capability. */
3444 SBIG_UINT(pdata,4,((uint64_t)(
3445 CIFS_UNIX_POSIX_ACLS_CAP|
3446 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3447 CIFS_UNIX_FCNTL_LOCKS_CAP|
3448 CIFS_UNIX_EXTATTR_CAP|
3449 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3450 encrypt_caps|
3451 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3452 (large_write ?
3453 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3454 break;
3457 case SMB_QUERY_POSIX_FS_INFO:
3459 int rc;
3460 vfs_statvfs_struct svfs;
3462 if (!lp_unix_extensions()) {
3463 return NT_STATUS_INVALID_LEVEL;
3466 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3468 if (!rc) {
3469 data_len = 56;
3470 SIVAL(pdata,0,svfs.OptimalTransferSize);
3471 SIVAL(pdata,4,svfs.BlockSize);
3472 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3473 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3474 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3475 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3476 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3477 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3478 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3479 #ifdef EOPNOTSUPP
3480 } else if (rc == EOPNOTSUPP) {
3481 return NT_STATUS_INVALID_LEVEL;
3482 #endif /* EOPNOTSUPP */
3483 } else {
3484 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3485 return NT_STATUS_DOS(ERRSRV, ERRerror);
3487 break;
3490 case SMB_QUERY_POSIX_WHOAMI:
3492 uint32_t flags = 0;
3493 uint32_t sid_bytes;
3494 int i;
3496 if (!lp_unix_extensions()) {
3497 return NT_STATUS_INVALID_LEVEL;
3500 if (max_data_bytes < 40) {
3501 return NT_STATUS_BUFFER_TOO_SMALL;
3504 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3505 flags |= SMB_WHOAMI_GUEST;
3508 /* NOTE: 8 bytes for UID/GID, irrespective of native
3509 * platform size. This matches
3510 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3512 data_len = 4 /* flags */
3513 + 4 /* flag mask */
3514 + 8 /* uid */
3515 + 8 /* gid */
3516 + 4 /* ngroups */
3517 + 4 /* num_sids */
3518 + 4 /* SID bytes */
3519 + 4 /* pad/reserved */
3520 + (conn->session_info->unix_token->ngroups * 8)
3521 /* groups list */
3522 + (conn->session_info->security_token->num_sids *
3523 SID_MAX_SIZE)
3524 /* SID list */;
3526 SIVAL(pdata, 0, flags);
3527 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3528 SBIG_UINT(pdata, 8,
3529 (uint64_t)conn->session_info->unix_token->uid);
3530 SBIG_UINT(pdata, 16,
3531 (uint64_t)conn->session_info->unix_token->gid);
3534 if (data_len >= max_data_bytes) {
3535 /* Potential overflow, skip the GIDs and SIDs. */
3537 SIVAL(pdata, 24, 0); /* num_groups */
3538 SIVAL(pdata, 28, 0); /* num_sids */
3539 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3540 SIVAL(pdata, 36, 0); /* reserved */
3542 data_len = 40;
3543 break;
3546 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3547 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3549 /* We walk the SID list twice, but this call is fairly
3550 * infrequent, and I don't expect that it's performance
3551 * sensitive -- jpeach
3553 for (i = 0, sid_bytes = 0;
3554 i < conn->session_info->security_token->num_sids; ++i) {
3555 sid_bytes += ndr_size_dom_sid(
3556 &conn->session_info->security_token->sids[i],
3560 /* SID list byte count */
3561 SIVAL(pdata, 32, sid_bytes);
3563 /* 4 bytes pad/reserved - must be zero */
3564 SIVAL(pdata, 36, 0);
3565 data_len = 40;
3567 /* GID list */
3568 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3569 SBIG_UINT(pdata, data_len,
3570 (uint64_t)conn->session_info->unix_token->groups[i]);
3571 data_len += 8;
3574 /* SID list */
3575 for (i = 0;
3576 i < conn->session_info->security_token->num_sids; ++i) {
3577 int sid_len = ndr_size_dom_sid(
3578 &conn->session_info->security_token->sids[i],
3581 sid_linearize(pdata + data_len, sid_len,
3582 &conn->session_info->security_token->sids[i]);
3583 data_len += sid_len;
3586 break;
3589 case SMB_MAC_QUERY_FS_INFO:
3591 * Thursby MAC extension... ONLY on NTFS filesystems
3592 * once we do streams then we don't need this
3594 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3595 data_len = 88;
3596 SIVAL(pdata,84,0x100); /* Don't support mac... */
3597 break;
3599 /* drop through */
3600 default:
3601 return NT_STATUS_INVALID_LEVEL;
3604 *ret_data_len = data_len;
3605 return NT_STATUS_OK;
3608 /****************************************************************************
3609 Reply to a TRANS2_QFSINFO (query filesystem info).
3610 ****************************************************************************/
3612 static void call_trans2qfsinfo(connection_struct *conn,
3613 struct smb_request *req,
3614 char **pparams, int total_params,
3615 char **ppdata, int total_data,
3616 unsigned int max_data_bytes)
3618 char *params = *pparams;
3619 uint16_t info_level;
3620 int data_len = 0;
3621 NTSTATUS status;
3623 if (total_params < 2) {
3624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3625 return;
3628 info_level = SVAL(params,0);
3630 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3631 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3632 DEBUG(0,("call_trans2qfsinfo: encryption required "
3633 "and info level 0x%x sent.\n",
3634 (unsigned int)info_level));
3635 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3636 return;
3640 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3642 status = smbd_do_qfsinfo(conn, req,
3643 info_level,
3644 req->flags2,
3645 max_data_bytes,
3646 NULL,
3647 ppdata, &data_len);
3648 if (!NT_STATUS_IS_OK(status)) {
3649 reply_nterror(req, status);
3650 return;
3653 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3654 max_data_bytes);
3656 DEBUG( 4, ( "%s info_level = %d\n",
3657 smb_fn_name(req->cmd), info_level) );
3659 return;
3662 /****************************************************************************
3663 Reply to a TRANS2_SETFSINFO (set filesystem info).
3664 ****************************************************************************/
3666 static void call_trans2setfsinfo(connection_struct *conn,
3667 struct smb_request *req,
3668 char **pparams, int total_params,
3669 char **ppdata, int total_data,
3670 unsigned int max_data_bytes)
3672 struct smbd_server_connection *sconn = req->sconn;
3673 char *pdata = *ppdata;
3674 char *params = *pparams;
3675 uint16 info_level;
3677 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3678 lp_servicename(talloc_tos(), SNUM(conn))));
3680 /* */
3681 if (total_params < 4) {
3682 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3683 total_params));
3684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3685 return;
3688 info_level = SVAL(params,2);
3690 if (IS_IPC(conn)) {
3691 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3692 info_level != SMB_SET_CIFS_UNIX_INFO) {
3693 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3694 "info level (0x%x) on IPC$.\n",
3695 (unsigned int)info_level));
3696 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3697 return;
3701 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3702 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3703 DEBUG(0,("call_trans2setfsinfo: encryption required "
3704 "and info level 0x%x sent.\n",
3705 (unsigned int)info_level));
3706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3707 return;
3711 switch(info_level) {
3712 case SMB_SET_CIFS_UNIX_INFO:
3713 if (!lp_unix_extensions()) {
3714 DEBUG(2,("call_trans2setfsinfo: "
3715 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3716 "unix extensions off\n"));
3717 reply_nterror(req,
3718 NT_STATUS_INVALID_LEVEL);
3719 return;
3722 /* There should be 12 bytes of capabilities set. */
3723 if (total_data < 12) {
3724 reply_nterror(
3725 req,
3726 NT_STATUS_INVALID_PARAMETER);
3727 return;
3729 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3730 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3731 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3732 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3733 /* Just print these values for now. */
3734 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3735 "major = %u, minor = %u cap_low = 0x%x, "
3736 "cap_high = 0x%xn",
3737 (unsigned int)sconn->
3738 smb1.unix_info.client_major,
3739 (unsigned int)sconn->
3740 smb1.unix_info.client_minor,
3741 (unsigned int)sconn->
3742 smb1.unix_info.client_cap_low,
3743 (unsigned int)sconn->
3744 smb1.unix_info.client_cap_high));
3746 /* Here is where we must switch to posix pathname processing... */
3747 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3748 lp_set_posix_pathnames();
3749 mangle_change_to_posix();
3752 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3753 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3754 /* Client that knows how to do posix locks,
3755 * but not posix open/mkdir operations. Set a
3756 * default type for read/write checks. */
3758 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3761 break;
3763 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3765 NTSTATUS status;
3766 size_t param_len = 0;
3767 size_t data_len = total_data;
3769 if (!lp_unix_extensions()) {
3770 reply_nterror(
3771 req,
3772 NT_STATUS_INVALID_LEVEL);
3773 return;
3776 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3777 reply_nterror(
3778 req,
3779 NT_STATUS_NOT_SUPPORTED);
3780 return;
3783 if (req->sconn->smb1.echo_handler.trusted_fde) {
3784 DEBUG( 2,("call_trans2setfsinfo: "
3785 "request transport encryption disabled"
3786 "with 'fork echo handler = yes'\n"));
3787 reply_nterror(
3788 req,
3789 NT_STATUS_NOT_SUPPORTED);
3790 return;
3793 DEBUG( 4,("call_trans2setfsinfo: "
3794 "request transport encryption.\n"));
3796 status = srv_request_encryption_setup(conn,
3797 (unsigned char **)ppdata,
3798 &data_len,
3799 (unsigned char **)pparams,
3800 &param_len);
3802 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3803 !NT_STATUS_IS_OK(status)) {
3804 reply_nterror(req, status);
3805 return;
3808 send_trans2_replies(conn, req,
3809 NT_STATUS_OK,
3810 *pparams,
3811 param_len,
3812 *ppdata,
3813 data_len,
3814 max_data_bytes);
3816 if (NT_STATUS_IS_OK(status)) {
3817 /* Server-side transport
3818 * encryption is now *on*. */
3819 status = srv_encryption_start(conn);
3820 if (!NT_STATUS_IS_OK(status)) {
3821 char *reason = talloc_asprintf(talloc_tos(),
3822 "Failure in setting "
3823 "up encrypted transport: %s",
3824 nt_errstr(status));
3825 exit_server_cleanly(reason);
3828 return;
3831 case SMB_FS_QUOTA_INFORMATION:
3833 files_struct *fsp = NULL;
3834 SMB_NTQUOTA_STRUCT quotas;
3836 ZERO_STRUCT(quotas);
3838 /* access check */
3839 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3840 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3841 lp_servicename(talloc_tos(), SNUM(conn)),
3842 conn->session_info->unix_info->unix_name));
3843 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3844 return;
3847 /* note: normaly there're 48 bytes,
3848 * but we didn't use the last 6 bytes for now
3849 * --metze
3851 fsp = file_fsp(req, SVAL(params,0));
3853 if (!check_fsp_ntquota_handle(conn, req,
3854 fsp)) {
3855 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3856 reply_nterror(
3857 req, NT_STATUS_INVALID_HANDLE);
3858 return;
3861 if (total_data < 42) {
3862 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3863 total_data));
3864 reply_nterror(
3865 req,
3866 NT_STATUS_INVALID_PARAMETER);
3867 return;
3870 /* unknown_1 24 NULL bytes in pdata*/
3872 /* the soft quotas 8 bytes (uint64_t)*/
3873 quotas.softlim = BVAL(pdata,24);
3875 /* the hard quotas 8 bytes (uint64_t)*/
3876 quotas.hardlim = BVAL(pdata,32);
3878 /* quota_flags 2 bytes **/
3879 quotas.qflags = SVAL(pdata,40);
3881 /* unknown_2 6 NULL bytes follow*/
3883 /* now set the quotas */
3884 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3885 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3886 reply_nterror(req, map_nt_error_from_unix(errno));
3887 return;
3890 break;
3892 default:
3893 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3894 info_level));
3895 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3896 return;
3897 break;
3901 * sending this reply works fine,
3902 * but I'm not sure it's the same
3903 * like windows do...
3904 * --metze
3906 reply_outbuf(req, 10, 0);
3909 #if defined(HAVE_POSIX_ACLS)
3910 /****************************************************************************
3911 Utility function to count the number of entries in a POSIX acl.
3912 ****************************************************************************/
3914 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3916 unsigned int ace_count = 0;
3917 int entry_id = SMB_ACL_FIRST_ENTRY;
3918 SMB_ACL_ENTRY_T entry;
3920 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3921 /* get_next... */
3922 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3923 entry_id = SMB_ACL_NEXT_ENTRY;
3925 ace_count++;
3927 return ace_count;
3930 /****************************************************************************
3931 Utility function to marshall a POSIX acl into wire format.
3932 ****************************************************************************/
3934 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3936 int entry_id = SMB_ACL_FIRST_ENTRY;
3937 SMB_ACL_ENTRY_T entry;
3939 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3940 SMB_ACL_TAG_T tagtype;
3941 SMB_ACL_PERMSET_T permset;
3942 unsigned char perms = 0;
3943 unsigned int own_grp;
3945 /* get_next... */
3946 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3947 entry_id = SMB_ACL_NEXT_ENTRY;
3950 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3951 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3952 return False;
3955 if (sys_acl_get_permset(entry, &permset) == -1) {
3956 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3957 return False;
3960 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3961 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3962 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3964 SCVAL(pdata,1,perms);
3966 switch (tagtype) {
3967 case SMB_ACL_USER_OBJ:
3968 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3969 own_grp = (unsigned int)pst->st_ex_uid;
3970 SIVAL(pdata,2,own_grp);
3971 SIVAL(pdata,6,0);
3972 break;
3973 case SMB_ACL_USER:
3975 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3976 if (!puid) {
3977 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3978 return False;
3980 own_grp = (unsigned int)*puid;
3981 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3982 SIVAL(pdata,2,own_grp);
3983 SIVAL(pdata,6,0);
3984 break;
3986 case SMB_ACL_GROUP_OBJ:
3987 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3988 own_grp = (unsigned int)pst->st_ex_gid;
3989 SIVAL(pdata,2,own_grp);
3990 SIVAL(pdata,6,0);
3991 break;
3992 case SMB_ACL_GROUP:
3994 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3995 if (!pgid) {
3996 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3997 return False;
3999 own_grp = (unsigned int)*pgid;
4000 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4001 SIVAL(pdata,2,own_grp);
4002 SIVAL(pdata,6,0);
4003 break;
4005 case SMB_ACL_MASK:
4006 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4007 SIVAL(pdata,2,0xFFFFFFFF);
4008 SIVAL(pdata,6,0xFFFFFFFF);
4009 break;
4010 case SMB_ACL_OTHER:
4011 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4012 SIVAL(pdata,2,0xFFFFFFFF);
4013 SIVAL(pdata,6,0xFFFFFFFF);
4014 break;
4015 default:
4016 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4017 return False;
4019 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4022 return True;
4024 #endif
4026 /****************************************************************************
4027 Store the FILE_UNIX_BASIC info.
4028 ****************************************************************************/
4030 static char *store_file_unix_basic(connection_struct *conn,
4031 char *pdata,
4032 files_struct *fsp,
4033 const SMB_STRUCT_STAT *psbuf)
4035 uint64_t file_index = get_FileIndex(conn, psbuf);
4036 dev_t devno;
4038 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4039 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4041 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4042 pdata += 8;
4044 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4045 pdata += 8;
4047 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4048 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4050 pdata += 24;
4052 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4053 SIVAL(pdata,4,0);
4054 pdata += 8;
4056 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4057 SIVAL(pdata,4,0);
4058 pdata += 8;
4060 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4061 pdata += 4;
4063 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4064 devno = psbuf->st_ex_rdev;
4065 } else {
4066 devno = psbuf->st_ex_dev;
4069 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4070 SIVAL(pdata,4,0);
4071 pdata += 8;
4073 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4074 SIVAL(pdata,4,0);
4075 pdata += 8;
4077 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4078 pdata += 8;
4080 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4081 SIVAL(pdata,4,0);
4082 pdata += 8;
4084 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4085 SIVAL(pdata,4,0);
4086 pdata += 8;
4088 return pdata;
4091 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4092 * the chflags(2) (or equivalent) flags.
4094 * XXX: this really should be behind the VFS interface. To do this, we would
4095 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4096 * Each VFS module could then implement its own mapping as appropriate for the
4097 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4099 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4100 info2_flags_map[] =
4102 #ifdef UF_NODUMP
4103 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4104 #endif
4106 #ifdef UF_IMMUTABLE
4107 { UF_IMMUTABLE, EXT_IMMUTABLE },
4108 #endif
4110 #ifdef UF_APPEND
4111 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4112 #endif
4114 #ifdef UF_HIDDEN
4115 { UF_HIDDEN, EXT_HIDDEN },
4116 #endif
4118 /* Do not remove. We need to guarantee that this array has at least one
4119 * entry to build on HP-UX.
4121 { 0, 0 }
4125 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4126 uint32 *smb_fflags, uint32 *smb_fmask)
4128 int i;
4130 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4131 *smb_fmask |= info2_flags_map[i].smb_fflag;
4132 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4133 *smb_fflags |= info2_flags_map[i].smb_fflag;
4138 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4139 const uint32 smb_fflags,
4140 const uint32 smb_fmask,
4141 int *stat_fflags)
4143 uint32 max_fmask = 0;
4144 int i;
4146 *stat_fflags = psbuf->st_ex_flags;
4148 /* For each flags requested in smb_fmask, check the state of the
4149 * corresponding flag in smb_fflags and set or clear the matching
4150 * stat flag.
4153 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4154 max_fmask |= info2_flags_map[i].smb_fflag;
4155 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4156 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4157 *stat_fflags |= info2_flags_map[i].stat_fflag;
4158 } else {
4159 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4164 /* If smb_fmask is asking to set any bits that are not supported by
4165 * our flag mappings, we should fail.
4167 if ((smb_fmask & max_fmask) != smb_fmask) {
4168 return False;
4171 return True;
4175 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4176 * of file flags and birth (create) time.
4178 static char *store_file_unix_basic_info2(connection_struct *conn,
4179 char *pdata,
4180 files_struct *fsp,
4181 const SMB_STRUCT_STAT *psbuf)
4183 uint32 file_flags = 0;
4184 uint32 flags_mask = 0;
4186 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4188 /* Create (birth) time 64 bit */
4189 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4190 pdata += 8;
4192 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4193 SIVAL(pdata, 0, file_flags); /* flags */
4194 SIVAL(pdata, 4, flags_mask); /* mask */
4195 pdata += 8;
4197 return pdata;
4200 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4201 const struct stream_struct *streams,
4202 char *data,
4203 unsigned int max_data_bytes,
4204 unsigned int *data_size)
4206 unsigned int i;
4207 unsigned int ofs = 0;
4209 for (i = 0; i < num_streams; i++) {
4210 unsigned int next_offset;
4211 size_t namelen;
4212 smb_ucs2_t *namebuf;
4214 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4215 streams[i].name, &namelen) ||
4216 namelen <= 2)
4218 return NT_STATUS_INVALID_PARAMETER;
4222 * name_buf is now null-terminated, we need to marshall as not
4223 * terminated
4226 namelen -= 2;
4229 * We cannot overflow ...
4231 if ((ofs + 24 + namelen) > max_data_bytes) {
4232 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4233 i));
4234 TALLOC_FREE(namebuf);
4235 return STATUS_BUFFER_OVERFLOW;
4238 SIVAL(data, ofs+4, namelen);
4239 SOFF_T(data, ofs+8, streams[i].size);
4240 SOFF_T(data, ofs+16, streams[i].alloc_size);
4241 memcpy(data+ofs+24, namebuf, namelen);
4242 TALLOC_FREE(namebuf);
4244 next_offset = ofs + 24 + namelen;
4246 if (i == num_streams-1) {
4247 SIVAL(data, ofs, 0);
4249 else {
4250 unsigned int align = ndr_align_size(next_offset, 8);
4252 if ((next_offset + align) > max_data_bytes) {
4253 DEBUG(10, ("refusing to overflow align "
4254 "reply at stream %u\n",
4255 i));
4256 TALLOC_FREE(namebuf);
4257 return STATUS_BUFFER_OVERFLOW;
4260 memset(data+next_offset, 0, align);
4261 next_offset += align;
4263 SIVAL(data, ofs, next_offset - ofs);
4264 ofs = next_offset;
4267 ofs = next_offset;
4270 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4272 *data_size = ofs;
4274 return NT_STATUS_OK;
4277 /****************************************************************************
4278 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4279 ****************************************************************************/
4281 static void call_trans2qpipeinfo(connection_struct *conn,
4282 struct smb_request *req,
4283 unsigned int tran_call,
4284 char **pparams, int total_params,
4285 char **ppdata, int total_data,
4286 unsigned int max_data_bytes)
4288 char *params = *pparams;
4289 char *pdata = *ppdata;
4290 unsigned int data_size = 0;
4291 unsigned int param_size = 2;
4292 uint16 info_level;
4293 files_struct *fsp;
4295 if (!params) {
4296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4297 return;
4300 if (total_params < 4) {
4301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4302 return;
4305 fsp = file_fsp(req, SVAL(params,0));
4306 if (!fsp_is_np(fsp)) {
4307 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4308 return;
4311 info_level = SVAL(params,2);
4313 *pparams = (char *)SMB_REALLOC(*pparams,2);
4314 if (*pparams == NULL) {
4315 reply_nterror(req, NT_STATUS_NO_MEMORY);
4316 return;
4318 params = *pparams;
4319 SSVAL(params,0,0);
4320 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4321 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4322 if (*ppdata == NULL ) {
4323 reply_nterror(req, NT_STATUS_NO_MEMORY);
4324 return;
4326 pdata = *ppdata;
4328 switch (info_level) {
4329 case SMB_FILE_STANDARD_INFORMATION:
4330 memset(pdata,0,24);
4331 SOFF_T(pdata,0,4096LL);
4332 SIVAL(pdata,16,1);
4333 SIVAL(pdata,20,1);
4334 data_size = 24;
4335 break;
4337 default:
4338 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4339 return;
4342 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4343 max_data_bytes);
4345 return;
4348 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4349 TALLOC_CTX *mem_ctx,
4350 uint16_t info_level,
4351 files_struct *fsp,
4352 struct smb_filename *smb_fname,
4353 bool delete_pending,
4354 struct timespec write_time_ts,
4355 struct ea_list *ea_list,
4356 int lock_data_count,
4357 char *lock_data,
4358 uint16_t flags2,
4359 unsigned int max_data_bytes,
4360 char **ppdata,
4361 unsigned int *pdata_size)
4363 char *pdata = *ppdata;
4364 char *dstart, *dend;
4365 unsigned int data_size;
4366 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4367 time_t create_time, mtime, atime, c_time;
4368 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4369 char *p;
4370 char *base_name;
4371 char *dos_fname;
4372 int mode;
4373 int nlink;
4374 NTSTATUS status;
4375 uint64_t file_size = 0;
4376 uint64_t pos = 0;
4377 uint64_t allocation_size = 0;
4378 uint64_t file_index = 0;
4379 uint32_t access_mask = 0;
4381 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4382 return NT_STATUS_INVALID_LEVEL;
4385 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4386 smb_fname_str_dbg(smb_fname),
4387 fsp_fnum_dbg(fsp),
4388 info_level, max_data_bytes));
4390 mode = dos_mode(conn, smb_fname);
4391 nlink = psbuf->st_ex_nlink;
4393 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4394 nlink = 1;
4397 if ((nlink > 0) && delete_pending) {
4398 nlink -= 1;
4401 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4402 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4403 if (*ppdata == NULL) {
4404 return NT_STATUS_NO_MEMORY;
4406 pdata = *ppdata;
4407 dstart = pdata;
4408 dend = dstart + data_size - 1;
4410 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4411 update_stat_ex_mtime(psbuf, write_time_ts);
4414 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4415 mtime_ts = psbuf->st_ex_mtime;
4416 atime_ts = psbuf->st_ex_atime;
4417 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4419 if (lp_dos_filetime_resolution(SNUM(conn))) {
4420 dos_filetime_timespec(&create_time_ts);
4421 dos_filetime_timespec(&mtime_ts);
4422 dos_filetime_timespec(&atime_ts);
4423 dos_filetime_timespec(&ctime_ts);
4426 create_time = convert_timespec_to_time_t(create_time_ts);
4427 mtime = convert_timespec_to_time_t(mtime_ts);
4428 atime = convert_timespec_to_time_t(atime_ts);
4429 c_time = convert_timespec_to_time_t(ctime_ts);
4431 p = strrchr_m(smb_fname->base_name,'/');
4432 if (!p)
4433 base_name = smb_fname->base_name;
4434 else
4435 base_name = p+1;
4437 /* NT expects the name to be in an exact form of the *full*
4438 filename. See the trans2 torture test */
4439 if (ISDOT(base_name)) {
4440 dos_fname = talloc_strdup(mem_ctx, "\\");
4441 if (!dos_fname) {
4442 return NT_STATUS_NO_MEMORY;
4444 } else {
4445 dos_fname = talloc_asprintf(mem_ctx,
4446 "\\%s",
4447 smb_fname->base_name);
4448 if (!dos_fname) {
4449 return NT_STATUS_NO_MEMORY;
4451 if (is_ntfs_stream_smb_fname(smb_fname)) {
4452 dos_fname = talloc_asprintf(dos_fname, "%s",
4453 smb_fname->stream_name);
4454 if (!dos_fname) {
4455 return NT_STATUS_NO_MEMORY;
4459 string_replace(dos_fname, '/', '\\');
4462 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4464 if (!fsp) {
4465 /* Do we have this path open ? */
4466 files_struct *fsp1;
4467 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4468 fsp1 = file_find_di_first(conn->sconn, fileid);
4469 if (fsp1 && fsp1->initial_allocation_size) {
4470 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4474 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4475 file_size = get_file_size_stat(psbuf);
4478 if (fsp) {
4479 pos = fsp->fh->position_information;
4482 if (fsp) {
4483 access_mask = fsp->access_mask;
4484 } else {
4485 /* GENERIC_EXECUTE mapping from Windows */
4486 access_mask = 0x12019F;
4489 /* This should be an index number - looks like
4490 dev/ino to me :-)
4492 I think this causes us to fail the IFSKIT
4493 BasicFileInformationTest. -tpot */
4494 file_index = get_FileIndex(conn, psbuf);
4496 switch (info_level) {
4497 case SMB_INFO_STANDARD:
4498 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4499 data_size = 22;
4500 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4501 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4502 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4503 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4504 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4505 SSVAL(pdata,l1_attrFile,mode);
4506 break;
4508 case SMB_INFO_QUERY_EA_SIZE:
4510 unsigned int ea_size =
4511 estimate_ea_size(conn, fsp,
4512 smb_fname);
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4514 data_size = 26;
4515 srv_put_dos_date2(pdata,0,create_time);
4516 srv_put_dos_date2(pdata,4,atime);
4517 srv_put_dos_date2(pdata,8,mtime); /* write time */
4518 SIVAL(pdata,12,(uint32)file_size);
4519 SIVAL(pdata,16,(uint32)allocation_size);
4520 SSVAL(pdata,20,mode);
4521 SIVAL(pdata,22,ea_size);
4522 break;
4525 case SMB_INFO_IS_NAME_VALID:
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4527 if (fsp) {
4528 /* os/2 needs this ? really ?*/
4529 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4531 /* This is only reached for qpathinfo */
4532 data_size = 0;
4533 break;
4535 case SMB_INFO_QUERY_EAS_FROM_LIST:
4537 size_t total_ea_len = 0;
4538 struct ea_list *ea_file_list = NULL;
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4541 status =
4542 get_ea_list_from_file(mem_ctx, conn, fsp,
4543 smb_fname,
4544 &total_ea_len, &ea_file_list);
4545 if (!NT_STATUS_IS_OK(status)) {
4546 return status;
4549 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4551 if (!ea_list || (total_ea_len > data_size)) {
4552 data_size = 4;
4553 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4554 break;
4557 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4558 break;
4561 case SMB_INFO_QUERY_ALL_EAS:
4563 /* We have data_size bytes to put EA's into. */
4564 size_t total_ea_len = 0;
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4567 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4568 smb_fname,
4569 &total_ea_len, &ea_list);
4570 if (!NT_STATUS_IS_OK(status)) {
4571 return status;
4574 if (!ea_list || (total_ea_len > data_size)) {
4575 data_size = 4;
4576 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4577 break;
4580 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4581 break;
4584 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4586 /* This is FileFullEaInformation - 0xF which maps to
4587 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4589 /* We have data_size bytes to put EA's into. */
4590 size_t total_ea_len = 0;
4591 struct ea_list *ea_file_list = NULL;
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4595 /*TODO: add filtering and index handling */
4597 status =
4598 get_ea_list_from_file(mem_ctx, conn, fsp,
4599 smb_fname,
4600 &total_ea_len, &ea_file_list);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 return status;
4604 if (!ea_file_list) {
4605 return NT_STATUS_NO_EAS_ON_FILE;
4608 status = fill_ea_chained_buffer(mem_ctx,
4609 pdata,
4610 data_size,
4611 &data_size,
4612 conn, ea_file_list);
4613 if (!NT_STATUS_IS_OK(status)) {
4614 return status;
4616 break;
4619 case SMB_FILE_BASIC_INFORMATION:
4620 case SMB_QUERY_FILE_BASIC_INFO:
4622 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4624 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4625 } else {
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4627 data_size = 40;
4628 SIVAL(pdata,36,0);
4630 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4631 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4632 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4633 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4634 SIVAL(pdata,32,mode);
4636 DEBUG(5,("SMB_QFBI - "));
4637 DEBUG(5,("create: %s ", ctime(&create_time)));
4638 DEBUG(5,("access: %s ", ctime(&atime)));
4639 DEBUG(5,("write: %s ", ctime(&mtime)));
4640 DEBUG(5,("change: %s ", ctime(&c_time)));
4641 DEBUG(5,("mode: %x\n", mode));
4642 break;
4644 case SMB_FILE_STANDARD_INFORMATION:
4645 case SMB_QUERY_FILE_STANDARD_INFO:
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4648 data_size = 24;
4649 SOFF_T(pdata,0,allocation_size);
4650 SOFF_T(pdata,8,file_size);
4651 SIVAL(pdata,16,nlink);
4652 SCVAL(pdata,20,delete_pending?1:0);
4653 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4654 SSVAL(pdata,22,0); /* Padding. */
4655 break;
4657 case SMB_FILE_EA_INFORMATION:
4658 case SMB_QUERY_FILE_EA_INFO:
4660 unsigned int ea_size =
4661 estimate_ea_size(conn, fsp, smb_fname);
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4663 data_size = 4;
4664 SIVAL(pdata,0,ea_size);
4665 break;
4668 /* Get the 8.3 name - used if NT SMB was negotiated. */
4669 case SMB_QUERY_FILE_ALT_NAME_INFO:
4670 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4672 int len;
4673 char mangled_name[13];
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4675 if (!name_to_8_3(base_name,mangled_name,
4676 True,conn->params)) {
4677 return NT_STATUS_NO_MEMORY;
4679 len = srvstr_push(dstart, flags2,
4680 pdata+4, mangled_name,
4681 PTR_DIFF(dend, pdata+4),
4682 STR_UNICODE);
4683 data_size = 4 + len;
4684 SIVAL(pdata,0,len);
4685 break;
4688 case SMB_QUERY_FILE_NAME_INFO:
4690 int len;
4692 this must be *exactly* right for ACLs on mapped drives to work
4694 len = srvstr_push(dstart, flags2,
4695 pdata+4, dos_fname,
4696 PTR_DIFF(dend, pdata+4),
4697 STR_UNICODE);
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4699 data_size = 4 + len;
4700 SIVAL(pdata,0,len);
4701 break;
4704 case SMB_FILE_ALLOCATION_INFORMATION:
4705 case SMB_QUERY_FILE_ALLOCATION_INFO:
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4707 data_size = 8;
4708 SOFF_T(pdata,0,allocation_size);
4709 break;
4711 case SMB_FILE_END_OF_FILE_INFORMATION:
4712 case SMB_QUERY_FILE_END_OF_FILEINFO:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4714 data_size = 8;
4715 SOFF_T(pdata,0,file_size);
4716 break;
4718 case SMB_QUERY_FILE_ALL_INFO:
4719 case SMB_FILE_ALL_INFORMATION:
4721 int len;
4722 unsigned int ea_size =
4723 estimate_ea_size(conn, fsp, smb_fname);
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4725 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4726 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4727 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4728 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4729 SIVAL(pdata,32,mode);
4730 SIVAL(pdata,36,0); /* padding. */
4731 pdata += 40;
4732 SOFF_T(pdata,0,allocation_size);
4733 SOFF_T(pdata,8,file_size);
4734 SIVAL(pdata,16,nlink);
4735 SCVAL(pdata,20,delete_pending);
4736 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4737 SSVAL(pdata,22,0);
4738 pdata += 24;
4739 SIVAL(pdata,0,ea_size);
4740 pdata += 4; /* EA info */
4741 len = srvstr_push(dstart, flags2,
4742 pdata+4, dos_fname,
4743 PTR_DIFF(dend, pdata+4),
4744 STR_UNICODE);
4745 SIVAL(pdata,0,len);
4746 pdata += 4 + len;
4747 data_size = PTR_DIFF(pdata,(*ppdata));
4748 break;
4751 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4753 int len;
4754 unsigned int ea_size =
4755 estimate_ea_size(conn, fsp, smb_fname);
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4757 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4758 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4759 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4760 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4761 SIVAL(pdata, 0x20, mode);
4762 SIVAL(pdata, 0x24, 0); /* padding. */
4763 SBVAL(pdata, 0x28, allocation_size);
4764 SBVAL(pdata, 0x30, file_size);
4765 SIVAL(pdata, 0x38, nlink);
4766 SCVAL(pdata, 0x3C, delete_pending);
4767 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4768 SSVAL(pdata, 0x3E, 0); /* padding */
4769 SBVAL(pdata, 0x40, file_index);
4770 SIVAL(pdata, 0x48, ea_size);
4771 SIVAL(pdata, 0x4C, access_mask);
4772 SBVAL(pdata, 0x50, pos);
4773 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4774 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4776 pdata += 0x60;
4778 len = srvstr_push(dstart, flags2,
4779 pdata+4, dos_fname,
4780 PTR_DIFF(dend, pdata+4),
4781 STR_UNICODE);
4782 SIVAL(pdata,0,len);
4783 pdata += 4 + len;
4784 data_size = PTR_DIFF(pdata,(*ppdata));
4785 break;
4787 case SMB_FILE_INTERNAL_INFORMATION:
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4790 SBVAL(pdata, 0, file_index);
4791 data_size = 8;
4792 break;
4794 case SMB_FILE_ACCESS_INFORMATION:
4795 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4796 SIVAL(pdata, 0, access_mask);
4797 data_size = 4;
4798 break;
4800 case SMB_FILE_NAME_INFORMATION:
4801 /* Pathname with leading '\'. */
4803 size_t byte_len;
4804 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4805 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4806 SIVAL(pdata,0,byte_len);
4807 data_size = 4 + byte_len;
4808 break;
4811 case SMB_FILE_DISPOSITION_INFORMATION:
4812 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4813 data_size = 1;
4814 SCVAL(pdata,0,delete_pending);
4815 break;
4817 case SMB_FILE_POSITION_INFORMATION:
4818 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4819 data_size = 8;
4820 SOFF_T(pdata,0,pos);
4821 break;
4823 case SMB_FILE_MODE_INFORMATION:
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4825 SIVAL(pdata,0,mode);
4826 data_size = 4;
4827 break;
4829 case SMB_FILE_ALIGNMENT_INFORMATION:
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4831 SIVAL(pdata,0,0); /* No alignment needed. */
4832 data_size = 4;
4833 break;
4836 * NT4 server just returns "invalid query" to this - if we try
4837 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4838 * want this. JRA.
4840 /* The first statement above is false - verified using Thursby
4841 * client against NT4 -- gcolley.
4843 case SMB_QUERY_FILE_STREAM_INFO:
4844 case SMB_FILE_STREAM_INFORMATION: {
4845 unsigned int num_streams = 0;
4846 struct stream_struct *streams = NULL;
4848 DEBUG(10,("smbd_do_qfilepathinfo: "
4849 "SMB_FILE_STREAM_INFORMATION\n"));
4851 if (is_ntfs_stream_smb_fname(smb_fname)) {
4852 return NT_STATUS_INVALID_PARAMETER;
4855 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4856 talloc_tos(), &num_streams, &streams);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 DEBUG(10, ("could not get stream info: %s\n",
4860 nt_errstr(status)));
4861 return status;
4864 status = marshall_stream_info(num_streams, streams,
4865 pdata, max_data_bytes,
4866 &data_size);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 DEBUG(10, ("marshall_stream_info failed: %s\n",
4870 nt_errstr(status)));
4871 TALLOC_FREE(streams);
4872 return status;
4875 TALLOC_FREE(streams);
4877 break;
4879 case SMB_QUERY_COMPRESSION_INFO:
4880 case SMB_FILE_COMPRESSION_INFORMATION:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4882 SOFF_T(pdata,0,file_size);
4883 SIVAL(pdata,8,0); /* ??? */
4884 SIVAL(pdata,12,0); /* ??? */
4885 data_size = 16;
4886 break;
4888 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4889 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4890 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4891 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4892 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4893 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4894 SOFF_T(pdata,32,allocation_size);
4895 SOFF_T(pdata,40,file_size);
4896 SIVAL(pdata,48,mode);
4897 SIVAL(pdata,52,0); /* ??? */
4898 data_size = 56;
4899 break;
4901 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4902 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4903 SIVAL(pdata,0,mode);
4904 SIVAL(pdata,4,0);
4905 data_size = 8;
4906 break;
4909 * CIFS UNIX Extensions.
4912 case SMB_QUERY_FILE_UNIX_BASIC:
4914 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4915 data_size = PTR_DIFF(pdata,(*ppdata));
4917 DEBUG(4,("smbd_do_qfilepathinfo: "
4918 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4919 dump_data(4, (uint8_t *)(*ppdata), data_size);
4921 break;
4923 case SMB_QUERY_FILE_UNIX_INFO2:
4925 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4926 data_size = PTR_DIFF(pdata,(*ppdata));
4929 int i;
4930 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4932 for (i=0; i<100; i++)
4933 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4934 DEBUG(4,("\n"));
4937 break;
4939 case SMB_QUERY_FILE_UNIX_LINK:
4941 int len;
4942 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4944 if (!buffer) {
4945 return NT_STATUS_NO_MEMORY;
4948 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4949 #ifdef S_ISLNK
4950 if(!S_ISLNK(psbuf->st_ex_mode)) {
4951 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4953 #else
4954 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4955 #endif
4956 len = SMB_VFS_READLINK(conn,
4957 smb_fname->base_name,
4958 buffer, PATH_MAX);
4959 if (len == -1) {
4960 return map_nt_error_from_unix(errno);
4962 buffer[len] = 0;
4963 len = srvstr_push(dstart, flags2,
4964 pdata, buffer,
4965 PTR_DIFF(dend, pdata),
4966 STR_TERMINATE);
4967 pdata += len;
4968 data_size = PTR_DIFF(pdata,(*ppdata));
4970 break;
4973 #if defined(HAVE_POSIX_ACLS)
4974 case SMB_QUERY_POSIX_ACL:
4976 SMB_ACL_T file_acl = NULL;
4977 SMB_ACL_T def_acl = NULL;
4978 uint16 num_file_acls = 0;
4979 uint16 num_def_acls = 0;
4981 if (fsp && fsp->fh->fd != -1) {
4982 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4983 talloc_tos());
4984 } else {
4985 file_acl =
4986 SMB_VFS_SYS_ACL_GET_FILE(conn,
4987 smb_fname->base_name,
4988 SMB_ACL_TYPE_ACCESS,
4989 talloc_tos());
4992 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4993 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4994 "not implemented on "
4995 "filesystem containing %s\n",
4996 smb_fname->base_name));
4997 return NT_STATUS_NOT_IMPLEMENTED;
5000 if (S_ISDIR(psbuf->st_ex_mode)) {
5001 if (fsp && fsp->is_directory) {
5002 def_acl =
5003 SMB_VFS_SYS_ACL_GET_FILE(
5004 conn,
5005 fsp->fsp_name->base_name,
5006 SMB_ACL_TYPE_DEFAULT,
5007 talloc_tos());
5008 } else {
5009 def_acl =
5010 SMB_VFS_SYS_ACL_GET_FILE(
5011 conn,
5012 smb_fname->base_name,
5013 SMB_ACL_TYPE_DEFAULT,
5014 talloc_tos());
5016 def_acl = free_empty_sys_acl(conn, def_acl);
5019 num_file_acls = count_acl_entries(conn, file_acl);
5020 num_def_acls = count_acl_entries(conn, def_acl);
5022 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5023 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5024 data_size,
5025 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5026 SMB_POSIX_ACL_HEADER_SIZE) ));
5027 if (file_acl) {
5028 TALLOC_FREE(file_acl);
5030 if (def_acl) {
5031 TALLOC_FREE(def_acl);
5033 return NT_STATUS_BUFFER_TOO_SMALL;
5036 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5037 SSVAL(pdata,2,num_file_acls);
5038 SSVAL(pdata,4,num_def_acls);
5039 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5040 if (file_acl) {
5041 TALLOC_FREE(file_acl);
5043 if (def_acl) {
5044 TALLOC_FREE(def_acl);
5046 return NT_STATUS_INTERNAL_ERROR;
5048 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5049 if (file_acl) {
5050 TALLOC_FREE(file_acl);
5052 if (def_acl) {
5053 TALLOC_FREE(def_acl);
5055 return NT_STATUS_INTERNAL_ERROR;
5058 if (file_acl) {
5059 TALLOC_FREE(file_acl);
5061 if (def_acl) {
5062 TALLOC_FREE(def_acl);
5064 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5065 break;
5067 #endif
5070 case SMB_QUERY_POSIX_LOCK:
5072 uint64_t count;
5073 uint64_t offset;
5074 uint64_t smblctx;
5075 enum brl_type lock_type;
5077 /* We need an open file with a real fd for this. */
5078 if (!fsp || fsp->fh->fd == -1) {
5079 return NT_STATUS_INVALID_LEVEL;
5082 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5083 return NT_STATUS_INVALID_PARAMETER;
5086 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5087 case POSIX_LOCK_TYPE_READ:
5088 lock_type = READ_LOCK;
5089 break;
5090 case POSIX_LOCK_TYPE_WRITE:
5091 lock_type = WRITE_LOCK;
5092 break;
5093 case POSIX_LOCK_TYPE_UNLOCK:
5094 default:
5095 /* There's no point in asking for an unlock... */
5096 return NT_STATUS_INVALID_PARAMETER;
5099 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5100 #if defined(HAVE_LONGLONG)
5101 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5102 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5103 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5104 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5105 #else /* HAVE_LONGLONG */
5106 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5107 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5108 #endif /* HAVE_LONGLONG */
5110 status = query_lock(fsp,
5111 &smblctx,
5112 &count,
5113 &offset,
5114 &lock_type,
5115 POSIX_LOCK);
5117 if (ERROR_WAS_LOCK_DENIED(status)) {
5118 /* Here we need to report who has it locked... */
5119 data_size = POSIX_LOCK_DATA_SIZE;
5121 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5122 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5123 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5124 #if defined(HAVE_LONGLONG)
5125 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5126 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5127 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5128 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5129 #else /* HAVE_LONGLONG */
5130 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5131 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5132 #endif /* HAVE_LONGLONG */
5134 } else if (NT_STATUS_IS_OK(status)) {
5135 /* For success we just return a copy of what we sent
5136 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5137 data_size = POSIX_LOCK_DATA_SIZE;
5138 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5139 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5140 } else {
5141 return status;
5143 break;
5146 default:
5147 return NT_STATUS_INVALID_LEVEL;
5150 *pdata_size = data_size;
5151 return NT_STATUS_OK;
5154 /****************************************************************************
5155 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5156 file name or file id).
5157 ****************************************************************************/
5159 static void call_trans2qfilepathinfo(connection_struct *conn,
5160 struct smb_request *req,
5161 unsigned int tran_call,
5162 char **pparams, int total_params,
5163 char **ppdata, int total_data,
5164 unsigned int max_data_bytes)
5166 char *params = *pparams;
5167 char *pdata = *ppdata;
5168 uint16 info_level;
5169 unsigned int data_size = 0;
5170 unsigned int param_size = 2;
5171 struct smb_filename *smb_fname = NULL;
5172 bool delete_pending = False;
5173 struct timespec write_time_ts;
5174 files_struct *fsp = NULL;
5175 struct file_id fileid;
5176 struct ea_list *ea_list = NULL;
5177 int lock_data_count = 0;
5178 char *lock_data = NULL;
5179 NTSTATUS status = NT_STATUS_OK;
5181 if (!params) {
5182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5183 return;
5186 ZERO_STRUCT(write_time_ts);
5188 if (tran_call == TRANSACT2_QFILEINFO) {
5189 if (total_params < 4) {
5190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5191 return;
5194 if (IS_IPC(conn)) {
5195 call_trans2qpipeinfo(conn, req, tran_call,
5196 pparams, total_params,
5197 ppdata, total_data,
5198 max_data_bytes);
5199 return;
5202 fsp = file_fsp(req, SVAL(params,0));
5203 info_level = SVAL(params,2);
5205 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5207 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5208 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5209 return;
5212 /* Initial check for valid fsp ptr. */
5213 if (!check_fsp_open(conn, req, fsp)) {
5214 return;
5217 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5218 if (smb_fname == NULL) {
5219 reply_nterror(req, NT_STATUS_NO_MEMORY);
5220 return;
5223 if(fsp->fake_file_handle) {
5225 * This is actually for the QUOTA_FAKE_FILE --metze
5228 /* We know this name is ok, it's already passed the checks. */
5230 } else if(fsp->fh->fd == -1) {
5232 * This is actually a QFILEINFO on a directory
5233 * handle (returned from an NT SMB). NT5.0 seems
5234 * to do this call. JRA.
5237 if (INFO_LEVEL_IS_UNIX(info_level)) {
5238 /* Always do lstat for UNIX calls. */
5239 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5240 DEBUG(3,("call_trans2qfilepathinfo: "
5241 "SMB_VFS_LSTAT of %s failed "
5242 "(%s)\n",
5243 smb_fname_str_dbg(smb_fname),
5244 strerror(errno)));
5245 reply_nterror(req,
5246 map_nt_error_from_unix(errno));
5247 return;
5249 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5250 DEBUG(3,("call_trans2qfilepathinfo: "
5251 "SMB_VFS_STAT of %s failed (%s)\n",
5252 smb_fname_str_dbg(smb_fname),
5253 strerror(errno)));
5254 reply_nterror(req,
5255 map_nt_error_from_unix(errno));
5256 return;
5259 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5260 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5261 } else {
5263 * Original code - this is an open file.
5265 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5266 DEBUG(3, ("fstat of %s failed (%s)\n",
5267 fsp_fnum_dbg(fsp), strerror(errno)));
5268 reply_nterror(req,
5269 map_nt_error_from_unix(errno));
5270 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);
5276 } else {
5277 uint32_t name_hash;
5278 char *fname = NULL;
5279 uint32_t ucf_flags = 0;
5281 /* qpathinfo */
5282 if (total_params < 7) {
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284 return;
5287 info_level = SVAL(params,0);
5289 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5291 if (INFO_LEVEL_IS_UNIX(info_level)) {
5292 if (!lp_unix_extensions()) {
5293 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5294 return;
5296 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5297 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5298 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5299 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5303 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5304 total_params - 6,
5305 STR_TERMINATE, &status);
5306 if (!NT_STATUS_IS_OK(status)) {
5307 reply_nterror(req, status);
5308 return;
5311 status = filename_convert(req,
5312 conn,
5313 req->flags2 & FLAGS2_DFS_PATHNAMES,
5314 fname,
5315 ucf_flags,
5316 NULL,
5317 &smb_fname);
5318 if (!NT_STATUS_IS_OK(status)) {
5319 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5320 reply_botherror(req,
5321 NT_STATUS_PATH_NOT_COVERED,
5322 ERRSRV, ERRbadpath);
5323 return;
5325 reply_nterror(req, status);
5326 return;
5329 /* If this is a stream, check if there is a delete_pending. */
5330 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5331 && is_ntfs_stream_smb_fname(smb_fname)) {
5332 struct smb_filename *smb_fname_base;
5334 /* Create an smb_filename with stream_name == NULL. */
5335 smb_fname_base = synthetic_smb_fname(
5336 talloc_tos(), smb_fname->base_name,
5337 NULL, NULL);
5338 if (smb_fname_base == NULL) {
5339 reply_nterror(req, NT_STATUS_NO_MEMORY);
5340 return;
5343 if (INFO_LEVEL_IS_UNIX(info_level)) {
5344 /* Always do lstat for UNIX calls. */
5345 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5346 DEBUG(3,("call_trans2qfilepathinfo: "
5347 "SMB_VFS_LSTAT of %s failed "
5348 "(%s)\n",
5349 smb_fname_str_dbg(smb_fname_base),
5350 strerror(errno)));
5351 TALLOC_FREE(smb_fname_base);
5352 reply_nterror(req,
5353 map_nt_error_from_unix(errno));
5354 return;
5356 } else {
5357 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5358 DEBUG(3,("call_trans2qfilepathinfo: "
5359 "fileinfo of %s failed "
5360 "(%s)\n",
5361 smb_fname_str_dbg(smb_fname_base),
5362 strerror(errno)));
5363 TALLOC_FREE(smb_fname_base);
5364 reply_nterror(req,
5365 map_nt_error_from_unix(errno));
5366 return;
5370 status = file_name_hash(conn,
5371 smb_fname_str_dbg(smb_fname_base),
5372 &name_hash);
5373 if (!NT_STATUS_IS_OK(status)) {
5374 TALLOC_FREE(smb_fname_base);
5375 reply_nterror(req, status);
5376 return;
5379 fileid = vfs_file_id_from_sbuf(conn,
5380 &smb_fname_base->st);
5381 TALLOC_FREE(smb_fname_base);
5382 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5383 if (delete_pending) {
5384 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5385 return;
5389 if (INFO_LEVEL_IS_UNIX(info_level)) {
5390 /* Always do lstat for UNIX calls. */
5391 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5392 DEBUG(3,("call_trans2qfilepathinfo: "
5393 "SMB_VFS_LSTAT of %s failed (%s)\n",
5394 smb_fname_str_dbg(smb_fname),
5395 strerror(errno)));
5396 reply_nterror(req,
5397 map_nt_error_from_unix(errno));
5398 return;
5401 } else {
5402 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5403 DEBUG(3,("call_trans2qfilepathinfo: "
5404 "SMB_VFS_STAT of %s failed (%s)\n",
5405 smb_fname_str_dbg(smb_fname),
5406 strerror(errno)));
5407 reply_nterror(req,
5408 map_nt_error_from_unix(errno));
5409 return;
5413 status = file_name_hash(conn,
5414 smb_fname_str_dbg(smb_fname),
5415 &name_hash);
5416 if (!NT_STATUS_IS_OK(status)) {
5417 reply_nterror(req, status);
5418 return;
5421 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5422 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5423 if (delete_pending) {
5424 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5425 return;
5429 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5430 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5431 fsp_fnum_dbg(fsp),
5432 info_level,tran_call,total_data));
5434 /* Pull out any data sent here before we realloc. */
5435 switch (info_level) {
5436 case SMB_INFO_QUERY_EAS_FROM_LIST:
5438 /* Pull any EA list from the data portion. */
5439 uint32 ea_size;
5441 if (total_data < 4) {
5442 reply_nterror(
5443 req, NT_STATUS_INVALID_PARAMETER);
5444 return;
5446 ea_size = IVAL(pdata,0);
5448 if (total_data > 0 && ea_size != total_data) {
5449 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5450 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5451 reply_nterror(
5452 req, NT_STATUS_INVALID_PARAMETER);
5453 return;
5456 if (!lp_ea_support(SNUM(conn))) {
5457 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5458 return;
5461 /* Pull out the list of names. */
5462 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5463 if (!ea_list) {
5464 reply_nterror(
5465 req, NT_STATUS_INVALID_PARAMETER);
5466 return;
5468 break;
5471 case SMB_QUERY_POSIX_LOCK:
5473 if (fsp == NULL || fsp->fh->fd == -1) {
5474 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5475 return;
5478 if (total_data != POSIX_LOCK_DATA_SIZE) {
5479 reply_nterror(
5480 req, NT_STATUS_INVALID_PARAMETER);
5481 return;
5484 /* Copy the lock range data. */
5485 lock_data = (char *)talloc_memdup(
5486 req, pdata, total_data);
5487 if (!lock_data) {
5488 reply_nterror(req, NT_STATUS_NO_MEMORY);
5489 return;
5491 lock_data_count = total_data;
5493 default:
5494 break;
5497 *pparams = (char *)SMB_REALLOC(*pparams,2);
5498 if (*pparams == NULL) {
5499 reply_nterror(req, NT_STATUS_NO_MEMORY);
5500 return;
5502 params = *pparams;
5503 SSVAL(params,0,0);
5506 * draft-leach-cifs-v1-spec-02.txt
5507 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5508 * says:
5510 * The requested information is placed in the Data portion of the
5511 * transaction response. For the information levels greater than 0x100,
5512 * the transaction response has 1 parameter word which should be
5513 * ignored by the client.
5515 * However Windows only follows this rule for the IS_NAME_VALID call.
5517 switch (info_level) {
5518 case SMB_INFO_IS_NAME_VALID:
5519 param_size = 0;
5520 break;
5523 if ((info_level & 0xFF00) == 0xFF00) {
5525 * We use levels that start with 0xFF00
5526 * internally to represent SMB2 specific levels
5528 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5529 return;
5532 status = smbd_do_qfilepathinfo(conn, req, info_level,
5533 fsp, smb_fname,
5534 delete_pending, write_time_ts,
5535 ea_list,
5536 lock_data_count, lock_data,
5537 req->flags2, max_data_bytes,
5538 ppdata, &data_size);
5539 if (!NT_STATUS_IS_OK(status)) {
5540 reply_nterror(req, status);
5541 return;
5544 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5545 max_data_bytes);
5547 return;
5550 /****************************************************************************
5551 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5552 code.
5553 ****************************************************************************/
5555 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5556 connection_struct *conn,
5557 struct smb_request *req,
5558 bool overwrite_if_exists,
5559 const struct smb_filename *smb_fname_old,
5560 struct smb_filename *smb_fname_new)
5562 NTSTATUS status = NT_STATUS_OK;
5564 /* source must already exist. */
5565 if (!VALID_STAT(smb_fname_old->st)) {
5566 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5569 if (VALID_STAT(smb_fname_new->st)) {
5570 if (overwrite_if_exists) {
5571 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5572 return NT_STATUS_FILE_IS_A_DIRECTORY;
5574 status = unlink_internals(conn,
5575 req,
5576 FILE_ATTRIBUTE_NORMAL,
5577 smb_fname_new,
5578 false);
5579 if (!NT_STATUS_IS_OK(status)) {
5580 return status;
5582 } else {
5583 /* Disallow if newname already exists. */
5584 return NT_STATUS_OBJECT_NAME_COLLISION;
5588 /* No links from a directory. */
5589 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5590 return NT_STATUS_FILE_IS_A_DIRECTORY;
5593 /* Setting a hardlink to/from a stream isn't currently supported. */
5594 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5595 is_ntfs_stream_smb_fname(smb_fname_new)) {
5596 return NT_STATUS_INVALID_PARAMETER;
5599 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5600 smb_fname_old->base_name, smb_fname_new->base_name));
5602 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5603 smb_fname_new->base_name) != 0) {
5604 status = map_nt_error_from_unix(errno);
5605 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5606 nt_errstr(status), smb_fname_old->base_name,
5607 smb_fname_new->base_name));
5609 return status;
5612 /****************************************************************************
5613 Deal with setting the time from any of the setfilepathinfo functions.
5614 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5615 calling this function.
5616 ****************************************************************************/
5618 NTSTATUS smb_set_file_time(connection_struct *conn,
5619 files_struct *fsp,
5620 const struct smb_filename *smb_fname,
5621 struct smb_file_time *ft,
5622 bool setting_write_time)
5624 struct smb_filename smb_fname_base;
5625 uint32 action =
5626 FILE_NOTIFY_CHANGE_LAST_ACCESS
5627 |FILE_NOTIFY_CHANGE_LAST_WRITE
5628 |FILE_NOTIFY_CHANGE_CREATION;
5630 if (!VALID_STAT(smb_fname->st)) {
5631 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5634 /* get some defaults (no modifications) if any info is zero or -1. */
5635 if (null_timespec(ft->create_time)) {
5636 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5639 if (null_timespec(ft->atime)) {
5640 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5643 if (null_timespec(ft->mtime)) {
5644 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5647 if (!setting_write_time) {
5648 /* ft->mtime comes from change time, not write time. */
5649 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5652 /* Ensure the resolution is the correct for
5653 * what we can store on this filesystem. */
5655 round_timespec(conn->ts_res, &ft->create_time);
5656 round_timespec(conn->ts_res, &ft->ctime);
5657 round_timespec(conn->ts_res, &ft->atime);
5658 round_timespec(conn->ts_res, &ft->mtime);
5660 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5661 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5662 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5663 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5664 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5665 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5666 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5667 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5669 if (setting_write_time) {
5671 * This was a Windows setfileinfo on an open file.
5672 * NT does this a lot. We also need to
5673 * set the time here, as it can be read by
5674 * FindFirst/FindNext and with the patch for bug #2045
5675 * in smbd/fileio.c it ensures that this timestamp is
5676 * kept sticky even after a write. We save the request
5677 * away and will set it on file close and after a write. JRA.
5680 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5681 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5683 if (fsp != NULL) {
5684 if (fsp->base_fsp) {
5685 set_sticky_write_time_fsp(fsp->base_fsp,
5686 ft->mtime);
5687 } else {
5688 set_sticky_write_time_fsp(fsp, ft->mtime);
5690 } else {
5691 set_sticky_write_time_path(
5692 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5693 ft->mtime);
5697 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5699 /* Always call ntimes on the base, even if a stream was passed in. */
5700 smb_fname_base = *smb_fname;
5701 smb_fname_base.stream_name = NULL;
5703 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5704 return map_nt_error_from_unix(errno);
5707 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5708 smb_fname->base_name);
5709 return NT_STATUS_OK;
5712 /****************************************************************************
5713 Deal with setting the dosmode from any of the setfilepathinfo functions.
5714 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5715 done before calling this function.
5716 ****************************************************************************/
5718 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5719 const struct smb_filename *smb_fname,
5720 uint32 dosmode)
5722 struct smb_filename *smb_fname_base;
5723 NTSTATUS status;
5725 if (!VALID_STAT(smb_fname->st)) {
5726 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5729 /* Always operate on the base_name, even if a stream was passed in. */
5730 smb_fname_base = synthetic_smb_fname(
5731 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5732 if (smb_fname_base == NULL) {
5733 return NT_STATUS_NO_MEMORY;
5736 if (dosmode) {
5737 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5738 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5739 } else {
5740 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5744 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5746 /* check the mode isn't different, before changing it */
5747 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5748 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5749 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5750 (unsigned int)dosmode));
5752 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5753 false)) {
5754 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5755 "%s failed (%s)\n",
5756 smb_fname_str_dbg(smb_fname_base),
5757 strerror(errno)));
5758 status = map_nt_error_from_unix(errno);
5759 goto out;
5762 status = NT_STATUS_OK;
5763 out:
5764 TALLOC_FREE(smb_fname_base);
5765 return status;
5768 /****************************************************************************
5769 Deal with setting the size from any of the setfilepathinfo functions.
5770 ****************************************************************************/
5772 static NTSTATUS smb_set_file_size(connection_struct *conn,
5773 struct smb_request *req,
5774 files_struct *fsp,
5775 const struct smb_filename *smb_fname,
5776 const SMB_STRUCT_STAT *psbuf,
5777 off_t size,
5778 bool fail_after_createfile)
5780 NTSTATUS status = NT_STATUS_OK;
5781 struct smb_filename *smb_fname_tmp = NULL;
5782 files_struct *new_fsp = NULL;
5784 if (!VALID_STAT(*psbuf)) {
5785 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5788 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5790 if (size == get_file_size_stat(psbuf)) {
5791 return NT_STATUS_OK;
5794 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5795 smb_fname_str_dbg(smb_fname), (double)size));
5797 if (fsp && fsp->fh->fd != -1) {
5798 /* Handle based call. */
5799 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5800 return NT_STATUS_ACCESS_DENIED;
5803 if (vfs_set_filelen(fsp, size) == -1) {
5804 return map_nt_error_from_unix(errno);
5806 trigger_write_time_update_immediate(fsp);
5807 return NT_STATUS_OK;
5810 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5811 if (smb_fname_tmp == NULL) {
5812 return NT_STATUS_NO_MEMORY;
5815 smb_fname_tmp->st = *psbuf;
5817 status = SMB_VFS_CREATE_FILE(
5818 conn, /* conn */
5819 req, /* req */
5820 0, /* root_dir_fid */
5821 smb_fname_tmp, /* fname */
5822 FILE_WRITE_DATA, /* access_mask */
5823 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5824 FILE_SHARE_DELETE),
5825 FILE_OPEN, /* create_disposition*/
5826 0, /* create_options */
5827 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5828 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5829 0, /* allocation_size */
5830 0, /* private_flags */
5831 NULL, /* sd */
5832 NULL, /* ea_list */
5833 &new_fsp, /* result */
5834 NULL); /* pinfo */
5836 TALLOC_FREE(smb_fname_tmp);
5838 if (!NT_STATUS_IS_OK(status)) {
5839 /* NB. We check for open_was_deferred in the caller. */
5840 return status;
5843 /* See RAW-SFILEINFO-END-OF-FILE */
5844 if (fail_after_createfile) {
5845 close_file(req, new_fsp,NORMAL_CLOSE);
5846 return NT_STATUS_INVALID_LEVEL;
5849 if (vfs_set_filelen(new_fsp, size) == -1) {
5850 status = map_nt_error_from_unix(errno);
5851 close_file(req, new_fsp,NORMAL_CLOSE);
5852 return status;
5855 trigger_write_time_update_immediate(new_fsp);
5856 close_file(req, new_fsp,NORMAL_CLOSE);
5857 return NT_STATUS_OK;
5860 /****************************************************************************
5861 Deal with SMB_INFO_SET_EA.
5862 ****************************************************************************/
5864 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5865 const char *pdata,
5866 int total_data,
5867 files_struct *fsp,
5868 const struct smb_filename *smb_fname)
5870 struct ea_list *ea_list = NULL;
5871 TALLOC_CTX *ctx = NULL;
5872 NTSTATUS status = NT_STATUS_OK;
5874 if (total_data < 10) {
5876 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5877 length. They seem to have no effect. Bug #3212. JRA */
5879 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5880 /* We're done. We only get EA info in this call. */
5881 return NT_STATUS_OK;
5884 return NT_STATUS_INVALID_PARAMETER;
5887 if (IVAL(pdata,0) > total_data) {
5888 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5889 IVAL(pdata,0), (unsigned int)total_data));
5890 return NT_STATUS_INVALID_PARAMETER;
5893 ctx = talloc_tos();
5894 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5895 if (!ea_list) {
5896 return NT_STATUS_INVALID_PARAMETER;
5899 status = set_ea(conn, fsp, smb_fname, ea_list);
5901 return status;
5904 /****************************************************************************
5905 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5906 ****************************************************************************/
5908 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5909 const char *pdata,
5910 int total_data,
5911 files_struct *fsp)
5913 struct ea_list *ea_list = NULL;
5914 NTSTATUS status;
5916 if (!fsp) {
5917 return NT_STATUS_INVALID_HANDLE;
5920 if (!lp_ea_support(SNUM(conn))) {
5921 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5922 "EA's not supported.\n",
5923 (unsigned int)total_data));
5924 return NT_STATUS_EAS_NOT_SUPPORTED;
5927 if (total_data < 10) {
5928 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5929 "too small.\n",
5930 (unsigned int)total_data));
5931 return NT_STATUS_INVALID_PARAMETER;
5934 ea_list = read_nttrans_ea_list(talloc_tos(),
5935 pdata,
5936 total_data);
5938 if (!ea_list) {
5939 return NT_STATUS_INVALID_PARAMETER;
5942 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5944 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5945 smb_fname_str_dbg(fsp->fsp_name),
5946 nt_errstr(status) ));
5948 return status;
5952 /****************************************************************************
5953 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5954 ****************************************************************************/
5956 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5957 const char *pdata,
5958 int total_data,
5959 files_struct *fsp,
5960 struct smb_filename *smb_fname)
5962 NTSTATUS status = NT_STATUS_OK;
5963 bool delete_on_close;
5964 uint32 dosmode = 0;
5966 if (total_data < 1) {
5967 return NT_STATUS_INVALID_PARAMETER;
5970 if (fsp == NULL) {
5971 return NT_STATUS_INVALID_HANDLE;
5974 delete_on_close = (CVAL(pdata,0) ? True : False);
5975 dosmode = dos_mode(conn, smb_fname);
5977 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5978 "delete_on_close = %u\n",
5979 smb_fname_str_dbg(smb_fname),
5980 (unsigned int)dosmode,
5981 (unsigned int)delete_on_close ));
5983 if (delete_on_close) {
5984 status = can_set_delete_on_close(fsp, dosmode);
5985 if (!NT_STATUS_IS_OK(status)) {
5986 return status;
5990 /* The set is across all open files on this dev/inode pair. */
5991 if (!set_delete_on_close(fsp, delete_on_close,
5992 conn->session_info->security_token,
5993 conn->session_info->unix_token)) {
5994 return NT_STATUS_ACCESS_DENIED;
5996 return NT_STATUS_OK;
5999 /****************************************************************************
6000 Deal with SMB_FILE_POSITION_INFORMATION.
6001 ****************************************************************************/
6003 static NTSTATUS smb_file_position_information(connection_struct *conn,
6004 const char *pdata,
6005 int total_data,
6006 files_struct *fsp)
6008 uint64_t position_information;
6010 if (total_data < 8) {
6011 return NT_STATUS_INVALID_PARAMETER;
6014 if (fsp == NULL) {
6015 /* Ignore on pathname based set. */
6016 return NT_STATUS_OK;
6019 position_information = (uint64_t)IVAL(pdata,0);
6020 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6022 DEBUG(10,("smb_file_position_information: Set file position "
6023 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6024 (double)position_information));
6025 fsp->fh->position_information = position_information;
6026 return NT_STATUS_OK;
6029 /****************************************************************************
6030 Deal with SMB_FILE_MODE_INFORMATION.
6031 ****************************************************************************/
6033 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6034 const char *pdata,
6035 int total_data)
6037 uint32 mode;
6039 if (total_data < 4) {
6040 return NT_STATUS_INVALID_PARAMETER;
6042 mode = IVAL(pdata,0);
6043 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6044 return NT_STATUS_INVALID_PARAMETER;
6046 return NT_STATUS_OK;
6049 /****************************************************************************
6050 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6051 ****************************************************************************/
6053 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6054 struct smb_request *req,
6055 const char *pdata,
6056 int total_data,
6057 const struct smb_filename *smb_fname)
6059 char *link_target = NULL;
6060 const char *newname = smb_fname->base_name;
6061 TALLOC_CTX *ctx = talloc_tos();
6063 /* Set a symbolic link. */
6064 /* Don't allow this if follow links is false. */
6066 if (total_data == 0) {
6067 return NT_STATUS_INVALID_PARAMETER;
6070 if (!lp_symlinks(SNUM(conn))) {
6071 return NT_STATUS_ACCESS_DENIED;
6074 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6075 total_data, STR_TERMINATE);
6077 if (!link_target) {
6078 return NT_STATUS_INVALID_PARAMETER;
6081 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6082 newname, link_target ));
6084 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6085 return map_nt_error_from_unix(errno);
6088 return NT_STATUS_OK;
6091 /****************************************************************************
6092 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6093 ****************************************************************************/
6095 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6096 struct smb_request *req,
6097 const char *pdata, int total_data,
6098 struct smb_filename *smb_fname_new)
6100 char *oldname = NULL;
6101 struct smb_filename *smb_fname_old = NULL;
6102 TALLOC_CTX *ctx = talloc_tos();
6103 NTSTATUS status = NT_STATUS_OK;
6105 /* Set a hard link. */
6106 if (total_data == 0) {
6107 return NT_STATUS_INVALID_PARAMETER;
6110 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6111 total_data, STR_TERMINATE, &status);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 return status;
6116 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6117 smb_fname_str_dbg(smb_fname_new), oldname));
6119 status = filename_convert(ctx,
6120 conn,
6121 req->flags2 & FLAGS2_DFS_PATHNAMES,
6122 oldname,
6124 NULL,
6125 &smb_fname_old);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return status;
6130 return hardlink_internals(ctx, conn, req, false,
6131 smb_fname_old, smb_fname_new);
6134 /****************************************************************************
6135 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6136 ****************************************************************************/
6138 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6139 struct smb_request *req,
6140 const char *pdata,
6141 int total_data,
6142 files_struct *fsp,
6143 struct smb_filename *smb_fname_src)
6145 bool overwrite;
6146 uint32_t len;
6147 char *newname = NULL;
6148 struct smb_filename *smb_fname_dst = NULL;
6149 NTSTATUS status = NT_STATUS_OK;
6150 TALLOC_CTX *ctx = talloc_tos();
6152 if (!fsp) {
6153 return NT_STATUS_INVALID_HANDLE;
6156 if (total_data < 20) {
6157 return NT_STATUS_INVALID_PARAMETER;
6160 overwrite = (CVAL(pdata,0) ? True : False);
6161 len = IVAL(pdata,16);
6163 if (len > (total_data - 20) || (len == 0)) {
6164 return NT_STATUS_INVALID_PARAMETER;
6167 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6168 &pdata[20], len, STR_TERMINATE,
6169 &status);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 return status;
6174 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6175 newname));
6177 status = filename_convert(ctx,
6178 conn,
6179 req->flags2 & FLAGS2_DFS_PATHNAMES,
6180 newname,
6181 UCF_SAVE_LCOMP,
6182 NULL,
6183 &smb_fname_dst);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 return status;
6188 if (fsp->base_fsp) {
6189 /* newname must be a stream name. */
6190 if (newname[0] != ':') {
6191 return NT_STATUS_NOT_SUPPORTED;
6194 /* Create an smb_fname to call rename_internals_fsp() with. */
6195 smb_fname_dst = synthetic_smb_fname(
6196 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6197 newname, NULL);
6198 if (smb_fname_dst == NULL) {
6199 status = NT_STATUS_NO_MEMORY;
6200 goto out;
6204 * Set the original last component, since
6205 * rename_internals_fsp() requires it.
6207 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6208 newname);
6209 if (smb_fname_dst->original_lcomp == NULL) {
6210 status = NT_STATUS_NO_MEMORY;
6211 goto out;
6216 DEBUG(10,("smb2_file_rename_information: "
6217 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6218 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6219 smb_fname_str_dbg(smb_fname_dst)));
6220 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6221 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6222 overwrite);
6224 out:
6225 TALLOC_FREE(smb_fname_dst);
6226 return status;
6229 static NTSTATUS smb_file_link_information(connection_struct *conn,
6230 struct smb_request *req,
6231 const char *pdata,
6232 int total_data,
6233 files_struct *fsp,
6234 struct smb_filename *smb_fname_src)
6236 bool overwrite;
6237 uint32_t len;
6238 char *newname = NULL;
6239 struct smb_filename *smb_fname_dst = NULL;
6240 NTSTATUS status = NT_STATUS_OK;
6241 TALLOC_CTX *ctx = talloc_tos();
6243 if (!fsp) {
6244 return NT_STATUS_INVALID_HANDLE;
6247 if (total_data < 20) {
6248 return NT_STATUS_INVALID_PARAMETER;
6251 overwrite = (CVAL(pdata,0) ? true : false);
6252 len = IVAL(pdata,16);
6254 if (len > (total_data - 20) || (len == 0)) {
6255 return NT_STATUS_INVALID_PARAMETER;
6258 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6259 &pdata[20], len, STR_TERMINATE,
6260 &status);
6261 if (!NT_STATUS_IS_OK(status)) {
6262 return status;
6265 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6266 newname));
6268 status = filename_convert(ctx,
6269 conn,
6270 req->flags2 & FLAGS2_DFS_PATHNAMES,
6271 newname,
6272 UCF_SAVE_LCOMP,
6273 NULL,
6274 &smb_fname_dst);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 return status;
6279 if (fsp->base_fsp) {
6280 /* No stream names. */
6281 return NT_STATUS_NOT_SUPPORTED;
6284 DEBUG(10,("smb_file_link_information: "
6285 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6286 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6287 smb_fname_str_dbg(smb_fname_dst)));
6288 status = hardlink_internals(ctx,
6289 conn,
6290 req,
6291 overwrite,
6292 fsp->fsp_name,
6293 smb_fname_dst);
6295 TALLOC_FREE(smb_fname_dst);
6296 return status;
6299 /****************************************************************************
6300 Deal with SMB_FILE_RENAME_INFORMATION.
6301 ****************************************************************************/
6303 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6304 struct smb_request *req,
6305 const char *pdata,
6306 int total_data,
6307 files_struct *fsp,
6308 struct smb_filename *smb_fname_src)
6310 bool overwrite;
6311 uint32 root_fid;
6312 uint32 len;
6313 char *newname = NULL;
6314 struct smb_filename *smb_fname_dst = NULL;
6315 bool dest_has_wcard = False;
6316 NTSTATUS status = NT_STATUS_OK;
6317 char *p;
6318 TALLOC_CTX *ctx = talloc_tos();
6320 if (total_data < 13) {
6321 return NT_STATUS_INVALID_PARAMETER;
6324 overwrite = (CVAL(pdata,0) ? True : False);
6325 root_fid = IVAL(pdata,4);
6326 len = IVAL(pdata,8);
6328 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6329 return NT_STATUS_INVALID_PARAMETER;
6332 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6333 len, 0, &status,
6334 &dest_has_wcard);
6335 if (!NT_STATUS_IS_OK(status)) {
6336 return status;
6339 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6340 newname));
6342 status = resolve_dfspath_wcard(ctx, conn,
6343 req->flags2 & FLAGS2_DFS_PATHNAMES,
6344 newname,
6345 true,
6346 !conn->sconn->using_smb2,
6347 &newname,
6348 &dest_has_wcard);
6349 if (!NT_STATUS_IS_OK(status)) {
6350 return status;
6353 /* Check the new name has no '/' characters. */
6354 if (strchr_m(newname, '/')) {
6355 return NT_STATUS_NOT_SUPPORTED;
6358 if (fsp && fsp->base_fsp) {
6359 /* newname must be a stream name. */
6360 if (newname[0] != ':') {
6361 return NT_STATUS_NOT_SUPPORTED;
6364 /* Create an smb_fname to call rename_internals_fsp() with. */
6365 smb_fname_dst = synthetic_smb_fname(
6366 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6367 newname, NULL);
6368 if (smb_fname_dst == NULL) {
6369 status = NT_STATUS_NO_MEMORY;
6370 goto out;
6374 * Set the original last component, since
6375 * rename_internals_fsp() requires it.
6377 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6378 newname);
6379 if (smb_fname_dst->original_lcomp == NULL) {
6380 status = NT_STATUS_NO_MEMORY;
6381 goto out;
6384 } else {
6386 * Build up an smb_fname_dst based on the filename passed in.
6387 * We basically just strip off the last component, and put on
6388 * the newname instead.
6390 char *base_name = NULL;
6392 /* newname must *not* be a stream name. */
6393 if (newname[0] == ':') {
6394 return NT_STATUS_NOT_SUPPORTED;
6398 * Strip off the last component (filename) of the path passed
6399 * in.
6401 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6402 if (!base_name) {
6403 return NT_STATUS_NO_MEMORY;
6405 p = strrchr_m(base_name, '/');
6406 if (p) {
6407 p[1] = '\0';
6408 } else {
6409 base_name = talloc_strdup(ctx, "");
6410 if (!base_name) {
6411 return NT_STATUS_NO_MEMORY;
6414 /* Append the new name. */
6415 base_name = talloc_asprintf_append(base_name,
6416 "%s",
6417 newname);
6418 if (!base_name) {
6419 return NT_STATUS_NO_MEMORY;
6422 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6423 (UCF_SAVE_LCOMP |
6424 (dest_has_wcard ?
6425 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6426 0)));
6428 /* If an error we expect this to be
6429 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6431 if (!NT_STATUS_IS_OK(status)) {
6432 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6433 status)) {
6434 goto out;
6436 /* Create an smb_fname to call rename_internals_fsp() */
6437 smb_fname_dst = synthetic_smb_fname(
6438 ctx, base_name, NULL, NULL);
6439 if (smb_fname_dst == NULL) {
6440 status = NT_STATUS_NO_MEMORY;
6441 goto out;
6446 if (fsp) {
6447 DEBUG(10,("smb_file_rename_information: "
6448 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6449 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6450 smb_fname_str_dbg(smb_fname_dst)));
6451 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6452 overwrite);
6453 } else {
6454 DEBUG(10,("smb_file_rename_information: "
6455 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6456 smb_fname_str_dbg(smb_fname_src),
6457 smb_fname_str_dbg(smb_fname_dst)));
6458 status = rename_internals(ctx, conn, req, smb_fname_src,
6459 smb_fname_dst, 0, overwrite, false,
6460 dest_has_wcard,
6461 FILE_WRITE_ATTRIBUTES);
6463 out:
6464 TALLOC_FREE(smb_fname_dst);
6465 return status;
6468 /****************************************************************************
6469 Deal with SMB_SET_POSIX_ACL.
6470 ****************************************************************************/
6472 #if defined(HAVE_POSIX_ACLS)
6473 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6474 const char *pdata,
6475 int total_data,
6476 files_struct *fsp,
6477 const struct smb_filename *smb_fname)
6479 uint16 posix_acl_version;
6480 uint16 num_file_acls;
6481 uint16 num_def_acls;
6482 bool valid_file_acls = True;
6483 bool valid_def_acls = True;
6485 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6486 return NT_STATUS_INVALID_PARAMETER;
6488 posix_acl_version = SVAL(pdata,0);
6489 num_file_acls = SVAL(pdata,2);
6490 num_def_acls = SVAL(pdata,4);
6492 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6493 valid_file_acls = False;
6494 num_file_acls = 0;
6497 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6498 valid_def_acls = False;
6499 num_def_acls = 0;
6502 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6503 return NT_STATUS_INVALID_PARAMETER;
6506 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6507 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6508 return NT_STATUS_INVALID_PARAMETER;
6511 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6512 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6513 (unsigned int)num_file_acls,
6514 (unsigned int)num_def_acls));
6516 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6517 smb_fname->base_name, num_file_acls,
6518 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6519 return map_nt_error_from_unix(errno);
6522 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6523 smb_fname->base_name, &smb_fname->st, num_def_acls,
6524 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6525 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6526 return map_nt_error_from_unix(errno);
6528 return NT_STATUS_OK;
6530 #endif
6532 /****************************************************************************
6533 Deal with SMB_SET_POSIX_LOCK.
6534 ****************************************************************************/
6536 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6537 struct smb_request *req,
6538 const char *pdata,
6539 int total_data,
6540 files_struct *fsp)
6542 uint64_t count;
6543 uint64_t offset;
6544 uint64_t smblctx;
6545 bool blocking_lock = False;
6546 enum brl_type lock_type;
6548 NTSTATUS status = NT_STATUS_OK;
6550 if (fsp == NULL || fsp->fh->fd == -1) {
6551 return NT_STATUS_INVALID_HANDLE;
6554 if (total_data != POSIX_LOCK_DATA_SIZE) {
6555 return NT_STATUS_INVALID_PARAMETER;
6558 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6559 case POSIX_LOCK_TYPE_READ:
6560 lock_type = READ_LOCK;
6561 break;
6562 case POSIX_LOCK_TYPE_WRITE:
6563 /* Return the right POSIX-mappable error code for files opened read-only. */
6564 if (!fsp->can_write) {
6565 return NT_STATUS_INVALID_HANDLE;
6567 lock_type = WRITE_LOCK;
6568 break;
6569 case POSIX_LOCK_TYPE_UNLOCK:
6570 lock_type = UNLOCK_LOCK;
6571 break;
6572 default:
6573 return NT_STATUS_INVALID_PARAMETER;
6576 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6577 blocking_lock = False;
6578 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6579 blocking_lock = True;
6580 } else {
6581 return NT_STATUS_INVALID_PARAMETER;
6584 if (!lp_blocking_locks(SNUM(conn))) {
6585 blocking_lock = False;
6588 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6589 #if defined(HAVE_LONGLONG)
6590 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6591 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6592 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6593 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6594 #else /* HAVE_LONGLONG */
6595 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6596 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6597 #endif /* HAVE_LONGLONG */
6599 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6600 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6601 fsp_str_dbg(fsp),
6602 (unsigned int)lock_type,
6603 (unsigned long long)smblctx,
6604 (double)count,
6605 (double)offset ));
6607 if (lock_type == UNLOCK_LOCK) {
6608 status = do_unlock(req->sconn->msg_ctx,
6609 fsp,
6610 smblctx,
6611 count,
6612 offset,
6613 POSIX_LOCK);
6614 } else {
6615 uint64_t block_smblctx;
6617 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6618 fsp,
6619 smblctx,
6620 count,
6621 offset,
6622 lock_type,
6623 POSIX_LOCK,
6624 blocking_lock,
6625 &status,
6626 &block_smblctx,
6627 NULL);
6629 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6631 * A blocking lock was requested. Package up
6632 * this smb into a queued request and push it
6633 * onto the blocking lock queue.
6635 if(push_blocking_lock_request(br_lck,
6636 req,
6637 fsp,
6638 -1, /* infinite timeout. */
6640 smblctx,
6641 lock_type,
6642 POSIX_LOCK,
6643 offset,
6644 count,
6645 block_smblctx)) {
6646 TALLOC_FREE(br_lck);
6647 return status;
6650 TALLOC_FREE(br_lck);
6653 return status;
6656 /****************************************************************************
6657 Deal with SMB_SET_FILE_BASIC_INFO.
6658 ****************************************************************************/
6660 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6661 const char *pdata,
6662 int total_data,
6663 files_struct *fsp,
6664 const struct smb_filename *smb_fname)
6666 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6667 struct smb_file_time ft;
6668 uint32 dosmode = 0;
6669 NTSTATUS status = NT_STATUS_OK;
6671 ZERO_STRUCT(ft);
6673 if (total_data < 36) {
6674 return NT_STATUS_INVALID_PARAMETER;
6677 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6678 if (!NT_STATUS_IS_OK(status)) {
6679 return status;
6682 /* Set the attributes */
6683 dosmode = IVAL(pdata,32);
6684 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6685 if (!NT_STATUS_IS_OK(status)) {
6686 return status;
6689 /* create time */
6690 ft.create_time = interpret_long_date(pdata);
6692 /* access time */
6693 ft.atime = interpret_long_date(pdata+8);
6695 /* write time. */
6696 ft.mtime = interpret_long_date(pdata+16);
6698 /* change time. */
6699 ft.ctime = interpret_long_date(pdata+24);
6701 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6702 smb_fname_str_dbg(smb_fname)));
6704 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6705 true);
6708 /****************************************************************************
6709 Deal with SMB_INFO_STANDARD.
6710 ****************************************************************************/
6712 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6713 const char *pdata,
6714 int total_data,
6715 files_struct *fsp,
6716 const struct smb_filename *smb_fname)
6718 NTSTATUS status;
6719 struct smb_file_time ft;
6721 ZERO_STRUCT(ft);
6723 if (total_data < 12) {
6724 return NT_STATUS_INVALID_PARAMETER;
6727 /* create time */
6728 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6729 /* access time */
6730 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6731 /* write time */
6732 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6734 DEBUG(10,("smb_set_info_standard: file %s\n",
6735 smb_fname_str_dbg(smb_fname)));
6737 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6738 if (!NT_STATUS_IS_OK(status)) {
6739 return status;
6742 return smb_set_file_time(conn,
6743 fsp,
6744 smb_fname,
6745 &ft,
6746 true);
6749 /****************************************************************************
6750 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6751 ****************************************************************************/
6753 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6754 struct smb_request *req,
6755 const char *pdata,
6756 int total_data,
6757 files_struct *fsp,
6758 struct smb_filename *smb_fname)
6760 uint64_t allocation_size = 0;
6761 NTSTATUS status = NT_STATUS_OK;
6762 files_struct *new_fsp = NULL;
6764 if (!VALID_STAT(smb_fname->st)) {
6765 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6768 if (total_data < 8) {
6769 return NT_STATUS_INVALID_PARAMETER;
6772 allocation_size = (uint64_t)IVAL(pdata,0);
6773 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6774 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6775 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6776 (double)allocation_size));
6778 if (allocation_size) {
6779 allocation_size = smb_roundup(conn, allocation_size);
6782 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6783 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6784 (double)allocation_size));
6786 if (fsp && fsp->fh->fd != -1) {
6787 /* Open file handle. */
6788 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6789 return NT_STATUS_ACCESS_DENIED;
6792 /* Only change if needed. */
6793 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6794 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6795 return map_nt_error_from_unix(errno);
6798 /* But always update the time. */
6800 * This is equivalent to a write. Ensure it's seen immediately
6801 * if there are no pending writes.
6803 trigger_write_time_update_immediate(fsp);
6804 return NT_STATUS_OK;
6807 /* Pathname or stat or directory file. */
6808 status = SMB_VFS_CREATE_FILE(
6809 conn, /* conn */
6810 req, /* req */
6811 0, /* root_dir_fid */
6812 smb_fname, /* fname */
6813 FILE_WRITE_DATA, /* access_mask */
6814 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6815 FILE_SHARE_DELETE),
6816 FILE_OPEN, /* create_disposition*/
6817 0, /* create_options */
6818 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6819 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6820 0, /* allocation_size */
6821 0, /* private_flags */
6822 NULL, /* sd */
6823 NULL, /* ea_list */
6824 &new_fsp, /* result */
6825 NULL); /* pinfo */
6827 if (!NT_STATUS_IS_OK(status)) {
6828 /* NB. We check for open_was_deferred in the caller. */
6829 return status;
6832 /* Only change if needed. */
6833 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6834 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6835 status = map_nt_error_from_unix(errno);
6836 close_file(req, new_fsp, NORMAL_CLOSE);
6837 return status;
6841 /* Changing the allocation size should set the last mod time. */
6843 * This is equivalent to a write. Ensure it's seen immediately
6844 * if there are no pending writes.
6846 trigger_write_time_update_immediate(new_fsp);
6848 close_file(req, new_fsp, NORMAL_CLOSE);
6849 return NT_STATUS_OK;
6852 /****************************************************************************
6853 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6854 ****************************************************************************/
6856 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6857 struct smb_request *req,
6858 const char *pdata,
6859 int total_data,
6860 files_struct *fsp,
6861 const struct smb_filename *smb_fname,
6862 bool fail_after_createfile)
6864 off_t size;
6866 if (total_data < 8) {
6867 return NT_STATUS_INVALID_PARAMETER;
6870 size = IVAL(pdata,0);
6871 size |= (((off_t)IVAL(pdata,4)) << 32);
6872 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6873 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6874 (double)size));
6876 return smb_set_file_size(conn, req,
6877 fsp,
6878 smb_fname,
6879 &smb_fname->st,
6880 size,
6881 fail_after_createfile);
6884 /****************************************************************************
6885 Allow a UNIX info mknod.
6886 ****************************************************************************/
6888 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6889 const char *pdata,
6890 int total_data,
6891 const struct smb_filename *smb_fname)
6893 uint32 file_type = IVAL(pdata,56);
6894 #if defined(HAVE_MAKEDEV)
6895 uint32 dev_major = IVAL(pdata,60);
6896 uint32 dev_minor = IVAL(pdata,68);
6897 #endif
6898 SMB_DEV_T dev = (SMB_DEV_T)0;
6899 uint32 raw_unixmode = IVAL(pdata,84);
6900 NTSTATUS status;
6901 mode_t unixmode;
6903 if (total_data < 100) {
6904 return NT_STATUS_INVALID_PARAMETER;
6907 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6908 PERM_NEW_FILE, &unixmode);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 return status;
6913 #if defined(HAVE_MAKEDEV)
6914 dev = makedev(dev_major, dev_minor);
6915 #endif
6917 switch (file_type) {
6918 #if defined(S_IFIFO)
6919 case UNIX_TYPE_FIFO:
6920 unixmode |= S_IFIFO;
6921 break;
6922 #endif
6923 #if defined(S_IFSOCK)
6924 case UNIX_TYPE_SOCKET:
6925 unixmode |= S_IFSOCK;
6926 break;
6927 #endif
6928 #if defined(S_IFCHR)
6929 case UNIX_TYPE_CHARDEV:
6930 unixmode |= S_IFCHR;
6931 break;
6932 #endif
6933 #if defined(S_IFBLK)
6934 case UNIX_TYPE_BLKDEV:
6935 unixmode |= S_IFBLK;
6936 break;
6937 #endif
6938 default:
6939 return NT_STATUS_INVALID_PARAMETER;
6942 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6943 "%.0f mode 0%o for file %s\n", (double)dev,
6944 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6946 /* Ok - do the mknod. */
6947 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6948 return map_nt_error_from_unix(errno);
6951 /* If any of the other "set" calls fail we
6952 * don't want to end up with a half-constructed mknod.
6955 if (lp_inherit_perms(SNUM(conn))) {
6956 char *parent;
6957 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6958 &parent, NULL)) {
6959 return NT_STATUS_NO_MEMORY;
6961 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6962 unixmode);
6963 TALLOC_FREE(parent);
6966 return NT_STATUS_OK;
6969 /****************************************************************************
6970 Deal with SMB_SET_FILE_UNIX_BASIC.
6971 ****************************************************************************/
6973 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6974 struct smb_request *req,
6975 const char *pdata,
6976 int total_data,
6977 files_struct *fsp,
6978 const struct smb_filename *smb_fname)
6980 struct smb_file_time ft;
6981 uint32 raw_unixmode;
6982 mode_t unixmode;
6983 off_t size = 0;
6984 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6985 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6986 NTSTATUS status = NT_STATUS_OK;
6987 bool delete_on_fail = False;
6988 enum perm_type ptype;
6989 files_struct *all_fsps = NULL;
6990 bool modify_mtime = true;
6991 struct file_id id;
6992 struct smb_filename *smb_fname_tmp = NULL;
6993 SMB_STRUCT_STAT sbuf;
6995 ZERO_STRUCT(ft);
6997 if (total_data < 100) {
6998 return NT_STATUS_INVALID_PARAMETER;
7001 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7002 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7003 size=IVAL(pdata,0); /* first 8 Bytes are size */
7004 size |= (((off_t)IVAL(pdata,4)) << 32);
7007 ft.atime = interpret_long_date(pdata+24); /* access_time */
7008 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7009 set_owner = (uid_t)IVAL(pdata,40);
7010 set_grp = (gid_t)IVAL(pdata,48);
7011 raw_unixmode = IVAL(pdata,84);
7013 if (VALID_STAT(smb_fname->st)) {
7014 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7015 ptype = PERM_EXISTING_DIR;
7016 } else {
7017 ptype = PERM_EXISTING_FILE;
7019 } else {
7020 ptype = PERM_NEW_FILE;
7023 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7024 ptype, &unixmode);
7025 if (!NT_STATUS_IS_OK(status)) {
7026 return status;
7029 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7030 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7031 smb_fname_str_dbg(smb_fname), (double)size,
7032 (unsigned int)set_owner, (unsigned int)set_grp,
7033 (int)raw_unixmode));
7035 sbuf = smb_fname->st;
7037 if (!VALID_STAT(sbuf)) {
7039 * The only valid use of this is to create character and block
7040 * devices, and named pipes. This is deprecated (IMHO) and
7041 * a new info level should be used for mknod. JRA.
7044 status = smb_unix_mknod(conn,
7045 pdata,
7046 total_data,
7047 smb_fname);
7048 if (!NT_STATUS_IS_OK(status)) {
7049 return status;
7052 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7053 if (smb_fname_tmp == NULL) {
7054 return NT_STATUS_NO_MEMORY;
7057 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7058 status = map_nt_error_from_unix(errno);
7059 TALLOC_FREE(smb_fname_tmp);
7060 SMB_VFS_UNLINK(conn, smb_fname);
7061 return status;
7064 sbuf = smb_fname_tmp->st;
7065 smb_fname = smb_fname_tmp;
7067 /* Ensure we don't try and change anything else. */
7068 raw_unixmode = SMB_MODE_NO_CHANGE;
7069 size = get_file_size_stat(&sbuf);
7070 ft.atime = sbuf.st_ex_atime;
7071 ft.mtime = sbuf.st_ex_mtime;
7073 * We continue here as we might want to change the
7074 * owner uid/gid.
7076 delete_on_fail = True;
7079 #if 1
7080 /* Horrible backwards compatibility hack as an old server bug
7081 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7082 * */
7084 if (!size) {
7085 size = get_file_size_stat(&sbuf);
7087 #endif
7090 * Deal with the UNIX specific mode set.
7093 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7094 int ret;
7096 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7097 "setting mode 0%o for file %s\n",
7098 (unsigned int)unixmode,
7099 smb_fname_str_dbg(smb_fname)));
7100 if (fsp && fsp->fh->fd != -1) {
7101 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7102 } else {
7103 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7105 if (ret != 0) {
7106 return map_nt_error_from_unix(errno);
7111 * Deal with the UNIX specific uid set.
7114 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7115 (sbuf.st_ex_uid != set_owner)) {
7116 int ret;
7118 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7119 "changing owner %u for path %s\n",
7120 (unsigned int)set_owner,
7121 smb_fname_str_dbg(smb_fname)));
7123 if (fsp && fsp->fh->fd != -1) {
7124 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7125 } else {
7127 * UNIX extensions calls must always operate
7128 * on symlinks.
7130 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7131 set_owner, (gid_t)-1);
7134 if (ret != 0) {
7135 status = map_nt_error_from_unix(errno);
7136 if (delete_on_fail) {
7137 SMB_VFS_UNLINK(conn, smb_fname);
7139 return status;
7144 * Deal with the UNIX specific gid set.
7147 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7148 (sbuf.st_ex_gid != set_grp)) {
7149 int ret;
7151 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7152 "changing group %u for file %s\n",
7153 (unsigned int)set_owner,
7154 smb_fname_str_dbg(smb_fname)));
7155 if (fsp && fsp->fh->fd != -1) {
7156 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7157 } else {
7159 * UNIX extensions calls must always operate
7160 * on symlinks.
7162 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7163 set_grp);
7165 if (ret != 0) {
7166 status = map_nt_error_from_unix(errno);
7167 if (delete_on_fail) {
7168 SMB_VFS_UNLINK(conn, smb_fname);
7170 return status;
7174 /* Deal with any size changes. */
7176 status = smb_set_file_size(conn, req,
7177 fsp,
7178 smb_fname,
7179 &sbuf,
7180 size,
7181 false);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 return status;
7186 /* Deal with any time changes. */
7187 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7188 /* No change, don't cancel anything. */
7189 return status;
7192 id = vfs_file_id_from_sbuf(conn, &sbuf);
7193 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7194 all_fsps = file_find_di_next(all_fsps)) {
7196 * We're setting the time explicitly for UNIX.
7197 * Cancel any pending changes over all handles.
7199 all_fsps->update_write_time_on_close = false;
7200 TALLOC_FREE(all_fsps->update_write_time_event);
7204 * Override the "setting_write_time"
7205 * parameter here as it almost does what
7206 * we need. Just remember if we modified
7207 * mtime and send the notify ourselves.
7209 if (null_timespec(ft.mtime)) {
7210 modify_mtime = false;
7213 status = smb_set_file_time(conn,
7214 fsp,
7215 smb_fname,
7216 &ft,
7217 false);
7218 if (modify_mtime) {
7219 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7220 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7222 return status;
7225 /****************************************************************************
7226 Deal with SMB_SET_FILE_UNIX_INFO2.
7227 ****************************************************************************/
7229 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7230 struct smb_request *req,
7231 const char *pdata,
7232 int total_data,
7233 files_struct *fsp,
7234 const struct smb_filename *smb_fname)
7236 NTSTATUS status;
7237 uint32 smb_fflags;
7238 uint32 smb_fmask;
7240 if (total_data < 116) {
7241 return NT_STATUS_INVALID_PARAMETER;
7244 /* Start by setting all the fields that are common between UNIX_BASIC
7245 * and UNIX_INFO2.
7247 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7248 fsp, smb_fname);
7249 if (!NT_STATUS_IS_OK(status)) {
7250 return status;
7253 smb_fflags = IVAL(pdata, 108);
7254 smb_fmask = IVAL(pdata, 112);
7256 /* NB: We should only attempt to alter the file flags if the client
7257 * sends a non-zero mask.
7259 if (smb_fmask != 0) {
7260 int stat_fflags = 0;
7262 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7263 smb_fmask, &stat_fflags)) {
7264 /* Client asked to alter a flag we don't understand. */
7265 return NT_STATUS_INVALID_PARAMETER;
7268 if (fsp && fsp->fh->fd != -1) {
7269 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7270 return NT_STATUS_NOT_SUPPORTED;
7271 } else {
7272 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7273 stat_fflags) != 0) {
7274 return map_nt_error_from_unix(errno);
7279 /* XXX: need to add support for changing the create_time here. You
7280 * can do this for paths on Darwin with setattrlist(2). The right way
7281 * to hook this up is probably by extending the VFS utimes interface.
7284 return NT_STATUS_OK;
7287 /****************************************************************************
7288 Create a directory with POSIX semantics.
7289 ****************************************************************************/
7291 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7292 struct smb_request *req,
7293 char **ppdata,
7294 int total_data,
7295 struct smb_filename *smb_fname,
7296 int *pdata_return_size)
7298 NTSTATUS status = NT_STATUS_OK;
7299 uint32 raw_unixmode = 0;
7300 uint32 mod_unixmode = 0;
7301 mode_t unixmode = (mode_t)0;
7302 files_struct *fsp = NULL;
7303 uint16 info_level_return = 0;
7304 int info;
7305 char *pdata = *ppdata;
7307 if (total_data < 18) {
7308 return NT_STATUS_INVALID_PARAMETER;
7311 raw_unixmode = IVAL(pdata,8);
7312 /* Next 4 bytes are not yet defined. */
7314 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7315 PERM_NEW_DIR, &unixmode);
7316 if (!NT_STATUS_IS_OK(status)) {
7317 return status;
7320 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7322 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7323 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7325 status = SMB_VFS_CREATE_FILE(
7326 conn, /* conn */
7327 req, /* req */
7328 0, /* root_dir_fid */
7329 smb_fname, /* fname */
7330 FILE_READ_ATTRIBUTES, /* access_mask */
7331 FILE_SHARE_NONE, /* share_access */
7332 FILE_CREATE, /* create_disposition*/
7333 FILE_DIRECTORY_FILE, /* create_options */
7334 mod_unixmode, /* file_attributes */
7335 0, /* oplock_request */
7336 0, /* allocation_size */
7337 0, /* private_flags */
7338 NULL, /* sd */
7339 NULL, /* ea_list */
7340 &fsp, /* result */
7341 &info); /* pinfo */
7343 if (NT_STATUS_IS_OK(status)) {
7344 close_file(req, fsp, NORMAL_CLOSE);
7347 info_level_return = SVAL(pdata,16);
7349 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7350 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7351 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7352 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7353 } else {
7354 *pdata_return_size = 12;
7357 /* Realloc the data size */
7358 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7359 if (*ppdata == NULL) {
7360 *pdata_return_size = 0;
7361 return NT_STATUS_NO_MEMORY;
7363 pdata = *ppdata;
7365 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7366 SSVAL(pdata,2,0); /* No fnum. */
7367 SIVAL(pdata,4,info); /* Was directory created. */
7369 switch (info_level_return) {
7370 case SMB_QUERY_FILE_UNIX_BASIC:
7371 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7372 SSVAL(pdata,10,0); /* Padding. */
7373 store_file_unix_basic(conn, pdata + 12, fsp,
7374 &smb_fname->st);
7375 break;
7376 case SMB_QUERY_FILE_UNIX_INFO2:
7377 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7378 SSVAL(pdata,10,0); /* Padding. */
7379 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7380 &smb_fname->st);
7381 break;
7382 default:
7383 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7384 SSVAL(pdata,10,0); /* Padding. */
7385 break;
7388 return status;
7391 /****************************************************************************
7392 Open/Create a file with POSIX semantics.
7393 ****************************************************************************/
7395 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7396 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7398 static NTSTATUS smb_posix_open(connection_struct *conn,
7399 struct smb_request *req,
7400 char **ppdata,
7401 int total_data,
7402 struct smb_filename *smb_fname,
7403 int *pdata_return_size)
7405 bool extended_oplock_granted = False;
7406 char *pdata = *ppdata;
7407 uint32 flags = 0;
7408 uint32 wire_open_mode = 0;
7409 uint32 raw_unixmode = 0;
7410 uint32 mod_unixmode = 0;
7411 uint32 create_disp = 0;
7412 uint32 access_mask = 0;
7413 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7414 NTSTATUS status = NT_STATUS_OK;
7415 mode_t unixmode = (mode_t)0;
7416 files_struct *fsp = NULL;
7417 int oplock_request = 0;
7418 int info = 0;
7419 uint16 info_level_return = 0;
7421 if (total_data < 18) {
7422 return NT_STATUS_INVALID_PARAMETER;
7425 flags = IVAL(pdata,0);
7426 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7427 if (oplock_request) {
7428 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7431 wire_open_mode = IVAL(pdata,4);
7433 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7434 return smb_posix_mkdir(conn, req,
7435 ppdata,
7436 total_data,
7437 smb_fname,
7438 pdata_return_size);
7441 switch (wire_open_mode & SMB_ACCMODE) {
7442 case SMB_O_RDONLY:
7443 access_mask = SMB_O_RDONLY_MAPPING;
7444 break;
7445 case SMB_O_WRONLY:
7446 access_mask = SMB_O_WRONLY_MAPPING;
7447 break;
7448 case SMB_O_RDWR:
7449 access_mask = (SMB_O_RDONLY_MAPPING|
7450 SMB_O_WRONLY_MAPPING);
7451 break;
7452 default:
7453 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7454 (unsigned int)wire_open_mode ));
7455 return NT_STATUS_INVALID_PARAMETER;
7458 wire_open_mode &= ~SMB_ACCMODE;
7460 /* First take care of O_CREAT|O_EXCL interactions. */
7461 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7462 case (SMB_O_CREAT | SMB_O_EXCL):
7463 /* File exists fail. File not exist create. */
7464 create_disp = FILE_CREATE;
7465 break;
7466 case SMB_O_CREAT:
7467 /* File exists open. File not exist create. */
7468 create_disp = FILE_OPEN_IF;
7469 break;
7470 case SMB_O_EXCL:
7471 /* O_EXCL on its own without O_CREAT is undefined.
7472 We deliberately ignore it as some versions of
7473 Linux CIFSFS can send a bare O_EXCL on the
7474 wire which other filesystems in the kernel
7475 ignore. See bug 9519 for details. */
7477 /* Fallthrough. */
7479 case 0:
7480 /* File exists open. File not exist fail. */
7481 create_disp = FILE_OPEN;
7482 break;
7483 default:
7484 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7485 (unsigned int)wire_open_mode ));
7486 return NT_STATUS_INVALID_PARAMETER;
7489 /* Next factor in the effects of O_TRUNC. */
7490 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7492 if (wire_open_mode & SMB_O_TRUNC) {
7493 switch (create_disp) {
7494 case FILE_CREATE:
7495 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7496 /* Leave create_disp alone as
7497 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7499 /* File exists fail. File not exist create. */
7500 break;
7501 case FILE_OPEN_IF:
7502 /* SMB_O_CREAT | SMB_O_TRUNC */
7503 /* File exists overwrite. File not exist create. */
7504 create_disp = FILE_OVERWRITE_IF;
7505 break;
7506 case FILE_OPEN:
7507 /* SMB_O_TRUNC */
7508 /* File exists overwrite. File not exist fail. */
7509 create_disp = FILE_OVERWRITE;
7510 break;
7511 default:
7512 /* Cannot get here. */
7513 smb_panic("smb_posix_open: logic error");
7514 return NT_STATUS_INVALID_PARAMETER;
7518 raw_unixmode = IVAL(pdata,8);
7519 /* Next 4 bytes are not yet defined. */
7521 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7522 (VALID_STAT(smb_fname->st) ?
7523 PERM_EXISTING_FILE : PERM_NEW_FILE),
7524 &unixmode);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 return status;
7530 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7532 if (wire_open_mode & SMB_O_SYNC) {
7533 create_options |= FILE_WRITE_THROUGH;
7535 if (wire_open_mode & SMB_O_APPEND) {
7536 access_mask |= FILE_APPEND_DATA;
7538 if (wire_open_mode & SMB_O_DIRECT) {
7539 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7542 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7543 VALID_STAT_OF_DIR(smb_fname->st)) {
7544 if (access_mask != SMB_O_RDONLY_MAPPING) {
7545 return NT_STATUS_FILE_IS_A_DIRECTORY;
7547 create_options &= ~FILE_NON_DIRECTORY_FILE;
7548 create_options |= FILE_DIRECTORY_FILE;
7551 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7552 smb_fname_str_dbg(smb_fname),
7553 (unsigned int)wire_open_mode,
7554 (unsigned int)unixmode ));
7556 status = SMB_VFS_CREATE_FILE(
7557 conn, /* conn */
7558 req, /* req */
7559 0, /* root_dir_fid */
7560 smb_fname, /* fname */
7561 access_mask, /* access_mask */
7562 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7563 FILE_SHARE_DELETE),
7564 create_disp, /* create_disposition*/
7565 create_options, /* create_options */
7566 mod_unixmode, /* file_attributes */
7567 oplock_request, /* oplock_request */
7568 0, /* allocation_size */
7569 0, /* private_flags */
7570 NULL, /* sd */
7571 NULL, /* ea_list */
7572 &fsp, /* result */
7573 &info); /* pinfo */
7575 if (!NT_STATUS_IS_OK(status)) {
7576 return status;
7579 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7580 extended_oplock_granted = True;
7583 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7584 extended_oplock_granted = True;
7587 info_level_return = SVAL(pdata,16);
7589 /* Allocate the correct return size. */
7591 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7592 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7593 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7594 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7595 } else {
7596 *pdata_return_size = 12;
7599 /* Realloc the data size */
7600 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7601 if (*ppdata == NULL) {
7602 close_file(req, fsp, ERROR_CLOSE);
7603 *pdata_return_size = 0;
7604 return NT_STATUS_NO_MEMORY;
7606 pdata = *ppdata;
7608 if (extended_oplock_granted) {
7609 if (flags & REQUEST_BATCH_OPLOCK) {
7610 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7611 } else {
7612 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7614 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7615 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7616 } else {
7617 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7620 SSVAL(pdata,2,fsp->fnum);
7621 SIVAL(pdata,4,info); /* Was file created etc. */
7623 switch (info_level_return) {
7624 case SMB_QUERY_FILE_UNIX_BASIC:
7625 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7626 SSVAL(pdata,10,0); /* padding. */
7627 store_file_unix_basic(conn, pdata + 12, fsp,
7628 &smb_fname->st);
7629 break;
7630 case SMB_QUERY_FILE_UNIX_INFO2:
7631 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7632 SSVAL(pdata,10,0); /* padding. */
7633 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7634 &smb_fname->st);
7635 break;
7636 default:
7637 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7638 SSVAL(pdata,10,0); /* padding. */
7639 break;
7641 return NT_STATUS_OK;
7644 /****************************************************************************
7645 Delete a file with POSIX semantics.
7646 ****************************************************************************/
7648 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7649 struct smb_request *req,
7650 const char *pdata,
7651 int total_data,
7652 struct smb_filename *smb_fname)
7654 NTSTATUS status = NT_STATUS_OK;
7655 files_struct *fsp = NULL;
7656 uint16 flags = 0;
7657 char del = 1;
7658 int info = 0;
7659 int create_options = 0;
7660 int i;
7661 struct share_mode_lock *lck = NULL;
7663 if (total_data < 2) {
7664 return NT_STATUS_INVALID_PARAMETER;
7667 flags = SVAL(pdata,0);
7669 if (!VALID_STAT(smb_fname->st)) {
7670 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7673 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7674 !VALID_STAT_OF_DIR(smb_fname->st)) {
7675 return NT_STATUS_NOT_A_DIRECTORY;
7678 DEBUG(10,("smb_posix_unlink: %s %s\n",
7679 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7680 smb_fname_str_dbg(smb_fname)));
7682 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7683 create_options |= FILE_DIRECTORY_FILE;
7686 status = SMB_VFS_CREATE_FILE(
7687 conn, /* conn */
7688 req, /* req */
7689 0, /* root_dir_fid */
7690 smb_fname, /* fname */
7691 DELETE_ACCESS, /* access_mask */
7692 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7693 FILE_SHARE_DELETE),
7694 FILE_OPEN, /* create_disposition*/
7695 create_options, /* create_options */
7696 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7697 0, /* oplock_request */
7698 0, /* allocation_size */
7699 0, /* private_flags */
7700 NULL, /* sd */
7701 NULL, /* ea_list */
7702 &fsp, /* result */
7703 &info); /* pinfo */
7705 if (!NT_STATUS_IS_OK(status)) {
7706 return status;
7710 * Don't lie to client. If we can't really delete due to
7711 * non-POSIX opens return SHARING_VIOLATION.
7714 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7715 if (lck == NULL) {
7716 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7717 "lock for file %s\n", fsp_str_dbg(fsp)));
7718 close_file(req, fsp, NORMAL_CLOSE);
7719 return NT_STATUS_INVALID_PARAMETER;
7723 * See if others still have the file open. If this is the case, then
7724 * don't delete. If all opens are POSIX delete we can set the delete
7725 * on close disposition.
7727 for (i=0; i<lck->data->num_share_modes; i++) {
7728 struct share_mode_entry *e = &lck->data->share_modes[i];
7729 if (is_valid_share_mode_entry(e)) {
7730 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7731 continue;
7733 if (share_mode_stale_pid(lck->data, i)) {
7734 continue;
7736 /* Fail with sharing violation. */
7737 TALLOC_FREE(lck);
7738 close_file(req, fsp, NORMAL_CLOSE);
7739 return NT_STATUS_SHARING_VIOLATION;
7744 * Set the delete on close.
7746 status = smb_set_file_disposition_info(conn,
7747 &del,
7749 fsp,
7750 smb_fname);
7752 TALLOC_FREE(lck);
7754 if (!NT_STATUS_IS_OK(status)) {
7755 close_file(req, fsp, NORMAL_CLOSE);
7756 return status;
7758 return close_file(req, fsp, NORMAL_CLOSE);
7761 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7762 struct smb_request *req,
7763 TALLOC_CTX *mem_ctx,
7764 uint16_t info_level,
7765 files_struct *fsp,
7766 struct smb_filename *smb_fname,
7767 char **ppdata, int total_data,
7768 int *ret_data_size)
7770 char *pdata = *ppdata;
7771 NTSTATUS status = NT_STATUS_OK;
7772 int data_return_size = 0;
7774 *ret_data_size = 0;
7776 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7777 return NT_STATUS_INVALID_LEVEL;
7780 if (!CAN_WRITE(conn)) {
7781 /* Allow POSIX opens. The open path will deny
7782 * any non-readonly opens. */
7783 if (info_level != SMB_POSIX_PATH_OPEN) {
7784 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7788 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7789 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7790 fsp_fnum_dbg(fsp),
7791 info_level, total_data));
7793 switch (info_level) {
7795 case SMB_INFO_STANDARD:
7797 status = smb_set_info_standard(conn,
7798 pdata,
7799 total_data,
7800 fsp,
7801 smb_fname);
7802 break;
7805 case SMB_INFO_SET_EA:
7807 status = smb_info_set_ea(conn,
7808 pdata,
7809 total_data,
7810 fsp,
7811 smb_fname);
7812 break;
7815 case SMB_SET_FILE_BASIC_INFO:
7816 case SMB_FILE_BASIC_INFORMATION:
7818 status = smb_set_file_basic_info(conn,
7819 pdata,
7820 total_data,
7821 fsp,
7822 smb_fname);
7823 break;
7826 case SMB_FILE_ALLOCATION_INFORMATION:
7827 case SMB_SET_FILE_ALLOCATION_INFO:
7829 status = smb_set_file_allocation_info(conn, req,
7830 pdata,
7831 total_data,
7832 fsp,
7833 smb_fname);
7834 break;
7837 case SMB_FILE_END_OF_FILE_INFORMATION:
7838 case SMB_SET_FILE_END_OF_FILE_INFO:
7841 * XP/Win7 both fail after the createfile with
7842 * SMB_SET_FILE_END_OF_FILE_INFO but not
7843 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7844 * The level is known here, so pass it down
7845 * appropriately.
7847 bool should_fail =
7848 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7850 status = smb_set_file_end_of_file_info(conn, req,
7851 pdata,
7852 total_data,
7853 fsp,
7854 smb_fname,
7855 should_fail);
7856 break;
7859 case SMB_FILE_DISPOSITION_INFORMATION:
7860 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7862 #if 0
7863 /* JRA - We used to just ignore this on a path ?
7864 * Shouldn't this be invalid level on a pathname
7865 * based call ?
7867 if (tran_call != TRANSACT2_SETFILEINFO) {
7868 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7870 #endif
7871 status = smb_set_file_disposition_info(conn,
7872 pdata,
7873 total_data,
7874 fsp,
7875 smb_fname);
7876 break;
7879 case SMB_FILE_POSITION_INFORMATION:
7881 status = smb_file_position_information(conn,
7882 pdata,
7883 total_data,
7884 fsp);
7885 break;
7888 case SMB_FILE_FULL_EA_INFORMATION:
7890 status = smb_set_file_full_ea_info(conn,
7891 pdata,
7892 total_data,
7893 fsp);
7894 break;
7897 /* From tridge Samba4 :
7898 * MODE_INFORMATION in setfileinfo (I have no
7899 * idea what "mode information" on a file is - it takes a value of 0,
7900 * 2, 4 or 6. What could it be?).
7903 case SMB_FILE_MODE_INFORMATION:
7905 status = smb_file_mode_information(conn,
7906 pdata,
7907 total_data);
7908 break;
7912 * CIFS UNIX extensions.
7915 case SMB_SET_FILE_UNIX_BASIC:
7917 status = smb_set_file_unix_basic(conn, req,
7918 pdata,
7919 total_data,
7920 fsp,
7921 smb_fname);
7922 break;
7925 case SMB_SET_FILE_UNIX_INFO2:
7927 status = smb_set_file_unix_info2(conn, req,
7928 pdata,
7929 total_data,
7930 fsp,
7931 smb_fname);
7932 break;
7935 case SMB_SET_FILE_UNIX_LINK:
7937 if (fsp) {
7938 /* We must have a pathname for this. */
7939 return NT_STATUS_INVALID_LEVEL;
7941 status = smb_set_file_unix_link(conn, req, pdata,
7942 total_data, smb_fname);
7943 break;
7946 case SMB_SET_FILE_UNIX_HLINK:
7948 if (fsp) {
7949 /* We must have a pathname for this. */
7950 return NT_STATUS_INVALID_LEVEL;
7952 status = smb_set_file_unix_hlink(conn, req,
7953 pdata, total_data,
7954 smb_fname);
7955 break;
7958 case SMB_FILE_RENAME_INFORMATION:
7960 status = smb_file_rename_information(conn, req,
7961 pdata, total_data,
7962 fsp, smb_fname);
7963 break;
7966 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7968 /* SMB2 rename information. */
7969 status = smb2_file_rename_information(conn, req,
7970 pdata, total_data,
7971 fsp, smb_fname);
7972 break;
7975 case SMB_FILE_LINK_INFORMATION:
7977 status = smb_file_link_information(conn, req,
7978 pdata, total_data,
7979 fsp, smb_fname);
7980 break;
7983 #if defined(HAVE_POSIX_ACLS)
7984 case SMB_SET_POSIX_ACL:
7986 status = smb_set_posix_acl(conn,
7987 pdata,
7988 total_data,
7989 fsp,
7990 smb_fname);
7991 break;
7993 #endif
7995 case SMB_SET_POSIX_LOCK:
7997 if (!fsp) {
7998 return NT_STATUS_INVALID_LEVEL;
8000 status = smb_set_posix_lock(conn, req,
8001 pdata, total_data, fsp);
8002 break;
8005 case SMB_POSIX_PATH_OPEN:
8007 if (fsp) {
8008 /* We must have a pathname for this. */
8009 return NT_STATUS_INVALID_LEVEL;
8012 status = smb_posix_open(conn, req,
8013 ppdata,
8014 total_data,
8015 smb_fname,
8016 &data_return_size);
8017 break;
8020 case SMB_POSIX_PATH_UNLINK:
8022 if (fsp) {
8023 /* We must have a pathname for this. */
8024 return NT_STATUS_INVALID_LEVEL;
8027 status = smb_posix_unlink(conn, req,
8028 pdata,
8029 total_data,
8030 smb_fname);
8031 break;
8034 default:
8035 return NT_STATUS_INVALID_LEVEL;
8038 if (!NT_STATUS_IS_OK(status)) {
8039 return status;
8042 *ret_data_size = data_return_size;
8043 return NT_STATUS_OK;
8046 /****************************************************************************
8047 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8048 ****************************************************************************/
8050 static void call_trans2setfilepathinfo(connection_struct *conn,
8051 struct smb_request *req,
8052 unsigned int tran_call,
8053 char **pparams, int total_params,
8054 char **ppdata, int total_data,
8055 unsigned int max_data_bytes)
8057 char *params = *pparams;
8058 char *pdata = *ppdata;
8059 uint16 info_level;
8060 struct smb_filename *smb_fname = NULL;
8061 files_struct *fsp = NULL;
8062 NTSTATUS status = NT_STATUS_OK;
8063 int data_return_size = 0;
8065 if (!params) {
8066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8067 return;
8070 if (tran_call == TRANSACT2_SETFILEINFO) {
8071 if (total_params < 4) {
8072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8073 return;
8076 fsp = file_fsp(req, SVAL(params,0));
8077 /* Basic check for non-null fsp. */
8078 if (!check_fsp_open(conn, req, fsp)) {
8079 return;
8081 info_level = SVAL(params,2);
8083 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8084 if (smb_fname == NULL) {
8085 reply_nterror(req, NT_STATUS_NO_MEMORY);
8086 return;
8089 if(fsp->fh->fd == -1) {
8091 * This is actually a SETFILEINFO on a directory
8092 * handle (returned from an NT SMB). NT5.0 seems
8093 * to do this call. JRA.
8095 if (INFO_LEVEL_IS_UNIX(info_level)) {
8096 /* Always do lstat for UNIX calls. */
8097 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8098 DEBUG(3,("call_trans2setfilepathinfo: "
8099 "SMB_VFS_LSTAT of %s failed "
8100 "(%s)\n",
8101 smb_fname_str_dbg(smb_fname),
8102 strerror(errno)));
8103 reply_nterror(req, map_nt_error_from_unix(errno));
8104 return;
8106 } else {
8107 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8108 DEBUG(3,("call_trans2setfilepathinfo: "
8109 "fileinfo of %s failed (%s)\n",
8110 smb_fname_str_dbg(smb_fname),
8111 strerror(errno)));
8112 reply_nterror(req, map_nt_error_from_unix(errno));
8113 return;
8116 } else if (fsp->print_file) {
8118 * Doing a DELETE_ON_CLOSE should cancel a print job.
8120 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8121 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8123 DEBUG(3,("call_trans2setfilepathinfo: "
8124 "Cancelling print job (%s)\n",
8125 fsp_str_dbg(fsp)));
8127 SSVAL(params,0,0);
8128 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8129 *ppdata, 0,
8130 max_data_bytes);
8131 return;
8132 } else {
8133 reply_nterror(req,
8134 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8135 return;
8137 } else {
8139 * Original code - this is an open file.
8141 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8142 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8143 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8144 strerror(errno)));
8145 reply_nterror(req, map_nt_error_from_unix(errno));
8146 return;
8149 } else {
8150 char *fname = NULL;
8151 uint32_t ucf_flags = 0;
8153 /* set path info */
8154 if (total_params < 7) {
8155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8156 return;
8159 info_level = SVAL(params,0);
8160 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8161 total_params - 6, STR_TERMINATE,
8162 &status);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 reply_nterror(req, status);
8165 return;
8168 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8169 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8170 info_level == SMB_FILE_RENAME_INFORMATION ||
8171 info_level == SMB_POSIX_PATH_UNLINK) {
8172 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8175 status = filename_convert(req, conn,
8176 req->flags2 & FLAGS2_DFS_PATHNAMES,
8177 fname,
8178 ucf_flags,
8179 NULL,
8180 &smb_fname);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8183 reply_botherror(req,
8184 NT_STATUS_PATH_NOT_COVERED,
8185 ERRSRV, ERRbadpath);
8186 return;
8188 reply_nterror(req, status);
8189 return;
8192 if (INFO_LEVEL_IS_UNIX(info_level)) {
8194 * For CIFS UNIX extensions the target name may not exist.
8197 /* Always do lstat for UNIX calls. */
8198 SMB_VFS_LSTAT(conn, smb_fname);
8200 } else if (!VALID_STAT(smb_fname->st) &&
8201 SMB_VFS_STAT(conn, smb_fname)) {
8202 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8203 "%s failed (%s)\n",
8204 smb_fname_str_dbg(smb_fname),
8205 strerror(errno)));
8206 reply_nterror(req, map_nt_error_from_unix(errno));
8207 return;
8211 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8212 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8213 fsp_fnum_dbg(fsp),
8214 info_level,total_data));
8216 /* Realloc the parameter size */
8217 *pparams = (char *)SMB_REALLOC(*pparams,2);
8218 if (*pparams == NULL) {
8219 reply_nterror(req, NT_STATUS_NO_MEMORY);
8220 return;
8222 params = *pparams;
8224 SSVAL(params,0,0);
8226 status = smbd_do_setfilepathinfo(conn, req, req,
8227 info_level,
8228 fsp,
8229 smb_fname,
8230 ppdata, total_data,
8231 &data_return_size);
8232 if (!NT_STATUS_IS_OK(status)) {
8233 if (open_was_deferred(req->sconn, req->mid)) {
8234 /* We have re-scheduled this call. */
8235 return;
8237 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8238 /* We have re-scheduled this call. */
8239 return;
8241 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8242 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8243 ERRSRV, ERRbadpath);
8244 return;
8246 if (info_level == SMB_POSIX_PATH_OPEN) {
8247 reply_openerror(req, status);
8248 return;
8252 * Invalid EA name needs to return 2 param bytes,
8253 * not a zero-length error packet.
8255 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8256 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8257 max_data_bytes);
8258 } else {
8259 reply_nterror(req, status);
8261 return;
8264 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8265 max_data_bytes);
8267 return;
8270 /****************************************************************************
8271 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8272 ****************************************************************************/
8274 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8275 char **pparams, int total_params,
8276 char **ppdata, int total_data,
8277 unsigned int max_data_bytes)
8279 struct smb_filename *smb_dname = NULL;
8280 char *params = *pparams;
8281 char *pdata = *ppdata;
8282 char *directory = NULL;
8283 NTSTATUS status = NT_STATUS_OK;
8284 struct ea_list *ea_list = NULL;
8285 TALLOC_CTX *ctx = talloc_tos();
8287 if (!CAN_WRITE(conn)) {
8288 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8289 return;
8292 if (total_params < 5) {
8293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8294 return;
8297 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8298 total_params - 4, STR_TERMINATE,
8299 &status);
8300 if (!NT_STATUS_IS_OK(status)) {
8301 reply_nterror(req, status);
8302 return;
8305 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8307 status = filename_convert(ctx,
8308 conn,
8309 req->flags2 & FLAGS2_DFS_PATHNAMES,
8310 directory,
8312 NULL,
8313 &smb_dname);
8315 if (!NT_STATUS_IS_OK(status)) {
8316 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8317 reply_botherror(req,
8318 NT_STATUS_PATH_NOT_COVERED,
8319 ERRSRV, ERRbadpath);
8320 return;
8322 reply_nterror(req, status);
8323 return;
8327 * OS/2 workplace shell seems to send SET_EA requests of "null"
8328 * length (4 bytes containing IVAL 4).
8329 * They seem to have no effect. Bug #3212. JRA.
8332 if (total_data && (total_data != 4)) {
8333 /* Any data in this call is an EA list. */
8334 if (total_data < 10) {
8335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8336 goto out;
8339 if (IVAL(pdata,0) > total_data) {
8340 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8341 IVAL(pdata,0), (unsigned int)total_data));
8342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8343 goto out;
8346 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8347 total_data - 4);
8348 if (!ea_list) {
8349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8350 goto out;
8353 if (!lp_ea_support(SNUM(conn))) {
8354 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8355 goto out;
8358 /* If total_data == 4 Windows doesn't care what values
8359 * are placed in that field, it just ignores them.
8360 * The System i QNTC IBM SMB client puts bad values here,
8361 * so ignore them. */
8363 status = create_directory(conn, req, smb_dname);
8365 if (!NT_STATUS_IS_OK(status)) {
8366 reply_nterror(req, status);
8367 goto out;
8370 /* Try and set any given EA. */
8371 if (ea_list) {
8372 status = set_ea(conn, NULL, smb_dname, ea_list);
8373 if (!NT_STATUS_IS_OK(status)) {
8374 reply_nterror(req, status);
8375 goto out;
8379 /* Realloc the parameter and data sizes */
8380 *pparams = (char *)SMB_REALLOC(*pparams,2);
8381 if(*pparams == NULL) {
8382 reply_nterror(req, NT_STATUS_NO_MEMORY);
8383 goto out;
8385 params = *pparams;
8387 SSVAL(params,0,0);
8389 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8391 out:
8392 TALLOC_FREE(smb_dname);
8393 return;
8396 /****************************************************************************
8397 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8398 We don't actually do this - we just send a null response.
8399 ****************************************************************************/
8401 static void call_trans2findnotifyfirst(connection_struct *conn,
8402 struct smb_request *req,
8403 char **pparams, int total_params,
8404 char **ppdata, int total_data,
8405 unsigned int max_data_bytes)
8407 char *params = *pparams;
8408 uint16 info_level;
8410 if (total_params < 6) {
8411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8412 return;
8415 info_level = SVAL(params,4);
8416 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8418 switch (info_level) {
8419 case 1:
8420 case 2:
8421 break;
8422 default:
8423 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8424 return;
8427 /* Realloc the parameter and data sizes */
8428 *pparams = (char *)SMB_REALLOC(*pparams,6);
8429 if (*pparams == NULL) {
8430 reply_nterror(req, NT_STATUS_NO_MEMORY);
8431 return;
8433 params = *pparams;
8435 SSVAL(params,0,fnf_handle);
8436 SSVAL(params,2,0); /* No changes */
8437 SSVAL(params,4,0); /* No EA errors */
8439 fnf_handle++;
8441 if(fnf_handle == 0)
8442 fnf_handle = 257;
8444 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8446 return;
8449 /****************************************************************************
8450 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8451 changes). Currently this does nothing.
8452 ****************************************************************************/
8454 static void call_trans2findnotifynext(connection_struct *conn,
8455 struct smb_request *req,
8456 char **pparams, int total_params,
8457 char **ppdata, int total_data,
8458 unsigned int max_data_bytes)
8460 char *params = *pparams;
8462 DEBUG(3,("call_trans2findnotifynext\n"));
8464 /* Realloc the parameter and data sizes */
8465 *pparams = (char *)SMB_REALLOC(*pparams,4);
8466 if (*pparams == NULL) {
8467 reply_nterror(req, NT_STATUS_NO_MEMORY);
8468 return;
8470 params = *pparams;
8472 SSVAL(params,0,0); /* No changes */
8473 SSVAL(params,2,0); /* No EA errors */
8475 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8477 return;
8480 /****************************************************************************
8481 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8482 ****************************************************************************/
8484 static void call_trans2getdfsreferral(connection_struct *conn,
8485 struct smb_request *req,
8486 char **pparams, int total_params,
8487 char **ppdata, int total_data,
8488 unsigned int max_data_bytes)
8490 char *params = *pparams;
8491 char *pathname = NULL;
8492 int reply_size = 0;
8493 int max_referral_level;
8494 NTSTATUS status = NT_STATUS_OK;
8495 TALLOC_CTX *ctx = talloc_tos();
8497 DEBUG(10,("call_trans2getdfsreferral\n"));
8499 if (total_params < 3) {
8500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8501 return;
8504 max_referral_level = SVAL(params,0);
8506 if(!lp_host_msdfs()) {
8507 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8508 return;
8511 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8512 total_params - 2, STR_TERMINATE);
8513 if (!pathname) {
8514 reply_nterror(req, NT_STATUS_NOT_FOUND);
8515 return;
8517 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8518 ppdata,&status)) < 0) {
8519 reply_nterror(req, status);
8520 return;
8523 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8524 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8525 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8527 return;
8530 #define LMCAT_SPL 0x53
8531 #define LMFUNC_GETJOBID 0x60
8533 /****************************************************************************
8534 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8535 ****************************************************************************/
8537 static void call_trans2ioctl(connection_struct *conn,
8538 struct smb_request *req,
8539 char **pparams, int total_params,
8540 char **ppdata, int total_data,
8541 unsigned int max_data_bytes)
8543 char *pdata = *ppdata;
8544 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8546 /* check for an invalid fid before proceeding */
8548 if (!fsp) {
8549 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8550 return;
8553 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8554 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8555 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8556 if (*ppdata == NULL) {
8557 reply_nterror(req, NT_STATUS_NO_MEMORY);
8558 return;
8560 pdata = *ppdata;
8562 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8563 CAN ACCEPT THIS IN UNICODE. JRA. */
8565 /* Job number */
8566 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8568 srvstr_push(pdata, req->flags2, pdata + 2,
8569 lp_netbios_name(), 15,
8570 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8571 srvstr_push(pdata, req->flags2, pdata+18,
8572 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8573 STR_ASCII|STR_TERMINATE); /* Service name */
8574 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8575 max_data_bytes);
8576 return;
8579 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8580 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8583 /****************************************************************************
8584 Reply to a SMBfindclose (stop trans2 directory search).
8585 ****************************************************************************/
8587 void reply_findclose(struct smb_request *req)
8589 int dptr_num;
8590 struct smbd_server_connection *sconn = req->sconn;
8592 START_PROFILE(SMBfindclose);
8594 if (req->wct < 1) {
8595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8596 END_PROFILE(SMBfindclose);
8597 return;
8600 dptr_num = SVALS(req->vwv+0, 0);
8602 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8604 dptr_close(sconn, &dptr_num);
8606 reply_outbuf(req, 0, 0);
8608 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8610 END_PROFILE(SMBfindclose);
8611 return;
8614 /****************************************************************************
8615 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8616 ****************************************************************************/
8618 void reply_findnclose(struct smb_request *req)
8620 int dptr_num;
8622 START_PROFILE(SMBfindnclose);
8624 if (req->wct < 1) {
8625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8626 END_PROFILE(SMBfindnclose);
8627 return;
8630 dptr_num = SVAL(req->vwv+0, 0);
8632 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8634 /* We never give out valid handles for a
8635 findnotifyfirst - so any dptr_num is ok here.
8636 Just ignore it. */
8638 reply_outbuf(req, 0, 0);
8640 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8642 END_PROFILE(SMBfindnclose);
8643 return;
8646 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8647 struct trans_state *state)
8649 if (get_Protocol() >= PROTOCOL_NT1) {
8650 req->flags2 |= 0x40; /* IS_LONG_NAME */
8651 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8654 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8655 if (state->call != TRANSACT2_QFSINFO &&
8656 state->call != TRANSACT2_SETFSINFO) {
8657 DEBUG(0,("handle_trans2: encryption required "
8658 "with call 0x%x\n",
8659 (unsigned int)state->call));
8660 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8661 return;
8665 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8667 /* Now we must call the relevant TRANS2 function */
8668 switch(state->call) {
8669 case TRANSACT2_OPEN:
8671 START_PROFILE(Trans2_open);
8672 call_trans2open(conn, req,
8673 &state->param, state->total_param,
8674 &state->data, state->total_data,
8675 state->max_data_return);
8676 END_PROFILE(Trans2_open);
8677 break;
8680 case TRANSACT2_FINDFIRST:
8682 START_PROFILE(Trans2_findfirst);
8683 call_trans2findfirst(conn, req,
8684 &state->param, state->total_param,
8685 &state->data, state->total_data,
8686 state->max_data_return);
8687 END_PROFILE(Trans2_findfirst);
8688 break;
8691 case TRANSACT2_FINDNEXT:
8693 START_PROFILE(Trans2_findnext);
8694 call_trans2findnext(conn, req,
8695 &state->param, state->total_param,
8696 &state->data, state->total_data,
8697 state->max_data_return);
8698 END_PROFILE(Trans2_findnext);
8699 break;
8702 case TRANSACT2_QFSINFO:
8704 START_PROFILE(Trans2_qfsinfo);
8705 call_trans2qfsinfo(conn, req,
8706 &state->param, state->total_param,
8707 &state->data, state->total_data,
8708 state->max_data_return);
8709 END_PROFILE(Trans2_qfsinfo);
8710 break;
8713 case TRANSACT2_SETFSINFO:
8715 START_PROFILE(Trans2_setfsinfo);
8716 call_trans2setfsinfo(conn, req,
8717 &state->param, state->total_param,
8718 &state->data, state->total_data,
8719 state->max_data_return);
8720 END_PROFILE(Trans2_setfsinfo);
8721 break;
8724 case TRANSACT2_QPATHINFO:
8725 case TRANSACT2_QFILEINFO:
8727 START_PROFILE(Trans2_qpathinfo);
8728 call_trans2qfilepathinfo(conn, req, state->call,
8729 &state->param, state->total_param,
8730 &state->data, state->total_data,
8731 state->max_data_return);
8732 END_PROFILE(Trans2_qpathinfo);
8733 break;
8736 case TRANSACT2_SETPATHINFO:
8737 case TRANSACT2_SETFILEINFO:
8739 START_PROFILE(Trans2_setpathinfo);
8740 call_trans2setfilepathinfo(conn, req, state->call,
8741 &state->param, state->total_param,
8742 &state->data, state->total_data,
8743 state->max_data_return);
8744 END_PROFILE(Trans2_setpathinfo);
8745 break;
8748 case TRANSACT2_FINDNOTIFYFIRST:
8750 START_PROFILE(Trans2_findnotifyfirst);
8751 call_trans2findnotifyfirst(conn, req,
8752 &state->param, state->total_param,
8753 &state->data, state->total_data,
8754 state->max_data_return);
8755 END_PROFILE(Trans2_findnotifyfirst);
8756 break;
8759 case TRANSACT2_FINDNOTIFYNEXT:
8761 START_PROFILE(Trans2_findnotifynext);
8762 call_trans2findnotifynext(conn, req,
8763 &state->param, state->total_param,
8764 &state->data, state->total_data,
8765 state->max_data_return);
8766 END_PROFILE(Trans2_findnotifynext);
8767 break;
8770 case TRANSACT2_MKDIR:
8772 START_PROFILE(Trans2_mkdir);
8773 call_trans2mkdir(conn, req,
8774 &state->param, state->total_param,
8775 &state->data, state->total_data,
8776 state->max_data_return);
8777 END_PROFILE(Trans2_mkdir);
8778 break;
8781 case TRANSACT2_GET_DFS_REFERRAL:
8783 START_PROFILE(Trans2_get_dfs_referral);
8784 call_trans2getdfsreferral(conn, req,
8785 &state->param, state->total_param,
8786 &state->data, state->total_data,
8787 state->max_data_return);
8788 END_PROFILE(Trans2_get_dfs_referral);
8789 break;
8792 case TRANSACT2_IOCTL:
8794 START_PROFILE(Trans2_ioctl);
8795 call_trans2ioctl(conn, req,
8796 &state->param, state->total_param,
8797 &state->data, state->total_data,
8798 state->max_data_return);
8799 END_PROFILE(Trans2_ioctl);
8800 break;
8803 default:
8804 /* Error in request */
8805 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8806 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8810 /****************************************************************************
8811 Reply to a SMBtrans2.
8812 ****************************************************************************/
8814 void reply_trans2(struct smb_request *req)
8816 connection_struct *conn = req->conn;
8817 unsigned int dsoff;
8818 unsigned int dscnt;
8819 unsigned int psoff;
8820 unsigned int pscnt;
8821 unsigned int tran_call;
8822 struct trans_state *state;
8823 NTSTATUS result;
8825 START_PROFILE(SMBtrans2);
8827 if (req->wct < 14) {
8828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8829 END_PROFILE(SMBtrans2);
8830 return;
8833 dsoff = SVAL(req->vwv+12, 0);
8834 dscnt = SVAL(req->vwv+11, 0);
8835 psoff = SVAL(req->vwv+10, 0);
8836 pscnt = SVAL(req->vwv+9, 0);
8837 tran_call = SVAL(req->vwv+14, 0);
8839 result = allow_new_trans(conn->pending_trans, req->mid);
8840 if (!NT_STATUS_IS_OK(result)) {
8841 DEBUG(2, ("Got invalid trans2 request: %s\n",
8842 nt_errstr(result)));
8843 reply_nterror(req, result);
8844 END_PROFILE(SMBtrans2);
8845 return;
8848 if (IS_IPC(conn)) {
8849 switch (tran_call) {
8850 /* List the allowed trans2 calls on IPC$ */
8851 case TRANSACT2_OPEN:
8852 case TRANSACT2_GET_DFS_REFERRAL:
8853 case TRANSACT2_QFILEINFO:
8854 case TRANSACT2_QFSINFO:
8855 case TRANSACT2_SETFSINFO:
8856 break;
8857 default:
8858 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8859 END_PROFILE(SMBtrans2);
8860 return;
8864 if ((state = talloc(conn, struct trans_state)) == NULL) {
8865 DEBUG(0, ("talloc failed\n"));
8866 reply_nterror(req, NT_STATUS_NO_MEMORY);
8867 END_PROFILE(SMBtrans2);
8868 return;
8871 state->cmd = SMBtrans2;
8873 state->mid = req->mid;
8874 state->vuid = req->vuid;
8875 state->setup_count = SVAL(req->vwv+13, 0);
8876 state->setup = NULL;
8877 state->total_param = SVAL(req->vwv+0, 0);
8878 state->param = NULL;
8879 state->total_data = SVAL(req->vwv+1, 0);
8880 state->data = NULL;
8881 state->max_param_return = SVAL(req->vwv+2, 0);
8882 state->max_data_return = SVAL(req->vwv+3, 0);
8883 state->max_setup_return = SVAL(req->vwv+4, 0);
8884 state->close_on_completion = BITSETW(req->vwv+5, 0);
8885 state->one_way = BITSETW(req->vwv+5, 1);
8887 state->call = tran_call;
8889 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8890 is so as a sanity check */
8891 if (state->setup_count != 1) {
8893 * Need to have rc=0 for ioctl to get job id for OS/2.
8894 * Network printing will fail if function is not successful.
8895 * Similar function in reply.c will be used if protocol
8896 * is LANMAN1.0 instead of LM1.2X002.
8897 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8898 * outbuf doesn't have to be set(only job id is used).
8900 if ( (state->setup_count == 4)
8901 && (tran_call == TRANSACT2_IOCTL)
8902 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8903 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8904 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8905 } else {
8906 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8907 DEBUG(2,("Transaction is %d\n",tran_call));
8908 TALLOC_FREE(state);
8909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8910 END_PROFILE(SMBtrans2);
8911 return;
8915 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8916 goto bad_param;
8918 if (state->total_data) {
8920 if (trans_oob(state->total_data, 0, dscnt)
8921 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8922 goto bad_param;
8925 /* Can't use talloc here, the core routines do realloc on the
8926 * params and data. */
8927 state->data = (char *)SMB_MALLOC(state->total_data);
8928 if (state->data == NULL) {
8929 DEBUG(0,("reply_trans2: data malloc fail for %u "
8930 "bytes !\n", (unsigned int)state->total_data));
8931 TALLOC_FREE(state);
8932 reply_nterror(req, NT_STATUS_NO_MEMORY);
8933 END_PROFILE(SMBtrans2);
8934 return;
8937 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8940 if (state->total_param) {
8942 if (trans_oob(state->total_param, 0, pscnt)
8943 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8944 goto bad_param;
8947 /* Can't use talloc here, the core routines do realloc on the
8948 * params and data. */
8949 state->param = (char *)SMB_MALLOC(state->total_param);
8950 if (state->param == NULL) {
8951 DEBUG(0,("reply_trans: param malloc fail for %u "
8952 "bytes !\n", (unsigned int)state->total_param));
8953 SAFE_FREE(state->data);
8954 TALLOC_FREE(state);
8955 reply_nterror(req, NT_STATUS_NO_MEMORY);
8956 END_PROFILE(SMBtrans2);
8957 return;
8960 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8963 state->received_data = dscnt;
8964 state->received_param = pscnt;
8966 if ((state->received_param == state->total_param) &&
8967 (state->received_data == state->total_data)) {
8969 handle_trans2(conn, req, state);
8971 SAFE_FREE(state->data);
8972 SAFE_FREE(state->param);
8973 TALLOC_FREE(state);
8974 END_PROFILE(SMBtrans2);
8975 return;
8978 DLIST_ADD(conn->pending_trans, state);
8980 /* We need to send an interim response then receive the rest
8981 of the parameter/data bytes */
8982 reply_outbuf(req, 0, 0);
8983 show_msg((char *)req->outbuf);
8984 END_PROFILE(SMBtrans2);
8985 return;
8987 bad_param:
8989 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8990 SAFE_FREE(state->data);
8991 SAFE_FREE(state->param);
8992 TALLOC_FREE(state);
8993 END_PROFILE(SMBtrans2);
8994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8998 /****************************************************************************
8999 Reply to a SMBtranss2
9000 ****************************************************************************/
9002 void reply_transs2(struct smb_request *req)
9004 connection_struct *conn = req->conn;
9005 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9006 struct trans_state *state;
9008 START_PROFILE(SMBtranss2);
9010 show_msg((const char *)req->inbuf);
9012 /* Windows clients expect all replies to
9013 a transact secondary (SMBtranss2 0x33)
9014 to have a command code of transact
9015 (SMBtrans2 0x32). See bug #8989
9016 and also [MS-CIFS] section 2.2.4.47.2
9017 for details.
9019 req->cmd = SMBtrans2;
9021 if (req->wct < 8) {
9022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 END_PROFILE(SMBtranss2);
9024 return;
9027 for (state = conn->pending_trans; state != NULL;
9028 state = state->next) {
9029 if (state->mid == req->mid) {
9030 break;
9034 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9036 END_PROFILE(SMBtranss2);
9037 return;
9040 /* Revise state->total_param and state->total_data in case they have
9041 changed downwards */
9043 if (SVAL(req->vwv+0, 0) < state->total_param)
9044 state->total_param = SVAL(req->vwv+0, 0);
9045 if (SVAL(req->vwv+1, 0) < state->total_data)
9046 state->total_data = SVAL(req->vwv+1, 0);
9048 pcnt = SVAL(req->vwv+2, 0);
9049 poff = SVAL(req->vwv+3, 0);
9050 pdisp = SVAL(req->vwv+4, 0);
9052 dcnt = SVAL(req->vwv+5, 0);
9053 doff = SVAL(req->vwv+6, 0);
9054 ddisp = SVAL(req->vwv+7, 0);
9056 state->received_param += pcnt;
9057 state->received_data += dcnt;
9059 if ((state->received_data > state->total_data) ||
9060 (state->received_param > state->total_param))
9061 goto bad_param;
9063 if (pcnt) {
9064 if (trans_oob(state->total_param, pdisp, pcnt)
9065 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9066 goto bad_param;
9068 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9071 if (dcnt) {
9072 if (trans_oob(state->total_data, ddisp, dcnt)
9073 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9074 goto bad_param;
9076 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9079 if ((state->received_param < state->total_param) ||
9080 (state->received_data < state->total_data)) {
9081 END_PROFILE(SMBtranss2);
9082 return;
9085 handle_trans2(conn, req, state);
9087 DLIST_REMOVE(conn->pending_trans, state);
9088 SAFE_FREE(state->data);
9089 SAFE_FREE(state->param);
9090 TALLOC_FREE(state);
9092 END_PROFILE(SMBtranss2);
9093 return;
9095 bad_param:
9097 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9098 DLIST_REMOVE(conn->pending_trans, state);
9099 SAFE_FREE(state->data);
9100 SAFE_FREE(state->param);
9101 TALLOC_FREE(state);
9102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9103 END_PROFILE(SMBtranss2);
9104 return;