Allow UNIX extensions client to act on open fsp instead of pathname if available.
[Samba.git] / source3 / smbd / trans2.c
blob3cd21926b181335bc9a281a9ade1e0f89130fa8c
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
882 uint8_t eclass;
883 uint32_t ecode;
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
887 __LINE__,__FILE__);
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
891 (char *)req->outbuf,
892 true, req->seqnum+1,
893 IS_CONN_ENCRYPTED(conn),
894 &req->pcd)) {
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
898 return;
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
913 + 2 * 10 /* wct */
914 + alignment_offset
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
966 else
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
974 } else {
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1014 if (overflow) {
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1018 __LINE__,__FILE__);
1019 } else if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1034 &req->pcd))
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1045 /* Sanity check */
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1049 return;
1053 return;
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1069 int deny_mode;
1070 int32 open_attr;
1071 bool oplock_request;
1072 #if 0
1073 bool return_additional_info;
1074 int16 open_sattr;
1075 time_t open_time;
1076 #endif
1077 int open_ofun;
1078 uint32 open_size;
1079 char *pname;
1080 char *fname = NULL;
1081 off_t size=0;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1084 int smb_action = 0;
1085 files_struct *fsp;
1086 struct ea_list *ea_list = NULL;
1087 uint16 flags = 0;
1088 NTSTATUS status;
1089 uint32 access_mask;
1090 uint32 share_mode;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 goto out;
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1113 #if 0
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1117 #endif
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = &params[28];
1122 if (IS_IPC(conn)) {
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1124 goto out;
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1129 &status);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1132 goto out;
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1159 goto out;
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1163 open_ofun,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1166 &create_options,
1167 &private_flags)) {
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1169 goto out;
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 goto out;
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 goto out;
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1187 total_data - 4);
1188 if (!ea_list) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1195 goto out;
1198 if (ea_list_has_invalid_name(ea_list)) {
1199 int param_len = 30;
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1203 goto out;
1205 params = *pparams;
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1209 goto out;
1213 status = SMB_VFS_CREATE_FILE(
1214 conn, /* conn */
1215 req, /* req */
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1225 private_flags,
1226 NULL, /* sd */
1227 ea_list, /* ea_list */
1228 &fsp, /* result */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1234 goto out;
1236 reply_openerror(req, status);
1237 goto out;
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 goto out;
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1254 goto out;
1256 params = *pparams;
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1277 if (flags & 8) {
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1279 smb_fname);
1280 SIVAL(params, 26, ea_size);
1281 } else {
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1287 out:
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1300 const char *str,
1301 const char *mask)
1303 if (mask[0] == '.' && mask[1] == 0) {
1304 return false;
1307 if (has_wild) {
1308 return false;
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1313 } else {
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1324 if(S_ISREG(mode))
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1328 #ifdef S_ISLNK
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1331 #endif
1332 #ifdef S_ISCHR
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1335 #endif
1336 #ifdef S_ISBLK
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1339 #endif
1340 #ifdef S_ISFIFO
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1343 #endif
1344 #ifdef S_ISSOCK
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1347 #endif
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1361 uint32 perms,
1362 enum perm_type ptype,
1363 mode_t *ret_perms)
1365 mode_t ret = 0;
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1370 } else {
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1385 #ifdef S_ISVTX
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1387 #endif
1388 #ifdef S_ISGID
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1390 #endif
1391 #ifdef S_ISUID
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1393 #endif
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1413 *ret_perms = ret;
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 "as a directory\n",
1433 pathname));
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1436 return true;
1438 errno = saved_errno;
1439 return false;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1451 bool has_wild;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1456 void *private_data,
1457 const char *dname,
1458 const char *mask,
1459 char **_fname)
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1463 bool ok;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1465 bool got_match;
1466 const char *fname;
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1472 if (!ok) {
1473 return false;
1475 fname = mangled_name;
1476 } else {
1477 fname = dname;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1482 fname, mask);
1483 state->got_exact_match = got_match;
1484 if (!got_match) {
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1500 if (!ok) {
1501 return false;
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1508 if (!got_match) {
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1514 if (!got_match) {
1515 return false;
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1520 return false;
1523 return true;
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1527 void *private_data,
1528 struct smb_filename *smb_fname,
1529 uint32_t *_mode)
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1534 uint32_t mode = 0;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1541 strerror(errno)));
1542 return false;
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1547 * directories */
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1551 &smb_fname->st);
1552 if (!ms_dfs_link) {
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1556 strerror(errno)));
1557 return false;
1561 if (ms_dfs_link) {
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1563 } else {
1564 mode = dos_mode(state->conn, smb_fname);
1567 *_mode = mode;
1568 return true;
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1573 uint16_t flags2,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1578 uint32_t mode,
1579 const char *fname,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1582 uint8_t align,
1583 bool do_pad,
1584 char *base_data,
1585 char **ppdata,
1586 char *end_data,
1587 bool *out_of_space,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1591 uint32_t reskey=0;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1595 uint32_t len;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1598 char *nameptr;
1599 char *last_entry_ptr;
1600 bool was_8_3;
1601 int off;
1602 int pad = 0;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1639 pad -= off;
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1645 (unsigned int)pad,
1646 space_remaining ));
1647 return false; /* Not finished - just out of space */
1650 off += pad;
1651 /* initialize padding to 0 */
1652 if (pad) {
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1658 space_remaining ));
1660 pdata += pad;
1661 p = pdata;
1662 last_entry_ptr = p;
1664 pad = 0;
1665 off = 0;
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 23;
1681 nameptr = p;
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE);
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1689 if (len > 2) {
1690 SCVAL(nameptr, -1, len - 2);
1691 } else {
1692 SCVAL(nameptr, -1, 0);
1694 } else {
1695 if (len > 1) {
1696 SCVAL(nameptr, -1, len - 1);
1697 } else {
1698 SCVAL(nameptr, -1, 0);
1701 p += len;
1702 break;
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key) {
1707 SIVAL(p,0,reskey);
1708 p += 4;
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1715 SSVAL(p,20,mode);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1718 smb_fname);
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1721 p += 27;
1722 nameptr = p - 1;
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1747 size_t ea_len = 0;
1748 NTSTATUS status;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1751 if (!name_list) {
1752 return false;
1754 if (requires_resume_key) {
1755 SIVAL(p,0,reskey);
1756 p += 4;
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1763 SSVAL(p,20,mode);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1767 smb_fname,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 file_list = NULL;
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1781 space_remaining ));
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1787 nameptr = p;
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1792 if (len > 2) {
1793 len -= 2;
1794 } else {
1795 len = 0;
1797 } else {
1798 if (len > 1) {
1799 len -= 1;
1800 } else {
1801 len = 0;
1804 SCVAL(nameptr,0,len);
1805 p += len + 1;
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1807 break;
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1813 p += 4;
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1825 } else {
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1830 p += 4;
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1838 conn->params)) {
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1846 if (len < 24) {
1847 memset(p + 2 + len,'\0',24 - len);
1849 SSVAL(p, 0, len);
1850 } else {
1851 memset(p,'\0',26);
1853 p += 2 + 24;
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1857 SIVAL(q,0,len);
1858 p += len;
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1867 SIVAL(pdata,0,pad);
1869 * set padding to zero
1871 if (do_pad) {
1872 memset(p, 0, pad - len);
1873 p = pdata + pad;
1874 } else {
1875 p = pdata + len;
1877 break;
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1881 p += 4;
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1893 SIVAL(p,0,len);
1894 p += 4 + len;
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1903 SIVAL(pdata,0,pad);
1905 * set padding to zero
1907 if (do_pad) {
1908 memset(p, 0, pad - len);
1909 p = pdata + pad;
1910 } else {
1911 p = pdata + len;
1913 break;
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1936 SIVAL(q, 0, len);
1937 p += len;
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1946 SIVAL(pdata,0,pad);
1948 * set padding to zero
1950 if (do_pad) {
1951 memset(p, 0, pad - len);
1952 p = pdata + pad;
1953 } else {
1954 p = pdata + len;
1956 break;
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1960 p += 4;
1961 SIVAL(p,0,reskey); p += 4;
1962 p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1968 SIVAL(p, -4, len);
1969 p += len;
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1978 SIVAL(pdata,0,pad);
1980 * set padding to zero
1982 if (do_pad) {
1983 memset(p, 0, pad - len);
1984 p = pdata + pad;
1985 } else {
1986 p = pdata + len;
1988 break;
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1992 p += 4;
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2004 } else {
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2006 smb_fname);
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2009 p += 4;
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2015 SIVAL(q, 0, len);
2016 p += len;
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2025 SIVAL(pdata,0,pad);
2027 * set padding to zero
2029 if (do_pad) {
2030 memset(p, 0, pad - len);
2031 p = pdata + pad;
2032 } else {
2033 p = pdata + len;
2035 break;
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2040 p += 4;
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2052 } else {
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2054 smb_fname);
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2057 p += 4;
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2065 conn->params)) {
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2073 SSVAL(p, 0, len);
2074 if (len < 24) {
2075 memset(p + 2 + len,'\0',24 - len);
2077 SSVAL(p, 0, len);
2078 } else {
2079 memset(p,'\0',26);
2081 p += 26;
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
2087 SIVAL(q,0,len);
2088 p += len;
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2097 SIVAL(pdata,0,pad);
2099 * set padding to zero
2101 if (do_pad) {
2102 memset(p, 0, pad - len);
2103 p = pdata + pad;
2104 } else {
2105 p = pdata + len;
2107 break;
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2113 p+= 4;
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2124 STR_TERMINATE);
2125 } else {
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2129 nameptr = p;
2130 p += 4;
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2136 p += len;
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2145 SIVAL(pdata,0,pad);
2147 * set padding to zero
2149 if (do_pad) {
2150 memset(p, 0, pad - len);
2151 p = pdata + pad;
2152 } else {
2153 p = pdata + len;
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2157 break;
2159 default:
2160 return false;
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2168 space_remaining ));
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2175 *ppdata = p;
2177 return true;
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 int requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 uint8_t align,
2191 bool do_pad,
2192 char **ppdata,
2193 char *base_data,
2194 char *end_data,
2195 int space_remaining,
2196 bool *out_of_space,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2201 const char *p;
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2204 uint32_t mode = 0;
2205 char *fname = NULL;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2208 bool ok;
2209 uint64_t last_entry_off = 0;
2211 ZERO_STRUCT(state);
2212 state.conn = conn;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2222 if(p != NULL) {
2223 if(p[1] == '\0') {
2224 mask = "*.*";
2225 } else {
2226 mask = p+1;
2228 } else {
2229 mask = path_mask;
2232 ok = smbd_dirptr_get_entry(ctx,
2233 dirptr,
2234 mask,
2235 dirtype,
2236 dont_descend,
2237 ask_sharemode,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2240 &state,
2241 &fname,
2242 &smb_fname,
2243 &mode,
2244 &prev_dirpos);
2245 if (!ok) {
2246 return false;
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2252 conn,
2253 flags2,
2254 info_level,
2255 name_list,
2256 state.check_mangled_names,
2257 requires_resume_key,
2258 mode,
2259 fname,
2260 smb_fname,
2261 space_remaining,
2262 align,
2263 do_pad,
2264 base_data,
2265 ppdata,
2266 end_data,
2267 out_of_space,
2268 &last_entry_off);
2269 TALLOC_FREE(fname);
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2273 return false;
2275 if (!ok) {
2276 return false;
2279 *_last_entry_off = last_entry_off;
2280 return true;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2286 uint16 flags2,
2287 const char *path_mask,
2288 uint32 dirtype,
2289 int info_level,
2290 bool requires_resume_key,
2291 bool dont_descend,
2292 bool ask_sharemode,
2293 char **ppdata,
2294 char *base_data,
2295 char *end_data,
2296 int space_remaining,
2297 bool *out_of_space,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2302 uint8_t align = 4;
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2307 align = 1;
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2313 align, do_pad,
2314 ppdata, base_data, end_data,
2315 space_remaining,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2334 requested. */
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2338 char *data_end;
2339 uint32 dirtype;
2340 int maxentries;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2343 bool close_if_end;
2344 bool requires_resume_key;
2345 int info_level;
2346 char *directory = NULL;
2347 char *mask = NULL;
2348 char *p;
2349 int last_entry_off=0;
2350 int dptr_num = -1;
2351 int numentries = 0;
2352 int i;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2367 if (total_params < 13) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2372 dirtype = SVAL(params,0);
2373 maxentries = SVAL(params,2);
2374 findfirst_flags = SVAL(params,4);
2375 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2376 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2377 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2378 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2379 security_token_has_privilege(get_current_nttok(conn),
2380 SEC_PRIV_BACKUP));
2382 info_level = SVAL(params,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2387 (int)backup_priv,
2388 info_level, max_data_bytes));
2390 if (!maxentries) {
2391 /* W2K3 seems to treat zero as 1. */
2392 maxentries = 1;
2395 switch (info_level) {
2396 case SMB_FIND_INFO_STANDARD:
2397 case SMB_FIND_EA_SIZE:
2398 case SMB_FIND_EA_LIST:
2399 case SMB_FIND_FILE_DIRECTORY_INFO:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_NAMES_INFO:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2405 break;
2406 case SMB_FIND_FILE_UNIX:
2407 case SMB_FIND_FILE_UNIX_INFO2:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode = false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 goto out;
2414 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 break;
2416 default:
2417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2418 goto out;
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2422 params+12, total_params - 12,
2423 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2424 if (!NT_STATUS_IS_OK(ntstatus)) {
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 if (backup_priv) {
2430 become_root();
2431 ntstatus = filename_convert_with_privilege(ctx,
2432 conn,
2433 req,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2438 } else {
2439 ntstatus = filename_convert(ctx, conn,
2440 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 directory,
2442 ucf_flags,
2443 &mask_contains_wcard,
2444 &smb_dname);
2447 if (!NT_STATUS_IS_OK(ntstatus)) {
2448 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2450 ERRSRV, ERRbadpath);
2451 goto out;
2453 reply_nterror(req, ntstatus);
2454 goto out;
2457 mask = smb_dname->original_lcomp;
2459 directory = smb_dname->base_name;
2461 p = strrchr_m(directory,'/');
2462 if(p == NULL) {
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory[0] == '.') && (directory[1] == '\0')) {
2465 mask = talloc_strdup(ctx,"*");
2466 if (!mask) {
2467 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 goto out;
2470 mask_contains_wcard = True;
2472 } else {
2473 *p = 0;
2476 if (p == NULL || p == directory) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory = talloc_strdup(talloc_tos(), ".");
2479 if (!directory) {
2480 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 goto out;
2485 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2487 if (info_level == SMB_FIND_EA_LIST) {
2488 uint32 ea_size;
2490 if (total_data < 4) {
2491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2492 goto out;
2495 ea_size = IVAL(pdata,0);
2496 if (ea_size != total_data) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 goto out;
2503 if (!lp_ea_support(SNUM(conn))) {
2504 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2505 goto out;
2508 /* Pull out the list of names. */
2509 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2510 if (!ea_list) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2516 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2518 goto out;
2521 *ppdata = (char *)SMB_REALLOC(
2522 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2523 if(*ppdata == NULL ) {
2524 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 goto out;
2527 pdata = *ppdata;
2528 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2530 /* Realloc the params space */
2531 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2532 if (*pparams == NULL) {
2533 reply_nterror(req, NT_STATUS_NO_MEMORY);
2534 goto out;
2536 params = *pparams;
2538 /* Save the wildcard match and attribs we are using on this directory -
2539 needed as lanman2 assumes these are being saved between calls */
2541 ntstatus = dptr_create(conn,
2542 req,
2543 NULL, /* fsp */
2544 directory,
2545 False,
2546 True,
2547 req->smbpid,
2548 mask,
2549 mask_contains_wcard,
2550 dirtype,
2551 &dirptr);
2553 if (!NT_STATUS_IS_OK(ntstatus)) {
2554 reply_nterror(req, ntstatus);
2555 goto out;
2558 if (backup_priv) {
2559 /* Remember this in case we have
2560 to do a findnext. */
2561 dptr_set_priv(dirptr);
2564 dptr_num = dptr_dnum(dirptr);
2565 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2567 /* Initialize per TRANS2_FIND_FIRST operation data */
2568 dptr_init_search_op(dirptr);
2570 /* We don't need to check for VOL here as this is returned by
2571 a different TRANS2 call. */
2573 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2574 directory,lp_dontdescend(ctx, SNUM(conn))));
2575 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2576 dont_descend = True;
2578 p = pdata;
2579 space_remaining = max_data_bytes;
2580 out_of_space = False;
2582 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2583 bool got_exact_match = False;
2585 /* this is a heuristic to avoid seeking the dirptr except when
2586 absolutely necessary. It allows for a filename of about 40 chars */
2587 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2588 out_of_space = True;
2589 finished = False;
2590 } else {
2591 finished = !get_lanman2_dir_entry(ctx,
2592 conn,
2593 dirptr,
2594 req->flags2,
2595 mask,dirtype,info_level,
2596 requires_resume_key,dont_descend,
2597 ask_sharemode,
2598 &p,pdata,data_end,
2599 space_remaining, &out_of_space,
2600 &got_exact_match,
2601 &last_entry_off, ea_list);
2604 if (finished && out_of_space)
2605 finished = False;
2607 if (!finished && !out_of_space)
2608 numentries++;
2611 * As an optimisation if we know we aren't looking
2612 * for a wildcard name (ie. the name matches the wildcard exactly)
2613 * then we can finish on any (first) match.
2614 * This speeds up large directory searches. JRA.
2617 if(got_exact_match)
2618 finished = True;
2620 /* Ensure space_remaining never goes -ve. */
2621 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2622 space_remaining = 0;
2623 out_of_space = true;
2624 } else {
2625 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2629 /* Check if we can close the dirptr */
2630 if(close_after_first || (finished && close_if_end)) {
2631 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2632 dptr_close(sconn, &dptr_num);
2636 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2637 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2638 * the protocol level is less than NT1. Tested with smbclient. JRA.
2639 * This should fix the OS/2 client bug #2335.
2642 if(numentries == 0) {
2643 dptr_close(sconn, &dptr_num);
2644 if (get_Protocol() < PROTOCOL_NT1) {
2645 reply_force_doserror(req, ERRDOS, ERRnofiles);
2646 goto out;
2647 } else {
2648 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2649 ERRDOS, ERRbadfile);
2650 goto out;
2654 /* At this point pdata points to numentries directory entries. */
2656 /* Set up the return parameter block */
2657 SSVAL(params,0,dptr_num);
2658 SSVAL(params,2,numentries);
2659 SSVAL(params,4,finished);
2660 SSVAL(params,6,0); /* Never an EA error */
2661 SSVAL(params,8,last_entry_off);
2663 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2664 max_data_bytes);
2666 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2667 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2668 if (!directory) {
2669 reply_nterror(req, NT_STATUS_NO_MEMORY);
2673 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2674 smb_fn_name(req->cmd),
2675 mask, directory, dirtype, numentries ) );
2678 * Force a name mangle here to ensure that the
2679 * mask as an 8.3 name is top of the mangled cache.
2680 * The reasons for this are subtle. Don't remove
2681 * this code unless you know what you are doing
2682 * (see PR#13758). JRA.
2685 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2686 char mangled_name[13];
2687 name_to_8_3(mask, mangled_name, True, conn->params);
2689 out:
2691 if (backup_priv) {
2692 unbecome_root();
2695 TALLOC_FREE(smb_dname);
2696 return;
2699 /****************************************************************************
2700 Reply to a TRANS2_FINDNEXT.
2701 ****************************************************************************/
2703 static void call_trans2findnext(connection_struct *conn,
2704 struct smb_request *req,
2705 char **pparams, int total_params,
2706 char **ppdata, int total_data,
2707 unsigned int max_data_bytes)
2709 /* We must be careful here that we don't return more than the
2710 allowed number of data bytes. If this means returning fewer than
2711 maxentries then so be it. We assume that the redirector has
2712 enough room for the fixed number of parameter bytes it has
2713 requested. */
2714 char *params = *pparams;
2715 char *pdata = *ppdata;
2716 char *data_end;
2717 int dptr_num;
2718 int maxentries;
2719 uint16 info_level;
2720 uint32 resume_key;
2721 uint16 findnext_flags;
2722 bool close_after_request;
2723 bool close_if_end;
2724 bool requires_resume_key;
2725 bool continue_bit;
2726 bool mask_contains_wcard = False;
2727 char *resume_name = NULL;
2728 const char *mask = NULL;
2729 const char *directory = NULL;
2730 char *p = NULL;
2731 uint16 dirtype;
2732 int numentries = 0;
2733 int i, last_entry_off=0;
2734 bool finished = False;
2735 bool dont_descend = False;
2736 bool out_of_space = False;
2737 int space_remaining;
2738 struct ea_list *ea_list = NULL;
2739 NTSTATUS ntstatus = NT_STATUS_OK;
2740 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2741 TALLOC_CTX *ctx = talloc_tos();
2742 struct dptr_struct *dirptr;
2743 struct smbd_server_connection *sconn = req->sconn;
2744 bool backup_priv = false;
2746 if (total_params < 13) {
2747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2748 return;
2751 dptr_num = SVAL(params,0);
2752 maxentries = SVAL(params,2);
2753 info_level = SVAL(params,4);
2754 resume_key = IVAL(params,6);
2755 findnext_flags = SVAL(params,10);
2756 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2757 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2758 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2759 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2761 if (!continue_bit) {
2762 /* We only need resume_name if continue_bit is zero. */
2763 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2764 params+12,
2765 total_params - 12, STR_TERMINATE, &ntstatus,
2766 &mask_contains_wcard);
2767 if (!NT_STATUS_IS_OK(ntstatus)) {
2768 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2769 complain (it thinks we're asking for the directory above the shared
2770 path or an invalid name). Catch this as the resume name is only compared, never used in
2771 a file access. JRA. */
2772 srvstr_pull_talloc(ctx, params, req->flags2,
2773 &resume_name, params+12,
2774 total_params - 12,
2775 STR_TERMINATE);
2777 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2778 reply_nterror(req, ntstatus);
2779 return;
2784 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2785 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2786 resume_key = %d resume name = %s continue=%d level = %d\n",
2787 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2788 requires_resume_key, resume_key,
2789 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2791 if (!maxentries) {
2792 /* W2K3 seems to treat zero as 1. */
2793 maxentries = 1;
2796 switch (info_level) {
2797 case SMB_FIND_INFO_STANDARD:
2798 case SMB_FIND_EA_SIZE:
2799 case SMB_FIND_EA_LIST:
2800 case SMB_FIND_FILE_DIRECTORY_INFO:
2801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2802 case SMB_FIND_FILE_NAMES_INFO:
2803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2804 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2806 break;
2807 case SMB_FIND_FILE_UNIX:
2808 case SMB_FIND_FILE_UNIX_INFO2:
2809 /* Always use filesystem for UNIX mtime query. */
2810 ask_sharemode = false;
2811 if (!lp_unix_extensions()) {
2812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 return;
2815 break;
2816 default:
2817 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2818 return;
2821 if (info_level == SMB_FIND_EA_LIST) {
2822 uint32 ea_size;
2824 if (total_data < 4) {
2825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2826 return;
2829 ea_size = IVAL(pdata,0);
2830 if (ea_size != total_data) {
2831 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2832 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2834 return;
2837 if (!lp_ea_support(SNUM(conn))) {
2838 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2839 return;
2842 /* Pull out the list of names. */
2843 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2844 if (!ea_list) {
2845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2846 return;
2850 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2852 return;
2855 *ppdata = (char *)SMB_REALLOC(
2856 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2857 if(*ppdata == NULL) {
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 return;
2862 pdata = *ppdata;
2863 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2865 /* Realloc the params space */
2866 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2867 if(*pparams == NULL ) {
2868 reply_nterror(req, NT_STATUS_NO_MEMORY);
2869 return;
2872 params = *pparams;
2874 /* Check that the dptr is valid */
2875 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2876 reply_nterror(req, STATUS_NO_MORE_FILES);
2877 return;
2880 directory = dptr_path(sconn, dptr_num);
2882 /* Get the wildcard mask from the dptr */
2883 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2884 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2885 reply_nterror(req, STATUS_NO_MORE_FILES);
2886 return;
2889 /* Get the attr mask from the dptr */
2890 dirtype = dptr_attr(sconn, dptr_num);
2892 backup_priv = dptr_get_priv(dirptr);
2894 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2895 "backup_priv = %d\n",
2896 dptr_num, mask, dirtype,
2897 (long)dirptr,
2898 dptr_TellDir(dirptr),
2899 (int)backup_priv));
2901 /* Initialize per TRANS2_FIND_NEXT operation data */
2902 dptr_init_search_op(dirptr);
2904 /* We don't need to check for VOL here as this is returned by
2905 a different TRANS2 call. */
2907 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2908 directory,lp_dontdescend(ctx, SNUM(conn))));
2909 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2910 dont_descend = True;
2912 p = pdata;
2913 space_remaining = max_data_bytes;
2914 out_of_space = False;
2916 if (backup_priv) {
2917 become_root();
2921 * Seek to the correct position. We no longer use the resume key but
2922 * depend on the last file name instead.
2925 if(!continue_bit && resume_name && *resume_name) {
2926 SMB_STRUCT_STAT st;
2928 long current_pos = 0;
2930 * Remember, name_to_8_3 is called by
2931 * get_lanman2_dir_entry(), so the resume name
2932 * could be mangled. Ensure we check the unmangled name.
2935 if (mangle_is_mangled(resume_name, conn->params)) {
2936 char *new_resume_name = NULL;
2937 mangle_lookup_name_from_8_3(ctx,
2938 resume_name,
2939 &new_resume_name,
2940 conn->params);
2941 if (new_resume_name) {
2942 resume_name = new_resume_name;
2947 * Fix for NT redirector problem triggered by resume key indexes
2948 * changing between directory scans. We now return a resume key of 0
2949 * and instead look for the filename to continue from (also given
2950 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2951 * findfirst/findnext (as is usual) then the directory pointer
2952 * should already be at the correct place.
2955 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2956 } /* end if resume_name && !continue_bit */
2958 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2959 bool got_exact_match = False;
2961 /* this is a heuristic to avoid seeking the dirptr except when
2962 absolutely necessary. It allows for a filename of about 40 chars */
2963 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2964 out_of_space = True;
2965 finished = False;
2966 } else {
2967 finished = !get_lanman2_dir_entry(ctx,
2968 conn,
2969 dirptr,
2970 req->flags2,
2971 mask,dirtype,info_level,
2972 requires_resume_key,dont_descend,
2973 ask_sharemode,
2974 &p,pdata,data_end,
2975 space_remaining, &out_of_space,
2976 &got_exact_match,
2977 &last_entry_off, ea_list);
2980 if (finished && out_of_space)
2981 finished = False;
2983 if (!finished && !out_of_space)
2984 numentries++;
2987 * As an optimisation if we know we aren't looking
2988 * for a wildcard name (ie. the name matches the wildcard exactly)
2989 * then we can finish on any (first) match.
2990 * This speeds up large directory searches. JRA.
2993 if(got_exact_match)
2994 finished = True;
2996 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2999 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3000 smb_fn_name(req->cmd),
3001 mask, directory, dirtype, numentries ) );
3003 /* Check if we can close the dirptr */
3004 if(close_after_request || (finished && close_if_end)) {
3005 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3006 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3009 if (backup_priv) {
3010 unbecome_root();
3013 /* Set up the return parameter block */
3014 SSVAL(params,0,numentries);
3015 SSVAL(params,2,finished);
3016 SSVAL(params,4,0); /* Never an EA error */
3017 SSVAL(params,6,last_entry_off);
3019 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3020 max_data_bytes);
3022 return;
3025 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3027 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3028 return objid;
3031 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3033 SMB_ASSERT(extended_info != NULL);
3035 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3036 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3037 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3038 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3039 #ifdef SAMBA_VERSION_REVISION
3040 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3041 #endif
3042 extended_info->samba_subversion = 0;
3043 #ifdef SAMBA_VERSION_RC_RELEASE
3044 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3045 #else
3046 #ifdef SAMBA_VERSION_PRE_RELEASE
3047 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3048 #endif
3049 #endif
3050 #ifdef SAMBA_VERSION_VENDOR_PATCH
3051 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3052 #endif
3053 extended_info->samba_gitcommitdate = 0;
3054 #ifdef SAMBA_VERSION_COMMIT_TIME
3055 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3056 #endif
3058 memset(extended_info->samba_version_string, 0,
3059 sizeof(extended_info->samba_version_string));
3061 snprintf (extended_info->samba_version_string,
3062 sizeof(extended_info->samba_version_string),
3063 "%s", samba_version_string());
3066 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3067 TALLOC_CTX *mem_ctx,
3068 uint16_t info_level,
3069 uint16_t flags2,
3070 unsigned int max_data_bytes,
3071 struct smb_filename *fname,
3072 char **ppdata,
3073 int *ret_data_len)
3075 char *pdata, *end_data;
3076 int data_len = 0, len;
3077 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3078 int snum = SNUM(conn);
3079 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3080 char *filename = NULL;
3081 uint32 additional_flags = 0;
3082 struct smb_filename smb_fname;
3083 SMB_STRUCT_STAT st;
3084 NTSTATUS status = NT_STATUS_OK;
3086 if (fname == NULL || fname->base_name == NULL) {
3087 filename = ".";
3088 } else {
3089 filename = fname->base_name;
3092 if (IS_IPC(conn)) {
3093 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3094 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3095 "info level (0x%x) on IPC$.\n",
3096 (unsigned int)info_level));
3097 return NT_STATUS_ACCESS_DENIED;
3101 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3103 ZERO_STRUCT(smb_fname);
3104 smb_fname.base_name = discard_const_p(char, filename);
3106 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3107 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3108 return map_nt_error_from_unix(errno);
3111 st = smb_fname.st;
3113 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3114 return NT_STATUS_INVALID_PARAMETER;
3117 *ppdata = (char *)SMB_REALLOC(
3118 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3119 if (*ppdata == NULL) {
3120 return NT_STATUS_NO_MEMORY;
3123 pdata = *ppdata;
3124 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3125 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3127 switch (info_level) {
3128 case SMB_INFO_ALLOCATION:
3130 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3131 data_len = 18;
3132 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3133 return map_nt_error_from_unix(errno);
3136 block_size = lp_block_size(snum);
3137 if (bsize < block_size) {
3138 uint64_t factor = block_size/bsize;
3139 bsize = block_size;
3140 dsize /= factor;
3141 dfree /= factor;
3143 if (bsize > block_size) {
3144 uint64_t factor = bsize/block_size;
3145 bsize = block_size;
3146 dsize *= factor;
3147 dfree *= factor;
3149 bytes_per_sector = 512;
3150 sectors_per_unit = bsize/bytes_per_sector;
3152 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3153 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3154 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3156 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3157 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3158 SIVAL(pdata,l1_cUnit,dsize);
3159 SIVAL(pdata,l1_cUnitAvail,dfree);
3160 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3161 break;
3164 case SMB_INFO_VOLUME:
3165 /* Return volume name */
3167 * Add volume serial number - hash of a combination of
3168 * the called hostname and the service name.
3170 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3172 * Win2k3 and previous mess this up by sending a name length
3173 * one byte short. I believe only older clients (OS/2 Win9x) use
3174 * this call so try fixing this by adding a terminating null to
3175 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3177 len = srvstr_push(
3178 pdata, flags2,
3179 pdata+l2_vol_szVolLabel, vname,
3180 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3181 STR_NOALIGN|STR_TERMINATE);
3182 SCVAL(pdata,l2_vol_cch,len);
3183 data_len = l2_vol_szVolLabel + len;
3184 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3185 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3186 len, vname));
3187 break;
3189 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3190 case SMB_FS_ATTRIBUTE_INFORMATION:
3192 additional_flags = 0;
3193 #if defined(HAVE_SYS_QUOTAS)
3194 additional_flags |= FILE_VOLUME_QUOTAS;
3195 #endif
3197 if(lp_nt_acl_support(SNUM(conn))) {
3198 additional_flags |= FILE_PERSISTENT_ACLS;
3201 /* Capabilities are filled in at connection time through STATVFS call */
3202 additional_flags |= conn->fs_capabilities;
3203 additional_flags |= lp_parm_int(conn->params->service,
3204 "share", "fake_fscaps",
3207 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3208 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3209 additional_flags); /* FS ATTRIBUTES */
3211 SIVAL(pdata,4,255); /* Max filename component length */
3212 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3213 and will think we can't do long filenames */
3214 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3215 PTR_DIFF(end_data, pdata+12),
3216 STR_UNICODE);
3217 SIVAL(pdata,8,len);
3218 data_len = 12 + len;
3219 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3220 /* the client only requested a portion of the
3221 file system name */
3222 data_len = max_data_bytes;
3223 status = STATUS_BUFFER_OVERFLOW;
3225 break;
3227 case SMB_QUERY_FS_LABEL_INFO:
3228 case SMB_FS_LABEL_INFORMATION:
3229 len = srvstr_push(pdata, flags2, pdata+4, vname,
3230 PTR_DIFF(end_data, pdata+4), 0);
3231 data_len = 4 + len;
3232 SIVAL(pdata,0,len);
3233 break;
3235 case SMB_QUERY_FS_VOLUME_INFO:
3236 case SMB_FS_VOLUME_INFORMATION:
3239 * Add volume serial number - hash of a combination of
3240 * the called hostname and the service name.
3242 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3243 (str_checksum(get_local_machine_name())<<16));
3245 /* Max label len is 32 characters. */
3246 len = srvstr_push(pdata, flags2, pdata+18, vname,
3247 PTR_DIFF(end_data, pdata+18),
3248 STR_UNICODE);
3249 SIVAL(pdata,12,len);
3250 data_len = 18+len;
3252 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3253 (int)strlen(vname),vname,
3254 lp_servicename(talloc_tos(), snum)));
3255 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3256 /* the client only requested a portion of the
3257 volume label */
3258 data_len = max_data_bytes;
3259 status = STATUS_BUFFER_OVERFLOW;
3261 break;
3263 case SMB_QUERY_FS_SIZE_INFO:
3264 case SMB_FS_SIZE_INFORMATION:
3266 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3267 data_len = 24;
3268 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3269 return map_nt_error_from_unix(errno);
3271 block_size = lp_block_size(snum);
3272 if (bsize < block_size) {
3273 uint64_t factor = block_size/bsize;
3274 bsize = block_size;
3275 dsize /= factor;
3276 dfree /= factor;
3278 if (bsize > block_size) {
3279 uint64_t factor = bsize/block_size;
3280 bsize = block_size;
3281 dsize *= factor;
3282 dfree *= factor;
3284 bytes_per_sector = 512;
3285 sectors_per_unit = bsize/bytes_per_sector;
3286 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3287 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3288 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3289 SBIG_UINT(pdata,0,dsize);
3290 SBIG_UINT(pdata,8,dfree);
3291 SIVAL(pdata,16,sectors_per_unit);
3292 SIVAL(pdata,20,bytes_per_sector);
3293 break;
3296 case SMB_FS_FULL_SIZE_INFORMATION:
3298 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3299 data_len = 32;
3300 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3301 return map_nt_error_from_unix(errno);
3303 block_size = lp_block_size(snum);
3304 if (bsize < block_size) {
3305 uint64_t factor = block_size/bsize;
3306 bsize = block_size;
3307 dsize /= factor;
3308 dfree /= factor;
3310 if (bsize > block_size) {
3311 uint64_t factor = bsize/block_size;
3312 bsize = block_size;
3313 dsize *= factor;
3314 dfree *= factor;
3316 bytes_per_sector = 512;
3317 sectors_per_unit = bsize/bytes_per_sector;
3318 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3319 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3320 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3321 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3322 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3323 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3324 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3325 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3326 break;
3329 case SMB_QUERY_FS_DEVICE_INFO:
3330 case SMB_FS_DEVICE_INFORMATION:
3332 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3334 if (!CAN_WRITE(conn)) {
3335 characteristics |= FILE_READ_ONLY_DEVICE;
3337 data_len = 8;
3338 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3339 SIVAL(pdata,4,characteristics);
3340 break;
3343 #ifdef HAVE_SYS_QUOTAS
3344 case SMB_FS_QUOTA_INFORMATION:
3346 * what we have to send --metze:
3348 * Unknown1: 24 NULL bytes
3349 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3350 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3351 * Quota Flags: 2 byte :
3352 * Unknown3: 6 NULL bytes
3354 * 48 bytes total
3356 * details for Quota Flags:
3358 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3359 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3360 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3361 * 0x0001 Enable Quotas: enable quota for this fs
3365 /* we need to fake up a fsp here,
3366 * because its not send in this call
3368 files_struct fsp;
3369 SMB_NTQUOTA_STRUCT quotas;
3371 ZERO_STRUCT(fsp);
3372 ZERO_STRUCT(quotas);
3374 fsp.conn = conn;
3375 fsp.fnum = FNUM_FIELD_INVALID;
3377 /* access check */
3378 if (get_current_uid(conn) != 0) {
3379 DEBUG(0,("get_user_quota: access_denied "
3380 "service [%s] user [%s]\n",
3381 lp_servicename(talloc_tos(), SNUM(conn)),
3382 conn->session_info->unix_info->unix_name));
3383 return NT_STATUS_ACCESS_DENIED;
3386 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3387 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3388 return map_nt_error_from_unix(errno);
3391 data_len = 48;
3393 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3394 lp_servicename(talloc_tos(), SNUM(conn))));
3396 /* Unknown1 24 NULL bytes*/
3397 SBIG_UINT(pdata,0,(uint64_t)0);
3398 SBIG_UINT(pdata,8,(uint64_t)0);
3399 SBIG_UINT(pdata,16,(uint64_t)0);
3401 /* Default Soft Quota 8 bytes */
3402 SBIG_UINT(pdata,24,quotas.softlim);
3404 /* Default Hard Quota 8 bytes */
3405 SBIG_UINT(pdata,32,quotas.hardlim);
3407 /* Quota flag 2 bytes */
3408 SSVAL(pdata,40,quotas.qflags);
3410 /* Unknown3 6 NULL bytes */
3411 SSVAL(pdata,42,0);
3412 SIVAL(pdata,44,0);
3414 break;
3416 #endif /* HAVE_SYS_QUOTAS */
3417 case SMB_FS_OBJECTID_INFORMATION:
3419 unsigned char objid[16];
3420 struct smb_extended_info extended_info;
3421 memcpy(pdata,create_volume_objectid(conn, objid),16);
3422 samba_extended_info_version (&extended_info);
3423 SIVAL(pdata,16,extended_info.samba_magic);
3424 SIVAL(pdata,20,extended_info.samba_version);
3425 SIVAL(pdata,24,extended_info.samba_subversion);
3426 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3427 memcpy(pdata+36,extended_info.samba_version_string,28);
3428 data_len = 64;
3429 break;
3433 * Query the version and capabilities of the CIFS UNIX extensions
3434 * in use.
3437 case SMB_QUERY_CIFS_UNIX_INFO:
3439 bool large_write = lp_min_receive_file_size() &&
3440 !srv_is_signing_active(conn->sconn);
3441 bool large_read = !srv_is_signing_active(conn->sconn);
3442 int encrypt_caps = 0;
3444 if (!lp_unix_extensions()) {
3445 return NT_STATUS_INVALID_LEVEL;
3448 switch (conn->encrypt_level) {
3449 case SMB_SIGNING_OFF:
3450 encrypt_caps = 0;
3451 break;
3452 case SMB_SIGNING_IF_REQUIRED:
3453 case SMB_SIGNING_DEFAULT:
3454 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3455 break;
3456 case SMB_SIGNING_REQUIRED:
3457 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3458 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3459 large_write = false;
3460 large_read = false;
3461 break;
3464 data_len = 12;
3465 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3466 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3468 /* We have POSIX ACLs, pathname, encryption,
3469 * large read/write, and locking capability. */
3471 SBIG_UINT(pdata,4,((uint64_t)(
3472 CIFS_UNIX_POSIX_ACLS_CAP|
3473 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3474 CIFS_UNIX_FCNTL_LOCKS_CAP|
3475 CIFS_UNIX_EXTATTR_CAP|
3476 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3477 encrypt_caps|
3478 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3479 (large_write ?
3480 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3481 break;
3484 case SMB_QUERY_POSIX_FS_INFO:
3486 int rc;
3487 vfs_statvfs_struct svfs;
3489 if (!lp_unix_extensions()) {
3490 return NT_STATUS_INVALID_LEVEL;
3493 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3495 if (!rc) {
3496 data_len = 56;
3497 SIVAL(pdata,0,svfs.OptimalTransferSize);
3498 SIVAL(pdata,4,svfs.BlockSize);
3499 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3500 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3501 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3502 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3503 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3504 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3505 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3506 #ifdef EOPNOTSUPP
3507 } else if (rc == EOPNOTSUPP) {
3508 return NT_STATUS_INVALID_LEVEL;
3509 #endif /* EOPNOTSUPP */
3510 } else {
3511 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3512 return NT_STATUS_DOS(ERRSRV, ERRerror);
3514 break;
3517 case SMB_QUERY_POSIX_WHOAMI:
3519 uint32_t flags = 0;
3520 uint32_t sid_bytes;
3521 int i;
3523 if (!lp_unix_extensions()) {
3524 return NT_STATUS_INVALID_LEVEL;
3527 if (max_data_bytes < 40) {
3528 return NT_STATUS_BUFFER_TOO_SMALL;
3531 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3532 flags |= SMB_WHOAMI_GUEST;
3535 /* NOTE: 8 bytes for UID/GID, irrespective of native
3536 * platform size. This matches
3537 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3539 data_len = 4 /* flags */
3540 + 4 /* flag mask */
3541 + 8 /* uid */
3542 + 8 /* gid */
3543 + 4 /* ngroups */
3544 + 4 /* num_sids */
3545 + 4 /* SID bytes */
3546 + 4 /* pad/reserved */
3547 + (conn->session_info->unix_token->ngroups * 8)
3548 /* groups list */
3549 + (conn->session_info->security_token->num_sids *
3550 SID_MAX_SIZE)
3551 /* SID list */;
3553 SIVAL(pdata, 0, flags);
3554 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3555 SBIG_UINT(pdata, 8,
3556 (uint64_t)conn->session_info->unix_token->uid);
3557 SBIG_UINT(pdata, 16,
3558 (uint64_t)conn->session_info->unix_token->gid);
3561 if (data_len >= max_data_bytes) {
3562 /* Potential overflow, skip the GIDs and SIDs. */
3564 SIVAL(pdata, 24, 0); /* num_groups */
3565 SIVAL(pdata, 28, 0); /* num_sids */
3566 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3567 SIVAL(pdata, 36, 0); /* reserved */
3569 data_len = 40;
3570 break;
3573 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3574 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3576 /* We walk the SID list twice, but this call is fairly
3577 * infrequent, and I don't expect that it's performance
3578 * sensitive -- jpeach
3580 for (i = 0, sid_bytes = 0;
3581 i < conn->session_info->security_token->num_sids; ++i) {
3582 sid_bytes += ndr_size_dom_sid(
3583 &conn->session_info->security_token->sids[i],
3587 /* SID list byte count */
3588 SIVAL(pdata, 32, sid_bytes);
3590 /* 4 bytes pad/reserved - must be zero */
3591 SIVAL(pdata, 36, 0);
3592 data_len = 40;
3594 /* GID list */
3595 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3596 SBIG_UINT(pdata, data_len,
3597 (uint64_t)conn->session_info->unix_token->groups[i]);
3598 data_len += 8;
3601 /* SID list */
3602 for (i = 0;
3603 i < conn->session_info->security_token->num_sids; ++i) {
3604 int sid_len = ndr_size_dom_sid(
3605 &conn->session_info->security_token->sids[i],
3608 sid_linearize(pdata + data_len, sid_len,
3609 &conn->session_info->security_token->sids[i]);
3610 data_len += sid_len;
3613 break;
3616 case SMB_MAC_QUERY_FS_INFO:
3618 * Thursby MAC extension... ONLY on NTFS filesystems
3619 * once we do streams then we don't need this
3621 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3622 data_len = 88;
3623 SIVAL(pdata,84,0x100); /* Don't support mac... */
3624 break;
3626 /* drop through */
3627 default:
3628 return NT_STATUS_INVALID_LEVEL;
3631 *ret_data_len = data_len;
3632 return status;
3635 /****************************************************************************
3636 Reply to a TRANS2_QFSINFO (query filesystem info).
3637 ****************************************************************************/
3639 static void call_trans2qfsinfo(connection_struct *conn,
3640 struct smb_request *req,
3641 char **pparams, int total_params,
3642 char **ppdata, int total_data,
3643 unsigned int max_data_bytes)
3645 char *params = *pparams;
3646 uint16_t info_level;
3647 int data_len = 0;
3648 NTSTATUS status;
3650 if (total_params < 2) {
3651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3652 return;
3655 info_level = SVAL(params,0);
3657 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3658 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3659 DEBUG(0,("call_trans2qfsinfo: encryption required "
3660 "and info level 0x%x sent.\n",
3661 (unsigned int)info_level));
3662 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3663 return;
3667 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3669 status = smbd_do_qfsinfo(conn, req,
3670 info_level,
3671 req->flags2,
3672 max_data_bytes,
3673 NULL,
3674 ppdata, &data_len);
3675 if (!NT_STATUS_IS_OK(status)) {
3676 reply_nterror(req, status);
3677 return;
3680 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3681 max_data_bytes);
3683 DEBUG( 4, ( "%s info_level = %d\n",
3684 smb_fn_name(req->cmd), info_level) );
3686 return;
3689 /****************************************************************************
3690 Reply to a TRANS2_SETFSINFO (set filesystem info).
3691 ****************************************************************************/
3693 static void call_trans2setfsinfo(connection_struct *conn,
3694 struct smb_request *req,
3695 char **pparams, int total_params,
3696 char **ppdata, int total_data,
3697 unsigned int max_data_bytes)
3699 struct smbd_server_connection *sconn = req->sconn;
3700 char *pdata = *ppdata;
3701 char *params = *pparams;
3702 uint16 info_level;
3704 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3705 lp_servicename(talloc_tos(), SNUM(conn))));
3707 /* */
3708 if (total_params < 4) {
3709 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3710 total_params));
3711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3712 return;
3715 info_level = SVAL(params,2);
3717 if (IS_IPC(conn)) {
3718 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3719 info_level != SMB_SET_CIFS_UNIX_INFO) {
3720 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3721 "info level (0x%x) on IPC$.\n",
3722 (unsigned int)info_level));
3723 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3724 return;
3728 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3729 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3730 DEBUG(0,("call_trans2setfsinfo: encryption required "
3731 "and info level 0x%x sent.\n",
3732 (unsigned int)info_level));
3733 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3734 return;
3738 switch(info_level) {
3739 case SMB_SET_CIFS_UNIX_INFO:
3740 if (!lp_unix_extensions()) {
3741 DEBUG(2,("call_trans2setfsinfo: "
3742 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3743 "unix extensions off\n"));
3744 reply_nterror(req,
3745 NT_STATUS_INVALID_LEVEL);
3746 return;
3749 /* There should be 12 bytes of capabilities set. */
3750 if (total_data < 12) {
3751 reply_nterror(
3752 req,
3753 NT_STATUS_INVALID_PARAMETER);
3754 return;
3756 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3757 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3758 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3759 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3760 /* Just print these values for now. */
3761 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3762 "major = %u, minor = %u cap_low = 0x%x, "
3763 "cap_high = 0x%xn",
3764 (unsigned int)sconn->
3765 smb1.unix_info.client_major,
3766 (unsigned int)sconn->
3767 smb1.unix_info.client_minor,
3768 (unsigned int)sconn->
3769 smb1.unix_info.client_cap_low,
3770 (unsigned int)sconn->
3771 smb1.unix_info.client_cap_high));
3773 /* Here is where we must switch to posix pathname processing... */
3774 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3775 lp_set_posix_pathnames();
3776 mangle_change_to_posix();
3779 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3780 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3781 /* Client that knows how to do posix locks,
3782 * but not posix open/mkdir operations. Set a
3783 * default type for read/write checks. */
3785 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3788 break;
3790 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3792 NTSTATUS status;
3793 size_t param_len = 0;
3794 size_t data_len = total_data;
3796 if (!lp_unix_extensions()) {
3797 reply_nterror(
3798 req,
3799 NT_STATUS_INVALID_LEVEL);
3800 return;
3803 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3804 reply_nterror(
3805 req,
3806 NT_STATUS_NOT_SUPPORTED);
3807 return;
3810 if (req->sconn->smb1.echo_handler.trusted_fde) {
3811 DEBUG( 2,("call_trans2setfsinfo: "
3812 "request transport encryption disabled"
3813 "with 'fork echo handler = yes'\n"));
3814 reply_nterror(
3815 req,
3816 NT_STATUS_NOT_SUPPORTED);
3817 return;
3820 DEBUG( 4,("call_trans2setfsinfo: "
3821 "request transport encryption.\n"));
3823 status = srv_request_encryption_setup(conn,
3824 (unsigned char **)ppdata,
3825 &data_len,
3826 (unsigned char **)pparams,
3827 &param_len);
3829 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3830 !NT_STATUS_IS_OK(status)) {
3831 reply_nterror(req, status);
3832 return;
3835 send_trans2_replies(conn, req,
3836 NT_STATUS_OK,
3837 *pparams,
3838 param_len,
3839 *ppdata,
3840 data_len,
3841 max_data_bytes);
3843 if (NT_STATUS_IS_OK(status)) {
3844 /* Server-side transport
3845 * encryption is now *on*. */
3846 status = srv_encryption_start(conn);
3847 if (!NT_STATUS_IS_OK(status)) {
3848 char *reason = talloc_asprintf(talloc_tos(),
3849 "Failure in setting "
3850 "up encrypted transport: %s",
3851 nt_errstr(status));
3852 exit_server_cleanly(reason);
3855 return;
3858 case SMB_FS_QUOTA_INFORMATION:
3860 files_struct *fsp = NULL;
3861 SMB_NTQUOTA_STRUCT quotas;
3863 ZERO_STRUCT(quotas);
3865 /* access check */
3866 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3867 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3868 lp_servicename(talloc_tos(), SNUM(conn)),
3869 conn->session_info->unix_info->unix_name));
3870 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3871 return;
3874 /* note: normaly there're 48 bytes,
3875 * but we didn't use the last 6 bytes for now
3876 * --metze
3878 fsp = file_fsp(req, SVAL(params,0));
3880 if (!check_fsp_ntquota_handle(conn, req,
3881 fsp)) {
3882 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3883 reply_nterror(
3884 req, NT_STATUS_INVALID_HANDLE);
3885 return;
3888 if (total_data < 42) {
3889 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3890 total_data));
3891 reply_nterror(
3892 req,
3893 NT_STATUS_INVALID_PARAMETER);
3894 return;
3897 /* unknown_1 24 NULL bytes in pdata*/
3899 /* the soft quotas 8 bytes (uint64_t)*/
3900 quotas.softlim = BVAL(pdata,24);
3902 /* the hard quotas 8 bytes (uint64_t)*/
3903 quotas.hardlim = BVAL(pdata,32);
3905 /* quota_flags 2 bytes **/
3906 quotas.qflags = SVAL(pdata,40);
3908 /* unknown_2 6 NULL bytes follow*/
3910 /* now set the quotas */
3911 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3912 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3913 reply_nterror(req, map_nt_error_from_unix(errno));
3914 return;
3917 break;
3919 default:
3920 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3921 info_level));
3922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3923 return;
3924 break;
3928 * sending this reply works fine,
3929 * but I'm not sure it's the same
3930 * like windows do...
3931 * --metze
3933 reply_outbuf(req, 10, 0);
3936 #if defined(HAVE_POSIX_ACLS)
3937 /****************************************************************************
3938 Utility function to count the number of entries in a POSIX acl.
3939 ****************************************************************************/
3941 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3943 unsigned int ace_count = 0;
3944 int entry_id = SMB_ACL_FIRST_ENTRY;
3945 SMB_ACL_ENTRY_T entry;
3947 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3948 /* get_next... */
3949 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3950 entry_id = SMB_ACL_NEXT_ENTRY;
3952 ace_count++;
3954 return ace_count;
3957 /****************************************************************************
3958 Utility function to marshall a POSIX acl into wire format.
3959 ****************************************************************************/
3961 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3963 int entry_id = SMB_ACL_FIRST_ENTRY;
3964 SMB_ACL_ENTRY_T entry;
3966 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3967 SMB_ACL_TAG_T tagtype;
3968 SMB_ACL_PERMSET_T permset;
3969 unsigned char perms = 0;
3970 unsigned int own_grp;
3972 /* get_next... */
3973 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3974 entry_id = SMB_ACL_NEXT_ENTRY;
3977 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3978 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3979 return False;
3982 if (sys_acl_get_permset(entry, &permset) == -1) {
3983 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3984 return False;
3987 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3988 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3989 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3991 SCVAL(pdata,1,perms);
3993 switch (tagtype) {
3994 case SMB_ACL_USER_OBJ:
3995 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3996 own_grp = (unsigned int)pst->st_ex_uid;
3997 SIVAL(pdata,2,own_grp);
3998 SIVAL(pdata,6,0);
3999 break;
4000 case SMB_ACL_USER:
4002 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4003 if (!puid) {
4004 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4005 return False;
4007 own_grp = (unsigned int)*puid;
4008 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4009 SIVAL(pdata,2,own_grp);
4010 SIVAL(pdata,6,0);
4011 break;
4013 case SMB_ACL_GROUP_OBJ:
4014 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4015 own_grp = (unsigned int)pst->st_ex_gid;
4016 SIVAL(pdata,2,own_grp);
4017 SIVAL(pdata,6,0);
4018 break;
4019 case SMB_ACL_GROUP:
4021 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4022 if (!pgid) {
4023 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4024 return False;
4026 own_grp = (unsigned int)*pgid;
4027 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4028 SIVAL(pdata,2,own_grp);
4029 SIVAL(pdata,6,0);
4030 break;
4032 case SMB_ACL_MASK:
4033 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4034 SIVAL(pdata,2,0xFFFFFFFF);
4035 SIVAL(pdata,6,0xFFFFFFFF);
4036 break;
4037 case SMB_ACL_OTHER:
4038 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4039 SIVAL(pdata,2,0xFFFFFFFF);
4040 SIVAL(pdata,6,0xFFFFFFFF);
4041 break;
4042 default:
4043 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4044 return False;
4046 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4049 return True;
4051 #endif
4053 /****************************************************************************
4054 Store the FILE_UNIX_BASIC info.
4055 ****************************************************************************/
4057 static char *store_file_unix_basic(connection_struct *conn,
4058 char *pdata,
4059 files_struct *fsp,
4060 const SMB_STRUCT_STAT *psbuf)
4062 uint64_t file_index = get_FileIndex(conn, psbuf);
4063 dev_t devno;
4065 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4066 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4068 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4069 pdata += 8;
4071 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4072 pdata += 8;
4074 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4075 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4076 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4077 pdata += 24;
4079 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4080 SIVAL(pdata,4,0);
4081 pdata += 8;
4083 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4084 SIVAL(pdata,4,0);
4085 pdata += 8;
4087 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4088 pdata += 4;
4090 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4091 devno = psbuf->st_ex_rdev;
4092 } else {
4093 devno = psbuf->st_ex_dev;
4096 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4097 SIVAL(pdata,4,0);
4098 pdata += 8;
4100 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4101 SIVAL(pdata,4,0);
4102 pdata += 8;
4104 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4105 pdata += 8;
4107 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4108 SIVAL(pdata,4,0);
4109 pdata += 8;
4111 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4112 SIVAL(pdata,4,0);
4113 pdata += 8;
4115 return pdata;
4118 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4119 * the chflags(2) (or equivalent) flags.
4121 * XXX: this really should be behind the VFS interface. To do this, we would
4122 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4123 * Each VFS module could then implement its own mapping as appropriate for the
4124 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4126 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4127 info2_flags_map[] =
4129 #ifdef UF_NODUMP
4130 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4131 #endif
4133 #ifdef UF_IMMUTABLE
4134 { UF_IMMUTABLE, EXT_IMMUTABLE },
4135 #endif
4137 #ifdef UF_APPEND
4138 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4139 #endif
4141 #ifdef UF_HIDDEN
4142 { UF_HIDDEN, EXT_HIDDEN },
4143 #endif
4145 /* Do not remove. We need to guarantee that this array has at least one
4146 * entry to build on HP-UX.
4148 { 0, 0 }
4152 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4153 uint32 *smb_fflags, uint32 *smb_fmask)
4155 int i;
4157 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4158 *smb_fmask |= info2_flags_map[i].smb_fflag;
4159 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4160 *smb_fflags |= info2_flags_map[i].smb_fflag;
4165 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4166 const uint32 smb_fflags,
4167 const uint32 smb_fmask,
4168 int *stat_fflags)
4170 uint32 max_fmask = 0;
4171 int i;
4173 *stat_fflags = psbuf->st_ex_flags;
4175 /* For each flags requested in smb_fmask, check the state of the
4176 * corresponding flag in smb_fflags and set or clear the matching
4177 * stat flag.
4180 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4181 max_fmask |= info2_flags_map[i].smb_fflag;
4182 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4183 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4184 *stat_fflags |= info2_flags_map[i].stat_fflag;
4185 } else {
4186 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4191 /* If smb_fmask is asking to set any bits that are not supported by
4192 * our flag mappings, we should fail.
4194 if ((smb_fmask & max_fmask) != smb_fmask) {
4195 return False;
4198 return True;
4202 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4203 * of file flags and birth (create) time.
4205 static char *store_file_unix_basic_info2(connection_struct *conn,
4206 char *pdata,
4207 files_struct *fsp,
4208 const SMB_STRUCT_STAT *psbuf)
4210 uint32 file_flags = 0;
4211 uint32 flags_mask = 0;
4213 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4215 /* Create (birth) time 64 bit */
4216 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4217 pdata += 8;
4219 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4220 SIVAL(pdata, 0, file_flags); /* flags */
4221 SIVAL(pdata, 4, flags_mask); /* mask */
4222 pdata += 8;
4224 return pdata;
4227 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4228 const struct stream_struct *streams,
4229 char *data,
4230 unsigned int max_data_bytes,
4231 unsigned int *data_size)
4233 unsigned int i;
4234 unsigned int ofs = 0;
4236 for (i = 0; i < num_streams; i++) {
4237 unsigned int next_offset;
4238 size_t namelen;
4239 smb_ucs2_t *namebuf;
4241 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4242 streams[i].name, &namelen) ||
4243 namelen <= 2)
4245 return NT_STATUS_INVALID_PARAMETER;
4249 * name_buf is now null-terminated, we need to marshall as not
4250 * terminated
4253 namelen -= 2;
4256 * We cannot overflow ...
4258 if ((ofs + 24 + namelen) > max_data_bytes) {
4259 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4260 i));
4261 TALLOC_FREE(namebuf);
4262 return STATUS_BUFFER_OVERFLOW;
4265 SIVAL(data, ofs+4, namelen);
4266 SOFF_T(data, ofs+8, streams[i].size);
4267 SOFF_T(data, ofs+16, streams[i].alloc_size);
4268 memcpy(data+ofs+24, namebuf, namelen);
4269 TALLOC_FREE(namebuf);
4271 next_offset = ofs + 24 + namelen;
4273 if (i == num_streams-1) {
4274 SIVAL(data, ofs, 0);
4276 else {
4277 unsigned int align = ndr_align_size(next_offset, 8);
4279 if ((next_offset + align) > max_data_bytes) {
4280 DEBUG(10, ("refusing to overflow align "
4281 "reply at stream %u\n",
4282 i));
4283 TALLOC_FREE(namebuf);
4284 return STATUS_BUFFER_OVERFLOW;
4287 memset(data+next_offset, 0, align);
4288 next_offset += align;
4290 SIVAL(data, ofs, next_offset - ofs);
4291 ofs = next_offset;
4294 ofs = next_offset;
4297 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4299 *data_size = ofs;
4301 return NT_STATUS_OK;
4304 /****************************************************************************
4305 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4306 ****************************************************************************/
4308 static void call_trans2qpipeinfo(connection_struct *conn,
4309 struct smb_request *req,
4310 unsigned int tran_call,
4311 char **pparams, int total_params,
4312 char **ppdata, int total_data,
4313 unsigned int max_data_bytes)
4315 char *params = *pparams;
4316 char *pdata = *ppdata;
4317 unsigned int data_size = 0;
4318 unsigned int param_size = 2;
4319 uint16 info_level;
4320 files_struct *fsp;
4322 if (!params) {
4323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4324 return;
4327 if (total_params < 4) {
4328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4329 return;
4332 fsp = file_fsp(req, SVAL(params,0));
4333 if (!fsp_is_np(fsp)) {
4334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4335 return;
4338 info_level = SVAL(params,2);
4340 *pparams = (char *)SMB_REALLOC(*pparams,2);
4341 if (*pparams == NULL) {
4342 reply_nterror(req, NT_STATUS_NO_MEMORY);
4343 return;
4345 params = *pparams;
4346 SSVAL(params,0,0);
4347 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4349 return;
4351 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4352 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4353 if (*ppdata == NULL ) {
4354 reply_nterror(req, NT_STATUS_NO_MEMORY);
4355 return;
4357 pdata = *ppdata;
4359 switch (info_level) {
4360 case SMB_FILE_STANDARD_INFORMATION:
4361 memset(pdata,0,24);
4362 SOFF_T(pdata,0,4096LL);
4363 SIVAL(pdata,16,1);
4364 SIVAL(pdata,20,1);
4365 data_size = 24;
4366 break;
4368 default:
4369 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4370 return;
4373 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4374 max_data_bytes);
4376 return;
4379 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4380 TALLOC_CTX *mem_ctx,
4381 uint16_t info_level,
4382 files_struct *fsp,
4383 struct smb_filename *smb_fname,
4384 bool delete_pending,
4385 struct timespec write_time_ts,
4386 struct ea_list *ea_list,
4387 int lock_data_count,
4388 char *lock_data,
4389 uint16_t flags2,
4390 unsigned int max_data_bytes,
4391 char **ppdata,
4392 unsigned int *pdata_size)
4394 char *pdata = *ppdata;
4395 char *dstart, *dend;
4396 unsigned int data_size;
4397 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4398 time_t create_time, mtime, atime, c_time;
4399 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4400 char *p;
4401 char *base_name;
4402 char *dos_fname;
4403 int mode;
4404 int nlink;
4405 NTSTATUS status;
4406 uint64_t file_size = 0;
4407 uint64_t pos = 0;
4408 uint64_t allocation_size = 0;
4409 uint64_t file_index = 0;
4410 uint32_t access_mask = 0;
4412 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4413 return NT_STATUS_INVALID_LEVEL;
4416 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4417 smb_fname_str_dbg(smb_fname),
4418 fsp_fnum_dbg(fsp),
4419 info_level, max_data_bytes));
4421 mode = dos_mode(conn, smb_fname);
4422 nlink = psbuf->st_ex_nlink;
4424 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4425 nlink = 1;
4428 if ((nlink > 0) && delete_pending) {
4429 nlink -= 1;
4432 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4433 return NT_STATUS_INVALID_PARAMETER;
4436 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4437 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4438 if (*ppdata == NULL) {
4439 return NT_STATUS_NO_MEMORY;
4441 pdata = *ppdata;
4442 dstart = pdata;
4443 dend = dstart + data_size - 1;
4445 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4446 update_stat_ex_mtime(psbuf, write_time_ts);
4449 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4450 mtime_ts = psbuf->st_ex_mtime;
4451 atime_ts = psbuf->st_ex_atime;
4452 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4454 if (lp_dos_filetime_resolution(SNUM(conn))) {
4455 dos_filetime_timespec(&create_time_ts);
4456 dos_filetime_timespec(&mtime_ts);
4457 dos_filetime_timespec(&atime_ts);
4458 dos_filetime_timespec(&ctime_ts);
4461 create_time = convert_timespec_to_time_t(create_time_ts);
4462 mtime = convert_timespec_to_time_t(mtime_ts);
4463 atime = convert_timespec_to_time_t(atime_ts);
4464 c_time = convert_timespec_to_time_t(ctime_ts);
4466 p = strrchr_m(smb_fname->base_name,'/');
4467 if (!p)
4468 base_name = smb_fname->base_name;
4469 else
4470 base_name = p+1;
4472 /* NT expects the name to be in an exact form of the *full*
4473 filename. See the trans2 torture test */
4474 if (ISDOT(base_name)) {
4475 dos_fname = talloc_strdup(mem_ctx, "\\");
4476 if (!dos_fname) {
4477 return NT_STATUS_NO_MEMORY;
4479 } else {
4480 dos_fname = talloc_asprintf(mem_ctx,
4481 "\\%s",
4482 smb_fname->base_name);
4483 if (!dos_fname) {
4484 return NT_STATUS_NO_MEMORY;
4486 if (is_ntfs_stream_smb_fname(smb_fname)) {
4487 dos_fname = talloc_asprintf(dos_fname, "%s",
4488 smb_fname->stream_name);
4489 if (!dos_fname) {
4490 return NT_STATUS_NO_MEMORY;
4494 string_replace(dos_fname, '/', '\\');
4497 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4499 if (!fsp) {
4500 /* Do we have this path open ? */
4501 files_struct *fsp1;
4502 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4503 fsp1 = file_find_di_first(conn->sconn, fileid);
4504 if (fsp1 && fsp1->initial_allocation_size) {
4505 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4509 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4510 file_size = get_file_size_stat(psbuf);
4513 if (fsp) {
4514 pos = fsp->fh->position_information;
4517 if (fsp) {
4518 access_mask = fsp->access_mask;
4519 } else {
4520 /* GENERIC_EXECUTE mapping from Windows */
4521 access_mask = 0x12019F;
4524 /* This should be an index number - looks like
4525 dev/ino to me :-)
4527 I think this causes us to fail the IFSKIT
4528 BasicFileInformationTest. -tpot */
4529 file_index = get_FileIndex(conn, psbuf);
4531 switch (info_level) {
4532 case SMB_INFO_STANDARD:
4533 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4534 data_size = 22;
4535 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4536 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4537 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4538 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4539 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4540 SSVAL(pdata,l1_attrFile,mode);
4541 break;
4543 case SMB_INFO_QUERY_EA_SIZE:
4545 unsigned int ea_size =
4546 estimate_ea_size(conn, fsp,
4547 smb_fname);
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4549 data_size = 26;
4550 srv_put_dos_date2(pdata,0,create_time);
4551 srv_put_dos_date2(pdata,4,atime);
4552 srv_put_dos_date2(pdata,8,mtime); /* write time */
4553 SIVAL(pdata,12,(uint32)file_size);
4554 SIVAL(pdata,16,(uint32)allocation_size);
4555 SSVAL(pdata,20,mode);
4556 SIVAL(pdata,22,ea_size);
4557 break;
4560 case SMB_INFO_IS_NAME_VALID:
4561 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4562 if (fsp) {
4563 /* os/2 needs this ? really ?*/
4564 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4566 /* This is only reached for qpathinfo */
4567 data_size = 0;
4568 break;
4570 case SMB_INFO_QUERY_EAS_FROM_LIST:
4572 size_t total_ea_len = 0;
4573 struct ea_list *ea_file_list = NULL;
4574 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4576 status =
4577 get_ea_list_from_file(mem_ctx, conn, fsp,
4578 smb_fname,
4579 &total_ea_len, &ea_file_list);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 return status;
4584 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4586 if (!ea_list || (total_ea_len > data_size)) {
4587 data_size = 4;
4588 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4589 break;
4592 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4593 break;
4596 case SMB_INFO_QUERY_ALL_EAS:
4598 /* We have data_size bytes to put EA's into. */
4599 size_t total_ea_len = 0;
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4602 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4603 smb_fname,
4604 &total_ea_len, &ea_list);
4605 if (!NT_STATUS_IS_OK(status)) {
4606 return status;
4609 if (!ea_list || (total_ea_len > data_size)) {
4610 data_size = 4;
4611 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4612 break;
4615 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4616 break;
4619 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4621 /* This is FileFullEaInformation - 0xF which maps to
4622 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4624 /* We have data_size bytes to put EA's into. */
4625 size_t total_ea_len = 0;
4626 struct ea_list *ea_file_list = NULL;
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4630 /*TODO: add filtering and index handling */
4632 status =
4633 get_ea_list_from_file(mem_ctx, conn, fsp,
4634 smb_fname,
4635 &total_ea_len, &ea_file_list);
4636 if (!NT_STATUS_IS_OK(status)) {
4637 return status;
4639 if (!ea_file_list) {
4640 return NT_STATUS_NO_EAS_ON_FILE;
4643 status = fill_ea_chained_buffer(mem_ctx,
4644 pdata,
4645 data_size,
4646 &data_size,
4647 conn, ea_file_list);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 return status;
4651 break;
4654 case SMB_FILE_BASIC_INFORMATION:
4655 case SMB_QUERY_FILE_BASIC_INFO:
4657 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4659 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4660 } else {
4661 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4662 data_size = 40;
4663 SIVAL(pdata,36,0);
4665 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4666 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4667 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4668 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4669 SIVAL(pdata,32,mode);
4671 DEBUG(5,("SMB_QFBI - "));
4672 DEBUG(5,("create: %s ", ctime(&create_time)));
4673 DEBUG(5,("access: %s ", ctime(&atime)));
4674 DEBUG(5,("write: %s ", ctime(&mtime)));
4675 DEBUG(5,("change: %s ", ctime(&c_time)));
4676 DEBUG(5,("mode: %x\n", mode));
4677 break;
4679 case SMB_FILE_STANDARD_INFORMATION:
4680 case SMB_QUERY_FILE_STANDARD_INFO:
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4683 data_size = 24;
4684 SOFF_T(pdata,0,allocation_size);
4685 SOFF_T(pdata,8,file_size);
4686 SIVAL(pdata,16,nlink);
4687 SCVAL(pdata,20,delete_pending?1:0);
4688 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4689 SSVAL(pdata,22,0); /* Padding. */
4690 break;
4692 case SMB_FILE_EA_INFORMATION:
4693 case SMB_QUERY_FILE_EA_INFO:
4695 unsigned int ea_size =
4696 estimate_ea_size(conn, fsp, smb_fname);
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4698 data_size = 4;
4699 SIVAL(pdata,0,ea_size);
4700 break;
4703 /* Get the 8.3 name - used if NT SMB was negotiated. */
4704 case SMB_QUERY_FILE_ALT_NAME_INFO:
4705 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4707 int len;
4708 char mangled_name[13];
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4710 if (!name_to_8_3(base_name,mangled_name,
4711 True,conn->params)) {
4712 return NT_STATUS_NO_MEMORY;
4714 len = srvstr_push(dstart, flags2,
4715 pdata+4, mangled_name,
4716 PTR_DIFF(dend, pdata+4),
4717 STR_UNICODE);
4718 data_size = 4 + len;
4719 SIVAL(pdata,0,len);
4720 break;
4723 case SMB_QUERY_FILE_NAME_INFO:
4725 int len;
4727 this must be *exactly* right for ACLs on mapped drives to work
4729 len = srvstr_push(dstart, flags2,
4730 pdata+4, dos_fname,
4731 PTR_DIFF(dend, pdata+4),
4732 STR_UNICODE);
4733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4734 data_size = 4 + len;
4735 SIVAL(pdata,0,len);
4736 break;
4739 case SMB_FILE_ALLOCATION_INFORMATION:
4740 case SMB_QUERY_FILE_ALLOCATION_INFO:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4742 data_size = 8;
4743 SOFF_T(pdata,0,allocation_size);
4744 break;
4746 case SMB_FILE_END_OF_FILE_INFORMATION:
4747 case SMB_QUERY_FILE_END_OF_FILEINFO:
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4749 data_size = 8;
4750 SOFF_T(pdata,0,file_size);
4751 break;
4753 case SMB_QUERY_FILE_ALL_INFO:
4754 case SMB_FILE_ALL_INFORMATION:
4756 int len;
4757 unsigned int ea_size =
4758 estimate_ea_size(conn, fsp, smb_fname);
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4760 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4761 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4762 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4763 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4764 SIVAL(pdata,32,mode);
4765 SIVAL(pdata,36,0); /* padding. */
4766 pdata += 40;
4767 SOFF_T(pdata,0,allocation_size);
4768 SOFF_T(pdata,8,file_size);
4769 SIVAL(pdata,16,nlink);
4770 SCVAL(pdata,20,delete_pending);
4771 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4772 SSVAL(pdata,22,0);
4773 pdata += 24;
4774 SIVAL(pdata,0,ea_size);
4775 pdata += 4; /* EA info */
4776 len = srvstr_push(dstart, flags2,
4777 pdata+4, dos_fname,
4778 PTR_DIFF(dend, pdata+4),
4779 STR_UNICODE);
4780 SIVAL(pdata,0,len);
4781 pdata += 4 + len;
4782 data_size = PTR_DIFF(pdata,(*ppdata));
4783 break;
4786 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4788 int len;
4789 unsigned int ea_size =
4790 estimate_ea_size(conn, fsp, smb_fname);
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4792 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4793 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4794 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4795 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4796 SIVAL(pdata, 0x20, mode);
4797 SIVAL(pdata, 0x24, 0); /* padding. */
4798 SBVAL(pdata, 0x28, allocation_size);
4799 SBVAL(pdata, 0x30, file_size);
4800 SIVAL(pdata, 0x38, nlink);
4801 SCVAL(pdata, 0x3C, delete_pending);
4802 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4803 SSVAL(pdata, 0x3E, 0); /* padding */
4804 SBVAL(pdata, 0x40, file_index);
4805 SIVAL(pdata, 0x48, ea_size);
4806 SIVAL(pdata, 0x4C, access_mask);
4807 SBVAL(pdata, 0x50, pos);
4808 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4809 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4811 pdata += 0x60;
4813 len = srvstr_push(dstart, flags2,
4814 pdata+4, dos_fname,
4815 PTR_DIFF(dend, pdata+4),
4816 STR_UNICODE);
4817 SIVAL(pdata,0,len);
4818 pdata += 4 + len;
4819 data_size = PTR_DIFF(pdata,(*ppdata));
4820 break;
4822 case SMB_FILE_INTERNAL_INFORMATION:
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4825 SBVAL(pdata, 0, file_index);
4826 data_size = 8;
4827 break;
4829 case SMB_FILE_ACCESS_INFORMATION:
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4831 SIVAL(pdata, 0, access_mask);
4832 data_size = 4;
4833 break;
4835 case SMB_FILE_NAME_INFORMATION:
4836 /* Pathname with leading '\'. */
4838 size_t byte_len;
4839 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4841 SIVAL(pdata,0,byte_len);
4842 data_size = 4 + byte_len;
4843 break;
4846 case SMB_FILE_DISPOSITION_INFORMATION:
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4848 data_size = 1;
4849 SCVAL(pdata,0,delete_pending);
4850 break;
4852 case SMB_FILE_POSITION_INFORMATION:
4853 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4854 data_size = 8;
4855 SOFF_T(pdata,0,pos);
4856 break;
4858 case SMB_FILE_MODE_INFORMATION:
4859 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4860 SIVAL(pdata,0,mode);
4861 data_size = 4;
4862 break;
4864 case SMB_FILE_ALIGNMENT_INFORMATION:
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4866 SIVAL(pdata,0,0); /* No alignment needed. */
4867 data_size = 4;
4868 break;
4871 * NT4 server just returns "invalid query" to this - if we try
4872 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4873 * want this. JRA.
4875 /* The first statement above is false - verified using Thursby
4876 * client against NT4 -- gcolley.
4878 case SMB_QUERY_FILE_STREAM_INFO:
4879 case SMB_FILE_STREAM_INFORMATION: {
4880 unsigned int num_streams = 0;
4881 struct stream_struct *streams = NULL;
4883 DEBUG(10,("smbd_do_qfilepathinfo: "
4884 "SMB_FILE_STREAM_INFORMATION\n"));
4886 if (is_ntfs_stream_smb_fname(smb_fname)) {
4887 return NT_STATUS_INVALID_PARAMETER;
4890 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4891 talloc_tos(), &num_streams, &streams);
4893 if (!NT_STATUS_IS_OK(status)) {
4894 DEBUG(10, ("could not get stream info: %s\n",
4895 nt_errstr(status)));
4896 return status;
4899 status = marshall_stream_info(num_streams, streams,
4900 pdata, max_data_bytes,
4901 &data_size);
4903 if (!NT_STATUS_IS_OK(status)) {
4904 DEBUG(10, ("marshall_stream_info failed: %s\n",
4905 nt_errstr(status)));
4906 TALLOC_FREE(streams);
4907 return status;
4910 TALLOC_FREE(streams);
4912 break;
4914 case SMB_QUERY_COMPRESSION_INFO:
4915 case SMB_FILE_COMPRESSION_INFORMATION:
4916 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4917 SOFF_T(pdata,0,file_size);
4918 SIVAL(pdata,8,0); /* ??? */
4919 SIVAL(pdata,12,0); /* ??? */
4920 data_size = 16;
4921 break;
4923 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4924 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4925 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4926 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4927 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4928 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4929 SOFF_T(pdata,32,allocation_size);
4930 SOFF_T(pdata,40,file_size);
4931 SIVAL(pdata,48,mode);
4932 SIVAL(pdata,52,0); /* ??? */
4933 data_size = 56;
4934 break;
4936 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4937 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4938 SIVAL(pdata,0,mode);
4939 SIVAL(pdata,4,0);
4940 data_size = 8;
4941 break;
4944 * CIFS UNIX Extensions.
4947 case SMB_QUERY_FILE_UNIX_BASIC:
4949 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4950 data_size = PTR_DIFF(pdata,(*ppdata));
4952 DEBUG(4,("smbd_do_qfilepathinfo: "
4953 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4954 dump_data(4, (uint8_t *)(*ppdata), data_size);
4956 break;
4958 case SMB_QUERY_FILE_UNIX_INFO2:
4960 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4961 data_size = PTR_DIFF(pdata,(*ppdata));
4964 int i;
4965 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4967 for (i=0; i<100; i++)
4968 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4969 DEBUG(4,("\n"));
4972 break;
4974 case SMB_QUERY_FILE_UNIX_LINK:
4976 int len;
4977 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4979 if (!buffer) {
4980 return NT_STATUS_NO_MEMORY;
4983 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4984 #ifdef S_ISLNK
4985 if(!S_ISLNK(psbuf->st_ex_mode)) {
4986 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4988 #else
4989 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4990 #endif
4991 len = SMB_VFS_READLINK(conn,
4992 smb_fname->base_name,
4993 buffer, PATH_MAX);
4994 if (len == -1) {
4995 return map_nt_error_from_unix(errno);
4997 buffer[len] = 0;
4998 len = srvstr_push(dstart, flags2,
4999 pdata, buffer,
5000 PTR_DIFF(dend, pdata),
5001 STR_TERMINATE);
5002 pdata += len;
5003 data_size = PTR_DIFF(pdata,(*ppdata));
5005 break;
5008 #if defined(HAVE_POSIX_ACLS)
5009 case SMB_QUERY_POSIX_ACL:
5011 SMB_ACL_T file_acl = NULL;
5012 SMB_ACL_T def_acl = NULL;
5013 uint16 num_file_acls = 0;
5014 uint16 num_def_acls = 0;
5016 if (fsp && fsp->fh->fd != -1) {
5017 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5018 talloc_tos());
5019 } else {
5020 file_acl =
5021 SMB_VFS_SYS_ACL_GET_FILE(conn,
5022 smb_fname->base_name,
5023 SMB_ACL_TYPE_ACCESS,
5024 talloc_tos());
5027 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5028 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5029 "not implemented on "
5030 "filesystem containing %s\n",
5031 smb_fname->base_name));
5032 return NT_STATUS_NOT_IMPLEMENTED;
5035 if (S_ISDIR(psbuf->st_ex_mode)) {
5036 if (fsp && fsp->is_directory) {
5037 def_acl =
5038 SMB_VFS_SYS_ACL_GET_FILE(
5039 conn,
5040 fsp->fsp_name->base_name,
5041 SMB_ACL_TYPE_DEFAULT,
5042 talloc_tos());
5043 } else {
5044 def_acl =
5045 SMB_VFS_SYS_ACL_GET_FILE(
5046 conn,
5047 smb_fname->base_name,
5048 SMB_ACL_TYPE_DEFAULT,
5049 talloc_tos());
5051 def_acl = free_empty_sys_acl(conn, def_acl);
5054 num_file_acls = count_acl_entries(conn, file_acl);
5055 num_def_acls = count_acl_entries(conn, def_acl);
5057 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5058 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5059 data_size,
5060 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5061 SMB_POSIX_ACL_HEADER_SIZE) ));
5062 if (file_acl) {
5063 TALLOC_FREE(file_acl);
5065 if (def_acl) {
5066 TALLOC_FREE(def_acl);
5068 return NT_STATUS_BUFFER_TOO_SMALL;
5071 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5072 SSVAL(pdata,2,num_file_acls);
5073 SSVAL(pdata,4,num_def_acls);
5074 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5075 if (file_acl) {
5076 TALLOC_FREE(file_acl);
5078 if (def_acl) {
5079 TALLOC_FREE(def_acl);
5081 return NT_STATUS_INTERNAL_ERROR;
5083 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5084 if (file_acl) {
5085 TALLOC_FREE(file_acl);
5087 if (def_acl) {
5088 TALLOC_FREE(def_acl);
5090 return NT_STATUS_INTERNAL_ERROR;
5093 if (file_acl) {
5094 TALLOC_FREE(file_acl);
5096 if (def_acl) {
5097 TALLOC_FREE(def_acl);
5099 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5100 break;
5102 #endif
5105 case SMB_QUERY_POSIX_LOCK:
5107 uint64_t count;
5108 uint64_t offset;
5109 uint64_t smblctx;
5110 enum brl_type lock_type;
5112 /* We need an open file with a real fd for this. */
5113 if (!fsp || fsp->fh->fd == -1) {
5114 return NT_STATUS_INVALID_LEVEL;
5117 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5118 return NT_STATUS_INVALID_PARAMETER;
5121 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5122 case POSIX_LOCK_TYPE_READ:
5123 lock_type = READ_LOCK;
5124 break;
5125 case POSIX_LOCK_TYPE_WRITE:
5126 lock_type = WRITE_LOCK;
5127 break;
5128 case POSIX_LOCK_TYPE_UNLOCK:
5129 default:
5130 /* There's no point in asking for an unlock... */
5131 return NT_STATUS_INVALID_PARAMETER;
5134 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5135 #if defined(HAVE_LONGLONG)
5136 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5137 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5138 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5139 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5140 #else /* HAVE_LONGLONG */
5141 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5142 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5143 #endif /* HAVE_LONGLONG */
5145 status = query_lock(fsp,
5146 &smblctx,
5147 &count,
5148 &offset,
5149 &lock_type,
5150 POSIX_LOCK);
5152 if (ERROR_WAS_LOCK_DENIED(status)) {
5153 /* Here we need to report who has it locked... */
5154 data_size = POSIX_LOCK_DATA_SIZE;
5156 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5157 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5158 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5159 #if defined(HAVE_LONGLONG)
5160 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5161 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5162 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5163 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5164 #else /* HAVE_LONGLONG */
5165 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5166 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5167 #endif /* HAVE_LONGLONG */
5169 } else if (NT_STATUS_IS_OK(status)) {
5170 /* For success we just return a copy of what we sent
5171 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5172 data_size = POSIX_LOCK_DATA_SIZE;
5173 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5174 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5175 } else {
5176 return status;
5178 break;
5181 default:
5182 return NT_STATUS_INVALID_LEVEL;
5185 *pdata_size = data_size;
5186 return NT_STATUS_OK;
5189 /****************************************************************************
5190 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5191 file name or file id).
5192 ****************************************************************************/
5194 static void call_trans2qfilepathinfo(connection_struct *conn,
5195 struct smb_request *req,
5196 unsigned int tran_call,
5197 char **pparams, int total_params,
5198 char **ppdata, int total_data,
5199 unsigned int max_data_bytes)
5201 char *params = *pparams;
5202 char *pdata = *ppdata;
5203 uint16 info_level;
5204 unsigned int data_size = 0;
5205 unsigned int param_size = 2;
5206 struct smb_filename *smb_fname = NULL;
5207 bool delete_pending = False;
5208 struct timespec write_time_ts;
5209 files_struct *fsp = NULL;
5210 struct file_id fileid;
5211 struct ea_list *ea_list = NULL;
5212 int lock_data_count = 0;
5213 char *lock_data = NULL;
5214 NTSTATUS status = NT_STATUS_OK;
5216 if (!params) {
5217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5218 return;
5221 ZERO_STRUCT(write_time_ts);
5223 if (tran_call == TRANSACT2_QFILEINFO) {
5224 if (total_params < 4) {
5225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5226 return;
5229 if (IS_IPC(conn)) {
5230 call_trans2qpipeinfo(conn, req, tran_call,
5231 pparams, total_params,
5232 ppdata, total_data,
5233 max_data_bytes);
5234 return;
5237 fsp = file_fsp(req, SVAL(params,0));
5238 info_level = SVAL(params,2);
5240 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5242 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5243 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5244 return;
5247 /* Initial check for valid fsp ptr. */
5248 if (!check_fsp_open(conn, req, fsp)) {
5249 return;
5252 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5253 if (smb_fname == NULL) {
5254 reply_nterror(req, NT_STATUS_NO_MEMORY);
5255 return;
5258 if(fsp->fake_file_handle) {
5260 * This is actually for the QUOTA_FAKE_FILE --metze
5263 /* We know this name is ok, it's already passed the checks. */
5265 } else if(fsp->fh->fd == -1) {
5267 * This is actually a QFILEINFO on a directory
5268 * handle (returned from an NT SMB). NT5.0 seems
5269 * to do this call. JRA.
5272 if (INFO_LEVEL_IS_UNIX(info_level)) {
5273 /* Always do lstat for UNIX calls. */
5274 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5275 DEBUG(3,("call_trans2qfilepathinfo: "
5276 "SMB_VFS_LSTAT of %s failed "
5277 "(%s)\n",
5278 smb_fname_str_dbg(smb_fname),
5279 strerror(errno)));
5280 reply_nterror(req,
5281 map_nt_error_from_unix(errno));
5282 return;
5284 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5285 DEBUG(3,("call_trans2qfilepathinfo: "
5286 "SMB_VFS_STAT of %s failed (%s)\n",
5287 smb_fname_str_dbg(smb_fname),
5288 strerror(errno)));
5289 reply_nterror(req,
5290 map_nt_error_from_unix(errno));
5291 return;
5294 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5295 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5296 } else {
5298 * Original code - this is an open file.
5300 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5301 DEBUG(3, ("fstat of %s failed (%s)\n",
5302 fsp_fnum_dbg(fsp), strerror(errno)));
5303 reply_nterror(req,
5304 map_nt_error_from_unix(errno));
5305 return;
5307 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5308 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5311 } else {
5312 uint32_t name_hash;
5313 char *fname = NULL;
5314 uint32_t ucf_flags = 0;
5316 /* qpathinfo */
5317 if (total_params < 7) {
5318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5319 return;
5322 info_level = SVAL(params,0);
5324 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5326 if (INFO_LEVEL_IS_UNIX(info_level)) {
5327 if (!lp_unix_extensions()) {
5328 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5329 return;
5331 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5332 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5333 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5334 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5338 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5339 total_params - 6,
5340 STR_TERMINATE, &status);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 reply_nterror(req, status);
5343 return;
5346 status = filename_convert(req,
5347 conn,
5348 req->flags2 & FLAGS2_DFS_PATHNAMES,
5349 fname,
5350 ucf_flags,
5351 NULL,
5352 &smb_fname);
5353 if (!NT_STATUS_IS_OK(status)) {
5354 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5355 reply_botherror(req,
5356 NT_STATUS_PATH_NOT_COVERED,
5357 ERRSRV, ERRbadpath);
5358 return;
5360 reply_nterror(req, status);
5361 return;
5364 /* If this is a stream, check if there is a delete_pending. */
5365 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5366 && is_ntfs_stream_smb_fname(smb_fname)) {
5367 struct smb_filename *smb_fname_base;
5369 /* Create an smb_filename with stream_name == NULL. */
5370 smb_fname_base = synthetic_smb_fname(
5371 talloc_tos(), smb_fname->base_name,
5372 NULL, NULL);
5373 if (smb_fname_base == NULL) {
5374 reply_nterror(req, NT_STATUS_NO_MEMORY);
5375 return;
5378 if (INFO_LEVEL_IS_UNIX(info_level)) {
5379 /* Always do lstat for UNIX calls. */
5380 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5381 DEBUG(3,("call_trans2qfilepathinfo: "
5382 "SMB_VFS_LSTAT of %s failed "
5383 "(%s)\n",
5384 smb_fname_str_dbg(smb_fname_base),
5385 strerror(errno)));
5386 TALLOC_FREE(smb_fname_base);
5387 reply_nterror(req,
5388 map_nt_error_from_unix(errno));
5389 return;
5391 } else {
5392 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5393 DEBUG(3,("call_trans2qfilepathinfo: "
5394 "fileinfo of %s failed "
5395 "(%s)\n",
5396 smb_fname_str_dbg(smb_fname_base),
5397 strerror(errno)));
5398 TALLOC_FREE(smb_fname_base);
5399 reply_nterror(req,
5400 map_nt_error_from_unix(errno));
5401 return;
5405 status = file_name_hash(conn,
5406 smb_fname_str_dbg(smb_fname_base),
5407 &name_hash);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 TALLOC_FREE(smb_fname_base);
5410 reply_nterror(req, status);
5411 return;
5414 fileid = vfs_file_id_from_sbuf(conn,
5415 &smb_fname_base->st);
5416 TALLOC_FREE(smb_fname_base);
5417 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5418 if (delete_pending) {
5419 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5420 return;
5424 if (INFO_LEVEL_IS_UNIX(info_level)) {
5425 /* Always do lstat for UNIX calls. */
5426 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5427 DEBUG(3,("call_trans2qfilepathinfo: "
5428 "SMB_VFS_LSTAT of %s failed (%s)\n",
5429 smb_fname_str_dbg(smb_fname),
5430 strerror(errno)));
5431 reply_nterror(req,
5432 map_nt_error_from_unix(errno));
5433 return;
5436 } else {
5437 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5438 DEBUG(3,("call_trans2qfilepathinfo: "
5439 "SMB_VFS_STAT of %s failed (%s)\n",
5440 smb_fname_str_dbg(smb_fname),
5441 strerror(errno)));
5442 reply_nterror(req,
5443 map_nt_error_from_unix(errno));
5444 return;
5448 status = file_name_hash(conn,
5449 smb_fname_str_dbg(smb_fname),
5450 &name_hash);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 reply_nterror(req, status);
5453 return;
5456 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5457 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5458 if (delete_pending) {
5459 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5460 return;
5464 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5465 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5466 fsp_fnum_dbg(fsp),
5467 info_level,tran_call,total_data));
5469 /* Pull out any data sent here before we realloc. */
5470 switch (info_level) {
5471 case SMB_INFO_QUERY_EAS_FROM_LIST:
5473 /* Pull any EA list from the data portion. */
5474 uint32 ea_size;
5476 if (total_data < 4) {
5477 reply_nterror(
5478 req, NT_STATUS_INVALID_PARAMETER);
5479 return;
5481 ea_size = IVAL(pdata,0);
5483 if (total_data > 0 && ea_size != total_data) {
5484 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5485 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5486 reply_nterror(
5487 req, NT_STATUS_INVALID_PARAMETER);
5488 return;
5491 if (!lp_ea_support(SNUM(conn))) {
5492 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5493 return;
5496 /* Pull out the list of names. */
5497 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5498 if (!ea_list) {
5499 reply_nterror(
5500 req, NT_STATUS_INVALID_PARAMETER);
5501 return;
5503 break;
5506 case SMB_QUERY_POSIX_LOCK:
5508 if (fsp == NULL || fsp->fh->fd == -1) {
5509 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5510 return;
5513 if (total_data != POSIX_LOCK_DATA_SIZE) {
5514 reply_nterror(
5515 req, NT_STATUS_INVALID_PARAMETER);
5516 return;
5519 /* Copy the lock range data. */
5520 lock_data = (char *)talloc_memdup(
5521 req, pdata, total_data);
5522 if (!lock_data) {
5523 reply_nterror(req, NT_STATUS_NO_MEMORY);
5524 return;
5526 lock_data_count = total_data;
5528 default:
5529 break;
5532 *pparams = (char *)SMB_REALLOC(*pparams,2);
5533 if (*pparams == NULL) {
5534 reply_nterror(req, NT_STATUS_NO_MEMORY);
5535 return;
5537 params = *pparams;
5538 SSVAL(params,0,0);
5541 * draft-leach-cifs-v1-spec-02.txt
5542 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5543 * says:
5545 * The requested information is placed in the Data portion of the
5546 * transaction response. For the information levels greater than 0x100,
5547 * the transaction response has 1 parameter word which should be
5548 * ignored by the client.
5550 * However Windows only follows this rule for the IS_NAME_VALID call.
5552 switch (info_level) {
5553 case SMB_INFO_IS_NAME_VALID:
5554 param_size = 0;
5555 break;
5558 if ((info_level & 0xFF00) == 0xFF00) {
5560 * We use levels that start with 0xFF00
5561 * internally to represent SMB2 specific levels
5563 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5564 return;
5567 status = smbd_do_qfilepathinfo(conn, req, info_level,
5568 fsp, smb_fname,
5569 delete_pending, write_time_ts,
5570 ea_list,
5571 lock_data_count, lock_data,
5572 req->flags2, max_data_bytes,
5573 ppdata, &data_size);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 reply_nterror(req, status);
5576 return;
5579 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5580 max_data_bytes);
5582 return;
5585 /****************************************************************************
5586 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5587 code.
5588 ****************************************************************************/
5590 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5591 connection_struct *conn,
5592 struct smb_request *req,
5593 bool overwrite_if_exists,
5594 const struct smb_filename *smb_fname_old,
5595 struct smb_filename *smb_fname_new)
5597 NTSTATUS status = NT_STATUS_OK;
5599 /* source must already exist. */
5600 if (!VALID_STAT(smb_fname_old->st)) {
5601 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5604 if (VALID_STAT(smb_fname_new->st)) {
5605 if (overwrite_if_exists) {
5606 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5607 return NT_STATUS_FILE_IS_A_DIRECTORY;
5609 status = unlink_internals(conn,
5610 req,
5611 FILE_ATTRIBUTE_NORMAL,
5612 smb_fname_new,
5613 false);
5614 if (!NT_STATUS_IS_OK(status)) {
5615 return status;
5617 } else {
5618 /* Disallow if newname already exists. */
5619 return NT_STATUS_OBJECT_NAME_COLLISION;
5623 /* No links from a directory. */
5624 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5625 return NT_STATUS_FILE_IS_A_DIRECTORY;
5628 /* Setting a hardlink to/from a stream isn't currently supported. */
5629 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5630 is_ntfs_stream_smb_fname(smb_fname_new)) {
5631 return NT_STATUS_INVALID_PARAMETER;
5634 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5635 smb_fname_old->base_name, smb_fname_new->base_name));
5637 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5638 smb_fname_new->base_name) != 0) {
5639 status = map_nt_error_from_unix(errno);
5640 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5641 nt_errstr(status), smb_fname_old->base_name,
5642 smb_fname_new->base_name));
5644 return status;
5647 /****************************************************************************
5648 Deal with setting the time from any of the setfilepathinfo functions.
5649 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5650 calling this function.
5651 ****************************************************************************/
5653 NTSTATUS smb_set_file_time(connection_struct *conn,
5654 files_struct *fsp,
5655 const struct smb_filename *smb_fname,
5656 struct smb_file_time *ft,
5657 bool setting_write_time)
5659 struct smb_filename smb_fname_base;
5660 uint32 action =
5661 FILE_NOTIFY_CHANGE_LAST_ACCESS
5662 |FILE_NOTIFY_CHANGE_LAST_WRITE
5663 |FILE_NOTIFY_CHANGE_CREATION;
5665 if (!VALID_STAT(smb_fname->st)) {
5666 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5669 /* get some defaults (no modifications) if any info is zero or -1. */
5670 if (null_timespec(ft->create_time)) {
5671 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5674 if (null_timespec(ft->atime)) {
5675 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5678 if (null_timespec(ft->mtime)) {
5679 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5682 if (!setting_write_time) {
5683 /* ft->mtime comes from change time, not write time. */
5684 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5687 /* Ensure the resolution is the correct for
5688 * what we can store on this filesystem. */
5690 round_timespec(conn->ts_res, &ft->create_time);
5691 round_timespec(conn->ts_res, &ft->ctime);
5692 round_timespec(conn->ts_res, &ft->atime);
5693 round_timespec(conn->ts_res, &ft->mtime);
5695 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5696 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5697 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5698 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5699 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5700 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5701 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5702 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5704 if (setting_write_time) {
5706 * This was a Windows setfileinfo on an open file.
5707 * NT does this a lot. We also need to
5708 * set the time here, as it can be read by
5709 * FindFirst/FindNext and with the patch for bug #2045
5710 * in smbd/fileio.c it ensures that this timestamp is
5711 * kept sticky even after a write. We save the request
5712 * away and will set it on file close and after a write. JRA.
5715 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5716 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5718 if (fsp != NULL) {
5719 if (fsp->base_fsp) {
5720 set_sticky_write_time_fsp(fsp->base_fsp,
5721 ft->mtime);
5722 } else {
5723 set_sticky_write_time_fsp(fsp, ft->mtime);
5725 } else {
5726 set_sticky_write_time_path(
5727 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5728 ft->mtime);
5732 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5734 /* Always call ntimes on the base, even if a stream was passed in. */
5735 smb_fname_base = *smb_fname;
5736 smb_fname_base.stream_name = NULL;
5738 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5739 return map_nt_error_from_unix(errno);
5742 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5743 smb_fname->base_name);
5744 return NT_STATUS_OK;
5747 /****************************************************************************
5748 Deal with setting the dosmode from any of the setfilepathinfo functions.
5749 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5750 done before calling this function.
5751 ****************************************************************************/
5753 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5754 const struct smb_filename *smb_fname,
5755 uint32 dosmode)
5757 struct smb_filename *smb_fname_base;
5758 NTSTATUS status;
5760 if (!VALID_STAT(smb_fname->st)) {
5761 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5764 /* Always operate on the base_name, even if a stream was passed in. */
5765 smb_fname_base = synthetic_smb_fname(
5766 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5767 if (smb_fname_base == NULL) {
5768 return NT_STATUS_NO_MEMORY;
5771 if (dosmode) {
5772 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5773 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5774 } else {
5775 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5779 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5781 /* check the mode isn't different, before changing it */
5782 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5783 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5784 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5785 (unsigned int)dosmode));
5787 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5788 false)) {
5789 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5790 "%s failed (%s)\n",
5791 smb_fname_str_dbg(smb_fname_base),
5792 strerror(errno)));
5793 status = map_nt_error_from_unix(errno);
5794 goto out;
5797 status = NT_STATUS_OK;
5798 out:
5799 TALLOC_FREE(smb_fname_base);
5800 return status;
5803 /****************************************************************************
5804 Deal with setting the size from any of the setfilepathinfo functions.
5805 ****************************************************************************/
5807 static NTSTATUS smb_set_file_size(connection_struct *conn,
5808 struct smb_request *req,
5809 files_struct *fsp,
5810 const struct smb_filename *smb_fname,
5811 const SMB_STRUCT_STAT *psbuf,
5812 off_t size,
5813 bool fail_after_createfile)
5815 NTSTATUS status = NT_STATUS_OK;
5816 struct smb_filename *smb_fname_tmp = NULL;
5817 files_struct *new_fsp = NULL;
5819 if (!VALID_STAT(*psbuf)) {
5820 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5823 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5825 if (size == get_file_size_stat(psbuf)) {
5826 return NT_STATUS_OK;
5829 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5830 smb_fname_str_dbg(smb_fname), (double)size));
5832 if (fsp && fsp->fh->fd != -1) {
5833 /* Handle based call. */
5834 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5835 return NT_STATUS_ACCESS_DENIED;
5838 if (vfs_set_filelen(fsp, size) == -1) {
5839 return map_nt_error_from_unix(errno);
5841 trigger_write_time_update_immediate(fsp);
5842 return NT_STATUS_OK;
5845 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5846 if (smb_fname_tmp == NULL) {
5847 return NT_STATUS_NO_MEMORY;
5850 smb_fname_tmp->st = *psbuf;
5852 status = SMB_VFS_CREATE_FILE(
5853 conn, /* conn */
5854 req, /* req */
5855 0, /* root_dir_fid */
5856 smb_fname_tmp, /* fname */
5857 FILE_WRITE_DATA, /* access_mask */
5858 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5859 FILE_SHARE_DELETE),
5860 FILE_OPEN, /* create_disposition*/
5861 0, /* create_options */
5862 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5863 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5864 0, /* allocation_size */
5865 0, /* private_flags */
5866 NULL, /* sd */
5867 NULL, /* ea_list */
5868 &new_fsp, /* result */
5869 NULL); /* pinfo */
5871 TALLOC_FREE(smb_fname_tmp);
5873 if (!NT_STATUS_IS_OK(status)) {
5874 /* NB. We check for open_was_deferred in the caller. */
5875 return status;
5878 /* See RAW-SFILEINFO-END-OF-FILE */
5879 if (fail_after_createfile) {
5880 close_file(req, new_fsp,NORMAL_CLOSE);
5881 return NT_STATUS_INVALID_LEVEL;
5884 if (vfs_set_filelen(new_fsp, size) == -1) {
5885 status = map_nt_error_from_unix(errno);
5886 close_file(req, new_fsp,NORMAL_CLOSE);
5887 return status;
5890 trigger_write_time_update_immediate(new_fsp);
5891 close_file(req, new_fsp,NORMAL_CLOSE);
5892 return NT_STATUS_OK;
5895 /****************************************************************************
5896 Deal with SMB_INFO_SET_EA.
5897 ****************************************************************************/
5899 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5900 const char *pdata,
5901 int total_data,
5902 files_struct *fsp,
5903 const struct smb_filename *smb_fname)
5905 struct ea_list *ea_list = NULL;
5906 TALLOC_CTX *ctx = NULL;
5907 NTSTATUS status = NT_STATUS_OK;
5909 if (total_data < 10) {
5911 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5912 length. They seem to have no effect. Bug #3212. JRA */
5914 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5915 /* We're done. We only get EA info in this call. */
5916 return NT_STATUS_OK;
5919 return NT_STATUS_INVALID_PARAMETER;
5922 if (IVAL(pdata,0) > total_data) {
5923 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5924 IVAL(pdata,0), (unsigned int)total_data));
5925 return NT_STATUS_INVALID_PARAMETER;
5928 ctx = talloc_tos();
5929 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5930 if (!ea_list) {
5931 return NT_STATUS_INVALID_PARAMETER;
5934 status = set_ea(conn, fsp, smb_fname, ea_list);
5936 return status;
5939 /****************************************************************************
5940 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5941 ****************************************************************************/
5943 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5944 const char *pdata,
5945 int total_data,
5946 files_struct *fsp)
5948 struct ea_list *ea_list = NULL;
5949 NTSTATUS status;
5951 if (!fsp) {
5952 return NT_STATUS_INVALID_HANDLE;
5955 if (!lp_ea_support(SNUM(conn))) {
5956 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5957 "EA's not supported.\n",
5958 (unsigned int)total_data));
5959 return NT_STATUS_EAS_NOT_SUPPORTED;
5962 if (total_data < 10) {
5963 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5964 "too small.\n",
5965 (unsigned int)total_data));
5966 return NT_STATUS_INVALID_PARAMETER;
5969 ea_list = read_nttrans_ea_list(talloc_tos(),
5970 pdata,
5971 total_data);
5973 if (!ea_list) {
5974 return NT_STATUS_INVALID_PARAMETER;
5977 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5979 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5980 smb_fname_str_dbg(fsp->fsp_name),
5981 nt_errstr(status) ));
5983 return status;
5987 /****************************************************************************
5988 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5989 ****************************************************************************/
5991 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5992 const char *pdata,
5993 int total_data,
5994 files_struct *fsp,
5995 struct smb_filename *smb_fname)
5997 NTSTATUS status = NT_STATUS_OK;
5998 bool delete_on_close;
5999 uint32 dosmode = 0;
6001 if (total_data < 1) {
6002 return NT_STATUS_INVALID_PARAMETER;
6005 if (fsp == NULL) {
6006 return NT_STATUS_INVALID_HANDLE;
6009 delete_on_close = (CVAL(pdata,0) ? True : False);
6010 dosmode = dos_mode(conn, smb_fname);
6012 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6013 "delete_on_close = %u\n",
6014 smb_fname_str_dbg(smb_fname),
6015 (unsigned int)dosmode,
6016 (unsigned int)delete_on_close ));
6018 if (delete_on_close) {
6019 status = can_set_delete_on_close(fsp, dosmode);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 return status;
6025 /* The set is across all open files on this dev/inode pair. */
6026 if (!set_delete_on_close(fsp, delete_on_close,
6027 conn->session_info->security_token,
6028 conn->session_info->unix_token)) {
6029 return NT_STATUS_ACCESS_DENIED;
6031 return NT_STATUS_OK;
6034 /****************************************************************************
6035 Deal with SMB_FILE_POSITION_INFORMATION.
6036 ****************************************************************************/
6038 static NTSTATUS smb_file_position_information(connection_struct *conn,
6039 const char *pdata,
6040 int total_data,
6041 files_struct *fsp)
6043 uint64_t position_information;
6045 if (total_data < 8) {
6046 return NT_STATUS_INVALID_PARAMETER;
6049 if (fsp == NULL) {
6050 /* Ignore on pathname based set. */
6051 return NT_STATUS_OK;
6054 position_information = (uint64_t)IVAL(pdata,0);
6055 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6057 DEBUG(10,("smb_file_position_information: Set file position "
6058 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6059 (double)position_information));
6060 fsp->fh->position_information = position_information;
6061 return NT_STATUS_OK;
6064 /****************************************************************************
6065 Deal with SMB_FILE_MODE_INFORMATION.
6066 ****************************************************************************/
6068 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6069 const char *pdata,
6070 int total_data)
6072 uint32 mode;
6074 if (total_data < 4) {
6075 return NT_STATUS_INVALID_PARAMETER;
6077 mode = IVAL(pdata,0);
6078 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6079 return NT_STATUS_INVALID_PARAMETER;
6081 return NT_STATUS_OK;
6084 /****************************************************************************
6085 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6086 ****************************************************************************/
6088 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6089 struct smb_request *req,
6090 const char *pdata,
6091 int total_data,
6092 const struct smb_filename *smb_fname)
6094 char *link_target = NULL;
6095 const char *newname = smb_fname->base_name;
6096 TALLOC_CTX *ctx = talloc_tos();
6098 /* Set a symbolic link. */
6099 /* Don't allow this if follow links is false. */
6101 if (total_data == 0) {
6102 return NT_STATUS_INVALID_PARAMETER;
6105 if (!lp_symlinks(SNUM(conn))) {
6106 return NT_STATUS_ACCESS_DENIED;
6109 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6110 total_data, STR_TERMINATE);
6112 if (!link_target) {
6113 return NT_STATUS_INVALID_PARAMETER;
6116 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6117 newname, link_target ));
6119 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6120 return map_nt_error_from_unix(errno);
6123 return NT_STATUS_OK;
6126 /****************************************************************************
6127 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6128 ****************************************************************************/
6130 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6131 struct smb_request *req,
6132 const char *pdata, int total_data,
6133 struct smb_filename *smb_fname_new)
6135 char *oldname = NULL;
6136 struct smb_filename *smb_fname_old = NULL;
6137 TALLOC_CTX *ctx = talloc_tos();
6138 NTSTATUS status = NT_STATUS_OK;
6140 /* Set a hard link. */
6141 if (total_data == 0) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6146 total_data, STR_TERMINATE, &status);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 return status;
6151 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6152 smb_fname_str_dbg(smb_fname_new), oldname));
6154 status = filename_convert(ctx,
6155 conn,
6156 req->flags2 & FLAGS2_DFS_PATHNAMES,
6157 oldname,
6159 NULL,
6160 &smb_fname_old);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 return status;
6165 return hardlink_internals(ctx, conn, req, false,
6166 smb_fname_old, smb_fname_new);
6169 /****************************************************************************
6170 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6171 ****************************************************************************/
6173 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6174 struct smb_request *req,
6175 const char *pdata,
6176 int total_data,
6177 files_struct *fsp,
6178 struct smb_filename *smb_fname_src)
6180 bool overwrite;
6181 uint32_t len;
6182 char *newname = NULL;
6183 struct smb_filename *smb_fname_dst = NULL;
6184 NTSTATUS status = NT_STATUS_OK;
6185 TALLOC_CTX *ctx = talloc_tos();
6187 if (!fsp) {
6188 return NT_STATUS_INVALID_HANDLE;
6191 if (total_data < 20) {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 overwrite = (CVAL(pdata,0) ? True : False);
6196 len = IVAL(pdata,16);
6198 if (len > (total_data - 20) || (len == 0)) {
6199 return NT_STATUS_INVALID_PARAMETER;
6202 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6203 &pdata[20], len, STR_TERMINATE,
6204 &status);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 return status;
6209 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6210 newname));
6212 status = filename_convert(ctx,
6213 conn,
6214 req->flags2 & FLAGS2_DFS_PATHNAMES,
6215 newname,
6216 UCF_SAVE_LCOMP,
6217 NULL,
6218 &smb_fname_dst);
6219 if (!NT_STATUS_IS_OK(status)) {
6220 return status;
6223 if (fsp->base_fsp) {
6224 /* newname must be a stream name. */
6225 if (newname[0] != ':') {
6226 return NT_STATUS_NOT_SUPPORTED;
6229 /* Create an smb_fname to call rename_internals_fsp() with. */
6230 smb_fname_dst = synthetic_smb_fname(
6231 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6232 newname, NULL);
6233 if (smb_fname_dst == NULL) {
6234 status = NT_STATUS_NO_MEMORY;
6235 goto out;
6239 * Set the original last component, since
6240 * rename_internals_fsp() requires it.
6242 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6243 newname);
6244 if (smb_fname_dst->original_lcomp == NULL) {
6245 status = NT_STATUS_NO_MEMORY;
6246 goto out;
6251 DEBUG(10,("smb2_file_rename_information: "
6252 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6253 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6254 smb_fname_str_dbg(smb_fname_dst)));
6255 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6256 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6257 overwrite);
6259 out:
6260 TALLOC_FREE(smb_fname_dst);
6261 return status;
6264 static NTSTATUS smb_file_link_information(connection_struct *conn,
6265 struct smb_request *req,
6266 const char *pdata,
6267 int total_data,
6268 files_struct *fsp,
6269 struct smb_filename *smb_fname_src)
6271 bool overwrite;
6272 uint32_t len;
6273 char *newname = NULL;
6274 struct smb_filename *smb_fname_dst = NULL;
6275 NTSTATUS status = NT_STATUS_OK;
6276 TALLOC_CTX *ctx = talloc_tos();
6278 if (!fsp) {
6279 return NT_STATUS_INVALID_HANDLE;
6282 if (total_data < 20) {
6283 return NT_STATUS_INVALID_PARAMETER;
6286 overwrite = (CVAL(pdata,0) ? true : false);
6287 len = IVAL(pdata,16);
6289 if (len > (total_data - 20) || (len == 0)) {
6290 return NT_STATUS_INVALID_PARAMETER;
6293 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6294 &pdata[20], len, STR_TERMINATE,
6295 &status);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 return status;
6300 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6301 newname));
6303 status = filename_convert(ctx,
6304 conn,
6305 req->flags2 & FLAGS2_DFS_PATHNAMES,
6306 newname,
6307 UCF_SAVE_LCOMP,
6308 NULL,
6309 &smb_fname_dst);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 return status;
6314 if (fsp->base_fsp) {
6315 /* No stream names. */
6316 return NT_STATUS_NOT_SUPPORTED;
6319 DEBUG(10,("smb_file_link_information: "
6320 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6321 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6322 smb_fname_str_dbg(smb_fname_dst)));
6323 status = hardlink_internals(ctx,
6324 conn,
6325 req,
6326 overwrite,
6327 fsp->fsp_name,
6328 smb_fname_dst);
6330 TALLOC_FREE(smb_fname_dst);
6331 return status;
6334 /****************************************************************************
6335 Deal with SMB_FILE_RENAME_INFORMATION.
6336 ****************************************************************************/
6338 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6339 struct smb_request *req,
6340 const char *pdata,
6341 int total_data,
6342 files_struct *fsp,
6343 struct smb_filename *smb_fname_src)
6345 bool overwrite;
6346 uint32 root_fid;
6347 uint32 len;
6348 char *newname = NULL;
6349 struct smb_filename *smb_fname_dst = NULL;
6350 bool dest_has_wcard = False;
6351 NTSTATUS status = NT_STATUS_OK;
6352 char *p;
6353 TALLOC_CTX *ctx = talloc_tos();
6355 if (total_data < 13) {
6356 return NT_STATUS_INVALID_PARAMETER;
6359 overwrite = (CVAL(pdata,0) ? True : False);
6360 root_fid = IVAL(pdata,4);
6361 len = IVAL(pdata,8);
6363 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6364 return NT_STATUS_INVALID_PARAMETER;
6367 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6368 len, 0, &status,
6369 &dest_has_wcard);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 return status;
6374 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6375 newname));
6377 status = resolve_dfspath_wcard(ctx, conn,
6378 req->flags2 & FLAGS2_DFS_PATHNAMES,
6379 newname,
6380 true,
6381 !conn->sconn->using_smb2,
6382 &newname,
6383 &dest_has_wcard);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 return status;
6388 /* Check the new name has no '/' characters. */
6389 if (strchr_m(newname, '/')) {
6390 return NT_STATUS_NOT_SUPPORTED;
6393 if (fsp && fsp->base_fsp) {
6394 /* newname must be a stream name. */
6395 if (newname[0] != ':') {
6396 return NT_STATUS_NOT_SUPPORTED;
6399 /* Create an smb_fname to call rename_internals_fsp() with. */
6400 smb_fname_dst = synthetic_smb_fname(
6401 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6402 newname, NULL);
6403 if (smb_fname_dst == NULL) {
6404 status = NT_STATUS_NO_MEMORY;
6405 goto out;
6409 * Set the original last component, since
6410 * rename_internals_fsp() requires it.
6412 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6413 newname);
6414 if (smb_fname_dst->original_lcomp == NULL) {
6415 status = NT_STATUS_NO_MEMORY;
6416 goto out;
6419 } else {
6421 * Build up an smb_fname_dst based on the filename passed in.
6422 * We basically just strip off the last component, and put on
6423 * the newname instead.
6425 char *base_name = NULL;
6427 /* newname must *not* be a stream name. */
6428 if (newname[0] == ':') {
6429 return NT_STATUS_NOT_SUPPORTED;
6433 * Strip off the last component (filename) of the path passed
6434 * in.
6436 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6437 if (!base_name) {
6438 return NT_STATUS_NO_MEMORY;
6440 p = strrchr_m(base_name, '/');
6441 if (p) {
6442 p[1] = '\0';
6443 } else {
6444 base_name = talloc_strdup(ctx, "");
6445 if (!base_name) {
6446 return NT_STATUS_NO_MEMORY;
6449 /* Append the new name. */
6450 base_name = talloc_asprintf_append(base_name,
6451 "%s",
6452 newname);
6453 if (!base_name) {
6454 return NT_STATUS_NO_MEMORY;
6457 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6458 (UCF_SAVE_LCOMP |
6459 (dest_has_wcard ?
6460 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6461 0)));
6463 /* If an error we expect this to be
6464 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6466 if (!NT_STATUS_IS_OK(status)) {
6467 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6468 status)) {
6469 goto out;
6471 /* Create an smb_fname to call rename_internals_fsp() */
6472 smb_fname_dst = synthetic_smb_fname(
6473 ctx, base_name, NULL, NULL);
6474 if (smb_fname_dst == NULL) {
6475 status = NT_STATUS_NO_MEMORY;
6476 goto out;
6481 if (fsp) {
6482 DEBUG(10,("smb_file_rename_information: "
6483 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6484 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6485 smb_fname_str_dbg(smb_fname_dst)));
6486 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6487 overwrite);
6488 } else {
6489 DEBUG(10,("smb_file_rename_information: "
6490 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6491 smb_fname_str_dbg(smb_fname_src),
6492 smb_fname_str_dbg(smb_fname_dst)));
6493 status = rename_internals(ctx, conn, req, smb_fname_src,
6494 smb_fname_dst, 0, overwrite, false,
6495 dest_has_wcard,
6496 FILE_WRITE_ATTRIBUTES);
6498 out:
6499 TALLOC_FREE(smb_fname_dst);
6500 return status;
6503 /****************************************************************************
6504 Deal with SMB_SET_POSIX_ACL.
6505 ****************************************************************************/
6507 #if defined(HAVE_POSIX_ACLS)
6508 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6509 const char *pdata,
6510 int total_data,
6511 files_struct *fsp,
6512 const struct smb_filename *smb_fname)
6514 uint16 posix_acl_version;
6515 uint16 num_file_acls;
6516 uint16 num_def_acls;
6517 bool valid_file_acls = True;
6518 bool valid_def_acls = True;
6520 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6521 return NT_STATUS_INVALID_PARAMETER;
6523 posix_acl_version = SVAL(pdata,0);
6524 num_file_acls = SVAL(pdata,2);
6525 num_def_acls = SVAL(pdata,4);
6527 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6528 valid_file_acls = False;
6529 num_file_acls = 0;
6532 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6533 valid_def_acls = False;
6534 num_def_acls = 0;
6537 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6538 return NT_STATUS_INVALID_PARAMETER;
6541 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6542 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6543 return NT_STATUS_INVALID_PARAMETER;
6546 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6547 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6548 (unsigned int)num_file_acls,
6549 (unsigned int)num_def_acls));
6551 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6552 smb_fname->base_name, num_file_acls,
6553 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6554 return map_nt_error_from_unix(errno);
6557 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6558 smb_fname->base_name, &smb_fname->st, num_def_acls,
6559 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6560 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6561 return map_nt_error_from_unix(errno);
6563 return NT_STATUS_OK;
6565 #endif
6567 /****************************************************************************
6568 Deal with SMB_SET_POSIX_LOCK.
6569 ****************************************************************************/
6571 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6572 struct smb_request *req,
6573 const char *pdata,
6574 int total_data,
6575 files_struct *fsp)
6577 uint64_t count;
6578 uint64_t offset;
6579 uint64_t smblctx;
6580 bool blocking_lock = False;
6581 enum brl_type lock_type;
6583 NTSTATUS status = NT_STATUS_OK;
6585 if (fsp == NULL || fsp->fh->fd == -1) {
6586 return NT_STATUS_INVALID_HANDLE;
6589 if (total_data != POSIX_LOCK_DATA_SIZE) {
6590 return NT_STATUS_INVALID_PARAMETER;
6593 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6594 case POSIX_LOCK_TYPE_READ:
6595 lock_type = READ_LOCK;
6596 break;
6597 case POSIX_LOCK_TYPE_WRITE:
6598 /* Return the right POSIX-mappable error code for files opened read-only. */
6599 if (!fsp->can_write) {
6600 return NT_STATUS_INVALID_HANDLE;
6602 lock_type = WRITE_LOCK;
6603 break;
6604 case POSIX_LOCK_TYPE_UNLOCK:
6605 lock_type = UNLOCK_LOCK;
6606 break;
6607 default:
6608 return NT_STATUS_INVALID_PARAMETER;
6611 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6612 blocking_lock = False;
6613 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6614 blocking_lock = True;
6615 } else {
6616 return NT_STATUS_INVALID_PARAMETER;
6619 if (!lp_blocking_locks(SNUM(conn))) {
6620 blocking_lock = False;
6623 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6624 #if defined(HAVE_LONGLONG)
6625 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6626 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6627 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6628 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6629 #else /* HAVE_LONGLONG */
6630 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6631 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6632 #endif /* HAVE_LONGLONG */
6634 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6635 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6636 fsp_str_dbg(fsp),
6637 (unsigned int)lock_type,
6638 (unsigned long long)smblctx,
6639 (double)count,
6640 (double)offset ));
6642 if (lock_type == UNLOCK_LOCK) {
6643 status = do_unlock(req->sconn->msg_ctx,
6644 fsp,
6645 smblctx,
6646 count,
6647 offset,
6648 POSIX_LOCK);
6649 } else {
6650 uint64_t block_smblctx;
6652 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6653 fsp,
6654 smblctx,
6655 count,
6656 offset,
6657 lock_type,
6658 POSIX_LOCK,
6659 blocking_lock,
6660 &status,
6661 &block_smblctx,
6662 NULL);
6664 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6666 * A blocking lock was requested. Package up
6667 * this smb into a queued request and push it
6668 * onto the blocking lock queue.
6670 if(push_blocking_lock_request(br_lck,
6671 req,
6672 fsp,
6673 -1, /* infinite timeout. */
6675 smblctx,
6676 lock_type,
6677 POSIX_LOCK,
6678 offset,
6679 count,
6680 block_smblctx)) {
6681 TALLOC_FREE(br_lck);
6682 return status;
6685 TALLOC_FREE(br_lck);
6688 return status;
6691 /****************************************************************************
6692 Deal with SMB_SET_FILE_BASIC_INFO.
6693 ****************************************************************************/
6695 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6696 const char *pdata,
6697 int total_data,
6698 files_struct *fsp,
6699 const struct smb_filename *smb_fname)
6701 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6702 struct smb_file_time ft;
6703 uint32 dosmode = 0;
6704 NTSTATUS status = NT_STATUS_OK;
6706 ZERO_STRUCT(ft);
6708 if (total_data < 36) {
6709 return NT_STATUS_INVALID_PARAMETER;
6712 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6713 if (!NT_STATUS_IS_OK(status)) {
6714 return status;
6717 /* Set the attributes */
6718 dosmode = IVAL(pdata,32);
6719 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6720 if (!NT_STATUS_IS_OK(status)) {
6721 return status;
6724 /* create time */
6725 ft.create_time = interpret_long_date(pdata);
6727 /* access time */
6728 ft.atime = interpret_long_date(pdata+8);
6730 /* write time. */
6731 ft.mtime = interpret_long_date(pdata+16);
6733 /* change time. */
6734 ft.ctime = interpret_long_date(pdata+24);
6736 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6737 smb_fname_str_dbg(smb_fname)));
6739 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6740 true);
6743 /****************************************************************************
6744 Deal with SMB_INFO_STANDARD.
6745 ****************************************************************************/
6747 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6748 const char *pdata,
6749 int total_data,
6750 files_struct *fsp,
6751 const struct smb_filename *smb_fname)
6753 NTSTATUS status;
6754 struct smb_file_time ft;
6756 ZERO_STRUCT(ft);
6758 if (total_data < 12) {
6759 return NT_STATUS_INVALID_PARAMETER;
6762 /* create time */
6763 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6764 /* access time */
6765 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6766 /* write time */
6767 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6769 DEBUG(10,("smb_set_info_standard: file %s\n",
6770 smb_fname_str_dbg(smb_fname)));
6772 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6773 if (!NT_STATUS_IS_OK(status)) {
6774 return status;
6777 return smb_set_file_time(conn,
6778 fsp,
6779 smb_fname,
6780 &ft,
6781 true);
6784 /****************************************************************************
6785 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6786 ****************************************************************************/
6788 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6789 struct smb_request *req,
6790 const char *pdata,
6791 int total_data,
6792 files_struct *fsp,
6793 struct smb_filename *smb_fname)
6795 uint64_t allocation_size = 0;
6796 NTSTATUS status = NT_STATUS_OK;
6797 files_struct *new_fsp = NULL;
6799 if (!VALID_STAT(smb_fname->st)) {
6800 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6803 if (total_data < 8) {
6804 return NT_STATUS_INVALID_PARAMETER;
6807 allocation_size = (uint64_t)IVAL(pdata,0);
6808 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6809 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6810 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6811 (double)allocation_size));
6813 if (allocation_size) {
6814 allocation_size = smb_roundup(conn, allocation_size);
6817 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6818 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6819 (double)allocation_size));
6821 if (fsp && fsp->fh->fd != -1) {
6822 /* Open file handle. */
6823 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6824 return NT_STATUS_ACCESS_DENIED;
6827 /* Only change if needed. */
6828 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6829 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6830 return map_nt_error_from_unix(errno);
6833 /* But always update the time. */
6835 * This is equivalent to a write. Ensure it's seen immediately
6836 * if there are no pending writes.
6838 trigger_write_time_update_immediate(fsp);
6839 return NT_STATUS_OK;
6842 /* Pathname or stat or directory file. */
6843 status = SMB_VFS_CREATE_FILE(
6844 conn, /* conn */
6845 req, /* req */
6846 0, /* root_dir_fid */
6847 smb_fname, /* fname */
6848 FILE_WRITE_DATA, /* access_mask */
6849 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6850 FILE_SHARE_DELETE),
6851 FILE_OPEN, /* create_disposition*/
6852 0, /* create_options */
6853 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6854 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6855 0, /* allocation_size */
6856 0, /* private_flags */
6857 NULL, /* sd */
6858 NULL, /* ea_list */
6859 &new_fsp, /* result */
6860 NULL); /* pinfo */
6862 if (!NT_STATUS_IS_OK(status)) {
6863 /* NB. We check for open_was_deferred in the caller. */
6864 return status;
6867 /* Only change if needed. */
6868 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6869 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6870 status = map_nt_error_from_unix(errno);
6871 close_file(req, new_fsp, NORMAL_CLOSE);
6872 return status;
6876 /* Changing the allocation size should set the last mod time. */
6878 * This is equivalent to a write. Ensure it's seen immediately
6879 * if there are no pending writes.
6881 trigger_write_time_update_immediate(new_fsp);
6883 close_file(req, new_fsp, NORMAL_CLOSE);
6884 return NT_STATUS_OK;
6887 /****************************************************************************
6888 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6889 ****************************************************************************/
6891 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6892 struct smb_request *req,
6893 const char *pdata,
6894 int total_data,
6895 files_struct *fsp,
6896 const struct smb_filename *smb_fname,
6897 bool fail_after_createfile)
6899 off_t size;
6901 if (total_data < 8) {
6902 return NT_STATUS_INVALID_PARAMETER;
6905 size = IVAL(pdata,0);
6906 size |= (((off_t)IVAL(pdata,4)) << 32);
6907 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6908 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6909 (double)size));
6911 return smb_set_file_size(conn, req,
6912 fsp,
6913 smb_fname,
6914 &smb_fname->st,
6915 size,
6916 fail_after_createfile);
6919 /****************************************************************************
6920 Allow a UNIX info mknod.
6921 ****************************************************************************/
6923 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6924 const char *pdata,
6925 int total_data,
6926 const struct smb_filename *smb_fname)
6928 uint32 file_type = IVAL(pdata,56);
6929 #if defined(HAVE_MAKEDEV)
6930 uint32 dev_major = IVAL(pdata,60);
6931 uint32 dev_minor = IVAL(pdata,68);
6932 #endif
6933 SMB_DEV_T dev = (SMB_DEV_T)0;
6934 uint32 raw_unixmode = IVAL(pdata,84);
6935 NTSTATUS status;
6936 mode_t unixmode;
6938 if (total_data < 100) {
6939 return NT_STATUS_INVALID_PARAMETER;
6942 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6943 PERM_NEW_FILE, &unixmode);
6944 if (!NT_STATUS_IS_OK(status)) {
6945 return status;
6948 #if defined(HAVE_MAKEDEV)
6949 dev = makedev(dev_major, dev_minor);
6950 #endif
6952 switch (file_type) {
6953 #if defined(S_IFIFO)
6954 case UNIX_TYPE_FIFO:
6955 unixmode |= S_IFIFO;
6956 break;
6957 #endif
6958 #if defined(S_IFSOCK)
6959 case UNIX_TYPE_SOCKET:
6960 unixmode |= S_IFSOCK;
6961 break;
6962 #endif
6963 #if defined(S_IFCHR)
6964 case UNIX_TYPE_CHARDEV:
6965 unixmode |= S_IFCHR;
6966 break;
6967 #endif
6968 #if defined(S_IFBLK)
6969 case UNIX_TYPE_BLKDEV:
6970 unixmode |= S_IFBLK;
6971 break;
6972 #endif
6973 default:
6974 return NT_STATUS_INVALID_PARAMETER;
6977 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6978 "%.0f mode 0%o for file %s\n", (double)dev,
6979 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6981 /* Ok - do the mknod. */
6982 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6983 return map_nt_error_from_unix(errno);
6986 /* If any of the other "set" calls fail we
6987 * don't want to end up with a half-constructed mknod.
6990 if (lp_inherit_perms(SNUM(conn))) {
6991 char *parent;
6992 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6993 &parent, NULL)) {
6994 return NT_STATUS_NO_MEMORY;
6996 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6997 unixmode);
6998 TALLOC_FREE(parent);
7001 return NT_STATUS_OK;
7004 /****************************************************************************
7005 Deal with SMB_SET_FILE_UNIX_BASIC.
7006 ****************************************************************************/
7008 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7009 struct smb_request *req,
7010 const char *pdata,
7011 int total_data,
7012 files_struct *fsp,
7013 const struct smb_filename *smb_fname)
7015 struct smb_file_time ft;
7016 uint32 raw_unixmode;
7017 mode_t unixmode;
7018 off_t size = 0;
7019 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7020 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7021 NTSTATUS status = NT_STATUS_OK;
7022 bool delete_on_fail = False;
7023 enum perm_type ptype;
7024 files_struct *all_fsps = NULL;
7025 bool modify_mtime = true;
7026 struct file_id id;
7027 struct smb_filename *smb_fname_tmp = NULL;
7028 SMB_STRUCT_STAT sbuf;
7030 ZERO_STRUCT(ft);
7032 if (total_data < 100) {
7033 return NT_STATUS_INVALID_PARAMETER;
7036 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7037 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7038 size=IVAL(pdata,0); /* first 8 Bytes are size */
7039 size |= (((off_t)IVAL(pdata,4)) << 32);
7042 ft.atime = interpret_long_date(pdata+24); /* access_time */
7043 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7044 set_owner = (uid_t)IVAL(pdata,40);
7045 set_grp = (gid_t)IVAL(pdata,48);
7046 raw_unixmode = IVAL(pdata,84);
7048 if (VALID_STAT(smb_fname->st)) {
7049 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7050 ptype = PERM_EXISTING_DIR;
7051 } else {
7052 ptype = PERM_EXISTING_FILE;
7054 } else {
7055 ptype = PERM_NEW_FILE;
7058 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7059 ptype, &unixmode);
7060 if (!NT_STATUS_IS_OK(status)) {
7061 return status;
7064 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7065 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7066 smb_fname_str_dbg(smb_fname), (double)size,
7067 (unsigned int)set_owner, (unsigned int)set_grp,
7068 (int)raw_unixmode));
7070 sbuf = smb_fname->st;
7072 if (!VALID_STAT(sbuf)) {
7074 * The only valid use of this is to create character and block
7075 * devices, and named pipes. This is deprecated (IMHO) and
7076 * a new info level should be used for mknod. JRA.
7079 status = smb_unix_mknod(conn,
7080 pdata,
7081 total_data,
7082 smb_fname);
7083 if (!NT_STATUS_IS_OK(status)) {
7084 return status;
7087 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7088 if (smb_fname_tmp == NULL) {
7089 return NT_STATUS_NO_MEMORY;
7092 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7093 status = map_nt_error_from_unix(errno);
7094 TALLOC_FREE(smb_fname_tmp);
7095 SMB_VFS_UNLINK(conn, smb_fname);
7096 return status;
7099 sbuf = smb_fname_tmp->st;
7100 smb_fname = smb_fname_tmp;
7102 /* Ensure we don't try and change anything else. */
7103 raw_unixmode = SMB_MODE_NO_CHANGE;
7104 size = get_file_size_stat(&sbuf);
7105 ft.atime = sbuf.st_ex_atime;
7106 ft.mtime = sbuf.st_ex_mtime;
7108 * We continue here as we might want to change the
7109 * owner uid/gid.
7111 delete_on_fail = True;
7114 #if 1
7115 /* Horrible backwards compatibility hack as an old server bug
7116 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7117 * */
7119 if (!size) {
7120 size = get_file_size_stat(&sbuf);
7122 #endif
7125 * Deal with the UNIX specific mode set.
7128 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7129 int ret;
7131 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7132 "setting mode 0%o for file %s\n",
7133 (unsigned int)unixmode,
7134 smb_fname_str_dbg(smb_fname)));
7135 if (fsp && fsp->fh->fd != -1) {
7136 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7137 } else {
7138 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7140 if (ret != 0) {
7141 return map_nt_error_from_unix(errno);
7146 * Deal with the UNIX specific uid set.
7149 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7150 (sbuf.st_ex_uid != set_owner)) {
7151 int ret;
7153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7154 "changing owner %u for path %s\n",
7155 (unsigned int)set_owner,
7156 smb_fname_str_dbg(smb_fname)));
7158 if (S_ISLNK(sbuf.st_ex_mode)) {
7159 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7160 set_owner, (gid_t)-1);
7161 } else {
7162 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7163 set_owner, (gid_t)-1);
7166 if (ret != 0) {
7167 status = map_nt_error_from_unix(errno);
7168 if (delete_on_fail) {
7169 SMB_VFS_UNLINK(conn, smb_fname);
7171 return status;
7176 * Deal with the UNIX specific gid set.
7179 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7180 (sbuf.st_ex_gid != set_grp)) {
7181 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7182 "changing group %u for file %s\n",
7183 (unsigned int)set_owner,
7184 smb_fname_str_dbg(smb_fname)));
7185 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7186 set_grp) != 0) {
7187 status = map_nt_error_from_unix(errno);
7188 if (delete_on_fail) {
7189 SMB_VFS_UNLINK(conn, smb_fname);
7191 return status;
7195 /* Deal with any size changes. */
7197 status = smb_set_file_size(conn, req,
7198 fsp,
7199 smb_fname,
7200 &sbuf,
7201 size,
7202 false);
7203 if (!NT_STATUS_IS_OK(status)) {
7204 return status;
7207 /* Deal with any time changes. */
7208 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7209 /* No change, don't cancel anything. */
7210 return status;
7213 id = vfs_file_id_from_sbuf(conn, &sbuf);
7214 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7215 all_fsps = file_find_di_next(all_fsps)) {
7217 * We're setting the time explicitly for UNIX.
7218 * Cancel any pending changes over all handles.
7220 all_fsps->update_write_time_on_close = false;
7221 TALLOC_FREE(all_fsps->update_write_time_event);
7225 * Override the "setting_write_time"
7226 * parameter here as it almost does what
7227 * we need. Just remember if we modified
7228 * mtime and send the notify ourselves.
7230 if (null_timespec(ft.mtime)) {
7231 modify_mtime = false;
7234 status = smb_set_file_time(conn,
7235 fsp,
7236 smb_fname,
7237 &ft,
7238 false);
7239 if (modify_mtime) {
7240 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7241 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7243 return status;
7246 /****************************************************************************
7247 Deal with SMB_SET_FILE_UNIX_INFO2.
7248 ****************************************************************************/
7250 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7251 struct smb_request *req,
7252 const char *pdata,
7253 int total_data,
7254 files_struct *fsp,
7255 const struct smb_filename *smb_fname)
7257 NTSTATUS status;
7258 uint32 smb_fflags;
7259 uint32 smb_fmask;
7261 if (total_data < 116) {
7262 return NT_STATUS_INVALID_PARAMETER;
7265 /* Start by setting all the fields that are common between UNIX_BASIC
7266 * and UNIX_INFO2.
7268 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7269 fsp, smb_fname);
7270 if (!NT_STATUS_IS_OK(status)) {
7271 return status;
7274 smb_fflags = IVAL(pdata, 108);
7275 smb_fmask = IVAL(pdata, 112);
7277 /* NB: We should only attempt to alter the file flags if the client
7278 * sends a non-zero mask.
7280 if (smb_fmask != 0) {
7281 int stat_fflags = 0;
7283 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7284 smb_fmask, &stat_fflags)) {
7285 /* Client asked to alter a flag we don't understand. */
7286 return NT_STATUS_INVALID_PARAMETER;
7289 if (fsp && fsp->fh->fd != -1) {
7290 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7291 return NT_STATUS_NOT_SUPPORTED;
7292 } else {
7293 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7294 stat_fflags) != 0) {
7295 return map_nt_error_from_unix(errno);
7300 /* XXX: need to add support for changing the create_time here. You
7301 * can do this for paths on Darwin with setattrlist(2). The right way
7302 * to hook this up is probably by extending the VFS utimes interface.
7305 return NT_STATUS_OK;
7308 /****************************************************************************
7309 Create a directory with POSIX semantics.
7310 ****************************************************************************/
7312 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7313 struct smb_request *req,
7314 char **ppdata,
7315 int total_data,
7316 struct smb_filename *smb_fname,
7317 int *pdata_return_size)
7319 NTSTATUS status = NT_STATUS_OK;
7320 uint32 raw_unixmode = 0;
7321 uint32 mod_unixmode = 0;
7322 mode_t unixmode = (mode_t)0;
7323 files_struct *fsp = NULL;
7324 uint16 info_level_return = 0;
7325 int info;
7326 char *pdata = *ppdata;
7328 if (total_data < 18) {
7329 return NT_STATUS_INVALID_PARAMETER;
7332 raw_unixmode = IVAL(pdata,8);
7333 /* Next 4 bytes are not yet defined. */
7335 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7336 PERM_NEW_DIR, &unixmode);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 return status;
7341 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7343 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7344 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7346 status = SMB_VFS_CREATE_FILE(
7347 conn, /* conn */
7348 req, /* req */
7349 0, /* root_dir_fid */
7350 smb_fname, /* fname */
7351 FILE_READ_ATTRIBUTES, /* access_mask */
7352 FILE_SHARE_NONE, /* share_access */
7353 FILE_CREATE, /* create_disposition*/
7354 FILE_DIRECTORY_FILE, /* create_options */
7355 mod_unixmode, /* file_attributes */
7356 0, /* oplock_request */
7357 0, /* allocation_size */
7358 0, /* private_flags */
7359 NULL, /* sd */
7360 NULL, /* ea_list */
7361 &fsp, /* result */
7362 &info); /* pinfo */
7364 if (NT_STATUS_IS_OK(status)) {
7365 close_file(req, fsp, NORMAL_CLOSE);
7368 info_level_return = SVAL(pdata,16);
7370 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7371 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7372 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7373 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7374 } else {
7375 *pdata_return_size = 12;
7378 /* Realloc the data size */
7379 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7380 if (*ppdata == NULL) {
7381 *pdata_return_size = 0;
7382 return NT_STATUS_NO_MEMORY;
7384 pdata = *ppdata;
7386 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7387 SSVAL(pdata,2,0); /* No fnum. */
7388 SIVAL(pdata,4,info); /* Was directory created. */
7390 switch (info_level_return) {
7391 case SMB_QUERY_FILE_UNIX_BASIC:
7392 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7393 SSVAL(pdata,10,0); /* Padding. */
7394 store_file_unix_basic(conn, pdata + 12, fsp,
7395 &smb_fname->st);
7396 break;
7397 case SMB_QUERY_FILE_UNIX_INFO2:
7398 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7399 SSVAL(pdata,10,0); /* Padding. */
7400 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7401 &smb_fname->st);
7402 break;
7403 default:
7404 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7405 SSVAL(pdata,10,0); /* Padding. */
7406 break;
7409 return status;
7412 /****************************************************************************
7413 Open/Create a file with POSIX semantics.
7414 ****************************************************************************/
7416 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7417 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7419 static NTSTATUS smb_posix_open(connection_struct *conn,
7420 struct smb_request *req,
7421 char **ppdata,
7422 int total_data,
7423 struct smb_filename *smb_fname,
7424 int *pdata_return_size)
7426 bool extended_oplock_granted = False;
7427 char *pdata = *ppdata;
7428 uint32 flags = 0;
7429 uint32 wire_open_mode = 0;
7430 uint32 raw_unixmode = 0;
7431 uint32 mod_unixmode = 0;
7432 uint32 create_disp = 0;
7433 uint32 access_mask = 0;
7434 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7435 NTSTATUS status = NT_STATUS_OK;
7436 mode_t unixmode = (mode_t)0;
7437 files_struct *fsp = NULL;
7438 int oplock_request = 0;
7439 int info = 0;
7440 uint16 info_level_return = 0;
7442 if (total_data < 18) {
7443 return NT_STATUS_INVALID_PARAMETER;
7446 flags = IVAL(pdata,0);
7447 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7448 if (oplock_request) {
7449 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7452 wire_open_mode = IVAL(pdata,4);
7454 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7455 return smb_posix_mkdir(conn, req,
7456 ppdata,
7457 total_data,
7458 smb_fname,
7459 pdata_return_size);
7462 switch (wire_open_mode & SMB_ACCMODE) {
7463 case SMB_O_RDONLY:
7464 access_mask = SMB_O_RDONLY_MAPPING;
7465 break;
7466 case SMB_O_WRONLY:
7467 access_mask = SMB_O_WRONLY_MAPPING;
7468 break;
7469 case SMB_O_RDWR:
7470 access_mask = (SMB_O_RDONLY_MAPPING|
7471 SMB_O_WRONLY_MAPPING);
7472 break;
7473 default:
7474 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7475 (unsigned int)wire_open_mode ));
7476 return NT_STATUS_INVALID_PARAMETER;
7479 wire_open_mode &= ~SMB_ACCMODE;
7481 /* First take care of O_CREAT|O_EXCL interactions. */
7482 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7483 case (SMB_O_CREAT | SMB_O_EXCL):
7484 /* File exists fail. File not exist create. */
7485 create_disp = FILE_CREATE;
7486 break;
7487 case SMB_O_CREAT:
7488 /* File exists open. File not exist create. */
7489 create_disp = FILE_OPEN_IF;
7490 break;
7491 case SMB_O_EXCL:
7492 /* O_EXCL on its own without O_CREAT is undefined.
7493 We deliberately ignore it as some versions of
7494 Linux CIFSFS can send a bare O_EXCL on the
7495 wire which other filesystems in the kernel
7496 ignore. See bug 9519 for details. */
7498 /* Fallthrough. */
7500 case 0:
7501 /* File exists open. File not exist fail. */
7502 create_disp = FILE_OPEN;
7503 break;
7504 default:
7505 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7506 (unsigned int)wire_open_mode ));
7507 return NT_STATUS_INVALID_PARAMETER;
7510 /* Next factor in the effects of O_TRUNC. */
7511 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7513 if (wire_open_mode & SMB_O_TRUNC) {
7514 switch (create_disp) {
7515 case FILE_CREATE:
7516 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7517 /* Leave create_disp alone as
7518 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7520 /* File exists fail. File not exist create. */
7521 break;
7522 case FILE_OPEN_IF:
7523 /* SMB_O_CREAT | SMB_O_TRUNC */
7524 /* File exists overwrite. File not exist create. */
7525 create_disp = FILE_OVERWRITE_IF;
7526 break;
7527 case FILE_OPEN:
7528 /* SMB_O_TRUNC */
7529 /* File exists overwrite. File not exist fail. */
7530 create_disp = FILE_OVERWRITE;
7531 break;
7532 default:
7533 /* Cannot get here. */
7534 smb_panic("smb_posix_open: logic error");
7535 return NT_STATUS_INVALID_PARAMETER;
7539 raw_unixmode = IVAL(pdata,8);
7540 /* Next 4 bytes are not yet defined. */
7542 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7543 (VALID_STAT(smb_fname->st) ?
7544 PERM_EXISTING_FILE : PERM_NEW_FILE),
7545 &unixmode);
7547 if (!NT_STATUS_IS_OK(status)) {
7548 return status;
7551 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7553 if (wire_open_mode & SMB_O_SYNC) {
7554 create_options |= FILE_WRITE_THROUGH;
7556 if (wire_open_mode & SMB_O_APPEND) {
7557 access_mask |= FILE_APPEND_DATA;
7559 if (wire_open_mode & SMB_O_DIRECT) {
7560 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7563 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7564 VALID_STAT_OF_DIR(smb_fname->st)) {
7565 if (access_mask != SMB_O_RDONLY_MAPPING) {
7566 return NT_STATUS_FILE_IS_A_DIRECTORY;
7568 create_options &= ~FILE_NON_DIRECTORY_FILE;
7569 create_options |= FILE_DIRECTORY_FILE;
7572 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7573 smb_fname_str_dbg(smb_fname),
7574 (unsigned int)wire_open_mode,
7575 (unsigned int)unixmode ));
7577 status = SMB_VFS_CREATE_FILE(
7578 conn, /* conn */
7579 req, /* req */
7580 0, /* root_dir_fid */
7581 smb_fname, /* fname */
7582 access_mask, /* access_mask */
7583 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7584 FILE_SHARE_DELETE),
7585 create_disp, /* create_disposition*/
7586 create_options, /* create_options */
7587 mod_unixmode, /* file_attributes */
7588 oplock_request, /* oplock_request */
7589 0, /* allocation_size */
7590 0, /* private_flags */
7591 NULL, /* sd */
7592 NULL, /* ea_list */
7593 &fsp, /* result */
7594 &info); /* pinfo */
7596 if (!NT_STATUS_IS_OK(status)) {
7597 return status;
7600 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7601 extended_oplock_granted = True;
7604 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7605 extended_oplock_granted = True;
7608 info_level_return = SVAL(pdata,16);
7610 /* Allocate the correct return size. */
7612 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7613 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7614 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7615 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7616 } else {
7617 *pdata_return_size = 12;
7620 /* Realloc the data size */
7621 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7622 if (*ppdata == NULL) {
7623 close_file(req, fsp, ERROR_CLOSE);
7624 *pdata_return_size = 0;
7625 return NT_STATUS_NO_MEMORY;
7627 pdata = *ppdata;
7629 if (extended_oplock_granted) {
7630 if (flags & REQUEST_BATCH_OPLOCK) {
7631 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7632 } else {
7633 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7635 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7636 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7637 } else {
7638 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7641 SSVAL(pdata,2,fsp->fnum);
7642 SIVAL(pdata,4,info); /* Was file created etc. */
7644 switch (info_level_return) {
7645 case SMB_QUERY_FILE_UNIX_BASIC:
7646 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7647 SSVAL(pdata,10,0); /* padding. */
7648 store_file_unix_basic(conn, pdata + 12, fsp,
7649 &smb_fname->st);
7650 break;
7651 case SMB_QUERY_FILE_UNIX_INFO2:
7652 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7653 SSVAL(pdata,10,0); /* padding. */
7654 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7655 &smb_fname->st);
7656 break;
7657 default:
7658 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7659 SSVAL(pdata,10,0); /* padding. */
7660 break;
7662 return NT_STATUS_OK;
7665 /****************************************************************************
7666 Delete a file with POSIX semantics.
7667 ****************************************************************************/
7669 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7670 struct smb_request *req,
7671 const char *pdata,
7672 int total_data,
7673 struct smb_filename *smb_fname)
7675 NTSTATUS status = NT_STATUS_OK;
7676 files_struct *fsp = NULL;
7677 uint16 flags = 0;
7678 char del = 1;
7679 int info = 0;
7680 int create_options = 0;
7681 int i;
7682 struct share_mode_lock *lck = NULL;
7684 if (total_data < 2) {
7685 return NT_STATUS_INVALID_PARAMETER;
7688 flags = SVAL(pdata,0);
7690 if (!VALID_STAT(smb_fname->st)) {
7691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7694 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7695 !VALID_STAT_OF_DIR(smb_fname->st)) {
7696 return NT_STATUS_NOT_A_DIRECTORY;
7699 DEBUG(10,("smb_posix_unlink: %s %s\n",
7700 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7701 smb_fname_str_dbg(smb_fname)));
7703 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7704 create_options |= FILE_DIRECTORY_FILE;
7707 status = SMB_VFS_CREATE_FILE(
7708 conn, /* conn */
7709 req, /* req */
7710 0, /* root_dir_fid */
7711 smb_fname, /* fname */
7712 DELETE_ACCESS, /* access_mask */
7713 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7714 FILE_SHARE_DELETE),
7715 FILE_OPEN, /* create_disposition*/
7716 create_options, /* create_options */
7717 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7718 0, /* oplock_request */
7719 0, /* allocation_size */
7720 0, /* private_flags */
7721 NULL, /* sd */
7722 NULL, /* ea_list */
7723 &fsp, /* result */
7724 &info); /* pinfo */
7726 if (!NT_STATUS_IS_OK(status)) {
7727 return status;
7731 * Don't lie to client. If we can't really delete due to
7732 * non-POSIX opens return SHARING_VIOLATION.
7735 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7736 if (lck == NULL) {
7737 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7738 "lock for file %s\n", fsp_str_dbg(fsp)));
7739 close_file(req, fsp, NORMAL_CLOSE);
7740 return NT_STATUS_INVALID_PARAMETER;
7744 * See if others still have the file open. If this is the case, then
7745 * don't delete. If all opens are POSIX delete we can set the delete
7746 * on close disposition.
7748 for (i=0; i<lck->data->num_share_modes; i++) {
7749 struct share_mode_entry *e = &lck->data->share_modes[i];
7750 if (is_valid_share_mode_entry(e)) {
7751 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7752 continue;
7754 if (share_mode_stale_pid(lck->data, i)) {
7755 continue;
7757 /* Fail with sharing violation. */
7758 TALLOC_FREE(lck);
7759 close_file(req, fsp, NORMAL_CLOSE);
7760 return NT_STATUS_SHARING_VIOLATION;
7765 * Set the delete on close.
7767 status = smb_set_file_disposition_info(conn,
7768 &del,
7770 fsp,
7771 smb_fname);
7773 TALLOC_FREE(lck);
7775 if (!NT_STATUS_IS_OK(status)) {
7776 close_file(req, fsp, NORMAL_CLOSE);
7777 return status;
7779 return close_file(req, fsp, NORMAL_CLOSE);
7782 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7783 struct smb_request *req,
7784 TALLOC_CTX *mem_ctx,
7785 uint16_t info_level,
7786 files_struct *fsp,
7787 struct smb_filename *smb_fname,
7788 char **ppdata, int total_data,
7789 int *ret_data_size)
7791 char *pdata = *ppdata;
7792 NTSTATUS status = NT_STATUS_OK;
7793 int data_return_size = 0;
7795 *ret_data_size = 0;
7797 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7798 return NT_STATUS_INVALID_LEVEL;
7801 if (!CAN_WRITE(conn)) {
7802 /* Allow POSIX opens. The open path will deny
7803 * any non-readonly opens. */
7804 if (info_level != SMB_POSIX_PATH_OPEN) {
7805 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7809 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7810 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7811 fsp_fnum_dbg(fsp),
7812 info_level, total_data));
7814 switch (info_level) {
7816 case SMB_INFO_STANDARD:
7818 status = smb_set_info_standard(conn,
7819 pdata,
7820 total_data,
7821 fsp,
7822 smb_fname);
7823 break;
7826 case SMB_INFO_SET_EA:
7828 status = smb_info_set_ea(conn,
7829 pdata,
7830 total_data,
7831 fsp,
7832 smb_fname);
7833 break;
7836 case SMB_SET_FILE_BASIC_INFO:
7837 case SMB_FILE_BASIC_INFORMATION:
7839 status = smb_set_file_basic_info(conn,
7840 pdata,
7841 total_data,
7842 fsp,
7843 smb_fname);
7844 break;
7847 case SMB_FILE_ALLOCATION_INFORMATION:
7848 case SMB_SET_FILE_ALLOCATION_INFO:
7850 status = smb_set_file_allocation_info(conn, req,
7851 pdata,
7852 total_data,
7853 fsp,
7854 smb_fname);
7855 break;
7858 case SMB_FILE_END_OF_FILE_INFORMATION:
7859 case SMB_SET_FILE_END_OF_FILE_INFO:
7862 * XP/Win7 both fail after the createfile with
7863 * SMB_SET_FILE_END_OF_FILE_INFO but not
7864 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7865 * The level is known here, so pass it down
7866 * appropriately.
7868 bool should_fail =
7869 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7871 status = smb_set_file_end_of_file_info(conn, req,
7872 pdata,
7873 total_data,
7874 fsp,
7875 smb_fname,
7876 should_fail);
7877 break;
7880 case SMB_FILE_DISPOSITION_INFORMATION:
7881 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7883 #if 0
7884 /* JRA - We used to just ignore this on a path ?
7885 * Shouldn't this be invalid level on a pathname
7886 * based call ?
7888 if (tran_call != TRANSACT2_SETFILEINFO) {
7889 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7891 #endif
7892 status = smb_set_file_disposition_info(conn,
7893 pdata,
7894 total_data,
7895 fsp,
7896 smb_fname);
7897 break;
7900 case SMB_FILE_POSITION_INFORMATION:
7902 status = smb_file_position_information(conn,
7903 pdata,
7904 total_data,
7905 fsp);
7906 break;
7909 case SMB_FILE_FULL_EA_INFORMATION:
7911 status = smb_set_file_full_ea_info(conn,
7912 pdata,
7913 total_data,
7914 fsp);
7915 break;
7918 /* From tridge Samba4 :
7919 * MODE_INFORMATION in setfileinfo (I have no
7920 * idea what "mode information" on a file is - it takes a value of 0,
7921 * 2, 4 or 6. What could it be?).
7924 case SMB_FILE_MODE_INFORMATION:
7926 status = smb_file_mode_information(conn,
7927 pdata,
7928 total_data);
7929 break;
7933 * CIFS UNIX extensions.
7936 case SMB_SET_FILE_UNIX_BASIC:
7938 status = smb_set_file_unix_basic(conn, req,
7939 pdata,
7940 total_data,
7941 fsp,
7942 smb_fname);
7943 break;
7946 case SMB_SET_FILE_UNIX_INFO2:
7948 status = smb_set_file_unix_info2(conn, req,
7949 pdata,
7950 total_data,
7951 fsp,
7952 smb_fname);
7953 break;
7956 case SMB_SET_FILE_UNIX_LINK:
7958 if (fsp) {
7959 /* We must have a pathname for this. */
7960 return NT_STATUS_INVALID_LEVEL;
7962 status = smb_set_file_unix_link(conn, req, pdata,
7963 total_data, smb_fname);
7964 break;
7967 case SMB_SET_FILE_UNIX_HLINK:
7969 if (fsp) {
7970 /* We must have a pathname for this. */
7971 return NT_STATUS_INVALID_LEVEL;
7973 status = smb_set_file_unix_hlink(conn, req,
7974 pdata, total_data,
7975 smb_fname);
7976 break;
7979 case SMB_FILE_RENAME_INFORMATION:
7981 status = smb_file_rename_information(conn, req,
7982 pdata, total_data,
7983 fsp, smb_fname);
7984 break;
7987 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7989 /* SMB2 rename information. */
7990 status = smb2_file_rename_information(conn, req,
7991 pdata, total_data,
7992 fsp, smb_fname);
7993 break;
7996 case SMB_FILE_LINK_INFORMATION:
7998 status = smb_file_link_information(conn, req,
7999 pdata, total_data,
8000 fsp, smb_fname);
8001 break;
8004 #if defined(HAVE_POSIX_ACLS)
8005 case SMB_SET_POSIX_ACL:
8007 status = smb_set_posix_acl(conn,
8008 pdata,
8009 total_data,
8010 fsp,
8011 smb_fname);
8012 break;
8014 #endif
8016 case SMB_SET_POSIX_LOCK:
8018 if (!fsp) {
8019 return NT_STATUS_INVALID_LEVEL;
8021 status = smb_set_posix_lock(conn, req,
8022 pdata, total_data, fsp);
8023 break;
8026 case SMB_POSIX_PATH_OPEN:
8028 if (fsp) {
8029 /* We must have a pathname for this. */
8030 return NT_STATUS_INVALID_LEVEL;
8033 status = smb_posix_open(conn, req,
8034 ppdata,
8035 total_data,
8036 smb_fname,
8037 &data_return_size);
8038 break;
8041 case SMB_POSIX_PATH_UNLINK:
8043 if (fsp) {
8044 /* We must have a pathname for this. */
8045 return NT_STATUS_INVALID_LEVEL;
8048 status = smb_posix_unlink(conn, req,
8049 pdata,
8050 total_data,
8051 smb_fname);
8052 break;
8055 default:
8056 return NT_STATUS_INVALID_LEVEL;
8059 if (!NT_STATUS_IS_OK(status)) {
8060 return status;
8063 *ret_data_size = data_return_size;
8064 return NT_STATUS_OK;
8067 /****************************************************************************
8068 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8069 ****************************************************************************/
8071 static void call_trans2setfilepathinfo(connection_struct *conn,
8072 struct smb_request *req,
8073 unsigned int tran_call,
8074 char **pparams, int total_params,
8075 char **ppdata, int total_data,
8076 unsigned int max_data_bytes)
8078 char *params = *pparams;
8079 char *pdata = *ppdata;
8080 uint16 info_level;
8081 struct smb_filename *smb_fname = NULL;
8082 files_struct *fsp = NULL;
8083 NTSTATUS status = NT_STATUS_OK;
8084 int data_return_size = 0;
8086 if (!params) {
8087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8088 return;
8091 if (tran_call == TRANSACT2_SETFILEINFO) {
8092 if (total_params < 4) {
8093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8094 return;
8097 fsp = file_fsp(req, SVAL(params,0));
8098 /* Basic check for non-null fsp. */
8099 if (!check_fsp_open(conn, req, fsp)) {
8100 return;
8102 info_level = SVAL(params,2);
8104 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8105 if (smb_fname == NULL) {
8106 reply_nterror(req, NT_STATUS_NO_MEMORY);
8107 return;
8110 if(fsp->fh->fd == -1) {
8112 * This is actually a SETFILEINFO on a directory
8113 * handle (returned from an NT SMB). NT5.0 seems
8114 * to do this call. JRA.
8116 if (INFO_LEVEL_IS_UNIX(info_level)) {
8117 /* Always do lstat for UNIX calls. */
8118 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8119 DEBUG(3,("call_trans2setfilepathinfo: "
8120 "SMB_VFS_LSTAT of %s failed "
8121 "(%s)\n",
8122 smb_fname_str_dbg(smb_fname),
8123 strerror(errno)));
8124 reply_nterror(req, map_nt_error_from_unix(errno));
8125 return;
8127 } else {
8128 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8129 DEBUG(3,("call_trans2setfilepathinfo: "
8130 "fileinfo of %s failed (%s)\n",
8131 smb_fname_str_dbg(smb_fname),
8132 strerror(errno)));
8133 reply_nterror(req, map_nt_error_from_unix(errno));
8134 return;
8137 } else if (fsp->print_file) {
8139 * Doing a DELETE_ON_CLOSE should cancel a print job.
8141 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8142 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8144 DEBUG(3,("call_trans2setfilepathinfo: "
8145 "Cancelling print job (%s)\n",
8146 fsp_str_dbg(fsp)));
8148 SSVAL(params,0,0);
8149 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8150 *ppdata, 0,
8151 max_data_bytes);
8152 return;
8153 } else {
8154 reply_nterror(req,
8155 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8156 return;
8158 } else {
8160 * Original code - this is an open file.
8162 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8163 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8164 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8165 strerror(errno)));
8166 reply_nterror(req, map_nt_error_from_unix(errno));
8167 return;
8170 } else {
8171 char *fname = NULL;
8172 uint32_t ucf_flags = 0;
8174 /* set path info */
8175 if (total_params < 7) {
8176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8177 return;
8180 info_level = SVAL(params,0);
8181 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8182 total_params - 6, STR_TERMINATE,
8183 &status);
8184 if (!NT_STATUS_IS_OK(status)) {
8185 reply_nterror(req, status);
8186 return;
8189 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8190 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8191 info_level == SMB_FILE_RENAME_INFORMATION ||
8192 info_level == SMB_POSIX_PATH_UNLINK) {
8193 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8196 status = filename_convert(req, conn,
8197 req->flags2 & FLAGS2_DFS_PATHNAMES,
8198 fname,
8199 ucf_flags,
8200 NULL,
8201 &smb_fname);
8202 if (!NT_STATUS_IS_OK(status)) {
8203 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8204 reply_botherror(req,
8205 NT_STATUS_PATH_NOT_COVERED,
8206 ERRSRV, ERRbadpath);
8207 return;
8209 reply_nterror(req, status);
8210 return;
8213 if (INFO_LEVEL_IS_UNIX(info_level)) {
8215 * For CIFS UNIX extensions the target name may not exist.
8218 /* Always do lstat for UNIX calls. */
8219 SMB_VFS_LSTAT(conn, smb_fname);
8221 } else if (!VALID_STAT(smb_fname->st) &&
8222 SMB_VFS_STAT(conn, smb_fname)) {
8223 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8224 "%s failed (%s)\n",
8225 smb_fname_str_dbg(smb_fname),
8226 strerror(errno)));
8227 reply_nterror(req, map_nt_error_from_unix(errno));
8228 return;
8232 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8233 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8234 fsp_fnum_dbg(fsp),
8235 info_level,total_data));
8237 /* Realloc the parameter size */
8238 *pparams = (char *)SMB_REALLOC(*pparams,2);
8239 if (*pparams == NULL) {
8240 reply_nterror(req, NT_STATUS_NO_MEMORY);
8241 return;
8243 params = *pparams;
8245 SSVAL(params,0,0);
8247 status = smbd_do_setfilepathinfo(conn, req, req,
8248 info_level,
8249 fsp,
8250 smb_fname,
8251 ppdata, total_data,
8252 &data_return_size);
8253 if (!NT_STATUS_IS_OK(status)) {
8254 if (open_was_deferred(req->sconn, req->mid)) {
8255 /* We have re-scheduled this call. */
8256 return;
8258 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8259 /* We have re-scheduled this call. */
8260 return;
8262 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8263 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8264 ERRSRV, ERRbadpath);
8265 return;
8267 if (info_level == SMB_POSIX_PATH_OPEN) {
8268 reply_openerror(req, status);
8269 return;
8273 * Invalid EA name needs to return 2 param bytes,
8274 * not a zero-length error packet.
8276 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8277 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8278 max_data_bytes);
8279 } else {
8280 reply_nterror(req, status);
8282 return;
8285 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8286 max_data_bytes);
8288 return;
8291 /****************************************************************************
8292 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8293 ****************************************************************************/
8295 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8296 char **pparams, int total_params,
8297 char **ppdata, int total_data,
8298 unsigned int max_data_bytes)
8300 struct smb_filename *smb_dname = NULL;
8301 char *params = *pparams;
8302 char *pdata = *ppdata;
8303 char *directory = NULL;
8304 NTSTATUS status = NT_STATUS_OK;
8305 struct ea_list *ea_list = NULL;
8306 TALLOC_CTX *ctx = talloc_tos();
8308 if (!CAN_WRITE(conn)) {
8309 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8310 return;
8313 if (total_params < 5) {
8314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8315 return;
8318 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8319 total_params - 4, STR_TERMINATE,
8320 &status);
8321 if (!NT_STATUS_IS_OK(status)) {
8322 reply_nterror(req, status);
8323 return;
8326 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8328 status = filename_convert(ctx,
8329 conn,
8330 req->flags2 & FLAGS2_DFS_PATHNAMES,
8331 directory,
8333 NULL,
8334 &smb_dname);
8336 if (!NT_STATUS_IS_OK(status)) {
8337 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8338 reply_botherror(req,
8339 NT_STATUS_PATH_NOT_COVERED,
8340 ERRSRV, ERRbadpath);
8341 return;
8343 reply_nterror(req, status);
8344 return;
8348 * OS/2 workplace shell seems to send SET_EA requests of "null"
8349 * length (4 bytes containing IVAL 4).
8350 * They seem to have no effect. Bug #3212. JRA.
8353 if (total_data && (total_data != 4)) {
8354 /* Any data in this call is an EA list. */
8355 if (total_data < 10) {
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 goto out;
8360 if (IVAL(pdata,0) > total_data) {
8361 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8362 IVAL(pdata,0), (unsigned int)total_data));
8363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8364 goto out;
8367 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8368 total_data - 4);
8369 if (!ea_list) {
8370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8371 goto out;
8374 if (!lp_ea_support(SNUM(conn))) {
8375 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8376 goto out;
8379 /* If total_data == 4 Windows doesn't care what values
8380 * are placed in that field, it just ignores them.
8381 * The System i QNTC IBM SMB client puts bad values here,
8382 * so ignore them. */
8384 status = create_directory(conn, req, smb_dname);
8386 if (!NT_STATUS_IS_OK(status)) {
8387 reply_nterror(req, status);
8388 goto out;
8391 /* Try and set any given EA. */
8392 if (ea_list) {
8393 status = set_ea(conn, NULL, smb_dname, ea_list);
8394 if (!NT_STATUS_IS_OK(status)) {
8395 reply_nterror(req, status);
8396 goto out;
8400 /* Realloc the parameter and data sizes */
8401 *pparams = (char *)SMB_REALLOC(*pparams,2);
8402 if(*pparams == NULL) {
8403 reply_nterror(req, NT_STATUS_NO_MEMORY);
8404 goto out;
8406 params = *pparams;
8408 SSVAL(params,0,0);
8410 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8412 out:
8413 TALLOC_FREE(smb_dname);
8414 return;
8417 /****************************************************************************
8418 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8419 We don't actually do this - we just send a null response.
8420 ****************************************************************************/
8422 static void call_trans2findnotifyfirst(connection_struct *conn,
8423 struct smb_request *req,
8424 char **pparams, int total_params,
8425 char **ppdata, int total_data,
8426 unsigned int max_data_bytes)
8428 char *params = *pparams;
8429 uint16 info_level;
8431 if (total_params < 6) {
8432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8433 return;
8436 info_level = SVAL(params,4);
8437 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8439 switch (info_level) {
8440 case 1:
8441 case 2:
8442 break;
8443 default:
8444 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8445 return;
8448 /* Realloc the parameter and data sizes */
8449 *pparams = (char *)SMB_REALLOC(*pparams,6);
8450 if (*pparams == NULL) {
8451 reply_nterror(req, NT_STATUS_NO_MEMORY);
8452 return;
8454 params = *pparams;
8456 SSVAL(params,0,fnf_handle);
8457 SSVAL(params,2,0); /* No changes */
8458 SSVAL(params,4,0); /* No EA errors */
8460 fnf_handle++;
8462 if(fnf_handle == 0)
8463 fnf_handle = 257;
8465 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8467 return;
8470 /****************************************************************************
8471 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8472 changes). Currently this does nothing.
8473 ****************************************************************************/
8475 static void call_trans2findnotifynext(connection_struct *conn,
8476 struct smb_request *req,
8477 char **pparams, int total_params,
8478 char **ppdata, int total_data,
8479 unsigned int max_data_bytes)
8481 char *params = *pparams;
8483 DEBUG(3,("call_trans2findnotifynext\n"));
8485 /* Realloc the parameter and data sizes */
8486 *pparams = (char *)SMB_REALLOC(*pparams,4);
8487 if (*pparams == NULL) {
8488 reply_nterror(req, NT_STATUS_NO_MEMORY);
8489 return;
8491 params = *pparams;
8493 SSVAL(params,0,0); /* No changes */
8494 SSVAL(params,2,0); /* No EA errors */
8496 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8498 return;
8501 /****************************************************************************
8502 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8503 ****************************************************************************/
8505 static void call_trans2getdfsreferral(connection_struct *conn,
8506 struct smb_request *req,
8507 char **pparams, int total_params,
8508 char **ppdata, int total_data,
8509 unsigned int max_data_bytes)
8511 char *params = *pparams;
8512 char *pathname = NULL;
8513 int reply_size = 0;
8514 int max_referral_level;
8515 NTSTATUS status = NT_STATUS_OK;
8516 TALLOC_CTX *ctx = talloc_tos();
8518 DEBUG(10,("call_trans2getdfsreferral\n"));
8520 if (total_params < 3) {
8521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8522 return;
8525 max_referral_level = SVAL(params,0);
8527 if(!lp_host_msdfs()) {
8528 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8529 return;
8532 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8533 total_params - 2, STR_TERMINATE);
8534 if (!pathname) {
8535 reply_nterror(req, NT_STATUS_NOT_FOUND);
8536 return;
8538 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8539 ppdata,&status)) < 0) {
8540 reply_nterror(req, status);
8541 return;
8544 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8545 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8546 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8548 return;
8551 #define LMCAT_SPL 0x53
8552 #define LMFUNC_GETJOBID 0x60
8554 /****************************************************************************
8555 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8556 ****************************************************************************/
8558 static void call_trans2ioctl(connection_struct *conn,
8559 struct smb_request *req,
8560 char **pparams, int total_params,
8561 char **ppdata, int total_data,
8562 unsigned int max_data_bytes)
8564 char *pdata = *ppdata;
8565 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8567 /* check for an invalid fid before proceeding */
8569 if (!fsp) {
8570 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8571 return;
8574 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8575 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8576 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8577 if (*ppdata == NULL) {
8578 reply_nterror(req, NT_STATUS_NO_MEMORY);
8579 return;
8581 pdata = *ppdata;
8583 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8584 CAN ACCEPT THIS IN UNICODE. JRA. */
8586 /* Job number */
8587 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8589 srvstr_push(pdata, req->flags2, pdata + 2,
8590 lp_netbios_name(), 15,
8591 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8592 srvstr_push(pdata, req->flags2, pdata+18,
8593 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8594 STR_ASCII|STR_TERMINATE); /* Service name */
8595 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8596 max_data_bytes);
8597 return;
8600 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8601 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8604 /****************************************************************************
8605 Reply to a SMBfindclose (stop trans2 directory search).
8606 ****************************************************************************/
8608 void reply_findclose(struct smb_request *req)
8610 int dptr_num;
8611 struct smbd_server_connection *sconn = req->sconn;
8613 START_PROFILE(SMBfindclose);
8615 if (req->wct < 1) {
8616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8617 END_PROFILE(SMBfindclose);
8618 return;
8621 dptr_num = SVALS(req->vwv+0, 0);
8623 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8625 dptr_close(sconn, &dptr_num);
8627 reply_outbuf(req, 0, 0);
8629 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8631 END_PROFILE(SMBfindclose);
8632 return;
8635 /****************************************************************************
8636 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8637 ****************************************************************************/
8639 void reply_findnclose(struct smb_request *req)
8641 int dptr_num;
8643 START_PROFILE(SMBfindnclose);
8645 if (req->wct < 1) {
8646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8647 END_PROFILE(SMBfindnclose);
8648 return;
8651 dptr_num = SVAL(req->vwv+0, 0);
8653 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8655 /* We never give out valid handles for a
8656 findnotifyfirst - so any dptr_num is ok here.
8657 Just ignore it. */
8659 reply_outbuf(req, 0, 0);
8661 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8663 END_PROFILE(SMBfindnclose);
8664 return;
8667 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8668 struct trans_state *state)
8670 if (get_Protocol() >= PROTOCOL_NT1) {
8671 req->flags2 |= 0x40; /* IS_LONG_NAME */
8672 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8675 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8676 if (state->call != TRANSACT2_QFSINFO &&
8677 state->call != TRANSACT2_SETFSINFO) {
8678 DEBUG(0,("handle_trans2: encryption required "
8679 "with call 0x%x\n",
8680 (unsigned int)state->call));
8681 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8682 return;
8686 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8688 /* Now we must call the relevant TRANS2 function */
8689 switch(state->call) {
8690 case TRANSACT2_OPEN:
8692 START_PROFILE(Trans2_open);
8693 call_trans2open(conn, req,
8694 &state->param, state->total_param,
8695 &state->data, state->total_data,
8696 state->max_data_return);
8697 END_PROFILE(Trans2_open);
8698 break;
8701 case TRANSACT2_FINDFIRST:
8703 START_PROFILE(Trans2_findfirst);
8704 call_trans2findfirst(conn, req,
8705 &state->param, state->total_param,
8706 &state->data, state->total_data,
8707 state->max_data_return);
8708 END_PROFILE(Trans2_findfirst);
8709 break;
8712 case TRANSACT2_FINDNEXT:
8714 START_PROFILE(Trans2_findnext);
8715 call_trans2findnext(conn, req,
8716 &state->param, state->total_param,
8717 &state->data, state->total_data,
8718 state->max_data_return);
8719 END_PROFILE(Trans2_findnext);
8720 break;
8723 case TRANSACT2_QFSINFO:
8725 START_PROFILE(Trans2_qfsinfo);
8726 call_trans2qfsinfo(conn, req,
8727 &state->param, state->total_param,
8728 &state->data, state->total_data,
8729 state->max_data_return);
8730 END_PROFILE(Trans2_qfsinfo);
8731 break;
8734 case TRANSACT2_SETFSINFO:
8736 START_PROFILE(Trans2_setfsinfo);
8737 call_trans2setfsinfo(conn, req,
8738 &state->param, state->total_param,
8739 &state->data, state->total_data,
8740 state->max_data_return);
8741 END_PROFILE(Trans2_setfsinfo);
8742 break;
8745 case TRANSACT2_QPATHINFO:
8746 case TRANSACT2_QFILEINFO:
8748 START_PROFILE(Trans2_qpathinfo);
8749 call_trans2qfilepathinfo(conn, req, state->call,
8750 &state->param, state->total_param,
8751 &state->data, state->total_data,
8752 state->max_data_return);
8753 END_PROFILE(Trans2_qpathinfo);
8754 break;
8757 case TRANSACT2_SETPATHINFO:
8758 case TRANSACT2_SETFILEINFO:
8760 START_PROFILE(Trans2_setpathinfo);
8761 call_trans2setfilepathinfo(conn, req, state->call,
8762 &state->param, state->total_param,
8763 &state->data, state->total_data,
8764 state->max_data_return);
8765 END_PROFILE(Trans2_setpathinfo);
8766 break;
8769 case TRANSACT2_FINDNOTIFYFIRST:
8771 START_PROFILE(Trans2_findnotifyfirst);
8772 call_trans2findnotifyfirst(conn, req,
8773 &state->param, state->total_param,
8774 &state->data, state->total_data,
8775 state->max_data_return);
8776 END_PROFILE(Trans2_findnotifyfirst);
8777 break;
8780 case TRANSACT2_FINDNOTIFYNEXT:
8782 START_PROFILE(Trans2_findnotifynext);
8783 call_trans2findnotifynext(conn, req,
8784 &state->param, state->total_param,
8785 &state->data, state->total_data,
8786 state->max_data_return);
8787 END_PROFILE(Trans2_findnotifynext);
8788 break;
8791 case TRANSACT2_MKDIR:
8793 START_PROFILE(Trans2_mkdir);
8794 call_trans2mkdir(conn, req,
8795 &state->param, state->total_param,
8796 &state->data, state->total_data,
8797 state->max_data_return);
8798 END_PROFILE(Trans2_mkdir);
8799 break;
8802 case TRANSACT2_GET_DFS_REFERRAL:
8804 START_PROFILE(Trans2_get_dfs_referral);
8805 call_trans2getdfsreferral(conn, req,
8806 &state->param, state->total_param,
8807 &state->data, state->total_data,
8808 state->max_data_return);
8809 END_PROFILE(Trans2_get_dfs_referral);
8810 break;
8813 case TRANSACT2_IOCTL:
8815 START_PROFILE(Trans2_ioctl);
8816 call_trans2ioctl(conn, req,
8817 &state->param, state->total_param,
8818 &state->data, state->total_data,
8819 state->max_data_return);
8820 END_PROFILE(Trans2_ioctl);
8821 break;
8824 default:
8825 /* Error in request */
8826 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8827 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8831 /****************************************************************************
8832 Reply to a SMBtrans2.
8833 ****************************************************************************/
8835 void reply_trans2(struct smb_request *req)
8837 connection_struct *conn = req->conn;
8838 unsigned int dsoff;
8839 unsigned int dscnt;
8840 unsigned int psoff;
8841 unsigned int pscnt;
8842 unsigned int tran_call;
8843 struct trans_state *state;
8844 NTSTATUS result;
8846 START_PROFILE(SMBtrans2);
8848 if (req->wct < 14) {
8849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8850 END_PROFILE(SMBtrans2);
8851 return;
8854 dsoff = SVAL(req->vwv+12, 0);
8855 dscnt = SVAL(req->vwv+11, 0);
8856 psoff = SVAL(req->vwv+10, 0);
8857 pscnt = SVAL(req->vwv+9, 0);
8858 tran_call = SVAL(req->vwv+14, 0);
8860 result = allow_new_trans(conn->pending_trans, req->mid);
8861 if (!NT_STATUS_IS_OK(result)) {
8862 DEBUG(2, ("Got invalid trans2 request: %s\n",
8863 nt_errstr(result)));
8864 reply_nterror(req, result);
8865 END_PROFILE(SMBtrans2);
8866 return;
8869 if (IS_IPC(conn)) {
8870 switch (tran_call) {
8871 /* List the allowed trans2 calls on IPC$ */
8872 case TRANSACT2_OPEN:
8873 case TRANSACT2_GET_DFS_REFERRAL:
8874 case TRANSACT2_QFILEINFO:
8875 case TRANSACT2_QFSINFO:
8876 case TRANSACT2_SETFSINFO:
8877 break;
8878 default:
8879 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8880 END_PROFILE(SMBtrans2);
8881 return;
8885 if ((state = talloc(conn, struct trans_state)) == NULL) {
8886 DEBUG(0, ("talloc failed\n"));
8887 reply_nterror(req, NT_STATUS_NO_MEMORY);
8888 END_PROFILE(SMBtrans2);
8889 return;
8892 state->cmd = SMBtrans2;
8894 state->mid = req->mid;
8895 state->vuid = req->vuid;
8896 state->setup_count = SVAL(req->vwv+13, 0);
8897 state->setup = NULL;
8898 state->total_param = SVAL(req->vwv+0, 0);
8899 state->param = NULL;
8900 state->total_data = SVAL(req->vwv+1, 0);
8901 state->data = NULL;
8902 state->max_param_return = SVAL(req->vwv+2, 0);
8903 state->max_data_return = SVAL(req->vwv+3, 0);
8904 state->max_setup_return = SVAL(req->vwv+4, 0);
8905 state->close_on_completion = BITSETW(req->vwv+5, 0);
8906 state->one_way = BITSETW(req->vwv+5, 1);
8908 state->call = tran_call;
8910 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8911 is so as a sanity check */
8912 if (state->setup_count != 1) {
8914 * Need to have rc=0 for ioctl to get job id for OS/2.
8915 * Network printing will fail if function is not successful.
8916 * Similar function in reply.c will be used if protocol
8917 * is LANMAN1.0 instead of LM1.2X002.
8918 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8919 * outbuf doesn't have to be set(only job id is used).
8921 if ( (state->setup_count == 4)
8922 && (tran_call == TRANSACT2_IOCTL)
8923 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8924 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8925 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8926 } else {
8927 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8928 DEBUG(2,("Transaction is %d\n",tran_call));
8929 TALLOC_FREE(state);
8930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8931 END_PROFILE(SMBtrans2);
8932 return;
8936 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8937 goto bad_param;
8939 if (state->total_data) {
8941 if (trans_oob(state->total_data, 0, dscnt)
8942 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8943 goto bad_param;
8946 /* Can't use talloc here, the core routines do realloc on the
8947 * params and data. */
8948 state->data = (char *)SMB_MALLOC(state->total_data);
8949 if (state->data == NULL) {
8950 DEBUG(0,("reply_trans2: data malloc fail for %u "
8951 "bytes !\n", (unsigned int)state->total_data));
8952 TALLOC_FREE(state);
8953 reply_nterror(req, NT_STATUS_NO_MEMORY);
8954 END_PROFILE(SMBtrans2);
8955 return;
8958 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8961 if (state->total_param) {
8963 if (trans_oob(state->total_param, 0, pscnt)
8964 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8965 goto bad_param;
8968 /* Can't use talloc here, the core routines do realloc on the
8969 * params and data. */
8970 state->param = (char *)SMB_MALLOC(state->total_param);
8971 if (state->param == NULL) {
8972 DEBUG(0,("reply_trans: param malloc fail for %u "
8973 "bytes !\n", (unsigned int)state->total_param));
8974 SAFE_FREE(state->data);
8975 TALLOC_FREE(state);
8976 reply_nterror(req, NT_STATUS_NO_MEMORY);
8977 END_PROFILE(SMBtrans2);
8978 return;
8981 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8984 state->received_data = dscnt;
8985 state->received_param = pscnt;
8987 if ((state->received_param == state->total_param) &&
8988 (state->received_data == state->total_data)) {
8990 handle_trans2(conn, req, state);
8992 SAFE_FREE(state->data);
8993 SAFE_FREE(state->param);
8994 TALLOC_FREE(state);
8995 END_PROFILE(SMBtrans2);
8996 return;
8999 DLIST_ADD(conn->pending_trans, state);
9001 /* We need to send an interim response then receive the rest
9002 of the parameter/data bytes */
9003 reply_outbuf(req, 0, 0);
9004 show_msg((char *)req->outbuf);
9005 END_PROFILE(SMBtrans2);
9006 return;
9008 bad_param:
9010 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9011 SAFE_FREE(state->data);
9012 SAFE_FREE(state->param);
9013 TALLOC_FREE(state);
9014 END_PROFILE(SMBtrans2);
9015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9019 /****************************************************************************
9020 Reply to a SMBtranss2
9021 ****************************************************************************/
9023 void reply_transs2(struct smb_request *req)
9025 connection_struct *conn = req->conn;
9026 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9027 struct trans_state *state;
9029 START_PROFILE(SMBtranss2);
9031 show_msg((const char *)req->inbuf);
9033 /* Windows clients expect all replies to
9034 a transact secondary (SMBtranss2 0x33)
9035 to have a command code of transact
9036 (SMBtrans2 0x32). See bug #8989
9037 and also [MS-CIFS] section 2.2.4.47.2
9038 for details.
9040 req->cmd = SMBtrans2;
9042 if (req->wct < 8) {
9043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9044 END_PROFILE(SMBtranss2);
9045 return;
9048 for (state = conn->pending_trans; state != NULL;
9049 state = state->next) {
9050 if (state->mid == req->mid) {
9051 break;
9055 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9057 END_PROFILE(SMBtranss2);
9058 return;
9061 /* Revise state->total_param and state->total_data in case they have
9062 changed downwards */
9064 if (SVAL(req->vwv+0, 0) < state->total_param)
9065 state->total_param = SVAL(req->vwv+0, 0);
9066 if (SVAL(req->vwv+1, 0) < state->total_data)
9067 state->total_data = SVAL(req->vwv+1, 0);
9069 pcnt = SVAL(req->vwv+2, 0);
9070 poff = SVAL(req->vwv+3, 0);
9071 pdisp = SVAL(req->vwv+4, 0);
9073 dcnt = SVAL(req->vwv+5, 0);
9074 doff = SVAL(req->vwv+6, 0);
9075 ddisp = SVAL(req->vwv+7, 0);
9077 state->received_param += pcnt;
9078 state->received_data += dcnt;
9080 if ((state->received_data > state->total_data) ||
9081 (state->received_param > state->total_param))
9082 goto bad_param;
9084 if (pcnt) {
9085 if (trans_oob(state->total_param, pdisp, pcnt)
9086 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9087 goto bad_param;
9089 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9092 if (dcnt) {
9093 if (trans_oob(state->total_data, ddisp, dcnt)
9094 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9095 goto bad_param;
9097 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9100 if ((state->received_param < state->total_param) ||
9101 (state->received_data < state->total_data)) {
9102 END_PROFILE(SMBtranss2);
9103 return;
9106 handle_trans2(conn, req, state);
9108 DLIST_REMOVE(conn->pending_trans, state);
9109 SAFE_FREE(state->data);
9110 SAFE_FREE(state->param);
9111 TALLOC_FREE(state);
9113 END_PROFILE(SMBtranss2);
9114 return;
9116 bad_param:
9118 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9119 DLIST_REMOVE(conn->pending_trans, state);
9120 SAFE_FREE(state->data);
9121 SAFE_FREE(state->param);
9122 TALLOC_FREE(state);
9123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9124 END_PROFILE(SMBtranss2);
9125 return;