s4:kdc/db-glue: allow principals in form of computer@EXAMPLE.COM
[Samba.git] / source3 / smbd / trans2.c
blobe518c7b48efb465b102f8d334874b2512bc3910d
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_t 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 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2378 DEBUG(1,("Conversion error: illegal character: %s\n",
2379 smb_fname_str_dbg(smb_fname)));
2381 TALLOC_FREE(fname);
2382 TALLOC_FREE(smb_fname);
2383 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2384 dptr_SeekDir(dirptr, prev_dirpos);
2385 return status;
2387 if (!NT_STATUS_IS_OK(status)) {
2388 return status;
2391 *_last_entry_off = last_entry_off;
2392 return NT_STATUS_OK;
2395 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2396 connection_struct *conn,
2397 struct dptr_struct *dirptr,
2398 uint16_t flags2,
2399 const char *path_mask,
2400 uint32_t dirtype,
2401 int info_level,
2402 bool requires_resume_key,
2403 bool dont_descend,
2404 bool ask_sharemode,
2405 char **ppdata,
2406 char *base_data,
2407 char *end_data,
2408 int space_remaining,
2409 bool *got_exact_match,
2410 int *last_entry_off,
2411 struct ea_list *name_list)
2413 uint8_t align = 4;
2414 const bool do_pad = true;
2416 if (info_level >= 1 && info_level <= 3) {
2417 /* No alignment on earlier info levels. */
2418 align = 1;
2421 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2422 path_mask, dirtype, info_level,
2423 requires_resume_key, dont_descend, ask_sharemode,
2424 align, do_pad,
2425 ppdata, base_data, end_data,
2426 space_remaining,
2427 got_exact_match,
2428 last_entry_off, name_list);
2431 /****************************************************************************
2432 Reply to a TRANS2_FINDFIRST.
2433 ****************************************************************************/
2435 static void call_trans2findfirst(connection_struct *conn,
2436 struct smb_request *req,
2437 char **pparams, int total_params,
2438 char **ppdata, int total_data,
2439 unsigned int max_data_bytes)
2441 /* We must be careful here that we don't return more than the
2442 allowed number of data bytes. If this means returning fewer than
2443 maxentries then so be it. We assume that the redirector has
2444 enough room for the fixed number of parameter bytes it has
2445 requested. */
2446 struct smb_filename *smb_dname = NULL;
2447 char *params = *pparams;
2448 char *pdata = *ppdata;
2449 char *data_end;
2450 uint32_t dirtype;
2451 int maxentries;
2452 uint16_t findfirst_flags;
2453 bool close_after_first;
2454 bool close_if_end;
2455 bool requires_resume_key;
2456 int info_level;
2457 char *directory = NULL;
2458 char *mask = NULL;
2459 char *p;
2460 int last_entry_off=0;
2461 int dptr_num = -1;
2462 int numentries = 0;
2463 int i;
2464 bool finished = False;
2465 bool dont_descend = False;
2466 bool out_of_space = False;
2467 int space_remaining;
2468 bool mask_contains_wcard = False;
2469 struct ea_list *ea_list = NULL;
2470 NTSTATUS ntstatus = NT_STATUS_OK;
2471 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2472 TALLOC_CTX *ctx = talloc_tos();
2473 struct dptr_struct *dirptr = NULL;
2474 struct smbd_server_connection *sconn = req->sconn;
2475 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2476 bool backup_priv = false;
2478 if (total_params < 13) {
2479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2480 goto out;
2483 dirtype = SVAL(params,0);
2484 maxentries = SVAL(params,2);
2485 findfirst_flags = SVAL(params,4);
2486 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2487 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2488 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2489 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2490 security_token_has_privilege(get_current_nttok(conn),
2491 SEC_PRIV_BACKUP));
2493 info_level = SVAL(params,6);
2495 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2496 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2497 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2498 (int)backup_priv,
2499 info_level, max_data_bytes));
2501 if (!maxentries) {
2502 /* W2K3 seems to treat zero as 1. */
2503 maxentries = 1;
2506 switch (info_level) {
2507 case SMB_FIND_INFO_STANDARD:
2508 case SMB_FIND_EA_SIZE:
2509 case SMB_FIND_EA_LIST:
2510 case SMB_FIND_FILE_DIRECTORY_INFO:
2511 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2512 case SMB_FIND_FILE_NAMES_INFO:
2513 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2514 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2515 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2516 break;
2517 case SMB_FIND_FILE_UNIX:
2518 case SMB_FIND_FILE_UNIX_INFO2:
2519 /* Always use filesystem for UNIX mtime query. */
2520 ask_sharemode = false;
2521 if (!lp_unix_extensions()) {
2522 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2523 goto out;
2525 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2526 break;
2527 default:
2528 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2529 goto out;
2532 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2533 params+12, total_params - 12,
2534 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2535 if (!NT_STATUS_IS_OK(ntstatus)) {
2536 reply_nterror(req, ntstatus);
2537 goto out;
2540 if (backup_priv) {
2541 become_root();
2542 ntstatus = filename_convert_with_privilege(ctx,
2543 conn,
2544 req,
2545 directory,
2546 ucf_flags,
2547 &mask_contains_wcard,
2548 &smb_dname);
2549 } else {
2550 ntstatus = filename_convert(ctx, conn,
2551 req->flags2 & FLAGS2_DFS_PATHNAMES,
2552 directory,
2553 ucf_flags,
2554 &mask_contains_wcard,
2555 &smb_dname);
2558 if (!NT_STATUS_IS_OK(ntstatus)) {
2559 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2560 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2561 ERRSRV, ERRbadpath);
2562 goto out;
2564 reply_nterror(req, ntstatus);
2565 goto out;
2568 mask = smb_dname->original_lcomp;
2570 directory = smb_dname->base_name;
2572 p = strrchr_m(directory,'/');
2573 if(p == NULL) {
2574 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2575 if((directory[0] == '.') && (directory[1] == '\0')) {
2576 mask = talloc_strdup(ctx,"*");
2577 if (!mask) {
2578 reply_nterror(req, NT_STATUS_NO_MEMORY);
2579 goto out;
2581 mask_contains_wcard = True;
2583 } else {
2584 *p = 0;
2587 if (p == NULL || p == directory) {
2588 /* Ensure we don't have a directory name of "". */
2589 directory = talloc_strdup(talloc_tos(), ".");
2590 if (!directory) {
2591 reply_nterror(req, NT_STATUS_NO_MEMORY);
2592 goto out;
2596 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2598 if (info_level == SMB_FIND_EA_LIST) {
2599 uint32_t ea_size;
2601 if (total_data < 4) {
2602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2603 goto out;
2606 ea_size = IVAL(pdata,0);
2607 if (ea_size != total_data) {
2608 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2609 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2611 goto out;
2614 if (!lp_ea_support(SNUM(conn))) {
2615 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2616 goto out;
2619 /* Pull out the list of names. */
2620 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2621 if (!ea_list) {
2622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2623 goto out;
2627 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2629 goto out;
2632 *ppdata = (char *)SMB_REALLOC(
2633 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2634 if(*ppdata == NULL ) {
2635 reply_nterror(req, NT_STATUS_NO_MEMORY);
2636 goto out;
2638 pdata = *ppdata;
2639 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2641 /* Realloc the params space */
2642 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2643 if (*pparams == NULL) {
2644 reply_nterror(req, NT_STATUS_NO_MEMORY);
2645 goto out;
2647 params = *pparams;
2649 /* Save the wildcard match and attribs we are using on this directory -
2650 needed as lanman2 assumes these are being saved between calls */
2652 ntstatus = dptr_create(conn,
2653 req,
2654 NULL, /* fsp */
2655 directory,
2656 False,
2657 True,
2658 req->smbpid,
2659 mask,
2660 mask_contains_wcard,
2661 dirtype,
2662 &dirptr);
2664 if (!NT_STATUS_IS_OK(ntstatus)) {
2665 reply_nterror(req, ntstatus);
2666 goto out;
2669 if (backup_priv) {
2670 /* Remember this in case we have
2671 to do a findnext. */
2672 dptr_set_priv(dirptr);
2675 dptr_num = dptr_dnum(dirptr);
2676 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2678 /* Initialize per TRANS2_FIND_FIRST operation data */
2679 dptr_init_search_op(dirptr);
2681 /* We don't need to check for VOL here as this is returned by
2682 a different TRANS2 call. */
2684 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2685 directory,lp_dont_descend(ctx, SNUM(conn))));
2686 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2687 dont_descend = True;
2689 p = pdata;
2690 space_remaining = max_data_bytes;
2691 out_of_space = False;
2693 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2694 bool got_exact_match = False;
2696 /* this is a heuristic to avoid seeking the dirptr except when
2697 absolutely necessary. It allows for a filename of about 40 chars */
2698 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2699 out_of_space = True;
2700 finished = False;
2701 } else {
2702 ntstatus = get_lanman2_dir_entry(ctx,
2703 conn,
2704 dirptr,
2705 req->flags2,
2706 mask,dirtype,info_level,
2707 requires_resume_key,dont_descend,
2708 ask_sharemode,
2709 &p,pdata,data_end,
2710 space_remaining,
2711 &got_exact_match,
2712 &last_entry_off, ea_list);
2713 if (NT_STATUS_EQUAL(ntstatus,
2714 NT_STATUS_ILLEGAL_CHARACTER)) {
2716 * Bad character conversion on name. Ignore this
2717 * entry.
2719 continue;
2721 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2722 out_of_space = true;
2723 } else {
2724 finished = !NT_STATUS_IS_OK(ntstatus);
2728 if (!finished && !out_of_space)
2729 numentries++;
2732 * As an optimisation if we know we aren't looking
2733 * for a wildcard name (ie. the name matches the wildcard exactly)
2734 * then we can finish on any (first) match.
2735 * This speeds up large directory searches. JRA.
2738 if(got_exact_match)
2739 finished = True;
2741 /* Ensure space_remaining never goes -ve. */
2742 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2743 space_remaining = 0;
2744 out_of_space = true;
2745 } else {
2746 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2750 /* Check if we can close the dirptr */
2751 if(close_after_first || (finished && close_if_end)) {
2752 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2753 dptr_close(sconn, &dptr_num);
2757 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2758 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2759 * the protocol level is less than NT1. Tested with smbclient. JRA.
2760 * This should fix the OS/2 client bug #2335.
2763 if(numentries == 0) {
2764 dptr_close(sconn, &dptr_num);
2765 if (get_Protocol() < PROTOCOL_NT1) {
2766 reply_force_doserror(req, ERRDOS, ERRnofiles);
2767 goto out;
2768 } else {
2769 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2770 ERRDOS, ERRbadfile);
2771 goto out;
2775 /* At this point pdata points to numentries directory entries. */
2777 /* Set up the return parameter block */
2778 SSVAL(params,0,dptr_num);
2779 SSVAL(params,2,numentries);
2780 SSVAL(params,4,finished);
2781 SSVAL(params,6,0); /* Never an EA error */
2782 SSVAL(params,8,last_entry_off);
2784 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2785 max_data_bytes);
2787 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2788 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2789 if (!directory) {
2790 reply_nterror(req, NT_STATUS_NO_MEMORY);
2794 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2795 smb_fn_name(req->cmd),
2796 mask, directory, dirtype, numentries ) );
2799 * Force a name mangle here to ensure that the
2800 * mask as an 8.3 name is top of the mangled cache.
2801 * The reasons for this are subtle. Don't remove
2802 * this code unless you know what you are doing
2803 * (see PR#13758). JRA.
2806 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2807 char mangled_name[13];
2808 name_to_8_3(mask, mangled_name, True, conn->params);
2810 out:
2812 if (backup_priv) {
2813 unbecome_root();
2816 TALLOC_FREE(smb_dname);
2817 return;
2820 /****************************************************************************
2821 Reply to a TRANS2_FINDNEXT.
2822 ****************************************************************************/
2824 static void call_trans2findnext(connection_struct *conn,
2825 struct smb_request *req,
2826 char **pparams, int total_params,
2827 char **ppdata, int total_data,
2828 unsigned int max_data_bytes)
2830 /* We must be careful here that we don't return more than the
2831 allowed number of data bytes. If this means returning fewer than
2832 maxentries then so be it. We assume that the redirector has
2833 enough room for the fixed number of parameter bytes it has
2834 requested. */
2835 char *params = *pparams;
2836 char *pdata = *ppdata;
2837 char *data_end;
2838 int dptr_num;
2839 int maxentries;
2840 uint16_t info_level;
2841 uint32_t resume_key;
2842 uint16_t findnext_flags;
2843 bool close_after_request;
2844 bool close_if_end;
2845 bool requires_resume_key;
2846 bool continue_bit;
2847 bool mask_contains_wcard = False;
2848 char *resume_name = NULL;
2849 const char *mask = NULL;
2850 const char *directory = NULL;
2851 char *p = NULL;
2852 uint16_t dirtype;
2853 int numentries = 0;
2854 int i, last_entry_off=0;
2855 bool finished = False;
2856 bool dont_descend = False;
2857 bool out_of_space = False;
2858 int space_remaining;
2859 struct ea_list *ea_list = NULL;
2860 NTSTATUS ntstatus = NT_STATUS_OK;
2861 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2862 TALLOC_CTX *ctx = talloc_tos();
2863 struct dptr_struct *dirptr;
2864 struct smbd_server_connection *sconn = req->sconn;
2865 bool backup_priv = false;
2867 if (total_params < 13) {
2868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2869 return;
2872 dptr_num = SVAL(params,0);
2873 maxentries = SVAL(params,2);
2874 info_level = SVAL(params,4);
2875 resume_key = IVAL(params,6);
2876 findnext_flags = SVAL(params,10);
2877 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2878 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2879 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2880 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2882 if (!continue_bit) {
2883 /* We only need resume_name if continue_bit is zero. */
2884 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2885 params+12,
2886 total_params - 12, STR_TERMINATE, &ntstatus,
2887 &mask_contains_wcard);
2888 if (!NT_STATUS_IS_OK(ntstatus)) {
2889 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2890 complain (it thinks we're asking for the directory above the shared
2891 path or an invalid name). Catch this as the resume name is only compared, never used in
2892 a file access. JRA. */
2893 srvstr_pull_talloc(ctx, params, req->flags2,
2894 &resume_name, params+12,
2895 total_params - 12,
2896 STR_TERMINATE);
2898 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2899 reply_nterror(req, ntstatus);
2900 return;
2905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2907 resume_key = %d resume name = %s continue=%d level = %d\n",
2908 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2909 requires_resume_key, resume_key,
2910 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2912 if (!maxentries) {
2913 /* W2K3 seems to treat zero as 1. */
2914 maxentries = 1;
2917 switch (info_level) {
2918 case SMB_FIND_INFO_STANDARD:
2919 case SMB_FIND_EA_SIZE:
2920 case SMB_FIND_EA_LIST:
2921 case SMB_FIND_FILE_DIRECTORY_INFO:
2922 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2923 case SMB_FIND_FILE_NAMES_INFO:
2924 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2925 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2926 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2927 break;
2928 case SMB_FIND_FILE_UNIX:
2929 case SMB_FIND_FILE_UNIX_INFO2:
2930 /* Always use filesystem for UNIX mtime query. */
2931 ask_sharemode = false;
2932 if (!lp_unix_extensions()) {
2933 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2934 return;
2936 break;
2937 default:
2938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2939 return;
2942 if (info_level == SMB_FIND_EA_LIST) {
2943 uint32_t ea_size;
2945 if (total_data < 4) {
2946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2947 return;
2950 ea_size = IVAL(pdata,0);
2951 if (ea_size != total_data) {
2952 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2953 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2955 return;
2958 if (!lp_ea_support(SNUM(conn))) {
2959 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2960 return;
2963 /* Pull out the list of names. */
2964 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2965 if (!ea_list) {
2966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2967 return;
2971 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2973 return;
2976 *ppdata = (char *)SMB_REALLOC(
2977 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2978 if(*ppdata == NULL) {
2979 reply_nterror(req, NT_STATUS_NO_MEMORY);
2980 return;
2983 pdata = *ppdata;
2984 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2986 /* Realloc the params space */
2987 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2988 if(*pparams == NULL ) {
2989 reply_nterror(req, NT_STATUS_NO_MEMORY);
2990 return;
2993 params = *pparams;
2995 /* Check that the dptr is valid */
2996 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2997 reply_nterror(req, STATUS_NO_MORE_FILES);
2998 return;
3001 directory = dptr_path(sconn, dptr_num);
3003 /* Get the wildcard mask from the dptr */
3004 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3005 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3006 reply_nterror(req, STATUS_NO_MORE_FILES);
3007 return;
3010 /* Get the attr mask from the dptr */
3011 dirtype = dptr_attr(sconn, dptr_num);
3013 backup_priv = dptr_get_priv(dirptr);
3015 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3016 "backup_priv = %d\n",
3017 dptr_num, mask, dirtype,
3018 (long)dirptr,
3019 dptr_TellDir(dirptr),
3020 (int)backup_priv));
3022 /* Initialize per TRANS2_FIND_NEXT operation data */
3023 dptr_init_search_op(dirptr);
3025 /* We don't need to check for VOL here as this is returned by
3026 a different TRANS2 call. */
3028 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3029 directory,lp_dont_descend(ctx, SNUM(conn))));
3030 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3031 dont_descend = True;
3033 p = pdata;
3034 space_remaining = max_data_bytes;
3035 out_of_space = False;
3037 if (backup_priv) {
3038 become_root();
3042 * Seek to the correct position. We no longer use the resume key but
3043 * depend on the last file name instead.
3046 if(!continue_bit && resume_name && *resume_name) {
3047 SMB_STRUCT_STAT st;
3049 long current_pos = 0;
3051 * Remember, name_to_8_3 is called by
3052 * get_lanman2_dir_entry(), so the resume name
3053 * could be mangled. Ensure we check the unmangled name.
3056 if (mangle_is_mangled(resume_name, conn->params)) {
3057 char *new_resume_name = NULL;
3058 mangle_lookup_name_from_8_3(ctx,
3059 resume_name,
3060 &new_resume_name,
3061 conn->params);
3062 if (new_resume_name) {
3063 resume_name = new_resume_name;
3068 * Fix for NT redirector problem triggered by resume key indexes
3069 * changing between directory scans. We now return a resume key of 0
3070 * and instead look for the filename to continue from (also given
3071 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3072 * findfirst/findnext (as is usual) then the directory pointer
3073 * should already be at the correct place.
3076 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3077 } /* end if resume_name && !continue_bit */
3079 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3080 bool got_exact_match = False;
3082 /* this is a heuristic to avoid seeking the dirptr except when
3083 absolutely necessary. It allows for a filename of about 40 chars */
3084 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3085 out_of_space = True;
3086 finished = False;
3087 } else {
3088 ntstatus = get_lanman2_dir_entry(ctx,
3089 conn,
3090 dirptr,
3091 req->flags2,
3092 mask,dirtype,info_level,
3093 requires_resume_key,dont_descend,
3094 ask_sharemode,
3095 &p,pdata,data_end,
3096 space_remaining,
3097 &got_exact_match,
3098 &last_entry_off, ea_list);
3099 if (NT_STATUS_EQUAL(ntstatus,
3100 NT_STATUS_ILLEGAL_CHARACTER)) {
3102 * Bad character conversion on name. Ignore this
3103 * entry.
3105 continue;
3107 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3108 out_of_space = true;
3109 } else {
3110 finished = !NT_STATUS_IS_OK(ntstatus);
3114 if (!finished && !out_of_space)
3115 numentries++;
3118 * As an optimisation if we know we aren't looking
3119 * for a wildcard name (ie. the name matches the wildcard exactly)
3120 * then we can finish on any (first) match.
3121 * This speeds up large directory searches. JRA.
3124 if(got_exact_match)
3125 finished = True;
3127 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3130 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3131 smb_fn_name(req->cmd),
3132 mask, directory, dirtype, numentries ) );
3134 /* Check if we can close the dirptr */
3135 if(close_after_request || (finished && close_if_end)) {
3136 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3137 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3140 if (backup_priv) {
3141 unbecome_root();
3144 /* Set up the return parameter block */
3145 SSVAL(params,0,numentries);
3146 SSVAL(params,2,finished);
3147 SSVAL(params,4,0); /* Never an EA error */
3148 SSVAL(params,6,last_entry_off);
3150 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3151 max_data_bytes);
3153 return;
3156 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3158 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3159 return objid;
3162 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3164 SMB_ASSERT(extended_info != NULL);
3166 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3167 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3168 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3169 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3170 #ifdef SAMBA_VERSION_REVISION
3171 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3172 #endif
3173 extended_info->samba_subversion = 0;
3174 #ifdef SAMBA_VERSION_RC_RELEASE
3175 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3176 #else
3177 #ifdef SAMBA_VERSION_PRE_RELEASE
3178 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3179 #endif
3180 #endif
3181 #ifdef SAMBA_VERSION_VENDOR_PATCH
3182 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3183 #endif
3184 extended_info->samba_gitcommitdate = 0;
3185 #ifdef SAMBA_VERSION_COMMIT_TIME
3186 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3187 #endif
3189 memset(extended_info->samba_version_string, 0,
3190 sizeof(extended_info->samba_version_string));
3192 snprintf (extended_info->samba_version_string,
3193 sizeof(extended_info->samba_version_string),
3194 "%s", samba_version_string());
3197 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3198 connection_struct *conn,
3199 TALLOC_CTX *mem_ctx,
3200 uint16_t info_level,
3201 uint16_t flags2,
3202 unsigned int max_data_bytes,
3203 size_t *fixed_portion,
3204 struct smb_filename *fname,
3205 char **ppdata,
3206 int *ret_data_len)
3208 char *pdata, *end_data;
3209 int data_len = 0;
3210 size_t len = 0;
3211 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3212 int snum = SNUM(conn);
3213 const char *fstype = lp_fstype(SNUM(conn));
3214 const char *filename = NULL;
3215 const uint64_t bytes_per_sector = 512;
3216 uint32_t additional_flags = 0;
3217 struct smb_filename smb_fname;
3218 SMB_STRUCT_STAT st;
3219 NTSTATUS status = NT_STATUS_OK;
3220 uint64_t df_ret;
3222 if (fname == NULL || fname->base_name == NULL) {
3223 filename = ".";
3224 } else {
3225 filename = fname->base_name;
3228 if (IS_IPC(conn)) {
3229 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3230 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3231 "info level (0x%x) on IPC$.\n",
3232 (unsigned int)info_level));
3233 return NT_STATUS_ACCESS_DENIED;
3237 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3239 ZERO_STRUCT(smb_fname);
3240 smb_fname.base_name = discard_const_p(char, filename);
3242 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3243 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3244 return map_nt_error_from_unix(errno);
3247 st = smb_fname.st;
3249 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3250 return NT_STATUS_INVALID_PARAMETER;
3253 *ppdata = (char *)SMB_REALLOC(
3254 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3255 if (*ppdata == NULL) {
3256 return NT_STATUS_NO_MEMORY;
3259 pdata = *ppdata;
3260 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3261 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3263 *fixed_portion = 0;
3265 switch (info_level) {
3266 case SMB_INFO_ALLOCATION:
3268 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3269 data_len = 18;
3270 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3271 &dsize);
3272 if (df_ret == (uint64_t)-1) {
3273 return map_nt_error_from_unix(errno);
3276 block_size = lp_block_size(snum);
3277 if (bsize < block_size) {
3278 uint64_t factor = block_size/bsize;
3279 bsize = block_size;
3280 dsize /= factor;
3281 dfree /= factor;
3283 if (bsize > block_size) {
3284 uint64_t factor = bsize/block_size;
3285 bsize = block_size;
3286 dsize *= factor;
3287 dfree *= factor;
3289 sectors_per_unit = bsize/bytes_per_sector;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3292 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3293 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3295 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3296 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3297 SIVAL(pdata,l1_cUnit,dsize);
3298 SIVAL(pdata,l1_cUnitAvail,dfree);
3299 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3300 break;
3303 case SMB_INFO_VOLUME:
3304 /* Return volume name */
3306 * Add volume serial number - hash of a combination of
3307 * the called hostname and the service name.
3309 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3311 * Win2k3 and previous mess this up by sending a name length
3312 * one byte short. I believe only older clients (OS/2 Win9x) use
3313 * this call so try fixing this by adding a terminating null to
3314 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3316 status = srvstr_push(
3317 pdata, flags2,
3318 pdata+l2_vol_szVolLabel, vname,
3319 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3320 STR_NOALIGN|STR_TERMINATE, &len);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 return status;
3324 SCVAL(pdata,l2_vol_cch,len);
3325 data_len = l2_vol_szVolLabel + len;
3326 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3327 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3328 (unsigned)len, vname));
3329 break;
3331 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3332 case SMB_FS_ATTRIBUTE_INFORMATION:
3334 additional_flags = 0;
3335 #if defined(HAVE_SYS_QUOTAS)
3336 additional_flags |= FILE_VOLUME_QUOTAS;
3337 #endif
3339 if(lp_nt_acl_support(SNUM(conn))) {
3340 additional_flags |= FILE_PERSISTENT_ACLS;
3343 /* Capabilities are filled in at connection time through STATVFS call */
3344 additional_flags |= conn->fs_capabilities;
3345 additional_flags |= lp_parm_int(conn->params->service,
3346 "share", "fake_fscaps",
3349 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3350 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3351 additional_flags); /* FS ATTRIBUTES */
3353 SIVAL(pdata,4,255); /* Max filename component length */
3354 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3355 and will think we can't do long filenames */
3356 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3357 PTR_DIFF(end_data, pdata+12),
3358 STR_UNICODE, &len);
3359 if (!NT_STATUS_IS_OK(status)) {
3360 return status;
3362 SIVAL(pdata,8,len);
3363 data_len = 12 + len;
3364 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3365 /* the client only requested a portion of the
3366 file system name */
3367 data_len = max_data_bytes;
3368 status = STATUS_BUFFER_OVERFLOW;
3370 *fixed_portion = 16;
3371 break;
3373 case SMB_QUERY_FS_LABEL_INFO:
3374 case SMB_FS_LABEL_INFORMATION:
3375 status = srvstr_push(pdata, flags2, pdata+4, vname,
3376 PTR_DIFF(end_data, pdata+4), 0, &len);
3377 if (!NT_STATUS_IS_OK(status)) {
3378 return status;
3380 data_len = 4 + len;
3381 SIVAL(pdata,0,len);
3382 break;
3384 case SMB_QUERY_FS_VOLUME_INFO:
3385 case SMB_FS_VOLUME_INFORMATION:
3388 * Add volume serial number - hash of a combination of
3389 * the called hostname and the service name.
3391 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3392 (str_checksum(get_local_machine_name())<<16));
3394 /* Max label len is 32 characters. */
3395 status = srvstr_push(pdata, flags2, pdata+18, vname,
3396 PTR_DIFF(end_data, pdata+18),
3397 STR_UNICODE, &len);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 return status;
3401 SIVAL(pdata,12,len);
3402 data_len = 18+len;
3404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3405 (int)strlen(vname),vname,
3406 lp_servicename(talloc_tos(), snum)));
3407 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3408 /* the client only requested a portion of the
3409 volume label */
3410 data_len = max_data_bytes;
3411 status = STATUS_BUFFER_OVERFLOW;
3413 *fixed_portion = 24;
3414 break;
3416 case SMB_QUERY_FS_SIZE_INFO:
3417 case SMB_FS_SIZE_INFORMATION:
3419 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3420 data_len = 24;
3421 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3422 &dsize);
3423 if (df_ret == (uint64_t)-1) {
3424 return map_nt_error_from_unix(errno);
3426 block_size = lp_block_size(snum);
3427 if (bsize < block_size) {
3428 uint64_t factor = block_size/bsize;
3429 bsize = block_size;
3430 dsize /= factor;
3431 dfree /= factor;
3433 if (bsize > block_size) {
3434 uint64_t factor = bsize/block_size;
3435 bsize = block_size;
3436 dsize *= factor;
3437 dfree *= factor;
3439 sectors_per_unit = bsize/bytes_per_sector;
3440 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3441 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3442 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3443 SBIG_UINT(pdata,0,dsize);
3444 SBIG_UINT(pdata,8,dfree);
3445 SIVAL(pdata,16,sectors_per_unit);
3446 SIVAL(pdata,20,bytes_per_sector);
3447 *fixed_portion = 24;
3448 break;
3451 case SMB_FS_FULL_SIZE_INFORMATION:
3453 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3454 data_len = 32;
3455 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3456 &dsize);
3457 if (df_ret == (uint64_t)-1) {
3458 return map_nt_error_from_unix(errno);
3460 block_size = lp_block_size(snum);
3461 if (bsize < block_size) {
3462 uint64_t factor = block_size/bsize;
3463 bsize = block_size;
3464 dsize /= factor;
3465 dfree /= factor;
3467 if (bsize > block_size) {
3468 uint64_t factor = bsize/block_size;
3469 bsize = block_size;
3470 dsize *= factor;
3471 dfree *= factor;
3473 sectors_per_unit = bsize/bytes_per_sector;
3474 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3475 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3476 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3477 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3478 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3479 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3480 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3481 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3482 *fixed_portion = 32;
3483 break;
3486 case SMB_QUERY_FS_DEVICE_INFO:
3487 case SMB_FS_DEVICE_INFORMATION:
3489 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3491 if (!CAN_WRITE(conn)) {
3492 characteristics |= FILE_READ_ONLY_DEVICE;
3494 data_len = 8;
3495 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3496 SIVAL(pdata,4,characteristics);
3497 *fixed_portion = 8;
3498 break;
3501 #ifdef HAVE_SYS_QUOTAS
3502 case SMB_FS_QUOTA_INFORMATION:
3504 * what we have to send --metze:
3506 * Unknown1: 24 NULL bytes
3507 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3508 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3509 * Quota Flags: 2 byte :
3510 * Unknown3: 6 NULL bytes
3512 * 48 bytes total
3514 * details for Quota Flags:
3516 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3517 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3518 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3519 * 0x0001 Enable Quotas: enable quota for this fs
3523 /* we need to fake up a fsp here,
3524 * because its not send in this call
3526 files_struct fsp;
3527 SMB_NTQUOTA_STRUCT quotas;
3529 ZERO_STRUCT(fsp);
3530 ZERO_STRUCT(quotas);
3532 fsp.conn = conn;
3533 fsp.fnum = FNUM_FIELD_INVALID;
3535 /* access check */
3536 if (get_current_uid(conn) != 0) {
3537 DEBUG(0,("get_user_quota: access_denied "
3538 "service [%s] user [%s]\n",
3539 lp_servicename(talloc_tos(), SNUM(conn)),
3540 conn->session_info->unix_info->unix_name));
3541 return NT_STATUS_ACCESS_DENIED;
3544 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3545 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3546 return map_nt_error_from_unix(errno);
3549 data_len = 48;
3551 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3552 lp_servicename(talloc_tos(), SNUM(conn))));
3554 /* Unknown1 24 NULL bytes*/
3555 SBIG_UINT(pdata,0,(uint64_t)0);
3556 SBIG_UINT(pdata,8,(uint64_t)0);
3557 SBIG_UINT(pdata,16,(uint64_t)0);
3559 /* Default Soft Quota 8 bytes */
3560 SBIG_UINT(pdata,24,quotas.softlim);
3562 /* Default Hard Quota 8 bytes */
3563 SBIG_UINT(pdata,32,quotas.hardlim);
3565 /* Quota flag 2 bytes */
3566 SSVAL(pdata,40,quotas.qflags);
3568 /* Unknown3 6 NULL bytes */
3569 SSVAL(pdata,42,0);
3570 SIVAL(pdata,44,0);
3572 break;
3574 #endif /* HAVE_SYS_QUOTAS */
3575 case SMB_FS_OBJECTID_INFORMATION:
3577 unsigned char objid[16];
3578 struct smb_extended_info extended_info;
3579 memcpy(pdata,create_volume_objectid(conn, objid),16);
3580 samba_extended_info_version (&extended_info);
3581 SIVAL(pdata,16,extended_info.samba_magic);
3582 SIVAL(pdata,20,extended_info.samba_version);
3583 SIVAL(pdata,24,extended_info.samba_subversion);
3584 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3585 memcpy(pdata+36,extended_info.samba_version_string,28);
3586 data_len = 64;
3587 break;
3590 case SMB_FS_SECTOR_SIZE_INFORMATION:
3592 data_len = 28;
3594 * These values match a physical Windows Server 2012
3595 * share backed by NTFS atop spinning rust.
3597 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3598 /* logical_bytes_per_sector */
3599 SIVAL(pdata, 0, bytes_per_sector);
3600 /* phys_bytes_per_sector_atomic */
3601 SIVAL(pdata, 4, bytes_per_sector);
3602 /* phys_bytes_per_sector_perf */
3603 SIVAL(pdata, 8, bytes_per_sector);
3604 /* fs_effective_phys_bytes_per_sector_atomic */
3605 SIVAL(pdata, 12, bytes_per_sector);
3606 /* flags */
3607 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3608 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3609 /* byte_off_sector_align */
3610 SIVAL(pdata, 20, 0);
3611 /* byte_off_partition_align */
3612 SIVAL(pdata, 24, 0);
3613 *fixed_portion = 28;
3614 break;
3619 * Query the version and capabilities of the CIFS UNIX extensions
3620 * in use.
3623 case SMB_QUERY_CIFS_UNIX_INFO:
3625 bool large_write = lp_min_receive_file_size() &&
3626 !srv_is_signing_active(xconn);
3627 bool large_read = !srv_is_signing_active(xconn);
3628 int encrypt_caps = 0;
3630 if (!lp_unix_extensions()) {
3631 return NT_STATUS_INVALID_LEVEL;
3634 switch (conn->encrypt_level) {
3635 case SMB_SIGNING_OFF:
3636 encrypt_caps = 0;
3637 break;
3638 case SMB_SIGNING_IF_REQUIRED:
3639 case SMB_SIGNING_DEFAULT:
3640 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3641 break;
3642 case SMB_SIGNING_REQUIRED:
3643 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3644 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3645 large_write = false;
3646 large_read = false;
3647 break;
3650 data_len = 12;
3651 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3652 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3654 /* We have POSIX ACLs, pathname, encryption,
3655 * large read/write, and locking capability. */
3657 SBIG_UINT(pdata,4,((uint64_t)(
3658 CIFS_UNIX_POSIX_ACLS_CAP|
3659 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3660 CIFS_UNIX_FCNTL_LOCKS_CAP|
3661 CIFS_UNIX_EXTATTR_CAP|
3662 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3663 encrypt_caps|
3664 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3665 (large_write ?
3666 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3667 break;
3670 case SMB_QUERY_POSIX_FS_INFO:
3672 int rc;
3673 vfs_statvfs_struct svfs;
3675 if (!lp_unix_extensions()) {
3676 return NT_STATUS_INVALID_LEVEL;
3679 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3681 if (!rc) {
3682 data_len = 56;
3683 SIVAL(pdata,0,svfs.OptimalTransferSize);
3684 SIVAL(pdata,4,svfs.BlockSize);
3685 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3686 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3687 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3688 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3689 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3690 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3691 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3692 #ifdef EOPNOTSUPP
3693 } else if (rc == EOPNOTSUPP) {
3694 return NT_STATUS_INVALID_LEVEL;
3695 #endif /* EOPNOTSUPP */
3696 } else {
3697 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3698 return NT_STATUS_DOS(ERRSRV, ERRerror);
3700 break;
3703 case SMB_QUERY_POSIX_WHOAMI:
3705 uint32_t flags = 0;
3706 uint32_t sid_bytes;
3707 int i;
3709 if (!lp_unix_extensions()) {
3710 return NT_STATUS_INVALID_LEVEL;
3713 if (max_data_bytes < 40) {
3714 return NT_STATUS_BUFFER_TOO_SMALL;
3717 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3718 flags |= SMB_WHOAMI_GUEST;
3721 /* NOTE: 8 bytes for UID/GID, irrespective of native
3722 * platform size. This matches
3723 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3725 data_len = 4 /* flags */
3726 + 4 /* flag mask */
3727 + 8 /* uid */
3728 + 8 /* gid */
3729 + 4 /* ngroups */
3730 + 4 /* num_sids */
3731 + 4 /* SID bytes */
3732 + 4 /* pad/reserved */
3733 + (conn->session_info->unix_token->ngroups * 8)
3734 /* groups list */
3735 + (conn->session_info->security_token->num_sids *
3736 SID_MAX_SIZE)
3737 /* SID list */;
3739 SIVAL(pdata, 0, flags);
3740 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3741 SBIG_UINT(pdata, 8,
3742 (uint64_t)conn->session_info->unix_token->uid);
3743 SBIG_UINT(pdata, 16,
3744 (uint64_t)conn->session_info->unix_token->gid);
3747 if (data_len >= max_data_bytes) {
3748 /* Potential overflow, skip the GIDs and SIDs. */
3750 SIVAL(pdata, 24, 0); /* num_groups */
3751 SIVAL(pdata, 28, 0); /* num_sids */
3752 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3753 SIVAL(pdata, 36, 0); /* reserved */
3755 data_len = 40;
3756 break;
3759 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3760 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3762 /* We walk the SID list twice, but this call is fairly
3763 * infrequent, and I don't expect that it's performance
3764 * sensitive -- jpeach
3766 for (i = 0, sid_bytes = 0;
3767 i < conn->session_info->security_token->num_sids; ++i) {
3768 sid_bytes += ndr_size_dom_sid(
3769 &conn->session_info->security_token->sids[i],
3773 /* SID list byte count */
3774 SIVAL(pdata, 32, sid_bytes);
3776 /* 4 bytes pad/reserved - must be zero */
3777 SIVAL(pdata, 36, 0);
3778 data_len = 40;
3780 /* GID list */
3781 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3782 SBIG_UINT(pdata, data_len,
3783 (uint64_t)conn->session_info->unix_token->groups[i]);
3784 data_len += 8;
3787 /* SID list */
3788 for (i = 0;
3789 i < conn->session_info->security_token->num_sids; ++i) {
3790 int sid_len = ndr_size_dom_sid(
3791 &conn->session_info->security_token->sids[i],
3794 sid_linearize(pdata + data_len, sid_len,
3795 &conn->session_info->security_token->sids[i]);
3796 data_len += sid_len;
3799 break;
3802 case SMB_MAC_QUERY_FS_INFO:
3804 * Thursby MAC extension... ONLY on NTFS filesystems
3805 * once we do streams then we don't need this
3807 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3808 data_len = 88;
3809 SIVAL(pdata,84,0x100); /* Don't support mac... */
3810 break;
3812 /* drop through */
3813 default:
3814 return NT_STATUS_INVALID_LEVEL;
3817 *ret_data_len = data_len;
3818 return status;
3821 /****************************************************************************
3822 Reply to a TRANS2_QFSINFO (query filesystem info).
3823 ****************************************************************************/
3825 static void call_trans2qfsinfo(connection_struct *conn,
3826 struct smb_request *req,
3827 char **pparams, int total_params,
3828 char **ppdata, int total_data,
3829 unsigned int max_data_bytes)
3831 char *params = *pparams;
3832 uint16_t info_level;
3833 int data_len = 0;
3834 size_t fixed_portion;
3835 NTSTATUS status;
3837 if (total_params < 2) {
3838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3839 return;
3842 info_level = SVAL(params,0);
3844 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3845 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3846 DEBUG(0,("call_trans2qfsinfo: encryption required "
3847 "and info level 0x%x sent.\n",
3848 (unsigned int)info_level));
3849 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3850 return;
3854 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3856 status = smbd_do_qfsinfo(req->xconn, conn, req,
3857 info_level,
3858 req->flags2,
3859 max_data_bytes,
3860 &fixed_portion,
3861 NULL,
3862 ppdata, &data_len);
3863 if (!NT_STATUS_IS_OK(status)) {
3864 reply_nterror(req, status);
3865 return;
3868 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3869 max_data_bytes);
3871 DEBUG( 4, ( "%s info_level = %d\n",
3872 smb_fn_name(req->cmd), info_level) );
3874 return;
3877 /****************************************************************************
3878 Reply to a TRANS2_SETFSINFO (set filesystem info).
3879 ****************************************************************************/
3881 static void call_trans2setfsinfo(connection_struct *conn,
3882 struct smb_request *req,
3883 char **pparams, int total_params,
3884 char **ppdata, int total_data,
3885 unsigned int max_data_bytes)
3887 struct smbXsrv_connection *xconn = req->xconn;
3888 char *pdata = *ppdata;
3889 char *params = *pparams;
3890 uint16_t info_level;
3892 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3893 lp_servicename(talloc_tos(), SNUM(conn))));
3895 /* */
3896 if (total_params < 4) {
3897 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3898 total_params));
3899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3900 return;
3903 info_level = SVAL(params,2);
3905 if (IS_IPC(conn)) {
3906 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3907 info_level != SMB_SET_CIFS_UNIX_INFO) {
3908 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3909 "info level (0x%x) on IPC$.\n",
3910 (unsigned int)info_level));
3911 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3912 return;
3916 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3917 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3918 DEBUG(0,("call_trans2setfsinfo: encryption required "
3919 "and info level 0x%x sent.\n",
3920 (unsigned int)info_level));
3921 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3922 return;
3926 switch(info_level) {
3927 case SMB_SET_CIFS_UNIX_INFO:
3928 if (!lp_unix_extensions()) {
3929 DEBUG(2,("call_trans2setfsinfo: "
3930 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3931 "unix extensions off\n"));
3932 reply_nterror(req,
3933 NT_STATUS_INVALID_LEVEL);
3934 return;
3937 /* There should be 12 bytes of capabilities set. */
3938 if (total_data < 12) {
3939 reply_nterror(
3940 req,
3941 NT_STATUS_INVALID_PARAMETER);
3942 return;
3944 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3945 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3946 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3947 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3948 /* Just print these values for now. */
3949 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3950 "major = %u, minor = %u cap_low = 0x%x, "
3951 "cap_high = 0x%xn",
3952 (unsigned int)xconn->
3953 smb1.unix_info.client_major,
3954 (unsigned int)xconn->
3955 smb1.unix_info.client_minor,
3956 (unsigned int)xconn->
3957 smb1.unix_info.client_cap_low,
3958 (unsigned int)xconn->
3959 smb1.unix_info.client_cap_high));
3961 /* Here is where we must switch to posix pathname processing... */
3962 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3963 lp_set_posix_pathnames();
3964 mangle_change_to_posix();
3967 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3968 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3969 /* Client that knows how to do posix locks,
3970 * but not posix open/mkdir operations. Set a
3971 * default type for read/write checks. */
3973 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3976 break;
3978 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3980 NTSTATUS status;
3981 size_t param_len = 0;
3982 size_t data_len = total_data;
3984 if (!lp_unix_extensions()) {
3985 reply_nterror(
3986 req,
3987 NT_STATUS_INVALID_LEVEL);
3988 return;
3991 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3992 reply_nterror(
3993 req,
3994 NT_STATUS_NOT_SUPPORTED);
3995 return;
3998 if (xconn->smb1.echo_handler.trusted_fde) {
3999 DEBUG( 2,("call_trans2setfsinfo: "
4000 "request transport encryption disabled"
4001 "with 'fork echo handler = yes'\n"));
4002 reply_nterror(
4003 req,
4004 NT_STATUS_NOT_SUPPORTED);
4005 return;
4008 DEBUG( 4,("call_trans2setfsinfo: "
4009 "request transport encryption.\n"));
4011 status = srv_request_encryption_setup(conn,
4012 (unsigned char **)ppdata,
4013 &data_len,
4014 (unsigned char **)pparams,
4015 &param_len);
4017 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4018 !NT_STATUS_IS_OK(status)) {
4019 reply_nterror(req, status);
4020 return;
4023 send_trans2_replies(conn, req,
4024 NT_STATUS_OK,
4025 *pparams,
4026 param_len,
4027 *ppdata,
4028 data_len,
4029 max_data_bytes);
4031 if (NT_STATUS_IS_OK(status)) {
4032 /* Server-side transport
4033 * encryption is now *on*. */
4034 status = srv_encryption_start(conn);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 char *reason = talloc_asprintf(talloc_tos(),
4037 "Failure in setting "
4038 "up encrypted transport: %s",
4039 nt_errstr(status));
4040 exit_server_cleanly(reason);
4043 return;
4046 case SMB_FS_QUOTA_INFORMATION:
4048 files_struct *fsp = NULL;
4049 SMB_NTQUOTA_STRUCT quotas;
4051 ZERO_STRUCT(quotas);
4053 /* access check */
4054 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4055 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4056 lp_servicename(talloc_tos(), SNUM(conn)),
4057 conn->session_info->unix_info->unix_name));
4058 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4059 return;
4062 /* note: normally there're 48 bytes,
4063 * but we didn't use the last 6 bytes for now
4064 * --metze
4066 fsp = file_fsp(req, SVAL(params,0));
4068 if (!check_fsp_ntquota_handle(conn, req,
4069 fsp)) {
4070 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4071 reply_nterror(
4072 req, NT_STATUS_INVALID_HANDLE);
4073 return;
4076 if (total_data < 42) {
4077 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4078 total_data));
4079 reply_nterror(
4080 req,
4081 NT_STATUS_INVALID_PARAMETER);
4082 return;
4085 /* unknown_1 24 NULL bytes in pdata*/
4087 /* the soft quotas 8 bytes (uint64_t)*/
4088 quotas.softlim = BVAL(pdata,24);
4090 /* the hard quotas 8 bytes (uint64_t)*/
4091 quotas.hardlim = BVAL(pdata,32);
4093 /* quota_flags 2 bytes **/
4094 quotas.qflags = SVAL(pdata,40);
4096 /* unknown_2 6 NULL bytes follow*/
4098 /* now set the quotas */
4099 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4100 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4101 reply_nterror(req, map_nt_error_from_unix(errno));
4102 return;
4105 break;
4107 default:
4108 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4109 info_level));
4110 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4111 return;
4112 break;
4116 * sending this reply works fine,
4117 * but I'm not sure it's the same
4118 * like windows do...
4119 * --metze
4121 reply_outbuf(req, 10, 0);
4124 #if defined(HAVE_POSIX_ACLS)
4125 /****************************************************************************
4126 Utility function to count the number of entries in a POSIX acl.
4127 ****************************************************************************/
4129 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4131 unsigned int ace_count = 0;
4132 int entry_id = SMB_ACL_FIRST_ENTRY;
4133 SMB_ACL_ENTRY_T entry;
4135 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4136 /* get_next... */
4137 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4138 entry_id = SMB_ACL_NEXT_ENTRY;
4140 ace_count++;
4142 return ace_count;
4145 /****************************************************************************
4146 Utility function to marshall a POSIX acl into wire format.
4147 ****************************************************************************/
4149 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4151 int entry_id = SMB_ACL_FIRST_ENTRY;
4152 SMB_ACL_ENTRY_T entry;
4154 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4155 SMB_ACL_TAG_T tagtype;
4156 SMB_ACL_PERMSET_T permset;
4157 unsigned char perms = 0;
4158 unsigned int own_grp;
4160 /* get_next... */
4161 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4162 entry_id = SMB_ACL_NEXT_ENTRY;
4165 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4166 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4167 return False;
4170 if (sys_acl_get_permset(entry, &permset) == -1) {
4171 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4172 return False;
4175 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4176 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4177 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4179 SCVAL(pdata,1,perms);
4181 switch (tagtype) {
4182 case SMB_ACL_USER_OBJ:
4183 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4184 own_grp = (unsigned int)pst->st_ex_uid;
4185 SIVAL(pdata,2,own_grp);
4186 SIVAL(pdata,6,0);
4187 break;
4188 case SMB_ACL_USER:
4190 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4191 if (!puid) {
4192 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4193 return False;
4195 own_grp = (unsigned int)*puid;
4196 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4197 SIVAL(pdata,2,own_grp);
4198 SIVAL(pdata,6,0);
4199 break;
4201 case SMB_ACL_GROUP_OBJ:
4202 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4203 own_grp = (unsigned int)pst->st_ex_gid;
4204 SIVAL(pdata,2,own_grp);
4205 SIVAL(pdata,6,0);
4206 break;
4207 case SMB_ACL_GROUP:
4209 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4210 if (!pgid) {
4211 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4212 return False;
4214 own_grp = (unsigned int)*pgid;
4215 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4216 SIVAL(pdata,2,own_grp);
4217 SIVAL(pdata,6,0);
4218 break;
4220 case SMB_ACL_MASK:
4221 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4222 SIVAL(pdata,2,0xFFFFFFFF);
4223 SIVAL(pdata,6,0xFFFFFFFF);
4224 break;
4225 case SMB_ACL_OTHER:
4226 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4227 SIVAL(pdata,2,0xFFFFFFFF);
4228 SIVAL(pdata,6,0xFFFFFFFF);
4229 break;
4230 default:
4231 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4232 return False;
4234 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4237 return True;
4239 #endif
4241 /****************************************************************************
4242 Store the FILE_UNIX_BASIC info.
4243 ****************************************************************************/
4245 static char *store_file_unix_basic(connection_struct *conn,
4246 char *pdata,
4247 files_struct *fsp,
4248 const SMB_STRUCT_STAT *psbuf)
4250 uint64_t file_index = get_FileIndex(conn, psbuf);
4251 dev_t devno;
4253 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4254 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4256 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4257 pdata += 8;
4259 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4260 pdata += 8;
4262 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4263 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4264 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4265 pdata += 24;
4267 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4268 SIVAL(pdata,4,0);
4269 pdata += 8;
4271 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4272 SIVAL(pdata,4,0);
4273 pdata += 8;
4275 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4276 pdata += 4;
4278 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4279 devno = psbuf->st_ex_rdev;
4280 } else {
4281 devno = psbuf->st_ex_dev;
4284 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4285 SIVAL(pdata,4,0);
4286 pdata += 8;
4288 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4289 SIVAL(pdata,4,0);
4290 pdata += 8;
4292 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4293 pdata += 8;
4295 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4296 SIVAL(pdata,4,0);
4297 pdata += 8;
4299 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4300 SIVAL(pdata,4,0);
4301 pdata += 8;
4303 return pdata;
4306 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4307 * the chflags(2) (or equivalent) flags.
4309 * XXX: this really should be behind the VFS interface. To do this, we would
4310 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4311 * Each VFS module could then implement its own mapping as appropriate for the
4312 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4314 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4315 info2_flags_map[] =
4317 #ifdef UF_NODUMP
4318 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4319 #endif
4321 #ifdef UF_IMMUTABLE
4322 { UF_IMMUTABLE, EXT_IMMUTABLE },
4323 #endif
4325 #ifdef UF_APPEND
4326 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4327 #endif
4329 #ifdef UF_HIDDEN
4330 { UF_HIDDEN, EXT_HIDDEN },
4331 #endif
4333 /* Do not remove. We need to guarantee that this array has at least one
4334 * entry to build on HP-UX.
4336 { 0, 0 }
4340 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4341 uint32_t *smb_fflags, uint32_t *smb_fmask)
4343 int i;
4345 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4346 *smb_fmask |= info2_flags_map[i].smb_fflag;
4347 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4348 *smb_fflags |= info2_flags_map[i].smb_fflag;
4353 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4354 const uint32_t smb_fflags,
4355 const uint32_t smb_fmask,
4356 int *stat_fflags)
4358 uint32_t max_fmask = 0;
4359 int i;
4361 *stat_fflags = psbuf->st_ex_flags;
4363 /* For each flags requested in smb_fmask, check the state of the
4364 * corresponding flag in smb_fflags and set or clear the matching
4365 * stat flag.
4368 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4369 max_fmask |= info2_flags_map[i].smb_fflag;
4370 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4371 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4372 *stat_fflags |= info2_flags_map[i].stat_fflag;
4373 } else {
4374 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4379 /* If smb_fmask is asking to set any bits that are not supported by
4380 * our flag mappings, we should fail.
4382 if ((smb_fmask & max_fmask) != smb_fmask) {
4383 return False;
4386 return True;
4390 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4391 * of file flags and birth (create) time.
4393 static char *store_file_unix_basic_info2(connection_struct *conn,
4394 char *pdata,
4395 files_struct *fsp,
4396 const SMB_STRUCT_STAT *psbuf)
4398 uint32_t file_flags = 0;
4399 uint32_t flags_mask = 0;
4401 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4403 /* Create (birth) time 64 bit */
4404 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4405 pdata += 8;
4407 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4408 SIVAL(pdata, 0, file_flags); /* flags */
4409 SIVAL(pdata, 4, flags_mask); /* mask */
4410 pdata += 8;
4412 return pdata;
4415 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4416 const struct stream_struct *streams,
4417 char *data,
4418 unsigned int max_data_bytes,
4419 unsigned int *data_size)
4421 unsigned int i;
4422 unsigned int ofs = 0;
4424 if (max_data_bytes < 32) {
4425 return NT_STATUS_INFO_LENGTH_MISMATCH;
4428 for (i = 0; i < num_streams; i++) {
4429 unsigned int next_offset;
4430 size_t namelen;
4431 smb_ucs2_t *namebuf;
4433 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4434 streams[i].name, &namelen) ||
4435 namelen <= 2)
4437 return NT_STATUS_INVALID_PARAMETER;
4441 * name_buf is now null-terminated, we need to marshall as not
4442 * terminated
4445 namelen -= 2;
4448 * We cannot overflow ...
4450 if ((ofs + 24 + namelen) > max_data_bytes) {
4451 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4452 i));
4453 TALLOC_FREE(namebuf);
4454 return STATUS_BUFFER_OVERFLOW;
4457 SIVAL(data, ofs+4, namelen);
4458 SOFF_T(data, ofs+8, streams[i].size);
4459 SOFF_T(data, ofs+16, streams[i].alloc_size);
4460 memcpy(data+ofs+24, namebuf, namelen);
4461 TALLOC_FREE(namebuf);
4463 next_offset = ofs + 24 + namelen;
4465 if (i == num_streams-1) {
4466 SIVAL(data, ofs, 0);
4468 else {
4469 unsigned int align = ndr_align_size(next_offset, 8);
4471 if ((next_offset + align) > max_data_bytes) {
4472 DEBUG(10, ("refusing to overflow align "
4473 "reply at stream %u\n",
4474 i));
4475 TALLOC_FREE(namebuf);
4476 return STATUS_BUFFER_OVERFLOW;
4479 memset(data+next_offset, 0, align);
4480 next_offset += align;
4482 SIVAL(data, ofs, next_offset - ofs);
4483 ofs = next_offset;
4486 ofs = next_offset;
4489 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4491 *data_size = ofs;
4493 return NT_STATUS_OK;
4496 /****************************************************************************
4497 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4498 ****************************************************************************/
4500 static void call_trans2qpipeinfo(connection_struct *conn,
4501 struct smb_request *req,
4502 unsigned int tran_call,
4503 char **pparams, int total_params,
4504 char **ppdata, int total_data,
4505 unsigned int max_data_bytes)
4507 char *params = *pparams;
4508 char *pdata = *ppdata;
4509 unsigned int data_size = 0;
4510 unsigned int param_size = 2;
4511 uint16_t info_level;
4512 files_struct *fsp;
4514 if (!params) {
4515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 return;
4519 if (total_params < 4) {
4520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521 return;
4524 fsp = file_fsp(req, SVAL(params,0));
4525 if (!fsp_is_np(fsp)) {
4526 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4527 return;
4530 info_level = SVAL(params,2);
4532 *pparams = (char *)SMB_REALLOC(*pparams,2);
4533 if (*pparams == NULL) {
4534 reply_nterror(req, NT_STATUS_NO_MEMORY);
4535 return;
4537 params = *pparams;
4538 SSVAL(params,0,0);
4539 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541 return;
4543 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4544 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4545 if (*ppdata == NULL ) {
4546 reply_nterror(req, NT_STATUS_NO_MEMORY);
4547 return;
4549 pdata = *ppdata;
4551 switch (info_level) {
4552 case SMB_FILE_STANDARD_INFORMATION:
4553 memset(pdata,0,24);
4554 SOFF_T(pdata,0,4096LL);
4555 SIVAL(pdata,16,1);
4556 SIVAL(pdata,20,1);
4557 data_size = 24;
4558 break;
4560 default:
4561 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4562 return;
4565 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4566 max_data_bytes);
4568 return;
4571 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4572 TALLOC_CTX *mem_ctx,
4573 uint16_t info_level,
4574 files_struct *fsp,
4575 struct smb_filename *smb_fname,
4576 bool delete_pending,
4577 struct timespec write_time_ts,
4578 struct ea_list *ea_list,
4579 int lock_data_count,
4580 char *lock_data,
4581 uint16_t flags2,
4582 unsigned int max_data_bytes,
4583 size_t *fixed_portion,
4584 char **ppdata,
4585 unsigned int *pdata_size)
4587 char *pdata = *ppdata;
4588 char *dstart, *dend;
4589 unsigned int data_size;
4590 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4591 time_t create_time, mtime, atime, c_time;
4592 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4593 char *p;
4594 char *base_name;
4595 char *dos_fname;
4596 int mode;
4597 int nlink;
4598 NTSTATUS status;
4599 uint64_t file_size = 0;
4600 uint64_t pos = 0;
4601 uint64_t allocation_size = 0;
4602 uint64_t file_index = 0;
4603 uint32_t access_mask = 0;
4604 size_t len = 0;
4606 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4607 return NT_STATUS_INVALID_LEVEL;
4610 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4611 smb_fname_str_dbg(smb_fname),
4612 fsp_fnum_dbg(fsp),
4613 info_level, max_data_bytes));
4615 mode = dos_mode(conn, smb_fname);
4616 nlink = psbuf->st_ex_nlink;
4618 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4619 nlink = 1;
4622 if ((nlink > 0) && delete_pending) {
4623 nlink -= 1;
4626 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4627 return NT_STATUS_INVALID_PARAMETER;
4630 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4631 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4632 if (*ppdata == NULL) {
4633 return NT_STATUS_NO_MEMORY;
4635 pdata = *ppdata;
4636 dstart = pdata;
4637 dend = dstart + data_size - 1;
4639 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4640 update_stat_ex_mtime(psbuf, write_time_ts);
4643 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4644 mtime_ts = psbuf->st_ex_mtime;
4645 atime_ts = psbuf->st_ex_atime;
4646 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4648 if (lp_dos_filetime_resolution(SNUM(conn))) {
4649 dos_filetime_timespec(&create_time_ts);
4650 dos_filetime_timespec(&mtime_ts);
4651 dos_filetime_timespec(&atime_ts);
4652 dos_filetime_timespec(&ctime_ts);
4655 create_time = convert_timespec_to_time_t(create_time_ts);
4656 mtime = convert_timespec_to_time_t(mtime_ts);
4657 atime = convert_timespec_to_time_t(atime_ts);
4658 c_time = convert_timespec_to_time_t(ctime_ts);
4660 p = strrchr_m(smb_fname->base_name,'/');
4661 if (!p)
4662 base_name = smb_fname->base_name;
4663 else
4664 base_name = p+1;
4666 /* NT expects the name to be in an exact form of the *full*
4667 filename. See the trans2 torture test */
4668 if (ISDOT(base_name)) {
4669 dos_fname = talloc_strdup(mem_ctx, "\\");
4670 if (!dos_fname) {
4671 return NT_STATUS_NO_MEMORY;
4673 } else {
4674 dos_fname = talloc_asprintf(mem_ctx,
4675 "\\%s",
4676 smb_fname->base_name);
4677 if (!dos_fname) {
4678 return NT_STATUS_NO_MEMORY;
4680 if (is_ntfs_stream_smb_fname(smb_fname)) {
4681 dos_fname = talloc_asprintf(dos_fname, "%s",
4682 smb_fname->stream_name);
4683 if (!dos_fname) {
4684 return NT_STATUS_NO_MEMORY;
4688 string_replace(dos_fname, '/', '\\');
4691 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4693 if (!fsp) {
4694 /* Do we have this path open ? */
4695 files_struct *fsp1;
4696 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4697 fsp1 = file_find_di_first(conn->sconn, fileid);
4698 if (fsp1 && fsp1->initial_allocation_size) {
4699 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4703 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4704 file_size = get_file_size_stat(psbuf);
4707 if (fsp) {
4708 pos = fsp->fh->position_information;
4711 if (fsp) {
4712 access_mask = fsp->access_mask;
4713 } else {
4714 /* GENERIC_EXECUTE mapping from Windows */
4715 access_mask = 0x12019F;
4718 /* This should be an index number - looks like
4719 dev/ino to me :-)
4721 I think this causes us to fail the IFSKIT
4722 BasicFileInformationTest. -tpot */
4723 file_index = get_FileIndex(conn, psbuf);
4725 *fixed_portion = 0;
4727 switch (info_level) {
4728 case SMB_INFO_STANDARD:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4730 data_size = 22;
4731 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4732 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4733 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4734 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4735 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4736 SSVAL(pdata,l1_attrFile,mode);
4737 break;
4739 case SMB_INFO_QUERY_EA_SIZE:
4741 unsigned int ea_size =
4742 estimate_ea_size(conn, fsp,
4743 smb_fname);
4744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4745 data_size = 26;
4746 srv_put_dos_date2(pdata,0,create_time);
4747 srv_put_dos_date2(pdata,4,atime);
4748 srv_put_dos_date2(pdata,8,mtime); /* write time */
4749 SIVAL(pdata,12,(uint32_t)file_size);
4750 SIVAL(pdata,16,(uint32_t)allocation_size);
4751 SSVAL(pdata,20,mode);
4752 SIVAL(pdata,22,ea_size);
4753 break;
4756 case SMB_INFO_IS_NAME_VALID:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4758 if (fsp) {
4759 /* os/2 needs this ? really ?*/
4760 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4762 /* This is only reached for qpathinfo */
4763 data_size = 0;
4764 break;
4766 case SMB_INFO_QUERY_EAS_FROM_LIST:
4768 size_t total_ea_len = 0;
4769 struct ea_list *ea_file_list = NULL;
4770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4772 status =
4773 get_ea_list_from_file(mem_ctx, conn, fsp,
4774 smb_fname,
4775 &total_ea_len, &ea_file_list);
4776 if (!NT_STATUS_IS_OK(status)) {
4777 return status;
4780 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4782 if (!ea_list || (total_ea_len > data_size)) {
4783 data_size = 4;
4784 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4785 break;
4788 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4789 break;
4792 case SMB_INFO_QUERY_ALL_EAS:
4794 /* We have data_size bytes to put EA's into. */
4795 size_t total_ea_len = 0;
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4798 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4799 smb_fname,
4800 &total_ea_len, &ea_list);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 return status;
4805 if (!ea_list || (total_ea_len > data_size)) {
4806 data_size = 4;
4807 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4808 break;
4811 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4812 break;
4815 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4817 /* This is FileFullEaInformation - 0xF which maps to
4818 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4820 /* We have data_size bytes to put EA's into. */
4821 size_t total_ea_len = 0;
4822 struct ea_list *ea_file_list = NULL;
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4826 /*TODO: add filtering and index handling */
4828 status =
4829 get_ea_list_from_file(mem_ctx, conn, fsp,
4830 smb_fname,
4831 &total_ea_len, &ea_file_list);
4832 if (!NT_STATUS_IS_OK(status)) {
4833 return status;
4835 if (!ea_file_list) {
4836 return NT_STATUS_NO_EAS_ON_FILE;
4839 status = fill_ea_chained_buffer(mem_ctx,
4840 pdata,
4841 data_size,
4842 &data_size,
4843 conn, ea_file_list);
4844 if (!NT_STATUS_IS_OK(status)) {
4845 return status;
4847 break;
4850 case SMB_FILE_BASIC_INFORMATION:
4851 case SMB_QUERY_FILE_BASIC_INFO:
4853 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4855 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4856 } else {
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4858 data_size = 40;
4859 SIVAL(pdata,36,0);
4861 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4862 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4863 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4864 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4865 SIVAL(pdata,32,mode);
4867 DEBUG(5,("SMB_QFBI - "));
4868 DEBUG(5,("create: %s ", ctime(&create_time)));
4869 DEBUG(5,("access: %s ", ctime(&atime)));
4870 DEBUG(5,("write: %s ", ctime(&mtime)));
4871 DEBUG(5,("change: %s ", ctime(&c_time)));
4872 DEBUG(5,("mode: %x\n", mode));
4873 *fixed_portion = data_size;
4874 break;
4876 case SMB_FILE_STANDARD_INFORMATION:
4877 case SMB_QUERY_FILE_STANDARD_INFO:
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4880 data_size = 24;
4881 SOFF_T(pdata,0,allocation_size);
4882 SOFF_T(pdata,8,file_size);
4883 SIVAL(pdata,16,nlink);
4884 SCVAL(pdata,20,delete_pending?1:0);
4885 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4886 SSVAL(pdata,22,0); /* Padding. */
4887 *fixed_portion = 24;
4888 break;
4890 case SMB_FILE_EA_INFORMATION:
4891 case SMB_QUERY_FILE_EA_INFO:
4893 unsigned int ea_size =
4894 estimate_ea_size(conn, fsp, smb_fname);
4895 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4896 data_size = 4;
4897 *fixed_portion = 4;
4898 SIVAL(pdata,0,ea_size);
4899 break;
4902 /* Get the 8.3 name - used if NT SMB was negotiated. */
4903 case SMB_QUERY_FILE_ALT_NAME_INFO:
4904 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4906 char mangled_name[13];
4907 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4908 if (!name_to_8_3(base_name,mangled_name,
4909 True,conn->params)) {
4910 return NT_STATUS_NO_MEMORY;
4912 status = srvstr_push(dstart, flags2,
4913 pdata+4, mangled_name,
4914 PTR_DIFF(dend, pdata+4),
4915 STR_UNICODE, &len);
4916 if (!NT_STATUS_IS_OK(status)) {
4917 return status;
4919 data_size = 4 + len;
4920 SIVAL(pdata,0,len);
4921 *fixed_portion = 8;
4922 break;
4925 case SMB_QUERY_FILE_NAME_INFO:
4928 this must be *exactly* right for ACLs on mapped drives to work
4930 status = srvstr_push(dstart, flags2,
4931 pdata+4, dos_fname,
4932 PTR_DIFF(dend, pdata+4),
4933 STR_UNICODE, &len);
4934 if (!NT_STATUS_IS_OK(status)) {
4935 return status;
4937 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4938 data_size = 4 + len;
4939 SIVAL(pdata,0,len);
4940 break;
4943 case SMB_FILE_ALLOCATION_INFORMATION:
4944 case SMB_QUERY_FILE_ALLOCATION_INFO:
4945 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4946 data_size = 8;
4947 SOFF_T(pdata,0,allocation_size);
4948 break;
4950 case SMB_FILE_END_OF_FILE_INFORMATION:
4951 case SMB_QUERY_FILE_END_OF_FILEINFO:
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4953 data_size = 8;
4954 SOFF_T(pdata,0,file_size);
4955 break;
4957 case SMB_QUERY_FILE_ALL_INFO:
4958 case SMB_FILE_ALL_INFORMATION:
4960 unsigned int ea_size =
4961 estimate_ea_size(conn, fsp, smb_fname);
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4963 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4964 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4965 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4966 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4967 SIVAL(pdata,32,mode);
4968 SIVAL(pdata,36,0); /* padding. */
4969 pdata += 40;
4970 SOFF_T(pdata,0,allocation_size);
4971 SOFF_T(pdata,8,file_size);
4972 SIVAL(pdata,16,nlink);
4973 SCVAL(pdata,20,delete_pending);
4974 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4975 SSVAL(pdata,22,0);
4976 pdata += 24;
4977 SIVAL(pdata,0,ea_size);
4978 pdata += 4; /* EA info */
4979 status = srvstr_push(dstart, flags2,
4980 pdata+4, dos_fname,
4981 PTR_DIFF(dend, pdata+4),
4982 STR_UNICODE, &len);
4983 if (!NT_STATUS_IS_OK(status)) {
4984 return status;
4986 SIVAL(pdata,0,len);
4987 pdata += 4 + len;
4988 data_size = PTR_DIFF(pdata,(*ppdata));
4989 *fixed_portion = 10;
4990 break;
4993 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4995 unsigned int ea_size =
4996 estimate_ea_size(conn, fsp, smb_fname);
4997 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4998 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4999 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5000 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5001 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5002 SIVAL(pdata, 0x20, mode);
5003 SIVAL(pdata, 0x24, 0); /* padding. */
5004 SBVAL(pdata, 0x28, allocation_size);
5005 SBVAL(pdata, 0x30, file_size);
5006 SIVAL(pdata, 0x38, nlink);
5007 SCVAL(pdata, 0x3C, delete_pending);
5008 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5009 SSVAL(pdata, 0x3E, 0); /* padding */
5010 SBVAL(pdata, 0x40, file_index);
5011 SIVAL(pdata, 0x48, ea_size);
5012 SIVAL(pdata, 0x4C, access_mask);
5013 SBVAL(pdata, 0x50, pos);
5014 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5015 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5017 pdata += 0x60;
5019 status = srvstr_push(dstart, flags2,
5020 pdata+4, dos_fname,
5021 PTR_DIFF(dend, pdata+4),
5022 STR_UNICODE, &len);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 return status;
5026 SIVAL(pdata,0,len);
5027 pdata += 4 + len;
5028 data_size = PTR_DIFF(pdata,(*ppdata));
5029 *fixed_portion = 104;
5030 break;
5032 case SMB_FILE_INTERNAL_INFORMATION:
5034 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5035 SBVAL(pdata, 0, file_index);
5036 data_size = 8;
5037 *fixed_portion = 8;
5038 break;
5040 case SMB_FILE_ACCESS_INFORMATION:
5041 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5042 SIVAL(pdata, 0, access_mask);
5043 data_size = 4;
5044 *fixed_portion = 4;
5045 break;
5047 case SMB_FILE_NAME_INFORMATION:
5048 /* Pathname with leading '\'. */
5050 size_t byte_len;
5051 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5052 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5053 SIVAL(pdata,0,byte_len);
5054 data_size = 4 + byte_len;
5055 break;
5058 case SMB_FILE_DISPOSITION_INFORMATION:
5059 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5060 data_size = 1;
5061 SCVAL(pdata,0,delete_pending);
5062 *fixed_portion = 1;
5063 break;
5065 case SMB_FILE_POSITION_INFORMATION:
5066 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5067 data_size = 8;
5068 SOFF_T(pdata,0,pos);
5069 *fixed_portion = 8;
5070 break;
5072 case SMB_FILE_MODE_INFORMATION:
5073 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5074 SIVAL(pdata,0,mode);
5075 data_size = 4;
5076 *fixed_portion = 4;
5077 break;
5079 case SMB_FILE_ALIGNMENT_INFORMATION:
5080 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5081 SIVAL(pdata,0,0); /* No alignment needed. */
5082 data_size = 4;
5083 *fixed_portion = 4;
5084 break;
5087 * NT4 server just returns "invalid query" to this - if we try
5088 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5089 * want this. JRA.
5091 /* The first statement above is false - verified using Thursby
5092 * client against NT4 -- gcolley.
5094 case SMB_QUERY_FILE_STREAM_INFO:
5095 case SMB_FILE_STREAM_INFORMATION: {
5096 unsigned int num_streams = 0;
5097 struct stream_struct *streams = NULL;
5099 DEBUG(10,("smbd_do_qfilepathinfo: "
5100 "SMB_FILE_STREAM_INFORMATION\n"));
5102 if (is_ntfs_stream_smb_fname(smb_fname)) {
5103 return NT_STATUS_INVALID_PARAMETER;
5106 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5107 talloc_tos(), &num_streams, &streams);
5109 if (!NT_STATUS_IS_OK(status)) {
5110 DEBUG(10, ("could not get stream info: %s\n",
5111 nt_errstr(status)));
5112 return status;
5115 status = marshall_stream_info(num_streams, streams,
5116 pdata, max_data_bytes,
5117 &data_size);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 DEBUG(10, ("marshall_stream_info failed: %s\n",
5121 nt_errstr(status)));
5122 TALLOC_FREE(streams);
5123 return status;
5126 TALLOC_FREE(streams);
5128 *fixed_portion = 32;
5130 break;
5132 case SMB_QUERY_COMPRESSION_INFO:
5133 case SMB_FILE_COMPRESSION_INFORMATION:
5134 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5135 SOFF_T(pdata,0,file_size);
5136 SIVAL(pdata,8,0); /* ??? */
5137 SIVAL(pdata,12,0); /* ??? */
5138 data_size = 16;
5139 *fixed_portion = 16;
5140 break;
5142 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5143 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5144 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5145 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5146 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5147 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5148 SOFF_T(pdata,32,allocation_size);
5149 SOFF_T(pdata,40,file_size);
5150 SIVAL(pdata,48,mode);
5151 SIVAL(pdata,52,0); /* ??? */
5152 data_size = 56;
5153 *fixed_portion = 56;
5154 break;
5156 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5158 SIVAL(pdata,0,mode);
5159 SIVAL(pdata,4,0);
5160 data_size = 8;
5161 *fixed_portion = 8;
5162 break;
5165 * CIFS UNIX Extensions.
5168 case SMB_QUERY_FILE_UNIX_BASIC:
5170 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5171 data_size = PTR_DIFF(pdata,(*ppdata));
5173 DEBUG(4,("smbd_do_qfilepathinfo: "
5174 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5175 dump_data(4, (uint8_t *)(*ppdata), data_size);
5177 break;
5179 case SMB_QUERY_FILE_UNIX_INFO2:
5181 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5182 data_size = PTR_DIFF(pdata,(*ppdata));
5185 int i;
5186 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5188 for (i=0; i<100; i++)
5189 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5190 DEBUG(4,("\n"));
5193 break;
5195 case SMB_QUERY_FILE_UNIX_LINK:
5197 int link_len = 0;
5198 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5200 if (!buffer) {
5201 return NT_STATUS_NO_MEMORY;
5204 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5205 #ifdef S_ISLNK
5206 if(!S_ISLNK(psbuf->st_ex_mode)) {
5207 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5209 #else
5210 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5211 #endif
5212 link_len = SMB_VFS_READLINK(conn,
5213 smb_fname->base_name,
5214 buffer, PATH_MAX);
5215 if (link_len == -1) {
5216 return map_nt_error_from_unix(errno);
5218 buffer[link_len] = 0;
5219 status = srvstr_push(dstart, flags2,
5220 pdata, buffer,
5221 PTR_DIFF(dend, pdata),
5222 STR_TERMINATE, &len);
5223 if (!NT_STATUS_IS_OK(status)) {
5224 return status;
5226 pdata += len;
5227 data_size = PTR_DIFF(pdata,(*ppdata));
5229 break;
5232 #if defined(HAVE_POSIX_ACLS)
5233 case SMB_QUERY_POSIX_ACL:
5235 SMB_ACL_T file_acl = NULL;
5236 SMB_ACL_T def_acl = NULL;
5237 uint16_t num_file_acls = 0;
5238 uint16_t num_def_acls = 0;
5240 if (fsp && fsp->fh->fd != -1) {
5241 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5242 talloc_tos());
5243 } else {
5244 file_acl =
5245 SMB_VFS_SYS_ACL_GET_FILE(conn,
5246 smb_fname->base_name,
5247 SMB_ACL_TYPE_ACCESS,
5248 talloc_tos());
5251 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5252 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5253 "not implemented on "
5254 "filesystem containing %s\n",
5255 smb_fname->base_name));
5256 return NT_STATUS_NOT_IMPLEMENTED;
5259 if (S_ISDIR(psbuf->st_ex_mode)) {
5260 if (fsp && fsp->is_directory) {
5261 def_acl =
5262 SMB_VFS_SYS_ACL_GET_FILE(
5263 conn,
5264 fsp->fsp_name->base_name,
5265 SMB_ACL_TYPE_DEFAULT,
5266 talloc_tos());
5267 } else {
5268 def_acl =
5269 SMB_VFS_SYS_ACL_GET_FILE(
5270 conn,
5271 smb_fname->base_name,
5272 SMB_ACL_TYPE_DEFAULT,
5273 talloc_tos());
5275 def_acl = free_empty_sys_acl(conn, def_acl);
5278 num_file_acls = count_acl_entries(conn, file_acl);
5279 num_def_acls = count_acl_entries(conn, def_acl);
5281 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5282 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5283 data_size,
5284 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5285 SMB_POSIX_ACL_HEADER_SIZE) ));
5286 if (file_acl) {
5287 TALLOC_FREE(file_acl);
5289 if (def_acl) {
5290 TALLOC_FREE(def_acl);
5292 return NT_STATUS_BUFFER_TOO_SMALL;
5295 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5296 SSVAL(pdata,2,num_file_acls);
5297 SSVAL(pdata,4,num_def_acls);
5298 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5299 if (file_acl) {
5300 TALLOC_FREE(file_acl);
5302 if (def_acl) {
5303 TALLOC_FREE(def_acl);
5305 return NT_STATUS_INTERNAL_ERROR;
5307 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5308 if (file_acl) {
5309 TALLOC_FREE(file_acl);
5311 if (def_acl) {
5312 TALLOC_FREE(def_acl);
5314 return NT_STATUS_INTERNAL_ERROR;
5317 if (file_acl) {
5318 TALLOC_FREE(file_acl);
5320 if (def_acl) {
5321 TALLOC_FREE(def_acl);
5323 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5324 break;
5326 #endif
5329 case SMB_QUERY_POSIX_LOCK:
5331 uint64_t count;
5332 uint64_t offset;
5333 uint64_t smblctx;
5334 enum brl_type lock_type;
5336 /* We need an open file with a real fd for this. */
5337 if (!fsp || fsp->fh->fd == -1) {
5338 return NT_STATUS_INVALID_LEVEL;
5341 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5342 return NT_STATUS_INVALID_PARAMETER;
5345 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5346 case POSIX_LOCK_TYPE_READ:
5347 lock_type = READ_LOCK;
5348 break;
5349 case POSIX_LOCK_TYPE_WRITE:
5350 lock_type = WRITE_LOCK;
5351 break;
5352 case POSIX_LOCK_TYPE_UNLOCK:
5353 default:
5354 /* There's no point in asking for an unlock... */
5355 return NT_STATUS_INVALID_PARAMETER;
5358 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5359 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5360 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5362 status = query_lock(fsp,
5363 &smblctx,
5364 &count,
5365 &offset,
5366 &lock_type,
5367 POSIX_LOCK);
5369 if (ERROR_WAS_LOCK_DENIED(status)) {
5370 /* Here we need to report who has it locked... */
5371 data_size = POSIX_LOCK_DATA_SIZE;
5373 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5374 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5375 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5376 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5377 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5379 } else if (NT_STATUS_IS_OK(status)) {
5380 /* For success we just return a copy of what we sent
5381 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5382 data_size = POSIX_LOCK_DATA_SIZE;
5383 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5384 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5385 } else {
5386 return status;
5388 break;
5391 default:
5392 return NT_STATUS_INVALID_LEVEL;
5395 *pdata_size = data_size;
5396 return NT_STATUS_OK;
5399 /****************************************************************************
5400 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5401 file name or file id).
5402 ****************************************************************************/
5404 static void call_trans2qfilepathinfo(connection_struct *conn,
5405 struct smb_request *req,
5406 unsigned int tran_call,
5407 char **pparams, int total_params,
5408 char **ppdata, int total_data,
5409 unsigned int max_data_bytes)
5411 char *params = *pparams;
5412 char *pdata = *ppdata;
5413 uint16_t info_level;
5414 unsigned int data_size = 0;
5415 unsigned int param_size = 2;
5416 struct smb_filename *smb_fname = NULL;
5417 bool delete_pending = False;
5418 struct timespec write_time_ts;
5419 files_struct *fsp = NULL;
5420 struct file_id fileid;
5421 struct ea_list *ea_list = NULL;
5422 int lock_data_count = 0;
5423 char *lock_data = NULL;
5424 size_t fixed_portion;
5425 NTSTATUS status = NT_STATUS_OK;
5427 if (!params) {
5428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5429 return;
5432 ZERO_STRUCT(write_time_ts);
5434 if (tran_call == TRANSACT2_QFILEINFO) {
5435 if (total_params < 4) {
5436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5437 return;
5440 if (IS_IPC(conn)) {
5441 call_trans2qpipeinfo(conn, req, tran_call,
5442 pparams, total_params,
5443 ppdata, total_data,
5444 max_data_bytes);
5445 return;
5448 fsp = file_fsp(req, SVAL(params,0));
5449 info_level = SVAL(params,2);
5451 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5453 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5454 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5455 return;
5458 /* Initial check for valid fsp ptr. */
5459 if (!check_fsp_open(conn, req, fsp)) {
5460 return;
5463 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5464 if (smb_fname == NULL) {
5465 reply_nterror(req, NT_STATUS_NO_MEMORY);
5466 return;
5469 if(fsp->fake_file_handle) {
5471 * This is actually for the QUOTA_FAKE_FILE --metze
5474 /* We know this name is ok, it's already passed the checks. */
5476 } else if(fsp->fh->fd == -1) {
5478 * This is actually a QFILEINFO on a directory
5479 * handle (returned from an NT SMB). NT5.0 seems
5480 * to do this call. JRA.
5483 if (INFO_LEVEL_IS_UNIX(info_level)) {
5484 /* Always do lstat for UNIX calls. */
5485 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5486 DEBUG(3,("call_trans2qfilepathinfo: "
5487 "SMB_VFS_LSTAT of %s failed "
5488 "(%s)\n",
5489 smb_fname_str_dbg(smb_fname),
5490 strerror(errno)));
5491 reply_nterror(req,
5492 map_nt_error_from_unix(errno));
5493 return;
5495 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5496 DEBUG(3,("call_trans2qfilepathinfo: "
5497 "SMB_VFS_STAT of %s failed (%s)\n",
5498 smb_fname_str_dbg(smb_fname),
5499 strerror(errno)));
5500 reply_nterror(req,
5501 map_nt_error_from_unix(errno));
5502 return;
5505 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5506 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5507 } else {
5509 * Original code - this is an open file.
5511 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5512 DEBUG(3, ("fstat of %s failed (%s)\n",
5513 fsp_fnum_dbg(fsp), strerror(errno)));
5514 reply_nterror(req,
5515 map_nt_error_from_unix(errno));
5516 return;
5518 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5519 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5522 } else {
5523 uint32_t name_hash;
5524 char *fname = NULL;
5525 uint32_t ucf_flags = 0;
5527 /* qpathinfo */
5528 if (total_params < 7) {
5529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5530 return;
5533 info_level = SVAL(params,0);
5535 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5537 if (INFO_LEVEL_IS_UNIX(info_level)) {
5538 if (!lp_unix_extensions()) {
5539 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5540 return;
5542 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5543 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5544 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5545 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5549 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5550 total_params - 6,
5551 STR_TERMINATE, &status);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 reply_nterror(req, status);
5554 return;
5557 status = filename_convert(req,
5558 conn,
5559 req->flags2 & FLAGS2_DFS_PATHNAMES,
5560 fname,
5561 ucf_flags,
5562 NULL,
5563 &smb_fname);
5564 if (!NT_STATUS_IS_OK(status)) {
5565 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5566 reply_botherror(req,
5567 NT_STATUS_PATH_NOT_COVERED,
5568 ERRSRV, ERRbadpath);
5569 return;
5571 reply_nterror(req, status);
5572 return;
5575 /* If this is a stream, check if there is a delete_pending. */
5576 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5577 && is_ntfs_stream_smb_fname(smb_fname)) {
5578 struct smb_filename *smb_fname_base;
5580 /* Create an smb_filename with stream_name == NULL. */
5581 smb_fname_base = synthetic_smb_fname(
5582 talloc_tos(), smb_fname->base_name,
5583 NULL, NULL);
5584 if (smb_fname_base == NULL) {
5585 reply_nterror(req, NT_STATUS_NO_MEMORY);
5586 return;
5589 if (INFO_LEVEL_IS_UNIX(info_level)) {
5590 /* Always do lstat for UNIX calls. */
5591 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5592 DEBUG(3,("call_trans2qfilepathinfo: "
5593 "SMB_VFS_LSTAT of %s failed "
5594 "(%s)\n",
5595 smb_fname_str_dbg(smb_fname_base),
5596 strerror(errno)));
5597 TALLOC_FREE(smb_fname_base);
5598 reply_nterror(req,
5599 map_nt_error_from_unix(errno));
5600 return;
5602 } else {
5603 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5604 DEBUG(3,("call_trans2qfilepathinfo: "
5605 "fileinfo of %s failed "
5606 "(%s)\n",
5607 smb_fname_str_dbg(smb_fname_base),
5608 strerror(errno)));
5609 TALLOC_FREE(smb_fname_base);
5610 reply_nterror(req,
5611 map_nt_error_from_unix(errno));
5612 return;
5616 status = file_name_hash(conn,
5617 smb_fname_str_dbg(smb_fname_base),
5618 &name_hash);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 TALLOC_FREE(smb_fname_base);
5621 reply_nterror(req, status);
5622 return;
5625 fileid = vfs_file_id_from_sbuf(conn,
5626 &smb_fname_base->st);
5627 TALLOC_FREE(smb_fname_base);
5628 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5629 if (delete_pending) {
5630 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5631 return;
5635 if (INFO_LEVEL_IS_UNIX(info_level)) {
5636 /* Always do lstat for UNIX calls. */
5637 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5638 DEBUG(3,("call_trans2qfilepathinfo: "
5639 "SMB_VFS_LSTAT of %s failed (%s)\n",
5640 smb_fname_str_dbg(smb_fname),
5641 strerror(errno)));
5642 reply_nterror(req,
5643 map_nt_error_from_unix(errno));
5644 return;
5647 } else {
5648 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5649 DEBUG(3,("call_trans2qfilepathinfo: "
5650 "SMB_VFS_STAT of %s failed (%s)\n",
5651 smb_fname_str_dbg(smb_fname),
5652 strerror(errno)));
5653 reply_nterror(req,
5654 map_nt_error_from_unix(errno));
5655 return;
5659 status = file_name_hash(conn,
5660 smb_fname_str_dbg(smb_fname),
5661 &name_hash);
5662 if (!NT_STATUS_IS_OK(status)) {
5663 reply_nterror(req, status);
5664 return;
5667 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5668 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5669 if (delete_pending) {
5670 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5671 return;
5675 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5676 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5677 fsp_fnum_dbg(fsp),
5678 info_level,tran_call,total_data));
5680 /* Pull out any data sent here before we realloc. */
5681 switch (info_level) {
5682 case SMB_INFO_QUERY_EAS_FROM_LIST:
5684 /* Pull any EA list from the data portion. */
5685 uint32_t ea_size;
5687 if (total_data < 4) {
5688 reply_nterror(
5689 req, NT_STATUS_INVALID_PARAMETER);
5690 return;
5692 ea_size = IVAL(pdata,0);
5694 if (total_data > 0 && ea_size != total_data) {
5695 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5696 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5697 reply_nterror(
5698 req, NT_STATUS_INVALID_PARAMETER);
5699 return;
5702 if (!lp_ea_support(SNUM(conn))) {
5703 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5704 return;
5707 /* Pull out the list of names. */
5708 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5709 if (!ea_list) {
5710 reply_nterror(
5711 req, NT_STATUS_INVALID_PARAMETER);
5712 return;
5714 break;
5717 case SMB_QUERY_POSIX_LOCK:
5719 if (fsp == NULL || fsp->fh->fd == -1) {
5720 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5721 return;
5724 if (total_data != POSIX_LOCK_DATA_SIZE) {
5725 reply_nterror(
5726 req, NT_STATUS_INVALID_PARAMETER);
5727 return;
5730 /* Copy the lock range data. */
5731 lock_data = (char *)talloc_memdup(
5732 req, pdata, total_data);
5733 if (!lock_data) {
5734 reply_nterror(req, NT_STATUS_NO_MEMORY);
5735 return;
5737 lock_data_count = total_data;
5739 default:
5740 break;
5743 *pparams = (char *)SMB_REALLOC(*pparams,2);
5744 if (*pparams == NULL) {
5745 reply_nterror(req, NT_STATUS_NO_MEMORY);
5746 return;
5748 params = *pparams;
5749 SSVAL(params,0,0);
5752 * draft-leach-cifs-v1-spec-02.txt
5753 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5754 * says:
5756 * The requested information is placed in the Data portion of the
5757 * transaction response. For the information levels greater than 0x100,
5758 * the transaction response has 1 parameter word which should be
5759 * ignored by the client.
5761 * However Windows only follows this rule for the IS_NAME_VALID call.
5763 switch (info_level) {
5764 case SMB_INFO_IS_NAME_VALID:
5765 param_size = 0;
5766 break;
5769 if ((info_level & 0xFF00) == 0xFF00) {
5771 * We use levels that start with 0xFF00
5772 * internally to represent SMB2 specific levels
5774 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5775 return;
5778 status = smbd_do_qfilepathinfo(conn, req, info_level,
5779 fsp, smb_fname,
5780 delete_pending, write_time_ts,
5781 ea_list,
5782 lock_data_count, lock_data,
5783 req->flags2, max_data_bytes,
5784 &fixed_portion,
5785 ppdata, &data_size);
5786 if (!NT_STATUS_IS_OK(status)) {
5787 reply_nterror(req, status);
5788 return;
5790 if (fixed_portion > max_data_bytes) {
5791 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5792 return;
5795 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5796 max_data_bytes);
5798 return;
5801 /****************************************************************************
5802 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5803 code.
5804 ****************************************************************************/
5806 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5807 connection_struct *conn,
5808 struct smb_request *req,
5809 bool overwrite_if_exists,
5810 const struct smb_filename *smb_fname_old,
5811 struct smb_filename *smb_fname_new)
5813 NTSTATUS status = NT_STATUS_OK;
5815 /* source must already exist. */
5816 if (!VALID_STAT(smb_fname_old->st)) {
5817 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5820 if (VALID_STAT(smb_fname_new->st)) {
5821 if (overwrite_if_exists) {
5822 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5823 return NT_STATUS_FILE_IS_A_DIRECTORY;
5825 status = unlink_internals(conn,
5826 req,
5827 FILE_ATTRIBUTE_NORMAL,
5828 smb_fname_new,
5829 false);
5830 if (!NT_STATUS_IS_OK(status)) {
5831 return status;
5833 } else {
5834 /* Disallow if newname already exists. */
5835 return NT_STATUS_OBJECT_NAME_COLLISION;
5839 /* No links from a directory. */
5840 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5841 return NT_STATUS_FILE_IS_A_DIRECTORY;
5844 /* Setting a hardlink to/from a stream isn't currently supported. */
5845 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5846 is_ntfs_stream_smb_fname(smb_fname_new)) {
5847 return NT_STATUS_INVALID_PARAMETER;
5850 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5851 smb_fname_old->base_name, smb_fname_new->base_name));
5853 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5854 smb_fname_new->base_name) != 0) {
5855 status = map_nt_error_from_unix(errno);
5856 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5857 nt_errstr(status), smb_fname_old->base_name,
5858 smb_fname_new->base_name));
5860 return status;
5863 /****************************************************************************
5864 Deal with setting the time from any of the setfilepathinfo functions.
5865 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5866 calling this function.
5867 ****************************************************************************/
5869 NTSTATUS smb_set_file_time(connection_struct *conn,
5870 files_struct *fsp,
5871 const struct smb_filename *smb_fname,
5872 struct smb_file_time *ft,
5873 bool setting_write_time)
5875 struct smb_filename smb_fname_base;
5876 uint32_t action =
5877 FILE_NOTIFY_CHANGE_LAST_ACCESS
5878 |FILE_NOTIFY_CHANGE_LAST_WRITE
5879 |FILE_NOTIFY_CHANGE_CREATION;
5881 if (!VALID_STAT(smb_fname->st)) {
5882 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5885 /* get some defaults (no modifications) if any info is zero or -1. */
5886 if (null_timespec(ft->create_time)) {
5887 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5890 if (null_timespec(ft->atime)) {
5891 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5894 if (null_timespec(ft->mtime)) {
5895 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5898 if (!setting_write_time) {
5899 /* ft->mtime comes from change time, not write time. */
5900 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5903 /* Ensure the resolution is the correct for
5904 * what we can store on this filesystem. */
5906 round_timespec(conn->ts_res, &ft->create_time);
5907 round_timespec(conn->ts_res, &ft->ctime);
5908 round_timespec(conn->ts_res, &ft->atime);
5909 round_timespec(conn->ts_res, &ft->mtime);
5911 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5912 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5913 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5914 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5915 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5916 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5917 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5918 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5920 if (setting_write_time) {
5922 * This was a Windows setfileinfo on an open file.
5923 * NT does this a lot. We also need to
5924 * set the time here, as it can be read by
5925 * FindFirst/FindNext and with the patch for bug #2045
5926 * in smbd/fileio.c it ensures that this timestamp is
5927 * kept sticky even after a write. We save the request
5928 * away and will set it on file close and after a write. JRA.
5931 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5932 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5934 if (fsp != NULL) {
5935 if (fsp->base_fsp) {
5936 set_sticky_write_time_fsp(fsp->base_fsp,
5937 ft->mtime);
5938 } else {
5939 set_sticky_write_time_fsp(fsp, ft->mtime);
5941 } else {
5942 set_sticky_write_time_path(
5943 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5944 ft->mtime);
5948 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5950 /* Always call ntimes on the base, even if a stream was passed in. */
5951 smb_fname_base = *smb_fname;
5952 smb_fname_base.stream_name = NULL;
5954 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5955 return map_nt_error_from_unix(errno);
5958 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5959 smb_fname->base_name);
5960 return NT_STATUS_OK;
5963 /****************************************************************************
5964 Deal with setting the dosmode from any of the setfilepathinfo functions.
5965 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5966 done before calling this function.
5967 ****************************************************************************/
5969 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5970 const struct smb_filename *smb_fname,
5971 uint32_t dosmode)
5973 struct smb_filename *smb_fname_base;
5974 NTSTATUS status;
5976 if (!VALID_STAT(smb_fname->st)) {
5977 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5980 /* Always operate on the base_name, even if a stream was passed in. */
5981 smb_fname_base = synthetic_smb_fname(
5982 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5983 if (smb_fname_base == NULL) {
5984 return NT_STATUS_NO_MEMORY;
5987 if (dosmode) {
5988 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5989 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5990 } else {
5991 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5995 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5997 /* check the mode isn't different, before changing it */
5998 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5999 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6000 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6001 (unsigned int)dosmode));
6003 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6004 false)) {
6005 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6006 "%s failed (%s)\n",
6007 smb_fname_str_dbg(smb_fname_base),
6008 strerror(errno)));
6009 status = map_nt_error_from_unix(errno);
6010 goto out;
6013 status = NT_STATUS_OK;
6014 out:
6015 TALLOC_FREE(smb_fname_base);
6016 return status;
6019 /****************************************************************************
6020 Deal with setting the size from any of the setfilepathinfo functions.
6021 ****************************************************************************/
6023 static NTSTATUS smb_set_file_size(connection_struct *conn,
6024 struct smb_request *req,
6025 files_struct *fsp,
6026 const struct smb_filename *smb_fname,
6027 const SMB_STRUCT_STAT *psbuf,
6028 off_t size,
6029 bool fail_after_createfile)
6031 NTSTATUS status = NT_STATUS_OK;
6032 struct smb_filename *smb_fname_tmp = NULL;
6033 files_struct *new_fsp = NULL;
6035 if (!VALID_STAT(*psbuf)) {
6036 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6039 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6041 if (size == get_file_size_stat(psbuf)) {
6042 return NT_STATUS_OK;
6045 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6046 smb_fname_str_dbg(smb_fname), (double)size));
6048 if (fsp && fsp->fh->fd != -1) {
6049 /* Handle based call. */
6050 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6051 return NT_STATUS_ACCESS_DENIED;
6054 if (vfs_set_filelen(fsp, size) == -1) {
6055 return map_nt_error_from_unix(errno);
6057 trigger_write_time_update_immediate(fsp);
6058 return NT_STATUS_OK;
6061 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6062 if (smb_fname_tmp == NULL) {
6063 return NT_STATUS_NO_MEMORY;
6066 smb_fname_tmp->st = *psbuf;
6068 status = SMB_VFS_CREATE_FILE(
6069 conn, /* conn */
6070 req, /* req */
6071 0, /* root_dir_fid */
6072 smb_fname_tmp, /* fname */
6073 FILE_WRITE_DATA, /* access_mask */
6074 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6075 FILE_SHARE_DELETE),
6076 FILE_OPEN, /* create_disposition*/
6077 0, /* create_options */
6078 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6079 0, /* oplock_request */
6080 NULL, /* lease */
6081 0, /* allocation_size */
6082 0, /* private_flags */
6083 NULL, /* sd */
6084 NULL, /* ea_list */
6085 &new_fsp, /* result */
6086 NULL, /* pinfo */
6087 NULL, NULL); /* create context */
6089 TALLOC_FREE(smb_fname_tmp);
6091 if (!NT_STATUS_IS_OK(status)) {
6092 /* NB. We check for open_was_deferred in the caller. */
6093 return status;
6096 /* See RAW-SFILEINFO-END-OF-FILE */
6097 if (fail_after_createfile) {
6098 close_file(req, new_fsp,NORMAL_CLOSE);
6099 return NT_STATUS_INVALID_LEVEL;
6102 if (vfs_set_filelen(new_fsp, size) == -1) {
6103 status = map_nt_error_from_unix(errno);
6104 close_file(req, new_fsp,NORMAL_CLOSE);
6105 return status;
6108 trigger_write_time_update_immediate(new_fsp);
6109 close_file(req, new_fsp,NORMAL_CLOSE);
6110 return NT_STATUS_OK;
6113 /****************************************************************************
6114 Deal with SMB_INFO_SET_EA.
6115 ****************************************************************************/
6117 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6118 const char *pdata,
6119 int total_data,
6120 files_struct *fsp,
6121 const struct smb_filename *smb_fname)
6123 struct ea_list *ea_list = NULL;
6124 TALLOC_CTX *ctx = NULL;
6125 NTSTATUS status = NT_STATUS_OK;
6127 if (total_data < 10) {
6129 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6130 length. They seem to have no effect. Bug #3212. JRA */
6132 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6133 /* We're done. We only get EA info in this call. */
6134 return NT_STATUS_OK;
6137 return NT_STATUS_INVALID_PARAMETER;
6140 if (IVAL(pdata,0) > total_data) {
6141 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6142 IVAL(pdata,0), (unsigned int)total_data));
6143 return NT_STATUS_INVALID_PARAMETER;
6146 ctx = talloc_tos();
6147 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6148 if (!ea_list) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 status = set_ea(conn, fsp, smb_fname, ea_list);
6154 return status;
6157 /****************************************************************************
6158 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6159 ****************************************************************************/
6161 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6162 const char *pdata,
6163 int total_data,
6164 files_struct *fsp)
6166 struct ea_list *ea_list = NULL;
6167 NTSTATUS status;
6169 if (!fsp) {
6170 return NT_STATUS_INVALID_HANDLE;
6173 if (!lp_ea_support(SNUM(conn))) {
6174 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6175 "EA's not supported.\n",
6176 (unsigned int)total_data));
6177 return NT_STATUS_EAS_NOT_SUPPORTED;
6180 if (total_data < 10) {
6181 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6182 "too small.\n",
6183 (unsigned int)total_data));
6184 return NT_STATUS_INVALID_PARAMETER;
6187 ea_list = read_nttrans_ea_list(talloc_tos(),
6188 pdata,
6189 total_data);
6191 if (!ea_list) {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6197 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6198 smb_fname_str_dbg(fsp->fsp_name),
6199 nt_errstr(status) ));
6201 return status;
6205 /****************************************************************************
6206 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6207 ****************************************************************************/
6209 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6210 const char *pdata,
6211 int total_data,
6212 files_struct *fsp,
6213 struct smb_filename *smb_fname)
6215 NTSTATUS status = NT_STATUS_OK;
6216 bool delete_on_close;
6217 uint32_t dosmode = 0;
6219 if (total_data < 1) {
6220 return NT_STATUS_INVALID_PARAMETER;
6223 if (fsp == NULL) {
6224 return NT_STATUS_INVALID_HANDLE;
6227 delete_on_close = (CVAL(pdata,0) ? True : False);
6228 dosmode = dos_mode(conn, smb_fname);
6230 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6231 "delete_on_close = %u\n",
6232 smb_fname_str_dbg(smb_fname),
6233 (unsigned int)dosmode,
6234 (unsigned int)delete_on_close ));
6236 if (delete_on_close) {
6237 status = can_set_delete_on_close(fsp, dosmode);
6238 if (!NT_STATUS_IS_OK(status)) {
6239 return status;
6243 /* The set is across all open files on this dev/inode pair. */
6244 if (!set_delete_on_close(fsp, delete_on_close,
6245 conn->session_info->security_token,
6246 conn->session_info->unix_token)) {
6247 return NT_STATUS_ACCESS_DENIED;
6249 return NT_STATUS_OK;
6252 /****************************************************************************
6253 Deal with SMB_FILE_POSITION_INFORMATION.
6254 ****************************************************************************/
6256 static NTSTATUS smb_file_position_information(connection_struct *conn,
6257 const char *pdata,
6258 int total_data,
6259 files_struct *fsp)
6261 uint64_t position_information;
6263 if (total_data < 8) {
6264 return NT_STATUS_INVALID_PARAMETER;
6267 if (fsp == NULL) {
6268 /* Ignore on pathname based set. */
6269 return NT_STATUS_OK;
6272 position_information = (uint64_t)IVAL(pdata,0);
6273 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6275 DEBUG(10,("smb_file_position_information: Set file position "
6276 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6277 (double)position_information));
6278 fsp->fh->position_information = position_information;
6279 return NT_STATUS_OK;
6282 /****************************************************************************
6283 Deal with SMB_FILE_MODE_INFORMATION.
6284 ****************************************************************************/
6286 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6287 const char *pdata,
6288 int total_data)
6290 uint32_t mode;
6292 if (total_data < 4) {
6293 return NT_STATUS_INVALID_PARAMETER;
6295 mode = IVAL(pdata,0);
6296 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6297 return NT_STATUS_INVALID_PARAMETER;
6299 return NT_STATUS_OK;
6302 /****************************************************************************
6303 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6304 ****************************************************************************/
6306 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6307 struct smb_request *req,
6308 const char *pdata,
6309 int total_data,
6310 const struct smb_filename *smb_fname)
6312 char *link_target = NULL;
6313 const char *newname = smb_fname->base_name;
6314 TALLOC_CTX *ctx = talloc_tos();
6316 /* Set a symbolic link. */
6317 /* Don't allow this if follow links is false. */
6319 if (total_data == 0) {
6320 return NT_STATUS_INVALID_PARAMETER;
6323 if (!lp_follow_symlinks(SNUM(conn))) {
6324 return NT_STATUS_ACCESS_DENIED;
6327 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6328 total_data, STR_TERMINATE);
6330 if (!link_target) {
6331 return NT_STATUS_INVALID_PARAMETER;
6334 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6335 newname, link_target ));
6337 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6338 return map_nt_error_from_unix(errno);
6341 return NT_STATUS_OK;
6344 /****************************************************************************
6345 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6346 ****************************************************************************/
6348 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6349 struct smb_request *req,
6350 const char *pdata, int total_data,
6351 struct smb_filename *smb_fname_new)
6353 char *oldname = NULL;
6354 struct smb_filename *smb_fname_old = NULL;
6355 TALLOC_CTX *ctx = talloc_tos();
6356 NTSTATUS status = NT_STATUS_OK;
6358 /* Set a hard link. */
6359 if (total_data == 0) {
6360 return NT_STATUS_INVALID_PARAMETER;
6363 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6364 total_data, STR_TERMINATE, &status);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 return status;
6369 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6370 smb_fname_str_dbg(smb_fname_new), oldname));
6372 status = filename_convert(ctx,
6373 conn,
6374 req->flags2 & FLAGS2_DFS_PATHNAMES,
6375 oldname,
6377 NULL,
6378 &smb_fname_old);
6379 if (!NT_STATUS_IS_OK(status)) {
6380 return status;
6383 return hardlink_internals(ctx, conn, req, false,
6384 smb_fname_old, smb_fname_new);
6387 /****************************************************************************
6388 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6389 ****************************************************************************/
6391 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6392 struct smb_request *req,
6393 const char *pdata,
6394 int total_data,
6395 files_struct *fsp,
6396 struct smb_filename *smb_fname_src)
6398 bool overwrite;
6399 uint32_t len;
6400 char *newname = NULL;
6401 struct smb_filename *smb_fname_dst = NULL;
6402 NTSTATUS status = NT_STATUS_OK;
6403 TALLOC_CTX *ctx = talloc_tos();
6405 if (!fsp) {
6406 return NT_STATUS_INVALID_HANDLE;
6409 if (total_data < 20) {
6410 return NT_STATUS_INVALID_PARAMETER;
6413 overwrite = (CVAL(pdata,0) ? True : False);
6414 len = IVAL(pdata,16);
6416 if (len > (total_data - 20) || (len == 0)) {
6417 return NT_STATUS_INVALID_PARAMETER;
6420 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6421 &pdata[20], len, STR_TERMINATE,
6422 &status);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 return status;
6427 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6428 newname));
6430 status = filename_convert(ctx,
6431 conn,
6432 req->flags2 & FLAGS2_DFS_PATHNAMES,
6433 newname,
6434 UCF_SAVE_LCOMP,
6435 NULL,
6436 &smb_fname_dst);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 return status;
6441 if (fsp->base_fsp) {
6442 /* newname must be a stream name. */
6443 if (newname[0] != ':') {
6444 return NT_STATUS_NOT_SUPPORTED;
6447 /* Create an smb_fname to call rename_internals_fsp() with. */
6448 smb_fname_dst = synthetic_smb_fname(
6449 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6450 newname, NULL);
6451 if (smb_fname_dst == NULL) {
6452 status = NT_STATUS_NO_MEMORY;
6453 goto out;
6457 * Set the original last component, since
6458 * rename_internals_fsp() requires it.
6460 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6461 newname);
6462 if (smb_fname_dst->original_lcomp == NULL) {
6463 status = NT_STATUS_NO_MEMORY;
6464 goto out;
6469 DEBUG(10,("smb2_file_rename_information: "
6470 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6471 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6472 smb_fname_str_dbg(smb_fname_dst)));
6473 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6474 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6475 overwrite);
6477 out:
6478 TALLOC_FREE(smb_fname_dst);
6479 return status;
6482 static NTSTATUS smb_file_link_information(connection_struct *conn,
6483 struct smb_request *req,
6484 const char *pdata,
6485 int total_data,
6486 files_struct *fsp,
6487 struct smb_filename *smb_fname_src)
6489 bool overwrite;
6490 uint32_t len;
6491 char *newname = NULL;
6492 struct smb_filename *smb_fname_dst = NULL;
6493 NTSTATUS status = NT_STATUS_OK;
6494 TALLOC_CTX *ctx = talloc_tos();
6496 if (!fsp) {
6497 return NT_STATUS_INVALID_HANDLE;
6500 if (total_data < 20) {
6501 return NT_STATUS_INVALID_PARAMETER;
6504 overwrite = (CVAL(pdata,0) ? true : false);
6505 len = IVAL(pdata,16);
6507 if (len > (total_data - 20) || (len == 0)) {
6508 return NT_STATUS_INVALID_PARAMETER;
6511 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6512 &pdata[20], len, STR_TERMINATE,
6513 &status);
6514 if (!NT_STATUS_IS_OK(status)) {
6515 return status;
6518 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6519 newname));
6521 status = filename_convert(ctx,
6522 conn,
6523 req->flags2 & FLAGS2_DFS_PATHNAMES,
6524 newname,
6525 UCF_SAVE_LCOMP,
6526 NULL,
6527 &smb_fname_dst);
6528 if (!NT_STATUS_IS_OK(status)) {
6529 return status;
6532 if (fsp->base_fsp) {
6533 /* No stream names. */
6534 return NT_STATUS_NOT_SUPPORTED;
6537 DEBUG(10,("smb_file_link_information: "
6538 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6539 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6540 smb_fname_str_dbg(smb_fname_dst)));
6541 status = hardlink_internals(ctx,
6542 conn,
6543 req,
6544 overwrite,
6545 fsp->fsp_name,
6546 smb_fname_dst);
6548 TALLOC_FREE(smb_fname_dst);
6549 return status;
6552 /****************************************************************************
6553 Deal with SMB_FILE_RENAME_INFORMATION.
6554 ****************************************************************************/
6556 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6557 struct smb_request *req,
6558 const char *pdata,
6559 int total_data,
6560 files_struct *fsp,
6561 struct smb_filename *smb_fname_src)
6563 bool overwrite;
6564 uint32_t root_fid;
6565 uint32_t len;
6566 char *newname = NULL;
6567 struct smb_filename *smb_fname_dst = NULL;
6568 bool dest_has_wcard = False;
6569 NTSTATUS status = NT_STATUS_OK;
6570 char *p;
6571 TALLOC_CTX *ctx = talloc_tos();
6573 if (total_data < 13) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 overwrite = (CVAL(pdata,0) ? True : False);
6578 root_fid = IVAL(pdata,4);
6579 len = IVAL(pdata,8);
6581 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6582 return NT_STATUS_INVALID_PARAMETER;
6585 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6586 len, 0, &status,
6587 &dest_has_wcard);
6588 if (!NT_STATUS_IS_OK(status)) {
6589 return status;
6592 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6593 newname));
6595 status = resolve_dfspath_wcard(ctx, conn,
6596 req->flags2 & FLAGS2_DFS_PATHNAMES,
6597 newname,
6598 true,
6599 !conn->sconn->using_smb2,
6600 &newname,
6601 &dest_has_wcard);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 return status;
6606 /* Check the new name has no '/' characters. */
6607 if (strchr_m(newname, '/')) {
6608 return NT_STATUS_NOT_SUPPORTED;
6611 if (fsp && fsp->base_fsp) {
6612 /* newname must be a stream name. */
6613 if (newname[0] != ':') {
6614 return NT_STATUS_NOT_SUPPORTED;
6617 /* Create an smb_fname to call rename_internals_fsp() with. */
6618 smb_fname_dst = synthetic_smb_fname(
6619 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6620 newname, NULL);
6621 if (smb_fname_dst == NULL) {
6622 status = NT_STATUS_NO_MEMORY;
6623 goto out;
6627 * Set the original last component, since
6628 * rename_internals_fsp() requires it.
6630 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6631 newname);
6632 if (smb_fname_dst->original_lcomp == NULL) {
6633 status = NT_STATUS_NO_MEMORY;
6634 goto out;
6637 } else {
6639 * Build up an smb_fname_dst based on the filename passed in.
6640 * We basically just strip off the last component, and put on
6641 * the newname instead.
6643 char *base_name = NULL;
6645 /* newname must *not* be a stream name. */
6646 if (newname[0] == ':') {
6647 return NT_STATUS_NOT_SUPPORTED;
6651 * Strip off the last component (filename) of the path passed
6652 * in.
6654 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6655 if (!base_name) {
6656 return NT_STATUS_NO_MEMORY;
6658 p = strrchr_m(base_name, '/');
6659 if (p) {
6660 p[1] = '\0';
6661 } else {
6662 base_name = talloc_strdup(ctx, "");
6663 if (!base_name) {
6664 return NT_STATUS_NO_MEMORY;
6667 /* Append the new name. */
6668 base_name = talloc_asprintf_append(base_name,
6669 "%s",
6670 newname);
6671 if (!base_name) {
6672 return NT_STATUS_NO_MEMORY;
6675 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6676 (UCF_SAVE_LCOMP |
6677 (dest_has_wcard ?
6678 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6679 0)));
6681 /* If an error we expect this to be
6682 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6684 if (!NT_STATUS_IS_OK(status)) {
6685 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6686 status)) {
6687 goto out;
6689 /* Create an smb_fname to call rename_internals_fsp() */
6690 smb_fname_dst = synthetic_smb_fname(
6691 ctx, base_name, NULL, NULL);
6692 if (smb_fname_dst == NULL) {
6693 status = NT_STATUS_NO_MEMORY;
6694 goto out;
6699 if (fsp) {
6700 DEBUG(10,("smb_file_rename_information: "
6701 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6702 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6703 smb_fname_str_dbg(smb_fname_dst)));
6704 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6705 overwrite);
6706 } else {
6707 DEBUG(10,("smb_file_rename_information: "
6708 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6709 smb_fname_str_dbg(smb_fname_src),
6710 smb_fname_str_dbg(smb_fname_dst)));
6711 status = rename_internals(ctx, conn, req, smb_fname_src,
6712 smb_fname_dst, 0, overwrite, false,
6713 dest_has_wcard,
6714 FILE_WRITE_ATTRIBUTES);
6716 out:
6717 TALLOC_FREE(smb_fname_dst);
6718 return status;
6721 /****************************************************************************
6722 Deal with SMB_SET_POSIX_ACL.
6723 ****************************************************************************/
6725 #if defined(HAVE_POSIX_ACLS)
6726 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6727 const char *pdata,
6728 int total_data,
6729 files_struct *fsp,
6730 const struct smb_filename *smb_fname)
6732 uint16_t posix_acl_version;
6733 uint16_t num_file_acls;
6734 uint16_t num_def_acls;
6735 bool valid_file_acls = True;
6736 bool valid_def_acls = True;
6738 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6739 return NT_STATUS_INVALID_PARAMETER;
6741 posix_acl_version = SVAL(pdata,0);
6742 num_file_acls = SVAL(pdata,2);
6743 num_def_acls = SVAL(pdata,4);
6745 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6746 valid_file_acls = False;
6747 num_file_acls = 0;
6750 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6751 valid_def_acls = False;
6752 num_def_acls = 0;
6755 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6756 return NT_STATUS_INVALID_PARAMETER;
6759 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6760 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6761 return NT_STATUS_INVALID_PARAMETER;
6764 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6765 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6766 (unsigned int)num_file_acls,
6767 (unsigned int)num_def_acls));
6769 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6770 smb_fname->base_name, num_file_acls,
6771 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6772 return map_nt_error_from_unix(errno);
6775 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6776 smb_fname->base_name, &smb_fname->st, num_def_acls,
6777 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6778 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6779 return map_nt_error_from_unix(errno);
6781 return NT_STATUS_OK;
6783 #endif
6785 /****************************************************************************
6786 Deal with SMB_SET_POSIX_LOCK.
6787 ****************************************************************************/
6789 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6790 struct smb_request *req,
6791 const char *pdata,
6792 int total_data,
6793 files_struct *fsp)
6795 uint64_t count;
6796 uint64_t offset;
6797 uint64_t smblctx;
6798 bool blocking_lock = False;
6799 enum brl_type lock_type;
6801 NTSTATUS status = NT_STATUS_OK;
6803 if (fsp == NULL || fsp->fh->fd == -1) {
6804 return NT_STATUS_INVALID_HANDLE;
6807 if (total_data != POSIX_LOCK_DATA_SIZE) {
6808 return NT_STATUS_INVALID_PARAMETER;
6811 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6812 case POSIX_LOCK_TYPE_READ:
6813 lock_type = READ_LOCK;
6814 break;
6815 case POSIX_LOCK_TYPE_WRITE:
6816 /* Return the right POSIX-mappable error code for files opened read-only. */
6817 if (!fsp->can_write) {
6818 return NT_STATUS_INVALID_HANDLE;
6820 lock_type = WRITE_LOCK;
6821 break;
6822 case POSIX_LOCK_TYPE_UNLOCK:
6823 lock_type = UNLOCK_LOCK;
6824 break;
6825 default:
6826 return NT_STATUS_INVALID_PARAMETER;
6829 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6830 blocking_lock = False;
6831 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6832 blocking_lock = True;
6833 } else {
6834 return NT_STATUS_INVALID_PARAMETER;
6837 if (!lp_blocking_locks(SNUM(conn))) {
6838 blocking_lock = False;
6841 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6842 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6843 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6844 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6845 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6847 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6848 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6849 fsp_str_dbg(fsp),
6850 (unsigned int)lock_type,
6851 (unsigned long long)smblctx,
6852 (double)count,
6853 (double)offset ));
6855 if (lock_type == UNLOCK_LOCK) {
6856 status = do_unlock(req->sconn->msg_ctx,
6857 fsp,
6858 smblctx,
6859 count,
6860 offset,
6861 POSIX_LOCK);
6862 } else {
6863 uint64_t block_smblctx;
6865 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6866 fsp,
6867 smblctx,
6868 count,
6869 offset,
6870 lock_type,
6871 POSIX_LOCK,
6872 blocking_lock,
6873 &status,
6874 &block_smblctx);
6876 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6878 * A blocking lock was requested. Package up
6879 * this smb into a queued request and push it
6880 * onto the blocking lock queue.
6882 if(push_blocking_lock_request(br_lck,
6883 req,
6884 fsp,
6885 -1, /* infinite timeout. */
6887 smblctx,
6888 lock_type,
6889 POSIX_LOCK,
6890 offset,
6891 count,
6892 block_smblctx)) {
6893 TALLOC_FREE(br_lck);
6894 return status;
6897 TALLOC_FREE(br_lck);
6900 return status;
6903 /****************************************************************************
6904 Deal with SMB_SET_FILE_BASIC_INFO.
6905 ****************************************************************************/
6907 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6908 const char *pdata,
6909 int total_data,
6910 files_struct *fsp,
6911 const struct smb_filename *smb_fname)
6913 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6914 struct smb_file_time ft;
6915 uint32_t dosmode = 0;
6916 NTSTATUS status = NT_STATUS_OK;
6918 ZERO_STRUCT(ft);
6920 if (total_data < 36) {
6921 return NT_STATUS_INVALID_PARAMETER;
6924 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6925 if (!NT_STATUS_IS_OK(status)) {
6926 return status;
6929 /* Set the attributes */
6930 dosmode = IVAL(pdata,32);
6931 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6932 if (!NT_STATUS_IS_OK(status)) {
6933 return status;
6936 /* create time */
6937 ft.create_time = interpret_long_date(pdata);
6939 /* access time */
6940 ft.atime = interpret_long_date(pdata+8);
6942 /* write time. */
6943 ft.mtime = interpret_long_date(pdata+16);
6945 /* change time. */
6946 ft.ctime = interpret_long_date(pdata+24);
6948 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6949 smb_fname_str_dbg(smb_fname)));
6951 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6952 true);
6955 /****************************************************************************
6956 Deal with SMB_INFO_STANDARD.
6957 ****************************************************************************/
6959 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6960 const char *pdata,
6961 int total_data,
6962 files_struct *fsp,
6963 const struct smb_filename *smb_fname)
6965 NTSTATUS status;
6966 struct smb_file_time ft;
6968 ZERO_STRUCT(ft);
6970 if (total_data < 12) {
6971 return NT_STATUS_INVALID_PARAMETER;
6974 /* create time */
6975 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6976 /* access time */
6977 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6978 /* write time */
6979 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6981 DEBUG(10,("smb_set_info_standard: file %s\n",
6982 smb_fname_str_dbg(smb_fname)));
6984 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6985 if (!NT_STATUS_IS_OK(status)) {
6986 return status;
6989 return smb_set_file_time(conn,
6990 fsp,
6991 smb_fname,
6992 &ft,
6993 true);
6996 /****************************************************************************
6997 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6998 ****************************************************************************/
7000 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7001 struct smb_request *req,
7002 const char *pdata,
7003 int total_data,
7004 files_struct *fsp,
7005 struct smb_filename *smb_fname)
7007 uint64_t allocation_size = 0;
7008 NTSTATUS status = NT_STATUS_OK;
7009 files_struct *new_fsp = NULL;
7011 if (!VALID_STAT(smb_fname->st)) {
7012 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7015 if (total_data < 8) {
7016 return NT_STATUS_INVALID_PARAMETER;
7019 allocation_size = (uint64_t)IVAL(pdata,0);
7020 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7021 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7022 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7023 (double)allocation_size));
7025 if (allocation_size) {
7026 allocation_size = smb_roundup(conn, allocation_size);
7029 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7030 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7031 (double)allocation_size));
7033 if (fsp && fsp->fh->fd != -1) {
7034 /* Open file handle. */
7035 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7036 return NT_STATUS_ACCESS_DENIED;
7039 /* Only change if needed. */
7040 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7041 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7042 return map_nt_error_from_unix(errno);
7045 /* But always update the time. */
7047 * This is equivalent to a write. Ensure it's seen immediately
7048 * if there are no pending writes.
7050 trigger_write_time_update_immediate(fsp);
7051 return NT_STATUS_OK;
7054 /* Pathname or stat or directory file. */
7055 status = SMB_VFS_CREATE_FILE(
7056 conn, /* conn */
7057 req, /* req */
7058 0, /* root_dir_fid */
7059 smb_fname, /* fname */
7060 FILE_WRITE_DATA, /* access_mask */
7061 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7062 FILE_SHARE_DELETE),
7063 FILE_OPEN, /* create_disposition*/
7064 0, /* create_options */
7065 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7066 0, /* oplock_request */
7067 NULL, /* lease */
7068 0, /* allocation_size */
7069 0, /* private_flags */
7070 NULL, /* sd */
7071 NULL, /* ea_list */
7072 &new_fsp, /* result */
7073 NULL, /* pinfo */
7074 NULL, NULL); /* create context */
7076 if (!NT_STATUS_IS_OK(status)) {
7077 /* NB. We check for open_was_deferred in the caller. */
7078 return status;
7081 /* Only change if needed. */
7082 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7083 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7084 status = map_nt_error_from_unix(errno);
7085 close_file(req, new_fsp, NORMAL_CLOSE);
7086 return status;
7090 /* Changing the allocation size should set the last mod time. */
7092 * This is equivalent to a write. Ensure it's seen immediately
7093 * if there are no pending writes.
7095 trigger_write_time_update_immediate(new_fsp);
7096 close_file(req, new_fsp, NORMAL_CLOSE);
7097 return NT_STATUS_OK;
7100 /****************************************************************************
7101 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7102 ****************************************************************************/
7104 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7105 struct smb_request *req,
7106 const char *pdata,
7107 int total_data,
7108 files_struct *fsp,
7109 const struct smb_filename *smb_fname,
7110 bool fail_after_createfile)
7112 off_t size;
7114 if (total_data < 8) {
7115 return NT_STATUS_INVALID_PARAMETER;
7118 size = IVAL(pdata,0);
7119 size |= (((off_t)IVAL(pdata,4)) << 32);
7120 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7121 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7122 (double)size));
7124 return smb_set_file_size(conn, req,
7125 fsp,
7126 smb_fname,
7127 &smb_fname->st,
7128 size,
7129 fail_after_createfile);
7132 /****************************************************************************
7133 Allow a UNIX info mknod.
7134 ****************************************************************************/
7136 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7137 const char *pdata,
7138 int total_data,
7139 const struct smb_filename *smb_fname)
7141 uint32_t file_type = IVAL(pdata,56);
7142 #if defined(HAVE_MAKEDEV)
7143 uint32_t dev_major = IVAL(pdata,60);
7144 uint32_t dev_minor = IVAL(pdata,68);
7145 #endif
7146 SMB_DEV_T dev = (SMB_DEV_T)0;
7147 uint32_t raw_unixmode = IVAL(pdata,84);
7148 NTSTATUS status;
7149 mode_t unixmode;
7151 if (total_data < 100) {
7152 return NT_STATUS_INVALID_PARAMETER;
7155 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7156 PERM_NEW_FILE, &unixmode);
7157 if (!NT_STATUS_IS_OK(status)) {
7158 return status;
7161 #if defined(HAVE_MAKEDEV)
7162 dev = makedev(dev_major, dev_minor);
7163 #endif
7165 switch (file_type) {
7166 #if defined(S_IFIFO)
7167 case UNIX_TYPE_FIFO:
7168 unixmode |= S_IFIFO;
7169 break;
7170 #endif
7171 #if defined(S_IFSOCK)
7172 case UNIX_TYPE_SOCKET:
7173 unixmode |= S_IFSOCK;
7174 break;
7175 #endif
7176 #if defined(S_IFCHR)
7177 case UNIX_TYPE_CHARDEV:
7178 unixmode |= S_IFCHR;
7179 break;
7180 #endif
7181 #if defined(S_IFBLK)
7182 case UNIX_TYPE_BLKDEV:
7183 unixmode |= S_IFBLK;
7184 break;
7185 #endif
7186 default:
7187 return NT_STATUS_INVALID_PARAMETER;
7190 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7191 "%.0f mode 0%o for file %s\n", (double)dev,
7192 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7194 /* Ok - do the mknod. */
7195 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7196 return map_nt_error_from_unix(errno);
7199 /* If any of the other "set" calls fail we
7200 * don't want to end up with a half-constructed mknod.
7203 if (lp_inherit_permissions(SNUM(conn))) {
7204 char *parent;
7205 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7206 &parent, NULL)) {
7207 return NT_STATUS_NO_MEMORY;
7209 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7210 unixmode);
7211 TALLOC_FREE(parent);
7214 return NT_STATUS_OK;
7217 /****************************************************************************
7218 Deal with SMB_SET_FILE_UNIX_BASIC.
7219 ****************************************************************************/
7221 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7222 struct smb_request *req,
7223 const char *pdata,
7224 int total_data,
7225 files_struct *fsp,
7226 const struct smb_filename *smb_fname)
7228 struct smb_file_time ft;
7229 uint32_t raw_unixmode;
7230 mode_t unixmode;
7231 off_t size = 0;
7232 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7233 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7234 NTSTATUS status = NT_STATUS_OK;
7235 bool delete_on_fail = False;
7236 enum perm_type ptype;
7237 files_struct *all_fsps = NULL;
7238 bool modify_mtime = true;
7239 struct file_id id;
7240 struct smb_filename *smb_fname_tmp = NULL;
7241 SMB_STRUCT_STAT sbuf;
7243 ZERO_STRUCT(ft);
7245 if (total_data < 100) {
7246 return NT_STATUS_INVALID_PARAMETER;
7249 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7250 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7251 size=IVAL(pdata,0); /* first 8 Bytes are size */
7252 size |= (((off_t)IVAL(pdata,4)) << 32);
7255 ft.atime = interpret_long_date(pdata+24); /* access_time */
7256 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7257 set_owner = (uid_t)IVAL(pdata,40);
7258 set_grp = (gid_t)IVAL(pdata,48);
7259 raw_unixmode = IVAL(pdata,84);
7261 if (VALID_STAT(smb_fname->st)) {
7262 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7263 ptype = PERM_EXISTING_DIR;
7264 } else {
7265 ptype = PERM_EXISTING_FILE;
7267 } else {
7268 ptype = PERM_NEW_FILE;
7271 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7272 ptype, &unixmode);
7273 if (!NT_STATUS_IS_OK(status)) {
7274 return status;
7277 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7278 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7279 smb_fname_str_dbg(smb_fname), (double)size,
7280 (unsigned int)set_owner, (unsigned int)set_grp,
7281 (int)raw_unixmode));
7283 sbuf = smb_fname->st;
7285 if (!VALID_STAT(sbuf)) {
7287 * The only valid use of this is to create character and block
7288 * devices, and named pipes. This is deprecated (IMHO) and
7289 * a new info level should be used for mknod. JRA.
7292 status = smb_unix_mknod(conn,
7293 pdata,
7294 total_data,
7295 smb_fname);
7296 if (!NT_STATUS_IS_OK(status)) {
7297 return status;
7300 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7301 if (smb_fname_tmp == NULL) {
7302 return NT_STATUS_NO_MEMORY;
7305 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7306 status = map_nt_error_from_unix(errno);
7307 TALLOC_FREE(smb_fname_tmp);
7308 SMB_VFS_UNLINK(conn, smb_fname);
7309 return status;
7312 sbuf = smb_fname_tmp->st;
7313 smb_fname = smb_fname_tmp;
7315 /* Ensure we don't try and change anything else. */
7316 raw_unixmode = SMB_MODE_NO_CHANGE;
7317 size = get_file_size_stat(&sbuf);
7318 ft.atime = sbuf.st_ex_atime;
7319 ft.mtime = sbuf.st_ex_mtime;
7321 * We continue here as we might want to change the
7322 * owner uid/gid.
7324 delete_on_fail = True;
7327 #if 1
7328 /* Horrible backwards compatibility hack as an old server bug
7329 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7330 * */
7332 if (!size) {
7333 size = get_file_size_stat(&sbuf);
7335 #endif
7338 * Deal with the UNIX specific mode set.
7341 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7342 int ret;
7344 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7345 "setting mode 0%o for file %s\n",
7346 (unsigned int)unixmode,
7347 smb_fname_str_dbg(smb_fname)));
7348 if (fsp && fsp->fh->fd != -1) {
7349 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7350 } else {
7351 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7353 if (ret != 0) {
7354 return map_nt_error_from_unix(errno);
7359 * Deal with the UNIX specific uid set.
7362 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7363 (sbuf.st_ex_uid != set_owner)) {
7364 int ret;
7366 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7367 "changing owner %u for path %s\n",
7368 (unsigned int)set_owner,
7369 smb_fname_str_dbg(smb_fname)));
7371 if (fsp && fsp->fh->fd != -1) {
7372 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7373 } else {
7375 * UNIX extensions calls must always operate
7376 * on symlinks.
7378 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7379 set_owner, (gid_t)-1);
7382 if (ret != 0) {
7383 status = map_nt_error_from_unix(errno);
7384 if (delete_on_fail) {
7385 SMB_VFS_UNLINK(conn, smb_fname);
7387 return status;
7392 * Deal with the UNIX specific gid set.
7395 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7396 (sbuf.st_ex_gid != set_grp)) {
7397 int ret;
7399 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7400 "changing group %u for file %s\n",
7401 (unsigned int)set_owner,
7402 smb_fname_str_dbg(smb_fname)));
7403 if (fsp && fsp->fh->fd != -1) {
7404 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7405 } else {
7407 * UNIX extensions calls must always operate
7408 * on symlinks.
7410 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7411 set_grp);
7413 if (ret != 0) {
7414 status = map_nt_error_from_unix(errno);
7415 if (delete_on_fail) {
7416 SMB_VFS_UNLINK(conn, smb_fname);
7418 return status;
7422 /* Deal with any size changes. */
7424 status = smb_set_file_size(conn, req,
7425 fsp,
7426 smb_fname,
7427 &sbuf,
7428 size,
7429 false);
7430 if (!NT_STATUS_IS_OK(status)) {
7431 return status;
7434 /* Deal with any time changes. */
7435 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7436 /* No change, don't cancel anything. */
7437 return status;
7440 id = vfs_file_id_from_sbuf(conn, &sbuf);
7441 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7442 all_fsps = file_find_di_next(all_fsps)) {
7444 * We're setting the time explicitly for UNIX.
7445 * Cancel any pending changes over all handles.
7447 all_fsps->update_write_time_on_close = false;
7448 TALLOC_FREE(all_fsps->update_write_time_event);
7452 * Override the "setting_write_time"
7453 * parameter here as it almost does what
7454 * we need. Just remember if we modified
7455 * mtime and send the notify ourselves.
7457 if (null_timespec(ft.mtime)) {
7458 modify_mtime = false;
7461 status = smb_set_file_time(conn,
7462 fsp,
7463 smb_fname,
7464 &ft,
7465 false);
7466 if (modify_mtime) {
7467 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7468 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7470 return status;
7473 /****************************************************************************
7474 Deal with SMB_SET_FILE_UNIX_INFO2.
7475 ****************************************************************************/
7477 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7478 struct smb_request *req,
7479 const char *pdata,
7480 int total_data,
7481 files_struct *fsp,
7482 const struct smb_filename *smb_fname)
7484 NTSTATUS status;
7485 uint32_t smb_fflags;
7486 uint32_t smb_fmask;
7488 if (total_data < 116) {
7489 return NT_STATUS_INVALID_PARAMETER;
7492 /* Start by setting all the fields that are common between UNIX_BASIC
7493 * and UNIX_INFO2.
7495 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7496 fsp, smb_fname);
7497 if (!NT_STATUS_IS_OK(status)) {
7498 return status;
7501 smb_fflags = IVAL(pdata, 108);
7502 smb_fmask = IVAL(pdata, 112);
7504 /* NB: We should only attempt to alter the file flags if the client
7505 * sends a non-zero mask.
7507 if (smb_fmask != 0) {
7508 int stat_fflags = 0;
7510 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7511 smb_fmask, &stat_fflags)) {
7512 /* Client asked to alter a flag we don't understand. */
7513 return NT_STATUS_INVALID_PARAMETER;
7516 if (fsp && fsp->fh->fd != -1) {
7517 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7518 return NT_STATUS_NOT_SUPPORTED;
7519 } else {
7520 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7521 stat_fflags) != 0) {
7522 return map_nt_error_from_unix(errno);
7527 /* XXX: need to add support for changing the create_time here. You
7528 * can do this for paths on Darwin with setattrlist(2). The right way
7529 * to hook this up is probably by extending the VFS utimes interface.
7532 return NT_STATUS_OK;
7535 /****************************************************************************
7536 Create a directory with POSIX semantics.
7537 ****************************************************************************/
7539 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7540 struct smb_request *req,
7541 char **ppdata,
7542 int total_data,
7543 struct smb_filename *smb_fname,
7544 int *pdata_return_size)
7546 NTSTATUS status = NT_STATUS_OK;
7547 uint32_t raw_unixmode = 0;
7548 uint32_t mod_unixmode = 0;
7549 mode_t unixmode = (mode_t)0;
7550 files_struct *fsp = NULL;
7551 uint16_t info_level_return = 0;
7552 int info;
7553 char *pdata = *ppdata;
7555 if (total_data < 18) {
7556 return NT_STATUS_INVALID_PARAMETER;
7559 raw_unixmode = IVAL(pdata,8);
7560 /* Next 4 bytes are not yet defined. */
7562 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7563 PERM_NEW_DIR, &unixmode);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 return status;
7568 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7570 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7571 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7573 status = SMB_VFS_CREATE_FILE(
7574 conn, /* conn */
7575 req, /* req */
7576 0, /* root_dir_fid */
7577 smb_fname, /* fname */
7578 FILE_READ_ATTRIBUTES, /* access_mask */
7579 FILE_SHARE_NONE, /* share_access */
7580 FILE_CREATE, /* create_disposition*/
7581 FILE_DIRECTORY_FILE, /* create_options */
7582 mod_unixmode, /* file_attributes */
7583 0, /* oplock_request */
7584 NULL, /* lease */
7585 0, /* allocation_size */
7586 0, /* private_flags */
7587 NULL, /* sd */
7588 NULL, /* ea_list */
7589 &fsp, /* result */
7590 &info, /* pinfo */
7591 NULL, NULL); /* create context */
7593 if (NT_STATUS_IS_OK(status)) {
7594 close_file(req, fsp, NORMAL_CLOSE);
7597 info_level_return = SVAL(pdata,16);
7599 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7600 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7601 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7602 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7603 } else {
7604 *pdata_return_size = 12;
7607 /* Realloc the data size */
7608 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7609 if (*ppdata == NULL) {
7610 *pdata_return_size = 0;
7611 return NT_STATUS_NO_MEMORY;
7613 pdata = *ppdata;
7615 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7616 SSVAL(pdata,2,0); /* No fnum. */
7617 SIVAL(pdata,4,info); /* Was directory created. */
7619 switch (info_level_return) {
7620 case SMB_QUERY_FILE_UNIX_BASIC:
7621 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7622 SSVAL(pdata,10,0); /* Padding. */
7623 store_file_unix_basic(conn, pdata + 12, fsp,
7624 &smb_fname->st);
7625 break;
7626 case SMB_QUERY_FILE_UNIX_INFO2:
7627 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7628 SSVAL(pdata,10,0); /* Padding. */
7629 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7630 &smb_fname->st);
7631 break;
7632 default:
7633 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7634 SSVAL(pdata,10,0); /* Padding. */
7635 break;
7638 return status;
7641 /****************************************************************************
7642 Open/Create a file with POSIX semantics.
7643 ****************************************************************************/
7645 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7646 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7648 static NTSTATUS smb_posix_open(connection_struct *conn,
7649 struct smb_request *req,
7650 char **ppdata,
7651 int total_data,
7652 struct smb_filename *smb_fname,
7653 int *pdata_return_size)
7655 bool extended_oplock_granted = False;
7656 char *pdata = *ppdata;
7657 uint32_t flags = 0;
7658 uint32_t wire_open_mode = 0;
7659 uint32_t raw_unixmode = 0;
7660 uint32_t mod_unixmode = 0;
7661 uint32_t create_disp = 0;
7662 uint32_t access_mask = 0;
7663 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7664 NTSTATUS status = NT_STATUS_OK;
7665 mode_t unixmode = (mode_t)0;
7666 files_struct *fsp = NULL;
7667 int oplock_request = 0;
7668 int info = 0;
7669 uint16_t info_level_return = 0;
7671 if (total_data < 18) {
7672 return NT_STATUS_INVALID_PARAMETER;
7675 flags = IVAL(pdata,0);
7676 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7677 if (oplock_request) {
7678 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7681 wire_open_mode = IVAL(pdata,4);
7683 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7684 return smb_posix_mkdir(conn, req,
7685 ppdata,
7686 total_data,
7687 smb_fname,
7688 pdata_return_size);
7691 switch (wire_open_mode & SMB_ACCMODE) {
7692 case SMB_O_RDONLY:
7693 access_mask = SMB_O_RDONLY_MAPPING;
7694 break;
7695 case SMB_O_WRONLY:
7696 access_mask = SMB_O_WRONLY_MAPPING;
7697 break;
7698 case SMB_O_RDWR:
7699 access_mask = (SMB_O_RDONLY_MAPPING|
7700 SMB_O_WRONLY_MAPPING);
7701 break;
7702 default:
7703 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7704 (unsigned int)wire_open_mode ));
7705 return NT_STATUS_INVALID_PARAMETER;
7708 wire_open_mode &= ~SMB_ACCMODE;
7710 /* First take care of O_CREAT|O_EXCL interactions. */
7711 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7712 case (SMB_O_CREAT | SMB_O_EXCL):
7713 /* File exists fail. File not exist create. */
7714 create_disp = FILE_CREATE;
7715 break;
7716 case SMB_O_CREAT:
7717 /* File exists open. File not exist create. */
7718 create_disp = FILE_OPEN_IF;
7719 break;
7720 case SMB_O_EXCL:
7721 /* O_EXCL on its own without O_CREAT is undefined.
7722 We deliberately ignore it as some versions of
7723 Linux CIFSFS can send a bare O_EXCL on the
7724 wire which other filesystems in the kernel
7725 ignore. See bug 9519 for details. */
7727 /* Fallthrough. */
7729 case 0:
7730 /* File exists open. File not exist fail. */
7731 create_disp = FILE_OPEN;
7732 break;
7733 default:
7734 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7735 (unsigned int)wire_open_mode ));
7736 return NT_STATUS_INVALID_PARAMETER;
7739 /* Next factor in the effects of O_TRUNC. */
7740 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7742 if (wire_open_mode & SMB_O_TRUNC) {
7743 switch (create_disp) {
7744 case FILE_CREATE:
7745 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7746 /* Leave create_disp alone as
7747 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7749 /* File exists fail. File not exist create. */
7750 break;
7751 case FILE_OPEN_IF:
7752 /* SMB_O_CREAT | SMB_O_TRUNC */
7753 /* File exists overwrite. File not exist create. */
7754 create_disp = FILE_OVERWRITE_IF;
7755 break;
7756 case FILE_OPEN:
7757 /* SMB_O_TRUNC */
7758 /* File exists overwrite. File not exist fail. */
7759 create_disp = FILE_OVERWRITE;
7760 break;
7761 default:
7762 /* Cannot get here. */
7763 smb_panic("smb_posix_open: logic error");
7764 return NT_STATUS_INVALID_PARAMETER;
7768 raw_unixmode = IVAL(pdata,8);
7769 /* Next 4 bytes are not yet defined. */
7771 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7772 (VALID_STAT(smb_fname->st) ?
7773 PERM_EXISTING_FILE : PERM_NEW_FILE),
7774 &unixmode);
7776 if (!NT_STATUS_IS_OK(status)) {
7777 return status;
7780 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7782 if (wire_open_mode & SMB_O_SYNC) {
7783 create_options |= FILE_WRITE_THROUGH;
7785 if (wire_open_mode & SMB_O_APPEND) {
7786 access_mask |= FILE_APPEND_DATA;
7788 if (wire_open_mode & SMB_O_DIRECT) {
7789 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7792 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7793 VALID_STAT_OF_DIR(smb_fname->st)) {
7794 if (access_mask != SMB_O_RDONLY_MAPPING) {
7795 return NT_STATUS_FILE_IS_A_DIRECTORY;
7797 create_options &= ~FILE_NON_DIRECTORY_FILE;
7798 create_options |= FILE_DIRECTORY_FILE;
7801 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7802 smb_fname_str_dbg(smb_fname),
7803 (unsigned int)wire_open_mode,
7804 (unsigned int)unixmode ));
7806 status = SMB_VFS_CREATE_FILE(
7807 conn, /* conn */
7808 req, /* req */
7809 0, /* root_dir_fid */
7810 smb_fname, /* fname */
7811 access_mask, /* access_mask */
7812 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7813 FILE_SHARE_DELETE),
7814 create_disp, /* create_disposition*/
7815 create_options, /* create_options */
7816 mod_unixmode, /* file_attributes */
7817 oplock_request, /* oplock_request */
7818 NULL, /* lease */
7819 0, /* allocation_size */
7820 0, /* private_flags */
7821 NULL, /* sd */
7822 NULL, /* ea_list */
7823 &fsp, /* result */
7824 &info, /* pinfo */
7825 NULL, NULL); /* create context */
7827 if (!NT_STATUS_IS_OK(status)) {
7828 return status;
7831 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7832 extended_oplock_granted = True;
7835 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7836 extended_oplock_granted = True;
7839 info_level_return = SVAL(pdata,16);
7841 /* Allocate the correct return size. */
7843 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7844 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7845 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7846 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7847 } else {
7848 *pdata_return_size = 12;
7851 /* Realloc the data size */
7852 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7853 if (*ppdata == NULL) {
7854 close_file(req, fsp, ERROR_CLOSE);
7855 *pdata_return_size = 0;
7856 return NT_STATUS_NO_MEMORY;
7858 pdata = *ppdata;
7860 if (extended_oplock_granted) {
7861 if (flags & REQUEST_BATCH_OPLOCK) {
7862 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7863 } else {
7864 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7866 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7867 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7868 } else {
7869 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7872 SSVAL(pdata,2,fsp->fnum);
7873 SIVAL(pdata,4,info); /* Was file created etc. */
7875 switch (info_level_return) {
7876 case SMB_QUERY_FILE_UNIX_BASIC:
7877 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7878 SSVAL(pdata,10,0); /* padding. */
7879 store_file_unix_basic(conn, pdata + 12, fsp,
7880 &smb_fname->st);
7881 break;
7882 case SMB_QUERY_FILE_UNIX_INFO2:
7883 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7884 SSVAL(pdata,10,0); /* padding. */
7885 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7886 &smb_fname->st);
7887 break;
7888 default:
7889 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7890 SSVAL(pdata,10,0); /* padding. */
7891 break;
7893 return NT_STATUS_OK;
7896 /****************************************************************************
7897 Delete a file with POSIX semantics.
7898 ****************************************************************************/
7900 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7901 struct smb_request *req,
7902 const char *pdata,
7903 int total_data,
7904 struct smb_filename *smb_fname)
7906 NTSTATUS status = NT_STATUS_OK;
7907 files_struct *fsp = NULL;
7908 uint16_t flags = 0;
7909 char del = 1;
7910 int info = 0;
7911 int create_options = 0;
7912 int i;
7913 struct share_mode_lock *lck = NULL;
7915 if (total_data < 2) {
7916 return NT_STATUS_INVALID_PARAMETER;
7919 flags = SVAL(pdata,0);
7921 if (!VALID_STAT(smb_fname->st)) {
7922 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7925 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7926 !VALID_STAT_OF_DIR(smb_fname->st)) {
7927 return NT_STATUS_NOT_A_DIRECTORY;
7930 DEBUG(10,("smb_posix_unlink: %s %s\n",
7931 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7932 smb_fname_str_dbg(smb_fname)));
7934 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7935 create_options |= FILE_DIRECTORY_FILE;
7938 status = SMB_VFS_CREATE_FILE(
7939 conn, /* conn */
7940 req, /* req */
7941 0, /* root_dir_fid */
7942 smb_fname, /* fname */
7943 DELETE_ACCESS, /* access_mask */
7944 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7945 FILE_SHARE_DELETE),
7946 FILE_OPEN, /* create_disposition*/
7947 create_options, /* create_options */
7948 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7949 0, /* oplock_request */
7950 NULL, /* lease */
7951 0, /* allocation_size */
7952 0, /* private_flags */
7953 NULL, /* sd */
7954 NULL, /* ea_list */
7955 &fsp, /* result */
7956 &info, /* pinfo */
7957 NULL, NULL); /* create context */
7959 if (!NT_STATUS_IS_OK(status)) {
7960 return status;
7964 * Don't lie to client. If we can't really delete due to
7965 * non-POSIX opens return SHARING_VIOLATION.
7968 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7969 if (lck == NULL) {
7970 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7971 "lock for file %s\n", fsp_str_dbg(fsp)));
7972 close_file(req, fsp, NORMAL_CLOSE);
7973 return NT_STATUS_INVALID_PARAMETER;
7977 * See if others still have the file open. If this is the case, then
7978 * don't delete. If all opens are POSIX delete we can set the delete
7979 * on close disposition.
7981 for (i=0; i<lck->data->num_share_modes; i++) {
7982 struct share_mode_entry *e = &lck->data->share_modes[i];
7983 if (is_valid_share_mode_entry(e)) {
7984 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7985 continue;
7987 if (share_mode_stale_pid(lck->data, i)) {
7988 continue;
7990 /* Fail with sharing violation. */
7991 TALLOC_FREE(lck);
7992 close_file(req, fsp, NORMAL_CLOSE);
7993 return NT_STATUS_SHARING_VIOLATION;
7998 * Set the delete on close.
8000 status = smb_set_file_disposition_info(conn,
8001 &del,
8003 fsp,
8004 smb_fname);
8006 TALLOC_FREE(lck);
8008 if (!NT_STATUS_IS_OK(status)) {
8009 close_file(req, fsp, NORMAL_CLOSE);
8010 return status;
8012 return close_file(req, fsp, NORMAL_CLOSE);
8015 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8016 struct smb_request *req,
8017 TALLOC_CTX *mem_ctx,
8018 uint16_t info_level,
8019 files_struct *fsp,
8020 struct smb_filename *smb_fname,
8021 char **ppdata, int total_data,
8022 int *ret_data_size)
8024 char *pdata = *ppdata;
8025 NTSTATUS status = NT_STATUS_OK;
8026 int data_return_size = 0;
8028 *ret_data_size = 0;
8030 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8031 return NT_STATUS_INVALID_LEVEL;
8034 if (!CAN_WRITE(conn)) {
8035 /* Allow POSIX opens. The open path will deny
8036 * any non-readonly opens. */
8037 if (info_level != SMB_POSIX_PATH_OPEN) {
8038 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8042 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8043 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8044 fsp_fnum_dbg(fsp),
8045 info_level, total_data));
8047 switch (info_level) {
8049 case SMB_INFO_STANDARD:
8051 status = smb_set_info_standard(conn,
8052 pdata,
8053 total_data,
8054 fsp,
8055 smb_fname);
8056 break;
8059 case SMB_INFO_SET_EA:
8061 status = smb_info_set_ea(conn,
8062 pdata,
8063 total_data,
8064 fsp,
8065 smb_fname);
8066 break;
8069 case SMB_SET_FILE_BASIC_INFO:
8070 case SMB_FILE_BASIC_INFORMATION:
8072 status = smb_set_file_basic_info(conn,
8073 pdata,
8074 total_data,
8075 fsp,
8076 smb_fname);
8077 break;
8080 case SMB_FILE_ALLOCATION_INFORMATION:
8081 case SMB_SET_FILE_ALLOCATION_INFO:
8083 status = smb_set_file_allocation_info(conn, req,
8084 pdata,
8085 total_data,
8086 fsp,
8087 smb_fname);
8088 break;
8091 case SMB_FILE_END_OF_FILE_INFORMATION:
8092 case SMB_SET_FILE_END_OF_FILE_INFO:
8095 * XP/Win7 both fail after the createfile with
8096 * SMB_SET_FILE_END_OF_FILE_INFO but not
8097 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8098 * The level is known here, so pass it down
8099 * appropriately.
8101 bool should_fail =
8102 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8104 status = smb_set_file_end_of_file_info(conn, req,
8105 pdata,
8106 total_data,
8107 fsp,
8108 smb_fname,
8109 should_fail);
8110 break;
8113 case SMB_FILE_DISPOSITION_INFORMATION:
8114 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8116 #if 0
8117 /* JRA - We used to just ignore this on a path ?
8118 * Shouldn't this be invalid level on a pathname
8119 * based call ?
8121 if (tran_call != TRANSACT2_SETFILEINFO) {
8122 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8124 #endif
8125 status = smb_set_file_disposition_info(conn,
8126 pdata,
8127 total_data,
8128 fsp,
8129 smb_fname);
8130 break;
8133 case SMB_FILE_POSITION_INFORMATION:
8135 status = smb_file_position_information(conn,
8136 pdata,
8137 total_data,
8138 fsp);
8139 break;
8142 case SMB_FILE_FULL_EA_INFORMATION:
8144 status = smb_set_file_full_ea_info(conn,
8145 pdata,
8146 total_data,
8147 fsp);
8148 break;
8151 /* From tridge Samba4 :
8152 * MODE_INFORMATION in setfileinfo (I have no
8153 * idea what "mode information" on a file is - it takes a value of 0,
8154 * 2, 4 or 6. What could it be?).
8157 case SMB_FILE_MODE_INFORMATION:
8159 status = smb_file_mode_information(conn,
8160 pdata,
8161 total_data);
8162 break;
8166 * CIFS UNIX extensions.
8169 case SMB_SET_FILE_UNIX_BASIC:
8171 status = smb_set_file_unix_basic(conn, req,
8172 pdata,
8173 total_data,
8174 fsp,
8175 smb_fname);
8176 break;
8179 case SMB_SET_FILE_UNIX_INFO2:
8181 status = smb_set_file_unix_info2(conn, req,
8182 pdata,
8183 total_data,
8184 fsp,
8185 smb_fname);
8186 break;
8189 case SMB_SET_FILE_UNIX_LINK:
8191 if (fsp) {
8192 /* We must have a pathname for this. */
8193 return NT_STATUS_INVALID_LEVEL;
8195 status = smb_set_file_unix_link(conn, req, pdata,
8196 total_data, smb_fname);
8197 break;
8200 case SMB_SET_FILE_UNIX_HLINK:
8202 if (fsp) {
8203 /* We must have a pathname for this. */
8204 return NT_STATUS_INVALID_LEVEL;
8206 status = smb_set_file_unix_hlink(conn, req,
8207 pdata, total_data,
8208 smb_fname);
8209 break;
8212 case SMB_FILE_RENAME_INFORMATION:
8214 status = smb_file_rename_information(conn, req,
8215 pdata, total_data,
8216 fsp, smb_fname);
8217 break;
8220 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8222 /* SMB2 rename information. */
8223 status = smb2_file_rename_information(conn, req,
8224 pdata, total_data,
8225 fsp, smb_fname);
8226 break;
8229 case SMB_FILE_LINK_INFORMATION:
8231 status = smb_file_link_information(conn, req,
8232 pdata, total_data,
8233 fsp, smb_fname);
8234 break;
8237 #if defined(HAVE_POSIX_ACLS)
8238 case SMB_SET_POSIX_ACL:
8240 status = smb_set_posix_acl(conn,
8241 pdata,
8242 total_data,
8243 fsp,
8244 smb_fname);
8245 break;
8247 #endif
8249 case SMB_SET_POSIX_LOCK:
8251 if (!fsp) {
8252 return NT_STATUS_INVALID_LEVEL;
8254 status = smb_set_posix_lock(conn, req,
8255 pdata, total_data, fsp);
8256 break;
8259 case SMB_POSIX_PATH_OPEN:
8261 if (fsp) {
8262 /* We must have a pathname for this. */
8263 return NT_STATUS_INVALID_LEVEL;
8266 status = smb_posix_open(conn, req,
8267 ppdata,
8268 total_data,
8269 smb_fname,
8270 &data_return_size);
8271 break;
8274 case SMB_POSIX_PATH_UNLINK:
8276 if (fsp) {
8277 /* We must have a pathname for this. */
8278 return NT_STATUS_INVALID_LEVEL;
8281 status = smb_posix_unlink(conn, req,
8282 pdata,
8283 total_data,
8284 smb_fname);
8285 break;
8288 default:
8289 return NT_STATUS_INVALID_LEVEL;
8292 if (!NT_STATUS_IS_OK(status)) {
8293 return status;
8296 *ret_data_size = data_return_size;
8297 return NT_STATUS_OK;
8300 /****************************************************************************
8301 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8302 ****************************************************************************/
8304 static void call_trans2setfilepathinfo(connection_struct *conn,
8305 struct smb_request *req,
8306 unsigned int tran_call,
8307 char **pparams, int total_params,
8308 char **ppdata, int total_data,
8309 unsigned int max_data_bytes)
8311 char *params = *pparams;
8312 char *pdata = *ppdata;
8313 uint16_t info_level;
8314 struct smb_filename *smb_fname = NULL;
8315 files_struct *fsp = NULL;
8316 NTSTATUS status = NT_STATUS_OK;
8317 int data_return_size = 0;
8319 if (!params) {
8320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8321 return;
8324 if (tran_call == TRANSACT2_SETFILEINFO) {
8325 if (total_params < 4) {
8326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8327 return;
8330 fsp = file_fsp(req, SVAL(params,0));
8331 /* Basic check for non-null fsp. */
8332 if (!check_fsp_open(conn, req, fsp)) {
8333 return;
8335 info_level = SVAL(params,2);
8337 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8338 if (smb_fname == NULL) {
8339 reply_nterror(req, NT_STATUS_NO_MEMORY);
8340 return;
8343 if(fsp->fh->fd == -1) {
8345 * This is actually a SETFILEINFO on a directory
8346 * handle (returned from an NT SMB). NT5.0 seems
8347 * to do this call. JRA.
8349 if (INFO_LEVEL_IS_UNIX(info_level)) {
8350 /* Always do lstat for UNIX calls. */
8351 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8352 DEBUG(3,("call_trans2setfilepathinfo: "
8353 "SMB_VFS_LSTAT of %s failed "
8354 "(%s)\n",
8355 smb_fname_str_dbg(smb_fname),
8356 strerror(errno)));
8357 reply_nterror(req, map_nt_error_from_unix(errno));
8358 return;
8360 } else {
8361 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8362 DEBUG(3,("call_trans2setfilepathinfo: "
8363 "fileinfo of %s failed (%s)\n",
8364 smb_fname_str_dbg(smb_fname),
8365 strerror(errno)));
8366 reply_nterror(req, map_nt_error_from_unix(errno));
8367 return;
8370 } else if (fsp->print_file) {
8372 * Doing a DELETE_ON_CLOSE should cancel a print job.
8374 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8375 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8377 DEBUG(3,("call_trans2setfilepathinfo: "
8378 "Cancelling print job (%s)\n",
8379 fsp_str_dbg(fsp)));
8381 SSVAL(params,0,0);
8382 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8383 *ppdata, 0,
8384 max_data_bytes);
8385 return;
8386 } else {
8387 reply_nterror(req,
8388 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8389 return;
8391 } else {
8393 * Original code - this is an open file.
8395 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8396 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8397 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8398 strerror(errno)));
8399 reply_nterror(req, map_nt_error_from_unix(errno));
8400 return;
8403 } else {
8404 char *fname = NULL;
8405 uint32_t ucf_flags = 0;
8407 /* set path info */
8408 if (total_params < 7) {
8409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8410 return;
8413 info_level = SVAL(params,0);
8414 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8415 total_params - 6, STR_TERMINATE,
8416 &status);
8417 if (!NT_STATUS_IS_OK(status)) {
8418 reply_nterror(req, status);
8419 return;
8422 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8423 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8424 info_level == SMB_FILE_RENAME_INFORMATION ||
8425 info_level == SMB_POSIX_PATH_UNLINK) {
8426 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8429 status = filename_convert(req, conn,
8430 req->flags2 & FLAGS2_DFS_PATHNAMES,
8431 fname,
8432 ucf_flags,
8433 NULL,
8434 &smb_fname);
8435 if (!NT_STATUS_IS_OK(status)) {
8436 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8437 reply_botherror(req,
8438 NT_STATUS_PATH_NOT_COVERED,
8439 ERRSRV, ERRbadpath);
8440 return;
8442 reply_nterror(req, status);
8443 return;
8446 if (INFO_LEVEL_IS_UNIX(info_level)) {
8448 * For CIFS UNIX extensions the target name may not exist.
8451 /* Always do lstat for UNIX calls. */
8452 SMB_VFS_LSTAT(conn, smb_fname);
8454 } else if (!VALID_STAT(smb_fname->st) &&
8455 SMB_VFS_STAT(conn, smb_fname)) {
8456 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8457 "%s failed (%s)\n",
8458 smb_fname_str_dbg(smb_fname),
8459 strerror(errno)));
8460 reply_nterror(req, map_nt_error_from_unix(errno));
8461 return;
8465 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8466 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8467 fsp_fnum_dbg(fsp),
8468 info_level,total_data));
8470 /* Realloc the parameter size */
8471 *pparams = (char *)SMB_REALLOC(*pparams,2);
8472 if (*pparams == NULL) {
8473 reply_nterror(req, NT_STATUS_NO_MEMORY);
8474 return;
8476 params = *pparams;
8478 SSVAL(params,0,0);
8480 status = smbd_do_setfilepathinfo(conn, req, req,
8481 info_level,
8482 fsp,
8483 smb_fname,
8484 ppdata, total_data,
8485 &data_return_size);
8486 if (!NT_STATUS_IS_OK(status)) {
8487 if (open_was_deferred(req->xconn, req->mid)) {
8488 /* We have re-scheduled this call. */
8489 return;
8491 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8492 /* We have re-scheduled this call. */
8493 return;
8495 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8496 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8497 ERRSRV, ERRbadpath);
8498 return;
8500 if (info_level == SMB_POSIX_PATH_OPEN) {
8501 reply_openerror(req, status);
8502 return;
8506 * Invalid EA name needs to return 2 param bytes,
8507 * not a zero-length error packet.
8509 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8510 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8511 max_data_bytes);
8512 } else {
8513 reply_nterror(req, status);
8515 return;
8518 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8519 max_data_bytes);
8521 return;
8524 /****************************************************************************
8525 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8526 ****************************************************************************/
8528 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8529 char **pparams, int total_params,
8530 char **ppdata, int total_data,
8531 unsigned int max_data_bytes)
8533 struct smb_filename *smb_dname = NULL;
8534 char *params = *pparams;
8535 char *pdata = *ppdata;
8536 char *directory = NULL;
8537 NTSTATUS status = NT_STATUS_OK;
8538 struct ea_list *ea_list = NULL;
8539 TALLOC_CTX *ctx = talloc_tos();
8541 if (!CAN_WRITE(conn)) {
8542 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8543 return;
8546 if (total_params < 5) {
8547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8548 return;
8551 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8552 total_params - 4, STR_TERMINATE,
8553 &status);
8554 if (!NT_STATUS_IS_OK(status)) {
8555 reply_nterror(req, status);
8556 return;
8559 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8561 status = filename_convert(ctx,
8562 conn,
8563 req->flags2 & FLAGS2_DFS_PATHNAMES,
8564 directory,
8566 NULL,
8567 &smb_dname);
8569 if (!NT_STATUS_IS_OK(status)) {
8570 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8571 reply_botherror(req,
8572 NT_STATUS_PATH_NOT_COVERED,
8573 ERRSRV, ERRbadpath);
8574 return;
8576 reply_nterror(req, status);
8577 return;
8581 * OS/2 workplace shell seems to send SET_EA requests of "null"
8582 * length (4 bytes containing IVAL 4).
8583 * They seem to have no effect. Bug #3212. JRA.
8586 if (total_data && (total_data != 4)) {
8587 /* Any data in this call is an EA list. */
8588 if (total_data < 10) {
8589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8590 goto out;
8593 if (IVAL(pdata,0) > total_data) {
8594 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8595 IVAL(pdata,0), (unsigned int)total_data));
8596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8597 goto out;
8600 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8601 total_data - 4);
8602 if (!ea_list) {
8603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8604 goto out;
8607 if (!lp_ea_support(SNUM(conn))) {
8608 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8609 goto out;
8612 /* If total_data == 4 Windows doesn't care what values
8613 * are placed in that field, it just ignores them.
8614 * The System i QNTC IBM SMB client puts bad values here,
8615 * so ignore them. */
8617 status = create_directory(conn, req, smb_dname);
8619 if (!NT_STATUS_IS_OK(status)) {
8620 reply_nterror(req, status);
8621 goto out;
8624 /* Try and set any given EA. */
8625 if (ea_list) {
8626 status = set_ea(conn, NULL, smb_dname, ea_list);
8627 if (!NT_STATUS_IS_OK(status)) {
8628 reply_nterror(req, status);
8629 goto out;
8633 /* Realloc the parameter and data sizes */
8634 *pparams = (char *)SMB_REALLOC(*pparams,2);
8635 if(*pparams == NULL) {
8636 reply_nterror(req, NT_STATUS_NO_MEMORY);
8637 goto out;
8639 params = *pparams;
8641 SSVAL(params,0,0);
8643 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8645 out:
8646 TALLOC_FREE(smb_dname);
8647 return;
8650 /****************************************************************************
8651 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8652 We don't actually do this - we just send a null response.
8653 ****************************************************************************/
8655 static void call_trans2findnotifyfirst(connection_struct *conn,
8656 struct smb_request *req,
8657 char **pparams, int total_params,
8658 char **ppdata, int total_data,
8659 unsigned int max_data_bytes)
8661 char *params = *pparams;
8662 uint16_t info_level;
8664 if (total_params < 6) {
8665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8666 return;
8669 info_level = SVAL(params,4);
8670 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8672 switch (info_level) {
8673 case 1:
8674 case 2:
8675 break;
8676 default:
8677 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8678 return;
8681 /* Realloc the parameter and data sizes */
8682 *pparams = (char *)SMB_REALLOC(*pparams,6);
8683 if (*pparams == NULL) {
8684 reply_nterror(req, NT_STATUS_NO_MEMORY);
8685 return;
8687 params = *pparams;
8689 SSVAL(params,0,fnf_handle);
8690 SSVAL(params,2,0); /* No changes */
8691 SSVAL(params,4,0); /* No EA errors */
8693 fnf_handle++;
8695 if(fnf_handle == 0)
8696 fnf_handle = 257;
8698 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8700 return;
8703 /****************************************************************************
8704 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8705 changes). Currently this does nothing.
8706 ****************************************************************************/
8708 static void call_trans2findnotifynext(connection_struct *conn,
8709 struct smb_request *req,
8710 char **pparams, int total_params,
8711 char **ppdata, int total_data,
8712 unsigned int max_data_bytes)
8714 char *params = *pparams;
8716 DEBUG(3,("call_trans2findnotifynext\n"));
8718 /* Realloc the parameter and data sizes */
8719 *pparams = (char *)SMB_REALLOC(*pparams,4);
8720 if (*pparams == NULL) {
8721 reply_nterror(req, NT_STATUS_NO_MEMORY);
8722 return;
8724 params = *pparams;
8726 SSVAL(params,0,0); /* No changes */
8727 SSVAL(params,2,0); /* No EA errors */
8729 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8731 return;
8734 /****************************************************************************
8735 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8736 ****************************************************************************/
8738 static void call_trans2getdfsreferral(connection_struct *conn,
8739 struct smb_request *req,
8740 char **pparams, int total_params,
8741 char **ppdata, int total_data,
8742 unsigned int max_data_bytes)
8744 char *params = *pparams;
8745 char *pathname = NULL;
8746 int reply_size = 0;
8747 int max_referral_level;
8748 NTSTATUS status = NT_STATUS_OK;
8749 TALLOC_CTX *ctx = talloc_tos();
8751 DEBUG(10,("call_trans2getdfsreferral\n"));
8753 if (total_params < 3) {
8754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8755 return;
8758 max_referral_level = SVAL(params,0);
8760 if(!lp_host_msdfs()) {
8761 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8762 return;
8765 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8766 total_params - 2, STR_TERMINATE);
8767 if (!pathname) {
8768 reply_nterror(req, NT_STATUS_NOT_FOUND);
8769 return;
8771 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8772 ppdata,&status)) < 0) {
8773 reply_nterror(req, status);
8774 return;
8777 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8778 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8779 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8781 return;
8784 #define LMCAT_SPL 0x53
8785 #define LMFUNC_GETJOBID 0x60
8787 /****************************************************************************
8788 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8789 ****************************************************************************/
8791 static void call_trans2ioctl(connection_struct *conn,
8792 struct smb_request *req,
8793 char **pparams, int total_params,
8794 char **ppdata, int total_data,
8795 unsigned int max_data_bytes)
8797 char *pdata = *ppdata;
8798 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8799 NTSTATUS status;
8800 size_t len = 0;
8802 /* check for an invalid fid before proceeding */
8804 if (!fsp) {
8805 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8806 return;
8809 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8810 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8811 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8812 if (*ppdata == NULL) {
8813 reply_nterror(req, NT_STATUS_NO_MEMORY);
8814 return;
8816 pdata = *ppdata;
8818 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8819 CAN ACCEPT THIS IN UNICODE. JRA. */
8821 /* Job number */
8822 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8824 status = srvstr_push(pdata, req->flags2, pdata + 2,
8825 lp_netbios_name(), 15,
8826 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8827 if (!NT_STATUS_IS_OK(status)) {
8828 reply_nterror(req, status);
8829 return;
8831 status = srvstr_push(pdata, req->flags2, pdata+18,
8832 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8833 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8834 if (!NT_STATUS_IS_OK(status)) {
8835 reply_nterror(req, status);
8836 return;
8838 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8839 max_data_bytes);
8840 return;
8843 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8844 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8847 /****************************************************************************
8848 Reply to a SMBfindclose (stop trans2 directory search).
8849 ****************************************************************************/
8851 void reply_findclose(struct smb_request *req)
8853 int dptr_num;
8854 struct smbd_server_connection *sconn = req->sconn;
8856 START_PROFILE(SMBfindclose);
8858 if (req->wct < 1) {
8859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8860 END_PROFILE(SMBfindclose);
8861 return;
8864 dptr_num = SVALS(req->vwv+0, 0);
8866 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8868 dptr_close(sconn, &dptr_num);
8870 reply_outbuf(req, 0, 0);
8872 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8874 END_PROFILE(SMBfindclose);
8875 return;
8878 /****************************************************************************
8879 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8880 ****************************************************************************/
8882 void reply_findnclose(struct smb_request *req)
8884 int dptr_num;
8886 START_PROFILE(SMBfindnclose);
8888 if (req->wct < 1) {
8889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8890 END_PROFILE(SMBfindnclose);
8891 return;
8894 dptr_num = SVAL(req->vwv+0, 0);
8896 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8898 /* We never give out valid handles for a
8899 findnotifyfirst - so any dptr_num is ok here.
8900 Just ignore it. */
8902 reply_outbuf(req, 0, 0);
8904 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8906 END_PROFILE(SMBfindnclose);
8907 return;
8910 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8911 struct trans_state *state)
8913 if (get_Protocol() >= PROTOCOL_NT1) {
8914 req->flags2 |= 0x40; /* IS_LONG_NAME */
8915 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8918 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8919 if (state->call != TRANSACT2_QFSINFO &&
8920 state->call != TRANSACT2_SETFSINFO) {
8921 DEBUG(0,("handle_trans2: encryption required "
8922 "with call 0x%x\n",
8923 (unsigned int)state->call));
8924 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8925 return;
8929 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8931 /* Now we must call the relevant TRANS2 function */
8932 switch(state->call) {
8933 case TRANSACT2_OPEN:
8935 START_PROFILE(Trans2_open);
8936 call_trans2open(conn, req,
8937 &state->param, state->total_param,
8938 &state->data, state->total_data,
8939 state->max_data_return);
8940 END_PROFILE(Trans2_open);
8941 break;
8944 case TRANSACT2_FINDFIRST:
8946 START_PROFILE(Trans2_findfirst);
8947 call_trans2findfirst(conn, req,
8948 &state->param, state->total_param,
8949 &state->data, state->total_data,
8950 state->max_data_return);
8951 END_PROFILE(Trans2_findfirst);
8952 break;
8955 case TRANSACT2_FINDNEXT:
8957 START_PROFILE(Trans2_findnext);
8958 call_trans2findnext(conn, req,
8959 &state->param, state->total_param,
8960 &state->data, state->total_data,
8961 state->max_data_return);
8962 END_PROFILE(Trans2_findnext);
8963 break;
8966 case TRANSACT2_QFSINFO:
8968 START_PROFILE(Trans2_qfsinfo);
8969 call_trans2qfsinfo(conn, req,
8970 &state->param, state->total_param,
8971 &state->data, state->total_data,
8972 state->max_data_return);
8973 END_PROFILE(Trans2_qfsinfo);
8974 break;
8977 case TRANSACT2_SETFSINFO:
8979 START_PROFILE(Trans2_setfsinfo);
8980 call_trans2setfsinfo(conn, req,
8981 &state->param, state->total_param,
8982 &state->data, state->total_data,
8983 state->max_data_return);
8984 END_PROFILE(Trans2_setfsinfo);
8985 break;
8988 case TRANSACT2_QPATHINFO:
8989 case TRANSACT2_QFILEINFO:
8991 START_PROFILE(Trans2_qpathinfo);
8992 call_trans2qfilepathinfo(conn, req, state->call,
8993 &state->param, state->total_param,
8994 &state->data, state->total_data,
8995 state->max_data_return);
8996 END_PROFILE(Trans2_qpathinfo);
8997 break;
9000 case TRANSACT2_SETPATHINFO:
9001 case TRANSACT2_SETFILEINFO:
9003 START_PROFILE(Trans2_setpathinfo);
9004 call_trans2setfilepathinfo(conn, req, state->call,
9005 &state->param, state->total_param,
9006 &state->data, state->total_data,
9007 state->max_data_return);
9008 END_PROFILE(Trans2_setpathinfo);
9009 break;
9012 case TRANSACT2_FINDNOTIFYFIRST:
9014 START_PROFILE(Trans2_findnotifyfirst);
9015 call_trans2findnotifyfirst(conn, req,
9016 &state->param, state->total_param,
9017 &state->data, state->total_data,
9018 state->max_data_return);
9019 END_PROFILE(Trans2_findnotifyfirst);
9020 break;
9023 case TRANSACT2_FINDNOTIFYNEXT:
9025 START_PROFILE(Trans2_findnotifynext);
9026 call_trans2findnotifynext(conn, req,
9027 &state->param, state->total_param,
9028 &state->data, state->total_data,
9029 state->max_data_return);
9030 END_PROFILE(Trans2_findnotifynext);
9031 break;
9034 case TRANSACT2_MKDIR:
9036 START_PROFILE(Trans2_mkdir);
9037 call_trans2mkdir(conn, req,
9038 &state->param, state->total_param,
9039 &state->data, state->total_data,
9040 state->max_data_return);
9041 END_PROFILE(Trans2_mkdir);
9042 break;
9045 case TRANSACT2_GET_DFS_REFERRAL:
9047 START_PROFILE(Trans2_get_dfs_referral);
9048 call_trans2getdfsreferral(conn, req,
9049 &state->param, state->total_param,
9050 &state->data, state->total_data,
9051 state->max_data_return);
9052 END_PROFILE(Trans2_get_dfs_referral);
9053 break;
9056 case TRANSACT2_IOCTL:
9058 START_PROFILE(Trans2_ioctl);
9059 call_trans2ioctl(conn, req,
9060 &state->param, state->total_param,
9061 &state->data, state->total_data,
9062 state->max_data_return);
9063 END_PROFILE(Trans2_ioctl);
9064 break;
9067 default:
9068 /* Error in request */
9069 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9070 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9074 /****************************************************************************
9075 Reply to a SMBtrans2.
9076 ****************************************************************************/
9078 void reply_trans2(struct smb_request *req)
9080 connection_struct *conn = req->conn;
9081 unsigned int dsoff;
9082 unsigned int dscnt;
9083 unsigned int psoff;
9084 unsigned int pscnt;
9085 unsigned int tran_call;
9086 struct trans_state *state;
9087 NTSTATUS result;
9089 START_PROFILE(SMBtrans2);
9091 if (req->wct < 14) {
9092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9093 END_PROFILE(SMBtrans2);
9094 return;
9097 dsoff = SVAL(req->vwv+12, 0);
9098 dscnt = SVAL(req->vwv+11, 0);
9099 psoff = SVAL(req->vwv+10, 0);
9100 pscnt = SVAL(req->vwv+9, 0);
9101 tran_call = SVAL(req->vwv+14, 0);
9103 result = allow_new_trans(conn->pending_trans, req->mid);
9104 if (!NT_STATUS_IS_OK(result)) {
9105 DEBUG(2, ("Got invalid trans2 request: %s\n",
9106 nt_errstr(result)));
9107 reply_nterror(req, result);
9108 END_PROFILE(SMBtrans2);
9109 return;
9112 if (IS_IPC(conn)) {
9113 switch (tran_call) {
9114 /* List the allowed trans2 calls on IPC$ */
9115 case TRANSACT2_OPEN:
9116 case TRANSACT2_GET_DFS_REFERRAL:
9117 case TRANSACT2_QFILEINFO:
9118 case TRANSACT2_QFSINFO:
9119 case TRANSACT2_SETFSINFO:
9120 break;
9121 default:
9122 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9123 END_PROFILE(SMBtrans2);
9124 return;
9128 if ((state = talloc(conn, struct trans_state)) == NULL) {
9129 DEBUG(0, ("talloc failed\n"));
9130 reply_nterror(req, NT_STATUS_NO_MEMORY);
9131 END_PROFILE(SMBtrans2);
9132 return;
9135 state->cmd = SMBtrans2;
9137 state->mid = req->mid;
9138 state->vuid = req->vuid;
9139 state->setup_count = SVAL(req->vwv+13, 0);
9140 state->setup = NULL;
9141 state->total_param = SVAL(req->vwv+0, 0);
9142 state->param = NULL;
9143 state->total_data = SVAL(req->vwv+1, 0);
9144 state->data = NULL;
9145 state->max_param_return = SVAL(req->vwv+2, 0);
9146 state->max_data_return = SVAL(req->vwv+3, 0);
9147 state->max_setup_return = SVAL(req->vwv+4, 0);
9148 state->close_on_completion = BITSETW(req->vwv+5, 0);
9149 state->one_way = BITSETW(req->vwv+5, 1);
9151 state->call = tran_call;
9153 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9154 is so as a sanity check */
9155 if (state->setup_count != 1) {
9157 * Need to have rc=0 for ioctl to get job id for OS/2.
9158 * Network printing will fail if function is not successful.
9159 * Similar function in reply.c will be used if protocol
9160 * is LANMAN1.0 instead of LM1.2X002.
9161 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9162 * outbuf doesn't have to be set(only job id is used).
9164 if ( (state->setup_count == 4)
9165 && (tran_call == TRANSACT2_IOCTL)
9166 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9167 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9168 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9169 } else {
9170 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9171 DEBUG(2,("Transaction is %d\n",tran_call));
9172 TALLOC_FREE(state);
9173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9174 END_PROFILE(SMBtrans2);
9175 return;
9179 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9180 goto bad_param;
9182 if (state->total_data) {
9184 if (trans_oob(state->total_data, 0, dscnt)
9185 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9186 goto bad_param;
9189 /* Can't use talloc here, the core routines do realloc on the
9190 * params and data. */
9191 state->data = (char *)SMB_MALLOC(state->total_data);
9192 if (state->data == NULL) {
9193 DEBUG(0,("reply_trans2: data malloc fail for %u "
9194 "bytes !\n", (unsigned int)state->total_data));
9195 TALLOC_FREE(state);
9196 reply_nterror(req, NT_STATUS_NO_MEMORY);
9197 END_PROFILE(SMBtrans2);
9198 return;
9201 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9204 if (state->total_param) {
9206 if (trans_oob(state->total_param, 0, pscnt)
9207 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9208 goto bad_param;
9211 /* Can't use talloc here, the core routines do realloc on the
9212 * params and data. */
9213 state->param = (char *)SMB_MALLOC(state->total_param);
9214 if (state->param == NULL) {
9215 DEBUG(0,("reply_trans: param malloc fail for %u "
9216 "bytes !\n", (unsigned int)state->total_param));
9217 SAFE_FREE(state->data);
9218 TALLOC_FREE(state);
9219 reply_nterror(req, NT_STATUS_NO_MEMORY);
9220 END_PROFILE(SMBtrans2);
9221 return;
9224 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9227 state->received_data = dscnt;
9228 state->received_param = pscnt;
9230 if ((state->received_param == state->total_param) &&
9231 (state->received_data == state->total_data)) {
9233 handle_trans2(conn, req, state);
9235 SAFE_FREE(state->data);
9236 SAFE_FREE(state->param);
9237 TALLOC_FREE(state);
9238 END_PROFILE(SMBtrans2);
9239 return;
9242 DLIST_ADD(conn->pending_trans, state);
9244 /* We need to send an interim response then receive the rest
9245 of the parameter/data bytes */
9246 reply_outbuf(req, 0, 0);
9247 show_msg((char *)req->outbuf);
9248 END_PROFILE(SMBtrans2);
9249 return;
9251 bad_param:
9253 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9254 SAFE_FREE(state->data);
9255 SAFE_FREE(state->param);
9256 TALLOC_FREE(state);
9257 END_PROFILE(SMBtrans2);
9258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9262 /****************************************************************************
9263 Reply to a SMBtranss2
9264 ****************************************************************************/
9266 void reply_transs2(struct smb_request *req)
9268 connection_struct *conn = req->conn;
9269 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9270 struct trans_state *state;
9272 START_PROFILE(SMBtranss2);
9274 show_msg((const char *)req->inbuf);
9276 /* Windows clients expect all replies to
9277 a transact secondary (SMBtranss2 0x33)
9278 to have a command code of transact
9279 (SMBtrans2 0x32). See bug #8989
9280 and also [MS-CIFS] section 2.2.4.47.2
9281 for details.
9283 req->cmd = SMBtrans2;
9285 if (req->wct < 8) {
9286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9287 END_PROFILE(SMBtranss2);
9288 return;
9291 for (state = conn->pending_trans; state != NULL;
9292 state = state->next) {
9293 if (state->mid == req->mid) {
9294 break;
9298 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9300 END_PROFILE(SMBtranss2);
9301 return;
9304 /* Revise state->total_param and state->total_data in case they have
9305 changed downwards */
9307 if (SVAL(req->vwv+0, 0) < state->total_param)
9308 state->total_param = SVAL(req->vwv+0, 0);
9309 if (SVAL(req->vwv+1, 0) < state->total_data)
9310 state->total_data = SVAL(req->vwv+1, 0);
9312 pcnt = SVAL(req->vwv+2, 0);
9313 poff = SVAL(req->vwv+3, 0);
9314 pdisp = SVAL(req->vwv+4, 0);
9316 dcnt = SVAL(req->vwv+5, 0);
9317 doff = SVAL(req->vwv+6, 0);
9318 ddisp = SVAL(req->vwv+7, 0);
9320 state->received_param += pcnt;
9321 state->received_data += dcnt;
9323 if ((state->received_data > state->total_data) ||
9324 (state->received_param > state->total_param))
9325 goto bad_param;
9327 if (pcnt) {
9328 if (trans_oob(state->total_param, pdisp, pcnt)
9329 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9330 goto bad_param;
9332 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9335 if (dcnt) {
9336 if (trans_oob(state->total_data, ddisp, dcnt)
9337 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9338 goto bad_param;
9340 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9343 if ((state->received_param < state->total_param) ||
9344 (state->received_data < state->total_data)) {
9345 END_PROFILE(SMBtranss2);
9346 return;
9349 handle_trans2(conn, req, state);
9351 DLIST_REMOVE(conn->pending_trans, state);
9352 SAFE_FREE(state->data);
9353 SAFE_FREE(state->param);
9354 TALLOC_FREE(state);
9356 END_PROFILE(SMBtranss2);
9357 return;
9359 bad_param:
9361 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9362 DLIST_REMOVE(conn->pending_trans, state);
9363 SAFE_FREE(state->data);
9364 SAFE_FREE(state->param);
9365 TALLOC_FREE(state);
9366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9367 END_PROFILE(SMBtranss2);
9368 return;