Convert all uses of uint8/16/32 to _t in source3/smbd.
[Samba.git] / source3 / smbd / trans2.c
blob7dcbe89fcc79b8e7c9c1a26a1f7284812743053f
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"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
53 char *pdata,
54 files_struct *fsp,
55 const SMB_STRUCT_STAT *psbuf);
57 /********************************************************************
58 The canonical "check access" based on object handle or path function.
59 ********************************************************************/
61 NTSTATUS check_access(connection_struct *conn,
62 files_struct *fsp,
63 const struct smb_filename *smb_fname,
64 uint32_t access_mask)
66 if (fsp) {
67 if (!(fsp->access_mask & access_mask)) {
68 return NT_STATUS_ACCESS_DENIED;
70 } else {
71 NTSTATUS status = smbd_check_access_rights(conn,
72 smb_fname,
73 false,
74 access_mask);
75 if (!NT_STATUS_IS_OK(status)) {
76 return status;
79 return NT_STATUS_OK;
82 /********************************************************************
83 Roundup a value to the nearest allocation roundup size boundary.
84 Only do this for Windows clients.
85 ********************************************************************/
87 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
89 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
91 /* Only roundup for Windows clients. */
92 enum remote_arch_types ra_type = get_remote_arch();
93 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
94 val = SMB_ROUNDUP(val,rval);
96 return val;
99 /********************************************************************
100 Create a 64 bit FileIndex. If the file is on the same device as
101 the root of the share, just return the 64-bit inode. If it isn't,
102 mangle as we used to do.
103 ********************************************************************/
105 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
107 uint64_t file_index;
108 if (conn->base_share_dev == psbuf->st_ex_dev) {
109 return (uint64_t)psbuf->st_ex_ino;
111 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
112 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
113 return file_index;
116 /****************************************************************************
117 Utility functions for dealing with extended attributes.
118 ****************************************************************************/
120 /****************************************************************************
121 Refuse to allow clients to overwrite our private xattrs.
122 ****************************************************************************/
124 bool samba_private_attr_name(const char *unix_ea_name)
126 static const char * const prohibited_ea_names[] = {
127 SAMBA_POSIX_INHERITANCE_EA_NAME,
128 SAMBA_XATTR_DOS_ATTRIB,
129 SAMBA_XATTR_MARKER,
130 XATTR_NTACL_NAME,
131 NULL
134 int i;
136 for (i = 0; prohibited_ea_names[i]; i++) {
137 if (strequal( prohibited_ea_names[i], unix_ea_name))
138 return true;
140 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
141 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
142 return true;
144 return false;
147 /****************************************************************************
148 Get one EA value. Fill in a struct ea_struct.
149 ****************************************************************************/
151 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
152 files_struct *fsp, const char *fname,
153 const char *ea_name, struct ea_struct *pea)
155 /* Get the value of this xattr. Max size is 64k. */
156 size_t attr_size = 256;
157 char *val = NULL;
158 ssize_t sizeret;
160 again:
162 val = talloc_realloc(mem_ctx, val, char, attr_size);
163 if (!val) {
164 return NT_STATUS_NO_MEMORY;
167 if (fsp && fsp->fh->fd != -1) {
168 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
169 } else {
170 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
173 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
174 attr_size = 65536;
175 goto again;
178 if (sizeret == -1) {
179 return map_nt_error_from_unix(errno);
182 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
183 dump_data(10, (uint8_t *)val, sizeret);
185 pea->flags = 0;
186 if (strnequal(ea_name, "user.", 5)) {
187 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
188 } else {
189 pea->name = talloc_strdup(mem_ctx, ea_name);
191 if (pea->name == NULL) {
192 TALLOC_FREE(val);
193 return NT_STATUS_NO_MEMORY;
195 pea->value.data = (unsigned char *)val;
196 pea->value.length = (size_t)sizeret;
197 return NT_STATUS_OK;
200 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
201 files_struct *fsp, const char *fname,
202 char ***pnames, size_t *pnum_names)
204 /* Get a list of all xattrs. Max namesize is 64k. */
205 size_t ea_namelist_size = 1024;
206 char *ea_namelist = NULL;
208 char *p;
209 char **names, **tmp;
210 size_t num_names;
211 ssize_t sizeret = -1;
213 if (!lp_ea_support(SNUM(conn))) {
214 if (pnames) {
215 *pnames = NULL;
217 *pnum_names = 0;
218 return NT_STATUS_OK;
222 * TALLOC the result early to get the talloc hierarchy right.
225 names = talloc_array(mem_ctx, char *, 1);
226 if (names == NULL) {
227 DEBUG(0, ("talloc failed\n"));
228 return NT_STATUS_NO_MEMORY;
231 while (ea_namelist_size <= 65536) {
233 ea_namelist = talloc_realloc(
234 names, ea_namelist, char, ea_namelist_size);
235 if (ea_namelist == NULL) {
236 DEBUG(0, ("talloc failed\n"));
237 TALLOC_FREE(names);
238 return NT_STATUS_NO_MEMORY;
241 if (fsp && fsp->fh->fd != -1) {
242 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
243 ea_namelist_size);
244 } else {
245 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
246 ea_namelist_size);
249 if ((sizeret == -1) && (errno == ERANGE)) {
250 ea_namelist_size *= 2;
252 else {
253 break;
257 if (sizeret == -1) {
258 TALLOC_FREE(names);
259 return map_nt_error_from_unix(errno);
262 DEBUG(10, ("%s: ea_namelist size = %u\n",
263 __func__, (unsigned int)sizeret));
265 if (sizeret == 0) {
266 TALLOC_FREE(names);
267 if (pnames) {
268 *pnames = NULL;
270 *pnum_names = 0;
271 return NT_STATUS_OK;
275 * Ensure the result is 0-terminated
278 if (ea_namelist[sizeret-1] != '\0') {
279 TALLOC_FREE(names);
280 return NT_STATUS_INTERNAL_ERROR;
284 * count the names
286 num_names = 0;
288 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
289 num_names += 1;
292 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
293 if (tmp == NULL) {
294 DEBUG(0, ("talloc failed\n"));
295 TALLOC_FREE(names);
296 return NT_STATUS_NO_MEMORY;
299 names = tmp;
300 num_names = 0;
302 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
303 names[num_names++] = p;
306 if (pnames) {
307 *pnames = names;
308 } else {
309 TALLOC_FREE(names);
311 *pnum_names = num_names;
312 return NT_STATUS_OK;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
320 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
322 /* Get a list of all xattrs. Max namesize is 64k. */
323 size_t i, num_names;
324 char **names;
325 struct ea_list *ea_list_head = NULL;
326 NTSTATUS status;
328 *pea_total_len = 0;
329 *ea_list = NULL;
331 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
332 &names, &num_names);
334 if (!NT_STATUS_IS_OK(status)) {
335 return status;
338 if (num_names == 0) {
339 *ea_list = NULL;
340 return NT_STATUS_OK;
343 for (i=0; i<num_names; i++) {
344 struct ea_list *listp;
345 fstring dos_ea_name;
347 if (strnequal(names[i], "system.", 7)
348 || samba_private_attr_name(names[i]))
349 continue;
352 * Filter out any underlying POSIX EA names
353 * that a Windows client can't handle.
355 if (!lp_posix_pathnames() &&
356 is_invalid_windows_ea_name(names[i])) {
357 continue;
360 listp = talloc(mem_ctx, struct ea_list);
361 if (listp == NULL) {
362 return NT_STATUS_NO_MEMORY;
365 status = get_ea_value(listp, conn, fsp,
366 fname, names[i],
367 &listp->ea);
369 if (!NT_STATUS_IS_OK(status)) {
370 TALLOC_FREE(listp);
371 return status;
374 if (listp->ea.value.length == 0) {
376 * We can never return a zero length EA.
377 * Windows reports the EA's as corrupted.
379 TALLOC_FREE(listp);
380 continue;
383 push_ascii_fstring(dos_ea_name, listp->ea.name);
385 *pea_total_len +=
386 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
388 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
389 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
390 (unsigned int)listp->ea.value.length));
392 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
396 /* Add on 4 for total length. */
397 if (*pea_total_len) {
398 *pea_total_len += 4;
401 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
402 (unsigned int)*pea_total_len));
404 *ea_list = ea_list_head;
405 return NT_STATUS_OK;
408 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
409 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
411 *pea_total_len = 0;
412 *ea_list = NULL;
414 if (!lp_ea_support(SNUM(conn))) {
415 return NT_STATUS_OK;
418 if (is_ntfs_stream_smb_fname(smb_fname)) {
419 return NT_STATUS_INVALID_PARAMETER;
422 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
425 /****************************************************************************
426 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
427 that was filled.
428 ****************************************************************************/
430 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
431 connection_struct *conn, struct ea_list *ea_list)
433 unsigned int ret_data_size = 4;
434 char *p = pdata;
436 SMB_ASSERT(total_data_size >= 4);
438 if (!lp_ea_support(SNUM(conn))) {
439 SIVAL(pdata,4,0);
440 return 4;
443 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
444 size_t dos_namelen;
445 fstring dos_ea_name;
446 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
447 dos_namelen = strlen(dos_ea_name);
448 if (dos_namelen > 255 || dos_namelen == 0) {
449 break;
451 if (ea_list->ea.value.length > 65535) {
452 break;
454 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
455 break;
458 /* We know we have room. */
459 SCVAL(p,0,ea_list->ea.flags);
460 SCVAL(p,1,dos_namelen);
461 SSVAL(p,2,ea_list->ea.value.length);
462 strlcpy(p+4, dos_ea_name, dos_namelen+1);
463 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
465 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
469 ret_data_size = PTR_DIFF(p, pdata);
470 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
471 SIVAL(pdata,0,ret_data_size);
472 return ret_data_size;
475 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
476 char *pdata,
477 unsigned int total_data_size,
478 unsigned int *ret_data_size,
479 connection_struct *conn,
480 struct ea_list *ea_list)
482 uint8_t *p = (uint8_t *)pdata;
483 uint8_t *last_start = NULL;
484 bool do_store_data = (pdata != NULL);
486 *ret_data_size = 0;
488 if (!lp_ea_support(SNUM(conn))) {
489 return NT_STATUS_NO_EAS_ON_FILE;
492 for (; ea_list; ea_list = ea_list->next) {
493 size_t dos_namelen;
494 fstring dos_ea_name;
495 size_t this_size;
496 size_t pad = 0;
498 if (last_start != NULL && do_store_data) {
499 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
501 last_start = p;
503 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
504 dos_namelen = strlen(dos_ea_name);
505 if (dos_namelen > 255 || dos_namelen == 0) {
506 return NT_STATUS_INTERNAL_ERROR;
508 if (ea_list->ea.value.length > 65535) {
509 return NT_STATUS_INTERNAL_ERROR;
512 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
514 if (ea_list->next) {
515 pad = (4 - (this_size % 4)) % 4;
516 this_size += pad;
519 if (do_store_data) {
520 if (this_size > total_data_size) {
521 return NT_STATUS_INFO_LENGTH_MISMATCH;
524 /* We know we have room. */
525 SIVAL(p, 0x00, 0); /* next offset */
526 SCVAL(p, 0x04, ea_list->ea.flags);
527 SCVAL(p, 0x05, dos_namelen);
528 SSVAL(p, 0x06, ea_list->ea.value.length);
529 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
530 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
531 if (pad) {
532 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
533 '\0',
534 pad);
536 total_data_size -= this_size;
539 p += this_size;
542 *ret_data_size = PTR_DIFF(p, pdata);
543 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
544 return NT_STATUS_OK;
547 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
549 size_t total_ea_len = 0;
550 TALLOC_CTX *mem_ctx;
551 struct ea_list *ea_list = NULL;
553 if (!lp_ea_support(SNUM(conn))) {
554 return 0;
556 mem_ctx = talloc_stackframe();
558 /* If this is a stream fsp, then we need to instead find the
559 * estimated ea len from the main file, not the stream
560 * (streams cannot have EAs), but the estimate isn't just 0 in
561 * this case! */
562 if (is_ntfs_stream_smb_fname(smb_fname)) {
563 fsp = NULL;
565 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
566 if(conn->sconn->using_smb2) {
567 NTSTATUS status;
568 unsigned int ret_data_size;
570 * We're going to be using fill_ea_chained_buffer() to
571 * marshall EA's - this size is significantly larger
572 * than the SMB1 buffer. Re-calculate the size without
573 * marshalling.
575 status = fill_ea_chained_buffer(mem_ctx,
576 NULL,
578 &ret_data_size,
579 conn,
580 ea_list);
581 if (!NT_STATUS_IS_OK(status)) {
582 ret_data_size = 0;
584 total_ea_len = ret_data_size;
586 TALLOC_FREE(mem_ctx);
587 return total_ea_len;
590 /****************************************************************************
591 Ensure the EA name is case insensitive by matching any existing EA name.
592 ****************************************************************************/
594 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
596 size_t total_ea_len;
597 TALLOC_CTX *mem_ctx = talloc_tos();
598 struct ea_list *ea_list;
599 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
600 if (!NT_STATUS_IS_OK(status)) {
601 return;
604 for (; ea_list; ea_list = ea_list->next) {
605 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
606 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
607 &unix_ea_name[5], ea_list->ea.name));
608 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
609 break;
614 /****************************************************************************
615 Set or delete an extended attribute.
616 ****************************************************************************/
618 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
619 const struct smb_filename *smb_fname, struct ea_list *ea_list)
621 NTSTATUS status;
622 char *fname = NULL;
624 if (!lp_ea_support(SNUM(conn))) {
625 return NT_STATUS_EAS_NOT_SUPPORTED;
628 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
629 if (!NT_STATUS_IS_OK(status)) {
630 return status;
633 /* Setting EAs on streams isn't supported. */
634 if (is_ntfs_stream_smb_fname(smb_fname)) {
635 return NT_STATUS_INVALID_PARAMETER;
639 * Filter out invalid Windows EA names - before
640 * we set *any* of them.
643 if (ea_list_has_invalid_name(ea_list)) {
644 return STATUS_INVALID_EA_NAME;
647 fname = smb_fname->base_name;
649 for (;ea_list; ea_list = ea_list->next) {
650 int ret;
651 fstring unix_ea_name;
653 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
654 fstrcat(unix_ea_name, ea_list->ea.name);
656 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
658 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
660 if (samba_private_attr_name(unix_ea_name)) {
661 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
662 return NT_STATUS_ACCESS_DENIED;
665 if (ea_list->ea.value.length == 0) {
666 /* Remove the attribute. */
667 if (fsp && (fsp->fh->fd != -1)) {
668 DEBUG(10,("set_ea: deleting ea name %s on "
669 "file %s by file descriptor.\n",
670 unix_ea_name, fsp_str_dbg(fsp)));
671 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
672 } else {
673 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
674 unix_ea_name, fname));
675 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
677 #ifdef ENOATTR
678 /* Removing a non existent attribute always succeeds. */
679 if (ret == -1 && errno == ENOATTR) {
680 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
681 unix_ea_name));
682 ret = 0;
684 #endif
685 } else {
686 if (fsp && (fsp->fh->fd != -1)) {
687 DEBUG(10,("set_ea: setting ea name %s on file "
688 "%s by file descriptor.\n",
689 unix_ea_name, fsp_str_dbg(fsp)));
690 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
691 ea_list->ea.value.data, ea_list->ea.value.length, 0);
692 } else {
693 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
694 unix_ea_name, fname));
695 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
700 if (ret == -1) {
701 #ifdef ENOTSUP
702 if (errno == ENOTSUP) {
703 return NT_STATUS_EAS_NOT_SUPPORTED;
705 #endif
706 return map_nt_error_from_unix(errno);
710 return NT_STATUS_OK;
712 /****************************************************************************
713 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
718 struct ea_list *ea_list_head = NULL;
719 size_t converted_size, offset = 0;
721 while (offset + 2 < data_size) {
722 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
723 unsigned int namelen = CVAL(pdata,offset);
725 offset++; /* Go past the namelen byte. */
727 /* integer wrap paranioa. */
728 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
729 (offset > data_size) || (namelen > data_size) ||
730 (offset + namelen >= data_size)) {
731 break;
733 /* Ensure the name is null terminated. */
734 if (pdata[offset + namelen] != '\0') {
735 return NULL;
737 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
738 &converted_size)) {
739 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
740 "failed: %s", strerror(errno)));
742 if (!eal->ea.name) {
743 return NULL;
746 offset += (namelen + 1); /* Go past the name + terminating zero. */
747 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
748 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
751 return ea_list_head;
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
760 struct ea_list *ea_list_head = NULL;
761 size_t offset = 0;
762 size_t bytes_used = 0;
764 while (offset < data_size) {
765 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
767 if (!eal) {
768 return NULL;
771 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
772 offset += bytes_used;
775 return ea_list_head;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list *ealist)
784 fstring dos_ea_name;
785 struct ea_list *listp;
786 size_t ret = 0;
788 for (listp = ealist; listp; listp = listp->next) {
789 push_ascii_fstring(dos_ea_name, listp->ea.name);
790 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
792 /* Add on 4 for total length. */
793 if (ret) {
794 ret += 4;
797 return ret;
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
808 struct ea_list *nlistp, *flistp;
810 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
811 for (flistp = file_list; flistp; flistp = flistp->next) {
812 if (strequal(nlistp->ea.name, flistp->ea.name)) {
813 break;
817 if (flistp) {
818 /* Copy the data from this entry. */
819 nlistp->ea.flags = flistp->ea.flags;
820 nlistp->ea.value = flistp->ea.value;
821 } else {
822 /* Null entry. */
823 nlistp->ea.flags = 0;
824 ZERO_STRUCT(nlistp->ea.value);
828 *total_ea_len = ea_list_size(name_list);
829 return name_list;
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct *conn,
840 struct smb_request *req,
841 NTSTATUS status,
842 const char *params,
843 int paramsize,
844 const char *pdata,
845 int datasize,
846 int max_data_bytes)
848 /* As we are using a protocol > LANMAN1 then the max_send
849 variable must have been set in the sessetupX call.
850 This takes precedence over the max_xmit field in the
851 global struct. These different max_xmit variables should
852 be merged as this is now too confusing */
854 int data_to_send = datasize;
855 int params_to_send = paramsize;
856 int useable_space;
857 const char *pp = params;
858 const char *pd = pdata;
859 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
860 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
861 int data_alignment_offset = 0;
862 bool overflow = False;
863 struct smbXsrv_connection *xconn = req->xconn;
864 int max_send = xconn->smb1.sessions.max_send;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
869 for OS/2. */
871 if (max_data_bytes > 0 && datasize > max_data_bytes) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes, datasize ));
874 datasize = data_to_send = max_data_bytes;
875 overflow = True;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send == 0 && data_to_send == 0) {
881 reply_outbuf(req, 10, 0);
882 if (NT_STATUS_V(status)) {
883 uint8_t eclass;
884 uint32_t ecode;
885 ntstatus_to_dos(status, &eclass, &ecode);
886 error_packet_set((char *)req->outbuf,
887 eclass, ecode, status,
888 __LINE__,__FILE__);
890 show_msg((char *)req->outbuf);
891 if (!srv_send_smb(xconn,
892 (char *)req->outbuf,
893 true, req->seqnum+1,
894 IS_CONN_ENCRYPTED(conn),
895 &req->pcd)) {
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req->outbuf);
899 return;
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send % 4) != 0) && (data_to_send != 0))
907 data_alignment_offset = 4 - (params_to_send % 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space = max_send - (smb_size
914 + 2 * 10 /* wct */
915 + alignment_offset
916 + data_alignment_offset);
918 if (useable_space < 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send || data_to_send) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime = params_to_send + data_to_send;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime = MIN(total_sent_thistime, useable_space);
939 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
940 + data_alignment_offset);
942 /* Set total params and data to be sent */
943 SSVAL(req->outbuf,smb_tprcnt,paramsize);
944 SSVAL(req->outbuf,smb_tdrcnt,datasize);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime = MIN(params_to_send,useable_space);
951 data_sent_thistime = useable_space - params_sent_thistime;
952 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
954 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req->outbuf,smb_proff,
962 ((smb_buf(req->outbuf)+alignment_offset)
963 - smb_base(req->outbuf)));
965 if(params_sent_thistime == 0)
966 SSVAL(req->outbuf,smb_prdisp,0);
967 else
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req->outbuf,smb_prdisp,pp - params);
971 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
972 if(data_sent_thistime == 0) {
973 SSVAL(req->outbuf,smb_droff,0);
974 SSVAL(req->outbuf,smb_drdisp, 0);
975 } else {
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req->outbuf, smb_droff,
979 ((smb_buf(req->outbuf)+alignment_offset)
980 - smb_base(req->outbuf))
981 + params_sent_thistime + data_alignment_offset);
982 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
985 /* Initialize the padding for alignment */
987 if (alignment_offset != 0) {
988 memset(smb_buf(req->outbuf), 0, alignment_offset);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime) {
994 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
995 params_sent_thistime);
998 /* Copy in the data bytes */
999 if(data_sent_thistime) {
1000 if (data_alignment_offset != 0) {
1001 memset((smb_buf(req->outbuf)+alignment_offset+
1002 params_sent_thistime), 0,
1003 data_alignment_offset);
1005 memcpy(smb_buf(req->outbuf)+alignment_offset
1006 +params_sent_thistime+data_alignment_offset,
1007 pd,data_sent_thistime);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime, data_sent_thistime, useable_space));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send, data_to_send, paramsize, datasize));
1015 if (overflow) {
1016 error_packet_set((char *)req->outbuf,
1017 ERRDOS,ERRbufferoverflow,
1018 STATUS_BUFFER_OVERFLOW,
1019 __LINE__,__FILE__);
1020 } else if (NT_STATUS_V(status)) {
1021 uint8_t eclass;
1022 uint32_t ecode;
1023 ntstatus_to_dos(status, &eclass, &ecode);
1024 error_packet_set((char *)req->outbuf,
1025 eclass, ecode, status,
1026 __LINE__,__FILE__);
1029 /* Send the packet */
1030 show_msg((char *)req->outbuf);
1031 if (!srv_send_smb(xconn,
1032 (char *)req->outbuf,
1033 true, req->seqnum+1,
1034 IS_CONN_ENCRYPTED(conn),
1035 &req->pcd))
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req->outbuf);
1040 pp += params_sent_thistime;
1041 pd += data_sent_thistime;
1043 params_to_send -= params_sent_thistime;
1044 data_to_send -= data_sent_thistime;
1046 /* Sanity check */
1047 if(params_to_send < 0 || data_to_send < 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send, data_to_send));
1050 return;
1054 return;
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct *conn,
1062 struct smb_request *req,
1063 char **pparams, int total_params,
1064 char **ppdata, int total_data,
1065 unsigned int max_data_bytes)
1067 struct smb_filename *smb_fname = NULL;
1068 char *params = *pparams;
1069 char *pdata = *ppdata;
1070 int deny_mode;
1071 int32 open_attr;
1072 bool oplock_request;
1073 #if 0
1074 bool return_additional_info;
1075 int16 open_sattr;
1076 time_t open_time;
1077 #endif
1078 int open_ofun;
1079 uint32_t open_size;
1080 char *pname;
1081 char *fname = NULL;
1082 off_t size=0;
1083 int fattr=0,mtime=0;
1084 SMB_INO_T inode = 0;
1085 int smb_action = 0;
1086 files_struct *fsp;
1087 struct ea_list *ea_list = NULL;
1088 uint16_t flags = 0;
1089 NTSTATUS status;
1090 uint32_t access_mask;
1091 uint32_t share_mode;
1092 uint32_t create_disposition;
1093 uint32_t create_options = 0;
1094 uint32_t private_flags = 0;
1095 TALLOC_CTX *ctx = talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params < 29) {
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1103 goto out;
1106 flags = SVAL(params, 0);
1107 deny_mode = SVAL(params, 2);
1108 open_attr = SVAL(params,6);
1109 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1110 if (oplock_request) {
1111 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1114 #if 0
1115 return_additional_info = BITSETW(params,0);
1116 open_sattr = SVAL(params, 4);
1117 open_time = make_unix_date3(params+8);
1118 #endif
1119 open_ofun = SVAL(params,12);
1120 open_size = IVAL(params,14);
1121 pname = &params[28];
1123 if (IS_IPC(conn)) {
1124 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1125 goto out;
1128 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1129 total_params - 28, STR_TERMINATE,
1130 &status);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 reply_nterror(req, status);
1133 goto out;
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1138 (unsigned int)open_ofun, open_size));
1140 status = filename_convert(ctx,
1141 conn,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1143 fname,
1145 NULL,
1146 &smb_fname);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req,
1150 NT_STATUS_PATH_NOT_COVERED,
1151 ERRSRV, ERRbadpath);
1152 goto out;
1154 reply_nterror(req, status);
1155 goto out;
1158 if (open_ofun == 0) {
1159 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1160 goto out;
1163 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1164 open_ofun,
1165 &access_mask, &share_mode,
1166 &create_disposition,
1167 &create_options,
1168 &private_flags)) {
1169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1170 goto out;
1173 /* Any data in this call is an EA list. */
1174 if (total_data && (total_data != 4)) {
1175 if (total_data < 10) {
1176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1177 goto out;
1180 if (IVAL(pdata,0) > total_data) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata,0), (unsigned int)total_data));
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1184 goto out;
1187 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1188 total_data - 4);
1189 if (!ea_list) {
1190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1191 goto out;
1194 if (!lp_ea_support(SNUM(conn))) {
1195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1196 goto out;
1199 if (ea_list_has_invalid_name(ea_list)) {
1200 int param_len = 30;
1201 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1202 if(*pparams == NULL ) {
1203 reply_nterror(req, NT_STATUS_NO_MEMORY);
1204 goto out;
1206 params = *pparams;
1207 memset(params, '\0', param_len);
1208 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1209 params, param_len, NULL, 0, max_data_bytes);
1210 goto out;
1214 status = SMB_VFS_CREATE_FILE(
1215 conn, /* conn */
1216 req, /* req */
1217 0, /* root_dir_fid */
1218 smb_fname, /* fname */
1219 access_mask, /* access_mask */
1220 share_mode, /* share_access */
1221 create_disposition, /* create_disposition*/
1222 create_options, /* create_options */
1223 open_attr, /* file_attributes */
1224 oplock_request, /* oplock_request */
1225 NULL, /* lease */
1226 open_size, /* allocation_size */
1227 private_flags,
1228 NULL, /* sd */
1229 ea_list, /* ea_list */
1230 &fsp, /* result */
1231 &smb_action, /* psbuf */
1232 NULL, NULL); /* create context */
1234 if (!NT_STATUS_IS_OK(status)) {
1235 if (open_was_deferred(req->xconn, req->mid)) {
1236 /* We have re-scheduled this call. */
1237 goto out;
1239 reply_openerror(req, status);
1240 goto out;
1243 size = get_file_size_stat(&smb_fname->st);
1244 fattr = dos_mode(conn, smb_fname);
1245 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1246 inode = smb_fname->st.st_ex_ino;
1247 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1248 close_file(req, fsp, ERROR_CLOSE);
1249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1250 goto out;
1253 /* Realloc the size of parameters and data we will return */
1254 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1255 if(*pparams == NULL ) {
1256 reply_nterror(req, NT_STATUS_NO_MEMORY);
1257 goto out;
1259 params = *pparams;
1261 SSVAL(params,0,fsp->fnum);
1262 SSVAL(params,2,fattr);
1263 srv_put_dos_date2(params,4, mtime);
1264 SIVAL(params,8, (uint32_t)size);
1265 SSVAL(params,12,deny_mode);
1266 SSVAL(params,14,0); /* open_type - file or directory. */
1267 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1269 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1270 smb_action |= EXTENDED_OPLOCK_GRANTED;
1273 SSVAL(params,18,smb_action);
1276 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1278 SIVAL(params,20,inode);
1279 SSVAL(params,24,0); /* Padding. */
1280 if (flags & 8) {
1281 uint32_t ea_size = estimate_ea_size(conn, fsp,
1282 smb_fname);
1283 SIVAL(params, 26, ea_size);
1284 } else {
1285 SIVAL(params, 26, 0);
1288 /* Send the required number of replies */
1289 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1290 out:
1291 TALLOC_FREE(smb_fname);
1294 /*********************************************************
1295 Routine to check if a given string matches exactly.
1296 as a special case a mask of "." does NOT match. That
1297 is required for correct wildcard semantics
1298 Case can be significant or not.
1299 **********************************************************/
1301 static bool exact_match(bool has_wild,
1302 bool case_sensitive,
1303 const char *str,
1304 const char *mask)
1306 if (mask[0] == '.' && mask[1] == 0) {
1307 return false;
1310 if (has_wild) {
1311 return false;
1314 if (case_sensitive) {
1315 return strcmp(str,mask)==0;
1316 } else {
1317 return strcasecmp_m(str,mask) == 0;
1321 /****************************************************************************
1322 Return the filetype for UNIX extensions.
1323 ****************************************************************************/
1325 static uint32_t unix_filetype(mode_t mode)
1327 if(S_ISREG(mode))
1328 return UNIX_TYPE_FILE;
1329 else if(S_ISDIR(mode))
1330 return UNIX_TYPE_DIR;
1331 #ifdef S_ISLNK
1332 else if(S_ISLNK(mode))
1333 return UNIX_TYPE_SYMLINK;
1334 #endif
1335 #ifdef S_ISCHR
1336 else if(S_ISCHR(mode))
1337 return UNIX_TYPE_CHARDEV;
1338 #endif
1339 #ifdef S_ISBLK
1340 else if(S_ISBLK(mode))
1341 return UNIX_TYPE_BLKDEV;
1342 #endif
1343 #ifdef S_ISFIFO
1344 else if(S_ISFIFO(mode))
1345 return UNIX_TYPE_FIFO;
1346 #endif
1347 #ifdef S_ISSOCK
1348 else if(S_ISSOCK(mode))
1349 return UNIX_TYPE_SOCKET;
1350 #endif
1352 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1353 return UNIX_TYPE_UNKNOWN;
1356 /****************************************************************************
1357 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1358 ****************************************************************************/
1360 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1362 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1363 const SMB_STRUCT_STAT *psbuf,
1364 uint32_t perms,
1365 enum perm_type ptype,
1366 mode_t *ret_perms)
1368 mode_t ret = 0;
1370 if (perms == SMB_MODE_NO_CHANGE) {
1371 if (!VALID_STAT(*psbuf)) {
1372 return NT_STATUS_INVALID_PARAMETER;
1373 } else {
1374 *ret_perms = psbuf->st_ex_mode;
1375 return NT_STATUS_OK;
1379 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1380 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1381 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1382 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1383 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1384 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1385 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1386 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1387 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1388 #ifdef S_ISVTX
1389 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1390 #endif
1391 #ifdef S_ISGID
1392 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1393 #endif
1394 #ifdef S_ISUID
1395 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1396 #endif
1398 if (ptype == PERM_NEW_FILE) {
1400 * "create mask"/"force create mode" are
1401 * only applied to new files, not existing ones.
1403 ret &= lp_create_mask(SNUM(conn));
1404 /* Add in force bits */
1405 ret |= lp_force_create_mode(SNUM(conn));
1406 } else if (ptype == PERM_NEW_DIR) {
1408 * "directory mask"/"force directory mode" are
1409 * only applied to new directories, not existing ones.
1411 ret &= lp_directory_mask(SNUM(conn));
1412 /* Add in force bits */
1413 ret |= lp_force_directory_mode(SNUM(conn));
1416 *ret_perms = ret;
1417 return NT_STATUS_OK;
1420 /****************************************************************************
1421 Needed to show the msdfs symlinks as directories. Modifies psbuf
1422 to be a directory if it's a msdfs link.
1423 ****************************************************************************/
1425 static bool check_msdfs_link(connection_struct *conn,
1426 const char *pathname,
1427 SMB_STRUCT_STAT *psbuf)
1429 int saved_errno = errno;
1430 if(lp_host_msdfs() &&
1431 lp_msdfs_root(SNUM(conn)) &&
1432 is_msdfs_link(conn, pathname, psbuf)) {
1434 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1435 "as a directory\n",
1436 pathname));
1437 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1438 errno = saved_errno;
1439 return true;
1441 errno = saved_errno;
1442 return false;
1446 /****************************************************************************
1447 Get a level dependent lanman2 dir entry.
1448 ****************************************************************************/
1450 struct smbd_dirptr_lanman2_state {
1451 connection_struct *conn;
1452 uint32_t info_level;
1453 bool check_mangled_names;
1454 bool has_wild;
1455 bool got_exact_match;
1458 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1459 void *private_data,
1460 const char *dname,
1461 const char *mask,
1462 char **_fname)
1464 struct smbd_dirptr_lanman2_state *state =
1465 (struct smbd_dirptr_lanman2_state *)private_data;
1466 bool ok;
1467 char mangled_name[13]; /* mangled 8.3 name. */
1468 bool got_match;
1469 const char *fname;
1471 /* Mangle fname if it's an illegal name. */
1472 if (mangle_must_mangle(dname, state->conn->params)) {
1474 * Slow path - ensure we can push the original name as UCS2. If
1475 * not, then just don't return this name.
1477 NTSTATUS status;
1478 size_t ret_len = 0;
1479 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1480 uint8_t *tmp = talloc_array(talloc_tos(),
1481 uint8_t,
1482 len);
1484 status = srvstr_push(NULL,
1485 FLAGS2_UNICODE_STRINGS,
1486 tmp,
1487 dname,
1488 len,
1489 STR_TERMINATE,
1490 &ret_len);
1492 TALLOC_FREE(tmp);
1494 if (!NT_STATUS_IS_OK(status)) {
1495 return false;
1498 ok = name_to_8_3(dname, mangled_name,
1499 true, state->conn->params);
1500 if (!ok) {
1501 return false;
1503 fname = mangled_name;
1504 } else {
1505 fname = dname;
1508 got_match = exact_match(state->has_wild,
1509 state->conn->case_sensitive,
1510 fname, mask);
1511 state->got_exact_match = got_match;
1512 if (!got_match) {
1513 got_match = mask_match(fname, mask,
1514 state->conn->case_sensitive);
1517 if(!got_match && state->check_mangled_names &&
1518 !mangle_is_8_3(fname, false, state->conn->params)) {
1520 * It turns out that NT matches wildcards against
1521 * both long *and* short names. This may explain some
1522 * of the wildcard wierdness from old DOS clients
1523 * that some people have been seeing.... JRA.
1525 /* Force the mangling into 8.3. */
1526 ok = name_to_8_3(fname, mangled_name,
1527 false, state->conn->params);
1528 if (!ok) {
1529 return false;
1532 got_match = exact_match(state->has_wild,
1533 state->conn->case_sensitive,
1534 mangled_name, mask);
1535 state->got_exact_match = got_match;
1536 if (!got_match) {
1537 got_match = mask_match(mangled_name, mask,
1538 state->conn->case_sensitive);
1542 if (!got_match) {
1543 return false;
1546 *_fname = talloc_strdup(ctx, fname);
1547 if (*_fname == NULL) {
1548 return false;
1551 return true;
1554 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1555 void *private_data,
1556 struct smb_filename *smb_fname,
1557 uint32_t *_mode)
1559 struct smbd_dirptr_lanman2_state *state =
1560 (struct smbd_dirptr_lanman2_state *)private_data;
1561 bool ms_dfs_link = false;
1562 uint32_t mode = 0;
1564 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1565 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1566 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1567 "Couldn't lstat [%s] (%s)\n",
1568 smb_fname_str_dbg(smb_fname),
1569 strerror(errno)));
1570 return false;
1572 } else if (!VALID_STAT(smb_fname->st) &&
1573 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1574 /* Needed to show the msdfs symlinks as
1575 * directories */
1577 ms_dfs_link = check_msdfs_link(state->conn,
1578 smb_fname->base_name,
1579 &smb_fname->st);
1580 if (!ms_dfs_link) {
1581 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1582 "Couldn't stat [%s] (%s)\n",
1583 smb_fname_str_dbg(smb_fname),
1584 strerror(errno)));
1585 return false;
1589 if (ms_dfs_link) {
1590 mode = dos_mode_msdfs(state->conn, smb_fname);
1591 } else {
1592 mode = dos_mode(state->conn, smb_fname);
1595 *_mode = mode;
1596 return true;
1599 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1600 connection_struct *conn,
1601 uint16_t flags2,
1602 uint32_t info_level,
1603 struct ea_list *name_list,
1604 bool check_mangled_names,
1605 bool requires_resume_key,
1606 uint32_t mode,
1607 const char *fname,
1608 const struct smb_filename *smb_fname,
1609 int space_remaining,
1610 uint8_t align,
1611 bool do_pad,
1612 char *base_data,
1613 char **ppdata,
1614 char *end_data,
1615 uint64_t *last_entry_off)
1617 char *p, *q, *pdata = *ppdata;
1618 uint32_t reskey=0;
1619 uint64_t file_size = 0;
1620 uint64_t allocation_size = 0;
1621 uint64_t file_index = 0;
1622 size_t len = 0;
1623 struct timespec mdate_ts = {0};
1624 struct timespec adate_ts = {0};
1625 struct timespec cdate_ts = {0};
1626 struct timespec create_date_ts = {0};
1627 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1628 char *nameptr;
1629 char *last_entry_ptr;
1630 bool was_8_3;
1631 int off;
1632 int pad = 0;
1633 NTSTATUS status;
1634 struct readdir_attr_data *readdir_attr_data = NULL;
1636 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1637 file_size = get_file_size_stat(&smb_fname->st);
1639 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1641 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1644 return status;
1648 file_index = get_FileIndex(conn, &smb_fname->st);
1650 mdate_ts = smb_fname->st.st_ex_mtime;
1651 adate_ts = smb_fname->st.st_ex_atime;
1652 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1653 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1655 if (lp_dos_filetime_resolution(SNUM(conn))) {
1656 dos_filetime_timespec(&create_date_ts);
1657 dos_filetime_timespec(&mdate_ts);
1658 dos_filetime_timespec(&adate_ts);
1659 dos_filetime_timespec(&cdate_ts);
1662 create_date = convert_timespec_to_time_t(create_date_ts);
1663 mdate = convert_timespec_to_time_t(mdate_ts);
1664 adate = convert_timespec_to_time_t(adate_ts);
1666 /* align the record */
1667 SMB_ASSERT(align >= 1);
1669 off = (int)PTR_DIFF(pdata, base_data);
1670 pad = (off + (align-1)) & ~(align-1);
1671 pad -= off;
1673 if (pad && pad > space_remaining) {
1674 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1675 "for padding (wanted %u, had %d)\n",
1676 (unsigned int)pad,
1677 space_remaining ));
1678 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1681 off += pad;
1682 /* initialize padding to 0 */
1683 if (pad) {
1684 memset(pdata, 0, pad);
1686 space_remaining -= pad;
1688 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1689 space_remaining ));
1691 pdata += pad;
1692 p = pdata;
1693 last_entry_ptr = p;
1695 pad = 0;
1696 off = 0;
1698 switch (info_level) {
1699 case SMB_FIND_INFO_STANDARD:
1700 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1701 if(requires_resume_key) {
1702 SIVAL(p,0,reskey);
1703 p += 4;
1705 srv_put_dos_date2(p,0,create_date);
1706 srv_put_dos_date2(p,4,adate);
1707 srv_put_dos_date2(p,8,mdate);
1708 SIVAL(p,12,(uint32_t)file_size);
1709 SIVAL(p,16,(uint32_t)allocation_size);
1710 SSVAL(p,20,mode);
1711 p += 23;
1712 nameptr = p;
1713 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1714 p += ucs2_align(base_data, p, 0);
1716 status = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE, &len);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 return status;
1722 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1723 if (len > 2) {
1724 SCVAL(nameptr, -1, len - 2);
1725 } else {
1726 SCVAL(nameptr, -1, 0);
1728 } else {
1729 if (len > 1) {
1730 SCVAL(nameptr, -1, len - 1);
1731 } else {
1732 SCVAL(nameptr, -1, 0);
1735 p += len;
1736 break;
1738 case SMB_FIND_EA_SIZE:
1739 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1740 if (requires_resume_key) {
1741 SIVAL(p,0,reskey);
1742 p += 4;
1744 srv_put_dos_date2(p,0,create_date);
1745 srv_put_dos_date2(p,4,adate);
1746 srv_put_dos_date2(p,8,mdate);
1747 SIVAL(p,12,(uint32_t)file_size);
1748 SIVAL(p,16,(uint32_t)allocation_size);
1749 SSVAL(p,20,mode);
1751 unsigned int ea_size = estimate_ea_size(conn, NULL,
1752 smb_fname);
1753 SIVAL(p,22,ea_size); /* Extended attributes */
1755 p += 27;
1756 nameptr = p - 1;
1757 status = srvstr_push(base_data, flags2,
1758 p, fname, PTR_DIFF(end_data, p),
1759 STR_TERMINATE | STR_NOALIGN, &len);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 return status;
1763 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1764 if (len > 2) {
1765 len -= 2;
1766 } else {
1767 len = 0;
1769 } else {
1770 if (len > 1) {
1771 len -= 1;
1772 } else {
1773 len = 0;
1776 SCVAL(nameptr,0,len);
1777 p += len;
1778 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1779 break;
1781 case SMB_FIND_EA_LIST:
1783 struct ea_list *file_list = NULL;
1784 size_t ea_len = 0;
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1787 if (!name_list) {
1788 return NT_STATUS_INVALID_PARAMETER;
1790 if (requires_resume_key) {
1791 SIVAL(p,0,reskey);
1792 p += 4;
1794 srv_put_dos_date2(p,0,create_date);
1795 srv_put_dos_date2(p,4,adate);
1796 srv_put_dos_date2(p,8,mdate);
1797 SIVAL(p,12,(uint32_t)file_size);
1798 SIVAL(p,16,(uint32_t)allocation_size);
1799 SSVAL(p,20,mode);
1800 p += 22; /* p now points to the EA area. */
1802 status = get_ea_list_from_file(ctx, conn, NULL,
1803 smb_fname,
1804 &ea_len, &file_list);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 file_list = NULL;
1808 name_list = ea_list_union(name_list, file_list, &ea_len);
1810 /* We need to determine if this entry will fit in the space available. */
1811 /* Max string size is 255 bytes. */
1812 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1813 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1814 "(wanted %u, had %d)\n",
1815 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1816 space_remaining ));
1817 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1820 /* Push the ea_data followed by the name. */
1821 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1822 nameptr = p;
1823 status = srvstr_push(base_data, flags2,
1824 p + 1, fname, PTR_DIFF(end_data, p+1),
1825 STR_TERMINATE | STR_NOALIGN, &len);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 return status;
1829 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1830 if (len > 2) {
1831 len -= 2;
1832 } else {
1833 len = 0;
1835 } else {
1836 if (len > 1) {
1837 len -= 1;
1838 } else {
1839 len = 0;
1842 SCVAL(nameptr,0,len);
1843 p += len + 1;
1844 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1845 break;
1848 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1850 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1851 p += 4;
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1854 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,mode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1861 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1862 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1863 } else {
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1868 p += 4;
1869 /* Clear the short name buffer. This is
1870 * IMPORTANT as not doing so will trigger
1871 * a Win2k client bug. JRA.
1873 if (!was_8_3 && check_mangled_names) {
1874 char mangled_name[13]; /* mangled 8.3 name. */
1875 if (!name_to_8_3(fname,mangled_name,True,
1876 conn->params)) {
1877 /* Error - mangle failed ! */
1878 memset(mangled_name,'\0',12);
1880 mangled_name[12] = 0;
1881 status = srvstr_push(base_data, flags2,
1882 p+2, mangled_name, 24,
1883 STR_UPPER|STR_UNICODE, &len);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 return status;
1887 if (len < 24) {
1888 memset(p + 2 + len,'\0',24 - len);
1890 SSVAL(p, 0, len);
1891 } else {
1892 memset(p,'\0',26);
1894 p += 2 + 24;
1895 status = srvstr_push(base_data, flags2, p,
1896 fname, PTR_DIFF(end_data, p),
1897 STR_TERMINATE_ASCII, &len);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 return status;
1901 SIVAL(q,0,len);
1902 p += len;
1904 len = PTR_DIFF(p, pdata);
1905 pad = (len + (align-1)) & ~(align-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1911 SIVAL(pdata,0,pad);
1913 * set padding to zero
1915 if (do_pad) {
1916 memset(p, 0, pad - len);
1917 p = pdata + pad;
1918 } else {
1919 p = pdata + len;
1921 break;
1923 case SMB_FIND_FILE_DIRECTORY_INFO:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1925 p += 4;
1926 SIVAL(p,0,reskey); p += 4;
1927 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1930 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1931 SOFF_T(p,0,file_size); p += 8;
1932 SOFF_T(p,0,allocation_size); p += 8;
1933 SIVAL(p,0,mode); p += 4;
1934 status = srvstr_push(base_data, flags2,
1935 p + 4, fname, PTR_DIFF(end_data, p+4),
1936 STR_TERMINATE_ASCII, &len);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 return status;
1940 SIVAL(p,0,len);
1941 p += 4 + len;
1943 len = PTR_DIFF(p, pdata);
1944 pad = (len + (align-1)) & ~(align-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1950 SIVAL(pdata,0,pad);
1952 * set padding to zero
1954 if (do_pad) {
1955 memset(p, 0, pad - len);
1956 p = pdata + pad;
1957 } else {
1958 p = pdata + len;
1960 break;
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1964 p += 4;
1965 SIVAL(p,0,reskey); p += 4;
1966 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1967 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1968 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1969 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1970 SOFF_T(p,0,file_size); p += 8;
1971 SOFF_T(p,0,allocation_size); p += 8;
1972 SIVAL(p,0,mode); p += 4;
1973 q = p; p += 4; /* q is placeholder for name length. */
1975 unsigned int ea_size = estimate_ea_size(conn, NULL,
1976 smb_fname);
1977 SIVAL(p,0,ea_size); /* Extended attributes */
1978 p +=4;
1980 status = srvstr_push(base_data, flags2, p,
1981 fname, PTR_DIFF(end_data, p),
1982 STR_TERMINATE_ASCII, &len);
1983 if (!NT_STATUS_IS_OK(status)) {
1984 return status;
1986 SIVAL(q, 0, len);
1987 p += len;
1989 len = PTR_DIFF(p, pdata);
1990 pad = (len + (align-1)) & ~(align-1);
1992 * offset to the next entry, the caller
1993 * will overwrite it for the last entry
1994 * that's why we always include the padding
1996 SIVAL(pdata,0,pad);
1998 * set padding to zero
2000 if (do_pad) {
2001 memset(p, 0, pad - len);
2002 p = pdata + pad;
2003 } else {
2004 p = pdata + len;
2006 break;
2008 case SMB_FIND_FILE_NAMES_INFO:
2009 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2010 p += 4;
2011 SIVAL(p,0,reskey); p += 4;
2012 p += 4;
2013 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2014 acl on a dir (tridge) */
2015 status = srvstr_push(base_data, flags2, p,
2016 fname, PTR_DIFF(end_data, p),
2017 STR_TERMINATE_ASCII, &len);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 return status;
2021 SIVAL(p, -4, len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2044 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2045 p += 4;
2046 SIVAL(p,0,reskey); p += 4;
2047 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2049 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2051 SOFF_T(p,0,file_size); p += 8;
2052 SOFF_T(p,0,allocation_size); p += 8;
2053 SIVAL(p,0,mode); p += 4;
2054 q = p; p += 4; /* q is placeholder for name length. */
2055 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2056 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2057 } else {
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2059 smb_fname);
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2062 p += 4;
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 status = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII, &len);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 return status;
2071 SIVAL(q, 0, len);
2072 p += len;
2074 len = PTR_DIFF(p, pdata);
2075 pad = (len + (align-1)) & ~(align-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2081 SIVAL(pdata,0,pad);
2083 * set padding to zero
2085 if (do_pad) {
2086 memset(p, 0, pad - len);
2087 p = pdata + pad;
2088 } else {
2089 p = pdata + len;
2091 break;
2093 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2095 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2096 p += 4;
2097 SIVAL(p,0,reskey); p += 4;
2098 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2099 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2100 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2101 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2102 SOFF_T(p,0,file_size); p += 8;
2103 SOFF_T(p,0,allocation_size); p += 8;
2104 SIVAL(p,0,mode); p += 4;
2105 q = p; p += 4; /* q is placeholder for name length */
2106 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2107 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2108 } else if (readdir_attr_data &&
2109 readdir_attr_data->type == RDATTR_AAPL) {
2111 * OS X specific SMB2 extension negotiated via
2112 * AAPL create context: return max_access in
2113 * ea_size field.
2115 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2116 } else {
2117 unsigned int ea_size = estimate_ea_size(conn, NULL,
2118 smb_fname);
2119 SIVAL(p,0,ea_size); /* Extended attributes */
2121 p += 4;
2123 if (readdir_attr_data &&
2124 readdir_attr_data->type == RDATTR_AAPL) {
2126 * OS X specific SMB2 extension negotiated via
2127 * AAPL create context: return resource fork
2128 * length and compressed FinderInfo in
2129 * shortname field.
2131 * According to documentation short_name_len
2132 * should be 0, but on the wire behaviour
2133 * shows its set to 24 by clients.
2135 SSVAL(p, 0, 24);
2137 /* Resourefork length */
2138 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2140 /* Compressed FinderInfo */
2141 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2142 } else if (!was_8_3 && check_mangled_names) {
2143 char mangled_name[13]; /* mangled 8.3 name. */
2144 if (!name_to_8_3(fname,mangled_name,True,
2145 conn->params)) {
2146 /* Error - mangle failed ! */
2147 memset(mangled_name,'\0',12);
2149 mangled_name[12] = 0;
2150 status = srvstr_push(base_data, flags2,
2151 p+2, mangled_name, 24,
2152 STR_UPPER|STR_UNICODE, &len);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 return status;
2156 SSVAL(p, 0, len);
2157 if (len < 24) {
2158 memset(p + 2 + len,'\0',24 - len);
2160 SSVAL(p, 0, len);
2161 } else {
2162 /* Clear the short name buffer. This is
2163 * IMPORTANT as not doing so will trigger
2164 * a Win2k client bug. JRA.
2166 memset(p,'\0',26);
2168 p += 26;
2170 /* Reserved ? */
2171 if (readdir_attr_data &&
2172 readdir_attr_data->type == RDATTR_AAPL) {
2174 * OS X specific SMB2 extension negotiated via
2175 * AAPL create context: return UNIX mode in
2176 * reserved field.
2178 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2179 SSVAL(p, 0, aapl_mode);
2180 } else {
2181 SSVAL(p, 0, 0);
2183 p += 2;
2185 SBVAL(p,0,file_index); p += 8;
2186 status = srvstr_push(base_data, flags2, p,
2187 fname, PTR_DIFF(end_data, p),
2188 STR_TERMINATE_ASCII, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return status;
2192 SIVAL(q,0,len);
2193 p += len;
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2202 SIVAL(pdata,0,pad);
2204 * set padding to zero
2206 if (do_pad) {
2207 memset(p, 0, pad - len);
2208 p = pdata + pad;
2209 } else {
2210 p = pdata + len;
2212 break;
2214 /* CIFS UNIX Extension. */
2216 case SMB_FIND_FILE_UNIX:
2217 case SMB_FIND_FILE_UNIX_INFO2:
2218 p+= 4;
2219 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2221 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (info_level == SMB_FIND_FILE_UNIX) {
2224 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2225 p = store_file_unix_basic(conn, p,
2226 NULL, &smb_fname->st);
2227 status = srvstr_push(base_data, flags2, p,
2228 fname, PTR_DIFF(end_data, p),
2229 STR_TERMINATE, &len);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 return status;
2233 } else {
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2235 p = store_file_unix_basic_info2(conn, p,
2236 NULL, &smb_fname->st);
2237 nameptr = p;
2238 p += 4;
2239 status = srvstr_push(base_data, flags2, p, fname,
2240 PTR_DIFF(end_data, p), 0, &len);
2241 if (!NT_STATUS_IS_OK(status)) {
2242 return status;
2244 SIVAL(nameptr, 0, len);
2247 p += len;
2249 len = PTR_DIFF(p, pdata);
2250 pad = (len + (align-1)) & ~(align-1);
2252 * offset to the next entry, the caller
2253 * will overwrite it for the last entry
2254 * that's why we always include the padding
2256 SIVAL(pdata,0,pad);
2258 * set padding to zero
2260 if (do_pad) {
2261 memset(p, 0, pad - len);
2262 p = pdata + pad;
2263 } else {
2264 p = pdata + len;
2266 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2268 break;
2270 default:
2271 return NT_STATUS_INVALID_LEVEL;
2274 if (PTR_DIFF(p,pdata) > space_remaining) {
2275 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2276 "(wanted %u, had %d)\n",
2277 (unsigned int)PTR_DIFF(p,pdata),
2278 space_remaining ));
2279 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2282 /* Setup the last entry pointer, as an offset from base_data */
2283 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2284 /* Advance the data pointer to the next slot */
2285 *ppdata = p;
2287 return NT_STATUS_OK;
2290 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2291 connection_struct *conn,
2292 struct dptr_struct *dirptr,
2293 uint16_t flags2,
2294 const char *path_mask,
2295 uint32_t dirtype,
2296 int info_level,
2297 int requires_resume_key,
2298 bool dont_descend,
2299 bool ask_sharemode,
2300 uint8_t align,
2301 bool do_pad,
2302 char **ppdata,
2303 char *base_data,
2304 char *end_data,
2305 int space_remaining,
2306 bool *got_exact_match,
2307 int *_last_entry_off,
2308 struct ea_list *name_list)
2310 const char *p;
2311 const char *mask = NULL;
2312 long prev_dirpos = 0;
2313 uint32_t mode = 0;
2314 char *fname = NULL;
2315 struct smb_filename *smb_fname = NULL;
2316 struct smbd_dirptr_lanman2_state state;
2317 bool ok;
2318 uint64_t last_entry_off = 0;
2319 NTSTATUS status;
2321 ZERO_STRUCT(state);
2322 state.conn = conn;
2323 state.info_level = info_level;
2324 state.check_mangled_names = lp_mangled_names(conn->params);
2325 state.has_wild = dptr_has_wild(dirptr);
2326 state.got_exact_match = false;
2328 *got_exact_match = false;
2330 p = strrchr_m(path_mask,'/');
2331 if(p != NULL) {
2332 if(p[1] == '\0') {
2333 mask = "*.*";
2334 } else {
2335 mask = p+1;
2337 } else {
2338 mask = path_mask;
2341 ok = smbd_dirptr_get_entry(ctx,
2342 dirptr,
2343 mask,
2344 dirtype,
2345 dont_descend,
2346 ask_sharemode,
2347 smbd_dirptr_lanman2_match_fn,
2348 smbd_dirptr_lanman2_mode_fn,
2349 &state,
2350 &fname,
2351 &smb_fname,
2352 &mode,
2353 &prev_dirpos);
2354 if (!ok) {
2355 return NT_STATUS_END_OF_FILE;
2358 *got_exact_match = state.got_exact_match;
2360 status = smbd_marshall_dir_entry(ctx,
2361 conn,
2362 flags2,
2363 info_level,
2364 name_list,
2365 state.check_mangled_names,
2366 requires_resume_key,
2367 mode,
2368 fname,
2369 smb_fname,
2370 space_remaining,
2371 align,
2372 do_pad,
2373 base_data,
2374 ppdata,
2375 end_data,
2376 &last_entry_off);
2377 TALLOC_FREE(fname);
2378 TALLOC_FREE(smb_fname);
2379 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2380 dptr_SeekDir(dirptr, prev_dirpos);
2381 return status;
2383 if (!NT_STATUS_IS_OK(status)) {
2384 return status;
2387 *_last_entry_off = last_entry_off;
2388 return NT_STATUS_OK;
2391 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2392 connection_struct *conn,
2393 struct dptr_struct *dirptr,
2394 uint16_t flags2,
2395 const char *path_mask,
2396 uint32_t dirtype,
2397 int info_level,
2398 bool requires_resume_key,
2399 bool dont_descend,
2400 bool ask_sharemode,
2401 char **ppdata,
2402 char *base_data,
2403 char *end_data,
2404 int space_remaining,
2405 bool *got_exact_match,
2406 int *last_entry_off,
2407 struct ea_list *name_list)
2409 uint8_t align = 4;
2410 const bool do_pad = true;
2412 if (info_level >= 1 && info_level <= 3) {
2413 /* No alignment on earlier info levels. */
2414 align = 1;
2417 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2418 path_mask, dirtype, info_level,
2419 requires_resume_key, dont_descend, ask_sharemode,
2420 align, do_pad,
2421 ppdata, base_data, end_data,
2422 space_remaining,
2423 got_exact_match,
2424 last_entry_off, name_list);
2427 /****************************************************************************
2428 Reply to a TRANS2_FINDFIRST.
2429 ****************************************************************************/
2431 static void call_trans2findfirst(connection_struct *conn,
2432 struct smb_request *req,
2433 char **pparams, int total_params,
2434 char **ppdata, int total_data,
2435 unsigned int max_data_bytes)
2437 /* We must be careful here that we don't return more than the
2438 allowed number of data bytes. If this means returning fewer than
2439 maxentries then so be it. We assume that the redirector has
2440 enough room for the fixed number of parameter bytes it has
2441 requested. */
2442 struct smb_filename *smb_dname = NULL;
2443 char *params = *pparams;
2444 char *pdata = *ppdata;
2445 char *data_end;
2446 uint32_t dirtype;
2447 int maxentries;
2448 uint16_t findfirst_flags;
2449 bool close_after_first;
2450 bool close_if_end;
2451 bool requires_resume_key;
2452 int info_level;
2453 char *directory = NULL;
2454 char *mask = NULL;
2455 char *p;
2456 int last_entry_off=0;
2457 int dptr_num = -1;
2458 int numentries = 0;
2459 int i;
2460 bool finished = False;
2461 bool dont_descend = False;
2462 bool out_of_space = False;
2463 int space_remaining;
2464 bool mask_contains_wcard = False;
2465 struct ea_list *ea_list = NULL;
2466 NTSTATUS ntstatus = NT_STATUS_OK;
2467 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2468 TALLOC_CTX *ctx = talloc_tos();
2469 struct dptr_struct *dirptr = NULL;
2470 struct smbd_server_connection *sconn = req->sconn;
2471 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2472 bool backup_priv = false;
2474 if (total_params < 13) {
2475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2476 goto out;
2479 dirtype = SVAL(params,0);
2480 maxentries = SVAL(params,2);
2481 findfirst_flags = SVAL(params,4);
2482 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2483 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2484 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2485 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2486 security_token_has_privilege(get_current_nttok(conn),
2487 SEC_PRIV_BACKUP));
2489 info_level = SVAL(params,6);
2491 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2492 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2493 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2494 (int)backup_priv,
2495 info_level, max_data_bytes));
2497 if (!maxentries) {
2498 /* W2K3 seems to treat zero as 1. */
2499 maxentries = 1;
2502 switch (info_level) {
2503 case SMB_FIND_INFO_STANDARD:
2504 case SMB_FIND_EA_SIZE:
2505 case SMB_FIND_EA_LIST:
2506 case SMB_FIND_FILE_DIRECTORY_INFO:
2507 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2508 case SMB_FIND_FILE_NAMES_INFO:
2509 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2511 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2512 break;
2513 case SMB_FIND_FILE_UNIX:
2514 case SMB_FIND_FILE_UNIX_INFO2:
2515 /* Always use filesystem for UNIX mtime query. */
2516 ask_sharemode = false;
2517 if (!lp_unix_extensions()) {
2518 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2519 goto out;
2521 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2522 break;
2523 default:
2524 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2525 goto out;
2528 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2529 params+12, total_params - 12,
2530 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2531 if (!NT_STATUS_IS_OK(ntstatus)) {
2532 reply_nterror(req, ntstatus);
2533 goto out;
2536 if (backup_priv) {
2537 become_root();
2538 ntstatus = filename_convert_with_privilege(ctx,
2539 conn,
2540 req,
2541 directory,
2542 ucf_flags,
2543 &mask_contains_wcard,
2544 &smb_dname);
2545 } else {
2546 ntstatus = filename_convert(ctx, conn,
2547 req->flags2 & FLAGS2_DFS_PATHNAMES,
2548 directory,
2549 ucf_flags,
2550 &mask_contains_wcard,
2551 &smb_dname);
2554 if (!NT_STATUS_IS_OK(ntstatus)) {
2555 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2556 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2557 ERRSRV, ERRbadpath);
2558 goto out;
2560 reply_nterror(req, ntstatus);
2561 goto out;
2564 mask = smb_dname->original_lcomp;
2566 directory = smb_dname->base_name;
2568 p = strrchr_m(directory,'/');
2569 if(p == NULL) {
2570 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2571 if((directory[0] == '.') && (directory[1] == '\0')) {
2572 mask = talloc_strdup(ctx,"*");
2573 if (!mask) {
2574 reply_nterror(req, NT_STATUS_NO_MEMORY);
2575 goto out;
2577 mask_contains_wcard = True;
2579 } else {
2580 *p = 0;
2583 if (p == NULL || p == directory) {
2584 /* Ensure we don't have a directory name of "". */
2585 directory = talloc_strdup(talloc_tos(), ".");
2586 if (!directory) {
2587 reply_nterror(req, NT_STATUS_NO_MEMORY);
2588 goto out;
2592 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2594 if (info_level == SMB_FIND_EA_LIST) {
2595 uint32_t ea_size;
2597 if (total_data < 4) {
2598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2599 goto out;
2602 ea_size = IVAL(pdata,0);
2603 if (ea_size != total_data) {
2604 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2605 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2607 goto out;
2610 if (!lp_ea_support(SNUM(conn))) {
2611 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2612 goto out;
2615 /* Pull out the list of names. */
2616 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2617 if (!ea_list) {
2618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2619 goto out;
2623 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 goto out;
2628 *ppdata = (char *)SMB_REALLOC(
2629 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2630 if(*ppdata == NULL ) {
2631 reply_nterror(req, NT_STATUS_NO_MEMORY);
2632 goto out;
2634 pdata = *ppdata;
2635 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2637 /* Realloc the params space */
2638 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2639 if (*pparams == NULL) {
2640 reply_nterror(req, NT_STATUS_NO_MEMORY);
2641 goto out;
2643 params = *pparams;
2645 /* Save the wildcard match and attribs we are using on this directory -
2646 needed as lanman2 assumes these are being saved between calls */
2648 ntstatus = dptr_create(conn,
2649 req,
2650 NULL, /* fsp */
2651 directory,
2652 False,
2653 True,
2654 req->smbpid,
2655 mask,
2656 mask_contains_wcard,
2657 dirtype,
2658 &dirptr);
2660 if (!NT_STATUS_IS_OK(ntstatus)) {
2661 reply_nterror(req, ntstatus);
2662 goto out;
2665 if (backup_priv) {
2666 /* Remember this in case we have
2667 to do a findnext. */
2668 dptr_set_priv(dirptr);
2671 dptr_num = dptr_dnum(dirptr);
2672 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2674 /* Initialize per TRANS2_FIND_FIRST operation data */
2675 dptr_init_search_op(dirptr);
2677 /* We don't need to check for VOL here as this is returned by
2678 a different TRANS2 call. */
2680 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2681 directory,lp_dont_descend(ctx, SNUM(conn))));
2682 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2683 dont_descend = True;
2685 p = pdata;
2686 space_remaining = max_data_bytes;
2687 out_of_space = False;
2689 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2690 bool got_exact_match = False;
2692 /* this is a heuristic to avoid seeking the dirptr except when
2693 absolutely necessary. It allows for a filename of about 40 chars */
2694 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2695 out_of_space = True;
2696 finished = False;
2697 } else {
2698 ntstatus = get_lanman2_dir_entry(ctx,
2699 conn,
2700 dirptr,
2701 req->flags2,
2702 mask,dirtype,info_level,
2703 requires_resume_key,dont_descend,
2704 ask_sharemode,
2705 &p,pdata,data_end,
2706 space_remaining,
2707 &got_exact_match,
2708 &last_entry_off, ea_list);
2709 if (NT_STATUS_EQUAL(ntstatus,
2710 NT_STATUS_ILLEGAL_CHARACTER)) {
2712 * Bad character conversion on name. Ignore this
2713 * entry.
2715 continue;
2717 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2718 out_of_space = true;
2719 } else {
2720 finished = !NT_STATUS_IS_OK(ntstatus);
2724 if (!finished && !out_of_space)
2725 numentries++;
2728 * As an optimisation if we know we aren't looking
2729 * for a wildcard name (ie. the name matches the wildcard exactly)
2730 * then we can finish on any (first) match.
2731 * This speeds up large directory searches. JRA.
2734 if(got_exact_match)
2735 finished = True;
2737 /* Ensure space_remaining never goes -ve. */
2738 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2739 space_remaining = 0;
2740 out_of_space = true;
2741 } else {
2742 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2746 /* Check if we can close the dirptr */
2747 if(close_after_first || (finished && close_if_end)) {
2748 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2749 dptr_close(sconn, &dptr_num);
2753 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2754 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2755 * the protocol level is less than NT1. Tested with smbclient. JRA.
2756 * This should fix the OS/2 client bug #2335.
2759 if(numentries == 0) {
2760 dptr_close(sconn, &dptr_num);
2761 if (get_Protocol() < PROTOCOL_NT1) {
2762 reply_force_doserror(req, ERRDOS, ERRnofiles);
2763 goto out;
2764 } else {
2765 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2766 ERRDOS, ERRbadfile);
2767 goto out;
2771 /* At this point pdata points to numentries directory entries. */
2773 /* Set up the return parameter block */
2774 SSVAL(params,0,dptr_num);
2775 SSVAL(params,2,numentries);
2776 SSVAL(params,4,finished);
2777 SSVAL(params,6,0); /* Never an EA error */
2778 SSVAL(params,8,last_entry_off);
2780 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2781 max_data_bytes);
2783 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2784 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2785 if (!directory) {
2786 reply_nterror(req, NT_STATUS_NO_MEMORY);
2790 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2791 smb_fn_name(req->cmd),
2792 mask, directory, dirtype, numentries ) );
2795 * Force a name mangle here to ensure that the
2796 * mask as an 8.3 name is top of the mangled cache.
2797 * The reasons for this are subtle. Don't remove
2798 * this code unless you know what you are doing
2799 * (see PR#13758). JRA.
2802 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2803 char mangled_name[13];
2804 name_to_8_3(mask, mangled_name, True, conn->params);
2806 out:
2808 if (backup_priv) {
2809 unbecome_root();
2812 TALLOC_FREE(smb_dname);
2813 return;
2816 /****************************************************************************
2817 Reply to a TRANS2_FINDNEXT.
2818 ****************************************************************************/
2820 static void call_trans2findnext(connection_struct *conn,
2821 struct smb_request *req,
2822 char **pparams, int total_params,
2823 char **ppdata, int total_data,
2824 unsigned int max_data_bytes)
2826 /* We must be careful here that we don't return more than the
2827 allowed number of data bytes. If this means returning fewer than
2828 maxentries then so be it. We assume that the redirector has
2829 enough room for the fixed number of parameter bytes it has
2830 requested. */
2831 char *params = *pparams;
2832 char *pdata = *ppdata;
2833 char *data_end;
2834 int dptr_num;
2835 int maxentries;
2836 uint16_t info_level;
2837 uint32_t resume_key;
2838 uint16_t findnext_flags;
2839 bool close_after_request;
2840 bool close_if_end;
2841 bool requires_resume_key;
2842 bool continue_bit;
2843 bool mask_contains_wcard = False;
2844 char *resume_name = NULL;
2845 const char *mask = NULL;
2846 const char *directory = NULL;
2847 char *p = NULL;
2848 uint16_t dirtype;
2849 int numentries = 0;
2850 int i, last_entry_off=0;
2851 bool finished = False;
2852 bool dont_descend = False;
2853 bool out_of_space = False;
2854 int space_remaining;
2855 struct ea_list *ea_list = NULL;
2856 NTSTATUS ntstatus = NT_STATUS_OK;
2857 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2858 TALLOC_CTX *ctx = talloc_tos();
2859 struct dptr_struct *dirptr;
2860 struct smbd_server_connection *sconn = req->sconn;
2861 bool backup_priv = false;
2863 if (total_params < 13) {
2864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2865 return;
2868 dptr_num = SVAL(params,0);
2869 maxentries = SVAL(params,2);
2870 info_level = SVAL(params,4);
2871 resume_key = IVAL(params,6);
2872 findnext_flags = SVAL(params,10);
2873 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2874 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2875 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2876 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2878 if (!continue_bit) {
2879 /* We only need resume_name if continue_bit is zero. */
2880 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2881 params+12,
2882 total_params - 12, STR_TERMINATE, &ntstatus,
2883 &mask_contains_wcard);
2884 if (!NT_STATUS_IS_OK(ntstatus)) {
2885 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2886 complain (it thinks we're asking for the directory above the shared
2887 path or an invalid name). Catch this as the resume name is only compared, never used in
2888 a file access. JRA. */
2889 srvstr_pull_talloc(ctx, params, req->flags2,
2890 &resume_name, params+12,
2891 total_params - 12,
2892 STR_TERMINATE);
2894 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2895 reply_nterror(req, ntstatus);
2896 return;
2901 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2902 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2903 resume_key = %d resume name = %s continue=%d level = %d\n",
2904 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2905 requires_resume_key, resume_key,
2906 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2908 if (!maxentries) {
2909 /* W2K3 seems to treat zero as 1. */
2910 maxentries = 1;
2913 switch (info_level) {
2914 case SMB_FIND_INFO_STANDARD:
2915 case SMB_FIND_EA_SIZE:
2916 case SMB_FIND_EA_LIST:
2917 case SMB_FIND_FILE_DIRECTORY_INFO:
2918 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2919 case SMB_FIND_FILE_NAMES_INFO:
2920 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2921 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2922 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2923 break;
2924 case SMB_FIND_FILE_UNIX:
2925 case SMB_FIND_FILE_UNIX_INFO2:
2926 /* Always use filesystem for UNIX mtime query. */
2927 ask_sharemode = false;
2928 if (!lp_unix_extensions()) {
2929 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2930 return;
2932 break;
2933 default:
2934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2935 return;
2938 if (info_level == SMB_FIND_EA_LIST) {
2939 uint32_t ea_size;
2941 if (total_data < 4) {
2942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2943 return;
2946 ea_size = IVAL(pdata,0);
2947 if (ea_size != total_data) {
2948 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2949 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2951 return;
2954 if (!lp_ea_support(SNUM(conn))) {
2955 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2956 return;
2959 /* Pull out the list of names. */
2960 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2961 if (!ea_list) {
2962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2963 return;
2967 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2969 return;
2972 *ppdata = (char *)SMB_REALLOC(
2973 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2974 if(*ppdata == NULL) {
2975 reply_nterror(req, NT_STATUS_NO_MEMORY);
2976 return;
2979 pdata = *ppdata;
2980 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2982 /* Realloc the params space */
2983 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2984 if(*pparams == NULL ) {
2985 reply_nterror(req, NT_STATUS_NO_MEMORY);
2986 return;
2989 params = *pparams;
2991 /* Check that the dptr is valid */
2992 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2993 reply_nterror(req, STATUS_NO_MORE_FILES);
2994 return;
2997 directory = dptr_path(sconn, dptr_num);
2999 /* Get the wildcard mask from the dptr */
3000 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3001 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3002 reply_nterror(req, STATUS_NO_MORE_FILES);
3003 return;
3006 /* Get the attr mask from the dptr */
3007 dirtype = dptr_attr(sconn, dptr_num);
3009 backup_priv = dptr_get_priv(dirptr);
3011 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3012 "backup_priv = %d\n",
3013 dptr_num, mask, dirtype,
3014 (long)dirptr,
3015 dptr_TellDir(dirptr),
3016 (int)backup_priv));
3018 /* Initialize per TRANS2_FIND_NEXT operation data */
3019 dptr_init_search_op(dirptr);
3021 /* We don't need to check for VOL here as this is returned by
3022 a different TRANS2 call. */
3024 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3025 directory,lp_dont_descend(ctx, SNUM(conn))));
3026 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3027 dont_descend = True;
3029 p = pdata;
3030 space_remaining = max_data_bytes;
3031 out_of_space = False;
3033 if (backup_priv) {
3034 become_root();
3038 * Seek to the correct position. We no longer use the resume key but
3039 * depend on the last file name instead.
3042 if(!continue_bit && resume_name && *resume_name) {
3043 SMB_STRUCT_STAT st;
3045 long current_pos = 0;
3047 * Remember, name_to_8_3 is called by
3048 * get_lanman2_dir_entry(), so the resume name
3049 * could be mangled. Ensure we check the unmangled name.
3052 if (mangle_is_mangled(resume_name, conn->params)) {
3053 char *new_resume_name = NULL;
3054 mangle_lookup_name_from_8_3(ctx,
3055 resume_name,
3056 &new_resume_name,
3057 conn->params);
3058 if (new_resume_name) {
3059 resume_name = new_resume_name;
3064 * Fix for NT redirector problem triggered by resume key indexes
3065 * changing between directory scans. We now return a resume key of 0
3066 * and instead look for the filename to continue from (also given
3067 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3068 * findfirst/findnext (as is usual) then the directory pointer
3069 * should already be at the correct place.
3072 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3073 } /* end if resume_name && !continue_bit */
3075 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3076 bool got_exact_match = False;
3078 /* this is a heuristic to avoid seeking the dirptr except when
3079 absolutely necessary. It allows for a filename of about 40 chars */
3080 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3081 out_of_space = True;
3082 finished = False;
3083 } else {
3084 ntstatus = get_lanman2_dir_entry(ctx,
3085 conn,
3086 dirptr,
3087 req->flags2,
3088 mask,dirtype,info_level,
3089 requires_resume_key,dont_descend,
3090 ask_sharemode,
3091 &p,pdata,data_end,
3092 space_remaining,
3093 &got_exact_match,
3094 &last_entry_off, ea_list);
3095 if (NT_STATUS_EQUAL(ntstatus,
3096 NT_STATUS_ILLEGAL_CHARACTER)) {
3098 * Bad character conversion on name. Ignore this
3099 * entry.
3101 continue;
3103 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3104 out_of_space = true;
3105 } else {
3106 finished = !NT_STATUS_IS_OK(ntstatus);
3110 if (!finished && !out_of_space)
3111 numentries++;
3114 * As an optimisation if we know we aren't looking
3115 * for a wildcard name (ie. the name matches the wildcard exactly)
3116 * then we can finish on any (first) match.
3117 * This speeds up large directory searches. JRA.
3120 if(got_exact_match)
3121 finished = True;
3123 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3126 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3127 smb_fn_name(req->cmd),
3128 mask, directory, dirtype, numentries ) );
3130 /* Check if we can close the dirptr */
3131 if(close_after_request || (finished && close_if_end)) {
3132 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3133 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3136 if (backup_priv) {
3137 unbecome_root();
3140 /* Set up the return parameter block */
3141 SSVAL(params,0,numentries);
3142 SSVAL(params,2,finished);
3143 SSVAL(params,4,0); /* Never an EA error */
3144 SSVAL(params,6,last_entry_off);
3146 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3147 max_data_bytes);
3149 return;
3152 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3154 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3155 return objid;
3158 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3160 SMB_ASSERT(extended_info != NULL);
3162 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3163 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3164 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3165 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3166 #ifdef SAMBA_VERSION_REVISION
3167 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3168 #endif
3169 extended_info->samba_subversion = 0;
3170 #ifdef SAMBA_VERSION_RC_RELEASE
3171 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3172 #else
3173 #ifdef SAMBA_VERSION_PRE_RELEASE
3174 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3175 #endif
3176 #endif
3177 #ifdef SAMBA_VERSION_VENDOR_PATCH
3178 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3179 #endif
3180 extended_info->samba_gitcommitdate = 0;
3181 #ifdef SAMBA_VERSION_COMMIT_TIME
3182 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3183 #endif
3185 memset(extended_info->samba_version_string, 0,
3186 sizeof(extended_info->samba_version_string));
3188 snprintf (extended_info->samba_version_string,
3189 sizeof(extended_info->samba_version_string),
3190 "%s", samba_version_string());
3193 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3194 connection_struct *conn,
3195 TALLOC_CTX *mem_ctx,
3196 uint16_t info_level,
3197 uint16_t flags2,
3198 unsigned int max_data_bytes,
3199 size_t *fixed_portion,
3200 struct smb_filename *fname,
3201 char **ppdata,
3202 int *ret_data_len)
3204 char *pdata, *end_data;
3205 int data_len = 0;
3206 size_t len = 0;
3207 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3208 int snum = SNUM(conn);
3209 const char *fstype = lp_fstype(SNUM(conn));
3210 const char *filename = NULL;
3211 const uint64_t bytes_per_sector = 512;
3212 uint32_t additional_flags = 0;
3213 struct smb_filename smb_fname;
3214 SMB_STRUCT_STAT st;
3215 NTSTATUS status = NT_STATUS_OK;
3216 uint64_t df_ret;
3218 if (fname == NULL || fname->base_name == NULL) {
3219 filename = ".";
3220 } else {
3221 filename = fname->base_name;
3224 if (IS_IPC(conn)) {
3225 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3226 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3227 "info level (0x%x) on IPC$.\n",
3228 (unsigned int)info_level));
3229 return NT_STATUS_ACCESS_DENIED;
3233 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3235 ZERO_STRUCT(smb_fname);
3236 smb_fname.base_name = discard_const_p(char, filename);
3238 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3239 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3240 return map_nt_error_from_unix(errno);
3243 st = smb_fname.st;
3245 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3246 return NT_STATUS_INVALID_PARAMETER;
3249 *ppdata = (char *)SMB_REALLOC(
3250 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3251 if (*ppdata == NULL) {
3252 return NT_STATUS_NO_MEMORY;
3255 pdata = *ppdata;
3256 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3257 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3259 *fixed_portion = 0;
3261 switch (info_level) {
3262 case SMB_INFO_ALLOCATION:
3264 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3265 data_len = 18;
3266 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3267 &dsize);
3268 if (df_ret == (uint64_t)-1) {
3269 return map_nt_error_from_unix(errno);
3272 block_size = lp_block_size(snum);
3273 if (bsize < block_size) {
3274 uint64_t factor = block_size/bsize;
3275 bsize = block_size;
3276 dsize /= factor;
3277 dfree /= factor;
3279 if (bsize > block_size) {
3280 uint64_t factor = bsize/block_size;
3281 bsize = block_size;
3282 dsize *= factor;
3283 dfree *= factor;
3285 sectors_per_unit = bsize/bytes_per_sector;
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3291 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3292 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3293 SIVAL(pdata,l1_cUnit,dsize);
3294 SIVAL(pdata,l1_cUnitAvail,dfree);
3295 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3296 break;
3299 case SMB_INFO_VOLUME:
3300 /* Return volume name */
3302 * Add volume serial number - hash of a combination of
3303 * the called hostname and the service name.
3305 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3307 * Win2k3 and previous mess this up by sending a name length
3308 * one byte short. I believe only older clients (OS/2 Win9x) use
3309 * this call so try fixing this by adding a terminating null to
3310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3312 status = srvstr_push(
3313 pdata, flags2,
3314 pdata+l2_vol_szVolLabel, vname,
3315 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3316 STR_NOALIGN|STR_TERMINATE, &len);
3317 if (!NT_STATUS_IS_OK(status)) {
3318 return status;
3320 SCVAL(pdata,l2_vol_cch,len);
3321 data_len = l2_vol_szVolLabel + len;
3322 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3323 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3324 (unsigned)len, vname));
3325 break;
3327 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3328 case SMB_FS_ATTRIBUTE_INFORMATION:
3330 additional_flags = 0;
3331 #if defined(HAVE_SYS_QUOTAS)
3332 additional_flags |= FILE_VOLUME_QUOTAS;
3333 #endif
3335 if(lp_nt_acl_support(SNUM(conn))) {
3336 additional_flags |= FILE_PERSISTENT_ACLS;
3339 /* Capabilities are filled in at connection time through STATVFS call */
3340 additional_flags |= conn->fs_capabilities;
3341 additional_flags |= lp_parm_int(conn->params->service,
3342 "share", "fake_fscaps",
3345 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3346 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3347 additional_flags); /* FS ATTRIBUTES */
3349 SIVAL(pdata,4,255); /* Max filename component length */
3350 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3351 and will think we can't do long filenames */
3352 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3353 PTR_DIFF(end_data, pdata+12),
3354 STR_UNICODE, &len);
3355 if (!NT_STATUS_IS_OK(status)) {
3356 return status;
3358 SIVAL(pdata,8,len);
3359 data_len = 12 + len;
3360 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3361 /* the client only requested a portion of the
3362 file system name */
3363 data_len = max_data_bytes;
3364 status = STATUS_BUFFER_OVERFLOW;
3366 *fixed_portion = 16;
3367 break;
3369 case SMB_QUERY_FS_LABEL_INFO:
3370 case SMB_FS_LABEL_INFORMATION:
3371 status = srvstr_push(pdata, flags2, pdata+4, vname,
3372 PTR_DIFF(end_data, pdata+4), 0, &len);
3373 if (!NT_STATUS_IS_OK(status)) {
3374 return status;
3376 data_len = 4 + len;
3377 SIVAL(pdata,0,len);
3378 break;
3380 case SMB_QUERY_FS_VOLUME_INFO:
3381 case SMB_FS_VOLUME_INFORMATION:
3384 * Add volume serial number - hash of a combination of
3385 * the called hostname and the service name.
3387 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3388 (str_checksum(get_local_machine_name())<<16));
3390 /* Max label len is 32 characters. */
3391 status = srvstr_push(pdata, flags2, pdata+18, vname,
3392 PTR_DIFF(end_data, pdata+18),
3393 STR_UNICODE, &len);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 return status;
3397 SIVAL(pdata,12,len);
3398 data_len = 18+len;
3400 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3401 (int)strlen(vname),vname,
3402 lp_servicename(talloc_tos(), snum)));
3403 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3404 /* the client only requested a portion of the
3405 volume label */
3406 data_len = max_data_bytes;
3407 status = STATUS_BUFFER_OVERFLOW;
3409 *fixed_portion = 24;
3410 break;
3412 case SMB_QUERY_FS_SIZE_INFO:
3413 case SMB_FS_SIZE_INFORMATION:
3415 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3416 data_len = 24;
3417 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3418 &dsize);
3419 if (df_ret == (uint64_t)-1) {
3420 return map_nt_error_from_unix(errno);
3422 block_size = lp_block_size(snum);
3423 if (bsize < block_size) {
3424 uint64_t factor = block_size/bsize;
3425 bsize = block_size;
3426 dsize /= factor;
3427 dfree /= factor;
3429 if (bsize > block_size) {
3430 uint64_t factor = bsize/block_size;
3431 bsize = block_size;
3432 dsize *= factor;
3433 dfree *= factor;
3435 sectors_per_unit = bsize/bytes_per_sector;
3436 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3437 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3438 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3439 SBIG_UINT(pdata,0,dsize);
3440 SBIG_UINT(pdata,8,dfree);
3441 SIVAL(pdata,16,sectors_per_unit);
3442 SIVAL(pdata,20,bytes_per_sector);
3443 *fixed_portion = 24;
3444 break;
3447 case SMB_FS_FULL_SIZE_INFORMATION:
3449 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3450 data_len = 32;
3451 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3452 &dsize);
3453 if (df_ret == (uint64_t)-1) {
3454 return map_nt_error_from_unix(errno);
3456 block_size = lp_block_size(snum);
3457 if (bsize < block_size) {
3458 uint64_t factor = block_size/bsize;
3459 bsize = block_size;
3460 dsize /= factor;
3461 dfree /= factor;
3463 if (bsize > block_size) {
3464 uint64_t factor = bsize/block_size;
3465 bsize = block_size;
3466 dsize *= factor;
3467 dfree *= factor;
3469 sectors_per_unit = bsize/bytes_per_sector;
3470 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3471 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3472 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3473 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3474 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3475 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3476 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3477 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3478 *fixed_portion = 32;
3479 break;
3482 case SMB_QUERY_FS_DEVICE_INFO:
3483 case SMB_FS_DEVICE_INFORMATION:
3485 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3487 if (!CAN_WRITE(conn)) {
3488 characteristics |= FILE_READ_ONLY_DEVICE;
3490 data_len = 8;
3491 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3492 SIVAL(pdata,4,characteristics);
3493 *fixed_portion = 8;
3494 break;
3497 #ifdef HAVE_SYS_QUOTAS
3498 case SMB_FS_QUOTA_INFORMATION:
3500 * what we have to send --metze:
3502 * Unknown1: 24 NULL bytes
3503 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3504 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3505 * Quota Flags: 2 byte :
3506 * Unknown3: 6 NULL bytes
3508 * 48 bytes total
3510 * details for Quota Flags:
3512 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3513 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3514 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3515 * 0x0001 Enable Quotas: enable quota for this fs
3519 /* we need to fake up a fsp here,
3520 * because its not send in this call
3522 files_struct fsp;
3523 SMB_NTQUOTA_STRUCT quotas;
3525 ZERO_STRUCT(fsp);
3526 ZERO_STRUCT(quotas);
3528 fsp.conn = conn;
3529 fsp.fnum = FNUM_FIELD_INVALID;
3531 /* access check */
3532 if (get_current_uid(conn) != 0) {
3533 DEBUG(0,("get_user_quota: access_denied "
3534 "service [%s] user [%s]\n",
3535 lp_servicename(talloc_tos(), SNUM(conn)),
3536 conn->session_info->unix_info->unix_name));
3537 return NT_STATUS_ACCESS_DENIED;
3540 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3541 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3542 return map_nt_error_from_unix(errno);
3545 data_len = 48;
3547 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3548 lp_servicename(talloc_tos(), SNUM(conn))));
3550 /* Unknown1 24 NULL bytes*/
3551 SBIG_UINT(pdata,0,(uint64_t)0);
3552 SBIG_UINT(pdata,8,(uint64_t)0);
3553 SBIG_UINT(pdata,16,(uint64_t)0);
3555 /* Default Soft Quota 8 bytes */
3556 SBIG_UINT(pdata,24,quotas.softlim);
3558 /* Default Hard Quota 8 bytes */
3559 SBIG_UINT(pdata,32,quotas.hardlim);
3561 /* Quota flag 2 bytes */
3562 SSVAL(pdata,40,quotas.qflags);
3564 /* Unknown3 6 NULL bytes */
3565 SSVAL(pdata,42,0);
3566 SIVAL(pdata,44,0);
3568 break;
3570 #endif /* HAVE_SYS_QUOTAS */
3571 case SMB_FS_OBJECTID_INFORMATION:
3573 unsigned char objid[16];
3574 struct smb_extended_info extended_info;
3575 memcpy(pdata,create_volume_objectid(conn, objid),16);
3576 samba_extended_info_version (&extended_info);
3577 SIVAL(pdata,16,extended_info.samba_magic);
3578 SIVAL(pdata,20,extended_info.samba_version);
3579 SIVAL(pdata,24,extended_info.samba_subversion);
3580 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3581 memcpy(pdata+36,extended_info.samba_version_string,28);
3582 data_len = 64;
3583 break;
3586 case SMB_FS_SECTOR_SIZE_INFORMATION:
3588 data_len = 28;
3590 * These values match a physical Windows Server 2012
3591 * share backed by NTFS atop spinning rust.
3593 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3594 /* logical_bytes_per_sector */
3595 SIVAL(pdata, 0, bytes_per_sector);
3596 /* phys_bytes_per_sector_atomic */
3597 SIVAL(pdata, 4, bytes_per_sector);
3598 /* phys_bytes_per_sector_perf */
3599 SIVAL(pdata, 8, bytes_per_sector);
3600 /* fs_effective_phys_bytes_per_sector_atomic */
3601 SIVAL(pdata, 12, bytes_per_sector);
3602 /* flags */
3603 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3604 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3605 /* byte_off_sector_align */
3606 SIVAL(pdata, 20, 0);
3607 /* byte_off_partition_align */
3608 SIVAL(pdata, 24, 0);
3609 *fixed_portion = 28;
3610 break;
3615 * Query the version and capabilities of the CIFS UNIX extensions
3616 * in use.
3619 case SMB_QUERY_CIFS_UNIX_INFO:
3621 bool large_write = lp_min_receive_file_size() &&
3622 !srv_is_signing_active(xconn);
3623 bool large_read = !srv_is_signing_active(xconn);
3624 int encrypt_caps = 0;
3626 if (!lp_unix_extensions()) {
3627 return NT_STATUS_INVALID_LEVEL;
3630 switch (conn->encrypt_level) {
3631 case SMB_SIGNING_OFF:
3632 encrypt_caps = 0;
3633 break;
3634 case SMB_SIGNING_IF_REQUIRED:
3635 case SMB_SIGNING_DEFAULT:
3636 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3637 break;
3638 case SMB_SIGNING_REQUIRED:
3639 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3640 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3641 large_write = false;
3642 large_read = false;
3643 break;
3646 data_len = 12;
3647 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3648 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3650 /* We have POSIX ACLs, pathname, encryption,
3651 * large read/write, and locking capability. */
3653 SBIG_UINT(pdata,4,((uint64_t)(
3654 CIFS_UNIX_POSIX_ACLS_CAP|
3655 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3656 CIFS_UNIX_FCNTL_LOCKS_CAP|
3657 CIFS_UNIX_EXTATTR_CAP|
3658 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3659 encrypt_caps|
3660 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3661 (large_write ?
3662 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3663 break;
3666 case SMB_QUERY_POSIX_FS_INFO:
3668 int rc;
3669 vfs_statvfs_struct svfs;
3671 if (!lp_unix_extensions()) {
3672 return NT_STATUS_INVALID_LEVEL;
3675 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3677 if (!rc) {
3678 data_len = 56;
3679 SIVAL(pdata,0,svfs.OptimalTransferSize);
3680 SIVAL(pdata,4,svfs.BlockSize);
3681 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3682 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3683 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3684 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3685 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3686 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3687 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3688 #ifdef EOPNOTSUPP
3689 } else if (rc == EOPNOTSUPP) {
3690 return NT_STATUS_INVALID_LEVEL;
3691 #endif /* EOPNOTSUPP */
3692 } else {
3693 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3694 return NT_STATUS_DOS(ERRSRV, ERRerror);
3696 break;
3699 case SMB_QUERY_POSIX_WHOAMI:
3701 uint32_t flags = 0;
3702 uint32_t sid_bytes;
3703 int i;
3705 if (!lp_unix_extensions()) {
3706 return NT_STATUS_INVALID_LEVEL;
3709 if (max_data_bytes < 40) {
3710 return NT_STATUS_BUFFER_TOO_SMALL;
3713 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3714 flags |= SMB_WHOAMI_GUEST;
3717 /* NOTE: 8 bytes for UID/GID, irrespective of native
3718 * platform size. This matches
3719 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3721 data_len = 4 /* flags */
3722 + 4 /* flag mask */
3723 + 8 /* uid */
3724 + 8 /* gid */
3725 + 4 /* ngroups */
3726 + 4 /* num_sids */
3727 + 4 /* SID bytes */
3728 + 4 /* pad/reserved */
3729 + (conn->session_info->unix_token->ngroups * 8)
3730 /* groups list */
3731 + (conn->session_info->security_token->num_sids *
3732 SID_MAX_SIZE)
3733 /* SID list */;
3735 SIVAL(pdata, 0, flags);
3736 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3737 SBIG_UINT(pdata, 8,
3738 (uint64_t)conn->session_info->unix_token->uid);
3739 SBIG_UINT(pdata, 16,
3740 (uint64_t)conn->session_info->unix_token->gid);
3743 if (data_len >= max_data_bytes) {
3744 /* Potential overflow, skip the GIDs and SIDs. */
3746 SIVAL(pdata, 24, 0); /* num_groups */
3747 SIVAL(pdata, 28, 0); /* num_sids */
3748 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3749 SIVAL(pdata, 36, 0); /* reserved */
3751 data_len = 40;
3752 break;
3755 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3756 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3758 /* We walk the SID list twice, but this call is fairly
3759 * infrequent, and I don't expect that it's performance
3760 * sensitive -- jpeach
3762 for (i = 0, sid_bytes = 0;
3763 i < conn->session_info->security_token->num_sids; ++i) {
3764 sid_bytes += ndr_size_dom_sid(
3765 &conn->session_info->security_token->sids[i],
3769 /* SID list byte count */
3770 SIVAL(pdata, 32, sid_bytes);
3772 /* 4 bytes pad/reserved - must be zero */
3773 SIVAL(pdata, 36, 0);
3774 data_len = 40;
3776 /* GID list */
3777 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3778 SBIG_UINT(pdata, data_len,
3779 (uint64_t)conn->session_info->unix_token->groups[i]);
3780 data_len += 8;
3783 /* SID list */
3784 for (i = 0;
3785 i < conn->session_info->security_token->num_sids; ++i) {
3786 int sid_len = ndr_size_dom_sid(
3787 &conn->session_info->security_token->sids[i],
3790 sid_linearize(pdata + data_len, sid_len,
3791 &conn->session_info->security_token->sids[i]);
3792 data_len += sid_len;
3795 break;
3798 case SMB_MAC_QUERY_FS_INFO:
3800 * Thursby MAC extension... ONLY on NTFS filesystems
3801 * once we do streams then we don't need this
3803 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3804 data_len = 88;
3805 SIVAL(pdata,84,0x100); /* Don't support mac... */
3806 break;
3808 /* drop through */
3809 default:
3810 return NT_STATUS_INVALID_LEVEL;
3813 *ret_data_len = data_len;
3814 return status;
3817 /****************************************************************************
3818 Reply to a TRANS2_QFSINFO (query filesystem info).
3819 ****************************************************************************/
3821 static void call_trans2qfsinfo(connection_struct *conn,
3822 struct smb_request *req,
3823 char **pparams, int total_params,
3824 char **ppdata, int total_data,
3825 unsigned int max_data_bytes)
3827 char *params = *pparams;
3828 uint16_t info_level;
3829 int data_len = 0;
3830 size_t fixed_portion;
3831 NTSTATUS status;
3833 if (total_params < 2) {
3834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3835 return;
3838 info_level = SVAL(params,0);
3840 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3841 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3842 DEBUG(0,("call_trans2qfsinfo: encryption required "
3843 "and info level 0x%x sent.\n",
3844 (unsigned int)info_level));
3845 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3846 return;
3850 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3852 status = smbd_do_qfsinfo(req->xconn, conn, req,
3853 info_level,
3854 req->flags2,
3855 max_data_bytes,
3856 &fixed_portion,
3857 NULL,
3858 ppdata, &data_len);
3859 if (!NT_STATUS_IS_OK(status)) {
3860 reply_nterror(req, status);
3861 return;
3864 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3865 max_data_bytes);
3867 DEBUG( 4, ( "%s info_level = %d\n",
3868 smb_fn_name(req->cmd), info_level) );
3870 return;
3873 /****************************************************************************
3874 Reply to a TRANS2_SETFSINFO (set filesystem info).
3875 ****************************************************************************/
3877 static void call_trans2setfsinfo(connection_struct *conn,
3878 struct smb_request *req,
3879 char **pparams, int total_params,
3880 char **ppdata, int total_data,
3881 unsigned int max_data_bytes)
3883 struct smbXsrv_connection *xconn = req->xconn;
3884 char *pdata = *ppdata;
3885 char *params = *pparams;
3886 uint16_t info_level;
3888 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3889 lp_servicename(talloc_tos(), SNUM(conn))));
3891 /* */
3892 if (total_params < 4) {
3893 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3894 total_params));
3895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3896 return;
3899 info_level = SVAL(params,2);
3901 if (IS_IPC(conn)) {
3902 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3903 info_level != SMB_SET_CIFS_UNIX_INFO) {
3904 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3905 "info level (0x%x) on IPC$.\n",
3906 (unsigned int)info_level));
3907 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3908 return;
3912 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3913 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3914 DEBUG(0,("call_trans2setfsinfo: encryption required "
3915 "and info level 0x%x sent.\n",
3916 (unsigned int)info_level));
3917 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3918 return;
3922 switch(info_level) {
3923 case SMB_SET_CIFS_UNIX_INFO:
3924 if (!lp_unix_extensions()) {
3925 DEBUG(2,("call_trans2setfsinfo: "
3926 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3927 "unix extensions off\n"));
3928 reply_nterror(req,
3929 NT_STATUS_INVALID_LEVEL);
3930 return;
3933 /* There should be 12 bytes of capabilities set. */
3934 if (total_data < 12) {
3935 reply_nterror(
3936 req,
3937 NT_STATUS_INVALID_PARAMETER);
3938 return;
3940 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3941 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3942 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3943 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3944 /* Just print these values for now. */
3945 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3946 "major = %u, minor = %u cap_low = 0x%x, "
3947 "cap_high = 0x%xn",
3948 (unsigned int)xconn->
3949 smb1.unix_info.client_major,
3950 (unsigned int)xconn->
3951 smb1.unix_info.client_minor,
3952 (unsigned int)xconn->
3953 smb1.unix_info.client_cap_low,
3954 (unsigned int)xconn->
3955 smb1.unix_info.client_cap_high));
3957 /* Here is where we must switch to posix pathname processing... */
3958 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3959 lp_set_posix_pathnames();
3960 mangle_change_to_posix();
3963 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3964 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3965 /* Client that knows how to do posix locks,
3966 * but not posix open/mkdir operations. Set a
3967 * default type for read/write checks. */
3969 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3972 break;
3974 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3976 NTSTATUS status;
3977 size_t param_len = 0;
3978 size_t data_len = total_data;
3980 if (!lp_unix_extensions()) {
3981 reply_nterror(
3982 req,
3983 NT_STATUS_INVALID_LEVEL);
3984 return;
3987 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3988 reply_nterror(
3989 req,
3990 NT_STATUS_NOT_SUPPORTED);
3991 return;
3994 if (xconn->smb1.echo_handler.trusted_fde) {
3995 DEBUG( 2,("call_trans2setfsinfo: "
3996 "request transport encryption disabled"
3997 "with 'fork echo handler = yes'\n"));
3998 reply_nterror(
3999 req,
4000 NT_STATUS_NOT_SUPPORTED);
4001 return;
4004 DEBUG( 4,("call_trans2setfsinfo: "
4005 "request transport encryption.\n"));
4007 status = srv_request_encryption_setup(conn,
4008 (unsigned char **)ppdata,
4009 &data_len,
4010 (unsigned char **)pparams,
4011 &param_len);
4013 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4014 !NT_STATUS_IS_OK(status)) {
4015 reply_nterror(req, status);
4016 return;
4019 send_trans2_replies(conn, req,
4020 NT_STATUS_OK,
4021 *pparams,
4022 param_len,
4023 *ppdata,
4024 data_len,
4025 max_data_bytes);
4027 if (NT_STATUS_IS_OK(status)) {
4028 /* Server-side transport
4029 * encryption is now *on*. */
4030 status = srv_encryption_start(conn);
4031 if (!NT_STATUS_IS_OK(status)) {
4032 char *reason = talloc_asprintf(talloc_tos(),
4033 "Failure in setting "
4034 "up encrypted transport: %s",
4035 nt_errstr(status));
4036 exit_server_cleanly(reason);
4039 return;
4042 case SMB_FS_QUOTA_INFORMATION:
4044 files_struct *fsp = NULL;
4045 SMB_NTQUOTA_STRUCT quotas;
4047 ZERO_STRUCT(quotas);
4049 /* access check */
4050 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4051 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4052 lp_servicename(talloc_tos(), SNUM(conn)),
4053 conn->session_info->unix_info->unix_name));
4054 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4055 return;
4058 /* note: normally there're 48 bytes,
4059 * but we didn't use the last 6 bytes for now
4060 * --metze
4062 fsp = file_fsp(req, SVAL(params,0));
4064 if (!check_fsp_ntquota_handle(conn, req,
4065 fsp)) {
4066 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4067 reply_nterror(
4068 req, NT_STATUS_INVALID_HANDLE);
4069 return;
4072 if (total_data < 42) {
4073 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4074 total_data));
4075 reply_nterror(
4076 req,
4077 NT_STATUS_INVALID_PARAMETER);
4078 return;
4081 /* unknown_1 24 NULL bytes in pdata*/
4083 /* the soft quotas 8 bytes (uint64_t)*/
4084 quotas.softlim = BVAL(pdata,24);
4086 /* the hard quotas 8 bytes (uint64_t)*/
4087 quotas.hardlim = BVAL(pdata,32);
4089 /* quota_flags 2 bytes **/
4090 quotas.qflags = SVAL(pdata,40);
4092 /* unknown_2 6 NULL bytes follow*/
4094 /* now set the quotas */
4095 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4096 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4097 reply_nterror(req, map_nt_error_from_unix(errno));
4098 return;
4101 break;
4103 default:
4104 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4105 info_level));
4106 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4107 return;
4108 break;
4112 * sending this reply works fine,
4113 * but I'm not sure it's the same
4114 * like windows do...
4115 * --metze
4117 reply_outbuf(req, 10, 0);
4120 #if defined(HAVE_POSIX_ACLS)
4121 /****************************************************************************
4122 Utility function to count the number of entries in a POSIX acl.
4123 ****************************************************************************/
4125 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4127 unsigned int ace_count = 0;
4128 int entry_id = SMB_ACL_FIRST_ENTRY;
4129 SMB_ACL_ENTRY_T entry;
4131 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4132 /* get_next... */
4133 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4134 entry_id = SMB_ACL_NEXT_ENTRY;
4136 ace_count++;
4138 return ace_count;
4141 /****************************************************************************
4142 Utility function to marshall a POSIX acl into wire format.
4143 ****************************************************************************/
4145 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4147 int entry_id = SMB_ACL_FIRST_ENTRY;
4148 SMB_ACL_ENTRY_T entry;
4150 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4151 SMB_ACL_TAG_T tagtype;
4152 SMB_ACL_PERMSET_T permset;
4153 unsigned char perms = 0;
4154 unsigned int own_grp;
4156 /* get_next... */
4157 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4158 entry_id = SMB_ACL_NEXT_ENTRY;
4161 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4162 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4163 return False;
4166 if (sys_acl_get_permset(entry, &permset) == -1) {
4167 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4168 return False;
4171 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4172 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4173 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4175 SCVAL(pdata,1,perms);
4177 switch (tagtype) {
4178 case SMB_ACL_USER_OBJ:
4179 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4180 own_grp = (unsigned int)pst->st_ex_uid;
4181 SIVAL(pdata,2,own_grp);
4182 SIVAL(pdata,6,0);
4183 break;
4184 case SMB_ACL_USER:
4186 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4187 if (!puid) {
4188 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4189 return False;
4191 own_grp = (unsigned int)*puid;
4192 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4193 SIVAL(pdata,2,own_grp);
4194 SIVAL(pdata,6,0);
4195 break;
4197 case SMB_ACL_GROUP_OBJ:
4198 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4199 own_grp = (unsigned int)pst->st_ex_gid;
4200 SIVAL(pdata,2,own_grp);
4201 SIVAL(pdata,6,0);
4202 break;
4203 case SMB_ACL_GROUP:
4205 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4206 if (!pgid) {
4207 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4208 return False;
4210 own_grp = (unsigned int)*pgid;
4211 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4212 SIVAL(pdata,2,own_grp);
4213 SIVAL(pdata,6,0);
4214 break;
4216 case SMB_ACL_MASK:
4217 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4218 SIVAL(pdata,2,0xFFFFFFFF);
4219 SIVAL(pdata,6,0xFFFFFFFF);
4220 break;
4221 case SMB_ACL_OTHER:
4222 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4223 SIVAL(pdata,2,0xFFFFFFFF);
4224 SIVAL(pdata,6,0xFFFFFFFF);
4225 break;
4226 default:
4227 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4228 return False;
4230 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4233 return True;
4235 #endif
4237 /****************************************************************************
4238 Store the FILE_UNIX_BASIC info.
4239 ****************************************************************************/
4241 static char *store_file_unix_basic(connection_struct *conn,
4242 char *pdata,
4243 files_struct *fsp,
4244 const SMB_STRUCT_STAT *psbuf)
4246 uint64_t file_index = get_FileIndex(conn, psbuf);
4247 dev_t devno;
4249 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4250 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4252 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4253 pdata += 8;
4255 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4256 pdata += 8;
4258 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4259 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4260 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4261 pdata += 24;
4263 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4264 SIVAL(pdata,4,0);
4265 pdata += 8;
4267 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4268 SIVAL(pdata,4,0);
4269 pdata += 8;
4271 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4272 pdata += 4;
4274 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4275 devno = psbuf->st_ex_rdev;
4276 } else {
4277 devno = psbuf->st_ex_dev;
4280 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4281 SIVAL(pdata,4,0);
4282 pdata += 8;
4284 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4285 SIVAL(pdata,4,0);
4286 pdata += 8;
4288 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4289 pdata += 8;
4291 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4292 SIVAL(pdata,4,0);
4293 pdata += 8;
4295 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4296 SIVAL(pdata,4,0);
4297 pdata += 8;
4299 return pdata;
4302 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4303 * the chflags(2) (or equivalent) flags.
4305 * XXX: this really should be behind the VFS interface. To do this, we would
4306 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4307 * Each VFS module could then implement its own mapping as appropriate for the
4308 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4310 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4311 info2_flags_map[] =
4313 #ifdef UF_NODUMP
4314 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4315 #endif
4317 #ifdef UF_IMMUTABLE
4318 { UF_IMMUTABLE, EXT_IMMUTABLE },
4319 #endif
4321 #ifdef UF_APPEND
4322 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4323 #endif
4325 #ifdef UF_HIDDEN
4326 { UF_HIDDEN, EXT_HIDDEN },
4327 #endif
4329 /* Do not remove. We need to guarantee that this array has at least one
4330 * entry to build on HP-UX.
4332 { 0, 0 }
4336 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4337 uint32_t *smb_fflags, uint32_t *smb_fmask)
4339 int i;
4341 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4342 *smb_fmask |= info2_flags_map[i].smb_fflag;
4343 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4344 *smb_fflags |= info2_flags_map[i].smb_fflag;
4349 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4350 const uint32_t smb_fflags,
4351 const uint32_t smb_fmask,
4352 int *stat_fflags)
4354 uint32_t max_fmask = 0;
4355 int i;
4357 *stat_fflags = psbuf->st_ex_flags;
4359 /* For each flags requested in smb_fmask, check the state of the
4360 * corresponding flag in smb_fflags and set or clear the matching
4361 * stat flag.
4364 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4365 max_fmask |= info2_flags_map[i].smb_fflag;
4366 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4367 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4368 *stat_fflags |= info2_flags_map[i].stat_fflag;
4369 } else {
4370 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4375 /* If smb_fmask is asking to set any bits that are not supported by
4376 * our flag mappings, we should fail.
4378 if ((smb_fmask & max_fmask) != smb_fmask) {
4379 return False;
4382 return True;
4386 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4387 * of file flags and birth (create) time.
4389 static char *store_file_unix_basic_info2(connection_struct *conn,
4390 char *pdata,
4391 files_struct *fsp,
4392 const SMB_STRUCT_STAT *psbuf)
4394 uint32_t file_flags = 0;
4395 uint32_t flags_mask = 0;
4397 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4399 /* Create (birth) time 64 bit */
4400 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4401 pdata += 8;
4403 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4404 SIVAL(pdata, 0, file_flags); /* flags */
4405 SIVAL(pdata, 4, flags_mask); /* mask */
4406 pdata += 8;
4408 return pdata;
4411 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4412 const struct stream_struct *streams,
4413 char *data,
4414 unsigned int max_data_bytes,
4415 unsigned int *data_size)
4417 unsigned int i;
4418 unsigned int ofs = 0;
4420 if (max_data_bytes < 32) {
4421 return NT_STATUS_INFO_LENGTH_MISMATCH;
4424 for (i = 0; i < num_streams; i++) {
4425 unsigned int next_offset;
4426 size_t namelen;
4427 smb_ucs2_t *namebuf;
4429 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4430 streams[i].name, &namelen) ||
4431 namelen <= 2)
4433 return NT_STATUS_INVALID_PARAMETER;
4437 * name_buf is now null-terminated, we need to marshall as not
4438 * terminated
4441 namelen -= 2;
4444 * We cannot overflow ...
4446 if ((ofs + 24 + namelen) > max_data_bytes) {
4447 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4448 i));
4449 TALLOC_FREE(namebuf);
4450 return STATUS_BUFFER_OVERFLOW;
4453 SIVAL(data, ofs+4, namelen);
4454 SOFF_T(data, ofs+8, streams[i].size);
4455 SOFF_T(data, ofs+16, streams[i].alloc_size);
4456 memcpy(data+ofs+24, namebuf, namelen);
4457 TALLOC_FREE(namebuf);
4459 next_offset = ofs + 24 + namelen;
4461 if (i == num_streams-1) {
4462 SIVAL(data, ofs, 0);
4464 else {
4465 unsigned int align = ndr_align_size(next_offset, 8);
4467 if ((next_offset + align) > max_data_bytes) {
4468 DEBUG(10, ("refusing to overflow align "
4469 "reply at stream %u\n",
4470 i));
4471 TALLOC_FREE(namebuf);
4472 return STATUS_BUFFER_OVERFLOW;
4475 memset(data+next_offset, 0, align);
4476 next_offset += align;
4478 SIVAL(data, ofs, next_offset - ofs);
4479 ofs = next_offset;
4482 ofs = next_offset;
4485 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4487 *data_size = ofs;
4489 return NT_STATUS_OK;
4492 /****************************************************************************
4493 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4494 ****************************************************************************/
4496 static void call_trans2qpipeinfo(connection_struct *conn,
4497 struct smb_request *req,
4498 unsigned int tran_call,
4499 char **pparams, int total_params,
4500 char **ppdata, int total_data,
4501 unsigned int max_data_bytes)
4503 char *params = *pparams;
4504 char *pdata = *ppdata;
4505 unsigned int data_size = 0;
4506 unsigned int param_size = 2;
4507 uint16_t info_level;
4508 files_struct *fsp;
4510 if (!params) {
4511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4512 return;
4515 if (total_params < 4) {
4516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517 return;
4520 fsp = file_fsp(req, SVAL(params,0));
4521 if (!fsp_is_np(fsp)) {
4522 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4523 return;
4526 info_level = SVAL(params,2);
4528 *pparams = (char *)SMB_REALLOC(*pparams,2);
4529 if (*pparams == NULL) {
4530 reply_nterror(req, NT_STATUS_NO_MEMORY);
4531 return;
4533 params = *pparams;
4534 SSVAL(params,0,0);
4535 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4537 return;
4539 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4540 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4541 if (*ppdata == NULL ) {
4542 reply_nterror(req, NT_STATUS_NO_MEMORY);
4543 return;
4545 pdata = *ppdata;
4547 switch (info_level) {
4548 case SMB_FILE_STANDARD_INFORMATION:
4549 memset(pdata,0,24);
4550 SOFF_T(pdata,0,4096LL);
4551 SIVAL(pdata,16,1);
4552 SIVAL(pdata,20,1);
4553 data_size = 24;
4554 break;
4556 default:
4557 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4558 return;
4561 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4562 max_data_bytes);
4564 return;
4567 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4568 TALLOC_CTX *mem_ctx,
4569 uint16_t info_level,
4570 files_struct *fsp,
4571 struct smb_filename *smb_fname,
4572 bool delete_pending,
4573 struct timespec write_time_ts,
4574 struct ea_list *ea_list,
4575 int lock_data_count,
4576 char *lock_data,
4577 uint16_t flags2,
4578 unsigned int max_data_bytes,
4579 size_t *fixed_portion,
4580 char **ppdata,
4581 unsigned int *pdata_size)
4583 char *pdata = *ppdata;
4584 char *dstart, *dend;
4585 unsigned int data_size;
4586 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4587 time_t create_time, mtime, atime, c_time;
4588 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4589 char *p;
4590 char *base_name;
4591 char *dos_fname;
4592 int mode;
4593 int nlink;
4594 NTSTATUS status;
4595 uint64_t file_size = 0;
4596 uint64_t pos = 0;
4597 uint64_t allocation_size = 0;
4598 uint64_t file_index = 0;
4599 uint32_t access_mask = 0;
4600 size_t len = 0;
4602 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4603 return NT_STATUS_INVALID_LEVEL;
4606 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4607 smb_fname_str_dbg(smb_fname),
4608 fsp_fnum_dbg(fsp),
4609 info_level, max_data_bytes));
4611 mode = dos_mode(conn, smb_fname);
4612 nlink = psbuf->st_ex_nlink;
4614 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4615 nlink = 1;
4618 if ((nlink > 0) && delete_pending) {
4619 nlink -= 1;
4622 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4623 return NT_STATUS_INVALID_PARAMETER;
4626 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4627 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4628 if (*ppdata == NULL) {
4629 return NT_STATUS_NO_MEMORY;
4631 pdata = *ppdata;
4632 dstart = pdata;
4633 dend = dstart + data_size - 1;
4635 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4636 update_stat_ex_mtime(psbuf, write_time_ts);
4639 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4640 mtime_ts = psbuf->st_ex_mtime;
4641 atime_ts = psbuf->st_ex_atime;
4642 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4644 if (lp_dos_filetime_resolution(SNUM(conn))) {
4645 dos_filetime_timespec(&create_time_ts);
4646 dos_filetime_timespec(&mtime_ts);
4647 dos_filetime_timespec(&atime_ts);
4648 dos_filetime_timespec(&ctime_ts);
4651 create_time = convert_timespec_to_time_t(create_time_ts);
4652 mtime = convert_timespec_to_time_t(mtime_ts);
4653 atime = convert_timespec_to_time_t(atime_ts);
4654 c_time = convert_timespec_to_time_t(ctime_ts);
4656 p = strrchr_m(smb_fname->base_name,'/');
4657 if (!p)
4658 base_name = smb_fname->base_name;
4659 else
4660 base_name = p+1;
4662 /* NT expects the name to be in an exact form of the *full*
4663 filename. See the trans2 torture test */
4664 if (ISDOT(base_name)) {
4665 dos_fname = talloc_strdup(mem_ctx, "\\");
4666 if (!dos_fname) {
4667 return NT_STATUS_NO_MEMORY;
4669 } else {
4670 dos_fname = talloc_asprintf(mem_ctx,
4671 "\\%s",
4672 smb_fname->base_name);
4673 if (!dos_fname) {
4674 return NT_STATUS_NO_MEMORY;
4676 if (is_ntfs_stream_smb_fname(smb_fname)) {
4677 dos_fname = talloc_asprintf(dos_fname, "%s",
4678 smb_fname->stream_name);
4679 if (!dos_fname) {
4680 return NT_STATUS_NO_MEMORY;
4684 string_replace(dos_fname, '/', '\\');
4687 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4689 if (!fsp) {
4690 /* Do we have this path open ? */
4691 files_struct *fsp1;
4692 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4693 fsp1 = file_find_di_first(conn->sconn, fileid);
4694 if (fsp1 && fsp1->initial_allocation_size) {
4695 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4699 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4700 file_size = get_file_size_stat(psbuf);
4703 if (fsp) {
4704 pos = fsp->fh->position_information;
4707 if (fsp) {
4708 access_mask = fsp->access_mask;
4709 } else {
4710 /* GENERIC_EXECUTE mapping from Windows */
4711 access_mask = 0x12019F;
4714 /* This should be an index number - looks like
4715 dev/ino to me :-)
4717 I think this causes us to fail the IFSKIT
4718 BasicFileInformationTest. -tpot */
4719 file_index = get_FileIndex(conn, psbuf);
4721 *fixed_portion = 0;
4723 switch (info_level) {
4724 case SMB_INFO_STANDARD:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4726 data_size = 22;
4727 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4728 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4729 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4730 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4731 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4732 SSVAL(pdata,l1_attrFile,mode);
4733 break;
4735 case SMB_INFO_QUERY_EA_SIZE:
4737 unsigned int ea_size =
4738 estimate_ea_size(conn, fsp,
4739 smb_fname);
4740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4741 data_size = 26;
4742 srv_put_dos_date2(pdata,0,create_time);
4743 srv_put_dos_date2(pdata,4,atime);
4744 srv_put_dos_date2(pdata,8,mtime); /* write time */
4745 SIVAL(pdata,12,(uint32_t)file_size);
4746 SIVAL(pdata,16,(uint32_t)allocation_size);
4747 SSVAL(pdata,20,mode);
4748 SIVAL(pdata,22,ea_size);
4749 break;
4752 case SMB_INFO_IS_NAME_VALID:
4753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4754 if (fsp) {
4755 /* os/2 needs this ? really ?*/
4756 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4758 /* This is only reached for qpathinfo */
4759 data_size = 0;
4760 break;
4762 case SMB_INFO_QUERY_EAS_FROM_LIST:
4764 size_t total_ea_len = 0;
4765 struct ea_list *ea_file_list = NULL;
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4768 status =
4769 get_ea_list_from_file(mem_ctx, conn, fsp,
4770 smb_fname,
4771 &total_ea_len, &ea_file_list);
4772 if (!NT_STATUS_IS_OK(status)) {
4773 return status;
4776 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4778 if (!ea_list || (total_ea_len > data_size)) {
4779 data_size = 4;
4780 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4781 break;
4784 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4785 break;
4788 case SMB_INFO_QUERY_ALL_EAS:
4790 /* We have data_size bytes to put EA's into. */
4791 size_t total_ea_len = 0;
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4794 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4795 smb_fname,
4796 &total_ea_len, &ea_list);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 return status;
4801 if (!ea_list || (total_ea_len > data_size)) {
4802 data_size = 4;
4803 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4804 break;
4807 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4808 break;
4811 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4813 /* This is FileFullEaInformation - 0xF which maps to
4814 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4816 /* We have data_size bytes to put EA's into. */
4817 size_t total_ea_len = 0;
4818 struct ea_list *ea_file_list = NULL;
4820 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4822 /*TODO: add filtering and index handling */
4824 status =
4825 get_ea_list_from_file(mem_ctx, conn, fsp,
4826 smb_fname,
4827 &total_ea_len, &ea_file_list);
4828 if (!NT_STATUS_IS_OK(status)) {
4829 return status;
4831 if (!ea_file_list) {
4832 return NT_STATUS_NO_EAS_ON_FILE;
4835 status = fill_ea_chained_buffer(mem_ctx,
4836 pdata,
4837 data_size,
4838 &data_size,
4839 conn, ea_file_list);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 return status;
4843 break;
4846 case SMB_FILE_BASIC_INFORMATION:
4847 case SMB_QUERY_FILE_BASIC_INFO:
4849 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4851 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4852 } else {
4853 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4854 data_size = 40;
4855 SIVAL(pdata,36,0);
4857 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4858 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4859 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4860 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4861 SIVAL(pdata,32,mode);
4863 DEBUG(5,("SMB_QFBI - "));
4864 DEBUG(5,("create: %s ", ctime(&create_time)));
4865 DEBUG(5,("access: %s ", ctime(&atime)));
4866 DEBUG(5,("write: %s ", ctime(&mtime)));
4867 DEBUG(5,("change: %s ", ctime(&c_time)));
4868 DEBUG(5,("mode: %x\n", mode));
4869 *fixed_portion = data_size;
4870 break;
4872 case SMB_FILE_STANDARD_INFORMATION:
4873 case SMB_QUERY_FILE_STANDARD_INFO:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4876 data_size = 24;
4877 SOFF_T(pdata,0,allocation_size);
4878 SOFF_T(pdata,8,file_size);
4879 SIVAL(pdata,16,nlink);
4880 SCVAL(pdata,20,delete_pending?1:0);
4881 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4882 SSVAL(pdata,22,0); /* Padding. */
4883 *fixed_portion = 24;
4884 break;
4886 case SMB_FILE_EA_INFORMATION:
4887 case SMB_QUERY_FILE_EA_INFO:
4889 unsigned int ea_size =
4890 estimate_ea_size(conn, fsp, smb_fname);
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4892 data_size = 4;
4893 *fixed_portion = 4;
4894 SIVAL(pdata,0,ea_size);
4895 break;
4898 /* Get the 8.3 name - used if NT SMB was negotiated. */
4899 case SMB_QUERY_FILE_ALT_NAME_INFO:
4900 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4902 char mangled_name[13];
4903 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4904 if (!name_to_8_3(base_name,mangled_name,
4905 True,conn->params)) {
4906 return NT_STATUS_NO_MEMORY;
4908 status = srvstr_push(dstart, flags2,
4909 pdata+4, mangled_name,
4910 PTR_DIFF(dend, pdata+4),
4911 STR_UNICODE, &len);
4912 if (!NT_STATUS_IS_OK(status)) {
4913 return status;
4915 data_size = 4 + len;
4916 SIVAL(pdata,0,len);
4917 *fixed_portion = 8;
4918 break;
4921 case SMB_QUERY_FILE_NAME_INFO:
4924 this must be *exactly* right for ACLs on mapped drives to work
4926 status = srvstr_push(dstart, flags2,
4927 pdata+4, dos_fname,
4928 PTR_DIFF(dend, pdata+4),
4929 STR_UNICODE, &len);
4930 if (!NT_STATUS_IS_OK(status)) {
4931 return status;
4933 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4934 data_size = 4 + len;
4935 SIVAL(pdata,0,len);
4936 break;
4939 case SMB_FILE_ALLOCATION_INFORMATION:
4940 case SMB_QUERY_FILE_ALLOCATION_INFO:
4941 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4942 data_size = 8;
4943 SOFF_T(pdata,0,allocation_size);
4944 break;
4946 case SMB_FILE_END_OF_FILE_INFORMATION:
4947 case SMB_QUERY_FILE_END_OF_FILEINFO:
4948 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4949 data_size = 8;
4950 SOFF_T(pdata,0,file_size);
4951 break;
4953 case SMB_QUERY_FILE_ALL_INFO:
4954 case SMB_FILE_ALL_INFORMATION:
4956 unsigned int ea_size =
4957 estimate_ea_size(conn, fsp, smb_fname);
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4959 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4960 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4961 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4962 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4963 SIVAL(pdata,32,mode);
4964 SIVAL(pdata,36,0); /* padding. */
4965 pdata += 40;
4966 SOFF_T(pdata,0,allocation_size);
4967 SOFF_T(pdata,8,file_size);
4968 SIVAL(pdata,16,nlink);
4969 SCVAL(pdata,20,delete_pending);
4970 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4971 SSVAL(pdata,22,0);
4972 pdata += 24;
4973 SIVAL(pdata,0,ea_size);
4974 pdata += 4; /* EA info */
4975 status = srvstr_push(dstart, flags2,
4976 pdata+4, dos_fname,
4977 PTR_DIFF(dend, pdata+4),
4978 STR_UNICODE, &len);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 return status;
4982 SIVAL(pdata,0,len);
4983 pdata += 4 + len;
4984 data_size = PTR_DIFF(pdata,(*ppdata));
4985 *fixed_portion = 10;
4986 break;
4989 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4991 unsigned int ea_size =
4992 estimate_ea_size(conn, fsp, smb_fname);
4993 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4994 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4995 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4996 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4997 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4998 SIVAL(pdata, 0x20, mode);
4999 SIVAL(pdata, 0x24, 0); /* padding. */
5000 SBVAL(pdata, 0x28, allocation_size);
5001 SBVAL(pdata, 0x30, file_size);
5002 SIVAL(pdata, 0x38, nlink);
5003 SCVAL(pdata, 0x3C, delete_pending);
5004 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5005 SSVAL(pdata, 0x3E, 0); /* padding */
5006 SBVAL(pdata, 0x40, file_index);
5007 SIVAL(pdata, 0x48, ea_size);
5008 SIVAL(pdata, 0x4C, access_mask);
5009 SBVAL(pdata, 0x50, pos);
5010 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5011 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5013 pdata += 0x60;
5015 status = srvstr_push(dstart, flags2,
5016 pdata+4, dos_fname,
5017 PTR_DIFF(dend, pdata+4),
5018 STR_UNICODE, &len);
5019 if (!NT_STATUS_IS_OK(status)) {
5020 return status;
5022 SIVAL(pdata,0,len);
5023 pdata += 4 + len;
5024 data_size = PTR_DIFF(pdata,(*ppdata));
5025 *fixed_portion = 104;
5026 break;
5028 case SMB_FILE_INTERNAL_INFORMATION:
5030 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5031 SBVAL(pdata, 0, file_index);
5032 data_size = 8;
5033 *fixed_portion = 8;
5034 break;
5036 case SMB_FILE_ACCESS_INFORMATION:
5037 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5038 SIVAL(pdata, 0, access_mask);
5039 data_size = 4;
5040 *fixed_portion = 4;
5041 break;
5043 case SMB_FILE_NAME_INFORMATION:
5044 /* Pathname with leading '\'. */
5046 size_t byte_len;
5047 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5048 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5049 SIVAL(pdata,0,byte_len);
5050 data_size = 4 + byte_len;
5051 break;
5054 case SMB_FILE_DISPOSITION_INFORMATION:
5055 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5056 data_size = 1;
5057 SCVAL(pdata,0,delete_pending);
5058 *fixed_portion = 1;
5059 break;
5061 case SMB_FILE_POSITION_INFORMATION:
5062 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5063 data_size = 8;
5064 SOFF_T(pdata,0,pos);
5065 *fixed_portion = 8;
5066 break;
5068 case SMB_FILE_MODE_INFORMATION:
5069 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5070 SIVAL(pdata,0,mode);
5071 data_size = 4;
5072 *fixed_portion = 4;
5073 break;
5075 case SMB_FILE_ALIGNMENT_INFORMATION:
5076 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5077 SIVAL(pdata,0,0); /* No alignment needed. */
5078 data_size = 4;
5079 *fixed_portion = 4;
5080 break;
5083 * NT4 server just returns "invalid query" to this - if we try
5084 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5085 * want this. JRA.
5087 /* The first statement above is false - verified using Thursby
5088 * client against NT4 -- gcolley.
5090 case SMB_QUERY_FILE_STREAM_INFO:
5091 case SMB_FILE_STREAM_INFORMATION: {
5092 unsigned int num_streams = 0;
5093 struct stream_struct *streams = NULL;
5095 DEBUG(10,("smbd_do_qfilepathinfo: "
5096 "SMB_FILE_STREAM_INFORMATION\n"));
5098 if (is_ntfs_stream_smb_fname(smb_fname)) {
5099 return NT_STATUS_INVALID_PARAMETER;
5102 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5103 talloc_tos(), &num_streams, &streams);
5105 if (!NT_STATUS_IS_OK(status)) {
5106 DEBUG(10, ("could not get stream info: %s\n",
5107 nt_errstr(status)));
5108 return status;
5111 status = marshall_stream_info(num_streams, streams,
5112 pdata, max_data_bytes,
5113 &data_size);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 DEBUG(10, ("marshall_stream_info failed: %s\n",
5117 nt_errstr(status)));
5118 TALLOC_FREE(streams);
5119 return status;
5122 TALLOC_FREE(streams);
5124 *fixed_portion = 32;
5126 break;
5128 case SMB_QUERY_COMPRESSION_INFO:
5129 case SMB_FILE_COMPRESSION_INFORMATION:
5130 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5131 SOFF_T(pdata,0,file_size);
5132 SIVAL(pdata,8,0); /* ??? */
5133 SIVAL(pdata,12,0); /* ??? */
5134 data_size = 16;
5135 *fixed_portion = 16;
5136 break;
5138 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5140 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5141 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5142 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5143 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5144 SOFF_T(pdata,32,allocation_size);
5145 SOFF_T(pdata,40,file_size);
5146 SIVAL(pdata,48,mode);
5147 SIVAL(pdata,52,0); /* ??? */
5148 data_size = 56;
5149 *fixed_portion = 56;
5150 break;
5152 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5153 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5154 SIVAL(pdata,0,mode);
5155 SIVAL(pdata,4,0);
5156 data_size = 8;
5157 *fixed_portion = 8;
5158 break;
5161 * CIFS UNIX Extensions.
5164 case SMB_QUERY_FILE_UNIX_BASIC:
5166 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5167 data_size = PTR_DIFF(pdata,(*ppdata));
5169 DEBUG(4,("smbd_do_qfilepathinfo: "
5170 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5171 dump_data(4, (uint8_t *)(*ppdata), data_size);
5173 break;
5175 case SMB_QUERY_FILE_UNIX_INFO2:
5177 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5178 data_size = PTR_DIFF(pdata,(*ppdata));
5181 int i;
5182 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5184 for (i=0; i<100; i++)
5185 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5186 DEBUG(4,("\n"));
5189 break;
5191 case SMB_QUERY_FILE_UNIX_LINK:
5193 int link_len = 0;
5194 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5196 if (!buffer) {
5197 return NT_STATUS_NO_MEMORY;
5200 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5201 #ifdef S_ISLNK
5202 if(!S_ISLNK(psbuf->st_ex_mode)) {
5203 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5205 #else
5206 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5207 #endif
5208 link_len = SMB_VFS_READLINK(conn,
5209 smb_fname->base_name,
5210 buffer, PATH_MAX);
5211 if (link_len == -1) {
5212 return map_nt_error_from_unix(errno);
5214 buffer[link_len] = 0;
5215 status = srvstr_push(dstart, flags2,
5216 pdata, buffer,
5217 PTR_DIFF(dend, pdata),
5218 STR_TERMINATE, &len);
5219 if (!NT_STATUS_IS_OK(status)) {
5220 return status;
5222 pdata += len;
5223 data_size = PTR_DIFF(pdata,(*ppdata));
5225 break;
5228 #if defined(HAVE_POSIX_ACLS)
5229 case SMB_QUERY_POSIX_ACL:
5231 SMB_ACL_T file_acl = NULL;
5232 SMB_ACL_T def_acl = NULL;
5233 uint16_t num_file_acls = 0;
5234 uint16_t num_def_acls = 0;
5236 if (fsp && fsp->fh->fd != -1) {
5237 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5238 talloc_tos());
5239 } else {
5240 file_acl =
5241 SMB_VFS_SYS_ACL_GET_FILE(conn,
5242 smb_fname->base_name,
5243 SMB_ACL_TYPE_ACCESS,
5244 talloc_tos());
5247 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5248 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5249 "not implemented on "
5250 "filesystem containing %s\n",
5251 smb_fname->base_name));
5252 return NT_STATUS_NOT_IMPLEMENTED;
5255 if (S_ISDIR(psbuf->st_ex_mode)) {
5256 if (fsp && fsp->is_directory) {
5257 def_acl =
5258 SMB_VFS_SYS_ACL_GET_FILE(
5259 conn,
5260 fsp->fsp_name->base_name,
5261 SMB_ACL_TYPE_DEFAULT,
5262 talloc_tos());
5263 } else {
5264 def_acl =
5265 SMB_VFS_SYS_ACL_GET_FILE(
5266 conn,
5267 smb_fname->base_name,
5268 SMB_ACL_TYPE_DEFAULT,
5269 talloc_tos());
5271 def_acl = free_empty_sys_acl(conn, def_acl);
5274 num_file_acls = count_acl_entries(conn, file_acl);
5275 num_def_acls = count_acl_entries(conn, def_acl);
5277 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5278 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5279 data_size,
5280 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5281 SMB_POSIX_ACL_HEADER_SIZE) ));
5282 if (file_acl) {
5283 TALLOC_FREE(file_acl);
5285 if (def_acl) {
5286 TALLOC_FREE(def_acl);
5288 return NT_STATUS_BUFFER_TOO_SMALL;
5291 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5292 SSVAL(pdata,2,num_file_acls);
5293 SSVAL(pdata,4,num_def_acls);
5294 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5295 if (file_acl) {
5296 TALLOC_FREE(file_acl);
5298 if (def_acl) {
5299 TALLOC_FREE(def_acl);
5301 return NT_STATUS_INTERNAL_ERROR;
5303 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5304 if (file_acl) {
5305 TALLOC_FREE(file_acl);
5307 if (def_acl) {
5308 TALLOC_FREE(def_acl);
5310 return NT_STATUS_INTERNAL_ERROR;
5313 if (file_acl) {
5314 TALLOC_FREE(file_acl);
5316 if (def_acl) {
5317 TALLOC_FREE(def_acl);
5319 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5320 break;
5322 #endif
5325 case SMB_QUERY_POSIX_LOCK:
5327 uint64_t count;
5328 uint64_t offset;
5329 uint64_t smblctx;
5330 enum brl_type lock_type;
5332 /* We need an open file with a real fd for this. */
5333 if (!fsp || fsp->fh->fd == -1) {
5334 return NT_STATUS_INVALID_LEVEL;
5337 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5338 return NT_STATUS_INVALID_PARAMETER;
5341 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5342 case POSIX_LOCK_TYPE_READ:
5343 lock_type = READ_LOCK;
5344 break;
5345 case POSIX_LOCK_TYPE_WRITE:
5346 lock_type = WRITE_LOCK;
5347 break;
5348 case POSIX_LOCK_TYPE_UNLOCK:
5349 default:
5350 /* There's no point in asking for an unlock... */
5351 return NT_STATUS_INVALID_PARAMETER;
5354 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5355 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5356 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5358 status = query_lock(fsp,
5359 &smblctx,
5360 &count,
5361 &offset,
5362 &lock_type,
5363 POSIX_LOCK);
5365 if (ERROR_WAS_LOCK_DENIED(status)) {
5366 /* Here we need to report who has it locked... */
5367 data_size = POSIX_LOCK_DATA_SIZE;
5369 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5370 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5371 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5372 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5373 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5375 } else if (NT_STATUS_IS_OK(status)) {
5376 /* For success we just return a copy of what we sent
5377 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5378 data_size = POSIX_LOCK_DATA_SIZE;
5379 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5380 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5381 } else {
5382 return status;
5384 break;
5387 default:
5388 return NT_STATUS_INVALID_LEVEL;
5391 *pdata_size = data_size;
5392 return NT_STATUS_OK;
5395 /****************************************************************************
5396 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5397 file name or file id).
5398 ****************************************************************************/
5400 static void call_trans2qfilepathinfo(connection_struct *conn,
5401 struct smb_request *req,
5402 unsigned int tran_call,
5403 char **pparams, int total_params,
5404 char **ppdata, int total_data,
5405 unsigned int max_data_bytes)
5407 char *params = *pparams;
5408 char *pdata = *ppdata;
5409 uint16_t info_level;
5410 unsigned int data_size = 0;
5411 unsigned int param_size = 2;
5412 struct smb_filename *smb_fname = NULL;
5413 bool delete_pending = False;
5414 struct timespec write_time_ts;
5415 files_struct *fsp = NULL;
5416 struct file_id fileid;
5417 struct ea_list *ea_list = NULL;
5418 int lock_data_count = 0;
5419 char *lock_data = NULL;
5420 size_t fixed_portion;
5421 NTSTATUS status = NT_STATUS_OK;
5423 if (!params) {
5424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5425 return;
5428 ZERO_STRUCT(write_time_ts);
5430 if (tran_call == TRANSACT2_QFILEINFO) {
5431 if (total_params < 4) {
5432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5433 return;
5436 if (IS_IPC(conn)) {
5437 call_trans2qpipeinfo(conn, req, tran_call,
5438 pparams, total_params,
5439 ppdata, total_data,
5440 max_data_bytes);
5441 return;
5444 fsp = file_fsp(req, SVAL(params,0));
5445 info_level = SVAL(params,2);
5447 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5449 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5450 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5451 return;
5454 /* Initial check for valid fsp ptr. */
5455 if (!check_fsp_open(conn, req, fsp)) {
5456 return;
5459 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5460 if (smb_fname == NULL) {
5461 reply_nterror(req, NT_STATUS_NO_MEMORY);
5462 return;
5465 if(fsp->fake_file_handle) {
5467 * This is actually for the QUOTA_FAKE_FILE --metze
5470 /* We know this name is ok, it's already passed the checks. */
5472 } else if(fsp->fh->fd == -1) {
5474 * This is actually a QFILEINFO on a directory
5475 * handle (returned from an NT SMB). NT5.0 seems
5476 * to do this call. JRA.
5479 if (INFO_LEVEL_IS_UNIX(info_level)) {
5480 /* Always do lstat for UNIX calls. */
5481 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5482 DEBUG(3,("call_trans2qfilepathinfo: "
5483 "SMB_VFS_LSTAT of %s failed "
5484 "(%s)\n",
5485 smb_fname_str_dbg(smb_fname),
5486 strerror(errno)));
5487 reply_nterror(req,
5488 map_nt_error_from_unix(errno));
5489 return;
5491 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5492 DEBUG(3,("call_trans2qfilepathinfo: "
5493 "SMB_VFS_STAT of %s failed (%s)\n",
5494 smb_fname_str_dbg(smb_fname),
5495 strerror(errno)));
5496 reply_nterror(req,
5497 map_nt_error_from_unix(errno));
5498 return;
5501 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5502 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5503 } else {
5505 * Original code - this is an open file.
5507 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5508 DEBUG(3, ("fstat of %s failed (%s)\n",
5509 fsp_fnum_dbg(fsp), strerror(errno)));
5510 reply_nterror(req,
5511 map_nt_error_from_unix(errno));
5512 return;
5514 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5515 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5518 } else {
5519 uint32_t name_hash;
5520 char *fname = NULL;
5521 uint32_t ucf_flags = 0;
5523 /* qpathinfo */
5524 if (total_params < 7) {
5525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5526 return;
5529 info_level = SVAL(params,0);
5531 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5533 if (INFO_LEVEL_IS_UNIX(info_level)) {
5534 if (!lp_unix_extensions()) {
5535 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5536 return;
5538 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5539 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5540 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5541 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5545 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5546 total_params - 6,
5547 STR_TERMINATE, &status);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 reply_nterror(req, status);
5550 return;
5553 status = filename_convert(req,
5554 conn,
5555 req->flags2 & FLAGS2_DFS_PATHNAMES,
5556 fname,
5557 ucf_flags,
5558 NULL,
5559 &smb_fname);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5562 reply_botherror(req,
5563 NT_STATUS_PATH_NOT_COVERED,
5564 ERRSRV, ERRbadpath);
5565 return;
5567 reply_nterror(req, status);
5568 return;
5571 /* If this is a stream, check if there is a delete_pending. */
5572 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5573 && is_ntfs_stream_smb_fname(smb_fname)) {
5574 struct smb_filename *smb_fname_base;
5576 /* Create an smb_filename with stream_name == NULL. */
5577 smb_fname_base = synthetic_smb_fname(
5578 talloc_tos(), smb_fname->base_name,
5579 NULL, NULL);
5580 if (smb_fname_base == NULL) {
5581 reply_nterror(req, NT_STATUS_NO_MEMORY);
5582 return;
5585 if (INFO_LEVEL_IS_UNIX(info_level)) {
5586 /* Always do lstat for UNIX calls. */
5587 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5588 DEBUG(3,("call_trans2qfilepathinfo: "
5589 "SMB_VFS_LSTAT of %s failed "
5590 "(%s)\n",
5591 smb_fname_str_dbg(smb_fname_base),
5592 strerror(errno)));
5593 TALLOC_FREE(smb_fname_base);
5594 reply_nterror(req,
5595 map_nt_error_from_unix(errno));
5596 return;
5598 } else {
5599 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5600 DEBUG(3,("call_trans2qfilepathinfo: "
5601 "fileinfo of %s failed "
5602 "(%s)\n",
5603 smb_fname_str_dbg(smb_fname_base),
5604 strerror(errno)));
5605 TALLOC_FREE(smb_fname_base);
5606 reply_nterror(req,
5607 map_nt_error_from_unix(errno));
5608 return;
5612 status = file_name_hash(conn,
5613 smb_fname_str_dbg(smb_fname_base),
5614 &name_hash);
5615 if (!NT_STATUS_IS_OK(status)) {
5616 TALLOC_FREE(smb_fname_base);
5617 reply_nterror(req, status);
5618 return;
5621 fileid = vfs_file_id_from_sbuf(conn,
5622 &smb_fname_base->st);
5623 TALLOC_FREE(smb_fname_base);
5624 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5625 if (delete_pending) {
5626 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5627 return;
5631 if (INFO_LEVEL_IS_UNIX(info_level)) {
5632 /* Always do lstat for UNIX calls. */
5633 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5634 DEBUG(3,("call_trans2qfilepathinfo: "
5635 "SMB_VFS_LSTAT of %s failed (%s)\n",
5636 smb_fname_str_dbg(smb_fname),
5637 strerror(errno)));
5638 reply_nterror(req,
5639 map_nt_error_from_unix(errno));
5640 return;
5643 } else {
5644 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5645 DEBUG(3,("call_trans2qfilepathinfo: "
5646 "SMB_VFS_STAT of %s failed (%s)\n",
5647 smb_fname_str_dbg(smb_fname),
5648 strerror(errno)));
5649 reply_nterror(req,
5650 map_nt_error_from_unix(errno));
5651 return;
5655 status = file_name_hash(conn,
5656 smb_fname_str_dbg(smb_fname),
5657 &name_hash);
5658 if (!NT_STATUS_IS_OK(status)) {
5659 reply_nterror(req, status);
5660 return;
5663 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5664 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5665 if (delete_pending) {
5666 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5667 return;
5671 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5672 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5673 fsp_fnum_dbg(fsp),
5674 info_level,tran_call,total_data));
5676 /* Pull out any data sent here before we realloc. */
5677 switch (info_level) {
5678 case SMB_INFO_QUERY_EAS_FROM_LIST:
5680 /* Pull any EA list from the data portion. */
5681 uint32_t ea_size;
5683 if (total_data < 4) {
5684 reply_nterror(
5685 req, NT_STATUS_INVALID_PARAMETER);
5686 return;
5688 ea_size = IVAL(pdata,0);
5690 if (total_data > 0 && ea_size != total_data) {
5691 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5692 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5693 reply_nterror(
5694 req, NT_STATUS_INVALID_PARAMETER);
5695 return;
5698 if (!lp_ea_support(SNUM(conn))) {
5699 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5700 return;
5703 /* Pull out the list of names. */
5704 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5705 if (!ea_list) {
5706 reply_nterror(
5707 req, NT_STATUS_INVALID_PARAMETER);
5708 return;
5710 break;
5713 case SMB_QUERY_POSIX_LOCK:
5715 if (fsp == NULL || fsp->fh->fd == -1) {
5716 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5717 return;
5720 if (total_data != POSIX_LOCK_DATA_SIZE) {
5721 reply_nterror(
5722 req, NT_STATUS_INVALID_PARAMETER);
5723 return;
5726 /* Copy the lock range data. */
5727 lock_data = (char *)talloc_memdup(
5728 req, pdata, total_data);
5729 if (!lock_data) {
5730 reply_nterror(req, NT_STATUS_NO_MEMORY);
5731 return;
5733 lock_data_count = total_data;
5735 default:
5736 break;
5739 *pparams = (char *)SMB_REALLOC(*pparams,2);
5740 if (*pparams == NULL) {
5741 reply_nterror(req, NT_STATUS_NO_MEMORY);
5742 return;
5744 params = *pparams;
5745 SSVAL(params,0,0);
5748 * draft-leach-cifs-v1-spec-02.txt
5749 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5750 * says:
5752 * The requested information is placed in the Data portion of the
5753 * transaction response. For the information levels greater than 0x100,
5754 * the transaction response has 1 parameter word which should be
5755 * ignored by the client.
5757 * However Windows only follows this rule for the IS_NAME_VALID call.
5759 switch (info_level) {
5760 case SMB_INFO_IS_NAME_VALID:
5761 param_size = 0;
5762 break;
5765 if ((info_level & 0xFF00) == 0xFF00) {
5767 * We use levels that start with 0xFF00
5768 * internally to represent SMB2 specific levels
5770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5771 return;
5774 status = smbd_do_qfilepathinfo(conn, req, info_level,
5775 fsp, smb_fname,
5776 delete_pending, write_time_ts,
5777 ea_list,
5778 lock_data_count, lock_data,
5779 req->flags2, max_data_bytes,
5780 &fixed_portion,
5781 ppdata, &data_size);
5782 if (!NT_STATUS_IS_OK(status)) {
5783 reply_nterror(req, status);
5784 return;
5786 if (fixed_portion > max_data_bytes) {
5787 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5788 return;
5791 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5792 max_data_bytes);
5794 return;
5797 /****************************************************************************
5798 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5799 code.
5800 ****************************************************************************/
5802 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5803 connection_struct *conn,
5804 struct smb_request *req,
5805 bool overwrite_if_exists,
5806 const struct smb_filename *smb_fname_old,
5807 struct smb_filename *smb_fname_new)
5809 NTSTATUS status = NT_STATUS_OK;
5811 /* source must already exist. */
5812 if (!VALID_STAT(smb_fname_old->st)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5816 if (VALID_STAT(smb_fname_new->st)) {
5817 if (overwrite_if_exists) {
5818 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5819 return NT_STATUS_FILE_IS_A_DIRECTORY;
5821 status = unlink_internals(conn,
5822 req,
5823 FILE_ATTRIBUTE_NORMAL,
5824 smb_fname_new,
5825 false);
5826 if (!NT_STATUS_IS_OK(status)) {
5827 return status;
5829 } else {
5830 /* Disallow if newname already exists. */
5831 return NT_STATUS_OBJECT_NAME_COLLISION;
5835 /* No links from a directory. */
5836 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5837 return NT_STATUS_FILE_IS_A_DIRECTORY;
5840 /* Setting a hardlink to/from a stream isn't currently supported. */
5841 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5842 is_ntfs_stream_smb_fname(smb_fname_new)) {
5843 return NT_STATUS_INVALID_PARAMETER;
5846 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5847 smb_fname_old->base_name, smb_fname_new->base_name));
5849 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5850 smb_fname_new->base_name) != 0) {
5851 status = map_nt_error_from_unix(errno);
5852 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5853 nt_errstr(status), smb_fname_old->base_name,
5854 smb_fname_new->base_name));
5856 return status;
5859 /****************************************************************************
5860 Deal with setting the time from any of the setfilepathinfo functions.
5861 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5862 calling this function.
5863 ****************************************************************************/
5865 NTSTATUS smb_set_file_time(connection_struct *conn,
5866 files_struct *fsp,
5867 const struct smb_filename *smb_fname,
5868 struct smb_file_time *ft,
5869 bool setting_write_time)
5871 struct smb_filename smb_fname_base;
5872 uint32_t action =
5873 FILE_NOTIFY_CHANGE_LAST_ACCESS
5874 |FILE_NOTIFY_CHANGE_LAST_WRITE
5875 |FILE_NOTIFY_CHANGE_CREATION;
5877 if (!VALID_STAT(smb_fname->st)) {
5878 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5881 /* get some defaults (no modifications) if any info is zero or -1. */
5882 if (null_timespec(ft->create_time)) {
5883 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5886 if (null_timespec(ft->atime)) {
5887 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5890 if (null_timespec(ft->mtime)) {
5891 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5894 if (!setting_write_time) {
5895 /* ft->mtime comes from change time, not write time. */
5896 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5899 /* Ensure the resolution is the correct for
5900 * what we can store on this filesystem. */
5902 round_timespec(conn->ts_res, &ft->create_time);
5903 round_timespec(conn->ts_res, &ft->ctime);
5904 round_timespec(conn->ts_res, &ft->atime);
5905 round_timespec(conn->ts_res, &ft->mtime);
5907 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5908 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5909 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5910 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5911 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5912 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5913 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5914 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5916 if (setting_write_time) {
5918 * This was a Windows setfileinfo on an open file.
5919 * NT does this a lot. We also need to
5920 * set the time here, as it can be read by
5921 * FindFirst/FindNext and with the patch for bug #2045
5922 * in smbd/fileio.c it ensures that this timestamp is
5923 * kept sticky even after a write. We save the request
5924 * away and will set it on file close and after a write. JRA.
5927 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5928 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5930 if (fsp != NULL) {
5931 if (fsp->base_fsp) {
5932 set_sticky_write_time_fsp(fsp->base_fsp,
5933 ft->mtime);
5934 } else {
5935 set_sticky_write_time_fsp(fsp, ft->mtime);
5937 } else {
5938 set_sticky_write_time_path(
5939 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5940 ft->mtime);
5944 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5946 /* Always call ntimes on the base, even if a stream was passed in. */
5947 smb_fname_base = *smb_fname;
5948 smb_fname_base.stream_name = NULL;
5950 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5951 return map_nt_error_from_unix(errno);
5954 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5955 smb_fname->base_name);
5956 return NT_STATUS_OK;
5959 /****************************************************************************
5960 Deal with setting the dosmode from any of the setfilepathinfo functions.
5961 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5962 done before calling this function.
5963 ****************************************************************************/
5965 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5966 const struct smb_filename *smb_fname,
5967 uint32_t dosmode)
5969 struct smb_filename *smb_fname_base;
5970 NTSTATUS status;
5972 if (!VALID_STAT(smb_fname->st)) {
5973 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5976 /* Always operate on the base_name, even if a stream was passed in. */
5977 smb_fname_base = synthetic_smb_fname(
5978 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5979 if (smb_fname_base == NULL) {
5980 return NT_STATUS_NO_MEMORY;
5983 if (dosmode) {
5984 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5985 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5986 } else {
5987 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5991 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5993 /* check the mode isn't different, before changing it */
5994 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5995 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5996 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5997 (unsigned int)dosmode));
5999 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6000 false)) {
6001 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6002 "%s failed (%s)\n",
6003 smb_fname_str_dbg(smb_fname_base),
6004 strerror(errno)));
6005 status = map_nt_error_from_unix(errno);
6006 goto out;
6009 status = NT_STATUS_OK;
6010 out:
6011 TALLOC_FREE(smb_fname_base);
6012 return status;
6015 /****************************************************************************
6016 Deal with setting the size from any of the setfilepathinfo functions.
6017 ****************************************************************************/
6019 static NTSTATUS smb_set_file_size(connection_struct *conn,
6020 struct smb_request *req,
6021 files_struct *fsp,
6022 const struct smb_filename *smb_fname,
6023 const SMB_STRUCT_STAT *psbuf,
6024 off_t size,
6025 bool fail_after_createfile)
6027 NTSTATUS status = NT_STATUS_OK;
6028 struct smb_filename *smb_fname_tmp = NULL;
6029 files_struct *new_fsp = NULL;
6031 if (!VALID_STAT(*psbuf)) {
6032 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6035 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6037 if (size == get_file_size_stat(psbuf)) {
6038 return NT_STATUS_OK;
6041 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6042 smb_fname_str_dbg(smb_fname), (double)size));
6044 if (fsp && fsp->fh->fd != -1) {
6045 /* Handle based call. */
6046 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6047 return NT_STATUS_ACCESS_DENIED;
6050 if (vfs_set_filelen(fsp, size) == -1) {
6051 return map_nt_error_from_unix(errno);
6053 trigger_write_time_update_immediate(fsp);
6054 return NT_STATUS_OK;
6057 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6058 if (smb_fname_tmp == NULL) {
6059 return NT_STATUS_NO_MEMORY;
6062 smb_fname_tmp->st = *psbuf;
6064 status = SMB_VFS_CREATE_FILE(
6065 conn, /* conn */
6066 req, /* req */
6067 0, /* root_dir_fid */
6068 smb_fname_tmp, /* fname */
6069 FILE_WRITE_DATA, /* access_mask */
6070 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6071 FILE_SHARE_DELETE),
6072 FILE_OPEN, /* create_disposition*/
6073 0, /* create_options */
6074 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6075 0, /* oplock_request */
6076 NULL, /* lease */
6077 0, /* allocation_size */
6078 0, /* private_flags */
6079 NULL, /* sd */
6080 NULL, /* ea_list */
6081 &new_fsp, /* result */
6082 NULL, /* pinfo */
6083 NULL, NULL); /* create context */
6085 TALLOC_FREE(smb_fname_tmp);
6087 if (!NT_STATUS_IS_OK(status)) {
6088 /* NB. We check for open_was_deferred in the caller. */
6089 return status;
6092 /* See RAW-SFILEINFO-END-OF-FILE */
6093 if (fail_after_createfile) {
6094 close_file(req, new_fsp,NORMAL_CLOSE);
6095 return NT_STATUS_INVALID_LEVEL;
6098 if (vfs_set_filelen(new_fsp, size) == -1) {
6099 status = map_nt_error_from_unix(errno);
6100 close_file(req, new_fsp,NORMAL_CLOSE);
6101 return status;
6104 trigger_write_time_update_immediate(new_fsp);
6105 close_file(req, new_fsp,NORMAL_CLOSE);
6106 return NT_STATUS_OK;
6109 /****************************************************************************
6110 Deal with SMB_INFO_SET_EA.
6111 ****************************************************************************/
6113 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6114 const char *pdata,
6115 int total_data,
6116 files_struct *fsp,
6117 const struct smb_filename *smb_fname)
6119 struct ea_list *ea_list = NULL;
6120 TALLOC_CTX *ctx = NULL;
6121 NTSTATUS status = NT_STATUS_OK;
6123 if (total_data < 10) {
6125 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6126 length. They seem to have no effect. Bug #3212. JRA */
6128 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6129 /* We're done. We only get EA info in this call. */
6130 return NT_STATUS_OK;
6133 return NT_STATUS_INVALID_PARAMETER;
6136 if (IVAL(pdata,0) > total_data) {
6137 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6138 IVAL(pdata,0), (unsigned int)total_data));
6139 return NT_STATUS_INVALID_PARAMETER;
6142 ctx = talloc_tos();
6143 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6144 if (!ea_list) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 status = set_ea(conn, fsp, smb_fname, ea_list);
6150 return status;
6153 /****************************************************************************
6154 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6155 ****************************************************************************/
6157 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6158 const char *pdata,
6159 int total_data,
6160 files_struct *fsp)
6162 struct ea_list *ea_list = NULL;
6163 NTSTATUS status;
6165 if (!fsp) {
6166 return NT_STATUS_INVALID_HANDLE;
6169 if (!lp_ea_support(SNUM(conn))) {
6170 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6171 "EA's not supported.\n",
6172 (unsigned int)total_data));
6173 return NT_STATUS_EAS_NOT_SUPPORTED;
6176 if (total_data < 10) {
6177 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6178 "too small.\n",
6179 (unsigned int)total_data));
6180 return NT_STATUS_INVALID_PARAMETER;
6183 ea_list = read_nttrans_ea_list(talloc_tos(),
6184 pdata,
6185 total_data);
6187 if (!ea_list) {
6188 return NT_STATUS_INVALID_PARAMETER;
6191 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6193 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6194 smb_fname_str_dbg(fsp->fsp_name),
6195 nt_errstr(status) ));
6197 return status;
6201 /****************************************************************************
6202 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6203 ****************************************************************************/
6205 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6206 const char *pdata,
6207 int total_data,
6208 files_struct *fsp,
6209 struct smb_filename *smb_fname)
6211 NTSTATUS status = NT_STATUS_OK;
6212 bool delete_on_close;
6213 uint32_t dosmode = 0;
6215 if (total_data < 1) {
6216 return NT_STATUS_INVALID_PARAMETER;
6219 if (fsp == NULL) {
6220 return NT_STATUS_INVALID_HANDLE;
6223 delete_on_close = (CVAL(pdata,0) ? True : False);
6224 dosmode = dos_mode(conn, smb_fname);
6226 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6227 "delete_on_close = %u\n",
6228 smb_fname_str_dbg(smb_fname),
6229 (unsigned int)dosmode,
6230 (unsigned int)delete_on_close ));
6232 if (delete_on_close) {
6233 status = can_set_delete_on_close(fsp, dosmode);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 return status;
6239 /* The set is across all open files on this dev/inode pair. */
6240 if (!set_delete_on_close(fsp, delete_on_close,
6241 conn->session_info->security_token,
6242 conn->session_info->unix_token)) {
6243 return NT_STATUS_ACCESS_DENIED;
6245 return NT_STATUS_OK;
6248 /****************************************************************************
6249 Deal with SMB_FILE_POSITION_INFORMATION.
6250 ****************************************************************************/
6252 static NTSTATUS smb_file_position_information(connection_struct *conn,
6253 const char *pdata,
6254 int total_data,
6255 files_struct *fsp)
6257 uint64_t position_information;
6259 if (total_data < 8) {
6260 return NT_STATUS_INVALID_PARAMETER;
6263 if (fsp == NULL) {
6264 /* Ignore on pathname based set. */
6265 return NT_STATUS_OK;
6268 position_information = (uint64_t)IVAL(pdata,0);
6269 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6271 DEBUG(10,("smb_file_position_information: Set file position "
6272 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6273 (double)position_information));
6274 fsp->fh->position_information = position_information;
6275 return NT_STATUS_OK;
6278 /****************************************************************************
6279 Deal with SMB_FILE_MODE_INFORMATION.
6280 ****************************************************************************/
6282 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6283 const char *pdata,
6284 int total_data)
6286 uint32_t mode;
6288 if (total_data < 4) {
6289 return NT_STATUS_INVALID_PARAMETER;
6291 mode = IVAL(pdata,0);
6292 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6293 return NT_STATUS_INVALID_PARAMETER;
6295 return NT_STATUS_OK;
6298 /****************************************************************************
6299 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6300 ****************************************************************************/
6302 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6303 struct smb_request *req,
6304 const char *pdata,
6305 int total_data,
6306 const struct smb_filename *smb_fname)
6308 char *link_target = NULL;
6309 const char *newname = smb_fname->base_name;
6310 TALLOC_CTX *ctx = talloc_tos();
6312 /* Set a symbolic link. */
6313 /* Don't allow this if follow links is false. */
6315 if (total_data == 0) {
6316 return NT_STATUS_INVALID_PARAMETER;
6319 if (!lp_follow_symlinks(SNUM(conn))) {
6320 return NT_STATUS_ACCESS_DENIED;
6323 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6324 total_data, STR_TERMINATE);
6326 if (!link_target) {
6327 return NT_STATUS_INVALID_PARAMETER;
6330 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6331 newname, link_target ));
6333 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6334 return map_nt_error_from_unix(errno);
6337 return NT_STATUS_OK;
6340 /****************************************************************************
6341 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6342 ****************************************************************************/
6344 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6345 struct smb_request *req,
6346 const char *pdata, int total_data,
6347 struct smb_filename *smb_fname_new)
6349 char *oldname = NULL;
6350 struct smb_filename *smb_fname_old = NULL;
6351 TALLOC_CTX *ctx = talloc_tos();
6352 NTSTATUS status = NT_STATUS_OK;
6354 /* Set a hard link. */
6355 if (total_data == 0) {
6356 return NT_STATUS_INVALID_PARAMETER;
6359 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6360 total_data, STR_TERMINATE, &status);
6361 if (!NT_STATUS_IS_OK(status)) {
6362 return status;
6365 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6366 smb_fname_str_dbg(smb_fname_new), oldname));
6368 status = filename_convert(ctx,
6369 conn,
6370 req->flags2 & FLAGS2_DFS_PATHNAMES,
6371 oldname,
6373 NULL,
6374 &smb_fname_old);
6375 if (!NT_STATUS_IS_OK(status)) {
6376 return status;
6379 return hardlink_internals(ctx, conn, req, false,
6380 smb_fname_old, smb_fname_new);
6383 /****************************************************************************
6384 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6385 ****************************************************************************/
6387 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6388 struct smb_request *req,
6389 const char *pdata,
6390 int total_data,
6391 files_struct *fsp,
6392 struct smb_filename *smb_fname_src)
6394 bool overwrite;
6395 uint32_t len;
6396 char *newname = NULL;
6397 struct smb_filename *smb_fname_dst = NULL;
6398 NTSTATUS status = NT_STATUS_OK;
6399 TALLOC_CTX *ctx = talloc_tos();
6401 if (!fsp) {
6402 return NT_STATUS_INVALID_HANDLE;
6405 if (total_data < 20) {
6406 return NT_STATUS_INVALID_PARAMETER;
6409 overwrite = (CVAL(pdata,0) ? True : False);
6410 len = IVAL(pdata,16);
6412 if (len > (total_data - 20) || (len == 0)) {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6417 &pdata[20], len, STR_TERMINATE,
6418 &status);
6419 if (!NT_STATUS_IS_OK(status)) {
6420 return status;
6423 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6424 newname));
6426 status = filename_convert(ctx,
6427 conn,
6428 req->flags2 & FLAGS2_DFS_PATHNAMES,
6429 newname,
6430 UCF_SAVE_LCOMP,
6431 NULL,
6432 &smb_fname_dst);
6433 if (!NT_STATUS_IS_OK(status)) {
6434 return status;
6437 if (fsp->base_fsp) {
6438 /* newname must be a stream name. */
6439 if (newname[0] != ':') {
6440 return NT_STATUS_NOT_SUPPORTED;
6443 /* Create an smb_fname to call rename_internals_fsp() with. */
6444 smb_fname_dst = synthetic_smb_fname(
6445 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6446 newname, NULL);
6447 if (smb_fname_dst == NULL) {
6448 status = NT_STATUS_NO_MEMORY;
6449 goto out;
6453 * Set the original last component, since
6454 * rename_internals_fsp() requires it.
6456 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6457 newname);
6458 if (smb_fname_dst->original_lcomp == NULL) {
6459 status = NT_STATUS_NO_MEMORY;
6460 goto out;
6465 DEBUG(10,("smb2_file_rename_information: "
6466 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6467 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6468 smb_fname_str_dbg(smb_fname_dst)));
6469 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6470 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6471 overwrite);
6473 out:
6474 TALLOC_FREE(smb_fname_dst);
6475 return status;
6478 static NTSTATUS smb_file_link_information(connection_struct *conn,
6479 struct smb_request *req,
6480 const char *pdata,
6481 int total_data,
6482 files_struct *fsp,
6483 struct smb_filename *smb_fname_src)
6485 bool overwrite;
6486 uint32_t len;
6487 char *newname = NULL;
6488 struct smb_filename *smb_fname_dst = NULL;
6489 NTSTATUS status = NT_STATUS_OK;
6490 TALLOC_CTX *ctx = talloc_tos();
6492 if (!fsp) {
6493 return NT_STATUS_INVALID_HANDLE;
6496 if (total_data < 20) {
6497 return NT_STATUS_INVALID_PARAMETER;
6500 overwrite = (CVAL(pdata,0) ? true : false);
6501 len = IVAL(pdata,16);
6503 if (len > (total_data - 20) || (len == 0)) {
6504 return NT_STATUS_INVALID_PARAMETER;
6507 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6508 &pdata[20], len, STR_TERMINATE,
6509 &status);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 return status;
6514 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6515 newname));
6517 status = filename_convert(ctx,
6518 conn,
6519 req->flags2 & FLAGS2_DFS_PATHNAMES,
6520 newname,
6521 UCF_SAVE_LCOMP,
6522 NULL,
6523 &smb_fname_dst);
6524 if (!NT_STATUS_IS_OK(status)) {
6525 return status;
6528 if (fsp->base_fsp) {
6529 /* No stream names. */
6530 return NT_STATUS_NOT_SUPPORTED;
6533 DEBUG(10,("smb_file_link_information: "
6534 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6535 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6536 smb_fname_str_dbg(smb_fname_dst)));
6537 status = hardlink_internals(ctx,
6538 conn,
6539 req,
6540 overwrite,
6541 fsp->fsp_name,
6542 smb_fname_dst);
6544 TALLOC_FREE(smb_fname_dst);
6545 return status;
6548 /****************************************************************************
6549 Deal with SMB_FILE_RENAME_INFORMATION.
6550 ****************************************************************************/
6552 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6553 struct smb_request *req,
6554 const char *pdata,
6555 int total_data,
6556 files_struct *fsp,
6557 struct smb_filename *smb_fname_src)
6559 bool overwrite;
6560 uint32_t root_fid;
6561 uint32_t len;
6562 char *newname = NULL;
6563 struct smb_filename *smb_fname_dst = NULL;
6564 bool dest_has_wcard = False;
6565 NTSTATUS status = NT_STATUS_OK;
6566 char *p;
6567 TALLOC_CTX *ctx = talloc_tos();
6569 if (total_data < 13) {
6570 return NT_STATUS_INVALID_PARAMETER;
6573 overwrite = (CVAL(pdata,0) ? True : False);
6574 root_fid = IVAL(pdata,4);
6575 len = IVAL(pdata,8);
6577 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6578 return NT_STATUS_INVALID_PARAMETER;
6581 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6582 len, 0, &status,
6583 &dest_has_wcard);
6584 if (!NT_STATUS_IS_OK(status)) {
6585 return status;
6588 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6589 newname));
6591 status = resolve_dfspath_wcard(ctx, conn,
6592 req->flags2 & FLAGS2_DFS_PATHNAMES,
6593 newname,
6594 true,
6595 !conn->sconn->using_smb2,
6596 &newname,
6597 &dest_has_wcard);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 return status;
6602 /* Check the new name has no '/' characters. */
6603 if (strchr_m(newname, '/')) {
6604 return NT_STATUS_NOT_SUPPORTED;
6607 if (fsp && fsp->base_fsp) {
6608 /* newname must be a stream name. */
6609 if (newname[0] != ':') {
6610 return NT_STATUS_NOT_SUPPORTED;
6613 /* Create an smb_fname to call rename_internals_fsp() with. */
6614 smb_fname_dst = synthetic_smb_fname(
6615 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6616 newname, NULL);
6617 if (smb_fname_dst == NULL) {
6618 status = NT_STATUS_NO_MEMORY;
6619 goto out;
6623 * Set the original last component, since
6624 * rename_internals_fsp() requires it.
6626 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6627 newname);
6628 if (smb_fname_dst->original_lcomp == NULL) {
6629 status = NT_STATUS_NO_MEMORY;
6630 goto out;
6633 } else {
6635 * Build up an smb_fname_dst based on the filename passed in.
6636 * We basically just strip off the last component, and put on
6637 * the newname instead.
6639 char *base_name = NULL;
6641 /* newname must *not* be a stream name. */
6642 if (newname[0] == ':') {
6643 return NT_STATUS_NOT_SUPPORTED;
6647 * Strip off the last component (filename) of the path passed
6648 * in.
6650 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6651 if (!base_name) {
6652 return NT_STATUS_NO_MEMORY;
6654 p = strrchr_m(base_name, '/');
6655 if (p) {
6656 p[1] = '\0';
6657 } else {
6658 base_name = talloc_strdup(ctx, "");
6659 if (!base_name) {
6660 return NT_STATUS_NO_MEMORY;
6663 /* Append the new name. */
6664 base_name = talloc_asprintf_append(base_name,
6665 "%s",
6666 newname);
6667 if (!base_name) {
6668 return NT_STATUS_NO_MEMORY;
6671 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6672 (UCF_SAVE_LCOMP |
6673 (dest_has_wcard ?
6674 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6675 0)));
6677 /* If an error we expect this to be
6678 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6680 if (!NT_STATUS_IS_OK(status)) {
6681 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6682 status)) {
6683 goto out;
6685 /* Create an smb_fname to call rename_internals_fsp() */
6686 smb_fname_dst = synthetic_smb_fname(
6687 ctx, base_name, NULL, NULL);
6688 if (smb_fname_dst == NULL) {
6689 status = NT_STATUS_NO_MEMORY;
6690 goto out;
6695 if (fsp) {
6696 DEBUG(10,("smb_file_rename_information: "
6697 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6698 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6699 smb_fname_str_dbg(smb_fname_dst)));
6700 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6701 overwrite);
6702 } else {
6703 DEBUG(10,("smb_file_rename_information: "
6704 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6705 smb_fname_str_dbg(smb_fname_src),
6706 smb_fname_str_dbg(smb_fname_dst)));
6707 status = rename_internals(ctx, conn, req, smb_fname_src,
6708 smb_fname_dst, 0, overwrite, false,
6709 dest_has_wcard,
6710 FILE_WRITE_ATTRIBUTES);
6712 out:
6713 TALLOC_FREE(smb_fname_dst);
6714 return status;
6717 /****************************************************************************
6718 Deal with SMB_SET_POSIX_ACL.
6719 ****************************************************************************/
6721 #if defined(HAVE_POSIX_ACLS)
6722 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6723 const char *pdata,
6724 int total_data,
6725 files_struct *fsp,
6726 const struct smb_filename *smb_fname)
6728 uint16_t posix_acl_version;
6729 uint16_t num_file_acls;
6730 uint16_t num_def_acls;
6731 bool valid_file_acls = True;
6732 bool valid_def_acls = True;
6734 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6735 return NT_STATUS_INVALID_PARAMETER;
6737 posix_acl_version = SVAL(pdata,0);
6738 num_file_acls = SVAL(pdata,2);
6739 num_def_acls = SVAL(pdata,4);
6741 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6742 valid_file_acls = False;
6743 num_file_acls = 0;
6746 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6747 valid_def_acls = False;
6748 num_def_acls = 0;
6751 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6752 return NT_STATUS_INVALID_PARAMETER;
6755 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6756 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6757 return NT_STATUS_INVALID_PARAMETER;
6760 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6761 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6762 (unsigned int)num_file_acls,
6763 (unsigned int)num_def_acls));
6765 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6766 smb_fname->base_name, num_file_acls,
6767 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6768 return map_nt_error_from_unix(errno);
6771 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6772 smb_fname->base_name, &smb_fname->st, num_def_acls,
6773 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6774 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6775 return map_nt_error_from_unix(errno);
6777 return NT_STATUS_OK;
6779 #endif
6781 /****************************************************************************
6782 Deal with SMB_SET_POSIX_LOCK.
6783 ****************************************************************************/
6785 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6786 struct smb_request *req,
6787 const char *pdata,
6788 int total_data,
6789 files_struct *fsp)
6791 uint64_t count;
6792 uint64_t offset;
6793 uint64_t smblctx;
6794 bool blocking_lock = False;
6795 enum brl_type lock_type;
6797 NTSTATUS status = NT_STATUS_OK;
6799 if (fsp == NULL || fsp->fh->fd == -1) {
6800 return NT_STATUS_INVALID_HANDLE;
6803 if (total_data != POSIX_LOCK_DATA_SIZE) {
6804 return NT_STATUS_INVALID_PARAMETER;
6807 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6808 case POSIX_LOCK_TYPE_READ:
6809 lock_type = READ_LOCK;
6810 break;
6811 case POSIX_LOCK_TYPE_WRITE:
6812 /* Return the right POSIX-mappable error code for files opened read-only. */
6813 if (!fsp->can_write) {
6814 return NT_STATUS_INVALID_HANDLE;
6816 lock_type = WRITE_LOCK;
6817 break;
6818 case POSIX_LOCK_TYPE_UNLOCK:
6819 lock_type = UNLOCK_LOCK;
6820 break;
6821 default:
6822 return NT_STATUS_INVALID_PARAMETER;
6825 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6826 blocking_lock = False;
6827 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6828 blocking_lock = True;
6829 } else {
6830 return NT_STATUS_INVALID_PARAMETER;
6833 if (!lp_blocking_locks(SNUM(conn))) {
6834 blocking_lock = False;
6837 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6838 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6839 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6840 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6841 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6843 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6844 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6845 fsp_str_dbg(fsp),
6846 (unsigned int)lock_type,
6847 (unsigned long long)smblctx,
6848 (double)count,
6849 (double)offset ));
6851 if (lock_type == UNLOCK_LOCK) {
6852 status = do_unlock(req->sconn->msg_ctx,
6853 fsp,
6854 smblctx,
6855 count,
6856 offset,
6857 POSIX_LOCK);
6858 } else {
6859 uint64_t block_smblctx;
6861 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6862 fsp,
6863 smblctx,
6864 count,
6865 offset,
6866 lock_type,
6867 POSIX_LOCK,
6868 blocking_lock,
6869 &status,
6870 &block_smblctx);
6872 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6874 * A blocking lock was requested. Package up
6875 * this smb into a queued request and push it
6876 * onto the blocking lock queue.
6878 if(push_blocking_lock_request(br_lck,
6879 req,
6880 fsp,
6881 -1, /* infinite timeout. */
6883 smblctx,
6884 lock_type,
6885 POSIX_LOCK,
6886 offset,
6887 count,
6888 block_smblctx)) {
6889 TALLOC_FREE(br_lck);
6890 return status;
6893 TALLOC_FREE(br_lck);
6896 return status;
6899 /****************************************************************************
6900 Deal with SMB_SET_FILE_BASIC_INFO.
6901 ****************************************************************************/
6903 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6904 const char *pdata,
6905 int total_data,
6906 files_struct *fsp,
6907 const struct smb_filename *smb_fname)
6909 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6910 struct smb_file_time ft;
6911 uint32_t dosmode = 0;
6912 NTSTATUS status = NT_STATUS_OK;
6914 ZERO_STRUCT(ft);
6916 if (total_data < 36) {
6917 return NT_STATUS_INVALID_PARAMETER;
6920 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6921 if (!NT_STATUS_IS_OK(status)) {
6922 return status;
6925 /* Set the attributes */
6926 dosmode = IVAL(pdata,32);
6927 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6928 if (!NT_STATUS_IS_OK(status)) {
6929 return status;
6932 /* create time */
6933 ft.create_time = interpret_long_date(pdata);
6935 /* access time */
6936 ft.atime = interpret_long_date(pdata+8);
6938 /* write time. */
6939 ft.mtime = interpret_long_date(pdata+16);
6941 /* change time. */
6942 ft.ctime = interpret_long_date(pdata+24);
6944 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6945 smb_fname_str_dbg(smb_fname)));
6947 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6948 true);
6951 /****************************************************************************
6952 Deal with SMB_INFO_STANDARD.
6953 ****************************************************************************/
6955 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6956 const char *pdata,
6957 int total_data,
6958 files_struct *fsp,
6959 const struct smb_filename *smb_fname)
6961 NTSTATUS status;
6962 struct smb_file_time ft;
6964 ZERO_STRUCT(ft);
6966 if (total_data < 12) {
6967 return NT_STATUS_INVALID_PARAMETER;
6970 /* create time */
6971 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6972 /* access time */
6973 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6974 /* write time */
6975 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6977 DEBUG(10,("smb_set_info_standard: file %s\n",
6978 smb_fname_str_dbg(smb_fname)));
6980 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6981 if (!NT_STATUS_IS_OK(status)) {
6982 return status;
6985 return smb_set_file_time(conn,
6986 fsp,
6987 smb_fname,
6988 &ft,
6989 true);
6992 /****************************************************************************
6993 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6994 ****************************************************************************/
6996 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6997 struct smb_request *req,
6998 const char *pdata,
6999 int total_data,
7000 files_struct *fsp,
7001 struct smb_filename *smb_fname)
7003 uint64_t allocation_size = 0;
7004 NTSTATUS status = NT_STATUS_OK;
7005 files_struct *new_fsp = NULL;
7007 if (!VALID_STAT(smb_fname->st)) {
7008 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7011 if (total_data < 8) {
7012 return NT_STATUS_INVALID_PARAMETER;
7015 allocation_size = (uint64_t)IVAL(pdata,0);
7016 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7017 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7018 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7019 (double)allocation_size));
7021 if (allocation_size) {
7022 allocation_size = smb_roundup(conn, allocation_size);
7025 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7026 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7027 (double)allocation_size));
7029 if (fsp && fsp->fh->fd != -1) {
7030 /* Open file handle. */
7031 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7032 return NT_STATUS_ACCESS_DENIED;
7035 /* Only change if needed. */
7036 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7037 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7038 return map_nt_error_from_unix(errno);
7041 /* But always update the time. */
7043 * This is equivalent to a write. Ensure it's seen immediately
7044 * if there are no pending writes.
7046 trigger_write_time_update_immediate(fsp);
7047 return NT_STATUS_OK;
7050 /* Pathname or stat or directory file. */
7051 status = SMB_VFS_CREATE_FILE(
7052 conn, /* conn */
7053 req, /* req */
7054 0, /* root_dir_fid */
7055 smb_fname, /* fname */
7056 FILE_WRITE_DATA, /* access_mask */
7057 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7058 FILE_SHARE_DELETE),
7059 FILE_OPEN, /* create_disposition*/
7060 0, /* create_options */
7061 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7062 0, /* oplock_request */
7063 NULL, /* lease */
7064 0, /* allocation_size */
7065 0, /* private_flags */
7066 NULL, /* sd */
7067 NULL, /* ea_list */
7068 &new_fsp, /* result */
7069 NULL, /* pinfo */
7070 NULL, NULL); /* create context */
7072 if (!NT_STATUS_IS_OK(status)) {
7073 /* NB. We check for open_was_deferred in the caller. */
7074 return status;
7077 /* Only change if needed. */
7078 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7079 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7080 status = map_nt_error_from_unix(errno);
7081 close_file(req, new_fsp, NORMAL_CLOSE);
7082 return status;
7086 /* Changing the allocation size should set the last mod time. */
7088 * This is equivalent to a write. Ensure it's seen immediately
7089 * if there are no pending writes.
7091 trigger_write_time_update_immediate(new_fsp);
7092 close_file(req, new_fsp, NORMAL_CLOSE);
7093 return NT_STATUS_OK;
7096 /****************************************************************************
7097 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7098 ****************************************************************************/
7100 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7101 struct smb_request *req,
7102 const char *pdata,
7103 int total_data,
7104 files_struct *fsp,
7105 const struct smb_filename *smb_fname,
7106 bool fail_after_createfile)
7108 off_t size;
7110 if (total_data < 8) {
7111 return NT_STATUS_INVALID_PARAMETER;
7114 size = IVAL(pdata,0);
7115 size |= (((off_t)IVAL(pdata,4)) << 32);
7116 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7117 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7118 (double)size));
7120 return smb_set_file_size(conn, req,
7121 fsp,
7122 smb_fname,
7123 &smb_fname->st,
7124 size,
7125 fail_after_createfile);
7128 /****************************************************************************
7129 Allow a UNIX info mknod.
7130 ****************************************************************************/
7132 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7133 const char *pdata,
7134 int total_data,
7135 const struct smb_filename *smb_fname)
7137 uint32_t file_type = IVAL(pdata,56);
7138 #if defined(HAVE_MAKEDEV)
7139 uint32_t dev_major = IVAL(pdata,60);
7140 uint32_t dev_minor = IVAL(pdata,68);
7141 #endif
7142 SMB_DEV_T dev = (SMB_DEV_T)0;
7143 uint32_t raw_unixmode = IVAL(pdata,84);
7144 NTSTATUS status;
7145 mode_t unixmode;
7147 if (total_data < 100) {
7148 return NT_STATUS_INVALID_PARAMETER;
7151 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7152 PERM_NEW_FILE, &unixmode);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 return status;
7157 #if defined(HAVE_MAKEDEV)
7158 dev = makedev(dev_major, dev_minor);
7159 #endif
7161 switch (file_type) {
7162 #if defined(S_IFIFO)
7163 case UNIX_TYPE_FIFO:
7164 unixmode |= S_IFIFO;
7165 break;
7166 #endif
7167 #if defined(S_IFSOCK)
7168 case UNIX_TYPE_SOCKET:
7169 unixmode |= S_IFSOCK;
7170 break;
7171 #endif
7172 #if defined(S_IFCHR)
7173 case UNIX_TYPE_CHARDEV:
7174 unixmode |= S_IFCHR;
7175 break;
7176 #endif
7177 #if defined(S_IFBLK)
7178 case UNIX_TYPE_BLKDEV:
7179 unixmode |= S_IFBLK;
7180 break;
7181 #endif
7182 default:
7183 return NT_STATUS_INVALID_PARAMETER;
7186 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7187 "%.0f mode 0%o for file %s\n", (double)dev,
7188 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7190 /* Ok - do the mknod. */
7191 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7192 return map_nt_error_from_unix(errno);
7195 /* If any of the other "set" calls fail we
7196 * don't want to end up with a half-constructed mknod.
7199 if (lp_inherit_permissions(SNUM(conn))) {
7200 char *parent;
7201 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7202 &parent, NULL)) {
7203 return NT_STATUS_NO_MEMORY;
7205 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7206 unixmode);
7207 TALLOC_FREE(parent);
7210 return NT_STATUS_OK;
7213 /****************************************************************************
7214 Deal with SMB_SET_FILE_UNIX_BASIC.
7215 ****************************************************************************/
7217 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7218 struct smb_request *req,
7219 const char *pdata,
7220 int total_data,
7221 files_struct *fsp,
7222 const struct smb_filename *smb_fname)
7224 struct smb_file_time ft;
7225 uint32_t raw_unixmode;
7226 mode_t unixmode;
7227 off_t size = 0;
7228 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7229 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7230 NTSTATUS status = NT_STATUS_OK;
7231 bool delete_on_fail = False;
7232 enum perm_type ptype;
7233 files_struct *all_fsps = NULL;
7234 bool modify_mtime = true;
7235 struct file_id id;
7236 struct smb_filename *smb_fname_tmp = NULL;
7237 SMB_STRUCT_STAT sbuf;
7239 ZERO_STRUCT(ft);
7241 if (total_data < 100) {
7242 return NT_STATUS_INVALID_PARAMETER;
7245 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7246 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7247 size=IVAL(pdata,0); /* first 8 Bytes are size */
7248 size |= (((off_t)IVAL(pdata,4)) << 32);
7251 ft.atime = interpret_long_date(pdata+24); /* access_time */
7252 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7253 set_owner = (uid_t)IVAL(pdata,40);
7254 set_grp = (gid_t)IVAL(pdata,48);
7255 raw_unixmode = IVAL(pdata,84);
7257 if (VALID_STAT(smb_fname->st)) {
7258 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7259 ptype = PERM_EXISTING_DIR;
7260 } else {
7261 ptype = PERM_EXISTING_FILE;
7263 } else {
7264 ptype = PERM_NEW_FILE;
7267 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7268 ptype, &unixmode);
7269 if (!NT_STATUS_IS_OK(status)) {
7270 return status;
7273 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7274 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7275 smb_fname_str_dbg(smb_fname), (double)size,
7276 (unsigned int)set_owner, (unsigned int)set_grp,
7277 (int)raw_unixmode));
7279 sbuf = smb_fname->st;
7281 if (!VALID_STAT(sbuf)) {
7283 * The only valid use of this is to create character and block
7284 * devices, and named pipes. This is deprecated (IMHO) and
7285 * a new info level should be used for mknod. JRA.
7288 status = smb_unix_mknod(conn,
7289 pdata,
7290 total_data,
7291 smb_fname);
7292 if (!NT_STATUS_IS_OK(status)) {
7293 return status;
7296 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7297 if (smb_fname_tmp == NULL) {
7298 return NT_STATUS_NO_MEMORY;
7301 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7302 status = map_nt_error_from_unix(errno);
7303 TALLOC_FREE(smb_fname_tmp);
7304 SMB_VFS_UNLINK(conn, smb_fname);
7305 return status;
7308 sbuf = smb_fname_tmp->st;
7309 smb_fname = smb_fname_tmp;
7311 /* Ensure we don't try and change anything else. */
7312 raw_unixmode = SMB_MODE_NO_CHANGE;
7313 size = get_file_size_stat(&sbuf);
7314 ft.atime = sbuf.st_ex_atime;
7315 ft.mtime = sbuf.st_ex_mtime;
7317 * We continue here as we might want to change the
7318 * owner uid/gid.
7320 delete_on_fail = True;
7323 #if 1
7324 /* Horrible backwards compatibility hack as an old server bug
7325 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7326 * */
7328 if (!size) {
7329 size = get_file_size_stat(&sbuf);
7331 #endif
7334 * Deal with the UNIX specific mode set.
7337 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7338 int ret;
7340 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7341 "setting mode 0%o for file %s\n",
7342 (unsigned int)unixmode,
7343 smb_fname_str_dbg(smb_fname)));
7344 if (fsp && fsp->fh->fd != -1) {
7345 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7346 } else {
7347 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7349 if (ret != 0) {
7350 return map_nt_error_from_unix(errno);
7355 * Deal with the UNIX specific uid set.
7358 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7359 (sbuf.st_ex_uid != set_owner)) {
7360 int ret;
7362 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7363 "changing owner %u for path %s\n",
7364 (unsigned int)set_owner,
7365 smb_fname_str_dbg(smb_fname)));
7367 if (fsp && fsp->fh->fd != -1) {
7368 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7369 } else {
7371 * UNIX extensions calls must always operate
7372 * on symlinks.
7374 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7375 set_owner, (gid_t)-1);
7378 if (ret != 0) {
7379 status = map_nt_error_from_unix(errno);
7380 if (delete_on_fail) {
7381 SMB_VFS_UNLINK(conn, smb_fname);
7383 return status;
7388 * Deal with the UNIX specific gid set.
7391 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7392 (sbuf.st_ex_gid != set_grp)) {
7393 int ret;
7395 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7396 "changing group %u for file %s\n",
7397 (unsigned int)set_owner,
7398 smb_fname_str_dbg(smb_fname)));
7399 if (fsp && fsp->fh->fd != -1) {
7400 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7401 } else {
7403 * UNIX extensions calls must always operate
7404 * on symlinks.
7406 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7407 set_grp);
7409 if (ret != 0) {
7410 status = map_nt_error_from_unix(errno);
7411 if (delete_on_fail) {
7412 SMB_VFS_UNLINK(conn, smb_fname);
7414 return status;
7418 /* Deal with any size changes. */
7420 status = smb_set_file_size(conn, req,
7421 fsp,
7422 smb_fname,
7423 &sbuf,
7424 size,
7425 false);
7426 if (!NT_STATUS_IS_OK(status)) {
7427 return status;
7430 /* Deal with any time changes. */
7431 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7432 /* No change, don't cancel anything. */
7433 return status;
7436 id = vfs_file_id_from_sbuf(conn, &sbuf);
7437 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7438 all_fsps = file_find_di_next(all_fsps)) {
7440 * We're setting the time explicitly for UNIX.
7441 * Cancel any pending changes over all handles.
7443 all_fsps->update_write_time_on_close = false;
7444 TALLOC_FREE(all_fsps->update_write_time_event);
7448 * Override the "setting_write_time"
7449 * parameter here as it almost does what
7450 * we need. Just remember if we modified
7451 * mtime and send the notify ourselves.
7453 if (null_timespec(ft.mtime)) {
7454 modify_mtime = false;
7457 status = smb_set_file_time(conn,
7458 fsp,
7459 smb_fname,
7460 &ft,
7461 false);
7462 if (modify_mtime) {
7463 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7464 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7466 return status;
7469 /****************************************************************************
7470 Deal with SMB_SET_FILE_UNIX_INFO2.
7471 ****************************************************************************/
7473 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7474 struct smb_request *req,
7475 const char *pdata,
7476 int total_data,
7477 files_struct *fsp,
7478 const struct smb_filename *smb_fname)
7480 NTSTATUS status;
7481 uint32_t smb_fflags;
7482 uint32_t smb_fmask;
7484 if (total_data < 116) {
7485 return NT_STATUS_INVALID_PARAMETER;
7488 /* Start by setting all the fields that are common between UNIX_BASIC
7489 * and UNIX_INFO2.
7491 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7492 fsp, smb_fname);
7493 if (!NT_STATUS_IS_OK(status)) {
7494 return status;
7497 smb_fflags = IVAL(pdata, 108);
7498 smb_fmask = IVAL(pdata, 112);
7500 /* NB: We should only attempt to alter the file flags if the client
7501 * sends a non-zero mask.
7503 if (smb_fmask != 0) {
7504 int stat_fflags = 0;
7506 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7507 smb_fmask, &stat_fflags)) {
7508 /* Client asked to alter a flag we don't understand. */
7509 return NT_STATUS_INVALID_PARAMETER;
7512 if (fsp && fsp->fh->fd != -1) {
7513 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7514 return NT_STATUS_NOT_SUPPORTED;
7515 } else {
7516 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7517 stat_fflags) != 0) {
7518 return map_nt_error_from_unix(errno);
7523 /* XXX: need to add support for changing the create_time here. You
7524 * can do this for paths on Darwin with setattrlist(2). The right way
7525 * to hook this up is probably by extending the VFS utimes interface.
7528 return NT_STATUS_OK;
7531 /****************************************************************************
7532 Create a directory with POSIX semantics.
7533 ****************************************************************************/
7535 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7536 struct smb_request *req,
7537 char **ppdata,
7538 int total_data,
7539 struct smb_filename *smb_fname,
7540 int *pdata_return_size)
7542 NTSTATUS status = NT_STATUS_OK;
7543 uint32_t raw_unixmode = 0;
7544 uint32_t mod_unixmode = 0;
7545 mode_t unixmode = (mode_t)0;
7546 files_struct *fsp = NULL;
7547 uint16_t info_level_return = 0;
7548 int info;
7549 char *pdata = *ppdata;
7551 if (total_data < 18) {
7552 return NT_STATUS_INVALID_PARAMETER;
7555 raw_unixmode = IVAL(pdata,8);
7556 /* Next 4 bytes are not yet defined. */
7558 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7559 PERM_NEW_DIR, &unixmode);
7560 if (!NT_STATUS_IS_OK(status)) {
7561 return status;
7564 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7566 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7567 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7569 status = SMB_VFS_CREATE_FILE(
7570 conn, /* conn */
7571 req, /* req */
7572 0, /* root_dir_fid */
7573 smb_fname, /* fname */
7574 FILE_READ_ATTRIBUTES, /* access_mask */
7575 FILE_SHARE_NONE, /* share_access */
7576 FILE_CREATE, /* create_disposition*/
7577 FILE_DIRECTORY_FILE, /* create_options */
7578 mod_unixmode, /* file_attributes */
7579 0, /* oplock_request */
7580 NULL, /* lease */
7581 0, /* allocation_size */
7582 0, /* private_flags */
7583 NULL, /* sd */
7584 NULL, /* ea_list */
7585 &fsp, /* result */
7586 &info, /* pinfo */
7587 NULL, NULL); /* create context */
7589 if (NT_STATUS_IS_OK(status)) {
7590 close_file(req, fsp, NORMAL_CLOSE);
7593 info_level_return = SVAL(pdata,16);
7595 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7596 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7597 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7598 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7599 } else {
7600 *pdata_return_size = 12;
7603 /* Realloc the data size */
7604 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7605 if (*ppdata == NULL) {
7606 *pdata_return_size = 0;
7607 return NT_STATUS_NO_MEMORY;
7609 pdata = *ppdata;
7611 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7612 SSVAL(pdata,2,0); /* No fnum. */
7613 SIVAL(pdata,4,info); /* Was directory created. */
7615 switch (info_level_return) {
7616 case SMB_QUERY_FILE_UNIX_BASIC:
7617 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7618 SSVAL(pdata,10,0); /* Padding. */
7619 store_file_unix_basic(conn, pdata + 12, fsp,
7620 &smb_fname->st);
7621 break;
7622 case SMB_QUERY_FILE_UNIX_INFO2:
7623 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7624 SSVAL(pdata,10,0); /* Padding. */
7625 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7626 &smb_fname->st);
7627 break;
7628 default:
7629 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7630 SSVAL(pdata,10,0); /* Padding. */
7631 break;
7634 return status;
7637 /****************************************************************************
7638 Open/Create a file with POSIX semantics.
7639 ****************************************************************************/
7641 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7642 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7644 static NTSTATUS smb_posix_open(connection_struct *conn,
7645 struct smb_request *req,
7646 char **ppdata,
7647 int total_data,
7648 struct smb_filename *smb_fname,
7649 int *pdata_return_size)
7651 bool extended_oplock_granted = False;
7652 char *pdata = *ppdata;
7653 uint32_t flags = 0;
7654 uint32_t wire_open_mode = 0;
7655 uint32_t raw_unixmode = 0;
7656 uint32_t mod_unixmode = 0;
7657 uint32_t create_disp = 0;
7658 uint32_t access_mask = 0;
7659 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7660 NTSTATUS status = NT_STATUS_OK;
7661 mode_t unixmode = (mode_t)0;
7662 files_struct *fsp = NULL;
7663 int oplock_request = 0;
7664 int info = 0;
7665 uint16_t info_level_return = 0;
7667 if (total_data < 18) {
7668 return NT_STATUS_INVALID_PARAMETER;
7671 flags = IVAL(pdata,0);
7672 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7673 if (oplock_request) {
7674 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7677 wire_open_mode = IVAL(pdata,4);
7679 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7680 return smb_posix_mkdir(conn, req,
7681 ppdata,
7682 total_data,
7683 smb_fname,
7684 pdata_return_size);
7687 switch (wire_open_mode & SMB_ACCMODE) {
7688 case SMB_O_RDONLY:
7689 access_mask = SMB_O_RDONLY_MAPPING;
7690 break;
7691 case SMB_O_WRONLY:
7692 access_mask = SMB_O_WRONLY_MAPPING;
7693 break;
7694 case SMB_O_RDWR:
7695 access_mask = (SMB_O_RDONLY_MAPPING|
7696 SMB_O_WRONLY_MAPPING);
7697 break;
7698 default:
7699 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7700 (unsigned int)wire_open_mode ));
7701 return NT_STATUS_INVALID_PARAMETER;
7704 wire_open_mode &= ~SMB_ACCMODE;
7706 /* First take care of O_CREAT|O_EXCL interactions. */
7707 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7708 case (SMB_O_CREAT | SMB_O_EXCL):
7709 /* File exists fail. File not exist create. */
7710 create_disp = FILE_CREATE;
7711 break;
7712 case SMB_O_CREAT:
7713 /* File exists open. File not exist create. */
7714 create_disp = FILE_OPEN_IF;
7715 break;
7716 case SMB_O_EXCL:
7717 /* O_EXCL on its own without O_CREAT is undefined.
7718 We deliberately ignore it as some versions of
7719 Linux CIFSFS can send a bare O_EXCL on the
7720 wire which other filesystems in the kernel
7721 ignore. See bug 9519 for details. */
7723 /* Fallthrough. */
7725 case 0:
7726 /* File exists open. File not exist fail. */
7727 create_disp = FILE_OPEN;
7728 break;
7729 default:
7730 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7731 (unsigned int)wire_open_mode ));
7732 return NT_STATUS_INVALID_PARAMETER;
7735 /* Next factor in the effects of O_TRUNC. */
7736 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7738 if (wire_open_mode & SMB_O_TRUNC) {
7739 switch (create_disp) {
7740 case FILE_CREATE:
7741 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7742 /* Leave create_disp alone as
7743 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7745 /* File exists fail. File not exist create. */
7746 break;
7747 case FILE_OPEN_IF:
7748 /* SMB_O_CREAT | SMB_O_TRUNC */
7749 /* File exists overwrite. File not exist create. */
7750 create_disp = FILE_OVERWRITE_IF;
7751 break;
7752 case FILE_OPEN:
7753 /* SMB_O_TRUNC */
7754 /* File exists overwrite. File not exist fail. */
7755 create_disp = FILE_OVERWRITE;
7756 break;
7757 default:
7758 /* Cannot get here. */
7759 smb_panic("smb_posix_open: logic error");
7760 return NT_STATUS_INVALID_PARAMETER;
7764 raw_unixmode = IVAL(pdata,8);
7765 /* Next 4 bytes are not yet defined. */
7767 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7768 (VALID_STAT(smb_fname->st) ?
7769 PERM_EXISTING_FILE : PERM_NEW_FILE),
7770 &unixmode);
7772 if (!NT_STATUS_IS_OK(status)) {
7773 return status;
7776 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7778 if (wire_open_mode & SMB_O_SYNC) {
7779 create_options |= FILE_WRITE_THROUGH;
7781 if (wire_open_mode & SMB_O_APPEND) {
7782 access_mask |= FILE_APPEND_DATA;
7784 if (wire_open_mode & SMB_O_DIRECT) {
7785 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7788 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7789 VALID_STAT_OF_DIR(smb_fname->st)) {
7790 if (access_mask != SMB_O_RDONLY_MAPPING) {
7791 return NT_STATUS_FILE_IS_A_DIRECTORY;
7793 create_options &= ~FILE_NON_DIRECTORY_FILE;
7794 create_options |= FILE_DIRECTORY_FILE;
7797 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7798 smb_fname_str_dbg(smb_fname),
7799 (unsigned int)wire_open_mode,
7800 (unsigned int)unixmode ));
7802 status = SMB_VFS_CREATE_FILE(
7803 conn, /* conn */
7804 req, /* req */
7805 0, /* root_dir_fid */
7806 smb_fname, /* fname */
7807 access_mask, /* access_mask */
7808 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7809 FILE_SHARE_DELETE),
7810 create_disp, /* create_disposition*/
7811 create_options, /* create_options */
7812 mod_unixmode, /* file_attributes */
7813 oplock_request, /* oplock_request */
7814 NULL, /* lease */
7815 0, /* allocation_size */
7816 0, /* private_flags */
7817 NULL, /* sd */
7818 NULL, /* ea_list */
7819 &fsp, /* result */
7820 &info, /* pinfo */
7821 NULL, NULL); /* create context */
7823 if (!NT_STATUS_IS_OK(status)) {
7824 return status;
7827 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7828 extended_oplock_granted = True;
7831 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7832 extended_oplock_granted = True;
7835 info_level_return = SVAL(pdata,16);
7837 /* Allocate the correct return size. */
7839 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7840 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7841 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7842 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7843 } else {
7844 *pdata_return_size = 12;
7847 /* Realloc the data size */
7848 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7849 if (*ppdata == NULL) {
7850 close_file(req, fsp, ERROR_CLOSE);
7851 *pdata_return_size = 0;
7852 return NT_STATUS_NO_MEMORY;
7854 pdata = *ppdata;
7856 if (extended_oplock_granted) {
7857 if (flags & REQUEST_BATCH_OPLOCK) {
7858 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7859 } else {
7860 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7862 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7863 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7864 } else {
7865 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7868 SSVAL(pdata,2,fsp->fnum);
7869 SIVAL(pdata,4,info); /* Was file created etc. */
7871 switch (info_level_return) {
7872 case SMB_QUERY_FILE_UNIX_BASIC:
7873 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7874 SSVAL(pdata,10,0); /* padding. */
7875 store_file_unix_basic(conn, pdata + 12, fsp,
7876 &smb_fname->st);
7877 break;
7878 case SMB_QUERY_FILE_UNIX_INFO2:
7879 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7880 SSVAL(pdata,10,0); /* padding. */
7881 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7882 &smb_fname->st);
7883 break;
7884 default:
7885 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7886 SSVAL(pdata,10,0); /* padding. */
7887 break;
7889 return NT_STATUS_OK;
7892 /****************************************************************************
7893 Delete a file with POSIX semantics.
7894 ****************************************************************************/
7896 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7897 struct smb_request *req,
7898 const char *pdata,
7899 int total_data,
7900 struct smb_filename *smb_fname)
7902 NTSTATUS status = NT_STATUS_OK;
7903 files_struct *fsp = NULL;
7904 uint16_t flags = 0;
7905 char del = 1;
7906 int info = 0;
7907 int create_options = 0;
7908 int i;
7909 struct share_mode_lock *lck = NULL;
7911 if (total_data < 2) {
7912 return NT_STATUS_INVALID_PARAMETER;
7915 flags = SVAL(pdata,0);
7917 if (!VALID_STAT(smb_fname->st)) {
7918 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7921 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7922 !VALID_STAT_OF_DIR(smb_fname->st)) {
7923 return NT_STATUS_NOT_A_DIRECTORY;
7926 DEBUG(10,("smb_posix_unlink: %s %s\n",
7927 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7928 smb_fname_str_dbg(smb_fname)));
7930 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7931 create_options |= FILE_DIRECTORY_FILE;
7934 status = SMB_VFS_CREATE_FILE(
7935 conn, /* conn */
7936 req, /* req */
7937 0, /* root_dir_fid */
7938 smb_fname, /* fname */
7939 DELETE_ACCESS, /* access_mask */
7940 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7941 FILE_SHARE_DELETE),
7942 FILE_OPEN, /* create_disposition*/
7943 create_options, /* create_options */
7944 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7945 0, /* oplock_request */
7946 NULL, /* lease */
7947 0, /* allocation_size */
7948 0, /* private_flags */
7949 NULL, /* sd */
7950 NULL, /* ea_list */
7951 &fsp, /* result */
7952 &info, /* pinfo */
7953 NULL, NULL); /* create context */
7955 if (!NT_STATUS_IS_OK(status)) {
7956 return status;
7960 * Don't lie to client. If we can't really delete due to
7961 * non-POSIX opens return SHARING_VIOLATION.
7964 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7965 if (lck == NULL) {
7966 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7967 "lock for file %s\n", fsp_str_dbg(fsp)));
7968 close_file(req, fsp, NORMAL_CLOSE);
7969 return NT_STATUS_INVALID_PARAMETER;
7973 * See if others still have the file open. If this is the case, then
7974 * don't delete. If all opens are POSIX delete we can set the delete
7975 * on close disposition.
7977 for (i=0; i<lck->data->num_share_modes; i++) {
7978 struct share_mode_entry *e = &lck->data->share_modes[i];
7979 if (is_valid_share_mode_entry(e)) {
7980 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7981 continue;
7983 if (share_mode_stale_pid(lck->data, i)) {
7984 continue;
7986 /* Fail with sharing violation. */
7987 TALLOC_FREE(lck);
7988 close_file(req, fsp, NORMAL_CLOSE);
7989 return NT_STATUS_SHARING_VIOLATION;
7994 * Set the delete on close.
7996 status = smb_set_file_disposition_info(conn,
7997 &del,
7999 fsp,
8000 smb_fname);
8002 TALLOC_FREE(lck);
8004 if (!NT_STATUS_IS_OK(status)) {
8005 close_file(req, fsp, NORMAL_CLOSE);
8006 return status;
8008 return close_file(req, fsp, NORMAL_CLOSE);
8011 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8012 struct smb_request *req,
8013 TALLOC_CTX *mem_ctx,
8014 uint16_t info_level,
8015 files_struct *fsp,
8016 struct smb_filename *smb_fname,
8017 char **ppdata, int total_data,
8018 int *ret_data_size)
8020 char *pdata = *ppdata;
8021 NTSTATUS status = NT_STATUS_OK;
8022 int data_return_size = 0;
8024 *ret_data_size = 0;
8026 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8027 return NT_STATUS_INVALID_LEVEL;
8030 if (!CAN_WRITE(conn)) {
8031 /* Allow POSIX opens. The open path will deny
8032 * any non-readonly opens. */
8033 if (info_level != SMB_POSIX_PATH_OPEN) {
8034 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8038 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8039 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8040 fsp_fnum_dbg(fsp),
8041 info_level, total_data));
8043 switch (info_level) {
8045 case SMB_INFO_STANDARD:
8047 status = smb_set_info_standard(conn,
8048 pdata,
8049 total_data,
8050 fsp,
8051 smb_fname);
8052 break;
8055 case SMB_INFO_SET_EA:
8057 status = smb_info_set_ea(conn,
8058 pdata,
8059 total_data,
8060 fsp,
8061 smb_fname);
8062 break;
8065 case SMB_SET_FILE_BASIC_INFO:
8066 case SMB_FILE_BASIC_INFORMATION:
8068 status = smb_set_file_basic_info(conn,
8069 pdata,
8070 total_data,
8071 fsp,
8072 smb_fname);
8073 break;
8076 case SMB_FILE_ALLOCATION_INFORMATION:
8077 case SMB_SET_FILE_ALLOCATION_INFO:
8079 status = smb_set_file_allocation_info(conn, req,
8080 pdata,
8081 total_data,
8082 fsp,
8083 smb_fname);
8084 break;
8087 case SMB_FILE_END_OF_FILE_INFORMATION:
8088 case SMB_SET_FILE_END_OF_FILE_INFO:
8091 * XP/Win7 both fail after the createfile with
8092 * SMB_SET_FILE_END_OF_FILE_INFO but not
8093 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8094 * The level is known here, so pass it down
8095 * appropriately.
8097 bool should_fail =
8098 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8100 status = smb_set_file_end_of_file_info(conn, req,
8101 pdata,
8102 total_data,
8103 fsp,
8104 smb_fname,
8105 should_fail);
8106 break;
8109 case SMB_FILE_DISPOSITION_INFORMATION:
8110 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8112 #if 0
8113 /* JRA - We used to just ignore this on a path ?
8114 * Shouldn't this be invalid level on a pathname
8115 * based call ?
8117 if (tran_call != TRANSACT2_SETFILEINFO) {
8118 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8120 #endif
8121 status = smb_set_file_disposition_info(conn,
8122 pdata,
8123 total_data,
8124 fsp,
8125 smb_fname);
8126 break;
8129 case SMB_FILE_POSITION_INFORMATION:
8131 status = smb_file_position_information(conn,
8132 pdata,
8133 total_data,
8134 fsp);
8135 break;
8138 case SMB_FILE_FULL_EA_INFORMATION:
8140 status = smb_set_file_full_ea_info(conn,
8141 pdata,
8142 total_data,
8143 fsp);
8144 break;
8147 /* From tridge Samba4 :
8148 * MODE_INFORMATION in setfileinfo (I have no
8149 * idea what "mode information" on a file is - it takes a value of 0,
8150 * 2, 4 or 6. What could it be?).
8153 case SMB_FILE_MODE_INFORMATION:
8155 status = smb_file_mode_information(conn,
8156 pdata,
8157 total_data);
8158 break;
8162 * CIFS UNIX extensions.
8165 case SMB_SET_FILE_UNIX_BASIC:
8167 status = smb_set_file_unix_basic(conn, req,
8168 pdata,
8169 total_data,
8170 fsp,
8171 smb_fname);
8172 break;
8175 case SMB_SET_FILE_UNIX_INFO2:
8177 status = smb_set_file_unix_info2(conn, req,
8178 pdata,
8179 total_data,
8180 fsp,
8181 smb_fname);
8182 break;
8185 case SMB_SET_FILE_UNIX_LINK:
8187 if (fsp) {
8188 /* We must have a pathname for this. */
8189 return NT_STATUS_INVALID_LEVEL;
8191 status = smb_set_file_unix_link(conn, req, pdata,
8192 total_data, smb_fname);
8193 break;
8196 case SMB_SET_FILE_UNIX_HLINK:
8198 if (fsp) {
8199 /* We must have a pathname for this. */
8200 return NT_STATUS_INVALID_LEVEL;
8202 status = smb_set_file_unix_hlink(conn, req,
8203 pdata, total_data,
8204 smb_fname);
8205 break;
8208 case SMB_FILE_RENAME_INFORMATION:
8210 status = smb_file_rename_information(conn, req,
8211 pdata, total_data,
8212 fsp, smb_fname);
8213 break;
8216 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8218 /* SMB2 rename information. */
8219 status = smb2_file_rename_information(conn, req,
8220 pdata, total_data,
8221 fsp, smb_fname);
8222 break;
8225 case SMB_FILE_LINK_INFORMATION:
8227 status = smb_file_link_information(conn, req,
8228 pdata, total_data,
8229 fsp, smb_fname);
8230 break;
8233 #if defined(HAVE_POSIX_ACLS)
8234 case SMB_SET_POSIX_ACL:
8236 status = smb_set_posix_acl(conn,
8237 pdata,
8238 total_data,
8239 fsp,
8240 smb_fname);
8241 break;
8243 #endif
8245 case SMB_SET_POSIX_LOCK:
8247 if (!fsp) {
8248 return NT_STATUS_INVALID_LEVEL;
8250 status = smb_set_posix_lock(conn, req,
8251 pdata, total_data, fsp);
8252 break;
8255 case SMB_POSIX_PATH_OPEN:
8257 if (fsp) {
8258 /* We must have a pathname for this. */
8259 return NT_STATUS_INVALID_LEVEL;
8262 status = smb_posix_open(conn, req,
8263 ppdata,
8264 total_data,
8265 smb_fname,
8266 &data_return_size);
8267 break;
8270 case SMB_POSIX_PATH_UNLINK:
8272 if (fsp) {
8273 /* We must have a pathname for this. */
8274 return NT_STATUS_INVALID_LEVEL;
8277 status = smb_posix_unlink(conn, req,
8278 pdata,
8279 total_data,
8280 smb_fname);
8281 break;
8284 default:
8285 return NT_STATUS_INVALID_LEVEL;
8288 if (!NT_STATUS_IS_OK(status)) {
8289 return status;
8292 *ret_data_size = data_return_size;
8293 return NT_STATUS_OK;
8296 /****************************************************************************
8297 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8298 ****************************************************************************/
8300 static void call_trans2setfilepathinfo(connection_struct *conn,
8301 struct smb_request *req,
8302 unsigned int tran_call,
8303 char **pparams, int total_params,
8304 char **ppdata, int total_data,
8305 unsigned int max_data_bytes)
8307 char *params = *pparams;
8308 char *pdata = *ppdata;
8309 uint16_t info_level;
8310 struct smb_filename *smb_fname = NULL;
8311 files_struct *fsp = NULL;
8312 NTSTATUS status = NT_STATUS_OK;
8313 int data_return_size = 0;
8315 if (!params) {
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 return;
8320 if (tran_call == TRANSACT2_SETFILEINFO) {
8321 if (total_params < 4) {
8322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8323 return;
8326 fsp = file_fsp(req, SVAL(params,0));
8327 /* Basic check for non-null fsp. */
8328 if (!check_fsp_open(conn, req, fsp)) {
8329 return;
8331 info_level = SVAL(params,2);
8333 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8334 if (smb_fname == NULL) {
8335 reply_nterror(req, NT_STATUS_NO_MEMORY);
8336 return;
8339 if(fsp->fh->fd == -1) {
8341 * This is actually a SETFILEINFO on a directory
8342 * handle (returned from an NT SMB). NT5.0 seems
8343 * to do this call. JRA.
8345 if (INFO_LEVEL_IS_UNIX(info_level)) {
8346 /* Always do lstat for UNIX calls. */
8347 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8348 DEBUG(3,("call_trans2setfilepathinfo: "
8349 "SMB_VFS_LSTAT of %s failed "
8350 "(%s)\n",
8351 smb_fname_str_dbg(smb_fname),
8352 strerror(errno)));
8353 reply_nterror(req, map_nt_error_from_unix(errno));
8354 return;
8356 } else {
8357 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8358 DEBUG(3,("call_trans2setfilepathinfo: "
8359 "fileinfo of %s failed (%s)\n",
8360 smb_fname_str_dbg(smb_fname),
8361 strerror(errno)));
8362 reply_nterror(req, map_nt_error_from_unix(errno));
8363 return;
8366 } else if (fsp->print_file) {
8368 * Doing a DELETE_ON_CLOSE should cancel a print job.
8370 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8371 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8373 DEBUG(3,("call_trans2setfilepathinfo: "
8374 "Cancelling print job (%s)\n",
8375 fsp_str_dbg(fsp)));
8377 SSVAL(params,0,0);
8378 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8379 *ppdata, 0,
8380 max_data_bytes);
8381 return;
8382 } else {
8383 reply_nterror(req,
8384 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8385 return;
8387 } else {
8389 * Original code - this is an open file.
8391 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8392 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8393 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8394 strerror(errno)));
8395 reply_nterror(req, map_nt_error_from_unix(errno));
8396 return;
8399 } else {
8400 char *fname = NULL;
8401 uint32_t ucf_flags = 0;
8403 /* set path info */
8404 if (total_params < 7) {
8405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 return;
8409 info_level = SVAL(params,0);
8410 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8411 total_params - 6, STR_TERMINATE,
8412 &status);
8413 if (!NT_STATUS_IS_OK(status)) {
8414 reply_nterror(req, status);
8415 return;
8418 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8419 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8420 info_level == SMB_FILE_RENAME_INFORMATION ||
8421 info_level == SMB_POSIX_PATH_UNLINK) {
8422 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8425 status = filename_convert(req, conn,
8426 req->flags2 & FLAGS2_DFS_PATHNAMES,
8427 fname,
8428 ucf_flags,
8429 NULL,
8430 &smb_fname);
8431 if (!NT_STATUS_IS_OK(status)) {
8432 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8433 reply_botherror(req,
8434 NT_STATUS_PATH_NOT_COVERED,
8435 ERRSRV, ERRbadpath);
8436 return;
8438 reply_nterror(req, status);
8439 return;
8442 if (INFO_LEVEL_IS_UNIX(info_level)) {
8444 * For CIFS UNIX extensions the target name may not exist.
8447 /* Always do lstat for UNIX calls. */
8448 SMB_VFS_LSTAT(conn, smb_fname);
8450 } else if (!VALID_STAT(smb_fname->st) &&
8451 SMB_VFS_STAT(conn, smb_fname)) {
8452 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8453 "%s failed (%s)\n",
8454 smb_fname_str_dbg(smb_fname),
8455 strerror(errno)));
8456 reply_nterror(req, map_nt_error_from_unix(errno));
8457 return;
8461 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8462 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8463 fsp_fnum_dbg(fsp),
8464 info_level,total_data));
8466 /* Realloc the parameter size */
8467 *pparams = (char *)SMB_REALLOC(*pparams,2);
8468 if (*pparams == NULL) {
8469 reply_nterror(req, NT_STATUS_NO_MEMORY);
8470 return;
8472 params = *pparams;
8474 SSVAL(params,0,0);
8476 status = smbd_do_setfilepathinfo(conn, req, req,
8477 info_level,
8478 fsp,
8479 smb_fname,
8480 ppdata, total_data,
8481 &data_return_size);
8482 if (!NT_STATUS_IS_OK(status)) {
8483 if (open_was_deferred(req->xconn, req->mid)) {
8484 /* We have re-scheduled this call. */
8485 return;
8487 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8488 /* We have re-scheduled this call. */
8489 return;
8491 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8492 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8493 ERRSRV, ERRbadpath);
8494 return;
8496 if (info_level == SMB_POSIX_PATH_OPEN) {
8497 reply_openerror(req, status);
8498 return;
8502 * Invalid EA name needs to return 2 param bytes,
8503 * not a zero-length error packet.
8505 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8506 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8507 max_data_bytes);
8508 } else {
8509 reply_nterror(req, status);
8511 return;
8514 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8515 max_data_bytes);
8517 return;
8520 /****************************************************************************
8521 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8522 ****************************************************************************/
8524 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8525 char **pparams, int total_params,
8526 char **ppdata, int total_data,
8527 unsigned int max_data_bytes)
8529 struct smb_filename *smb_dname = NULL;
8530 char *params = *pparams;
8531 char *pdata = *ppdata;
8532 char *directory = NULL;
8533 NTSTATUS status = NT_STATUS_OK;
8534 struct ea_list *ea_list = NULL;
8535 TALLOC_CTX *ctx = talloc_tos();
8537 if (!CAN_WRITE(conn)) {
8538 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8539 return;
8542 if (total_params < 5) {
8543 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8544 return;
8547 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8548 total_params - 4, STR_TERMINATE,
8549 &status);
8550 if (!NT_STATUS_IS_OK(status)) {
8551 reply_nterror(req, status);
8552 return;
8555 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8557 status = filename_convert(ctx,
8558 conn,
8559 req->flags2 & FLAGS2_DFS_PATHNAMES,
8560 directory,
8562 NULL,
8563 &smb_dname);
8565 if (!NT_STATUS_IS_OK(status)) {
8566 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8567 reply_botherror(req,
8568 NT_STATUS_PATH_NOT_COVERED,
8569 ERRSRV, ERRbadpath);
8570 return;
8572 reply_nterror(req, status);
8573 return;
8577 * OS/2 workplace shell seems to send SET_EA requests of "null"
8578 * length (4 bytes containing IVAL 4).
8579 * They seem to have no effect. Bug #3212. JRA.
8582 if (total_data && (total_data != 4)) {
8583 /* Any data in this call is an EA list. */
8584 if (total_data < 10) {
8585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8586 goto out;
8589 if (IVAL(pdata,0) > total_data) {
8590 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8591 IVAL(pdata,0), (unsigned int)total_data));
8592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8593 goto out;
8596 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8597 total_data - 4);
8598 if (!ea_list) {
8599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8600 goto out;
8603 if (!lp_ea_support(SNUM(conn))) {
8604 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8605 goto out;
8608 /* If total_data == 4 Windows doesn't care what values
8609 * are placed in that field, it just ignores them.
8610 * The System i QNTC IBM SMB client puts bad values here,
8611 * so ignore them. */
8613 status = create_directory(conn, req, smb_dname);
8615 if (!NT_STATUS_IS_OK(status)) {
8616 reply_nterror(req, status);
8617 goto out;
8620 /* Try and set any given EA. */
8621 if (ea_list) {
8622 status = set_ea(conn, NULL, smb_dname, ea_list);
8623 if (!NT_STATUS_IS_OK(status)) {
8624 reply_nterror(req, status);
8625 goto out;
8629 /* Realloc the parameter and data sizes */
8630 *pparams = (char *)SMB_REALLOC(*pparams,2);
8631 if(*pparams == NULL) {
8632 reply_nterror(req, NT_STATUS_NO_MEMORY);
8633 goto out;
8635 params = *pparams;
8637 SSVAL(params,0,0);
8639 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8641 out:
8642 TALLOC_FREE(smb_dname);
8643 return;
8646 /****************************************************************************
8647 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8648 We don't actually do this - we just send a null response.
8649 ****************************************************************************/
8651 static void call_trans2findnotifyfirst(connection_struct *conn,
8652 struct smb_request *req,
8653 char **pparams, int total_params,
8654 char **ppdata, int total_data,
8655 unsigned int max_data_bytes)
8657 char *params = *pparams;
8658 uint16_t info_level;
8660 if (total_params < 6) {
8661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8662 return;
8665 info_level = SVAL(params,4);
8666 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8668 switch (info_level) {
8669 case 1:
8670 case 2:
8671 break;
8672 default:
8673 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8674 return;
8677 /* Realloc the parameter and data sizes */
8678 *pparams = (char *)SMB_REALLOC(*pparams,6);
8679 if (*pparams == NULL) {
8680 reply_nterror(req, NT_STATUS_NO_MEMORY);
8681 return;
8683 params = *pparams;
8685 SSVAL(params,0,fnf_handle);
8686 SSVAL(params,2,0); /* No changes */
8687 SSVAL(params,4,0); /* No EA errors */
8689 fnf_handle++;
8691 if(fnf_handle == 0)
8692 fnf_handle = 257;
8694 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8696 return;
8699 /****************************************************************************
8700 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8701 changes). Currently this does nothing.
8702 ****************************************************************************/
8704 static void call_trans2findnotifynext(connection_struct *conn,
8705 struct smb_request *req,
8706 char **pparams, int total_params,
8707 char **ppdata, int total_data,
8708 unsigned int max_data_bytes)
8710 char *params = *pparams;
8712 DEBUG(3,("call_trans2findnotifynext\n"));
8714 /* Realloc the parameter and data sizes */
8715 *pparams = (char *)SMB_REALLOC(*pparams,4);
8716 if (*pparams == NULL) {
8717 reply_nterror(req, NT_STATUS_NO_MEMORY);
8718 return;
8720 params = *pparams;
8722 SSVAL(params,0,0); /* No changes */
8723 SSVAL(params,2,0); /* No EA errors */
8725 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8727 return;
8730 /****************************************************************************
8731 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8732 ****************************************************************************/
8734 static void call_trans2getdfsreferral(connection_struct *conn,
8735 struct smb_request *req,
8736 char **pparams, int total_params,
8737 char **ppdata, int total_data,
8738 unsigned int max_data_bytes)
8740 char *params = *pparams;
8741 char *pathname = NULL;
8742 int reply_size = 0;
8743 int max_referral_level;
8744 NTSTATUS status = NT_STATUS_OK;
8745 TALLOC_CTX *ctx = talloc_tos();
8747 DEBUG(10,("call_trans2getdfsreferral\n"));
8749 if (total_params < 3) {
8750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8751 return;
8754 max_referral_level = SVAL(params,0);
8756 if(!lp_host_msdfs()) {
8757 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8758 return;
8761 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8762 total_params - 2, STR_TERMINATE);
8763 if (!pathname) {
8764 reply_nterror(req, NT_STATUS_NOT_FOUND);
8765 return;
8767 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8768 ppdata,&status)) < 0) {
8769 reply_nterror(req, status);
8770 return;
8773 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8774 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8775 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8777 return;
8780 #define LMCAT_SPL 0x53
8781 #define LMFUNC_GETJOBID 0x60
8783 /****************************************************************************
8784 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8785 ****************************************************************************/
8787 static void call_trans2ioctl(connection_struct *conn,
8788 struct smb_request *req,
8789 char **pparams, int total_params,
8790 char **ppdata, int total_data,
8791 unsigned int max_data_bytes)
8793 char *pdata = *ppdata;
8794 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8795 NTSTATUS status;
8796 size_t len = 0;
8798 /* check for an invalid fid before proceeding */
8800 if (!fsp) {
8801 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8802 return;
8805 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8806 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8807 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8808 if (*ppdata == NULL) {
8809 reply_nterror(req, NT_STATUS_NO_MEMORY);
8810 return;
8812 pdata = *ppdata;
8814 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8815 CAN ACCEPT THIS IN UNICODE. JRA. */
8817 /* Job number */
8818 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8820 status = srvstr_push(pdata, req->flags2, pdata + 2,
8821 lp_netbios_name(), 15,
8822 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8823 if (!NT_STATUS_IS_OK(status)) {
8824 reply_nterror(req, status);
8825 return;
8827 status = srvstr_push(pdata, req->flags2, pdata+18,
8828 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8829 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8830 if (!NT_STATUS_IS_OK(status)) {
8831 reply_nterror(req, status);
8832 return;
8834 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8835 max_data_bytes);
8836 return;
8839 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8840 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8843 /****************************************************************************
8844 Reply to a SMBfindclose (stop trans2 directory search).
8845 ****************************************************************************/
8847 void reply_findclose(struct smb_request *req)
8849 int dptr_num;
8850 struct smbd_server_connection *sconn = req->sconn;
8852 START_PROFILE(SMBfindclose);
8854 if (req->wct < 1) {
8855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8856 END_PROFILE(SMBfindclose);
8857 return;
8860 dptr_num = SVALS(req->vwv+0, 0);
8862 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8864 dptr_close(sconn, &dptr_num);
8866 reply_outbuf(req, 0, 0);
8868 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8870 END_PROFILE(SMBfindclose);
8871 return;
8874 /****************************************************************************
8875 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8876 ****************************************************************************/
8878 void reply_findnclose(struct smb_request *req)
8880 int dptr_num;
8882 START_PROFILE(SMBfindnclose);
8884 if (req->wct < 1) {
8885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8886 END_PROFILE(SMBfindnclose);
8887 return;
8890 dptr_num = SVAL(req->vwv+0, 0);
8892 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8894 /* We never give out valid handles for a
8895 findnotifyfirst - so any dptr_num is ok here.
8896 Just ignore it. */
8898 reply_outbuf(req, 0, 0);
8900 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8902 END_PROFILE(SMBfindnclose);
8903 return;
8906 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8907 struct trans_state *state)
8909 if (get_Protocol() >= PROTOCOL_NT1) {
8910 req->flags2 |= 0x40; /* IS_LONG_NAME */
8911 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8914 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8915 if (state->call != TRANSACT2_QFSINFO &&
8916 state->call != TRANSACT2_SETFSINFO) {
8917 DEBUG(0,("handle_trans2: encryption required "
8918 "with call 0x%x\n",
8919 (unsigned int)state->call));
8920 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8921 return;
8925 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8927 /* Now we must call the relevant TRANS2 function */
8928 switch(state->call) {
8929 case TRANSACT2_OPEN:
8931 START_PROFILE(Trans2_open);
8932 call_trans2open(conn, req,
8933 &state->param, state->total_param,
8934 &state->data, state->total_data,
8935 state->max_data_return);
8936 END_PROFILE(Trans2_open);
8937 break;
8940 case TRANSACT2_FINDFIRST:
8942 START_PROFILE(Trans2_findfirst);
8943 call_trans2findfirst(conn, req,
8944 &state->param, state->total_param,
8945 &state->data, state->total_data,
8946 state->max_data_return);
8947 END_PROFILE(Trans2_findfirst);
8948 break;
8951 case TRANSACT2_FINDNEXT:
8953 START_PROFILE(Trans2_findnext);
8954 call_trans2findnext(conn, req,
8955 &state->param, state->total_param,
8956 &state->data, state->total_data,
8957 state->max_data_return);
8958 END_PROFILE(Trans2_findnext);
8959 break;
8962 case TRANSACT2_QFSINFO:
8964 START_PROFILE(Trans2_qfsinfo);
8965 call_trans2qfsinfo(conn, req,
8966 &state->param, state->total_param,
8967 &state->data, state->total_data,
8968 state->max_data_return);
8969 END_PROFILE(Trans2_qfsinfo);
8970 break;
8973 case TRANSACT2_SETFSINFO:
8975 START_PROFILE(Trans2_setfsinfo);
8976 call_trans2setfsinfo(conn, req,
8977 &state->param, state->total_param,
8978 &state->data, state->total_data,
8979 state->max_data_return);
8980 END_PROFILE(Trans2_setfsinfo);
8981 break;
8984 case TRANSACT2_QPATHINFO:
8985 case TRANSACT2_QFILEINFO:
8987 START_PROFILE(Trans2_qpathinfo);
8988 call_trans2qfilepathinfo(conn, req, state->call,
8989 &state->param, state->total_param,
8990 &state->data, state->total_data,
8991 state->max_data_return);
8992 END_PROFILE(Trans2_qpathinfo);
8993 break;
8996 case TRANSACT2_SETPATHINFO:
8997 case TRANSACT2_SETFILEINFO:
8999 START_PROFILE(Trans2_setpathinfo);
9000 call_trans2setfilepathinfo(conn, req, state->call,
9001 &state->param, state->total_param,
9002 &state->data, state->total_data,
9003 state->max_data_return);
9004 END_PROFILE(Trans2_setpathinfo);
9005 break;
9008 case TRANSACT2_FINDNOTIFYFIRST:
9010 START_PROFILE(Trans2_findnotifyfirst);
9011 call_trans2findnotifyfirst(conn, req,
9012 &state->param, state->total_param,
9013 &state->data, state->total_data,
9014 state->max_data_return);
9015 END_PROFILE(Trans2_findnotifyfirst);
9016 break;
9019 case TRANSACT2_FINDNOTIFYNEXT:
9021 START_PROFILE(Trans2_findnotifynext);
9022 call_trans2findnotifynext(conn, req,
9023 &state->param, state->total_param,
9024 &state->data, state->total_data,
9025 state->max_data_return);
9026 END_PROFILE(Trans2_findnotifynext);
9027 break;
9030 case TRANSACT2_MKDIR:
9032 START_PROFILE(Trans2_mkdir);
9033 call_trans2mkdir(conn, req,
9034 &state->param, state->total_param,
9035 &state->data, state->total_data,
9036 state->max_data_return);
9037 END_PROFILE(Trans2_mkdir);
9038 break;
9041 case TRANSACT2_GET_DFS_REFERRAL:
9043 START_PROFILE(Trans2_get_dfs_referral);
9044 call_trans2getdfsreferral(conn, req,
9045 &state->param, state->total_param,
9046 &state->data, state->total_data,
9047 state->max_data_return);
9048 END_PROFILE(Trans2_get_dfs_referral);
9049 break;
9052 case TRANSACT2_IOCTL:
9054 START_PROFILE(Trans2_ioctl);
9055 call_trans2ioctl(conn, req,
9056 &state->param, state->total_param,
9057 &state->data, state->total_data,
9058 state->max_data_return);
9059 END_PROFILE(Trans2_ioctl);
9060 break;
9063 default:
9064 /* Error in request */
9065 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9066 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9070 /****************************************************************************
9071 Reply to a SMBtrans2.
9072 ****************************************************************************/
9074 void reply_trans2(struct smb_request *req)
9076 connection_struct *conn = req->conn;
9077 unsigned int dsoff;
9078 unsigned int dscnt;
9079 unsigned int psoff;
9080 unsigned int pscnt;
9081 unsigned int tran_call;
9082 struct trans_state *state;
9083 NTSTATUS result;
9085 START_PROFILE(SMBtrans2);
9087 if (req->wct < 14) {
9088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9089 END_PROFILE(SMBtrans2);
9090 return;
9093 dsoff = SVAL(req->vwv+12, 0);
9094 dscnt = SVAL(req->vwv+11, 0);
9095 psoff = SVAL(req->vwv+10, 0);
9096 pscnt = SVAL(req->vwv+9, 0);
9097 tran_call = SVAL(req->vwv+14, 0);
9099 result = allow_new_trans(conn->pending_trans, req->mid);
9100 if (!NT_STATUS_IS_OK(result)) {
9101 DEBUG(2, ("Got invalid trans2 request: %s\n",
9102 nt_errstr(result)));
9103 reply_nterror(req, result);
9104 END_PROFILE(SMBtrans2);
9105 return;
9108 if (IS_IPC(conn)) {
9109 switch (tran_call) {
9110 /* List the allowed trans2 calls on IPC$ */
9111 case TRANSACT2_OPEN:
9112 case TRANSACT2_GET_DFS_REFERRAL:
9113 case TRANSACT2_QFILEINFO:
9114 case TRANSACT2_QFSINFO:
9115 case TRANSACT2_SETFSINFO:
9116 break;
9117 default:
9118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9119 END_PROFILE(SMBtrans2);
9120 return;
9124 if ((state = talloc(conn, struct trans_state)) == NULL) {
9125 DEBUG(0, ("talloc failed\n"));
9126 reply_nterror(req, NT_STATUS_NO_MEMORY);
9127 END_PROFILE(SMBtrans2);
9128 return;
9131 state->cmd = SMBtrans2;
9133 state->mid = req->mid;
9134 state->vuid = req->vuid;
9135 state->setup_count = SVAL(req->vwv+13, 0);
9136 state->setup = NULL;
9137 state->total_param = SVAL(req->vwv+0, 0);
9138 state->param = NULL;
9139 state->total_data = SVAL(req->vwv+1, 0);
9140 state->data = NULL;
9141 state->max_param_return = SVAL(req->vwv+2, 0);
9142 state->max_data_return = SVAL(req->vwv+3, 0);
9143 state->max_setup_return = SVAL(req->vwv+4, 0);
9144 state->close_on_completion = BITSETW(req->vwv+5, 0);
9145 state->one_way = BITSETW(req->vwv+5, 1);
9147 state->call = tran_call;
9149 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9150 is so as a sanity check */
9151 if (state->setup_count != 1) {
9153 * Need to have rc=0 for ioctl to get job id for OS/2.
9154 * Network printing will fail if function is not successful.
9155 * Similar function in reply.c will be used if protocol
9156 * is LANMAN1.0 instead of LM1.2X002.
9157 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9158 * outbuf doesn't have to be set(only job id is used).
9160 if ( (state->setup_count == 4)
9161 && (tran_call == TRANSACT2_IOCTL)
9162 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9163 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9164 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9165 } else {
9166 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9167 DEBUG(2,("Transaction is %d\n",tran_call));
9168 TALLOC_FREE(state);
9169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9170 END_PROFILE(SMBtrans2);
9171 return;
9175 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9176 goto bad_param;
9178 if (state->total_data) {
9180 if (trans_oob(state->total_data, 0, dscnt)
9181 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9182 goto bad_param;
9185 /* Can't use talloc here, the core routines do realloc on the
9186 * params and data. */
9187 state->data = (char *)SMB_MALLOC(state->total_data);
9188 if (state->data == NULL) {
9189 DEBUG(0,("reply_trans2: data malloc fail for %u "
9190 "bytes !\n", (unsigned int)state->total_data));
9191 TALLOC_FREE(state);
9192 reply_nterror(req, NT_STATUS_NO_MEMORY);
9193 END_PROFILE(SMBtrans2);
9194 return;
9197 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9200 if (state->total_param) {
9202 if (trans_oob(state->total_param, 0, pscnt)
9203 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9204 goto bad_param;
9207 /* Can't use talloc here, the core routines do realloc on the
9208 * params and data. */
9209 state->param = (char *)SMB_MALLOC(state->total_param);
9210 if (state->param == NULL) {
9211 DEBUG(0,("reply_trans: param malloc fail for %u "
9212 "bytes !\n", (unsigned int)state->total_param));
9213 SAFE_FREE(state->data);
9214 TALLOC_FREE(state);
9215 reply_nterror(req, NT_STATUS_NO_MEMORY);
9216 END_PROFILE(SMBtrans2);
9217 return;
9220 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9223 state->received_data = dscnt;
9224 state->received_param = pscnt;
9226 if ((state->received_param == state->total_param) &&
9227 (state->received_data == state->total_data)) {
9229 handle_trans2(conn, req, state);
9231 SAFE_FREE(state->data);
9232 SAFE_FREE(state->param);
9233 TALLOC_FREE(state);
9234 END_PROFILE(SMBtrans2);
9235 return;
9238 DLIST_ADD(conn->pending_trans, state);
9240 /* We need to send an interim response then receive the rest
9241 of the parameter/data bytes */
9242 reply_outbuf(req, 0, 0);
9243 show_msg((char *)req->outbuf);
9244 END_PROFILE(SMBtrans2);
9245 return;
9247 bad_param:
9249 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9250 SAFE_FREE(state->data);
9251 SAFE_FREE(state->param);
9252 TALLOC_FREE(state);
9253 END_PROFILE(SMBtrans2);
9254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9258 /****************************************************************************
9259 Reply to a SMBtranss2
9260 ****************************************************************************/
9262 void reply_transs2(struct smb_request *req)
9264 connection_struct *conn = req->conn;
9265 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9266 struct trans_state *state;
9268 START_PROFILE(SMBtranss2);
9270 show_msg((const char *)req->inbuf);
9272 /* Windows clients expect all replies to
9273 a transact secondary (SMBtranss2 0x33)
9274 to have a command code of transact
9275 (SMBtrans2 0x32). See bug #8989
9276 and also [MS-CIFS] section 2.2.4.47.2
9277 for details.
9279 req->cmd = SMBtrans2;
9281 if (req->wct < 8) {
9282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9283 END_PROFILE(SMBtranss2);
9284 return;
9287 for (state = conn->pending_trans; state != NULL;
9288 state = state->next) {
9289 if (state->mid == req->mid) {
9290 break;
9294 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9296 END_PROFILE(SMBtranss2);
9297 return;
9300 /* Revise state->total_param and state->total_data in case they have
9301 changed downwards */
9303 if (SVAL(req->vwv+0, 0) < state->total_param)
9304 state->total_param = SVAL(req->vwv+0, 0);
9305 if (SVAL(req->vwv+1, 0) < state->total_data)
9306 state->total_data = SVAL(req->vwv+1, 0);
9308 pcnt = SVAL(req->vwv+2, 0);
9309 poff = SVAL(req->vwv+3, 0);
9310 pdisp = SVAL(req->vwv+4, 0);
9312 dcnt = SVAL(req->vwv+5, 0);
9313 doff = SVAL(req->vwv+6, 0);
9314 ddisp = SVAL(req->vwv+7, 0);
9316 state->received_param += pcnt;
9317 state->received_data += dcnt;
9319 if ((state->received_data > state->total_data) ||
9320 (state->received_param > state->total_param))
9321 goto bad_param;
9323 if (pcnt) {
9324 if (trans_oob(state->total_param, pdisp, pcnt)
9325 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9326 goto bad_param;
9328 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9331 if (dcnt) {
9332 if (trans_oob(state->total_data, ddisp, dcnt)
9333 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9334 goto bad_param;
9336 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9339 if ((state->received_param < state->total_param) ||
9340 (state->received_data < state->total_data)) {
9341 END_PROFILE(SMBtranss2);
9342 return;
9345 handle_trans2(conn, req, state);
9347 DLIST_REMOVE(conn->pending_trans, state);
9348 SAFE_FREE(state->data);
9349 SAFE_FREE(state->param);
9350 TALLOC_FREE(state);
9352 END_PROFILE(SMBtranss2);
9353 return;
9355 bad_param:
9357 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9358 DLIST_REMOVE(conn->pending_trans, state);
9359 SAFE_FREE(state->data);
9360 SAFE_FREE(state->param);
9361 TALLOC_FREE(state);
9362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9363 END_PROFILE(SMBtranss2);
9364 return;