s4:rpc_server/netlogon: implement dcesrv_netr_ServerTrustPasswordsGet()
[Samba.git] / source3 / smbd / trans2.c
blob8816402a52f41d3d3b795066907640f20132ecc6
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;
2477 bool as_root = false;
2479 if (total_params < 13) {
2480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2481 goto out;
2484 dirtype = SVAL(params,0);
2485 maxentries = SVAL(params,2);
2486 findfirst_flags = SVAL(params,4);
2487 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2488 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2489 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2490 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2491 security_token_has_privilege(get_current_nttok(conn),
2492 SEC_PRIV_BACKUP));
2494 info_level = SVAL(params,6);
2496 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2497 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2498 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2499 (int)backup_priv,
2500 info_level, max_data_bytes));
2502 if (!maxentries) {
2503 /* W2K3 seems to treat zero as 1. */
2504 maxentries = 1;
2507 switch (info_level) {
2508 case SMB_FIND_INFO_STANDARD:
2509 case SMB_FIND_EA_SIZE:
2510 case SMB_FIND_EA_LIST:
2511 case SMB_FIND_FILE_DIRECTORY_INFO:
2512 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2513 case SMB_FIND_FILE_NAMES_INFO:
2514 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2515 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2516 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2517 break;
2518 case SMB_FIND_FILE_UNIX:
2519 case SMB_FIND_FILE_UNIX_INFO2:
2520 /* Always use filesystem for UNIX mtime query. */
2521 ask_sharemode = false;
2522 if (!lp_unix_extensions()) {
2523 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2524 goto out;
2526 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2527 break;
2528 default:
2529 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2530 goto out;
2533 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2534 params+12, total_params - 12,
2535 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2536 if (!NT_STATUS_IS_OK(ntstatus)) {
2537 reply_nterror(req, ntstatus);
2538 goto out;
2541 if (backup_priv) {
2542 become_root();
2543 as_root = true;
2544 ntstatus = filename_convert_with_privilege(ctx,
2545 conn,
2546 req,
2547 directory,
2548 ucf_flags,
2549 &mask_contains_wcard,
2550 &smb_dname);
2551 } else {
2552 ntstatus = filename_convert(ctx, conn,
2553 req->flags2 & FLAGS2_DFS_PATHNAMES,
2554 directory,
2555 ucf_flags,
2556 &mask_contains_wcard,
2557 &smb_dname);
2560 if (!NT_STATUS_IS_OK(ntstatus)) {
2561 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2562 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2563 ERRSRV, ERRbadpath);
2564 goto out;
2566 reply_nterror(req, ntstatus);
2567 goto out;
2570 mask = smb_dname->original_lcomp;
2572 directory = smb_dname->base_name;
2574 p = strrchr_m(directory,'/');
2575 if(p == NULL) {
2576 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2577 if((directory[0] == '.') && (directory[1] == '\0')) {
2578 mask = talloc_strdup(ctx,"*");
2579 if (!mask) {
2580 reply_nterror(req, NT_STATUS_NO_MEMORY);
2581 goto out;
2583 mask_contains_wcard = True;
2585 } else {
2586 *p = 0;
2589 if (p == NULL || p == directory) {
2590 /* Ensure we don't have a directory name of "". */
2591 directory = talloc_strdup(talloc_tos(), ".");
2592 if (!directory) {
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2594 goto out;
2598 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2600 if (info_level == SMB_FIND_EA_LIST) {
2601 uint32_t ea_size;
2603 if (total_data < 4) {
2604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2605 goto out;
2608 ea_size = IVAL(pdata,0);
2609 if (ea_size != total_data) {
2610 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2611 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2613 goto out;
2616 if (!lp_ea_support(SNUM(conn))) {
2617 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2618 goto out;
2621 /* Pull out the list of names. */
2622 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2623 if (!ea_list) {
2624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 goto out;
2629 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2631 goto out;
2634 *ppdata = (char *)SMB_REALLOC(
2635 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2636 if(*ppdata == NULL ) {
2637 reply_nterror(req, NT_STATUS_NO_MEMORY);
2638 goto out;
2640 pdata = *ppdata;
2641 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2643 /* Realloc the params space */
2644 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2645 if (*pparams == NULL) {
2646 reply_nterror(req, NT_STATUS_NO_MEMORY);
2647 goto out;
2649 params = *pparams;
2651 /* Save the wildcard match and attribs we are using on this directory -
2652 needed as lanman2 assumes these are being saved between calls */
2654 ntstatus = dptr_create(conn,
2655 req,
2656 NULL, /* fsp */
2657 directory,
2658 False,
2659 True,
2660 req->smbpid,
2661 mask,
2662 mask_contains_wcard,
2663 dirtype,
2664 &dirptr);
2666 if (!NT_STATUS_IS_OK(ntstatus)) {
2667 reply_nterror(req, ntstatus);
2668 goto out;
2671 if (backup_priv) {
2672 /* Remember this in case we have
2673 to do a findnext. */
2674 dptr_set_priv(dirptr);
2677 dptr_num = dptr_dnum(dirptr);
2678 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2680 /* Initialize per TRANS2_FIND_FIRST operation data */
2681 dptr_init_search_op(dirptr);
2683 /* We don't need to check for VOL here as this is returned by
2684 a different TRANS2 call. */
2686 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2687 directory,lp_dont_descend(ctx, SNUM(conn))));
2688 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2689 dont_descend = True;
2691 p = pdata;
2692 space_remaining = max_data_bytes;
2693 out_of_space = False;
2695 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2696 bool got_exact_match = False;
2698 /* this is a heuristic to avoid seeking the dirptr except when
2699 absolutely necessary. It allows for a filename of about 40 chars */
2700 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2701 out_of_space = True;
2702 finished = False;
2703 } else {
2704 ntstatus = get_lanman2_dir_entry(ctx,
2705 conn,
2706 dirptr,
2707 req->flags2,
2708 mask,dirtype,info_level,
2709 requires_resume_key,dont_descend,
2710 ask_sharemode,
2711 &p,pdata,data_end,
2712 space_remaining,
2713 &got_exact_match,
2714 &last_entry_off, ea_list);
2715 if (NT_STATUS_EQUAL(ntstatus,
2716 NT_STATUS_ILLEGAL_CHARACTER)) {
2718 * Bad character conversion on name. Ignore this
2719 * entry.
2721 continue;
2723 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2724 out_of_space = true;
2725 } else {
2726 finished = !NT_STATUS_IS_OK(ntstatus);
2730 if (!finished && !out_of_space)
2731 numentries++;
2734 * As an optimisation if we know we aren't looking
2735 * for a wildcard name (ie. the name matches the wildcard exactly)
2736 * then we can finish on any (first) match.
2737 * This speeds up large directory searches. JRA.
2740 if(got_exact_match)
2741 finished = True;
2743 /* Ensure space_remaining never goes -ve. */
2744 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2745 space_remaining = 0;
2746 out_of_space = true;
2747 } else {
2748 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2752 /* Check if we can close the dirptr */
2753 if(close_after_first || (finished && close_if_end)) {
2754 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2755 dptr_close(sconn, &dptr_num);
2759 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2760 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2761 * the protocol level is less than NT1. Tested with smbclient. JRA.
2762 * This should fix the OS/2 client bug #2335.
2765 if(numentries == 0) {
2766 dptr_close(sconn, &dptr_num);
2767 if (get_Protocol() < PROTOCOL_NT1) {
2768 reply_force_doserror(req, ERRDOS, ERRnofiles);
2769 goto out;
2770 } else {
2771 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2772 ERRDOS, ERRbadfile);
2773 goto out;
2777 /* At this point pdata points to numentries directory entries. */
2779 /* Set up the return parameter block */
2780 SSVAL(params,0,dptr_num);
2781 SSVAL(params,2,numentries);
2782 SSVAL(params,4,finished);
2783 SSVAL(params,6,0); /* Never an EA error */
2784 SSVAL(params,8,last_entry_off);
2786 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2787 max_data_bytes);
2789 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2790 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2791 if (!directory) {
2792 reply_nterror(req, NT_STATUS_NO_MEMORY);
2796 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2797 smb_fn_name(req->cmd),
2798 mask, directory, dirtype, numentries ) );
2801 * Force a name mangle here to ensure that the
2802 * mask as an 8.3 name is top of the mangled cache.
2803 * The reasons for this are subtle. Don't remove
2804 * this code unless you know what you are doing
2805 * (see PR#13758). JRA.
2808 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2809 char mangled_name[13];
2810 name_to_8_3(mask, mangled_name, True, conn->params);
2812 out:
2814 if (as_root) {
2815 unbecome_root();
2818 TALLOC_FREE(smb_dname);
2819 return;
2822 /****************************************************************************
2823 Reply to a TRANS2_FINDNEXT.
2824 ****************************************************************************/
2826 static void call_trans2findnext(connection_struct *conn,
2827 struct smb_request *req,
2828 char **pparams, int total_params,
2829 char **ppdata, int total_data,
2830 unsigned int max_data_bytes)
2832 /* We must be careful here that we don't return more than the
2833 allowed number of data bytes. If this means returning fewer than
2834 maxentries then so be it. We assume that the redirector has
2835 enough room for the fixed number of parameter bytes it has
2836 requested. */
2837 char *params = *pparams;
2838 char *pdata = *ppdata;
2839 char *data_end;
2840 int dptr_num;
2841 int maxentries;
2842 uint16_t info_level;
2843 uint32_t resume_key;
2844 uint16_t findnext_flags;
2845 bool close_after_request;
2846 bool close_if_end;
2847 bool requires_resume_key;
2848 bool continue_bit;
2849 bool mask_contains_wcard = False;
2850 char *resume_name = NULL;
2851 const char *mask = NULL;
2852 const char *directory = NULL;
2853 char *p = NULL;
2854 uint16_t dirtype;
2855 int numentries = 0;
2856 int i, last_entry_off=0;
2857 bool finished = False;
2858 bool dont_descend = False;
2859 bool out_of_space = False;
2860 int space_remaining;
2861 struct ea_list *ea_list = NULL;
2862 NTSTATUS ntstatus = NT_STATUS_OK;
2863 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2864 TALLOC_CTX *ctx = talloc_tos();
2865 struct dptr_struct *dirptr;
2866 struct smbd_server_connection *sconn = req->sconn;
2867 bool backup_priv = false;
2868 bool as_root = false;
2870 if (total_params < 13) {
2871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2872 return;
2875 dptr_num = SVAL(params,0);
2876 maxentries = SVAL(params,2);
2877 info_level = SVAL(params,4);
2878 resume_key = IVAL(params,6);
2879 findnext_flags = SVAL(params,10);
2880 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2881 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2882 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2883 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2885 if (!continue_bit) {
2886 /* We only need resume_name if continue_bit is zero. */
2887 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2888 params+12,
2889 total_params - 12, STR_TERMINATE, &ntstatus,
2890 &mask_contains_wcard);
2891 if (!NT_STATUS_IS_OK(ntstatus)) {
2892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2893 complain (it thinks we're asking for the directory above the shared
2894 path or an invalid name). Catch this as the resume name is only compared, never used in
2895 a file access. JRA. */
2896 srvstr_pull_talloc(ctx, params, req->flags2,
2897 &resume_name, params+12,
2898 total_params - 12,
2899 STR_TERMINATE);
2901 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2902 reply_nterror(req, ntstatus);
2903 return;
2908 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2909 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2910 resume_key = %d resume name = %s continue=%d level = %d\n",
2911 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2912 requires_resume_key, resume_key,
2913 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2915 if (!maxentries) {
2916 /* W2K3 seems to treat zero as 1. */
2917 maxentries = 1;
2920 switch (info_level) {
2921 case SMB_FIND_INFO_STANDARD:
2922 case SMB_FIND_EA_SIZE:
2923 case SMB_FIND_EA_LIST:
2924 case SMB_FIND_FILE_DIRECTORY_INFO:
2925 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2926 case SMB_FIND_FILE_NAMES_INFO:
2927 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2929 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2930 break;
2931 case SMB_FIND_FILE_UNIX:
2932 case SMB_FIND_FILE_UNIX_INFO2:
2933 /* Always use filesystem for UNIX mtime query. */
2934 ask_sharemode = false;
2935 if (!lp_unix_extensions()) {
2936 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2937 return;
2939 break;
2940 default:
2941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2942 return;
2945 if (info_level == SMB_FIND_EA_LIST) {
2946 uint32_t ea_size;
2948 if (total_data < 4) {
2949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2950 return;
2953 ea_size = IVAL(pdata,0);
2954 if (ea_size != total_data) {
2955 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2956 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2958 return;
2961 if (!lp_ea_support(SNUM(conn))) {
2962 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2963 return;
2966 /* Pull out the list of names. */
2967 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2968 if (!ea_list) {
2969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2970 return;
2974 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2976 return;
2979 *ppdata = (char *)SMB_REALLOC(
2980 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2981 if(*ppdata == NULL) {
2982 reply_nterror(req, NT_STATUS_NO_MEMORY);
2983 return;
2986 pdata = *ppdata;
2987 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2989 /* Realloc the params space */
2990 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2991 if(*pparams == NULL ) {
2992 reply_nterror(req, NT_STATUS_NO_MEMORY);
2993 return;
2996 params = *pparams;
2998 /* Check that the dptr is valid */
2999 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3000 reply_nterror(req, STATUS_NO_MORE_FILES);
3001 return;
3004 directory = dptr_path(sconn, dptr_num);
3006 /* Get the wildcard mask from the dptr */
3007 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3008 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3009 reply_nterror(req, STATUS_NO_MORE_FILES);
3010 return;
3013 /* Get the attr mask from the dptr */
3014 dirtype = dptr_attr(sconn, dptr_num);
3016 backup_priv = dptr_get_priv(dirptr);
3018 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3019 "backup_priv = %d\n",
3020 dptr_num, mask, dirtype,
3021 (long)dirptr,
3022 dptr_TellDir(dirptr),
3023 (int)backup_priv));
3025 /* Initialize per TRANS2_FIND_NEXT operation data */
3026 dptr_init_search_op(dirptr);
3028 /* We don't need to check for VOL here as this is returned by
3029 a different TRANS2 call. */
3031 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3032 directory,lp_dont_descend(ctx, SNUM(conn))));
3033 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3034 dont_descend = True;
3036 p = pdata;
3037 space_remaining = max_data_bytes;
3038 out_of_space = False;
3040 if (backup_priv) {
3041 become_root();
3042 as_root = true;
3046 * Seek to the correct position. We no longer use the resume key but
3047 * depend on the last file name instead.
3050 if(!continue_bit && resume_name && *resume_name) {
3051 SMB_STRUCT_STAT st;
3053 long current_pos = 0;
3055 * Remember, name_to_8_3 is called by
3056 * get_lanman2_dir_entry(), so the resume name
3057 * could be mangled. Ensure we check the unmangled name.
3060 if (mangle_is_mangled(resume_name, conn->params)) {
3061 char *new_resume_name = NULL;
3062 mangle_lookup_name_from_8_3(ctx,
3063 resume_name,
3064 &new_resume_name,
3065 conn->params);
3066 if (new_resume_name) {
3067 resume_name = new_resume_name;
3072 * Fix for NT redirector problem triggered by resume key indexes
3073 * changing between directory scans. We now return a resume key of 0
3074 * and instead look for the filename to continue from (also given
3075 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3076 * findfirst/findnext (as is usual) then the directory pointer
3077 * should already be at the correct place.
3080 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3081 } /* end if resume_name && !continue_bit */
3083 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3084 bool got_exact_match = False;
3086 /* this is a heuristic to avoid seeking the dirptr except when
3087 absolutely necessary. It allows for a filename of about 40 chars */
3088 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3089 out_of_space = True;
3090 finished = False;
3091 } else {
3092 ntstatus = get_lanman2_dir_entry(ctx,
3093 conn,
3094 dirptr,
3095 req->flags2,
3096 mask,dirtype,info_level,
3097 requires_resume_key,dont_descend,
3098 ask_sharemode,
3099 &p,pdata,data_end,
3100 space_remaining,
3101 &got_exact_match,
3102 &last_entry_off, ea_list);
3103 if (NT_STATUS_EQUAL(ntstatus,
3104 NT_STATUS_ILLEGAL_CHARACTER)) {
3106 * Bad character conversion on name. Ignore this
3107 * entry.
3109 continue;
3111 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3112 out_of_space = true;
3113 } else {
3114 finished = !NT_STATUS_IS_OK(ntstatus);
3118 if (!finished && !out_of_space)
3119 numentries++;
3122 * As an optimisation if we know we aren't looking
3123 * for a wildcard name (ie. the name matches the wildcard exactly)
3124 * then we can finish on any (first) match.
3125 * This speeds up large directory searches. JRA.
3128 if(got_exact_match)
3129 finished = True;
3131 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3134 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3135 smb_fn_name(req->cmd),
3136 mask, directory, dirtype, numentries ) );
3138 /* Check if we can close the dirptr */
3139 if(close_after_request || (finished && close_if_end)) {
3140 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3141 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3144 if (as_root) {
3145 unbecome_root();
3148 /* Set up the return parameter block */
3149 SSVAL(params,0,numentries);
3150 SSVAL(params,2,finished);
3151 SSVAL(params,4,0); /* Never an EA error */
3152 SSVAL(params,6,last_entry_off);
3154 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3155 max_data_bytes);
3157 return;
3160 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3162 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3163 return objid;
3166 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3168 SMB_ASSERT(extended_info != NULL);
3170 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3171 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3172 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3173 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3174 #ifdef SAMBA_VERSION_REVISION
3175 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3176 #endif
3177 extended_info->samba_subversion = 0;
3178 #ifdef SAMBA_VERSION_RC_RELEASE
3179 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3180 #else
3181 #ifdef SAMBA_VERSION_PRE_RELEASE
3182 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3183 #endif
3184 #endif
3185 #ifdef SAMBA_VERSION_VENDOR_PATCH
3186 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3187 #endif
3188 extended_info->samba_gitcommitdate = 0;
3189 #ifdef SAMBA_VERSION_COMMIT_TIME
3190 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3191 #endif
3193 memset(extended_info->samba_version_string, 0,
3194 sizeof(extended_info->samba_version_string));
3196 snprintf (extended_info->samba_version_string,
3197 sizeof(extended_info->samba_version_string),
3198 "%s", samba_version_string());
3201 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3202 connection_struct *conn,
3203 TALLOC_CTX *mem_ctx,
3204 uint16_t info_level,
3205 uint16_t flags2,
3206 unsigned int max_data_bytes,
3207 size_t *fixed_portion,
3208 struct smb_filename *fname,
3209 char **ppdata,
3210 int *ret_data_len)
3212 char *pdata, *end_data;
3213 int data_len = 0;
3214 size_t len = 0;
3215 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3216 int snum = SNUM(conn);
3217 const char *fstype = lp_fstype(SNUM(conn));
3218 const char *filename = NULL;
3219 const uint64_t bytes_per_sector = 512;
3220 uint32_t additional_flags = 0;
3221 struct smb_filename smb_fname;
3222 SMB_STRUCT_STAT st;
3223 NTSTATUS status = NT_STATUS_OK;
3224 uint64_t df_ret;
3226 if (fname == NULL || fname->base_name == NULL) {
3227 filename = ".";
3228 } else {
3229 filename = fname->base_name;
3232 if (IS_IPC(conn)) {
3233 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3234 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3235 "info level (0x%x) on IPC$.\n",
3236 (unsigned int)info_level));
3237 return NT_STATUS_ACCESS_DENIED;
3241 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3243 ZERO_STRUCT(smb_fname);
3244 smb_fname.base_name = discard_const_p(char, filename);
3246 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3247 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3248 return map_nt_error_from_unix(errno);
3251 st = smb_fname.st;
3253 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3254 return NT_STATUS_INVALID_PARAMETER;
3257 *ppdata = (char *)SMB_REALLOC(
3258 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3259 if (*ppdata == NULL) {
3260 return NT_STATUS_NO_MEMORY;
3263 pdata = *ppdata;
3264 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3265 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3267 *fixed_portion = 0;
3269 switch (info_level) {
3270 case SMB_INFO_ALLOCATION:
3272 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3273 data_len = 18;
3274 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3275 &dsize);
3276 if (df_ret == (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno);
3280 block_size = lp_block_size(snum);
3281 if (bsize < block_size) {
3282 uint64_t factor = block_size/bsize;
3283 bsize = block_size;
3284 dsize /= factor;
3285 dfree /= factor;
3287 if (bsize > block_size) {
3288 uint64_t factor = bsize/block_size;
3289 bsize = block_size;
3290 dsize *= factor;
3291 dfree *= factor;
3293 sectors_per_unit = bsize/bytes_per_sector;
3295 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3296 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3297 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3299 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3300 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3301 SIVAL(pdata,l1_cUnit,dsize);
3302 SIVAL(pdata,l1_cUnitAvail,dfree);
3303 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3304 break;
3307 case SMB_INFO_VOLUME:
3308 /* Return volume name */
3310 * Add volume serial number - hash of a combination of
3311 * the called hostname and the service name.
3313 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3315 * Win2k3 and previous mess this up by sending a name length
3316 * one byte short. I believe only older clients (OS/2 Win9x) use
3317 * this call so try fixing this by adding a terminating null to
3318 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3320 status = srvstr_push(
3321 pdata, flags2,
3322 pdata+l2_vol_szVolLabel, vname,
3323 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3324 STR_NOALIGN|STR_TERMINATE, &len);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 return status;
3328 SCVAL(pdata,l2_vol_cch,len);
3329 data_len = l2_vol_szVolLabel + len;
3330 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3331 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3332 (unsigned)len, vname));
3333 break;
3335 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3336 case SMB_FS_ATTRIBUTE_INFORMATION:
3338 additional_flags = 0;
3339 #if defined(HAVE_SYS_QUOTAS)
3340 additional_flags |= FILE_VOLUME_QUOTAS;
3341 #endif
3343 if(lp_nt_acl_support(SNUM(conn))) {
3344 additional_flags |= FILE_PERSISTENT_ACLS;
3347 /* Capabilities are filled in at connection time through STATVFS call */
3348 additional_flags |= conn->fs_capabilities;
3349 additional_flags |= lp_parm_int(conn->params->service,
3350 "share", "fake_fscaps",
3353 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3354 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3355 additional_flags); /* FS ATTRIBUTES */
3357 SIVAL(pdata,4,255); /* Max filename component length */
3358 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3359 and will think we can't do long filenames */
3360 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3361 PTR_DIFF(end_data, pdata+12),
3362 STR_UNICODE, &len);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 return status;
3366 SIVAL(pdata,8,len);
3367 data_len = 12 + len;
3368 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3369 /* the client only requested a portion of the
3370 file system name */
3371 data_len = max_data_bytes;
3372 status = STATUS_BUFFER_OVERFLOW;
3374 *fixed_portion = 16;
3375 break;
3377 case SMB_QUERY_FS_LABEL_INFO:
3378 case SMB_FS_LABEL_INFORMATION:
3379 status = srvstr_push(pdata, flags2, pdata+4, vname,
3380 PTR_DIFF(end_data, pdata+4), 0, &len);
3381 if (!NT_STATUS_IS_OK(status)) {
3382 return status;
3384 data_len = 4 + len;
3385 SIVAL(pdata,0,len);
3386 break;
3388 case SMB_QUERY_FS_VOLUME_INFO:
3389 case SMB_FS_VOLUME_INFORMATION:
3392 * Add volume serial number - hash of a combination of
3393 * the called hostname and the service name.
3395 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3396 (str_checksum(get_local_machine_name())<<16));
3398 /* Max label len is 32 characters. */
3399 status = srvstr_push(pdata, flags2, pdata+18, vname,
3400 PTR_DIFF(end_data, pdata+18),
3401 STR_UNICODE, &len);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 return status;
3405 SIVAL(pdata,12,len);
3406 data_len = 18+len;
3408 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3409 (int)strlen(vname),vname,
3410 lp_servicename(talloc_tos(), snum)));
3411 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3412 /* the client only requested a portion of the
3413 volume label */
3414 data_len = max_data_bytes;
3415 status = STATUS_BUFFER_OVERFLOW;
3417 *fixed_portion = 24;
3418 break;
3420 case SMB_QUERY_FS_SIZE_INFO:
3421 case SMB_FS_SIZE_INFORMATION:
3423 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3424 data_len = 24;
3425 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3426 &dsize);
3427 if (df_ret == (uint64_t)-1) {
3428 return map_nt_error_from_unix(errno);
3430 block_size = lp_block_size(snum);
3431 if (bsize < block_size) {
3432 uint64_t factor = block_size/bsize;
3433 bsize = block_size;
3434 dsize /= factor;
3435 dfree /= factor;
3437 if (bsize > block_size) {
3438 uint64_t factor = bsize/block_size;
3439 bsize = block_size;
3440 dsize *= factor;
3441 dfree *= factor;
3443 sectors_per_unit = bsize/bytes_per_sector;
3444 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3446 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3447 SBIG_UINT(pdata,0,dsize);
3448 SBIG_UINT(pdata,8,dfree);
3449 SIVAL(pdata,16,sectors_per_unit);
3450 SIVAL(pdata,20,bytes_per_sector);
3451 *fixed_portion = 24;
3452 break;
3455 case SMB_FS_FULL_SIZE_INFORMATION:
3457 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3458 data_len = 32;
3459 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3460 &dsize);
3461 if (df_ret == (uint64_t)-1) {
3462 return map_nt_error_from_unix(errno);
3464 block_size = lp_block_size(snum);
3465 if (bsize < block_size) {
3466 uint64_t factor = block_size/bsize;
3467 bsize = block_size;
3468 dsize /= factor;
3469 dfree /= factor;
3471 if (bsize > block_size) {
3472 uint64_t factor = bsize/block_size;
3473 bsize = block_size;
3474 dsize *= factor;
3475 dfree *= factor;
3477 sectors_per_unit = bsize/bytes_per_sector;
3478 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3479 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3480 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3481 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3482 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3483 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3484 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3485 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3486 *fixed_portion = 32;
3487 break;
3490 case SMB_QUERY_FS_DEVICE_INFO:
3491 case SMB_FS_DEVICE_INFORMATION:
3493 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3495 if (!CAN_WRITE(conn)) {
3496 characteristics |= FILE_READ_ONLY_DEVICE;
3498 data_len = 8;
3499 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3500 SIVAL(pdata,4,characteristics);
3501 *fixed_portion = 8;
3502 break;
3505 #ifdef HAVE_SYS_QUOTAS
3506 case SMB_FS_QUOTA_INFORMATION:
3508 * what we have to send --metze:
3510 * Unknown1: 24 NULL bytes
3511 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3512 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3513 * Quota Flags: 2 byte :
3514 * Unknown3: 6 NULL bytes
3516 * 48 bytes total
3518 * details for Quota Flags:
3520 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3521 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3522 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3523 * 0x0001 Enable Quotas: enable quota for this fs
3527 /* we need to fake up a fsp here,
3528 * because its not send in this call
3530 files_struct fsp;
3531 SMB_NTQUOTA_STRUCT quotas;
3533 ZERO_STRUCT(fsp);
3534 ZERO_STRUCT(quotas);
3536 fsp.conn = conn;
3537 fsp.fnum = FNUM_FIELD_INVALID;
3539 /* access check */
3540 if (get_current_uid(conn) != 0) {
3541 DEBUG(0,("get_user_quota: access_denied "
3542 "service [%s] user [%s]\n",
3543 lp_servicename(talloc_tos(), SNUM(conn)),
3544 conn->session_info->unix_info->unix_name));
3545 return NT_STATUS_ACCESS_DENIED;
3548 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3549 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3550 return map_nt_error_from_unix(errno);
3553 data_len = 48;
3555 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3556 lp_servicename(talloc_tos(), SNUM(conn))));
3558 /* Unknown1 24 NULL bytes*/
3559 SBIG_UINT(pdata,0,(uint64_t)0);
3560 SBIG_UINT(pdata,8,(uint64_t)0);
3561 SBIG_UINT(pdata,16,(uint64_t)0);
3563 /* Default Soft Quota 8 bytes */
3564 SBIG_UINT(pdata,24,quotas.softlim);
3566 /* Default Hard Quota 8 bytes */
3567 SBIG_UINT(pdata,32,quotas.hardlim);
3569 /* Quota flag 2 bytes */
3570 SSVAL(pdata,40,quotas.qflags);
3572 /* Unknown3 6 NULL bytes */
3573 SSVAL(pdata,42,0);
3574 SIVAL(pdata,44,0);
3576 break;
3578 #endif /* HAVE_SYS_QUOTAS */
3579 case SMB_FS_OBJECTID_INFORMATION:
3581 unsigned char objid[16];
3582 struct smb_extended_info extended_info;
3583 memcpy(pdata,create_volume_objectid(conn, objid),16);
3584 samba_extended_info_version (&extended_info);
3585 SIVAL(pdata,16,extended_info.samba_magic);
3586 SIVAL(pdata,20,extended_info.samba_version);
3587 SIVAL(pdata,24,extended_info.samba_subversion);
3588 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3589 memcpy(pdata+36,extended_info.samba_version_string,28);
3590 data_len = 64;
3591 break;
3594 case SMB_FS_SECTOR_SIZE_INFORMATION:
3596 data_len = 28;
3598 * These values match a physical Windows Server 2012
3599 * share backed by NTFS atop spinning rust.
3601 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3602 /* logical_bytes_per_sector */
3603 SIVAL(pdata, 0, bytes_per_sector);
3604 /* phys_bytes_per_sector_atomic */
3605 SIVAL(pdata, 4, bytes_per_sector);
3606 /* phys_bytes_per_sector_perf */
3607 SIVAL(pdata, 8, bytes_per_sector);
3608 /* fs_effective_phys_bytes_per_sector_atomic */
3609 SIVAL(pdata, 12, bytes_per_sector);
3610 /* flags */
3611 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3612 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3613 /* byte_off_sector_align */
3614 SIVAL(pdata, 20, 0);
3615 /* byte_off_partition_align */
3616 SIVAL(pdata, 24, 0);
3617 *fixed_portion = 28;
3618 break;
3623 * Query the version and capabilities of the CIFS UNIX extensions
3624 * in use.
3627 case SMB_QUERY_CIFS_UNIX_INFO:
3629 bool large_write = lp_min_receive_file_size() &&
3630 !srv_is_signing_active(xconn);
3631 bool large_read = !srv_is_signing_active(xconn);
3632 int encrypt_caps = 0;
3634 if (!lp_unix_extensions()) {
3635 return NT_STATUS_INVALID_LEVEL;
3638 switch (conn->encrypt_level) {
3639 case SMB_SIGNING_OFF:
3640 encrypt_caps = 0;
3641 break;
3642 case SMB_SIGNING_DESIRED:
3643 case SMB_SIGNING_IF_REQUIRED:
3644 case SMB_SIGNING_DEFAULT:
3645 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3646 break;
3647 case SMB_SIGNING_REQUIRED:
3648 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3649 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3650 large_write = false;
3651 large_read = false;
3652 break;
3655 data_len = 12;
3656 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3657 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3659 /* We have POSIX ACLs, pathname, encryption,
3660 * large read/write, and locking capability. */
3662 SBIG_UINT(pdata,4,((uint64_t)(
3663 CIFS_UNIX_POSIX_ACLS_CAP|
3664 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3665 CIFS_UNIX_FCNTL_LOCKS_CAP|
3666 CIFS_UNIX_EXTATTR_CAP|
3667 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3668 encrypt_caps|
3669 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3670 (large_write ?
3671 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3672 break;
3675 case SMB_QUERY_POSIX_FS_INFO:
3677 int rc;
3678 vfs_statvfs_struct svfs;
3680 if (!lp_unix_extensions()) {
3681 return NT_STATUS_INVALID_LEVEL;
3684 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3686 if (!rc) {
3687 data_len = 56;
3688 SIVAL(pdata,0,svfs.OptimalTransferSize);
3689 SIVAL(pdata,4,svfs.BlockSize);
3690 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3691 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3692 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3693 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3694 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3695 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3696 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3697 #ifdef EOPNOTSUPP
3698 } else if (rc == EOPNOTSUPP) {
3699 return NT_STATUS_INVALID_LEVEL;
3700 #endif /* EOPNOTSUPP */
3701 } else {
3702 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3703 return NT_STATUS_DOS(ERRSRV, ERRerror);
3705 break;
3708 case SMB_QUERY_POSIX_WHOAMI:
3710 uint32_t flags = 0;
3711 uint32_t sid_bytes;
3712 int i;
3714 if (!lp_unix_extensions()) {
3715 return NT_STATUS_INVALID_LEVEL;
3718 if (max_data_bytes < 40) {
3719 return NT_STATUS_BUFFER_TOO_SMALL;
3722 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3723 flags |= SMB_WHOAMI_GUEST;
3726 /* NOTE: 8 bytes for UID/GID, irrespective of native
3727 * platform size. This matches
3728 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3730 data_len = 4 /* flags */
3731 + 4 /* flag mask */
3732 + 8 /* uid */
3733 + 8 /* gid */
3734 + 4 /* ngroups */
3735 + 4 /* num_sids */
3736 + 4 /* SID bytes */
3737 + 4 /* pad/reserved */
3738 + (conn->session_info->unix_token->ngroups * 8)
3739 /* groups list */
3740 + (conn->session_info->security_token->num_sids *
3741 SID_MAX_SIZE)
3742 /* SID list */;
3744 SIVAL(pdata, 0, flags);
3745 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3746 SBIG_UINT(pdata, 8,
3747 (uint64_t)conn->session_info->unix_token->uid);
3748 SBIG_UINT(pdata, 16,
3749 (uint64_t)conn->session_info->unix_token->gid);
3752 if (data_len >= max_data_bytes) {
3753 /* Potential overflow, skip the GIDs and SIDs. */
3755 SIVAL(pdata, 24, 0); /* num_groups */
3756 SIVAL(pdata, 28, 0); /* num_sids */
3757 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3758 SIVAL(pdata, 36, 0); /* reserved */
3760 data_len = 40;
3761 break;
3764 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3765 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3767 /* We walk the SID list twice, but this call is fairly
3768 * infrequent, and I don't expect that it's performance
3769 * sensitive -- jpeach
3771 for (i = 0, sid_bytes = 0;
3772 i < conn->session_info->security_token->num_sids; ++i) {
3773 sid_bytes += ndr_size_dom_sid(
3774 &conn->session_info->security_token->sids[i],
3778 /* SID list byte count */
3779 SIVAL(pdata, 32, sid_bytes);
3781 /* 4 bytes pad/reserved - must be zero */
3782 SIVAL(pdata, 36, 0);
3783 data_len = 40;
3785 /* GID list */
3786 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3787 SBIG_UINT(pdata, data_len,
3788 (uint64_t)conn->session_info->unix_token->groups[i]);
3789 data_len += 8;
3792 /* SID list */
3793 for (i = 0;
3794 i < conn->session_info->security_token->num_sids; ++i) {
3795 int sid_len = ndr_size_dom_sid(
3796 &conn->session_info->security_token->sids[i],
3799 sid_linearize(pdata + data_len, sid_len,
3800 &conn->session_info->security_token->sids[i]);
3801 data_len += sid_len;
3804 break;
3807 case SMB_MAC_QUERY_FS_INFO:
3809 * Thursby MAC extension... ONLY on NTFS filesystems
3810 * once we do streams then we don't need this
3812 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3813 data_len = 88;
3814 SIVAL(pdata,84,0x100); /* Don't support mac... */
3815 break;
3817 /* drop through */
3818 default:
3819 return NT_STATUS_INVALID_LEVEL;
3822 *ret_data_len = data_len;
3823 return status;
3826 /****************************************************************************
3827 Reply to a TRANS2_QFSINFO (query filesystem info).
3828 ****************************************************************************/
3830 static void call_trans2qfsinfo(connection_struct *conn,
3831 struct smb_request *req,
3832 char **pparams, int total_params,
3833 char **ppdata, int total_data,
3834 unsigned int max_data_bytes)
3836 char *params = *pparams;
3837 uint16_t info_level;
3838 int data_len = 0;
3839 size_t fixed_portion;
3840 NTSTATUS status;
3842 if (total_params < 2) {
3843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3844 return;
3847 info_level = SVAL(params,0);
3849 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3850 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3851 DEBUG(0,("call_trans2qfsinfo: encryption required "
3852 "and info level 0x%x sent.\n",
3853 (unsigned int)info_level));
3854 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3855 return;
3859 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3861 status = smbd_do_qfsinfo(req->xconn, conn, req,
3862 info_level,
3863 req->flags2,
3864 max_data_bytes,
3865 &fixed_portion,
3866 NULL,
3867 ppdata, &data_len);
3868 if (!NT_STATUS_IS_OK(status)) {
3869 reply_nterror(req, status);
3870 return;
3873 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3874 max_data_bytes);
3876 DEBUG( 4, ( "%s info_level = %d\n",
3877 smb_fn_name(req->cmd), info_level) );
3879 return;
3882 /****************************************************************************
3883 Reply to a TRANS2_SETFSINFO (set filesystem info).
3884 ****************************************************************************/
3886 static void call_trans2setfsinfo(connection_struct *conn,
3887 struct smb_request *req,
3888 char **pparams, int total_params,
3889 char **ppdata, int total_data,
3890 unsigned int max_data_bytes)
3892 struct smbXsrv_connection *xconn = req->xconn;
3893 char *pdata = *ppdata;
3894 char *params = *pparams;
3895 uint16_t info_level;
3897 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3898 lp_servicename(talloc_tos(), SNUM(conn))));
3900 /* */
3901 if (total_params < 4) {
3902 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3903 total_params));
3904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3905 return;
3908 info_level = SVAL(params,2);
3910 if (IS_IPC(conn)) {
3911 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3912 info_level != SMB_SET_CIFS_UNIX_INFO) {
3913 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3914 "info level (0x%x) on IPC$.\n",
3915 (unsigned int)info_level));
3916 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3917 return;
3921 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3922 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3923 DEBUG(0,("call_trans2setfsinfo: encryption required "
3924 "and info level 0x%x sent.\n",
3925 (unsigned int)info_level));
3926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3927 return;
3931 switch(info_level) {
3932 case SMB_SET_CIFS_UNIX_INFO:
3933 if (!lp_unix_extensions()) {
3934 DEBUG(2,("call_trans2setfsinfo: "
3935 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3936 "unix extensions off\n"));
3937 reply_nterror(req,
3938 NT_STATUS_INVALID_LEVEL);
3939 return;
3942 /* There should be 12 bytes of capabilities set. */
3943 if (total_data < 12) {
3944 reply_nterror(
3945 req,
3946 NT_STATUS_INVALID_PARAMETER);
3947 return;
3949 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3950 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3951 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3952 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3953 /* Just print these values for now. */
3954 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3955 "major = %u, minor = %u cap_low = 0x%x, "
3956 "cap_high = 0x%xn",
3957 (unsigned int)xconn->
3958 smb1.unix_info.client_major,
3959 (unsigned int)xconn->
3960 smb1.unix_info.client_minor,
3961 (unsigned int)xconn->
3962 smb1.unix_info.client_cap_low,
3963 (unsigned int)xconn->
3964 smb1.unix_info.client_cap_high));
3966 /* Here is where we must switch to posix pathname processing... */
3967 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3968 lp_set_posix_pathnames();
3969 mangle_change_to_posix();
3972 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3973 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3974 /* Client that knows how to do posix locks,
3975 * but not posix open/mkdir operations. Set a
3976 * default type for read/write checks. */
3978 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3981 break;
3983 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3985 NTSTATUS status;
3986 size_t param_len = 0;
3987 size_t data_len = total_data;
3989 if (!lp_unix_extensions()) {
3990 reply_nterror(
3991 req,
3992 NT_STATUS_INVALID_LEVEL);
3993 return;
3996 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3997 reply_nterror(
3998 req,
3999 NT_STATUS_NOT_SUPPORTED);
4000 return;
4003 if (xconn->smb1.echo_handler.trusted_fde) {
4004 DEBUG( 2,("call_trans2setfsinfo: "
4005 "request transport encryption disabled"
4006 "with 'fork echo handler = yes'\n"));
4007 reply_nterror(
4008 req,
4009 NT_STATUS_NOT_SUPPORTED);
4010 return;
4013 DEBUG( 4,("call_trans2setfsinfo: "
4014 "request transport encryption.\n"));
4016 status = srv_request_encryption_setup(conn,
4017 (unsigned char **)ppdata,
4018 &data_len,
4019 (unsigned char **)pparams,
4020 &param_len);
4022 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4023 !NT_STATUS_IS_OK(status)) {
4024 reply_nterror(req, status);
4025 return;
4028 send_trans2_replies(conn, req,
4029 NT_STATUS_OK,
4030 *pparams,
4031 param_len,
4032 *ppdata,
4033 data_len,
4034 max_data_bytes);
4036 if (NT_STATUS_IS_OK(status)) {
4037 /* Server-side transport
4038 * encryption is now *on*. */
4039 status = srv_encryption_start(conn);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 char *reason = talloc_asprintf(talloc_tos(),
4042 "Failure in setting "
4043 "up encrypted transport: %s",
4044 nt_errstr(status));
4045 exit_server_cleanly(reason);
4048 return;
4051 case SMB_FS_QUOTA_INFORMATION:
4053 files_struct *fsp = NULL;
4054 SMB_NTQUOTA_STRUCT quotas;
4056 ZERO_STRUCT(quotas);
4058 /* access check */
4059 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4060 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4061 lp_servicename(talloc_tos(), SNUM(conn)),
4062 conn->session_info->unix_info->unix_name));
4063 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4064 return;
4067 /* note: normally there're 48 bytes,
4068 * but we didn't use the last 6 bytes for now
4069 * --metze
4071 fsp = file_fsp(req, SVAL(params,0));
4073 if (!check_fsp_ntquota_handle(conn, req,
4074 fsp)) {
4075 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4076 reply_nterror(
4077 req, NT_STATUS_INVALID_HANDLE);
4078 return;
4081 if (total_data < 42) {
4082 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4083 total_data));
4084 reply_nterror(
4085 req,
4086 NT_STATUS_INVALID_PARAMETER);
4087 return;
4090 /* unknown_1 24 NULL bytes in pdata*/
4092 /* the soft quotas 8 bytes (uint64_t)*/
4093 quotas.softlim = BVAL(pdata,24);
4095 /* the hard quotas 8 bytes (uint64_t)*/
4096 quotas.hardlim = BVAL(pdata,32);
4098 /* quota_flags 2 bytes **/
4099 quotas.qflags = SVAL(pdata,40);
4101 /* unknown_2 6 NULL bytes follow*/
4103 /* now set the quotas */
4104 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4105 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4106 reply_nterror(req, map_nt_error_from_unix(errno));
4107 return;
4110 break;
4112 default:
4113 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4114 info_level));
4115 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4116 return;
4117 break;
4121 * sending this reply works fine,
4122 * but I'm not sure it's the same
4123 * like windows do...
4124 * --metze
4126 reply_outbuf(req, 10, 0);
4129 #if defined(HAVE_POSIX_ACLS)
4130 /****************************************************************************
4131 Utility function to count the number of entries in a POSIX acl.
4132 ****************************************************************************/
4134 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4136 unsigned int ace_count = 0;
4137 int entry_id = SMB_ACL_FIRST_ENTRY;
4138 SMB_ACL_ENTRY_T entry;
4140 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4141 /* get_next... */
4142 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4143 entry_id = SMB_ACL_NEXT_ENTRY;
4145 ace_count++;
4147 return ace_count;
4150 /****************************************************************************
4151 Utility function to marshall a POSIX acl into wire format.
4152 ****************************************************************************/
4154 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4156 int entry_id = SMB_ACL_FIRST_ENTRY;
4157 SMB_ACL_ENTRY_T entry;
4159 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4160 SMB_ACL_TAG_T tagtype;
4161 SMB_ACL_PERMSET_T permset;
4162 unsigned char perms = 0;
4163 unsigned int own_grp;
4165 /* get_next... */
4166 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4167 entry_id = SMB_ACL_NEXT_ENTRY;
4170 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4171 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4172 return False;
4175 if (sys_acl_get_permset(entry, &permset) == -1) {
4176 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4177 return False;
4180 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4181 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4182 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4184 SCVAL(pdata,1,perms);
4186 switch (tagtype) {
4187 case SMB_ACL_USER_OBJ:
4188 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4189 own_grp = (unsigned int)pst->st_ex_uid;
4190 SIVAL(pdata,2,own_grp);
4191 SIVAL(pdata,6,0);
4192 break;
4193 case SMB_ACL_USER:
4195 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4196 if (!puid) {
4197 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4198 return False;
4200 own_grp = (unsigned int)*puid;
4201 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4202 SIVAL(pdata,2,own_grp);
4203 SIVAL(pdata,6,0);
4204 break;
4206 case SMB_ACL_GROUP_OBJ:
4207 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4208 own_grp = (unsigned int)pst->st_ex_gid;
4209 SIVAL(pdata,2,own_grp);
4210 SIVAL(pdata,6,0);
4211 break;
4212 case SMB_ACL_GROUP:
4214 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4215 if (!pgid) {
4216 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4217 return False;
4219 own_grp = (unsigned int)*pgid;
4220 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4221 SIVAL(pdata,2,own_grp);
4222 SIVAL(pdata,6,0);
4223 break;
4225 case SMB_ACL_MASK:
4226 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4227 SIVAL(pdata,2,0xFFFFFFFF);
4228 SIVAL(pdata,6,0xFFFFFFFF);
4229 break;
4230 case SMB_ACL_OTHER:
4231 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4232 SIVAL(pdata,2,0xFFFFFFFF);
4233 SIVAL(pdata,6,0xFFFFFFFF);
4234 break;
4235 default:
4236 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4237 return False;
4239 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4242 return True;
4244 #endif
4246 /****************************************************************************
4247 Store the FILE_UNIX_BASIC info.
4248 ****************************************************************************/
4250 static char *store_file_unix_basic(connection_struct *conn,
4251 char *pdata,
4252 files_struct *fsp,
4253 const SMB_STRUCT_STAT *psbuf)
4255 uint64_t file_index = get_FileIndex(conn, psbuf);
4256 dev_t devno;
4258 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4259 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4261 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4262 pdata += 8;
4264 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4265 pdata += 8;
4267 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4268 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4269 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4270 pdata += 24;
4272 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4273 SIVAL(pdata,4,0);
4274 pdata += 8;
4276 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4277 SIVAL(pdata,4,0);
4278 pdata += 8;
4280 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4281 pdata += 4;
4283 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4284 devno = psbuf->st_ex_rdev;
4285 } else {
4286 devno = psbuf->st_ex_dev;
4289 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4290 SIVAL(pdata,4,0);
4291 pdata += 8;
4293 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4294 SIVAL(pdata,4,0);
4295 pdata += 8;
4297 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4298 pdata += 8;
4300 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4301 SIVAL(pdata,4,0);
4302 pdata += 8;
4304 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4305 SIVAL(pdata,4,0);
4306 pdata += 8;
4308 return pdata;
4311 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4312 * the chflags(2) (or equivalent) flags.
4314 * XXX: this really should be behind the VFS interface. To do this, we would
4315 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4316 * Each VFS module could then implement its own mapping as appropriate for the
4317 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4319 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4320 info2_flags_map[] =
4322 #ifdef UF_NODUMP
4323 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4324 #endif
4326 #ifdef UF_IMMUTABLE
4327 { UF_IMMUTABLE, EXT_IMMUTABLE },
4328 #endif
4330 #ifdef UF_APPEND
4331 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4332 #endif
4334 #ifdef UF_HIDDEN
4335 { UF_HIDDEN, EXT_HIDDEN },
4336 #endif
4338 /* Do not remove. We need to guarantee that this array has at least one
4339 * entry to build on HP-UX.
4341 { 0, 0 }
4345 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4346 uint32_t *smb_fflags, uint32_t *smb_fmask)
4348 int i;
4350 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4351 *smb_fmask |= info2_flags_map[i].smb_fflag;
4352 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4353 *smb_fflags |= info2_flags_map[i].smb_fflag;
4358 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4359 const uint32_t smb_fflags,
4360 const uint32_t smb_fmask,
4361 int *stat_fflags)
4363 uint32_t max_fmask = 0;
4364 int i;
4366 *stat_fflags = psbuf->st_ex_flags;
4368 /* For each flags requested in smb_fmask, check the state of the
4369 * corresponding flag in smb_fflags and set or clear the matching
4370 * stat flag.
4373 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4374 max_fmask |= info2_flags_map[i].smb_fflag;
4375 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4376 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4377 *stat_fflags |= info2_flags_map[i].stat_fflag;
4378 } else {
4379 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4384 /* If smb_fmask is asking to set any bits that are not supported by
4385 * our flag mappings, we should fail.
4387 if ((smb_fmask & max_fmask) != smb_fmask) {
4388 return False;
4391 return True;
4395 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4396 * of file flags and birth (create) time.
4398 static char *store_file_unix_basic_info2(connection_struct *conn,
4399 char *pdata,
4400 files_struct *fsp,
4401 const SMB_STRUCT_STAT *psbuf)
4403 uint32_t file_flags = 0;
4404 uint32_t flags_mask = 0;
4406 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4408 /* Create (birth) time 64 bit */
4409 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4410 pdata += 8;
4412 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4413 SIVAL(pdata, 0, file_flags); /* flags */
4414 SIVAL(pdata, 4, flags_mask); /* mask */
4415 pdata += 8;
4417 return pdata;
4420 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4421 const struct stream_struct *streams,
4422 char *data,
4423 unsigned int max_data_bytes,
4424 unsigned int *data_size)
4426 unsigned int i;
4427 unsigned int ofs = 0;
4429 if (max_data_bytes < 32) {
4430 return NT_STATUS_INFO_LENGTH_MISMATCH;
4433 for (i = 0; i < num_streams; i++) {
4434 unsigned int next_offset;
4435 size_t namelen;
4436 smb_ucs2_t *namebuf;
4438 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4439 streams[i].name, &namelen) ||
4440 namelen <= 2)
4442 return NT_STATUS_INVALID_PARAMETER;
4446 * name_buf is now null-terminated, we need to marshall as not
4447 * terminated
4450 namelen -= 2;
4453 * We cannot overflow ...
4455 if ((ofs + 24 + namelen) > max_data_bytes) {
4456 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4457 i));
4458 TALLOC_FREE(namebuf);
4459 return STATUS_BUFFER_OVERFLOW;
4462 SIVAL(data, ofs+4, namelen);
4463 SOFF_T(data, ofs+8, streams[i].size);
4464 SOFF_T(data, ofs+16, streams[i].alloc_size);
4465 memcpy(data+ofs+24, namebuf, namelen);
4466 TALLOC_FREE(namebuf);
4468 next_offset = ofs + 24 + namelen;
4470 if (i == num_streams-1) {
4471 SIVAL(data, ofs, 0);
4473 else {
4474 unsigned int align = ndr_align_size(next_offset, 8);
4476 if ((next_offset + align) > max_data_bytes) {
4477 DEBUG(10, ("refusing to overflow align "
4478 "reply at stream %u\n",
4479 i));
4480 TALLOC_FREE(namebuf);
4481 return STATUS_BUFFER_OVERFLOW;
4484 memset(data+next_offset, 0, align);
4485 next_offset += align;
4487 SIVAL(data, ofs, next_offset - ofs);
4488 ofs = next_offset;
4491 ofs = next_offset;
4494 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4496 *data_size = ofs;
4498 return NT_STATUS_OK;
4501 /****************************************************************************
4502 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4503 ****************************************************************************/
4505 static void call_trans2qpipeinfo(connection_struct *conn,
4506 struct smb_request *req,
4507 unsigned int tran_call,
4508 char **pparams, int total_params,
4509 char **ppdata, int total_data,
4510 unsigned int max_data_bytes)
4512 char *params = *pparams;
4513 char *pdata = *ppdata;
4514 unsigned int data_size = 0;
4515 unsigned int param_size = 2;
4516 uint16_t info_level;
4517 files_struct *fsp;
4519 if (!params) {
4520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521 return;
4524 if (total_params < 4) {
4525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4526 return;
4529 fsp = file_fsp(req, SVAL(params,0));
4530 if (!fsp_is_np(fsp)) {
4531 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4532 return;
4535 info_level = SVAL(params,2);
4537 *pparams = (char *)SMB_REALLOC(*pparams,2);
4538 if (*pparams == NULL) {
4539 reply_nterror(req, NT_STATUS_NO_MEMORY);
4540 return;
4542 params = *pparams;
4543 SSVAL(params,0,0);
4544 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 return;
4548 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4549 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4550 if (*ppdata == NULL ) {
4551 reply_nterror(req, NT_STATUS_NO_MEMORY);
4552 return;
4554 pdata = *ppdata;
4556 switch (info_level) {
4557 case SMB_FILE_STANDARD_INFORMATION:
4558 memset(pdata,0,24);
4559 SOFF_T(pdata,0,4096LL);
4560 SIVAL(pdata,16,1);
4561 SIVAL(pdata,20,1);
4562 data_size = 24;
4563 break;
4565 default:
4566 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4567 return;
4570 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4571 max_data_bytes);
4573 return;
4576 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4577 TALLOC_CTX *mem_ctx,
4578 uint16_t info_level,
4579 files_struct *fsp,
4580 struct smb_filename *smb_fname,
4581 bool delete_pending,
4582 struct timespec write_time_ts,
4583 struct ea_list *ea_list,
4584 int lock_data_count,
4585 char *lock_data,
4586 uint16_t flags2,
4587 unsigned int max_data_bytes,
4588 size_t *fixed_portion,
4589 char **ppdata,
4590 unsigned int *pdata_size)
4592 char *pdata = *ppdata;
4593 char *dstart, *dend;
4594 unsigned int data_size;
4595 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4596 time_t create_time, mtime, atime, c_time;
4597 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4598 char *p;
4599 char *base_name;
4600 char *dos_fname;
4601 int mode;
4602 int nlink;
4603 NTSTATUS status;
4604 uint64_t file_size = 0;
4605 uint64_t pos = 0;
4606 uint64_t allocation_size = 0;
4607 uint64_t file_index = 0;
4608 uint32_t access_mask = 0;
4609 size_t len = 0;
4611 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4612 return NT_STATUS_INVALID_LEVEL;
4615 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4616 smb_fname_str_dbg(smb_fname),
4617 fsp_fnum_dbg(fsp),
4618 info_level, max_data_bytes));
4620 mode = dos_mode(conn, smb_fname);
4621 nlink = psbuf->st_ex_nlink;
4623 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4624 nlink = 1;
4627 if ((nlink > 0) && delete_pending) {
4628 nlink -= 1;
4631 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4632 return NT_STATUS_INVALID_PARAMETER;
4635 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4636 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4637 if (*ppdata == NULL) {
4638 return NT_STATUS_NO_MEMORY;
4640 pdata = *ppdata;
4641 dstart = pdata;
4642 dend = dstart + data_size - 1;
4644 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4645 update_stat_ex_mtime(psbuf, write_time_ts);
4648 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4649 mtime_ts = psbuf->st_ex_mtime;
4650 atime_ts = psbuf->st_ex_atime;
4651 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4653 if (lp_dos_filetime_resolution(SNUM(conn))) {
4654 dos_filetime_timespec(&create_time_ts);
4655 dos_filetime_timespec(&mtime_ts);
4656 dos_filetime_timespec(&atime_ts);
4657 dos_filetime_timespec(&ctime_ts);
4660 create_time = convert_timespec_to_time_t(create_time_ts);
4661 mtime = convert_timespec_to_time_t(mtime_ts);
4662 atime = convert_timespec_to_time_t(atime_ts);
4663 c_time = convert_timespec_to_time_t(ctime_ts);
4665 p = strrchr_m(smb_fname->base_name,'/');
4666 if (!p)
4667 base_name = smb_fname->base_name;
4668 else
4669 base_name = p+1;
4671 /* NT expects the name to be in an exact form of the *full*
4672 filename. See the trans2 torture test */
4673 if (ISDOT(base_name)) {
4674 dos_fname = talloc_strdup(mem_ctx, "\\");
4675 if (!dos_fname) {
4676 return NT_STATUS_NO_MEMORY;
4678 } else {
4679 dos_fname = talloc_asprintf(mem_ctx,
4680 "\\%s",
4681 smb_fname->base_name);
4682 if (!dos_fname) {
4683 return NT_STATUS_NO_MEMORY;
4685 if (is_ntfs_stream_smb_fname(smb_fname)) {
4686 dos_fname = talloc_asprintf(dos_fname, "%s",
4687 smb_fname->stream_name);
4688 if (!dos_fname) {
4689 return NT_STATUS_NO_MEMORY;
4693 string_replace(dos_fname, '/', '\\');
4696 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4698 if (!fsp) {
4699 /* Do we have this path open ? */
4700 files_struct *fsp1;
4701 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4702 fsp1 = file_find_di_first(conn->sconn, fileid);
4703 if (fsp1 && fsp1->initial_allocation_size) {
4704 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4708 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4709 file_size = get_file_size_stat(psbuf);
4712 if (fsp) {
4713 pos = fsp->fh->position_information;
4716 if (fsp) {
4717 access_mask = fsp->access_mask;
4718 } else {
4719 /* GENERIC_EXECUTE mapping from Windows */
4720 access_mask = 0x12019F;
4723 /* This should be an index number - looks like
4724 dev/ino to me :-)
4726 I think this causes us to fail the IFSKIT
4727 BasicFileInformationTest. -tpot */
4728 file_index = get_FileIndex(conn, psbuf);
4730 *fixed_portion = 0;
4732 switch (info_level) {
4733 case SMB_INFO_STANDARD:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4735 data_size = 22;
4736 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4737 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4738 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4739 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4740 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4741 SSVAL(pdata,l1_attrFile,mode);
4742 break;
4744 case SMB_INFO_QUERY_EA_SIZE:
4746 unsigned int ea_size =
4747 estimate_ea_size(conn, fsp,
4748 smb_fname);
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4750 data_size = 26;
4751 srv_put_dos_date2(pdata,0,create_time);
4752 srv_put_dos_date2(pdata,4,atime);
4753 srv_put_dos_date2(pdata,8,mtime); /* write time */
4754 SIVAL(pdata,12,(uint32_t)file_size);
4755 SIVAL(pdata,16,(uint32_t)allocation_size);
4756 SSVAL(pdata,20,mode);
4757 SIVAL(pdata,22,ea_size);
4758 break;
4761 case SMB_INFO_IS_NAME_VALID:
4762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4763 if (fsp) {
4764 /* os/2 needs this ? really ?*/
4765 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4767 /* This is only reached for qpathinfo */
4768 data_size = 0;
4769 break;
4771 case SMB_INFO_QUERY_EAS_FROM_LIST:
4773 size_t total_ea_len = 0;
4774 struct ea_list *ea_file_list = NULL;
4775 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4777 status =
4778 get_ea_list_from_file(mem_ctx, conn, fsp,
4779 smb_fname,
4780 &total_ea_len, &ea_file_list);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 return status;
4785 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4787 if (!ea_list || (total_ea_len > data_size)) {
4788 data_size = 4;
4789 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4790 break;
4793 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4794 break;
4797 case SMB_INFO_QUERY_ALL_EAS:
4799 /* We have data_size bytes to put EA's into. */
4800 size_t total_ea_len = 0;
4801 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4803 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4804 smb_fname,
4805 &total_ea_len, &ea_list);
4806 if (!NT_STATUS_IS_OK(status)) {
4807 return status;
4810 if (!ea_list || (total_ea_len > data_size)) {
4811 data_size = 4;
4812 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4813 break;
4816 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4817 break;
4820 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4822 /* This is FileFullEaInformation - 0xF which maps to
4823 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4825 /* We have data_size bytes to put EA's into. */
4826 size_t total_ea_len = 0;
4827 struct ea_list *ea_file_list = NULL;
4829 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4831 /*TODO: add filtering and index handling */
4833 status =
4834 get_ea_list_from_file(mem_ctx, conn, fsp,
4835 smb_fname,
4836 &total_ea_len, &ea_file_list);
4837 if (!NT_STATUS_IS_OK(status)) {
4838 return status;
4840 if (!ea_file_list) {
4841 return NT_STATUS_NO_EAS_ON_FILE;
4844 status = fill_ea_chained_buffer(mem_ctx,
4845 pdata,
4846 data_size,
4847 &data_size,
4848 conn, ea_file_list);
4849 if (!NT_STATUS_IS_OK(status)) {
4850 return status;
4852 break;
4855 case SMB_FILE_BASIC_INFORMATION:
4856 case SMB_QUERY_FILE_BASIC_INFO:
4858 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4859 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4860 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4861 } else {
4862 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4863 data_size = 40;
4864 SIVAL(pdata,36,0);
4866 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4867 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4868 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4869 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4870 SIVAL(pdata,32,mode);
4872 DEBUG(5,("SMB_QFBI - "));
4873 DEBUG(5,("create: %s ", ctime(&create_time)));
4874 DEBUG(5,("access: %s ", ctime(&atime)));
4875 DEBUG(5,("write: %s ", ctime(&mtime)));
4876 DEBUG(5,("change: %s ", ctime(&c_time)));
4877 DEBUG(5,("mode: %x\n", mode));
4878 *fixed_portion = data_size;
4879 break;
4881 case SMB_FILE_STANDARD_INFORMATION:
4882 case SMB_QUERY_FILE_STANDARD_INFO:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4885 data_size = 24;
4886 SOFF_T(pdata,0,allocation_size);
4887 SOFF_T(pdata,8,file_size);
4888 SIVAL(pdata,16,nlink);
4889 SCVAL(pdata,20,delete_pending?1:0);
4890 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4891 SSVAL(pdata,22,0); /* Padding. */
4892 *fixed_portion = 24;
4893 break;
4895 case SMB_FILE_EA_INFORMATION:
4896 case SMB_QUERY_FILE_EA_INFO:
4898 unsigned int ea_size =
4899 estimate_ea_size(conn, fsp, smb_fname);
4900 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4901 data_size = 4;
4902 *fixed_portion = 4;
4903 SIVAL(pdata,0,ea_size);
4904 break;
4907 /* Get the 8.3 name - used if NT SMB was negotiated. */
4908 case SMB_QUERY_FILE_ALT_NAME_INFO:
4909 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4911 char mangled_name[13];
4912 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4913 if (!name_to_8_3(base_name,mangled_name,
4914 True,conn->params)) {
4915 return NT_STATUS_NO_MEMORY;
4917 status = srvstr_push(dstart, flags2,
4918 pdata+4, mangled_name,
4919 PTR_DIFF(dend, pdata+4),
4920 STR_UNICODE, &len);
4921 if (!NT_STATUS_IS_OK(status)) {
4922 return status;
4924 data_size = 4 + len;
4925 SIVAL(pdata,0,len);
4926 *fixed_portion = 8;
4927 break;
4930 case SMB_QUERY_FILE_NAME_INFO:
4933 this must be *exactly* right for ACLs on mapped drives to work
4935 status = srvstr_push(dstart, flags2,
4936 pdata+4, dos_fname,
4937 PTR_DIFF(dend, pdata+4),
4938 STR_UNICODE, &len);
4939 if (!NT_STATUS_IS_OK(status)) {
4940 return status;
4942 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4943 data_size = 4 + len;
4944 SIVAL(pdata,0,len);
4945 break;
4948 case SMB_FILE_ALLOCATION_INFORMATION:
4949 case SMB_QUERY_FILE_ALLOCATION_INFO:
4950 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4951 data_size = 8;
4952 SOFF_T(pdata,0,allocation_size);
4953 break;
4955 case SMB_FILE_END_OF_FILE_INFORMATION:
4956 case SMB_QUERY_FILE_END_OF_FILEINFO:
4957 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4958 data_size = 8;
4959 SOFF_T(pdata,0,file_size);
4960 break;
4962 case SMB_QUERY_FILE_ALL_INFO:
4963 case SMB_FILE_ALL_INFORMATION:
4965 unsigned int ea_size =
4966 estimate_ea_size(conn, fsp, smb_fname);
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4968 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4969 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4970 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4971 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4972 SIVAL(pdata,32,mode);
4973 SIVAL(pdata,36,0); /* padding. */
4974 pdata += 40;
4975 SOFF_T(pdata,0,allocation_size);
4976 SOFF_T(pdata,8,file_size);
4977 SIVAL(pdata,16,nlink);
4978 SCVAL(pdata,20,delete_pending);
4979 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4980 SSVAL(pdata,22,0);
4981 pdata += 24;
4982 SIVAL(pdata,0,ea_size);
4983 pdata += 4; /* EA info */
4984 status = srvstr_push(dstart, flags2,
4985 pdata+4, dos_fname,
4986 PTR_DIFF(dend, pdata+4),
4987 STR_UNICODE, &len);
4988 if (!NT_STATUS_IS_OK(status)) {
4989 return status;
4991 SIVAL(pdata,0,len);
4992 pdata += 4 + len;
4993 data_size = PTR_DIFF(pdata,(*ppdata));
4994 *fixed_portion = 10;
4995 break;
4998 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5000 unsigned int ea_size =
5001 estimate_ea_size(conn, fsp, smb_fname);
5002 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5003 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5004 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5005 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5006 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5007 SIVAL(pdata, 0x20, mode);
5008 SIVAL(pdata, 0x24, 0); /* padding. */
5009 SBVAL(pdata, 0x28, allocation_size);
5010 SBVAL(pdata, 0x30, file_size);
5011 SIVAL(pdata, 0x38, nlink);
5012 SCVAL(pdata, 0x3C, delete_pending);
5013 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5014 SSVAL(pdata, 0x3E, 0); /* padding */
5015 SBVAL(pdata, 0x40, file_index);
5016 SIVAL(pdata, 0x48, ea_size);
5017 SIVAL(pdata, 0x4C, access_mask);
5018 SBVAL(pdata, 0x50, pos);
5019 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5020 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5022 pdata += 0x60;
5024 status = srvstr_push(dstart, flags2,
5025 pdata+4, dos_fname,
5026 PTR_DIFF(dend, pdata+4),
5027 STR_UNICODE, &len);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 return status;
5031 SIVAL(pdata,0,len);
5032 pdata += 4 + len;
5033 data_size = PTR_DIFF(pdata,(*ppdata));
5034 *fixed_portion = 104;
5035 break;
5037 case SMB_FILE_INTERNAL_INFORMATION:
5039 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5040 SBVAL(pdata, 0, file_index);
5041 data_size = 8;
5042 *fixed_portion = 8;
5043 break;
5045 case SMB_FILE_ACCESS_INFORMATION:
5046 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5047 SIVAL(pdata, 0, access_mask);
5048 data_size = 4;
5049 *fixed_portion = 4;
5050 break;
5052 case SMB_FILE_NAME_INFORMATION:
5053 /* Pathname with leading '\'. */
5055 size_t byte_len;
5056 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5058 SIVAL(pdata,0,byte_len);
5059 data_size = 4 + byte_len;
5060 break;
5063 case SMB_FILE_DISPOSITION_INFORMATION:
5064 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5065 data_size = 1;
5066 SCVAL(pdata,0,delete_pending);
5067 *fixed_portion = 1;
5068 break;
5070 case SMB_FILE_POSITION_INFORMATION:
5071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5072 data_size = 8;
5073 SOFF_T(pdata,0,pos);
5074 *fixed_portion = 8;
5075 break;
5077 case SMB_FILE_MODE_INFORMATION:
5078 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5079 SIVAL(pdata,0,mode);
5080 data_size = 4;
5081 *fixed_portion = 4;
5082 break;
5084 case SMB_FILE_ALIGNMENT_INFORMATION:
5085 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5086 SIVAL(pdata,0,0); /* No alignment needed. */
5087 data_size = 4;
5088 *fixed_portion = 4;
5089 break;
5092 * NT4 server just returns "invalid query" to this - if we try
5093 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5094 * want this. JRA.
5096 /* The first statement above is false - verified using Thursby
5097 * client against NT4 -- gcolley.
5099 case SMB_QUERY_FILE_STREAM_INFO:
5100 case SMB_FILE_STREAM_INFORMATION: {
5101 unsigned int num_streams = 0;
5102 struct stream_struct *streams = NULL;
5104 DEBUG(10,("smbd_do_qfilepathinfo: "
5105 "SMB_FILE_STREAM_INFORMATION\n"));
5107 if (is_ntfs_stream_smb_fname(smb_fname)) {
5108 return NT_STATUS_INVALID_PARAMETER;
5111 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5112 talloc_tos(), &num_streams, &streams);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 DEBUG(10, ("could not get stream info: %s\n",
5116 nt_errstr(status)));
5117 return status;
5120 status = marshall_stream_info(num_streams, streams,
5121 pdata, max_data_bytes,
5122 &data_size);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 DEBUG(10, ("marshall_stream_info failed: %s\n",
5126 nt_errstr(status)));
5127 TALLOC_FREE(streams);
5128 return status;
5131 TALLOC_FREE(streams);
5133 *fixed_portion = 32;
5135 break;
5137 case SMB_QUERY_COMPRESSION_INFO:
5138 case SMB_FILE_COMPRESSION_INFORMATION:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5140 SOFF_T(pdata,0,file_size);
5141 SIVAL(pdata,8,0); /* ??? */
5142 SIVAL(pdata,12,0); /* ??? */
5143 data_size = 16;
5144 *fixed_portion = 16;
5145 break;
5147 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5148 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5149 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5150 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5151 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5152 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5153 SOFF_T(pdata,32,allocation_size);
5154 SOFF_T(pdata,40,file_size);
5155 SIVAL(pdata,48,mode);
5156 SIVAL(pdata,52,0); /* ??? */
5157 data_size = 56;
5158 *fixed_portion = 56;
5159 break;
5161 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5162 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5163 SIVAL(pdata,0,mode);
5164 SIVAL(pdata,4,0);
5165 data_size = 8;
5166 *fixed_portion = 8;
5167 break;
5170 * CIFS UNIX Extensions.
5173 case SMB_QUERY_FILE_UNIX_BASIC:
5175 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5176 data_size = PTR_DIFF(pdata,(*ppdata));
5178 DEBUG(4,("smbd_do_qfilepathinfo: "
5179 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5180 dump_data(4, (uint8_t *)(*ppdata), data_size);
5182 break;
5184 case SMB_QUERY_FILE_UNIX_INFO2:
5186 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5187 data_size = PTR_DIFF(pdata,(*ppdata));
5190 int i;
5191 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5193 for (i=0; i<100; i++)
5194 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5195 DEBUG(4,("\n"));
5198 break;
5200 case SMB_QUERY_FILE_UNIX_LINK:
5202 int link_len = 0;
5203 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5205 if (!buffer) {
5206 return NT_STATUS_NO_MEMORY;
5209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5210 #ifdef S_ISLNK
5211 if(!S_ISLNK(psbuf->st_ex_mode)) {
5212 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5214 #else
5215 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5216 #endif
5217 link_len = SMB_VFS_READLINK(conn,
5218 smb_fname->base_name,
5219 buffer, PATH_MAX);
5220 if (link_len == -1) {
5221 return map_nt_error_from_unix(errno);
5223 buffer[link_len] = 0;
5224 status = srvstr_push(dstart, flags2,
5225 pdata, buffer,
5226 PTR_DIFF(dend, pdata),
5227 STR_TERMINATE, &len);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 return status;
5231 pdata += len;
5232 data_size = PTR_DIFF(pdata,(*ppdata));
5234 break;
5237 #if defined(HAVE_POSIX_ACLS)
5238 case SMB_QUERY_POSIX_ACL:
5240 SMB_ACL_T file_acl = NULL;
5241 SMB_ACL_T def_acl = NULL;
5242 uint16_t num_file_acls = 0;
5243 uint16_t num_def_acls = 0;
5245 if (fsp && fsp->fh->fd != -1) {
5246 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5247 talloc_tos());
5248 } else {
5249 file_acl =
5250 SMB_VFS_SYS_ACL_GET_FILE(conn,
5251 smb_fname->base_name,
5252 SMB_ACL_TYPE_ACCESS,
5253 talloc_tos());
5256 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5257 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5258 "not implemented on "
5259 "filesystem containing %s\n",
5260 smb_fname->base_name));
5261 return NT_STATUS_NOT_IMPLEMENTED;
5264 if (S_ISDIR(psbuf->st_ex_mode)) {
5265 if (fsp && fsp->is_directory) {
5266 def_acl =
5267 SMB_VFS_SYS_ACL_GET_FILE(
5268 conn,
5269 fsp->fsp_name->base_name,
5270 SMB_ACL_TYPE_DEFAULT,
5271 talloc_tos());
5272 } else {
5273 def_acl =
5274 SMB_VFS_SYS_ACL_GET_FILE(
5275 conn,
5276 smb_fname->base_name,
5277 SMB_ACL_TYPE_DEFAULT,
5278 talloc_tos());
5280 def_acl = free_empty_sys_acl(conn, def_acl);
5283 num_file_acls = count_acl_entries(conn, file_acl);
5284 num_def_acls = count_acl_entries(conn, def_acl);
5286 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5287 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5288 data_size,
5289 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5290 SMB_POSIX_ACL_HEADER_SIZE) ));
5291 if (file_acl) {
5292 TALLOC_FREE(file_acl);
5294 if (def_acl) {
5295 TALLOC_FREE(def_acl);
5297 return NT_STATUS_BUFFER_TOO_SMALL;
5300 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5301 SSVAL(pdata,2,num_file_acls);
5302 SSVAL(pdata,4,num_def_acls);
5303 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5304 if (file_acl) {
5305 TALLOC_FREE(file_acl);
5307 if (def_acl) {
5308 TALLOC_FREE(def_acl);
5310 return NT_STATUS_INTERNAL_ERROR;
5312 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5313 if (file_acl) {
5314 TALLOC_FREE(file_acl);
5316 if (def_acl) {
5317 TALLOC_FREE(def_acl);
5319 return NT_STATUS_INTERNAL_ERROR;
5322 if (file_acl) {
5323 TALLOC_FREE(file_acl);
5325 if (def_acl) {
5326 TALLOC_FREE(def_acl);
5328 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5329 break;
5331 #endif
5334 case SMB_QUERY_POSIX_LOCK:
5336 uint64_t count;
5337 uint64_t offset;
5338 uint64_t smblctx;
5339 enum brl_type lock_type;
5341 /* We need an open file with a real fd for this. */
5342 if (!fsp || fsp->fh->fd == -1) {
5343 return NT_STATUS_INVALID_LEVEL;
5346 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5347 return NT_STATUS_INVALID_PARAMETER;
5350 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5351 case POSIX_LOCK_TYPE_READ:
5352 lock_type = READ_LOCK;
5353 break;
5354 case POSIX_LOCK_TYPE_WRITE:
5355 lock_type = WRITE_LOCK;
5356 break;
5357 case POSIX_LOCK_TYPE_UNLOCK:
5358 default:
5359 /* There's no point in asking for an unlock... */
5360 return NT_STATUS_INVALID_PARAMETER;
5363 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5364 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5365 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5367 status = query_lock(fsp,
5368 &smblctx,
5369 &count,
5370 &offset,
5371 &lock_type,
5372 POSIX_LOCK);
5374 if (ERROR_WAS_LOCK_DENIED(status)) {
5375 /* Here we need to report who has it locked... */
5376 data_size = POSIX_LOCK_DATA_SIZE;
5378 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5379 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5380 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5381 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5382 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5384 } else if (NT_STATUS_IS_OK(status)) {
5385 /* For success we just return a copy of what we sent
5386 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5387 data_size = POSIX_LOCK_DATA_SIZE;
5388 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5389 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5390 } else {
5391 return status;
5393 break;
5396 default:
5397 return NT_STATUS_INVALID_LEVEL;
5400 *pdata_size = data_size;
5401 return NT_STATUS_OK;
5404 /****************************************************************************
5405 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5406 file name or file id).
5407 ****************************************************************************/
5409 static void call_trans2qfilepathinfo(connection_struct *conn,
5410 struct smb_request *req,
5411 unsigned int tran_call,
5412 char **pparams, int total_params,
5413 char **ppdata, int total_data,
5414 unsigned int max_data_bytes)
5416 char *params = *pparams;
5417 char *pdata = *ppdata;
5418 uint16_t info_level;
5419 unsigned int data_size = 0;
5420 unsigned int param_size = 2;
5421 struct smb_filename *smb_fname = NULL;
5422 bool delete_pending = False;
5423 struct timespec write_time_ts;
5424 files_struct *fsp = NULL;
5425 struct file_id fileid;
5426 struct ea_list *ea_list = NULL;
5427 int lock_data_count = 0;
5428 char *lock_data = NULL;
5429 size_t fixed_portion;
5430 NTSTATUS status = NT_STATUS_OK;
5432 if (!params) {
5433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5434 return;
5437 ZERO_STRUCT(write_time_ts);
5439 if (tran_call == TRANSACT2_QFILEINFO) {
5440 if (total_params < 4) {
5441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5442 return;
5445 if (IS_IPC(conn)) {
5446 call_trans2qpipeinfo(conn, req, tran_call,
5447 pparams, total_params,
5448 ppdata, total_data,
5449 max_data_bytes);
5450 return;
5453 fsp = file_fsp(req, SVAL(params,0));
5454 info_level = SVAL(params,2);
5456 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5458 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5459 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5460 return;
5463 /* Initial check for valid fsp ptr. */
5464 if (!check_fsp_open(conn, req, fsp)) {
5465 return;
5468 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5469 if (smb_fname == NULL) {
5470 reply_nterror(req, NT_STATUS_NO_MEMORY);
5471 return;
5474 if(fsp->fake_file_handle) {
5476 * This is actually for the QUOTA_FAKE_FILE --metze
5479 /* We know this name is ok, it's already passed the checks. */
5481 } else if(fsp->fh->fd == -1) {
5483 * This is actually a QFILEINFO on a directory
5484 * handle (returned from an NT SMB). NT5.0 seems
5485 * to do this call. JRA.
5488 if (INFO_LEVEL_IS_UNIX(info_level)) {
5489 /* Always do lstat for UNIX calls. */
5490 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5491 DEBUG(3,("call_trans2qfilepathinfo: "
5492 "SMB_VFS_LSTAT of %s failed "
5493 "(%s)\n",
5494 smb_fname_str_dbg(smb_fname),
5495 strerror(errno)));
5496 reply_nterror(req,
5497 map_nt_error_from_unix(errno));
5498 return;
5500 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5501 DEBUG(3,("call_trans2qfilepathinfo: "
5502 "SMB_VFS_STAT of %s failed (%s)\n",
5503 smb_fname_str_dbg(smb_fname),
5504 strerror(errno)));
5505 reply_nterror(req,
5506 map_nt_error_from_unix(errno));
5507 return;
5510 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5511 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5512 } else {
5514 * Original code - this is an open file.
5516 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5517 DEBUG(3, ("fstat of %s failed (%s)\n",
5518 fsp_fnum_dbg(fsp), strerror(errno)));
5519 reply_nterror(req,
5520 map_nt_error_from_unix(errno));
5521 return;
5523 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5524 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5527 } else {
5528 uint32_t name_hash;
5529 char *fname = NULL;
5530 uint32_t ucf_flags = 0;
5532 /* qpathinfo */
5533 if (total_params < 7) {
5534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5535 return;
5538 info_level = SVAL(params,0);
5540 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5542 if (INFO_LEVEL_IS_UNIX(info_level)) {
5543 if (!lp_unix_extensions()) {
5544 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5545 return;
5547 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5548 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5549 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5550 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5554 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5555 total_params - 6,
5556 STR_TERMINATE, &status);
5557 if (!NT_STATUS_IS_OK(status)) {
5558 reply_nterror(req, status);
5559 return;
5562 status = filename_convert(req,
5563 conn,
5564 req->flags2 & FLAGS2_DFS_PATHNAMES,
5565 fname,
5566 ucf_flags,
5567 NULL,
5568 &smb_fname);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5571 reply_botherror(req,
5572 NT_STATUS_PATH_NOT_COVERED,
5573 ERRSRV, ERRbadpath);
5574 return;
5576 reply_nterror(req, status);
5577 return;
5580 /* If this is a stream, check if there is a delete_pending. */
5581 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5582 && is_ntfs_stream_smb_fname(smb_fname)) {
5583 struct smb_filename *smb_fname_base;
5585 /* Create an smb_filename with stream_name == NULL. */
5586 smb_fname_base = synthetic_smb_fname(
5587 talloc_tos(), smb_fname->base_name,
5588 NULL, NULL);
5589 if (smb_fname_base == NULL) {
5590 reply_nterror(req, NT_STATUS_NO_MEMORY);
5591 return;
5594 if (INFO_LEVEL_IS_UNIX(info_level)) {
5595 /* Always do lstat for UNIX calls. */
5596 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5597 DEBUG(3,("call_trans2qfilepathinfo: "
5598 "SMB_VFS_LSTAT of %s failed "
5599 "(%s)\n",
5600 smb_fname_str_dbg(smb_fname_base),
5601 strerror(errno)));
5602 TALLOC_FREE(smb_fname_base);
5603 reply_nterror(req,
5604 map_nt_error_from_unix(errno));
5605 return;
5607 } else {
5608 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5609 DEBUG(3,("call_trans2qfilepathinfo: "
5610 "fileinfo of %s failed "
5611 "(%s)\n",
5612 smb_fname_str_dbg(smb_fname_base),
5613 strerror(errno)));
5614 TALLOC_FREE(smb_fname_base);
5615 reply_nterror(req,
5616 map_nt_error_from_unix(errno));
5617 return;
5621 status = file_name_hash(conn,
5622 smb_fname_str_dbg(smb_fname_base),
5623 &name_hash);
5624 if (!NT_STATUS_IS_OK(status)) {
5625 TALLOC_FREE(smb_fname_base);
5626 reply_nterror(req, status);
5627 return;
5630 fileid = vfs_file_id_from_sbuf(conn,
5631 &smb_fname_base->st);
5632 TALLOC_FREE(smb_fname_base);
5633 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5634 if (delete_pending) {
5635 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5636 return;
5640 if (INFO_LEVEL_IS_UNIX(info_level)) {
5641 /* Always do lstat for UNIX calls. */
5642 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5643 DEBUG(3,("call_trans2qfilepathinfo: "
5644 "SMB_VFS_LSTAT of %s failed (%s)\n",
5645 smb_fname_str_dbg(smb_fname),
5646 strerror(errno)));
5647 reply_nterror(req,
5648 map_nt_error_from_unix(errno));
5649 return;
5652 } else {
5653 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5654 DEBUG(3,("call_trans2qfilepathinfo: "
5655 "SMB_VFS_STAT of %s failed (%s)\n",
5656 smb_fname_str_dbg(smb_fname),
5657 strerror(errno)));
5658 reply_nterror(req,
5659 map_nt_error_from_unix(errno));
5660 return;
5664 status = file_name_hash(conn,
5665 smb_fname_str_dbg(smb_fname),
5666 &name_hash);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 reply_nterror(req, status);
5669 return;
5672 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5673 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5674 if (delete_pending) {
5675 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5676 return;
5680 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5681 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5682 fsp_fnum_dbg(fsp),
5683 info_level,tran_call,total_data));
5685 /* Pull out any data sent here before we realloc. */
5686 switch (info_level) {
5687 case SMB_INFO_QUERY_EAS_FROM_LIST:
5689 /* Pull any EA list from the data portion. */
5690 uint32_t ea_size;
5692 if (total_data < 4) {
5693 reply_nterror(
5694 req, NT_STATUS_INVALID_PARAMETER);
5695 return;
5697 ea_size = IVAL(pdata,0);
5699 if (total_data > 0 && ea_size != total_data) {
5700 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5701 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5702 reply_nterror(
5703 req, NT_STATUS_INVALID_PARAMETER);
5704 return;
5707 if (!lp_ea_support(SNUM(conn))) {
5708 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5709 return;
5712 /* Pull out the list of names. */
5713 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5714 if (!ea_list) {
5715 reply_nterror(
5716 req, NT_STATUS_INVALID_PARAMETER);
5717 return;
5719 break;
5722 case SMB_QUERY_POSIX_LOCK:
5724 if (fsp == NULL || fsp->fh->fd == -1) {
5725 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5726 return;
5729 if (total_data != POSIX_LOCK_DATA_SIZE) {
5730 reply_nterror(
5731 req, NT_STATUS_INVALID_PARAMETER);
5732 return;
5735 /* Copy the lock range data. */
5736 lock_data = (char *)talloc_memdup(
5737 req, pdata, total_data);
5738 if (!lock_data) {
5739 reply_nterror(req, NT_STATUS_NO_MEMORY);
5740 return;
5742 lock_data_count = total_data;
5744 default:
5745 break;
5748 *pparams = (char *)SMB_REALLOC(*pparams,2);
5749 if (*pparams == NULL) {
5750 reply_nterror(req, NT_STATUS_NO_MEMORY);
5751 return;
5753 params = *pparams;
5754 SSVAL(params,0,0);
5757 * draft-leach-cifs-v1-spec-02.txt
5758 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5759 * says:
5761 * The requested information is placed in the Data portion of the
5762 * transaction response. For the information levels greater than 0x100,
5763 * the transaction response has 1 parameter word which should be
5764 * ignored by the client.
5766 * However Windows only follows this rule for the IS_NAME_VALID call.
5768 switch (info_level) {
5769 case SMB_INFO_IS_NAME_VALID:
5770 param_size = 0;
5771 break;
5774 if ((info_level & 0xFF00) == 0xFF00) {
5776 * We use levels that start with 0xFF00
5777 * internally to represent SMB2 specific levels
5779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5780 return;
5783 status = smbd_do_qfilepathinfo(conn, req, info_level,
5784 fsp, smb_fname,
5785 delete_pending, write_time_ts,
5786 ea_list,
5787 lock_data_count, lock_data,
5788 req->flags2, max_data_bytes,
5789 &fixed_portion,
5790 ppdata, &data_size);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 reply_nterror(req, status);
5793 return;
5795 if (fixed_portion > max_data_bytes) {
5796 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5797 return;
5800 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5801 max_data_bytes);
5803 return;
5806 /****************************************************************************
5807 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5808 code.
5809 ****************************************************************************/
5811 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5812 connection_struct *conn,
5813 struct smb_request *req,
5814 bool overwrite_if_exists,
5815 const struct smb_filename *smb_fname_old,
5816 struct smb_filename *smb_fname_new)
5818 NTSTATUS status = NT_STATUS_OK;
5820 /* source must already exist. */
5821 if (!VALID_STAT(smb_fname_old->st)) {
5822 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5825 if (VALID_STAT(smb_fname_new->st)) {
5826 if (overwrite_if_exists) {
5827 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5828 return NT_STATUS_FILE_IS_A_DIRECTORY;
5830 status = unlink_internals(conn,
5831 req,
5832 FILE_ATTRIBUTE_NORMAL,
5833 smb_fname_new,
5834 false);
5835 if (!NT_STATUS_IS_OK(status)) {
5836 return status;
5838 } else {
5839 /* Disallow if newname already exists. */
5840 return NT_STATUS_OBJECT_NAME_COLLISION;
5844 /* No links from a directory. */
5845 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5846 return NT_STATUS_FILE_IS_A_DIRECTORY;
5849 /* Setting a hardlink to/from a stream isn't currently supported. */
5850 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5851 is_ntfs_stream_smb_fname(smb_fname_new)) {
5852 return NT_STATUS_INVALID_PARAMETER;
5855 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5856 smb_fname_old->base_name, smb_fname_new->base_name));
5858 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5859 smb_fname_new->base_name) != 0) {
5860 status = map_nt_error_from_unix(errno);
5861 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5862 nt_errstr(status), smb_fname_old->base_name,
5863 smb_fname_new->base_name));
5865 return status;
5868 /****************************************************************************
5869 Deal with setting the time from any of the setfilepathinfo functions.
5870 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5871 calling this function.
5872 ****************************************************************************/
5874 NTSTATUS smb_set_file_time(connection_struct *conn,
5875 files_struct *fsp,
5876 const struct smb_filename *smb_fname,
5877 struct smb_file_time *ft,
5878 bool setting_write_time)
5880 struct smb_filename smb_fname_base;
5881 uint32_t action =
5882 FILE_NOTIFY_CHANGE_LAST_ACCESS
5883 |FILE_NOTIFY_CHANGE_LAST_WRITE
5884 |FILE_NOTIFY_CHANGE_CREATION;
5886 if (!VALID_STAT(smb_fname->st)) {
5887 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5890 /* get some defaults (no modifications) if any info is zero or -1. */
5891 if (null_timespec(ft->create_time)) {
5892 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5895 if (null_timespec(ft->atime)) {
5896 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5899 if (null_timespec(ft->mtime)) {
5900 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5903 if (!setting_write_time) {
5904 /* ft->mtime comes from change time, not write time. */
5905 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5908 /* Ensure the resolution is the correct for
5909 * what we can store on this filesystem. */
5911 round_timespec(conn->ts_res, &ft->create_time);
5912 round_timespec(conn->ts_res, &ft->ctime);
5913 round_timespec(conn->ts_res, &ft->atime);
5914 round_timespec(conn->ts_res, &ft->mtime);
5916 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5917 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5918 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5919 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5920 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5921 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5922 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5923 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5925 if (setting_write_time) {
5927 * This was a Windows setfileinfo on an open file.
5928 * NT does this a lot. We also need to
5929 * set the time here, as it can be read by
5930 * FindFirst/FindNext and with the patch for bug #2045
5931 * in smbd/fileio.c it ensures that this timestamp is
5932 * kept sticky even after a write. We save the request
5933 * away and will set it on file close and after a write. JRA.
5936 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5937 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5939 if (fsp != NULL) {
5940 if (fsp->base_fsp) {
5941 set_sticky_write_time_fsp(fsp->base_fsp,
5942 ft->mtime);
5943 } else {
5944 set_sticky_write_time_fsp(fsp, ft->mtime);
5946 } else {
5947 set_sticky_write_time_path(
5948 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5949 ft->mtime);
5953 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5955 /* Always call ntimes on the base, even if a stream was passed in. */
5956 smb_fname_base = *smb_fname;
5957 smb_fname_base.stream_name = NULL;
5959 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5960 return map_nt_error_from_unix(errno);
5963 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5964 smb_fname->base_name);
5965 return NT_STATUS_OK;
5968 /****************************************************************************
5969 Deal with setting the dosmode from any of the setfilepathinfo functions.
5970 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5971 done before calling this function.
5972 ****************************************************************************/
5974 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5975 const struct smb_filename *smb_fname,
5976 uint32_t dosmode)
5978 struct smb_filename *smb_fname_base;
5979 NTSTATUS status;
5981 if (!VALID_STAT(smb_fname->st)) {
5982 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5985 /* Always operate on the base_name, even if a stream was passed in. */
5986 smb_fname_base = synthetic_smb_fname(
5987 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5988 if (smb_fname_base == NULL) {
5989 return NT_STATUS_NO_MEMORY;
5992 if (dosmode) {
5993 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5994 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5995 } else {
5996 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6000 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6002 /* check the mode isn't different, before changing it */
6003 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6005 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6006 (unsigned int)dosmode));
6008 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6009 false)) {
6010 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6011 "%s failed (%s)\n",
6012 smb_fname_str_dbg(smb_fname_base),
6013 strerror(errno)));
6014 status = map_nt_error_from_unix(errno);
6015 goto out;
6018 status = NT_STATUS_OK;
6019 out:
6020 TALLOC_FREE(smb_fname_base);
6021 return status;
6024 /****************************************************************************
6025 Deal with setting the size from any of the setfilepathinfo functions.
6026 ****************************************************************************/
6028 static NTSTATUS smb_set_file_size(connection_struct *conn,
6029 struct smb_request *req,
6030 files_struct *fsp,
6031 const struct smb_filename *smb_fname,
6032 const SMB_STRUCT_STAT *psbuf,
6033 off_t size,
6034 bool fail_after_createfile)
6036 NTSTATUS status = NT_STATUS_OK;
6037 struct smb_filename *smb_fname_tmp = NULL;
6038 files_struct *new_fsp = NULL;
6040 if (!VALID_STAT(*psbuf)) {
6041 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6044 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6046 if (size == get_file_size_stat(psbuf)) {
6047 return NT_STATUS_OK;
6050 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6051 smb_fname_str_dbg(smb_fname), (double)size));
6053 if (fsp && fsp->fh->fd != -1) {
6054 /* Handle based call. */
6055 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6056 return NT_STATUS_ACCESS_DENIED;
6059 if (vfs_set_filelen(fsp, size) == -1) {
6060 return map_nt_error_from_unix(errno);
6062 trigger_write_time_update_immediate(fsp);
6063 return NT_STATUS_OK;
6066 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6067 if (smb_fname_tmp == NULL) {
6068 return NT_STATUS_NO_MEMORY;
6071 smb_fname_tmp->st = *psbuf;
6073 status = SMB_VFS_CREATE_FILE(
6074 conn, /* conn */
6075 req, /* req */
6076 0, /* root_dir_fid */
6077 smb_fname_tmp, /* fname */
6078 FILE_WRITE_DATA, /* access_mask */
6079 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6080 FILE_SHARE_DELETE),
6081 FILE_OPEN, /* create_disposition*/
6082 0, /* create_options */
6083 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6084 0, /* oplock_request */
6085 NULL, /* lease */
6086 0, /* allocation_size */
6087 0, /* private_flags */
6088 NULL, /* sd */
6089 NULL, /* ea_list */
6090 &new_fsp, /* result */
6091 NULL, /* pinfo */
6092 NULL, NULL); /* create context */
6094 TALLOC_FREE(smb_fname_tmp);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 /* NB. We check for open_was_deferred in the caller. */
6098 return status;
6101 /* See RAW-SFILEINFO-END-OF-FILE */
6102 if (fail_after_createfile) {
6103 close_file(req, new_fsp,NORMAL_CLOSE);
6104 return NT_STATUS_INVALID_LEVEL;
6107 if (vfs_set_filelen(new_fsp, size) == -1) {
6108 status = map_nt_error_from_unix(errno);
6109 close_file(req, new_fsp,NORMAL_CLOSE);
6110 return status;
6113 trigger_write_time_update_immediate(new_fsp);
6114 close_file(req, new_fsp,NORMAL_CLOSE);
6115 return NT_STATUS_OK;
6118 /****************************************************************************
6119 Deal with SMB_INFO_SET_EA.
6120 ****************************************************************************/
6122 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6123 const char *pdata,
6124 int total_data,
6125 files_struct *fsp,
6126 const struct smb_filename *smb_fname)
6128 struct ea_list *ea_list = NULL;
6129 TALLOC_CTX *ctx = NULL;
6130 NTSTATUS status = NT_STATUS_OK;
6132 if (total_data < 10) {
6134 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6135 length. They seem to have no effect. Bug #3212. JRA */
6137 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6138 /* We're done. We only get EA info in this call. */
6139 return NT_STATUS_OK;
6142 return NT_STATUS_INVALID_PARAMETER;
6145 if (IVAL(pdata,0) > total_data) {
6146 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6147 IVAL(pdata,0), (unsigned int)total_data));
6148 return NT_STATUS_INVALID_PARAMETER;
6151 ctx = talloc_tos();
6152 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6153 if (!ea_list) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 status = set_ea(conn, fsp, smb_fname, ea_list);
6159 return status;
6162 /****************************************************************************
6163 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6164 ****************************************************************************/
6166 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6167 const char *pdata,
6168 int total_data,
6169 files_struct *fsp)
6171 struct ea_list *ea_list = NULL;
6172 NTSTATUS status;
6174 if (!fsp) {
6175 return NT_STATUS_INVALID_HANDLE;
6178 if (!lp_ea_support(SNUM(conn))) {
6179 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6180 "EA's not supported.\n",
6181 (unsigned int)total_data));
6182 return NT_STATUS_EAS_NOT_SUPPORTED;
6185 if (total_data < 10) {
6186 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6187 "too small.\n",
6188 (unsigned int)total_data));
6189 return NT_STATUS_INVALID_PARAMETER;
6192 ea_list = read_nttrans_ea_list(talloc_tos(),
6193 pdata,
6194 total_data);
6196 if (!ea_list) {
6197 return NT_STATUS_INVALID_PARAMETER;
6200 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6202 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6203 smb_fname_str_dbg(fsp->fsp_name),
6204 nt_errstr(status) ));
6206 return status;
6210 /****************************************************************************
6211 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6212 ****************************************************************************/
6214 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6215 const char *pdata,
6216 int total_data,
6217 files_struct *fsp,
6218 struct smb_filename *smb_fname)
6220 NTSTATUS status = NT_STATUS_OK;
6221 bool delete_on_close;
6222 uint32_t dosmode = 0;
6224 if (total_data < 1) {
6225 return NT_STATUS_INVALID_PARAMETER;
6228 if (fsp == NULL) {
6229 return NT_STATUS_INVALID_HANDLE;
6232 delete_on_close = (CVAL(pdata,0) ? True : False);
6233 dosmode = dos_mode(conn, smb_fname);
6235 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6236 "delete_on_close = %u\n",
6237 smb_fname_str_dbg(smb_fname),
6238 (unsigned int)dosmode,
6239 (unsigned int)delete_on_close ));
6241 if (delete_on_close) {
6242 status = can_set_delete_on_close(fsp, dosmode);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 return status;
6248 /* The set is across all open files on this dev/inode pair. */
6249 if (!set_delete_on_close(fsp, delete_on_close,
6250 conn->session_info->security_token,
6251 conn->session_info->unix_token)) {
6252 return NT_STATUS_ACCESS_DENIED;
6254 return NT_STATUS_OK;
6257 /****************************************************************************
6258 Deal with SMB_FILE_POSITION_INFORMATION.
6259 ****************************************************************************/
6261 static NTSTATUS smb_file_position_information(connection_struct *conn,
6262 const char *pdata,
6263 int total_data,
6264 files_struct *fsp)
6266 uint64_t position_information;
6268 if (total_data < 8) {
6269 return NT_STATUS_INVALID_PARAMETER;
6272 if (fsp == NULL) {
6273 /* Ignore on pathname based set. */
6274 return NT_STATUS_OK;
6277 position_information = (uint64_t)IVAL(pdata,0);
6278 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6280 DEBUG(10,("smb_file_position_information: Set file position "
6281 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6282 (double)position_information));
6283 fsp->fh->position_information = position_information;
6284 return NT_STATUS_OK;
6287 /****************************************************************************
6288 Deal with SMB_FILE_MODE_INFORMATION.
6289 ****************************************************************************/
6291 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6292 const char *pdata,
6293 int total_data)
6295 uint32_t mode;
6297 if (total_data < 4) {
6298 return NT_STATUS_INVALID_PARAMETER;
6300 mode = IVAL(pdata,0);
6301 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6302 return NT_STATUS_INVALID_PARAMETER;
6304 return NT_STATUS_OK;
6307 /****************************************************************************
6308 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6309 ****************************************************************************/
6311 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6312 struct smb_request *req,
6313 const char *pdata,
6314 int total_data,
6315 const struct smb_filename *smb_fname)
6317 char *link_target = NULL;
6318 const char *newname = smb_fname->base_name;
6319 TALLOC_CTX *ctx = talloc_tos();
6321 /* Set a symbolic link. */
6322 /* Don't allow this if follow links is false. */
6324 if (total_data == 0) {
6325 return NT_STATUS_INVALID_PARAMETER;
6328 if (!lp_follow_symlinks(SNUM(conn))) {
6329 return NT_STATUS_ACCESS_DENIED;
6332 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6333 total_data, STR_TERMINATE);
6335 if (!link_target) {
6336 return NT_STATUS_INVALID_PARAMETER;
6339 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6340 newname, link_target ));
6342 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6343 return map_nt_error_from_unix(errno);
6346 return NT_STATUS_OK;
6349 /****************************************************************************
6350 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6351 ****************************************************************************/
6353 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6354 struct smb_request *req,
6355 const char *pdata, int total_data,
6356 struct smb_filename *smb_fname_new)
6358 char *oldname = NULL;
6359 struct smb_filename *smb_fname_old = NULL;
6360 TALLOC_CTX *ctx = talloc_tos();
6361 NTSTATUS status = NT_STATUS_OK;
6363 /* Set a hard link. */
6364 if (total_data == 0) {
6365 return NT_STATUS_INVALID_PARAMETER;
6368 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6369 total_data, STR_TERMINATE, &status);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 return status;
6374 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6375 smb_fname_str_dbg(smb_fname_new), oldname));
6377 status = filename_convert(ctx,
6378 conn,
6379 req->flags2 & FLAGS2_DFS_PATHNAMES,
6380 oldname,
6382 NULL,
6383 &smb_fname_old);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 return status;
6388 return hardlink_internals(ctx, conn, req, false,
6389 smb_fname_old, smb_fname_new);
6392 /****************************************************************************
6393 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6394 ****************************************************************************/
6396 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6397 struct smb_request *req,
6398 const char *pdata,
6399 int total_data,
6400 files_struct *fsp,
6401 struct smb_filename *smb_fname_src)
6403 bool overwrite;
6404 uint32_t len;
6405 char *newname = NULL;
6406 struct smb_filename *smb_fname_dst = NULL;
6407 NTSTATUS status = NT_STATUS_OK;
6408 TALLOC_CTX *ctx = talloc_tos();
6410 if (!fsp) {
6411 return NT_STATUS_INVALID_HANDLE;
6414 if (total_data < 20) {
6415 return NT_STATUS_INVALID_PARAMETER;
6418 overwrite = (CVAL(pdata,0) ? True : False);
6419 len = IVAL(pdata,16);
6421 if (len > (total_data - 20) || (len == 0)) {
6422 return NT_STATUS_INVALID_PARAMETER;
6425 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6426 &pdata[20], len, STR_TERMINATE,
6427 &status);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 return status;
6432 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6433 newname));
6435 status = filename_convert(ctx,
6436 conn,
6437 req->flags2 & FLAGS2_DFS_PATHNAMES,
6438 newname,
6439 UCF_SAVE_LCOMP,
6440 NULL,
6441 &smb_fname_dst);
6442 if (!NT_STATUS_IS_OK(status)) {
6443 return status;
6446 if (fsp->base_fsp) {
6447 /* newname must be a stream name. */
6448 if (newname[0] != ':') {
6449 return NT_STATUS_NOT_SUPPORTED;
6452 /* Create an smb_fname to call rename_internals_fsp() with. */
6453 smb_fname_dst = synthetic_smb_fname(
6454 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6455 newname, NULL);
6456 if (smb_fname_dst == NULL) {
6457 status = NT_STATUS_NO_MEMORY;
6458 goto out;
6462 * Set the original last component, since
6463 * rename_internals_fsp() requires it.
6465 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6466 newname);
6467 if (smb_fname_dst->original_lcomp == NULL) {
6468 status = NT_STATUS_NO_MEMORY;
6469 goto out;
6474 DEBUG(10,("smb2_file_rename_information: "
6475 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6476 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6477 smb_fname_str_dbg(smb_fname_dst)));
6478 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6479 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6480 overwrite);
6482 out:
6483 TALLOC_FREE(smb_fname_dst);
6484 return status;
6487 static NTSTATUS smb_file_link_information(connection_struct *conn,
6488 struct smb_request *req,
6489 const char *pdata,
6490 int total_data,
6491 files_struct *fsp,
6492 struct smb_filename *smb_fname_src)
6494 bool overwrite;
6495 uint32_t len;
6496 char *newname = NULL;
6497 struct smb_filename *smb_fname_dst = NULL;
6498 NTSTATUS status = NT_STATUS_OK;
6499 TALLOC_CTX *ctx = talloc_tos();
6501 if (!fsp) {
6502 return NT_STATUS_INVALID_HANDLE;
6505 if (total_data < 20) {
6506 return NT_STATUS_INVALID_PARAMETER;
6509 overwrite = (CVAL(pdata,0) ? true : false);
6510 len = IVAL(pdata,16);
6512 if (len > (total_data - 20) || (len == 0)) {
6513 return NT_STATUS_INVALID_PARAMETER;
6516 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6517 &pdata[20], len, STR_TERMINATE,
6518 &status);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 return status;
6523 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6524 newname));
6526 status = filename_convert(ctx,
6527 conn,
6528 req->flags2 & FLAGS2_DFS_PATHNAMES,
6529 newname,
6530 UCF_SAVE_LCOMP,
6531 NULL,
6532 &smb_fname_dst);
6533 if (!NT_STATUS_IS_OK(status)) {
6534 return status;
6537 if (fsp->base_fsp) {
6538 /* No stream names. */
6539 return NT_STATUS_NOT_SUPPORTED;
6542 DEBUG(10,("smb_file_link_information: "
6543 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6544 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6545 smb_fname_str_dbg(smb_fname_dst)));
6546 status = hardlink_internals(ctx,
6547 conn,
6548 req,
6549 overwrite,
6550 fsp->fsp_name,
6551 smb_fname_dst);
6553 TALLOC_FREE(smb_fname_dst);
6554 return status;
6557 /****************************************************************************
6558 Deal with SMB_FILE_RENAME_INFORMATION.
6559 ****************************************************************************/
6561 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6562 struct smb_request *req,
6563 const char *pdata,
6564 int total_data,
6565 files_struct *fsp,
6566 struct smb_filename *smb_fname_src)
6568 bool overwrite;
6569 uint32_t root_fid;
6570 uint32_t len;
6571 char *newname = NULL;
6572 struct smb_filename *smb_fname_dst = NULL;
6573 bool dest_has_wcard = False;
6574 NTSTATUS status = NT_STATUS_OK;
6575 char *p;
6576 TALLOC_CTX *ctx = talloc_tos();
6578 if (total_data < 13) {
6579 return NT_STATUS_INVALID_PARAMETER;
6582 overwrite = (CVAL(pdata,0) ? True : False);
6583 root_fid = IVAL(pdata,4);
6584 len = IVAL(pdata,8);
6586 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6587 return NT_STATUS_INVALID_PARAMETER;
6590 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6591 len, 0, &status,
6592 &dest_has_wcard);
6593 if (!NT_STATUS_IS_OK(status)) {
6594 return status;
6597 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6598 newname));
6600 status = resolve_dfspath_wcard(ctx, conn,
6601 req->flags2 & FLAGS2_DFS_PATHNAMES,
6602 newname,
6603 true,
6604 !conn->sconn->using_smb2,
6605 &newname,
6606 &dest_has_wcard);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 return status;
6611 /* Check the new name has no '/' characters. */
6612 if (strchr_m(newname, '/')) {
6613 return NT_STATUS_NOT_SUPPORTED;
6616 if (fsp && fsp->base_fsp) {
6617 /* newname must be a stream name. */
6618 if (newname[0] != ':') {
6619 return NT_STATUS_NOT_SUPPORTED;
6622 /* Create an smb_fname to call rename_internals_fsp() with. */
6623 smb_fname_dst = synthetic_smb_fname(
6624 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6625 newname, NULL);
6626 if (smb_fname_dst == NULL) {
6627 status = NT_STATUS_NO_MEMORY;
6628 goto out;
6632 * Set the original last component, since
6633 * rename_internals_fsp() requires it.
6635 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6636 newname);
6637 if (smb_fname_dst->original_lcomp == NULL) {
6638 status = NT_STATUS_NO_MEMORY;
6639 goto out;
6642 } else {
6644 * Build up an smb_fname_dst based on the filename passed in.
6645 * We basically just strip off the last component, and put on
6646 * the newname instead.
6648 char *base_name = NULL;
6650 /* newname must *not* be a stream name. */
6651 if (newname[0] == ':') {
6652 return NT_STATUS_NOT_SUPPORTED;
6656 * Strip off the last component (filename) of the path passed
6657 * in.
6659 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6660 if (!base_name) {
6661 return NT_STATUS_NO_MEMORY;
6663 p = strrchr_m(base_name, '/');
6664 if (p) {
6665 p[1] = '\0';
6666 } else {
6667 base_name = talloc_strdup(ctx, "");
6668 if (!base_name) {
6669 return NT_STATUS_NO_MEMORY;
6672 /* Append the new name. */
6673 base_name = talloc_asprintf_append(base_name,
6674 "%s",
6675 newname);
6676 if (!base_name) {
6677 return NT_STATUS_NO_MEMORY;
6680 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6681 (UCF_SAVE_LCOMP |
6682 (dest_has_wcard ?
6683 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6684 0)));
6686 /* If an error we expect this to be
6687 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6689 if (!NT_STATUS_IS_OK(status)) {
6690 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6691 status)) {
6692 goto out;
6694 /* Create an smb_fname to call rename_internals_fsp() */
6695 smb_fname_dst = synthetic_smb_fname(
6696 ctx, base_name, NULL, NULL);
6697 if (smb_fname_dst == NULL) {
6698 status = NT_STATUS_NO_MEMORY;
6699 goto out;
6704 if (fsp) {
6705 DEBUG(10,("smb_file_rename_information: "
6706 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6707 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6708 smb_fname_str_dbg(smb_fname_dst)));
6709 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6710 overwrite);
6711 } else {
6712 DEBUG(10,("smb_file_rename_information: "
6713 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6714 smb_fname_str_dbg(smb_fname_src),
6715 smb_fname_str_dbg(smb_fname_dst)));
6716 status = rename_internals(ctx, conn, req, smb_fname_src,
6717 smb_fname_dst, 0, overwrite, false,
6718 dest_has_wcard,
6719 FILE_WRITE_ATTRIBUTES);
6721 out:
6722 TALLOC_FREE(smb_fname_dst);
6723 return status;
6726 /****************************************************************************
6727 Deal with SMB_SET_POSIX_ACL.
6728 ****************************************************************************/
6730 #if defined(HAVE_POSIX_ACLS)
6731 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6732 const char *pdata,
6733 int total_data,
6734 files_struct *fsp,
6735 const struct smb_filename *smb_fname)
6737 uint16_t posix_acl_version;
6738 uint16_t num_file_acls;
6739 uint16_t num_def_acls;
6740 bool valid_file_acls = True;
6741 bool valid_def_acls = True;
6743 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6744 return NT_STATUS_INVALID_PARAMETER;
6746 posix_acl_version = SVAL(pdata,0);
6747 num_file_acls = SVAL(pdata,2);
6748 num_def_acls = SVAL(pdata,4);
6750 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6751 valid_file_acls = False;
6752 num_file_acls = 0;
6755 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6756 valid_def_acls = False;
6757 num_def_acls = 0;
6760 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6761 return NT_STATUS_INVALID_PARAMETER;
6764 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6765 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6766 return NT_STATUS_INVALID_PARAMETER;
6769 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6770 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6771 (unsigned int)num_file_acls,
6772 (unsigned int)num_def_acls));
6774 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6775 smb_fname->base_name, num_file_acls,
6776 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6777 return map_nt_error_from_unix(errno);
6780 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6781 smb_fname->base_name, &smb_fname->st, num_def_acls,
6782 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6783 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6784 return map_nt_error_from_unix(errno);
6786 return NT_STATUS_OK;
6788 #endif
6790 /****************************************************************************
6791 Deal with SMB_SET_POSIX_LOCK.
6792 ****************************************************************************/
6794 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6795 struct smb_request *req,
6796 const char *pdata,
6797 int total_data,
6798 files_struct *fsp)
6800 uint64_t count;
6801 uint64_t offset;
6802 uint64_t smblctx;
6803 bool blocking_lock = False;
6804 enum brl_type lock_type;
6806 NTSTATUS status = NT_STATUS_OK;
6808 if (fsp == NULL || fsp->fh->fd == -1) {
6809 return NT_STATUS_INVALID_HANDLE;
6812 if (total_data != POSIX_LOCK_DATA_SIZE) {
6813 return NT_STATUS_INVALID_PARAMETER;
6816 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6817 case POSIX_LOCK_TYPE_READ:
6818 lock_type = READ_LOCK;
6819 break;
6820 case POSIX_LOCK_TYPE_WRITE:
6821 /* Return the right POSIX-mappable error code for files opened read-only. */
6822 if (!fsp->can_write) {
6823 return NT_STATUS_INVALID_HANDLE;
6825 lock_type = WRITE_LOCK;
6826 break;
6827 case POSIX_LOCK_TYPE_UNLOCK:
6828 lock_type = UNLOCK_LOCK;
6829 break;
6830 default:
6831 return NT_STATUS_INVALID_PARAMETER;
6834 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6835 blocking_lock = False;
6836 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6837 blocking_lock = True;
6838 } else {
6839 return NT_STATUS_INVALID_PARAMETER;
6842 if (!lp_blocking_locks(SNUM(conn))) {
6843 blocking_lock = False;
6846 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6847 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6848 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6849 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6850 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6852 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6853 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6854 fsp_str_dbg(fsp),
6855 (unsigned int)lock_type,
6856 (unsigned long long)smblctx,
6857 (double)count,
6858 (double)offset ));
6860 if (lock_type == UNLOCK_LOCK) {
6861 status = do_unlock(req->sconn->msg_ctx,
6862 fsp,
6863 smblctx,
6864 count,
6865 offset,
6866 POSIX_LOCK);
6867 } else {
6868 uint64_t block_smblctx;
6870 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6871 fsp,
6872 smblctx,
6873 count,
6874 offset,
6875 lock_type,
6876 POSIX_LOCK,
6877 blocking_lock,
6878 &status,
6879 &block_smblctx);
6881 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6883 * A blocking lock was requested. Package up
6884 * this smb into a queued request and push it
6885 * onto the blocking lock queue.
6887 if(push_blocking_lock_request(br_lck,
6888 req,
6889 fsp,
6890 -1, /* infinite timeout. */
6892 smblctx,
6893 lock_type,
6894 POSIX_LOCK,
6895 offset,
6896 count,
6897 block_smblctx)) {
6898 TALLOC_FREE(br_lck);
6899 return status;
6902 TALLOC_FREE(br_lck);
6905 return status;
6908 /****************************************************************************
6909 Deal with SMB_SET_FILE_BASIC_INFO.
6910 ****************************************************************************/
6912 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6913 const char *pdata,
6914 int total_data,
6915 files_struct *fsp,
6916 const struct smb_filename *smb_fname)
6918 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6919 struct smb_file_time ft;
6920 uint32_t dosmode = 0;
6921 NTSTATUS status = NT_STATUS_OK;
6923 ZERO_STRUCT(ft);
6925 if (total_data < 36) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 return status;
6934 /* Set the attributes */
6935 dosmode = IVAL(pdata,32);
6936 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 return status;
6941 /* create time */
6942 ft.create_time = interpret_long_date(pdata);
6944 /* access time */
6945 ft.atime = interpret_long_date(pdata+8);
6947 /* write time. */
6948 ft.mtime = interpret_long_date(pdata+16);
6950 /* change time. */
6951 ft.ctime = interpret_long_date(pdata+24);
6953 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6954 smb_fname_str_dbg(smb_fname)));
6956 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6957 true);
6960 /****************************************************************************
6961 Deal with SMB_INFO_STANDARD.
6962 ****************************************************************************/
6964 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6965 const char *pdata,
6966 int total_data,
6967 files_struct *fsp,
6968 const struct smb_filename *smb_fname)
6970 NTSTATUS status;
6971 struct smb_file_time ft;
6973 ZERO_STRUCT(ft);
6975 if (total_data < 12) {
6976 return NT_STATUS_INVALID_PARAMETER;
6979 /* create time */
6980 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6981 /* access time */
6982 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6983 /* write time */
6984 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6986 DEBUG(10,("smb_set_info_standard: file %s\n",
6987 smb_fname_str_dbg(smb_fname)));
6989 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6990 if (!NT_STATUS_IS_OK(status)) {
6991 return status;
6994 return smb_set_file_time(conn,
6995 fsp,
6996 smb_fname,
6997 &ft,
6998 true);
7001 /****************************************************************************
7002 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7003 ****************************************************************************/
7005 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7006 struct smb_request *req,
7007 const char *pdata,
7008 int total_data,
7009 files_struct *fsp,
7010 struct smb_filename *smb_fname)
7012 uint64_t allocation_size = 0;
7013 NTSTATUS status = NT_STATUS_OK;
7014 files_struct *new_fsp = NULL;
7016 if (!VALID_STAT(smb_fname->st)) {
7017 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7020 if (total_data < 8) {
7021 return NT_STATUS_INVALID_PARAMETER;
7024 allocation_size = (uint64_t)IVAL(pdata,0);
7025 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7026 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7027 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7028 (double)allocation_size));
7030 if (allocation_size) {
7031 allocation_size = smb_roundup(conn, allocation_size);
7034 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7035 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7036 (double)allocation_size));
7038 if (fsp && fsp->fh->fd != -1) {
7039 /* Open file handle. */
7040 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7041 return NT_STATUS_ACCESS_DENIED;
7044 /* Only change if needed. */
7045 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7046 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7047 return map_nt_error_from_unix(errno);
7050 /* But always update the time. */
7052 * This is equivalent to a write. Ensure it's seen immediately
7053 * if there are no pending writes.
7055 trigger_write_time_update_immediate(fsp);
7056 return NT_STATUS_OK;
7059 /* Pathname or stat or directory file. */
7060 status = SMB_VFS_CREATE_FILE(
7061 conn, /* conn */
7062 req, /* req */
7063 0, /* root_dir_fid */
7064 smb_fname, /* fname */
7065 FILE_WRITE_DATA, /* access_mask */
7066 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7067 FILE_SHARE_DELETE),
7068 FILE_OPEN, /* create_disposition*/
7069 0, /* create_options */
7070 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7071 0, /* oplock_request */
7072 NULL, /* lease */
7073 0, /* allocation_size */
7074 0, /* private_flags */
7075 NULL, /* sd */
7076 NULL, /* ea_list */
7077 &new_fsp, /* result */
7078 NULL, /* pinfo */
7079 NULL, NULL); /* create context */
7081 if (!NT_STATUS_IS_OK(status)) {
7082 /* NB. We check for open_was_deferred in the caller. */
7083 return status;
7086 /* Only change if needed. */
7087 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7088 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7089 status = map_nt_error_from_unix(errno);
7090 close_file(req, new_fsp, NORMAL_CLOSE);
7091 return status;
7095 /* Changing the allocation size should set the last mod time. */
7097 * This is equivalent to a write. Ensure it's seen immediately
7098 * if there are no pending writes.
7100 trigger_write_time_update_immediate(new_fsp);
7101 close_file(req, new_fsp, NORMAL_CLOSE);
7102 return NT_STATUS_OK;
7105 /****************************************************************************
7106 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7107 ****************************************************************************/
7109 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7110 struct smb_request *req,
7111 const char *pdata,
7112 int total_data,
7113 files_struct *fsp,
7114 const struct smb_filename *smb_fname,
7115 bool fail_after_createfile)
7117 off_t size;
7119 if (total_data < 8) {
7120 return NT_STATUS_INVALID_PARAMETER;
7123 size = IVAL(pdata,0);
7124 size |= (((off_t)IVAL(pdata,4)) << 32);
7125 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7126 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7127 (double)size));
7129 return smb_set_file_size(conn, req,
7130 fsp,
7131 smb_fname,
7132 &smb_fname->st,
7133 size,
7134 fail_after_createfile);
7137 /****************************************************************************
7138 Allow a UNIX info mknod.
7139 ****************************************************************************/
7141 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7142 const char *pdata,
7143 int total_data,
7144 const struct smb_filename *smb_fname)
7146 uint32_t file_type = IVAL(pdata,56);
7147 #if defined(HAVE_MAKEDEV)
7148 uint32_t dev_major = IVAL(pdata,60);
7149 uint32_t dev_minor = IVAL(pdata,68);
7150 #endif
7151 SMB_DEV_T dev = (SMB_DEV_T)0;
7152 uint32_t raw_unixmode = IVAL(pdata,84);
7153 NTSTATUS status;
7154 mode_t unixmode;
7156 if (total_data < 100) {
7157 return NT_STATUS_INVALID_PARAMETER;
7160 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7161 PERM_NEW_FILE, &unixmode);
7162 if (!NT_STATUS_IS_OK(status)) {
7163 return status;
7166 #if defined(HAVE_MAKEDEV)
7167 dev = makedev(dev_major, dev_minor);
7168 #endif
7170 switch (file_type) {
7171 #if defined(S_IFIFO)
7172 case UNIX_TYPE_FIFO:
7173 unixmode |= S_IFIFO;
7174 break;
7175 #endif
7176 #if defined(S_IFSOCK)
7177 case UNIX_TYPE_SOCKET:
7178 unixmode |= S_IFSOCK;
7179 break;
7180 #endif
7181 #if defined(S_IFCHR)
7182 case UNIX_TYPE_CHARDEV:
7183 unixmode |= S_IFCHR;
7184 break;
7185 #endif
7186 #if defined(S_IFBLK)
7187 case UNIX_TYPE_BLKDEV:
7188 unixmode |= S_IFBLK;
7189 break;
7190 #endif
7191 default:
7192 return NT_STATUS_INVALID_PARAMETER;
7195 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7196 "%.0f mode 0%o for file %s\n", (double)dev,
7197 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7199 /* Ok - do the mknod. */
7200 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7201 return map_nt_error_from_unix(errno);
7204 /* If any of the other "set" calls fail we
7205 * don't want to end up with a half-constructed mknod.
7208 if (lp_inherit_permissions(SNUM(conn))) {
7209 char *parent;
7210 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7211 &parent, NULL)) {
7212 return NT_STATUS_NO_MEMORY;
7214 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7215 unixmode);
7216 TALLOC_FREE(parent);
7219 return NT_STATUS_OK;
7222 /****************************************************************************
7223 Deal with SMB_SET_FILE_UNIX_BASIC.
7224 ****************************************************************************/
7226 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7227 struct smb_request *req,
7228 const char *pdata,
7229 int total_data,
7230 files_struct *fsp,
7231 const struct smb_filename *smb_fname)
7233 struct smb_file_time ft;
7234 uint32_t raw_unixmode;
7235 mode_t unixmode;
7236 off_t size = 0;
7237 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7238 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7239 NTSTATUS status = NT_STATUS_OK;
7240 bool delete_on_fail = False;
7241 enum perm_type ptype;
7242 files_struct *all_fsps = NULL;
7243 bool modify_mtime = true;
7244 struct file_id id;
7245 struct smb_filename *smb_fname_tmp = NULL;
7246 SMB_STRUCT_STAT sbuf;
7248 ZERO_STRUCT(ft);
7250 if (total_data < 100) {
7251 return NT_STATUS_INVALID_PARAMETER;
7254 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7255 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7256 size=IVAL(pdata,0); /* first 8 Bytes are size */
7257 size |= (((off_t)IVAL(pdata,4)) << 32);
7260 ft.atime = interpret_long_date(pdata+24); /* access_time */
7261 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7262 set_owner = (uid_t)IVAL(pdata,40);
7263 set_grp = (gid_t)IVAL(pdata,48);
7264 raw_unixmode = IVAL(pdata,84);
7266 if (VALID_STAT(smb_fname->st)) {
7267 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7268 ptype = PERM_EXISTING_DIR;
7269 } else {
7270 ptype = PERM_EXISTING_FILE;
7272 } else {
7273 ptype = PERM_NEW_FILE;
7276 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7277 ptype, &unixmode);
7278 if (!NT_STATUS_IS_OK(status)) {
7279 return status;
7282 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7283 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7284 smb_fname_str_dbg(smb_fname), (double)size,
7285 (unsigned int)set_owner, (unsigned int)set_grp,
7286 (int)raw_unixmode));
7288 sbuf = smb_fname->st;
7290 if (!VALID_STAT(sbuf)) {
7292 * The only valid use of this is to create character and block
7293 * devices, and named pipes. This is deprecated (IMHO) and
7294 * a new info level should be used for mknod. JRA.
7297 status = smb_unix_mknod(conn,
7298 pdata,
7299 total_data,
7300 smb_fname);
7301 if (!NT_STATUS_IS_OK(status)) {
7302 return status;
7305 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7306 if (smb_fname_tmp == NULL) {
7307 return NT_STATUS_NO_MEMORY;
7310 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7311 status = map_nt_error_from_unix(errno);
7312 TALLOC_FREE(smb_fname_tmp);
7313 SMB_VFS_UNLINK(conn, smb_fname);
7314 return status;
7317 sbuf = smb_fname_tmp->st;
7318 smb_fname = smb_fname_tmp;
7320 /* Ensure we don't try and change anything else. */
7321 raw_unixmode = SMB_MODE_NO_CHANGE;
7322 size = get_file_size_stat(&sbuf);
7323 ft.atime = sbuf.st_ex_atime;
7324 ft.mtime = sbuf.st_ex_mtime;
7326 * We continue here as we might want to change the
7327 * owner uid/gid.
7329 delete_on_fail = True;
7332 #if 1
7333 /* Horrible backwards compatibility hack as an old server bug
7334 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7335 * */
7337 if (!size) {
7338 size = get_file_size_stat(&sbuf);
7340 #endif
7343 * Deal with the UNIX specific mode set.
7346 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7347 int ret;
7349 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7350 "setting mode 0%o for file %s\n",
7351 (unsigned int)unixmode,
7352 smb_fname_str_dbg(smb_fname)));
7353 if (fsp && fsp->fh->fd != -1) {
7354 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7355 } else {
7356 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7358 if (ret != 0) {
7359 return map_nt_error_from_unix(errno);
7364 * Deal with the UNIX specific uid set.
7367 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7368 (sbuf.st_ex_uid != set_owner)) {
7369 int ret;
7371 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7372 "changing owner %u for path %s\n",
7373 (unsigned int)set_owner,
7374 smb_fname_str_dbg(smb_fname)));
7376 if (fsp && fsp->fh->fd != -1) {
7377 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7378 } else {
7380 * UNIX extensions calls must always operate
7381 * on symlinks.
7383 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7384 set_owner, (gid_t)-1);
7387 if (ret != 0) {
7388 status = map_nt_error_from_unix(errno);
7389 if (delete_on_fail) {
7390 SMB_VFS_UNLINK(conn, smb_fname);
7392 return status;
7397 * Deal with the UNIX specific gid set.
7400 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7401 (sbuf.st_ex_gid != set_grp)) {
7402 int ret;
7404 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7405 "changing group %u for file %s\n",
7406 (unsigned int)set_owner,
7407 smb_fname_str_dbg(smb_fname)));
7408 if (fsp && fsp->fh->fd != -1) {
7409 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7410 } else {
7412 * UNIX extensions calls must always operate
7413 * on symlinks.
7415 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7416 set_grp);
7418 if (ret != 0) {
7419 status = map_nt_error_from_unix(errno);
7420 if (delete_on_fail) {
7421 SMB_VFS_UNLINK(conn, smb_fname);
7423 return status;
7427 /* Deal with any size changes. */
7429 status = smb_set_file_size(conn, req,
7430 fsp,
7431 smb_fname,
7432 &sbuf,
7433 size,
7434 false);
7435 if (!NT_STATUS_IS_OK(status)) {
7436 return status;
7439 /* Deal with any time changes. */
7440 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7441 /* No change, don't cancel anything. */
7442 return status;
7445 id = vfs_file_id_from_sbuf(conn, &sbuf);
7446 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7447 all_fsps = file_find_di_next(all_fsps)) {
7449 * We're setting the time explicitly for UNIX.
7450 * Cancel any pending changes over all handles.
7452 all_fsps->update_write_time_on_close = false;
7453 TALLOC_FREE(all_fsps->update_write_time_event);
7457 * Override the "setting_write_time"
7458 * parameter here as it almost does what
7459 * we need. Just remember if we modified
7460 * mtime and send the notify ourselves.
7462 if (null_timespec(ft.mtime)) {
7463 modify_mtime = false;
7466 status = smb_set_file_time(conn,
7467 fsp,
7468 smb_fname,
7469 &ft,
7470 false);
7471 if (modify_mtime) {
7472 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7473 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7475 return status;
7478 /****************************************************************************
7479 Deal with SMB_SET_FILE_UNIX_INFO2.
7480 ****************************************************************************/
7482 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7483 struct smb_request *req,
7484 const char *pdata,
7485 int total_data,
7486 files_struct *fsp,
7487 const struct smb_filename *smb_fname)
7489 NTSTATUS status;
7490 uint32_t smb_fflags;
7491 uint32_t smb_fmask;
7493 if (total_data < 116) {
7494 return NT_STATUS_INVALID_PARAMETER;
7497 /* Start by setting all the fields that are common between UNIX_BASIC
7498 * and UNIX_INFO2.
7500 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7501 fsp, smb_fname);
7502 if (!NT_STATUS_IS_OK(status)) {
7503 return status;
7506 smb_fflags = IVAL(pdata, 108);
7507 smb_fmask = IVAL(pdata, 112);
7509 /* NB: We should only attempt to alter the file flags if the client
7510 * sends a non-zero mask.
7512 if (smb_fmask != 0) {
7513 int stat_fflags = 0;
7515 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7516 smb_fmask, &stat_fflags)) {
7517 /* Client asked to alter a flag we don't understand. */
7518 return NT_STATUS_INVALID_PARAMETER;
7521 if (fsp && fsp->fh->fd != -1) {
7522 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7523 return NT_STATUS_NOT_SUPPORTED;
7524 } else {
7525 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7526 stat_fflags) != 0) {
7527 return map_nt_error_from_unix(errno);
7532 /* XXX: need to add support for changing the create_time here. You
7533 * can do this for paths on Darwin with setattrlist(2). The right way
7534 * to hook this up is probably by extending the VFS utimes interface.
7537 return NT_STATUS_OK;
7540 /****************************************************************************
7541 Create a directory with POSIX semantics.
7542 ****************************************************************************/
7544 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7545 struct smb_request *req,
7546 char **ppdata,
7547 int total_data,
7548 struct smb_filename *smb_fname,
7549 int *pdata_return_size)
7551 NTSTATUS status = NT_STATUS_OK;
7552 uint32_t raw_unixmode = 0;
7553 uint32_t mod_unixmode = 0;
7554 mode_t unixmode = (mode_t)0;
7555 files_struct *fsp = NULL;
7556 uint16_t info_level_return = 0;
7557 int info;
7558 char *pdata = *ppdata;
7560 if (total_data < 18) {
7561 return NT_STATUS_INVALID_PARAMETER;
7564 raw_unixmode = IVAL(pdata,8);
7565 /* Next 4 bytes are not yet defined. */
7567 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7568 PERM_NEW_DIR, &unixmode);
7569 if (!NT_STATUS_IS_OK(status)) {
7570 return status;
7573 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7575 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7576 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7578 status = SMB_VFS_CREATE_FILE(
7579 conn, /* conn */
7580 req, /* req */
7581 0, /* root_dir_fid */
7582 smb_fname, /* fname */
7583 FILE_READ_ATTRIBUTES, /* access_mask */
7584 FILE_SHARE_NONE, /* share_access */
7585 FILE_CREATE, /* create_disposition*/
7586 FILE_DIRECTORY_FILE, /* create_options */
7587 mod_unixmode, /* file_attributes */
7588 0, /* oplock_request */
7589 NULL, /* lease */
7590 0, /* allocation_size */
7591 0, /* private_flags */
7592 NULL, /* sd */
7593 NULL, /* ea_list */
7594 &fsp, /* result */
7595 &info, /* pinfo */
7596 NULL, NULL); /* create context */
7598 if (NT_STATUS_IS_OK(status)) {
7599 close_file(req, fsp, NORMAL_CLOSE);
7602 info_level_return = SVAL(pdata,16);
7604 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7605 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7606 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7607 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7608 } else {
7609 *pdata_return_size = 12;
7612 /* Realloc the data size */
7613 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7614 if (*ppdata == NULL) {
7615 *pdata_return_size = 0;
7616 return NT_STATUS_NO_MEMORY;
7618 pdata = *ppdata;
7620 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7621 SSVAL(pdata,2,0); /* No fnum. */
7622 SIVAL(pdata,4,info); /* Was directory created. */
7624 switch (info_level_return) {
7625 case SMB_QUERY_FILE_UNIX_BASIC:
7626 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7627 SSVAL(pdata,10,0); /* Padding. */
7628 store_file_unix_basic(conn, pdata + 12, fsp,
7629 &smb_fname->st);
7630 break;
7631 case SMB_QUERY_FILE_UNIX_INFO2:
7632 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7633 SSVAL(pdata,10,0); /* Padding. */
7634 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7635 &smb_fname->st);
7636 break;
7637 default:
7638 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7639 SSVAL(pdata,10,0); /* Padding. */
7640 break;
7643 return status;
7646 /****************************************************************************
7647 Open/Create a file with POSIX semantics.
7648 ****************************************************************************/
7650 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7651 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7653 static NTSTATUS smb_posix_open(connection_struct *conn,
7654 struct smb_request *req,
7655 char **ppdata,
7656 int total_data,
7657 struct smb_filename *smb_fname,
7658 int *pdata_return_size)
7660 bool extended_oplock_granted = False;
7661 char *pdata = *ppdata;
7662 uint32_t flags = 0;
7663 uint32_t wire_open_mode = 0;
7664 uint32_t raw_unixmode = 0;
7665 uint32_t mod_unixmode = 0;
7666 uint32_t create_disp = 0;
7667 uint32_t access_mask = 0;
7668 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7669 NTSTATUS status = NT_STATUS_OK;
7670 mode_t unixmode = (mode_t)0;
7671 files_struct *fsp = NULL;
7672 int oplock_request = 0;
7673 int info = 0;
7674 uint16_t info_level_return = 0;
7676 if (total_data < 18) {
7677 return NT_STATUS_INVALID_PARAMETER;
7680 flags = IVAL(pdata,0);
7681 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7682 if (oplock_request) {
7683 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7686 wire_open_mode = IVAL(pdata,4);
7688 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7689 return smb_posix_mkdir(conn, req,
7690 ppdata,
7691 total_data,
7692 smb_fname,
7693 pdata_return_size);
7696 switch (wire_open_mode & SMB_ACCMODE) {
7697 case SMB_O_RDONLY:
7698 access_mask = SMB_O_RDONLY_MAPPING;
7699 break;
7700 case SMB_O_WRONLY:
7701 access_mask = SMB_O_WRONLY_MAPPING;
7702 break;
7703 case SMB_O_RDWR:
7704 access_mask = (SMB_O_RDONLY_MAPPING|
7705 SMB_O_WRONLY_MAPPING);
7706 break;
7707 default:
7708 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7709 (unsigned int)wire_open_mode ));
7710 return NT_STATUS_INVALID_PARAMETER;
7713 wire_open_mode &= ~SMB_ACCMODE;
7715 /* First take care of O_CREAT|O_EXCL interactions. */
7716 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7717 case (SMB_O_CREAT | SMB_O_EXCL):
7718 /* File exists fail. File not exist create. */
7719 create_disp = FILE_CREATE;
7720 break;
7721 case SMB_O_CREAT:
7722 /* File exists open. File not exist create. */
7723 create_disp = FILE_OPEN_IF;
7724 break;
7725 case SMB_O_EXCL:
7726 /* O_EXCL on its own without O_CREAT is undefined.
7727 We deliberately ignore it as some versions of
7728 Linux CIFSFS can send a bare O_EXCL on the
7729 wire which other filesystems in the kernel
7730 ignore. See bug 9519 for details. */
7732 /* Fallthrough. */
7734 case 0:
7735 /* File exists open. File not exist fail. */
7736 create_disp = FILE_OPEN;
7737 break;
7738 default:
7739 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7740 (unsigned int)wire_open_mode ));
7741 return NT_STATUS_INVALID_PARAMETER;
7744 /* Next factor in the effects of O_TRUNC. */
7745 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7747 if (wire_open_mode & SMB_O_TRUNC) {
7748 switch (create_disp) {
7749 case FILE_CREATE:
7750 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7751 /* Leave create_disp alone as
7752 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7754 /* File exists fail. File not exist create. */
7755 break;
7756 case FILE_OPEN_IF:
7757 /* SMB_O_CREAT | SMB_O_TRUNC */
7758 /* File exists overwrite. File not exist create. */
7759 create_disp = FILE_OVERWRITE_IF;
7760 break;
7761 case FILE_OPEN:
7762 /* SMB_O_TRUNC */
7763 /* File exists overwrite. File not exist fail. */
7764 create_disp = FILE_OVERWRITE;
7765 break;
7766 default:
7767 /* Cannot get here. */
7768 smb_panic("smb_posix_open: logic error");
7769 return NT_STATUS_INVALID_PARAMETER;
7773 raw_unixmode = IVAL(pdata,8);
7774 /* Next 4 bytes are not yet defined. */
7776 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7777 (VALID_STAT(smb_fname->st) ?
7778 PERM_EXISTING_FILE : PERM_NEW_FILE),
7779 &unixmode);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 return status;
7785 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7787 if (wire_open_mode & SMB_O_SYNC) {
7788 create_options |= FILE_WRITE_THROUGH;
7790 if (wire_open_mode & SMB_O_APPEND) {
7791 access_mask |= FILE_APPEND_DATA;
7793 if (wire_open_mode & SMB_O_DIRECT) {
7794 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7797 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7798 VALID_STAT_OF_DIR(smb_fname->st)) {
7799 if (access_mask != SMB_O_RDONLY_MAPPING) {
7800 return NT_STATUS_FILE_IS_A_DIRECTORY;
7802 create_options &= ~FILE_NON_DIRECTORY_FILE;
7803 create_options |= FILE_DIRECTORY_FILE;
7806 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7807 smb_fname_str_dbg(smb_fname),
7808 (unsigned int)wire_open_mode,
7809 (unsigned int)unixmode ));
7811 status = SMB_VFS_CREATE_FILE(
7812 conn, /* conn */
7813 req, /* req */
7814 0, /* root_dir_fid */
7815 smb_fname, /* fname */
7816 access_mask, /* access_mask */
7817 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7818 FILE_SHARE_DELETE),
7819 create_disp, /* create_disposition*/
7820 create_options, /* create_options */
7821 mod_unixmode, /* file_attributes */
7822 oplock_request, /* oplock_request */
7823 NULL, /* lease */
7824 0, /* allocation_size */
7825 0, /* private_flags */
7826 NULL, /* sd */
7827 NULL, /* ea_list */
7828 &fsp, /* result */
7829 &info, /* pinfo */
7830 NULL, NULL); /* create context */
7832 if (!NT_STATUS_IS_OK(status)) {
7833 return status;
7836 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7837 extended_oplock_granted = True;
7840 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7841 extended_oplock_granted = True;
7844 info_level_return = SVAL(pdata,16);
7846 /* Allocate the correct return size. */
7848 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7849 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7850 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7851 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7852 } else {
7853 *pdata_return_size = 12;
7856 /* Realloc the data size */
7857 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7858 if (*ppdata == NULL) {
7859 close_file(req, fsp, ERROR_CLOSE);
7860 *pdata_return_size = 0;
7861 return NT_STATUS_NO_MEMORY;
7863 pdata = *ppdata;
7865 if (extended_oplock_granted) {
7866 if (flags & REQUEST_BATCH_OPLOCK) {
7867 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7868 } else {
7869 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7871 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7872 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7873 } else {
7874 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7877 SSVAL(pdata,2,fsp->fnum);
7878 SIVAL(pdata,4,info); /* Was file created etc. */
7880 switch (info_level_return) {
7881 case SMB_QUERY_FILE_UNIX_BASIC:
7882 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7883 SSVAL(pdata,10,0); /* padding. */
7884 store_file_unix_basic(conn, pdata + 12, fsp,
7885 &smb_fname->st);
7886 break;
7887 case SMB_QUERY_FILE_UNIX_INFO2:
7888 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7889 SSVAL(pdata,10,0); /* padding. */
7890 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7891 &smb_fname->st);
7892 break;
7893 default:
7894 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7895 SSVAL(pdata,10,0); /* padding. */
7896 break;
7898 return NT_STATUS_OK;
7901 /****************************************************************************
7902 Delete a file with POSIX semantics.
7903 ****************************************************************************/
7905 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7906 struct smb_request *req,
7907 const char *pdata,
7908 int total_data,
7909 struct smb_filename *smb_fname)
7911 NTSTATUS status = NT_STATUS_OK;
7912 files_struct *fsp = NULL;
7913 uint16_t flags = 0;
7914 char del = 1;
7915 int info = 0;
7916 int create_options = 0;
7917 int i;
7918 struct share_mode_lock *lck = NULL;
7920 if (total_data < 2) {
7921 return NT_STATUS_INVALID_PARAMETER;
7924 flags = SVAL(pdata,0);
7926 if (!VALID_STAT(smb_fname->st)) {
7927 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7930 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7931 !VALID_STAT_OF_DIR(smb_fname->st)) {
7932 return NT_STATUS_NOT_A_DIRECTORY;
7935 DEBUG(10,("smb_posix_unlink: %s %s\n",
7936 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7937 smb_fname_str_dbg(smb_fname)));
7939 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7940 create_options |= FILE_DIRECTORY_FILE;
7943 status = SMB_VFS_CREATE_FILE(
7944 conn, /* conn */
7945 req, /* req */
7946 0, /* root_dir_fid */
7947 smb_fname, /* fname */
7948 DELETE_ACCESS, /* access_mask */
7949 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7950 FILE_SHARE_DELETE),
7951 FILE_OPEN, /* create_disposition*/
7952 create_options, /* create_options */
7953 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7954 0, /* oplock_request */
7955 NULL, /* lease */
7956 0, /* allocation_size */
7957 0, /* private_flags */
7958 NULL, /* sd */
7959 NULL, /* ea_list */
7960 &fsp, /* result */
7961 &info, /* pinfo */
7962 NULL, NULL); /* create context */
7964 if (!NT_STATUS_IS_OK(status)) {
7965 return status;
7969 * Don't lie to client. If we can't really delete due to
7970 * non-POSIX opens return SHARING_VIOLATION.
7973 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7974 if (lck == NULL) {
7975 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7976 "lock for file %s\n", fsp_str_dbg(fsp)));
7977 close_file(req, fsp, NORMAL_CLOSE);
7978 return NT_STATUS_INVALID_PARAMETER;
7982 * See if others still have the file open. If this is the case, then
7983 * don't delete. If all opens are POSIX delete we can set the delete
7984 * on close disposition.
7986 for (i=0; i<lck->data->num_share_modes; i++) {
7987 struct share_mode_entry *e = &lck->data->share_modes[i];
7988 if (is_valid_share_mode_entry(e)) {
7989 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7990 continue;
7992 if (share_mode_stale_pid(lck->data, i)) {
7993 continue;
7995 /* Fail with sharing violation. */
7996 TALLOC_FREE(lck);
7997 close_file(req, fsp, NORMAL_CLOSE);
7998 return NT_STATUS_SHARING_VIOLATION;
8003 * Set the delete on close.
8005 status = smb_set_file_disposition_info(conn,
8006 &del,
8008 fsp,
8009 smb_fname);
8011 TALLOC_FREE(lck);
8013 if (!NT_STATUS_IS_OK(status)) {
8014 close_file(req, fsp, NORMAL_CLOSE);
8015 return status;
8017 return close_file(req, fsp, NORMAL_CLOSE);
8020 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8021 struct smb_request *req,
8022 TALLOC_CTX *mem_ctx,
8023 uint16_t info_level,
8024 files_struct *fsp,
8025 struct smb_filename *smb_fname,
8026 char **ppdata, int total_data,
8027 int *ret_data_size)
8029 char *pdata = *ppdata;
8030 NTSTATUS status = NT_STATUS_OK;
8031 int data_return_size = 0;
8033 *ret_data_size = 0;
8035 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8036 return NT_STATUS_INVALID_LEVEL;
8039 if (!CAN_WRITE(conn)) {
8040 /* Allow POSIX opens. The open path will deny
8041 * any non-readonly opens. */
8042 if (info_level != SMB_POSIX_PATH_OPEN) {
8043 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8047 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8048 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8049 fsp_fnum_dbg(fsp),
8050 info_level, total_data));
8052 switch (info_level) {
8054 case SMB_INFO_STANDARD:
8056 status = smb_set_info_standard(conn,
8057 pdata,
8058 total_data,
8059 fsp,
8060 smb_fname);
8061 break;
8064 case SMB_INFO_SET_EA:
8066 status = smb_info_set_ea(conn,
8067 pdata,
8068 total_data,
8069 fsp,
8070 smb_fname);
8071 break;
8074 case SMB_SET_FILE_BASIC_INFO:
8075 case SMB_FILE_BASIC_INFORMATION:
8077 status = smb_set_file_basic_info(conn,
8078 pdata,
8079 total_data,
8080 fsp,
8081 smb_fname);
8082 break;
8085 case SMB_FILE_ALLOCATION_INFORMATION:
8086 case SMB_SET_FILE_ALLOCATION_INFO:
8088 status = smb_set_file_allocation_info(conn, req,
8089 pdata,
8090 total_data,
8091 fsp,
8092 smb_fname);
8093 break;
8096 case SMB_FILE_END_OF_FILE_INFORMATION:
8097 case SMB_SET_FILE_END_OF_FILE_INFO:
8100 * XP/Win7 both fail after the createfile with
8101 * SMB_SET_FILE_END_OF_FILE_INFO but not
8102 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8103 * The level is known here, so pass it down
8104 * appropriately.
8106 bool should_fail =
8107 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8109 status = smb_set_file_end_of_file_info(conn, req,
8110 pdata,
8111 total_data,
8112 fsp,
8113 smb_fname,
8114 should_fail);
8115 break;
8118 case SMB_FILE_DISPOSITION_INFORMATION:
8119 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8121 #if 0
8122 /* JRA - We used to just ignore this on a path ?
8123 * Shouldn't this be invalid level on a pathname
8124 * based call ?
8126 if (tran_call != TRANSACT2_SETFILEINFO) {
8127 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8129 #endif
8130 status = smb_set_file_disposition_info(conn,
8131 pdata,
8132 total_data,
8133 fsp,
8134 smb_fname);
8135 break;
8138 case SMB_FILE_POSITION_INFORMATION:
8140 status = smb_file_position_information(conn,
8141 pdata,
8142 total_data,
8143 fsp);
8144 break;
8147 case SMB_FILE_FULL_EA_INFORMATION:
8149 status = smb_set_file_full_ea_info(conn,
8150 pdata,
8151 total_data,
8152 fsp);
8153 break;
8156 /* From tridge Samba4 :
8157 * MODE_INFORMATION in setfileinfo (I have no
8158 * idea what "mode information" on a file is - it takes a value of 0,
8159 * 2, 4 or 6. What could it be?).
8162 case SMB_FILE_MODE_INFORMATION:
8164 status = smb_file_mode_information(conn,
8165 pdata,
8166 total_data);
8167 break;
8171 * CIFS UNIX extensions.
8174 case SMB_SET_FILE_UNIX_BASIC:
8176 status = smb_set_file_unix_basic(conn, req,
8177 pdata,
8178 total_data,
8179 fsp,
8180 smb_fname);
8181 break;
8184 case SMB_SET_FILE_UNIX_INFO2:
8186 status = smb_set_file_unix_info2(conn, req,
8187 pdata,
8188 total_data,
8189 fsp,
8190 smb_fname);
8191 break;
8194 case SMB_SET_FILE_UNIX_LINK:
8196 if (fsp) {
8197 /* We must have a pathname for this. */
8198 return NT_STATUS_INVALID_LEVEL;
8200 status = smb_set_file_unix_link(conn, req, pdata,
8201 total_data, smb_fname);
8202 break;
8205 case SMB_SET_FILE_UNIX_HLINK:
8207 if (fsp) {
8208 /* We must have a pathname for this. */
8209 return NT_STATUS_INVALID_LEVEL;
8211 status = smb_set_file_unix_hlink(conn, req,
8212 pdata, total_data,
8213 smb_fname);
8214 break;
8217 case SMB_FILE_RENAME_INFORMATION:
8219 status = smb_file_rename_information(conn, req,
8220 pdata, total_data,
8221 fsp, smb_fname);
8222 break;
8225 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8227 /* SMB2 rename information. */
8228 status = smb2_file_rename_information(conn, req,
8229 pdata, total_data,
8230 fsp, smb_fname);
8231 break;
8234 case SMB_FILE_LINK_INFORMATION:
8236 status = smb_file_link_information(conn, req,
8237 pdata, total_data,
8238 fsp, smb_fname);
8239 break;
8242 #if defined(HAVE_POSIX_ACLS)
8243 case SMB_SET_POSIX_ACL:
8245 status = smb_set_posix_acl(conn,
8246 pdata,
8247 total_data,
8248 fsp,
8249 smb_fname);
8250 break;
8252 #endif
8254 case SMB_SET_POSIX_LOCK:
8256 if (!fsp) {
8257 return NT_STATUS_INVALID_LEVEL;
8259 status = smb_set_posix_lock(conn, req,
8260 pdata, total_data, fsp);
8261 break;
8264 case SMB_POSIX_PATH_OPEN:
8266 if (fsp) {
8267 /* We must have a pathname for this. */
8268 return NT_STATUS_INVALID_LEVEL;
8271 status = smb_posix_open(conn, req,
8272 ppdata,
8273 total_data,
8274 smb_fname,
8275 &data_return_size);
8276 break;
8279 case SMB_POSIX_PATH_UNLINK:
8281 if (fsp) {
8282 /* We must have a pathname for this. */
8283 return NT_STATUS_INVALID_LEVEL;
8286 status = smb_posix_unlink(conn, req,
8287 pdata,
8288 total_data,
8289 smb_fname);
8290 break;
8293 default:
8294 return NT_STATUS_INVALID_LEVEL;
8297 if (!NT_STATUS_IS_OK(status)) {
8298 return status;
8301 *ret_data_size = data_return_size;
8302 return NT_STATUS_OK;
8305 /****************************************************************************
8306 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8307 ****************************************************************************/
8309 static void call_trans2setfilepathinfo(connection_struct *conn,
8310 struct smb_request *req,
8311 unsigned int tran_call,
8312 char **pparams, int total_params,
8313 char **ppdata, int total_data,
8314 unsigned int max_data_bytes)
8316 char *params = *pparams;
8317 char *pdata = *ppdata;
8318 uint16_t info_level;
8319 struct smb_filename *smb_fname = NULL;
8320 files_struct *fsp = NULL;
8321 NTSTATUS status = NT_STATUS_OK;
8322 int data_return_size = 0;
8324 if (!params) {
8325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8326 return;
8329 if (tran_call == TRANSACT2_SETFILEINFO) {
8330 if (total_params < 4) {
8331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8332 return;
8335 fsp = file_fsp(req, SVAL(params,0));
8336 /* Basic check for non-null fsp. */
8337 if (!check_fsp_open(conn, req, fsp)) {
8338 return;
8340 info_level = SVAL(params,2);
8342 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8343 if (smb_fname == NULL) {
8344 reply_nterror(req, NT_STATUS_NO_MEMORY);
8345 return;
8348 if(fsp->fh->fd == -1) {
8350 * This is actually a SETFILEINFO on a directory
8351 * handle (returned from an NT SMB). NT5.0 seems
8352 * to do this call. JRA.
8354 if (INFO_LEVEL_IS_UNIX(info_level)) {
8355 /* Always do lstat for UNIX calls. */
8356 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8357 DEBUG(3,("call_trans2setfilepathinfo: "
8358 "SMB_VFS_LSTAT of %s failed "
8359 "(%s)\n",
8360 smb_fname_str_dbg(smb_fname),
8361 strerror(errno)));
8362 reply_nterror(req, map_nt_error_from_unix(errno));
8363 return;
8365 } else {
8366 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8367 DEBUG(3,("call_trans2setfilepathinfo: "
8368 "fileinfo of %s failed (%s)\n",
8369 smb_fname_str_dbg(smb_fname),
8370 strerror(errno)));
8371 reply_nterror(req, map_nt_error_from_unix(errno));
8372 return;
8375 } else if (fsp->print_file) {
8377 * Doing a DELETE_ON_CLOSE should cancel a print job.
8379 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8380 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8382 DEBUG(3,("call_trans2setfilepathinfo: "
8383 "Cancelling print job (%s)\n",
8384 fsp_str_dbg(fsp)));
8386 SSVAL(params,0,0);
8387 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8388 *ppdata, 0,
8389 max_data_bytes);
8390 return;
8391 } else {
8392 reply_nterror(req,
8393 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8394 return;
8396 } else {
8398 * Original code - this is an open file.
8400 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8401 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8402 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8403 strerror(errno)));
8404 reply_nterror(req, map_nt_error_from_unix(errno));
8405 return;
8408 } else {
8409 char *fname = NULL;
8410 uint32_t ucf_flags = 0;
8412 /* set path info */
8413 if (total_params < 7) {
8414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8415 return;
8418 info_level = SVAL(params,0);
8419 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8420 total_params - 6, STR_TERMINATE,
8421 &status);
8422 if (!NT_STATUS_IS_OK(status)) {
8423 reply_nterror(req, status);
8424 return;
8427 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8428 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8429 info_level == SMB_FILE_RENAME_INFORMATION ||
8430 info_level == SMB_POSIX_PATH_UNLINK) {
8431 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8434 status = filename_convert(req, conn,
8435 req->flags2 & FLAGS2_DFS_PATHNAMES,
8436 fname,
8437 ucf_flags,
8438 NULL,
8439 &smb_fname);
8440 if (!NT_STATUS_IS_OK(status)) {
8441 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8442 reply_botherror(req,
8443 NT_STATUS_PATH_NOT_COVERED,
8444 ERRSRV, ERRbadpath);
8445 return;
8447 reply_nterror(req, status);
8448 return;
8451 if (INFO_LEVEL_IS_UNIX(info_level)) {
8453 * For CIFS UNIX extensions the target name may not exist.
8456 /* Always do lstat for UNIX calls. */
8457 SMB_VFS_LSTAT(conn, smb_fname);
8459 } else if (!VALID_STAT(smb_fname->st) &&
8460 SMB_VFS_STAT(conn, smb_fname)) {
8461 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8462 "%s failed (%s)\n",
8463 smb_fname_str_dbg(smb_fname),
8464 strerror(errno)));
8465 reply_nterror(req, map_nt_error_from_unix(errno));
8466 return;
8470 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8471 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8472 fsp_fnum_dbg(fsp),
8473 info_level,total_data));
8475 /* Realloc the parameter size */
8476 *pparams = (char *)SMB_REALLOC(*pparams,2);
8477 if (*pparams == NULL) {
8478 reply_nterror(req, NT_STATUS_NO_MEMORY);
8479 return;
8481 params = *pparams;
8483 SSVAL(params,0,0);
8485 status = smbd_do_setfilepathinfo(conn, req, req,
8486 info_level,
8487 fsp,
8488 smb_fname,
8489 ppdata, total_data,
8490 &data_return_size);
8491 if (!NT_STATUS_IS_OK(status)) {
8492 if (open_was_deferred(req->xconn, req->mid)) {
8493 /* We have re-scheduled this call. */
8494 return;
8496 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8497 /* We have re-scheduled this call. */
8498 return;
8500 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8501 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8502 ERRSRV, ERRbadpath);
8503 return;
8505 if (info_level == SMB_POSIX_PATH_OPEN) {
8506 reply_openerror(req, status);
8507 return;
8511 * Invalid EA name needs to return 2 param bytes,
8512 * not a zero-length error packet.
8514 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8515 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8516 max_data_bytes);
8517 } else {
8518 reply_nterror(req, status);
8520 return;
8523 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8524 max_data_bytes);
8526 return;
8529 /****************************************************************************
8530 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8531 ****************************************************************************/
8533 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8534 char **pparams, int total_params,
8535 char **ppdata, int total_data,
8536 unsigned int max_data_bytes)
8538 struct smb_filename *smb_dname = NULL;
8539 char *params = *pparams;
8540 char *pdata = *ppdata;
8541 char *directory = NULL;
8542 NTSTATUS status = NT_STATUS_OK;
8543 struct ea_list *ea_list = NULL;
8544 TALLOC_CTX *ctx = talloc_tos();
8546 if (!CAN_WRITE(conn)) {
8547 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8548 return;
8551 if (total_params < 5) {
8552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8553 return;
8556 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8557 total_params - 4, STR_TERMINATE,
8558 &status);
8559 if (!NT_STATUS_IS_OK(status)) {
8560 reply_nterror(req, status);
8561 return;
8564 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8566 status = filename_convert(ctx,
8567 conn,
8568 req->flags2 & FLAGS2_DFS_PATHNAMES,
8569 directory,
8571 NULL,
8572 &smb_dname);
8574 if (!NT_STATUS_IS_OK(status)) {
8575 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8576 reply_botherror(req,
8577 NT_STATUS_PATH_NOT_COVERED,
8578 ERRSRV, ERRbadpath);
8579 return;
8581 reply_nterror(req, status);
8582 return;
8586 * OS/2 workplace shell seems to send SET_EA requests of "null"
8587 * length (4 bytes containing IVAL 4).
8588 * They seem to have no effect. Bug #3212. JRA.
8591 if (total_data && (total_data != 4)) {
8592 /* Any data in this call is an EA list. */
8593 if (total_data < 10) {
8594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8595 goto out;
8598 if (IVAL(pdata,0) > total_data) {
8599 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8600 IVAL(pdata,0), (unsigned int)total_data));
8601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8602 goto out;
8605 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8606 total_data - 4);
8607 if (!ea_list) {
8608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8609 goto out;
8612 if (!lp_ea_support(SNUM(conn))) {
8613 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8614 goto out;
8617 /* If total_data == 4 Windows doesn't care what values
8618 * are placed in that field, it just ignores them.
8619 * The System i QNTC IBM SMB client puts bad values here,
8620 * so ignore them. */
8622 status = create_directory(conn, req, smb_dname);
8624 if (!NT_STATUS_IS_OK(status)) {
8625 reply_nterror(req, status);
8626 goto out;
8629 /* Try and set any given EA. */
8630 if (ea_list) {
8631 status = set_ea(conn, NULL, smb_dname, ea_list);
8632 if (!NT_STATUS_IS_OK(status)) {
8633 reply_nterror(req, status);
8634 goto out;
8638 /* Realloc the parameter and data sizes */
8639 *pparams = (char *)SMB_REALLOC(*pparams,2);
8640 if(*pparams == NULL) {
8641 reply_nterror(req, NT_STATUS_NO_MEMORY);
8642 goto out;
8644 params = *pparams;
8646 SSVAL(params,0,0);
8648 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8650 out:
8651 TALLOC_FREE(smb_dname);
8652 return;
8655 /****************************************************************************
8656 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8657 We don't actually do this - we just send a null response.
8658 ****************************************************************************/
8660 static void call_trans2findnotifyfirst(connection_struct *conn,
8661 struct smb_request *req,
8662 char **pparams, int total_params,
8663 char **ppdata, int total_data,
8664 unsigned int max_data_bytes)
8666 char *params = *pparams;
8667 uint16_t info_level;
8669 if (total_params < 6) {
8670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8671 return;
8674 info_level = SVAL(params,4);
8675 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8677 switch (info_level) {
8678 case 1:
8679 case 2:
8680 break;
8681 default:
8682 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8683 return;
8686 /* Realloc the parameter and data sizes */
8687 *pparams = (char *)SMB_REALLOC(*pparams,6);
8688 if (*pparams == NULL) {
8689 reply_nterror(req, NT_STATUS_NO_MEMORY);
8690 return;
8692 params = *pparams;
8694 SSVAL(params,0,fnf_handle);
8695 SSVAL(params,2,0); /* No changes */
8696 SSVAL(params,4,0); /* No EA errors */
8698 fnf_handle++;
8700 if(fnf_handle == 0)
8701 fnf_handle = 257;
8703 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8705 return;
8708 /****************************************************************************
8709 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8710 changes). Currently this does nothing.
8711 ****************************************************************************/
8713 static void call_trans2findnotifynext(connection_struct *conn,
8714 struct smb_request *req,
8715 char **pparams, int total_params,
8716 char **ppdata, int total_data,
8717 unsigned int max_data_bytes)
8719 char *params = *pparams;
8721 DEBUG(3,("call_trans2findnotifynext\n"));
8723 /* Realloc the parameter and data sizes */
8724 *pparams = (char *)SMB_REALLOC(*pparams,4);
8725 if (*pparams == NULL) {
8726 reply_nterror(req, NT_STATUS_NO_MEMORY);
8727 return;
8729 params = *pparams;
8731 SSVAL(params,0,0); /* No changes */
8732 SSVAL(params,2,0); /* No EA errors */
8734 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8736 return;
8739 /****************************************************************************
8740 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8741 ****************************************************************************/
8743 static void call_trans2getdfsreferral(connection_struct *conn,
8744 struct smb_request *req,
8745 char **pparams, int total_params,
8746 char **ppdata, int total_data,
8747 unsigned int max_data_bytes)
8749 char *params = *pparams;
8750 char *pathname = NULL;
8751 int reply_size = 0;
8752 int max_referral_level;
8753 NTSTATUS status = NT_STATUS_OK;
8754 TALLOC_CTX *ctx = talloc_tos();
8756 DEBUG(10,("call_trans2getdfsreferral\n"));
8758 if (total_params < 3) {
8759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8760 return;
8763 max_referral_level = SVAL(params,0);
8765 if(!lp_host_msdfs()) {
8766 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8767 return;
8770 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8771 total_params - 2, STR_TERMINATE);
8772 if (!pathname) {
8773 reply_nterror(req, NT_STATUS_NOT_FOUND);
8774 return;
8776 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8777 ppdata,&status)) < 0) {
8778 reply_nterror(req, status);
8779 return;
8782 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8783 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8784 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8786 return;
8789 #define LMCAT_SPL 0x53
8790 #define LMFUNC_GETJOBID 0x60
8792 /****************************************************************************
8793 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8794 ****************************************************************************/
8796 static void call_trans2ioctl(connection_struct *conn,
8797 struct smb_request *req,
8798 char **pparams, int total_params,
8799 char **ppdata, int total_data,
8800 unsigned int max_data_bytes)
8802 char *pdata = *ppdata;
8803 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8804 NTSTATUS status;
8805 size_t len = 0;
8807 /* check for an invalid fid before proceeding */
8809 if (!fsp) {
8810 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8811 return;
8814 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8815 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8816 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8817 if (*ppdata == NULL) {
8818 reply_nterror(req, NT_STATUS_NO_MEMORY);
8819 return;
8821 pdata = *ppdata;
8823 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8824 CAN ACCEPT THIS IN UNICODE. JRA. */
8826 /* Job number */
8827 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8829 status = srvstr_push(pdata, req->flags2, pdata + 2,
8830 lp_netbios_name(), 15,
8831 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8832 if (!NT_STATUS_IS_OK(status)) {
8833 reply_nterror(req, status);
8834 return;
8836 status = srvstr_push(pdata, req->flags2, pdata+18,
8837 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8838 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8839 if (!NT_STATUS_IS_OK(status)) {
8840 reply_nterror(req, status);
8841 return;
8843 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8844 max_data_bytes);
8845 return;
8848 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8849 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8852 /****************************************************************************
8853 Reply to a SMBfindclose (stop trans2 directory search).
8854 ****************************************************************************/
8856 void reply_findclose(struct smb_request *req)
8858 int dptr_num;
8859 struct smbd_server_connection *sconn = req->sconn;
8861 START_PROFILE(SMBfindclose);
8863 if (req->wct < 1) {
8864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8865 END_PROFILE(SMBfindclose);
8866 return;
8869 dptr_num = SVALS(req->vwv+0, 0);
8871 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8873 dptr_close(sconn, &dptr_num);
8875 reply_outbuf(req, 0, 0);
8877 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8879 END_PROFILE(SMBfindclose);
8880 return;
8883 /****************************************************************************
8884 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8885 ****************************************************************************/
8887 void reply_findnclose(struct smb_request *req)
8889 int dptr_num;
8891 START_PROFILE(SMBfindnclose);
8893 if (req->wct < 1) {
8894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8895 END_PROFILE(SMBfindnclose);
8896 return;
8899 dptr_num = SVAL(req->vwv+0, 0);
8901 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8903 /* We never give out valid handles for a
8904 findnotifyfirst - so any dptr_num is ok here.
8905 Just ignore it. */
8907 reply_outbuf(req, 0, 0);
8909 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8911 END_PROFILE(SMBfindnclose);
8912 return;
8915 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8916 struct trans_state *state)
8918 if (get_Protocol() >= PROTOCOL_NT1) {
8919 req->flags2 |= 0x40; /* IS_LONG_NAME */
8920 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8923 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8924 if (state->call != TRANSACT2_QFSINFO &&
8925 state->call != TRANSACT2_SETFSINFO) {
8926 DEBUG(0,("handle_trans2: encryption required "
8927 "with call 0x%x\n",
8928 (unsigned int)state->call));
8929 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8930 return;
8934 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8936 /* Now we must call the relevant TRANS2 function */
8937 switch(state->call) {
8938 case TRANSACT2_OPEN:
8940 START_PROFILE(Trans2_open);
8941 call_trans2open(conn, req,
8942 &state->param, state->total_param,
8943 &state->data, state->total_data,
8944 state->max_data_return);
8945 END_PROFILE(Trans2_open);
8946 break;
8949 case TRANSACT2_FINDFIRST:
8951 START_PROFILE(Trans2_findfirst);
8952 call_trans2findfirst(conn, req,
8953 &state->param, state->total_param,
8954 &state->data, state->total_data,
8955 state->max_data_return);
8956 END_PROFILE(Trans2_findfirst);
8957 break;
8960 case TRANSACT2_FINDNEXT:
8962 START_PROFILE(Trans2_findnext);
8963 call_trans2findnext(conn, req,
8964 &state->param, state->total_param,
8965 &state->data, state->total_data,
8966 state->max_data_return);
8967 END_PROFILE(Trans2_findnext);
8968 break;
8971 case TRANSACT2_QFSINFO:
8973 START_PROFILE(Trans2_qfsinfo);
8974 call_trans2qfsinfo(conn, req,
8975 &state->param, state->total_param,
8976 &state->data, state->total_data,
8977 state->max_data_return);
8978 END_PROFILE(Trans2_qfsinfo);
8979 break;
8982 case TRANSACT2_SETFSINFO:
8984 START_PROFILE(Trans2_setfsinfo);
8985 call_trans2setfsinfo(conn, req,
8986 &state->param, state->total_param,
8987 &state->data, state->total_data,
8988 state->max_data_return);
8989 END_PROFILE(Trans2_setfsinfo);
8990 break;
8993 case TRANSACT2_QPATHINFO:
8994 case TRANSACT2_QFILEINFO:
8996 START_PROFILE(Trans2_qpathinfo);
8997 call_trans2qfilepathinfo(conn, req, state->call,
8998 &state->param, state->total_param,
8999 &state->data, state->total_data,
9000 state->max_data_return);
9001 END_PROFILE(Trans2_qpathinfo);
9002 break;
9005 case TRANSACT2_SETPATHINFO:
9006 case TRANSACT2_SETFILEINFO:
9008 START_PROFILE(Trans2_setpathinfo);
9009 call_trans2setfilepathinfo(conn, req, state->call,
9010 &state->param, state->total_param,
9011 &state->data, state->total_data,
9012 state->max_data_return);
9013 END_PROFILE(Trans2_setpathinfo);
9014 break;
9017 case TRANSACT2_FINDNOTIFYFIRST:
9019 START_PROFILE(Trans2_findnotifyfirst);
9020 call_trans2findnotifyfirst(conn, req,
9021 &state->param, state->total_param,
9022 &state->data, state->total_data,
9023 state->max_data_return);
9024 END_PROFILE(Trans2_findnotifyfirst);
9025 break;
9028 case TRANSACT2_FINDNOTIFYNEXT:
9030 START_PROFILE(Trans2_findnotifynext);
9031 call_trans2findnotifynext(conn, req,
9032 &state->param, state->total_param,
9033 &state->data, state->total_data,
9034 state->max_data_return);
9035 END_PROFILE(Trans2_findnotifynext);
9036 break;
9039 case TRANSACT2_MKDIR:
9041 START_PROFILE(Trans2_mkdir);
9042 call_trans2mkdir(conn, req,
9043 &state->param, state->total_param,
9044 &state->data, state->total_data,
9045 state->max_data_return);
9046 END_PROFILE(Trans2_mkdir);
9047 break;
9050 case TRANSACT2_GET_DFS_REFERRAL:
9052 START_PROFILE(Trans2_get_dfs_referral);
9053 call_trans2getdfsreferral(conn, req,
9054 &state->param, state->total_param,
9055 &state->data, state->total_data,
9056 state->max_data_return);
9057 END_PROFILE(Trans2_get_dfs_referral);
9058 break;
9061 case TRANSACT2_IOCTL:
9063 START_PROFILE(Trans2_ioctl);
9064 call_trans2ioctl(conn, req,
9065 &state->param, state->total_param,
9066 &state->data, state->total_data,
9067 state->max_data_return);
9068 END_PROFILE(Trans2_ioctl);
9069 break;
9072 default:
9073 /* Error in request */
9074 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9075 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9079 /****************************************************************************
9080 Reply to a SMBtrans2.
9081 ****************************************************************************/
9083 void reply_trans2(struct smb_request *req)
9085 connection_struct *conn = req->conn;
9086 unsigned int dsoff;
9087 unsigned int dscnt;
9088 unsigned int psoff;
9089 unsigned int pscnt;
9090 unsigned int tran_call;
9091 struct trans_state *state;
9092 NTSTATUS result;
9094 START_PROFILE(SMBtrans2);
9096 if (req->wct < 14) {
9097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9098 END_PROFILE(SMBtrans2);
9099 return;
9102 dsoff = SVAL(req->vwv+12, 0);
9103 dscnt = SVAL(req->vwv+11, 0);
9104 psoff = SVAL(req->vwv+10, 0);
9105 pscnt = SVAL(req->vwv+9, 0);
9106 tran_call = SVAL(req->vwv+14, 0);
9108 result = allow_new_trans(conn->pending_trans, req->mid);
9109 if (!NT_STATUS_IS_OK(result)) {
9110 DEBUG(2, ("Got invalid trans2 request: %s\n",
9111 nt_errstr(result)));
9112 reply_nterror(req, result);
9113 END_PROFILE(SMBtrans2);
9114 return;
9117 if (IS_IPC(conn)) {
9118 switch (tran_call) {
9119 /* List the allowed trans2 calls on IPC$ */
9120 case TRANSACT2_OPEN:
9121 case TRANSACT2_GET_DFS_REFERRAL:
9122 case TRANSACT2_QFILEINFO:
9123 case TRANSACT2_QFSINFO:
9124 case TRANSACT2_SETFSINFO:
9125 break;
9126 default:
9127 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9128 END_PROFILE(SMBtrans2);
9129 return;
9133 if ((state = talloc(conn, struct trans_state)) == NULL) {
9134 DEBUG(0, ("talloc failed\n"));
9135 reply_nterror(req, NT_STATUS_NO_MEMORY);
9136 END_PROFILE(SMBtrans2);
9137 return;
9140 state->cmd = SMBtrans2;
9142 state->mid = req->mid;
9143 state->vuid = req->vuid;
9144 state->setup_count = SVAL(req->vwv+13, 0);
9145 state->setup = NULL;
9146 state->total_param = SVAL(req->vwv+0, 0);
9147 state->param = NULL;
9148 state->total_data = SVAL(req->vwv+1, 0);
9149 state->data = NULL;
9150 state->max_param_return = SVAL(req->vwv+2, 0);
9151 state->max_data_return = SVAL(req->vwv+3, 0);
9152 state->max_setup_return = SVAL(req->vwv+4, 0);
9153 state->close_on_completion = BITSETW(req->vwv+5, 0);
9154 state->one_way = BITSETW(req->vwv+5, 1);
9156 state->call = tran_call;
9158 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9159 is so as a sanity check */
9160 if (state->setup_count != 1) {
9162 * Need to have rc=0 for ioctl to get job id for OS/2.
9163 * Network printing will fail if function is not successful.
9164 * Similar function in reply.c will be used if protocol
9165 * is LANMAN1.0 instead of LM1.2X002.
9166 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9167 * outbuf doesn't have to be set(only job id is used).
9169 if ( (state->setup_count == 4)
9170 && (tran_call == TRANSACT2_IOCTL)
9171 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9172 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9173 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9174 } else {
9175 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9176 DEBUG(2,("Transaction is %d\n",tran_call));
9177 TALLOC_FREE(state);
9178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9179 END_PROFILE(SMBtrans2);
9180 return;
9184 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9185 goto bad_param;
9187 if (state->total_data) {
9189 if (trans_oob(state->total_data, 0, dscnt)
9190 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9191 goto bad_param;
9194 /* Can't use talloc here, the core routines do realloc on the
9195 * params and data. */
9196 state->data = (char *)SMB_MALLOC(state->total_data);
9197 if (state->data == NULL) {
9198 DEBUG(0,("reply_trans2: data malloc fail for %u "
9199 "bytes !\n", (unsigned int)state->total_data));
9200 TALLOC_FREE(state);
9201 reply_nterror(req, NT_STATUS_NO_MEMORY);
9202 END_PROFILE(SMBtrans2);
9203 return;
9206 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9209 if (state->total_param) {
9211 if (trans_oob(state->total_param, 0, pscnt)
9212 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9213 goto bad_param;
9216 /* Can't use talloc here, the core routines do realloc on the
9217 * params and data. */
9218 state->param = (char *)SMB_MALLOC(state->total_param);
9219 if (state->param == NULL) {
9220 DEBUG(0,("reply_trans: param malloc fail for %u "
9221 "bytes !\n", (unsigned int)state->total_param));
9222 SAFE_FREE(state->data);
9223 TALLOC_FREE(state);
9224 reply_nterror(req, NT_STATUS_NO_MEMORY);
9225 END_PROFILE(SMBtrans2);
9226 return;
9229 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9232 state->received_data = dscnt;
9233 state->received_param = pscnt;
9235 if ((state->received_param == state->total_param) &&
9236 (state->received_data == state->total_data)) {
9238 handle_trans2(conn, req, state);
9240 SAFE_FREE(state->data);
9241 SAFE_FREE(state->param);
9242 TALLOC_FREE(state);
9243 END_PROFILE(SMBtrans2);
9244 return;
9247 DLIST_ADD(conn->pending_trans, state);
9249 /* We need to send an interim response then receive the rest
9250 of the parameter/data bytes */
9251 reply_outbuf(req, 0, 0);
9252 show_msg((char *)req->outbuf);
9253 END_PROFILE(SMBtrans2);
9254 return;
9256 bad_param:
9258 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9259 SAFE_FREE(state->data);
9260 SAFE_FREE(state->param);
9261 TALLOC_FREE(state);
9262 END_PROFILE(SMBtrans2);
9263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9267 /****************************************************************************
9268 Reply to a SMBtranss2
9269 ****************************************************************************/
9271 void reply_transs2(struct smb_request *req)
9273 connection_struct *conn = req->conn;
9274 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9275 struct trans_state *state;
9277 START_PROFILE(SMBtranss2);
9279 show_msg((const char *)req->inbuf);
9281 /* Windows clients expect all replies to
9282 a transact secondary (SMBtranss2 0x33)
9283 to have a command code of transact
9284 (SMBtrans2 0x32). See bug #8989
9285 and also [MS-CIFS] section 2.2.4.47.2
9286 for details.
9288 req->cmd = SMBtrans2;
9290 if (req->wct < 8) {
9291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9292 END_PROFILE(SMBtranss2);
9293 return;
9296 for (state = conn->pending_trans; state != NULL;
9297 state = state->next) {
9298 if (state->mid == req->mid) {
9299 break;
9303 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9304 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9305 END_PROFILE(SMBtranss2);
9306 return;
9309 /* Revise state->total_param and state->total_data in case they have
9310 changed downwards */
9312 if (SVAL(req->vwv+0, 0) < state->total_param)
9313 state->total_param = SVAL(req->vwv+0, 0);
9314 if (SVAL(req->vwv+1, 0) < state->total_data)
9315 state->total_data = SVAL(req->vwv+1, 0);
9317 pcnt = SVAL(req->vwv+2, 0);
9318 poff = SVAL(req->vwv+3, 0);
9319 pdisp = SVAL(req->vwv+4, 0);
9321 dcnt = SVAL(req->vwv+5, 0);
9322 doff = SVAL(req->vwv+6, 0);
9323 ddisp = SVAL(req->vwv+7, 0);
9325 state->received_param += pcnt;
9326 state->received_data += dcnt;
9328 if ((state->received_data > state->total_data) ||
9329 (state->received_param > state->total_param))
9330 goto bad_param;
9332 if (pcnt) {
9333 if (trans_oob(state->total_param, pdisp, pcnt)
9334 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9335 goto bad_param;
9337 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9340 if (dcnt) {
9341 if (trans_oob(state->total_data, ddisp, dcnt)
9342 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9343 goto bad_param;
9345 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9348 if ((state->received_param < state->total_param) ||
9349 (state->received_data < state->total_data)) {
9350 END_PROFILE(SMBtranss2);
9351 return;
9354 handle_trans2(conn, req, state);
9356 DLIST_REMOVE(conn->pending_trans, state);
9357 SAFE_FREE(state->data);
9358 SAFE_FREE(state->param);
9359 TALLOC_FREE(state);
9361 END_PROFILE(SMBtranss2);
9362 return;
9364 bad_param:
9366 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9367 DLIST_REMOVE(conn->pending_trans, state);
9368 SAFE_FREE(state->data);
9369 SAFE_FREE(state->param);
9370 TALLOC_FREE(state);
9371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9372 END_PROFILE(SMBtranss2);
9373 return;