Ensure we never return an EA name to a Windows client it can't handle.
[Samba.git] / source3 / smbd / trans2.c
blobf12bd8fb5188e586ec4774292426bbde0acd9aab
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 "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 access_mask);
71 if (!NT_STATUS_IS_OK(status)) {
72 return status;
75 return NT_STATUS_OK;
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
92 return val;
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
103 uint64_t file_index;
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
109 return file_index;
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
125 SAMBA_XATTR_MARKER,
126 XATTR_NTACL_NAME,
127 NULL
130 int i;
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
134 return true;
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
138 return true;
140 return false;
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
153 char *val = NULL;
154 ssize_t sizeret;
156 again:
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
159 if (!val) {
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 } else {
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
170 attr_size = 65536;
171 goto again;
174 if (sizeret == -1) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
181 pea->flags = 0;
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
184 } else {
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
188 TALLOC_FREE(val);
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
193 return NT_STATUS_OK;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
204 char *p;
205 char **names, **tmp;
206 size_t num_names;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
214 return NT_STATUS_OK;
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
222 if (names == NULL) {
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
233 TALLOC_FREE(names);
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
239 ea_namelist_size);
240 } else {
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
242 ea_namelist_size);
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
248 else {
249 break;
253 if (sizeret == -1) {
254 TALLOC_FREE(names);
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
261 if (sizeret == 0) {
262 TALLOC_FREE(names);
263 if (pnames) {
264 *pnames = NULL;
266 *pnum_names = 0;
267 return NT_STATUS_OK;
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
275 TALLOC_FREE(names);
276 return NT_STATUS_INTERNAL_ERROR;
280 * count the names
282 num_names = 0;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
285 num_names += 1;
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
289 if (tmp == NULL) {
290 DEBUG(0, ("talloc failed\n"));
291 TALLOC_FREE(names);
292 return NT_STATUS_NO_MEMORY;
295 names = tmp;
296 num_names = 0;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
302 if (pnames) {
303 *pnames = names;
304 } else {
305 TALLOC_FREE(names);
307 *pnum_names = num_names;
308 return NT_STATUS_OK;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
318 /* Get a list of all xattrs. Max namesize is 64k. */
319 size_t i, num_names;
320 char **names;
321 struct ea_list *ea_list_head = NULL;
322 NTSTATUS status;
324 *pea_total_len = 0;
325 *ea_list = NULL;
327 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
328 &names, &num_names);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (num_names == 0) {
335 *ea_list = NULL;
336 return NT_STATUS_OK;
339 for (i=0; i<num_names; i++) {
340 struct ea_list *listp;
341 fstring dos_ea_name;
343 if (strnequal(names[i], "system.", 7)
344 || samba_private_attr_name(names[i]))
345 continue;
348 * Filter out any underlying POSIX EA names
349 * that a Windows client can't handle.
351 if (!lp_posix_pathnames() &&
352 is_invalid_windows_ea_name(names[i])) {
353 continue;
356 listp = talloc(mem_ctx, struct ea_list);
357 if (listp == NULL) {
358 return NT_STATUS_NO_MEMORY;
361 status = get_ea_value(listp, conn, fsp,
362 fname, names[i],
363 &listp->ea);
365 if (!NT_STATUS_IS_OK(status)) {
366 TALLOC_FREE(listp);
367 return status;
370 if (listp->ea.value.length == 0) {
372 * We can never return a zero length EA.
373 * Windows reports the EA's as corrupted.
375 TALLOC_FREE(listp);
376 continue;
379 push_ascii_fstring(dos_ea_name, listp->ea.name);
381 *pea_total_len +=
382 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
384 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
385 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
386 (unsigned int)listp->ea.value.length));
388 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
392 /* Add on 4 for total length. */
393 if (*pea_total_len) {
394 *pea_total_len += 4;
397 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
398 (unsigned int)*pea_total_len));
400 *ea_list = ea_list_head;
401 return NT_STATUS_OK;
404 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
405 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
407 *pea_total_len = 0;
408 *ea_list = NULL;
410 if (!lp_ea_support(SNUM(conn))) {
411 return NT_STATUS_OK;
414 if (is_ntfs_stream_smb_fname(smb_fname)) {
415 return NT_STATUS_INVALID_PARAMETER;
418 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
421 /****************************************************************************
422 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
423 that was filled.
424 ****************************************************************************/
426 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
427 connection_struct *conn, struct ea_list *ea_list)
429 unsigned int ret_data_size = 4;
430 char *p = pdata;
432 SMB_ASSERT(total_data_size >= 4);
434 if (!lp_ea_support(SNUM(conn))) {
435 SIVAL(pdata,4,0);
436 return 4;
439 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
440 size_t dos_namelen;
441 fstring dos_ea_name;
442 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
443 dos_namelen = strlen(dos_ea_name);
444 if (dos_namelen > 255 || dos_namelen == 0) {
445 break;
447 if (ea_list->ea.value.length > 65535) {
448 break;
450 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
451 break;
454 /* We know we have room. */
455 SCVAL(p,0,ea_list->ea.flags);
456 SCVAL(p,1,dos_namelen);
457 SSVAL(p,2,ea_list->ea.value.length);
458 strlcpy(p+4, dos_ea_name, dos_namelen+1);
459 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
461 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
462 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 ret_data_size = PTR_DIFF(p, pdata);
466 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
467 SIVAL(pdata,0,ret_data_size);
468 return ret_data_size;
471 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
472 char *pdata,
473 unsigned int total_data_size,
474 unsigned int *ret_data_size,
475 connection_struct *conn,
476 struct ea_list *ea_list)
478 uint8_t *p = (uint8_t *)pdata;
479 uint8_t *last_start = NULL;
480 bool do_store_data = (pdata != NULL);
482 *ret_data_size = 0;
484 if (!lp_ea_support(SNUM(conn))) {
485 return NT_STATUS_NO_EAS_ON_FILE;
488 for (; ea_list; ea_list = ea_list->next) {
489 size_t dos_namelen;
490 fstring dos_ea_name;
491 size_t this_size;
492 size_t pad = 0;
494 if (last_start != NULL && do_store_data) {
495 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
497 last_start = p;
499 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
500 dos_namelen = strlen(dos_ea_name);
501 if (dos_namelen > 255 || dos_namelen == 0) {
502 return NT_STATUS_INTERNAL_ERROR;
504 if (ea_list->ea.value.length > 65535) {
505 return NT_STATUS_INTERNAL_ERROR;
508 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
510 if (ea_list->next) {
511 pad = (4 - (this_size % 4)) % 4;
512 this_size += pad;
515 if (do_store_data) {
516 if (this_size > total_data_size) {
517 return NT_STATUS_INFO_LENGTH_MISMATCH;
520 /* We know we have room. */
521 SIVAL(p, 0x00, 0); /* next offset */
522 SCVAL(p, 0x04, ea_list->ea.flags);
523 SCVAL(p, 0x05, dos_namelen);
524 SSVAL(p, 0x06, ea_list->ea.value.length);
525 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
526 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
527 if (pad) {
528 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
529 '\0',
530 pad);
532 total_data_size -= this_size;
535 p += this_size;
538 *ret_data_size = PTR_DIFF(p, pdata);
539 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
540 return NT_STATUS_OK;
543 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
545 size_t total_ea_len = 0;
546 TALLOC_CTX *mem_ctx;
547 struct ea_list *ea_list = NULL;
549 if (!lp_ea_support(SNUM(conn))) {
550 return 0;
552 mem_ctx = talloc_stackframe();
554 /* If this is a stream fsp, then we need to instead find the
555 * estimated ea len from the main file, not the stream
556 * (streams cannot have EAs), but the estimate isn't just 0 in
557 * this case! */
558 if (is_ntfs_stream_smb_fname(smb_fname)) {
559 fsp = NULL;
561 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
562 if(conn->sconn->using_smb2) {
563 NTSTATUS status;
564 unsigned int ret_data_size;
566 * We're going to be using fill_ea_chained_buffer() to
567 * marshall EA's - this size is significantly larger
568 * than the SMB1 buffer. Re-calculate the size without
569 * marshalling.
571 status = fill_ea_chained_buffer(mem_ctx,
572 NULL,
574 &ret_data_size,
575 conn,
576 ea_list);
577 if (!NT_STATUS_IS_OK(status)) {
578 ret_data_size = 0;
580 total_ea_len = ret_data_size;
582 TALLOC_FREE(mem_ctx);
583 return total_ea_len;
586 /****************************************************************************
587 Ensure the EA name is case insensitive by matching any existing EA name.
588 ****************************************************************************/
590 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
592 size_t total_ea_len;
593 TALLOC_CTX *mem_ctx = talloc_tos();
594 struct ea_list *ea_list;
595 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
596 if (!NT_STATUS_IS_OK(status)) {
597 return;
600 for (; ea_list; ea_list = ea_list->next) {
601 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
602 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
603 &unix_ea_name[5], ea_list->ea.name));
604 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
605 break;
610 /****************************************************************************
611 Set or delete an extended attribute.
612 ****************************************************************************/
614 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
615 const struct smb_filename *smb_fname, struct ea_list *ea_list)
617 NTSTATUS status;
618 char *fname = NULL;
620 if (!lp_ea_support(SNUM(conn))) {
621 return NT_STATUS_EAS_NOT_SUPPORTED;
624 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
625 if (!NT_STATUS_IS_OK(status)) {
626 return status;
629 /* Setting EAs on streams isn't supported. */
630 if (is_ntfs_stream_smb_fname(smb_fname)) {
631 return NT_STATUS_INVALID_PARAMETER;
635 * Filter out invalid Windows EA names - before
636 * we set *any* of them.
639 if (ea_list_has_invalid_name(ea_list)) {
640 return STATUS_INVALID_EA_NAME;
643 fname = smb_fname->base_name;
645 for (;ea_list; ea_list = ea_list->next) {
646 int ret;
647 fstring unix_ea_name;
649 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
650 fstrcat(unix_ea_name, ea_list->ea.name);
652 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
654 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
656 if (samba_private_attr_name(unix_ea_name)) {
657 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
658 return NT_STATUS_ACCESS_DENIED;
661 if (ea_list->ea.value.length == 0) {
662 /* Remove the attribute. */
663 if (fsp && (fsp->fh->fd != -1)) {
664 DEBUG(10,("set_ea: deleting ea name %s on "
665 "file %s by file descriptor.\n",
666 unix_ea_name, fsp_str_dbg(fsp)));
667 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
668 } else {
669 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
670 unix_ea_name, fname));
671 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
673 #ifdef ENOATTR
674 /* Removing a non existent attribute always succeeds. */
675 if (ret == -1 && errno == ENOATTR) {
676 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
677 unix_ea_name));
678 ret = 0;
680 #endif
681 } else {
682 if (fsp && (fsp->fh->fd != -1)) {
683 DEBUG(10,("set_ea: setting ea name %s on file "
684 "%s by file descriptor.\n",
685 unix_ea_name, fsp_str_dbg(fsp)));
686 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
687 ea_list->ea.value.data, ea_list->ea.value.length, 0);
688 } else {
689 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
690 unix_ea_name, fname));
691 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
692 ea_list->ea.value.data, ea_list->ea.value.length, 0);
696 if (ret == -1) {
697 #ifdef ENOTSUP
698 if (errno == ENOTSUP) {
699 return NT_STATUS_EAS_NOT_SUPPORTED;
701 #endif
702 return map_nt_error_from_unix(errno);
706 return NT_STATUS_OK;
708 /****************************************************************************
709 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
710 ****************************************************************************/
712 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
714 struct ea_list *ea_list_head = NULL;
715 size_t converted_size, offset = 0;
717 while (offset + 2 < data_size) {
718 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
719 unsigned int namelen = CVAL(pdata,offset);
721 offset++; /* Go past the namelen byte. */
723 /* integer wrap paranioa. */
724 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
725 (offset > data_size) || (namelen > data_size) ||
726 (offset + namelen >= data_size)) {
727 break;
729 /* Ensure the name is null terminated. */
730 if (pdata[offset + namelen] != '\0') {
731 return NULL;
733 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
734 &converted_size)) {
735 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
736 "failed: %s", strerror(errno)));
738 if (!eal->ea.name) {
739 return NULL;
742 offset += (namelen + 1); /* Go past the name + terminating zero. */
743 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
744 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
747 return ea_list_head;
750 /****************************************************************************
751 Read one EA list entry from the buffer.
752 ****************************************************************************/
754 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
756 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
757 uint16 val_len;
758 unsigned int namelen;
759 size_t converted_size;
761 if (!eal) {
762 return NULL;
765 if (data_size < 6) {
766 return NULL;
769 eal->ea.flags = CVAL(pdata,0);
770 namelen = CVAL(pdata,1);
771 val_len = SVAL(pdata,2);
773 if (4 + namelen + 1 + val_len > data_size) {
774 return NULL;
777 /* Ensure the name is null terminated. */
778 if (pdata[namelen + 4] != '\0') {
779 return NULL;
781 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
782 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
783 strerror(errno)));
785 if (!eal->ea.name) {
786 return NULL;
789 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
790 if (!eal->ea.value.data) {
791 return NULL;
794 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
796 /* Ensure we're null terminated just in case we print the value. */
797 eal->ea.value.data[val_len] = '\0';
798 /* But don't count the null. */
799 eal->ea.value.length--;
801 if (pbytes_used) {
802 *pbytes_used = 4 + namelen + 1 + val_len;
805 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
806 dump_data(10, eal->ea.value.data, eal->ea.value.length);
808 return eal;
811 /****************************************************************************
812 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
813 ****************************************************************************/
815 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
817 struct ea_list *ea_list_head = NULL;
818 size_t offset = 0;
819 size_t bytes_used = 0;
821 while (offset < data_size) {
822 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
824 if (!eal) {
825 return NULL;
828 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
829 offset += bytes_used;
832 return ea_list_head;
835 /****************************************************************************
836 Count the total EA size needed.
837 ****************************************************************************/
839 static size_t ea_list_size(struct ea_list *ealist)
841 fstring dos_ea_name;
842 struct ea_list *listp;
843 size_t ret = 0;
845 for (listp = ealist; listp; listp = listp->next) {
846 push_ascii_fstring(dos_ea_name, listp->ea.name);
847 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
849 /* Add on 4 for total length. */
850 if (ret) {
851 ret += 4;
854 return ret;
857 /****************************************************************************
858 Return a union of EA's from a file list and a list of names.
859 The TALLOC context for the two lists *MUST* be identical as we steal
860 memory from one list to add to another. JRA.
861 ****************************************************************************/
863 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
865 struct ea_list *nlistp, *flistp;
867 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
868 for (flistp = file_list; flistp; flistp = flistp->next) {
869 if (strequal(nlistp->ea.name, flistp->ea.name)) {
870 break;
874 if (flistp) {
875 /* Copy the data from this entry. */
876 nlistp->ea.flags = flistp->ea.flags;
877 nlistp->ea.value = flistp->ea.value;
878 } else {
879 /* Null entry. */
880 nlistp->ea.flags = 0;
881 ZERO_STRUCT(nlistp->ea.value);
885 *total_ea_len = ea_list_size(name_list);
886 return name_list;
889 /****************************************************************************
890 Send the required number of replies back.
891 We assume all fields other than the data fields are
892 set correctly for the type of call.
893 HACK ! Always assumes smb_setup field is zero.
894 ****************************************************************************/
896 void send_trans2_replies(connection_struct *conn,
897 struct smb_request *req,
898 const char *params,
899 int paramsize,
900 const char *pdata,
901 int datasize,
902 int max_data_bytes)
904 /* As we are using a protocol > LANMAN1 then the max_send
905 variable must have been set in the sessetupX call.
906 This takes precedence over the max_xmit field in the
907 global struct. These different max_xmit variables should
908 be merged as this is now too confusing */
910 int data_to_send = datasize;
911 int params_to_send = paramsize;
912 int useable_space;
913 const char *pp = params;
914 const char *pd = pdata;
915 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
916 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
917 int data_alignment_offset = 0;
918 bool overflow = False;
919 struct smbd_server_connection *sconn = req->sconn;
920 int max_send = sconn->smb1.sessions.max_send;
922 /* Modify the data_to_send and datasize and set the error if
923 we're trying to send more than max_data_bytes. We still send
924 the part of the packet(s) that fit. Strange, but needed
925 for OS/2. */
927 if (max_data_bytes > 0 && datasize > max_data_bytes) {
928 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
929 max_data_bytes, datasize ));
930 datasize = data_to_send = max_data_bytes;
931 overflow = True;
934 /* If there genuinely are no parameters or data to send just send the empty packet */
936 if(params_to_send == 0 && data_to_send == 0) {
937 reply_outbuf(req, 10, 0);
938 show_msg((char *)req->outbuf);
939 if (!srv_send_smb(sconn,
940 (char *)req->outbuf,
941 true, req->seqnum+1,
942 IS_CONN_ENCRYPTED(conn),
943 &req->pcd)) {
944 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
946 TALLOC_FREE(req->outbuf);
947 return;
950 /* When sending params and data ensure that both are nicely aligned */
951 /* Only do this alignment when there is also data to send - else
952 can cause NT redirector problems. */
954 if (((params_to_send % 4) != 0) && (data_to_send != 0))
955 data_alignment_offset = 4 - (params_to_send % 4);
957 /* Space is bufsize minus Netbios over TCP header minus SMB header */
958 /* The alignment_offset is to align the param bytes on an even byte
959 boundary. NT 4.0 Beta needs this to work correctly. */
961 useable_space = max_send - (smb_size
962 + 2 * 10 /* wct */
963 + alignment_offset
964 + data_alignment_offset);
966 if (useable_space < 0) {
967 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
968 "= %d!!!", useable_space));
969 exit_server_cleanly("send_trans2_replies: Not enough space");
972 while (params_to_send || data_to_send) {
973 /* Calculate whether we will totally or partially fill this packet */
975 total_sent_thistime = params_to_send + data_to_send;
977 /* We can never send more than useable_space */
979 * Note that 'useable_space' does not include the alignment offsets,
980 * but we must include the alignment offsets in the calculation of
981 * the length of the data we send over the wire, as the alignment offsets
982 * are sent here. Fix from Marc_Jacobsen@hp.com.
985 total_sent_thistime = MIN(total_sent_thistime, useable_space);
987 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
988 + data_alignment_offset);
990 /* Set total params and data to be sent */
991 SSVAL(req->outbuf,smb_tprcnt,paramsize);
992 SSVAL(req->outbuf,smb_tdrcnt,datasize);
994 /* Calculate how many parameters and data we can fit into
995 * this packet. Parameters get precedence
998 params_sent_thistime = MIN(params_to_send,useable_space);
999 data_sent_thistime = useable_space - params_sent_thistime;
1000 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1002 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1004 /* smb_proff is the offset from the start of the SMB header to the
1005 parameter bytes, however the first 4 bytes of outbuf are
1006 the Netbios over TCP header. Thus use smb_base() to subtract
1007 them from the calculation */
1009 SSVAL(req->outbuf,smb_proff,
1010 ((smb_buf(req->outbuf)+alignment_offset)
1011 - smb_base(req->outbuf)));
1013 if(params_sent_thistime == 0)
1014 SSVAL(req->outbuf,smb_prdisp,0);
1015 else
1016 /* Absolute displacement of param bytes sent in this packet */
1017 SSVAL(req->outbuf,smb_prdisp,pp - params);
1019 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1020 if(data_sent_thistime == 0) {
1021 SSVAL(req->outbuf,smb_droff,0);
1022 SSVAL(req->outbuf,smb_drdisp, 0);
1023 } else {
1024 /* The offset of the data bytes is the offset of the
1025 parameter bytes plus the number of parameters being sent this time */
1026 SSVAL(req->outbuf, smb_droff,
1027 ((smb_buf(req->outbuf)+alignment_offset)
1028 - smb_base(req->outbuf))
1029 + params_sent_thistime + data_alignment_offset);
1030 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1033 /* Initialize the padding for alignment */
1035 if (alignment_offset != 0) {
1036 memset(smb_buf(req->outbuf), 0, alignment_offset);
1039 /* Copy the param bytes into the packet */
1041 if(params_sent_thistime) {
1042 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1043 params_sent_thistime);
1046 /* Copy in the data bytes */
1047 if(data_sent_thistime) {
1048 if (data_alignment_offset != 0) {
1049 memset((smb_buf(req->outbuf)+alignment_offset+
1050 params_sent_thistime), 0,
1051 data_alignment_offset);
1053 memcpy(smb_buf(req->outbuf)+alignment_offset
1054 +params_sent_thistime+data_alignment_offset,
1055 pd,data_sent_thistime);
1058 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1059 params_sent_thistime, data_sent_thistime, useable_space));
1060 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1061 params_to_send, data_to_send, paramsize, datasize));
1063 if (overflow) {
1064 error_packet_set((char *)req->outbuf,
1065 ERRDOS,ERRbufferoverflow,
1066 STATUS_BUFFER_OVERFLOW,
1067 __LINE__,__FILE__);
1070 /* Send the packet */
1071 show_msg((char *)req->outbuf);
1072 if (!srv_send_smb(sconn,
1073 (char *)req->outbuf,
1074 true, req->seqnum+1,
1075 IS_CONN_ENCRYPTED(conn),
1076 &req->pcd))
1077 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1079 TALLOC_FREE(req->outbuf);
1081 pp += params_sent_thistime;
1082 pd += data_sent_thistime;
1084 params_to_send -= params_sent_thistime;
1085 data_to_send -= data_sent_thistime;
1087 /* Sanity check */
1088 if(params_to_send < 0 || data_to_send < 0) {
1089 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1090 params_to_send, data_to_send));
1091 return;
1095 return;
1098 /****************************************************************************
1099 Reply to a TRANSACT2_OPEN.
1100 ****************************************************************************/
1102 static void call_trans2open(connection_struct *conn,
1103 struct smb_request *req,
1104 char **pparams, int total_params,
1105 char **ppdata, int total_data,
1106 unsigned int max_data_bytes)
1108 struct smb_filename *smb_fname = NULL;
1109 char *params = *pparams;
1110 char *pdata = *ppdata;
1111 int deny_mode;
1112 int32 open_attr;
1113 bool oplock_request;
1114 #if 0
1115 bool return_additional_info;
1116 int16 open_sattr;
1117 time_t open_time;
1118 #endif
1119 int open_ofun;
1120 uint32 open_size;
1121 char *pname;
1122 char *fname = NULL;
1123 off_t size=0;
1124 int fattr=0,mtime=0;
1125 SMB_INO_T inode = 0;
1126 int smb_action = 0;
1127 files_struct *fsp;
1128 struct ea_list *ea_list = NULL;
1129 uint16 flags = 0;
1130 NTSTATUS status;
1131 uint32 access_mask;
1132 uint32 share_mode;
1133 uint32 create_disposition;
1134 uint32 create_options = 0;
1135 uint32_t private_flags = 0;
1136 TALLOC_CTX *ctx = talloc_tos();
1139 * Ensure we have enough parameters to perform the operation.
1142 if (total_params < 29) {
1143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1144 goto out;
1147 flags = SVAL(params, 0);
1148 deny_mode = SVAL(params, 2);
1149 open_attr = SVAL(params,6);
1150 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1151 if (oplock_request) {
1152 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1155 #if 0
1156 return_additional_info = BITSETW(params,0);
1157 open_sattr = SVAL(params, 4);
1158 open_time = make_unix_date3(params+8);
1159 #endif
1160 open_ofun = SVAL(params,12);
1161 open_size = IVAL(params,14);
1162 pname = &params[28];
1164 if (IS_IPC(conn)) {
1165 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1166 goto out;
1169 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1170 total_params - 28, STR_TERMINATE,
1171 &status);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 reply_nterror(req, status);
1174 goto out;
1177 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1178 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1179 (unsigned int)open_ofun, open_size));
1181 status = filename_convert(ctx,
1182 conn,
1183 req->flags2 & FLAGS2_DFS_PATHNAMES,
1184 fname,
1186 NULL,
1187 &smb_fname);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1190 reply_botherror(req,
1191 NT_STATUS_PATH_NOT_COVERED,
1192 ERRSRV, ERRbadpath);
1193 goto out;
1195 reply_nterror(req, status);
1196 goto out;
1199 if (open_ofun == 0) {
1200 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1201 goto out;
1204 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1205 open_ofun,
1206 &access_mask, &share_mode,
1207 &create_disposition,
1208 &create_options,
1209 &private_flags)) {
1210 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1211 goto out;
1214 /* Any data in this call is an EA list. */
1215 if (total_data && (total_data != 4)) {
1216 if (total_data < 10) {
1217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1218 goto out;
1221 if (IVAL(pdata,0) > total_data) {
1222 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1223 IVAL(pdata,0), (unsigned int)total_data));
1224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1225 goto out;
1228 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1229 total_data - 4);
1230 if (!ea_list) {
1231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1232 goto out;
1235 if (!lp_ea_support(SNUM(conn))) {
1236 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1237 goto out;
1241 status = SMB_VFS_CREATE_FILE(
1242 conn, /* conn */
1243 req, /* req */
1244 0, /* root_dir_fid */
1245 smb_fname, /* fname */
1246 access_mask, /* access_mask */
1247 share_mode, /* share_access */
1248 create_disposition, /* create_disposition*/
1249 create_options, /* create_options */
1250 open_attr, /* file_attributes */
1251 oplock_request, /* oplock_request */
1252 open_size, /* allocation_size */
1253 private_flags,
1254 NULL, /* sd */
1255 ea_list, /* ea_list */
1256 &fsp, /* result */
1257 &smb_action); /* psbuf */
1259 if (!NT_STATUS_IS_OK(status)) {
1260 if (open_was_deferred(req->sconn, req->mid)) {
1261 /* We have re-scheduled this call. */
1262 goto out;
1264 reply_openerror(req, status);
1265 goto out;
1268 size = get_file_size_stat(&smb_fname->st);
1269 fattr = dos_mode(conn, smb_fname);
1270 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1271 inode = smb_fname->st.st_ex_ino;
1272 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1273 close_file(req, fsp, ERROR_CLOSE);
1274 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1275 goto out;
1278 /* Realloc the size of parameters and data we will return */
1279 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1280 if(*pparams == NULL ) {
1281 reply_nterror(req, NT_STATUS_NO_MEMORY);
1282 goto out;
1284 params = *pparams;
1286 SSVAL(params,0,fsp->fnum);
1287 SSVAL(params,2,fattr);
1288 srv_put_dos_date2(params,4, mtime);
1289 SIVAL(params,8, (uint32)size);
1290 SSVAL(params,12,deny_mode);
1291 SSVAL(params,14,0); /* open_type - file or directory. */
1292 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1294 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1295 smb_action |= EXTENDED_OPLOCK_GRANTED;
1298 SSVAL(params,18,smb_action);
1301 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1303 SIVAL(params,20,inode);
1304 SSVAL(params,24,0); /* Padding. */
1305 if (flags & 8) {
1306 uint32 ea_size = estimate_ea_size(conn, fsp,
1307 smb_fname);
1308 SIVAL(params, 26, ea_size);
1309 } else {
1310 SIVAL(params, 26, 0);
1313 /* Send the required number of replies */
1314 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1315 out:
1316 TALLOC_FREE(smb_fname);
1319 /*********************************************************
1320 Routine to check if a given string matches exactly.
1321 as a special case a mask of "." does NOT match. That
1322 is required for correct wildcard semantics
1323 Case can be significant or not.
1324 **********************************************************/
1326 static bool exact_match(bool has_wild,
1327 bool case_sensitive,
1328 const char *str,
1329 const char *mask)
1331 if (mask[0] == '.' && mask[1] == 0) {
1332 return false;
1335 if (has_wild) {
1336 return false;
1339 if (case_sensitive) {
1340 return strcmp(str,mask)==0;
1341 } else {
1342 return strcasecmp_m(str,mask) == 0;
1346 /****************************************************************************
1347 Return the filetype for UNIX extensions.
1348 ****************************************************************************/
1350 static uint32 unix_filetype(mode_t mode)
1352 if(S_ISREG(mode))
1353 return UNIX_TYPE_FILE;
1354 else if(S_ISDIR(mode))
1355 return UNIX_TYPE_DIR;
1356 #ifdef S_ISLNK
1357 else if(S_ISLNK(mode))
1358 return UNIX_TYPE_SYMLINK;
1359 #endif
1360 #ifdef S_ISCHR
1361 else if(S_ISCHR(mode))
1362 return UNIX_TYPE_CHARDEV;
1363 #endif
1364 #ifdef S_ISBLK
1365 else if(S_ISBLK(mode))
1366 return UNIX_TYPE_BLKDEV;
1367 #endif
1368 #ifdef S_ISFIFO
1369 else if(S_ISFIFO(mode))
1370 return UNIX_TYPE_FIFO;
1371 #endif
1372 #ifdef S_ISSOCK
1373 else if(S_ISSOCK(mode))
1374 return UNIX_TYPE_SOCKET;
1375 #endif
1377 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1378 return UNIX_TYPE_UNKNOWN;
1381 /****************************************************************************
1382 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1383 ****************************************************************************/
1385 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1387 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1388 const SMB_STRUCT_STAT *psbuf,
1389 uint32 perms,
1390 enum perm_type ptype,
1391 mode_t *ret_perms)
1393 mode_t ret = 0;
1395 if (perms == SMB_MODE_NO_CHANGE) {
1396 if (!VALID_STAT(*psbuf)) {
1397 return NT_STATUS_INVALID_PARAMETER;
1398 } else {
1399 *ret_perms = psbuf->st_ex_mode;
1400 return NT_STATUS_OK;
1404 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1405 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1406 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1407 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1408 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1409 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1410 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1411 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1412 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1413 #ifdef S_ISVTX
1414 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1415 #endif
1416 #ifdef S_ISGID
1417 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1418 #endif
1419 #ifdef S_ISUID
1420 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1421 #endif
1423 switch (ptype) {
1424 case PERM_NEW_FILE:
1425 case PERM_EXISTING_FILE:
1426 /* Apply mode mask */
1427 ret &= lp_create_mask(SNUM(conn));
1428 /* Add in force bits */
1429 ret |= lp_force_create_mode(SNUM(conn));
1430 break;
1431 case PERM_NEW_DIR:
1432 case PERM_EXISTING_DIR:
1433 ret &= lp_dir_mask(SNUM(conn));
1434 /* Add in force bits */
1435 ret |= lp_force_dir_mode(SNUM(conn));
1436 break;
1439 *ret_perms = ret;
1440 return NT_STATUS_OK;
1443 /****************************************************************************
1444 Needed to show the msdfs symlinks as directories. Modifies psbuf
1445 to be a directory if it's a msdfs link.
1446 ****************************************************************************/
1448 static bool check_msdfs_link(connection_struct *conn,
1449 const char *pathname,
1450 SMB_STRUCT_STAT *psbuf)
1452 int saved_errno = errno;
1453 if(lp_host_msdfs() &&
1454 lp_msdfs_root(SNUM(conn)) &&
1455 is_msdfs_link(conn, pathname, psbuf)) {
1457 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1458 "as a directory\n",
1459 pathname));
1460 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1461 errno = saved_errno;
1462 return true;
1464 errno = saved_errno;
1465 return false;
1469 /****************************************************************************
1470 Get a level dependent lanman2 dir entry.
1471 ****************************************************************************/
1473 struct smbd_dirptr_lanman2_state {
1474 connection_struct *conn;
1475 uint32_t info_level;
1476 bool check_mangled_names;
1477 bool has_wild;
1478 bool got_exact_match;
1481 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1482 void *private_data,
1483 const char *dname,
1484 const char *mask,
1485 char **_fname)
1487 struct smbd_dirptr_lanman2_state *state =
1488 (struct smbd_dirptr_lanman2_state *)private_data;
1489 bool ok;
1490 char mangled_name[13]; /* mangled 8.3 name. */
1491 bool got_match;
1492 const char *fname;
1494 /* Mangle fname if it's an illegal name. */
1495 if (mangle_must_mangle(dname, state->conn->params)) {
1496 ok = name_to_8_3(dname, mangled_name,
1497 true, state->conn->params);
1498 if (!ok) {
1499 return false;
1501 fname = mangled_name;
1502 } else {
1503 fname = dname;
1506 got_match = exact_match(state->has_wild,
1507 state->conn->case_sensitive,
1508 fname, mask);
1509 state->got_exact_match = got_match;
1510 if (!got_match) {
1511 got_match = mask_match(fname, mask,
1512 state->conn->case_sensitive);
1515 if(!got_match && state->check_mangled_names &&
1516 !mangle_is_8_3(fname, false, state->conn->params)) {
1518 * It turns out that NT matches wildcards against
1519 * both long *and* short names. This may explain some
1520 * of the wildcard wierdness from old DOS clients
1521 * that some people have been seeing.... JRA.
1523 /* Force the mangling into 8.3. */
1524 ok = name_to_8_3(fname, mangled_name,
1525 false, state->conn->params);
1526 if (!ok) {
1527 return false;
1530 got_match = exact_match(state->has_wild,
1531 state->conn->case_sensitive,
1532 mangled_name, mask);
1533 state->got_exact_match = got_match;
1534 if (!got_match) {
1535 got_match = mask_match(mangled_name, mask,
1536 state->conn->case_sensitive);
1540 if (!got_match) {
1541 return false;
1544 *_fname = talloc_strdup(ctx, fname);
1545 if (*_fname == NULL) {
1546 return false;
1549 return true;
1552 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1553 void *private_data,
1554 struct smb_filename *smb_fname,
1555 uint32_t *_mode)
1557 struct smbd_dirptr_lanman2_state *state =
1558 (struct smbd_dirptr_lanman2_state *)private_data;
1559 bool ms_dfs_link = false;
1560 uint32_t mode = 0;
1562 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1563 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1564 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1565 "Couldn't lstat [%s] (%s)\n",
1566 smb_fname_str_dbg(smb_fname),
1567 strerror(errno)));
1568 return false;
1570 } else if (!VALID_STAT(smb_fname->st) &&
1571 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1572 /* Needed to show the msdfs symlinks as
1573 * directories */
1575 ms_dfs_link = check_msdfs_link(state->conn,
1576 smb_fname->base_name,
1577 &smb_fname->st);
1578 if (!ms_dfs_link) {
1579 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1580 "Couldn't stat [%s] (%s)\n",
1581 smb_fname_str_dbg(smb_fname),
1582 strerror(errno)));
1583 return false;
1587 if (ms_dfs_link) {
1588 mode = dos_mode_msdfs(state->conn, smb_fname);
1589 } else {
1590 mode = dos_mode(state->conn, smb_fname);
1593 *_mode = mode;
1594 return true;
1597 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1598 connection_struct *conn,
1599 uint16_t flags2,
1600 uint32_t info_level,
1601 struct ea_list *name_list,
1602 bool check_mangled_names,
1603 bool requires_resume_key,
1604 uint32_t mode,
1605 const char *fname,
1606 const struct smb_filename *smb_fname,
1607 int space_remaining,
1608 uint8_t align,
1609 bool do_pad,
1610 char *base_data,
1611 char **ppdata,
1612 char *end_data,
1613 bool *out_of_space,
1614 uint64_t *last_entry_off)
1616 char *p, *q, *pdata = *ppdata;
1617 uint32_t reskey=0;
1618 uint64_t file_size = 0;
1619 uint64_t allocation_size = 0;
1620 uint64_t file_index = 0;
1621 uint32_t len;
1622 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1623 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1624 char *nameptr;
1625 char *last_entry_ptr;
1626 bool was_8_3;
1627 int off;
1628 int pad = 0;
1630 *out_of_space = false;
1632 ZERO_STRUCT(mdate_ts);
1633 ZERO_STRUCT(adate_ts);
1634 ZERO_STRUCT(create_date_ts);
1635 ZERO_STRUCT(cdate_ts);
1637 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1638 file_size = get_file_size_stat(&smb_fname->st);
1640 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1642 file_index = get_FileIndex(conn, &smb_fname->st);
1644 mdate_ts = smb_fname->st.st_ex_mtime;
1645 adate_ts = smb_fname->st.st_ex_atime;
1646 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1647 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1649 if (lp_dos_filetime_resolution(SNUM(conn))) {
1650 dos_filetime_timespec(&create_date_ts);
1651 dos_filetime_timespec(&mdate_ts);
1652 dos_filetime_timespec(&adate_ts);
1653 dos_filetime_timespec(&cdate_ts);
1656 create_date = convert_timespec_to_time_t(create_date_ts);
1657 mdate = convert_timespec_to_time_t(mdate_ts);
1658 adate = convert_timespec_to_time_t(adate_ts);
1660 /* align the record */
1661 SMB_ASSERT(align >= 1);
1663 off = (int)PTR_DIFF(pdata, base_data);
1664 pad = (off + (align-1)) & ~(align-1);
1665 pad -= off;
1667 if (pad && pad > space_remaining) {
1668 *out_of_space = true;
1669 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1670 "for padding (wanted %u, had %d)\n",
1671 (unsigned int)pad,
1672 space_remaining ));
1673 return false; /* Not finished - just out of space */
1676 off += pad;
1677 /* initialize padding to 0 */
1678 if (pad) {
1679 memset(pdata, 0, pad);
1681 space_remaining -= pad;
1683 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1684 space_remaining ));
1686 pdata += pad;
1687 p = pdata;
1688 last_entry_ptr = p;
1690 pad = 0;
1691 off = 0;
1693 switch (info_level) {
1694 case SMB_FIND_INFO_STANDARD:
1695 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1696 if(requires_resume_key) {
1697 SIVAL(p,0,reskey);
1698 p += 4;
1700 srv_put_dos_date2(p,0,create_date);
1701 srv_put_dos_date2(p,4,adate);
1702 srv_put_dos_date2(p,8,mdate);
1703 SIVAL(p,12,(uint32)file_size);
1704 SIVAL(p,16,(uint32)allocation_size);
1705 SSVAL(p,20,mode);
1706 p += 23;
1707 nameptr = p;
1708 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1709 p += ucs2_align(base_data, p, 0);
1711 len = srvstr_push(base_data, flags2, p,
1712 fname, PTR_DIFF(end_data, p),
1713 STR_TERMINATE);
1714 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1715 if (len > 2) {
1716 SCVAL(nameptr, -1, len - 2);
1717 } else {
1718 SCVAL(nameptr, -1, 0);
1720 } else {
1721 if (len > 1) {
1722 SCVAL(nameptr, -1, len - 1);
1723 } else {
1724 SCVAL(nameptr, -1, 0);
1727 p += len;
1728 break;
1730 case SMB_FIND_EA_SIZE:
1731 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1732 if (requires_resume_key) {
1733 SIVAL(p,0,reskey);
1734 p += 4;
1736 srv_put_dos_date2(p,0,create_date);
1737 srv_put_dos_date2(p,4,adate);
1738 srv_put_dos_date2(p,8,mdate);
1739 SIVAL(p,12,(uint32)file_size);
1740 SIVAL(p,16,(uint32)allocation_size);
1741 SSVAL(p,20,mode);
1743 unsigned int ea_size = estimate_ea_size(conn, NULL,
1744 smb_fname);
1745 SIVAL(p,22,ea_size); /* Extended attributes */
1747 p += 27;
1748 nameptr = p - 1;
1749 len = srvstr_push(base_data, flags2,
1750 p, fname, PTR_DIFF(end_data, p),
1751 STR_TERMINATE | STR_NOALIGN);
1752 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1753 if (len > 2) {
1754 len -= 2;
1755 } else {
1756 len = 0;
1758 } else {
1759 if (len > 1) {
1760 len -= 1;
1761 } else {
1762 len = 0;
1765 SCVAL(nameptr,0,len);
1766 p += len;
1767 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1768 break;
1770 case SMB_FIND_EA_LIST:
1772 struct ea_list *file_list = NULL;
1773 size_t ea_len = 0;
1774 NTSTATUS status;
1776 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1777 if (!name_list) {
1778 return false;
1780 if (requires_resume_key) {
1781 SIVAL(p,0,reskey);
1782 p += 4;
1784 srv_put_dos_date2(p,0,create_date);
1785 srv_put_dos_date2(p,4,adate);
1786 srv_put_dos_date2(p,8,mdate);
1787 SIVAL(p,12,(uint32)file_size);
1788 SIVAL(p,16,(uint32)allocation_size);
1789 SSVAL(p,20,mode);
1790 p += 22; /* p now points to the EA area. */
1792 status = get_ea_list_from_file(ctx, conn, NULL,
1793 smb_fname,
1794 &ea_len, &file_list);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 file_list = NULL;
1798 name_list = ea_list_union(name_list, file_list, &ea_len);
1800 /* We need to determine if this entry will fit in the space available. */
1801 /* Max string size is 255 bytes. */
1802 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1803 *out_of_space = true;
1804 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1805 "(wanted %u, had %d)\n",
1806 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1807 space_remaining ));
1808 return False; /* Not finished - just out of space */
1811 /* Push the ea_data followed by the name. */
1812 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1813 nameptr = p;
1814 len = srvstr_push(base_data, flags2,
1815 p + 1, fname, PTR_DIFF(end_data, p+1),
1816 STR_TERMINATE | STR_NOALIGN);
1817 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1818 if (len > 2) {
1819 len -= 2;
1820 } else {
1821 len = 0;
1823 } else {
1824 if (len > 1) {
1825 len -= 1;
1826 } else {
1827 len = 0;
1830 SCVAL(nameptr,0,len);
1831 p += len + 1;
1832 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1833 break;
1836 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1838 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1839 p += 4;
1840 SIVAL(p,0,reskey); p += 4;
1841 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1842 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1843 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1844 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1845 SOFF_T(p,0,file_size); p += 8;
1846 SOFF_T(p,0,allocation_size); p += 8;
1847 SIVAL(p,0,mode); p += 4;
1848 q = p; p += 4; /* q is placeholder for name length. */
1850 unsigned int ea_size = estimate_ea_size(conn, NULL,
1851 smb_fname);
1852 SIVAL(p,0,ea_size); /* Extended attributes */
1853 p += 4;
1855 /* Clear the short name buffer. This is
1856 * IMPORTANT as not doing so will trigger
1857 * a Win2k client bug. JRA.
1859 if (!was_8_3 && check_mangled_names) {
1860 char mangled_name[13]; /* mangled 8.3 name. */
1861 if (!name_to_8_3(fname,mangled_name,True,
1862 conn->params)) {
1863 /* Error - mangle failed ! */
1864 memset(mangled_name,'\0',12);
1866 mangled_name[12] = 0;
1867 len = srvstr_push(base_data, flags2,
1868 p+2, mangled_name, 24,
1869 STR_UPPER|STR_UNICODE);
1870 if (len < 24) {
1871 memset(p + 2 + len,'\0',24 - len);
1873 SSVAL(p, 0, len);
1874 } else {
1875 memset(p,'\0',26);
1877 p += 2 + 24;
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1881 SIVAL(q,0,len);
1882 p += len;
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1891 SIVAL(pdata,0,pad);
1893 * set padding to zero
1895 if (do_pad) {
1896 memset(p, 0, pad - len);
1897 p = pdata + pad;
1898 } else {
1899 p = pdata + len;
1901 break;
1903 case SMB_FIND_FILE_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1905 p += 4;
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 len = srvstr_push(base_data, flags2,
1915 p + 4, fname, PTR_DIFF(end_data, p+4),
1916 STR_TERMINATE_ASCII);
1917 SIVAL(p,0,len);
1918 p += 4 + len;
1920 len = PTR_DIFF(p, pdata);
1921 pad = (len + (align-1)) & ~(align-1);
1923 * offset to the next entry, the caller
1924 * will overwrite it for the last entry
1925 * that's why we always include the padding
1927 SIVAL(pdata,0,pad);
1929 * set padding to zero
1931 if (do_pad) {
1932 memset(p, 0, pad - len);
1933 p = pdata + pad;
1934 } else {
1935 p = pdata + len;
1937 break;
1939 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1941 p += 4;
1942 SIVAL(p,0,reskey); p += 4;
1943 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1945 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1946 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1947 SOFF_T(p,0,file_size); p += 8;
1948 SOFF_T(p,0,allocation_size); p += 8;
1949 SIVAL(p,0,mode); p += 4;
1950 q = p; p += 4; /* q is placeholder for name length. */
1952 unsigned int ea_size = estimate_ea_size(conn, NULL,
1953 smb_fname);
1954 SIVAL(p,0,ea_size); /* Extended attributes */
1955 p +=4;
1957 len = srvstr_push(base_data, flags2, p,
1958 fname, PTR_DIFF(end_data, p),
1959 STR_TERMINATE_ASCII);
1960 SIVAL(q, 0, len);
1961 p += len;
1963 len = PTR_DIFF(p, pdata);
1964 pad = (len + (align-1)) & ~(align-1);
1966 * offset to the next entry, the caller
1967 * will overwrite it for the last entry
1968 * that's why we always include the padding
1970 SIVAL(pdata,0,pad);
1972 * set padding to zero
1974 if (do_pad) {
1975 memset(p, 0, pad - len);
1976 p = pdata + pad;
1977 } else {
1978 p = pdata + len;
1980 break;
1982 case SMB_FIND_FILE_NAMES_INFO:
1983 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1984 p += 4;
1985 SIVAL(p,0,reskey); p += 4;
1986 p += 4;
1987 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1988 acl on a dir (tridge) */
1989 len = srvstr_push(base_data, flags2, p,
1990 fname, PTR_DIFF(end_data, p),
1991 STR_TERMINATE_ASCII);
1992 SIVAL(p, -4, len);
1993 p += len;
1995 len = PTR_DIFF(p, pdata);
1996 pad = (len + (align-1)) & ~(align-1);
1998 * offset to the next entry, the caller
1999 * will overwrite it for the last entry
2000 * that's why we always include the padding
2002 SIVAL(pdata,0,pad);
2004 * set padding to zero
2006 if (do_pad) {
2007 memset(p, 0, pad - len);
2008 p = pdata + pad;
2009 } else {
2010 p = pdata + len;
2012 break;
2014 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2015 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2016 p += 4;
2017 SIVAL(p,0,reskey); p += 4;
2018 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2019 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2020 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2021 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2022 SOFF_T(p,0,file_size); p += 8;
2023 SOFF_T(p,0,allocation_size); p += 8;
2024 SIVAL(p,0,mode); p += 4;
2025 q = p; p += 4; /* q is placeholder for name length. */
2027 unsigned int ea_size = estimate_ea_size(conn, NULL,
2028 smb_fname);
2029 SIVAL(p,0,ea_size); /* Extended attributes */
2030 p +=4;
2032 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2033 SBVAL(p,0,file_index); p += 8;
2034 len = srvstr_push(base_data, flags2, p,
2035 fname, PTR_DIFF(end_data, p),
2036 STR_TERMINATE_ASCII);
2037 SIVAL(q, 0, len);
2038 p += len;
2040 len = PTR_DIFF(p, pdata);
2041 pad = (len + (align-1)) & ~(align-1);
2043 * offset to the next entry, the caller
2044 * will overwrite it for the last entry
2045 * that's why we always include the padding
2047 SIVAL(pdata,0,pad);
2049 * set padding to zero
2051 if (do_pad) {
2052 memset(p, 0, pad - len);
2053 p = pdata + pad;
2054 } else {
2055 p = pdata + len;
2057 break;
2059 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2061 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2062 p += 4;
2063 SIVAL(p,0,reskey); p += 4;
2064 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2065 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2066 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2067 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2068 SOFF_T(p,0,file_size); p += 8;
2069 SOFF_T(p,0,allocation_size); p += 8;
2070 SIVAL(p,0,mode); p += 4;
2071 q = p; p += 4; /* q is placeholder for name length */
2073 unsigned int ea_size = estimate_ea_size(conn, NULL,
2074 smb_fname);
2075 SIVAL(p,0,ea_size); /* Extended attributes */
2076 p +=4;
2078 /* Clear the short name buffer. This is
2079 * IMPORTANT as not doing so will trigger
2080 * a Win2k client bug. JRA.
2082 if (!was_8_3 && check_mangled_names) {
2083 char mangled_name[13]; /* mangled 8.3 name. */
2084 if (!name_to_8_3(fname,mangled_name,True,
2085 conn->params)) {
2086 /* Error - mangle failed ! */
2087 memset(mangled_name,'\0',12);
2089 mangled_name[12] = 0;
2090 len = srvstr_push(base_data, flags2,
2091 p+2, mangled_name, 24,
2092 STR_UPPER|STR_UNICODE);
2093 SSVAL(p, 0, len);
2094 if (len < 24) {
2095 memset(p + 2 + len,'\0',24 - len);
2097 SSVAL(p, 0, len);
2098 } else {
2099 memset(p,'\0',26);
2101 p += 26;
2102 SSVAL(p,0,0); p += 2; /* Reserved ? */
2103 SBVAL(p,0,file_index); p += 8;
2104 len = srvstr_push(base_data, flags2, p,
2105 fname, PTR_DIFF(end_data, p),
2106 STR_TERMINATE_ASCII);
2107 SIVAL(q,0,len);
2108 p += len;
2110 len = PTR_DIFF(p, pdata);
2111 pad = (len + (align-1)) & ~(align-1);
2113 * offset to the next entry, the caller
2114 * will overwrite it for the last entry
2115 * that's why we always include the padding
2117 SIVAL(pdata,0,pad);
2119 * set padding to zero
2121 if (do_pad) {
2122 memset(p, 0, pad - len);
2123 p = pdata + pad;
2124 } else {
2125 p = pdata + len;
2127 break;
2129 /* CIFS UNIX Extension. */
2131 case SMB_FIND_FILE_UNIX:
2132 case SMB_FIND_FILE_UNIX_INFO2:
2133 p+= 4;
2134 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2136 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2138 if (info_level == SMB_FIND_FILE_UNIX) {
2139 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2140 p = store_file_unix_basic(conn, p,
2141 NULL, &smb_fname->st);
2142 len = srvstr_push(base_data, flags2, p,
2143 fname, PTR_DIFF(end_data, p),
2144 STR_TERMINATE);
2145 } else {
2146 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2147 p = store_file_unix_basic_info2(conn, p,
2148 NULL, &smb_fname->st);
2149 nameptr = p;
2150 p += 4;
2151 len = srvstr_push(base_data, flags2, p, fname,
2152 PTR_DIFF(end_data, p), 0);
2153 SIVAL(nameptr, 0, len);
2156 p += len;
2158 len = PTR_DIFF(p, pdata);
2159 pad = (len + (align-1)) & ~(align-1);
2161 * offset to the next entry, the caller
2162 * will overwrite it for the last entry
2163 * that's why we always include the padding
2165 SIVAL(pdata,0,pad);
2167 * set padding to zero
2169 if (do_pad) {
2170 memset(p, 0, pad - len);
2171 p = pdata + pad;
2172 } else {
2173 p = pdata + len;
2175 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2177 break;
2179 default:
2180 return false;
2183 if (PTR_DIFF(p,pdata) > space_remaining) {
2184 *out_of_space = true;
2185 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2186 "(wanted %u, had %d)\n",
2187 (unsigned int)PTR_DIFF(p,pdata),
2188 space_remaining ));
2189 return false; /* Not finished - just out of space */
2192 /* Setup the last entry pointer, as an offset from base_data */
2193 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2194 /* Advance the data pointer to the next slot */
2195 *ppdata = p;
2197 return true;
2200 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2201 connection_struct *conn,
2202 struct dptr_struct *dirptr,
2203 uint16 flags2,
2204 const char *path_mask,
2205 uint32 dirtype,
2206 int info_level,
2207 int requires_resume_key,
2208 bool dont_descend,
2209 bool ask_sharemode,
2210 uint8_t align,
2211 bool do_pad,
2212 char **ppdata,
2213 char *base_data,
2214 char *end_data,
2215 int space_remaining,
2216 bool *out_of_space,
2217 bool *got_exact_match,
2218 int *_last_entry_off,
2219 struct ea_list *name_list)
2221 const char *p;
2222 const char *mask = NULL;
2223 long prev_dirpos = 0;
2224 uint32_t mode = 0;
2225 char *fname = NULL;
2226 struct smb_filename *smb_fname = NULL;
2227 struct smbd_dirptr_lanman2_state state;
2228 bool ok;
2229 uint64_t last_entry_off = 0;
2231 ZERO_STRUCT(state);
2232 state.conn = conn;
2233 state.info_level = info_level;
2234 state.check_mangled_names = lp_manglednames(conn->params);
2235 state.has_wild = dptr_has_wild(dirptr);
2236 state.got_exact_match = false;
2238 *out_of_space = false;
2239 *got_exact_match = false;
2241 p = strrchr_m(path_mask,'/');
2242 if(p != NULL) {
2243 if(p[1] == '\0') {
2244 mask = "*.*";
2245 } else {
2246 mask = p+1;
2248 } else {
2249 mask = path_mask;
2252 ok = smbd_dirptr_get_entry(ctx,
2253 dirptr,
2254 mask,
2255 dirtype,
2256 dont_descend,
2257 ask_sharemode,
2258 smbd_dirptr_lanman2_match_fn,
2259 smbd_dirptr_lanman2_mode_fn,
2260 &state,
2261 &fname,
2262 &smb_fname,
2263 &mode,
2264 &prev_dirpos);
2265 if (!ok) {
2266 return false;
2269 *got_exact_match = state.got_exact_match;
2271 ok = smbd_marshall_dir_entry(ctx,
2272 conn,
2273 flags2,
2274 info_level,
2275 name_list,
2276 state.check_mangled_names,
2277 requires_resume_key,
2278 mode,
2279 fname,
2280 smb_fname,
2281 space_remaining,
2282 align,
2283 do_pad,
2284 base_data,
2285 ppdata,
2286 end_data,
2287 out_of_space,
2288 &last_entry_off);
2289 TALLOC_FREE(fname);
2290 TALLOC_FREE(smb_fname);
2291 if (*out_of_space) {
2292 dptr_SeekDir(dirptr, prev_dirpos);
2293 return false;
2295 if (!ok) {
2296 return false;
2299 *_last_entry_off = last_entry_off;
2300 return true;
2303 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2304 connection_struct *conn,
2305 struct dptr_struct *dirptr,
2306 uint16 flags2,
2307 const char *path_mask,
2308 uint32 dirtype,
2309 int info_level,
2310 bool requires_resume_key,
2311 bool dont_descend,
2312 bool ask_sharemode,
2313 char **ppdata,
2314 char *base_data,
2315 char *end_data,
2316 int space_remaining,
2317 bool *out_of_space,
2318 bool *got_exact_match,
2319 int *last_entry_off,
2320 struct ea_list *name_list)
2322 uint8_t align = 4;
2323 const bool do_pad = true;
2325 if (info_level >= 1 && info_level <= 3) {
2326 /* No alignment on earlier info levels. */
2327 align = 1;
2330 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2331 path_mask, dirtype, info_level,
2332 requires_resume_key, dont_descend, ask_sharemode,
2333 align, do_pad,
2334 ppdata, base_data, end_data,
2335 space_remaining,
2336 out_of_space, got_exact_match,
2337 last_entry_off, name_list);
2340 /****************************************************************************
2341 Reply to a TRANS2_FINDFIRST.
2342 ****************************************************************************/
2344 static void call_trans2findfirst(connection_struct *conn,
2345 struct smb_request *req,
2346 char **pparams, int total_params,
2347 char **ppdata, int total_data,
2348 unsigned int max_data_bytes)
2350 /* We must be careful here that we don't return more than the
2351 allowed number of data bytes. If this means returning fewer than
2352 maxentries then so be it. We assume that the redirector has
2353 enough room for the fixed number of parameter bytes it has
2354 requested. */
2355 struct smb_filename *smb_dname = NULL;
2356 char *params = *pparams;
2357 char *pdata = *ppdata;
2358 char *data_end;
2359 uint32 dirtype;
2360 int maxentries;
2361 uint16 findfirst_flags;
2362 bool close_after_first;
2363 bool close_if_end;
2364 bool requires_resume_key;
2365 int info_level;
2366 char *directory = NULL;
2367 char *mask = NULL;
2368 char *p;
2369 int last_entry_off=0;
2370 int dptr_num = -1;
2371 int numentries = 0;
2372 int i;
2373 bool finished = False;
2374 bool dont_descend = False;
2375 bool out_of_space = False;
2376 int space_remaining;
2377 bool mask_contains_wcard = False;
2378 struct ea_list *ea_list = NULL;
2379 NTSTATUS ntstatus = NT_STATUS_OK;
2380 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2381 TALLOC_CTX *ctx = talloc_tos();
2382 struct dptr_struct *dirptr = NULL;
2383 struct smbd_server_connection *sconn = req->sconn;
2384 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2385 bool backup_priv = false;
2387 if (total_params < 13) {
2388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2389 goto out;
2392 dirtype = SVAL(params,0);
2393 maxentries = SVAL(params,2);
2394 findfirst_flags = SVAL(params,4);
2395 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2396 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2397 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2398 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2399 security_token_has_privilege(get_current_nttok(conn),
2400 SEC_PRIV_BACKUP));
2402 info_level = SVAL(params,6);
2404 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2405 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2406 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2407 (int)backup_priv,
2408 info_level, max_data_bytes));
2410 if (!maxentries) {
2411 /* W2K3 seems to treat zero as 1. */
2412 maxentries = 1;
2415 switch (info_level) {
2416 case SMB_FIND_INFO_STANDARD:
2417 case SMB_FIND_EA_SIZE:
2418 case SMB_FIND_EA_LIST:
2419 case SMB_FIND_FILE_DIRECTORY_INFO:
2420 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2421 case SMB_FIND_FILE_NAMES_INFO:
2422 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2423 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2424 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2425 break;
2426 case SMB_FIND_FILE_UNIX:
2427 case SMB_FIND_FILE_UNIX_INFO2:
2428 /* Always use filesystem for UNIX mtime query. */
2429 ask_sharemode = false;
2430 if (!lp_unix_extensions()) {
2431 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2432 goto out;
2434 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2435 break;
2436 default:
2437 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2438 goto out;
2441 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2442 params+12, total_params - 12,
2443 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2444 if (!NT_STATUS_IS_OK(ntstatus)) {
2445 reply_nterror(req, ntstatus);
2446 goto out;
2449 if (backup_priv) {
2450 become_root();
2451 ntstatus = filename_convert_with_privilege(ctx,
2452 conn,
2453 req,
2454 directory,
2455 ucf_flags,
2456 &mask_contains_wcard,
2457 &smb_dname);
2458 } else {
2459 ntstatus = filename_convert(ctx, conn,
2460 req->flags2 & FLAGS2_DFS_PATHNAMES,
2461 directory,
2462 ucf_flags,
2463 &mask_contains_wcard,
2464 &smb_dname);
2467 if (!NT_STATUS_IS_OK(ntstatus)) {
2468 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2469 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2470 ERRSRV, ERRbadpath);
2471 goto out;
2473 reply_nterror(req, ntstatus);
2474 goto out;
2477 mask = smb_dname->original_lcomp;
2479 directory = smb_dname->base_name;
2481 p = strrchr_m(directory,'/');
2482 if(p == NULL) {
2483 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2484 if((directory[0] == '.') && (directory[1] == '\0')) {
2485 mask = talloc_strdup(ctx,"*");
2486 if (!mask) {
2487 reply_nterror(req, NT_STATUS_NO_MEMORY);
2488 goto out;
2490 mask_contains_wcard = True;
2492 } else {
2493 *p = 0;
2496 if (p == NULL || p == directory) {
2497 /* Ensure we don't have a directory name of "". */
2498 directory = talloc_strdup(talloc_tos(), ".");
2499 if (!directory) {
2500 reply_nterror(req, NT_STATUS_NO_MEMORY);
2501 goto out;
2505 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2507 if (info_level == SMB_FIND_EA_LIST) {
2508 uint32 ea_size;
2510 if (total_data < 4) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2515 ea_size = IVAL(pdata,0);
2516 if (ea_size != total_data) {
2517 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2518 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2520 goto out;
2523 if (!lp_ea_support(SNUM(conn))) {
2524 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2525 goto out;
2528 /* Pull out the list of names. */
2529 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2530 if (!ea_list) {
2531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2532 goto out;
2536 *ppdata = (char *)SMB_REALLOC(
2537 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2538 if(*ppdata == NULL ) {
2539 reply_nterror(req, NT_STATUS_NO_MEMORY);
2540 goto out;
2542 pdata = *ppdata;
2543 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2545 /* Realloc the params space */
2546 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2547 if (*pparams == NULL) {
2548 reply_nterror(req, NT_STATUS_NO_MEMORY);
2549 goto out;
2551 params = *pparams;
2553 /* Save the wildcard match and attribs we are using on this directory -
2554 needed as lanman2 assumes these are being saved between calls */
2556 ntstatus = dptr_create(conn,
2557 req,
2558 NULL, /* fsp */
2559 directory,
2560 False,
2561 True,
2562 req->smbpid,
2563 mask,
2564 mask_contains_wcard,
2565 dirtype,
2566 &dirptr);
2568 if (!NT_STATUS_IS_OK(ntstatus)) {
2569 reply_nterror(req, ntstatus);
2570 goto out;
2573 if (backup_priv) {
2574 /* Remember this in case we have
2575 to do a findnext. */
2576 dptr_set_priv(dirptr);
2579 dptr_num = dptr_dnum(dirptr);
2580 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2582 /* Initialize per TRANS2_FIND_FIRST operation data */
2583 dptr_init_search_op(dirptr);
2585 /* We don't need to check for VOL here as this is returned by
2586 a different TRANS2 call. */
2588 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2589 directory,lp_dontdescend(ctx, SNUM(conn))));
2590 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2591 dont_descend = True;
2593 p = pdata;
2594 space_remaining = max_data_bytes;
2595 out_of_space = False;
2597 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2598 bool got_exact_match = False;
2600 /* this is a heuristic to avoid seeking the dirptr except when
2601 absolutely necessary. It allows for a filename of about 40 chars */
2602 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2603 out_of_space = True;
2604 finished = False;
2605 } else {
2606 finished = !get_lanman2_dir_entry(ctx,
2607 conn,
2608 dirptr,
2609 req->flags2,
2610 mask,dirtype,info_level,
2611 requires_resume_key,dont_descend,
2612 ask_sharemode,
2613 &p,pdata,data_end,
2614 space_remaining, &out_of_space,
2615 &got_exact_match,
2616 &last_entry_off, ea_list);
2619 if (finished && out_of_space)
2620 finished = False;
2622 if (!finished && !out_of_space)
2623 numentries++;
2626 * As an optimisation if we know we aren't looking
2627 * for a wildcard name (ie. the name matches the wildcard exactly)
2628 * then we can finish on any (first) match.
2629 * This speeds up large directory searches. JRA.
2632 if(got_exact_match)
2633 finished = True;
2635 /* Ensure space_remaining never goes -ve. */
2636 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2637 space_remaining = 0;
2638 out_of_space = true;
2639 } else {
2640 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2644 /* Check if we can close the dirptr */
2645 if(close_after_first || (finished && close_if_end)) {
2646 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2647 dptr_close(sconn, &dptr_num);
2651 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2652 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2653 * the protocol level is less than NT1. Tested with smbclient. JRA.
2654 * This should fix the OS/2 client bug #2335.
2657 if(numentries == 0) {
2658 dptr_close(sconn, &dptr_num);
2659 if (get_Protocol() < PROTOCOL_NT1) {
2660 reply_force_doserror(req, ERRDOS, ERRnofiles);
2661 goto out;
2662 } else {
2663 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2664 ERRDOS, ERRbadfile);
2665 goto out;
2669 /* At this point pdata points to numentries directory entries. */
2671 /* Set up the return parameter block */
2672 SSVAL(params,0,dptr_num);
2673 SSVAL(params,2,numentries);
2674 SSVAL(params,4,finished);
2675 SSVAL(params,6,0); /* Never an EA error */
2676 SSVAL(params,8,last_entry_off);
2678 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2679 max_data_bytes);
2681 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2682 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2683 if (!directory) {
2684 reply_nterror(req, NT_STATUS_NO_MEMORY);
2688 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2689 smb_fn_name(req->cmd),
2690 mask, directory, dirtype, numentries ) );
2693 * Force a name mangle here to ensure that the
2694 * mask as an 8.3 name is top of the mangled cache.
2695 * The reasons for this are subtle. Don't remove
2696 * this code unless you know what you are doing
2697 * (see PR#13758). JRA.
2700 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2701 char mangled_name[13];
2702 name_to_8_3(mask, mangled_name, True, conn->params);
2704 out:
2706 if (backup_priv) {
2707 unbecome_root();
2710 TALLOC_FREE(smb_dname);
2711 return;
2714 /****************************************************************************
2715 Reply to a TRANS2_FINDNEXT.
2716 ****************************************************************************/
2718 static void call_trans2findnext(connection_struct *conn,
2719 struct smb_request *req,
2720 char **pparams, int total_params,
2721 char **ppdata, int total_data,
2722 unsigned int max_data_bytes)
2724 /* We must be careful here that we don't return more than the
2725 allowed number of data bytes. If this means returning fewer than
2726 maxentries then so be it. We assume that the redirector has
2727 enough room for the fixed number of parameter bytes it has
2728 requested. */
2729 char *params = *pparams;
2730 char *pdata = *ppdata;
2731 char *data_end;
2732 int dptr_num;
2733 int maxentries;
2734 uint16 info_level;
2735 uint32 resume_key;
2736 uint16 findnext_flags;
2737 bool close_after_request;
2738 bool close_if_end;
2739 bool requires_resume_key;
2740 bool continue_bit;
2741 bool mask_contains_wcard = False;
2742 char *resume_name = NULL;
2743 const char *mask = NULL;
2744 const char *directory = NULL;
2745 char *p = NULL;
2746 uint16 dirtype;
2747 int numentries = 0;
2748 int i, last_entry_off=0;
2749 bool finished = False;
2750 bool dont_descend = False;
2751 bool out_of_space = False;
2752 int space_remaining;
2753 struct ea_list *ea_list = NULL;
2754 NTSTATUS ntstatus = NT_STATUS_OK;
2755 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2756 TALLOC_CTX *ctx = talloc_tos();
2757 struct dptr_struct *dirptr;
2758 struct smbd_server_connection *sconn = req->sconn;
2759 bool backup_priv = false;
2761 if (total_params < 13) {
2762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 return;
2766 dptr_num = SVAL(params,0);
2767 maxentries = SVAL(params,2);
2768 info_level = SVAL(params,4);
2769 resume_key = IVAL(params,6);
2770 findnext_flags = SVAL(params,10);
2771 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2772 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2773 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2774 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2776 if (!continue_bit) {
2777 /* We only need resume_name if continue_bit is zero. */
2778 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2779 params+12,
2780 total_params - 12, STR_TERMINATE, &ntstatus,
2781 &mask_contains_wcard);
2782 if (!NT_STATUS_IS_OK(ntstatus)) {
2783 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2784 complain (it thinks we're asking for the directory above the shared
2785 path or an invalid name). Catch this as the resume name is only compared, never used in
2786 a file access. JRA. */
2787 srvstr_pull_talloc(ctx, params, req->flags2,
2788 &resume_name, params+12,
2789 total_params - 12,
2790 STR_TERMINATE);
2792 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2793 reply_nterror(req, ntstatus);
2794 return;
2799 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2800 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2801 resume_key = %d resume name = %s continue=%d level = %d\n",
2802 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2803 requires_resume_key, resume_key,
2804 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2806 if (!maxentries) {
2807 /* W2K3 seems to treat zero as 1. */
2808 maxentries = 1;
2811 switch (info_level) {
2812 case SMB_FIND_INFO_STANDARD:
2813 case SMB_FIND_EA_SIZE:
2814 case SMB_FIND_EA_LIST:
2815 case SMB_FIND_FILE_DIRECTORY_INFO:
2816 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2817 case SMB_FIND_FILE_NAMES_INFO:
2818 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2819 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2820 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2821 break;
2822 case SMB_FIND_FILE_UNIX:
2823 case SMB_FIND_FILE_UNIX_INFO2:
2824 /* Always use filesystem for UNIX mtime query. */
2825 ask_sharemode = false;
2826 if (!lp_unix_extensions()) {
2827 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2828 return;
2830 break;
2831 default:
2832 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2833 return;
2836 if (info_level == SMB_FIND_EA_LIST) {
2837 uint32 ea_size;
2839 if (total_data < 4) {
2840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2841 return;
2844 ea_size = IVAL(pdata,0);
2845 if (ea_size != total_data) {
2846 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2847 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2849 return;
2852 if (!lp_ea_support(SNUM(conn))) {
2853 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2854 return;
2857 /* Pull out the list of names. */
2858 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2859 if (!ea_list) {
2860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2861 return;
2865 *ppdata = (char *)SMB_REALLOC(
2866 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2867 if(*ppdata == NULL) {
2868 reply_nterror(req, NT_STATUS_NO_MEMORY);
2869 return;
2872 pdata = *ppdata;
2873 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2875 /* Realloc the params space */
2876 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2877 if(*pparams == NULL ) {
2878 reply_nterror(req, NT_STATUS_NO_MEMORY);
2879 return;
2882 params = *pparams;
2884 /* Check that the dptr is valid */
2885 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2886 reply_nterror(req, STATUS_NO_MORE_FILES);
2887 return;
2890 directory = dptr_path(sconn, dptr_num);
2892 /* Get the wildcard mask from the dptr */
2893 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2894 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2895 reply_nterror(req, STATUS_NO_MORE_FILES);
2896 return;
2899 /* Get the attr mask from the dptr */
2900 dirtype = dptr_attr(sconn, dptr_num);
2902 backup_priv = dptr_get_priv(dirptr);
2904 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2905 "backup_priv = %d\n",
2906 dptr_num, mask, dirtype,
2907 (long)dirptr,
2908 dptr_TellDir(dirptr),
2909 (int)backup_priv));
2911 /* Initialize per TRANS2_FIND_NEXT operation data */
2912 dptr_init_search_op(dirptr);
2914 /* We don't need to check for VOL here as this is returned by
2915 a different TRANS2 call. */
2917 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2918 directory,lp_dontdescend(ctx, SNUM(conn))));
2919 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2920 dont_descend = True;
2922 p = pdata;
2923 space_remaining = max_data_bytes;
2924 out_of_space = False;
2926 if (backup_priv) {
2927 become_root();
2931 * Seek to the correct position. We no longer use the resume key but
2932 * depend on the last file name instead.
2935 if(!continue_bit && resume_name && *resume_name) {
2936 SMB_STRUCT_STAT st;
2938 long current_pos = 0;
2940 * Remember, name_to_8_3 is called by
2941 * get_lanman2_dir_entry(), so the resume name
2942 * could be mangled. Ensure we check the unmangled name.
2945 if (mangle_is_mangled(resume_name, conn->params)) {
2946 char *new_resume_name = NULL;
2947 mangle_lookup_name_from_8_3(ctx,
2948 resume_name,
2949 &new_resume_name,
2950 conn->params);
2951 if (new_resume_name) {
2952 resume_name = new_resume_name;
2957 * Fix for NT redirector problem triggered by resume key indexes
2958 * changing between directory scans. We now return a resume key of 0
2959 * and instead look for the filename to continue from (also given
2960 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2961 * findfirst/findnext (as is usual) then the directory pointer
2962 * should already be at the correct place.
2965 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2966 } /* end if resume_name && !continue_bit */
2968 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2969 bool got_exact_match = False;
2971 /* this is a heuristic to avoid seeking the dirptr except when
2972 absolutely necessary. It allows for a filename of about 40 chars */
2973 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2974 out_of_space = True;
2975 finished = False;
2976 } else {
2977 finished = !get_lanman2_dir_entry(ctx,
2978 conn,
2979 dirptr,
2980 req->flags2,
2981 mask,dirtype,info_level,
2982 requires_resume_key,dont_descend,
2983 ask_sharemode,
2984 &p,pdata,data_end,
2985 space_remaining, &out_of_space,
2986 &got_exact_match,
2987 &last_entry_off, ea_list);
2990 if (finished && out_of_space)
2991 finished = False;
2993 if (!finished && !out_of_space)
2994 numentries++;
2997 * As an optimisation if we know we aren't looking
2998 * for a wildcard name (ie. the name matches the wildcard exactly)
2999 * then we can finish on any (first) match.
3000 * This speeds up large directory searches. JRA.
3003 if(got_exact_match)
3004 finished = True;
3006 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3009 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3010 smb_fn_name(req->cmd),
3011 mask, directory, dirtype, numentries ) );
3013 /* Check if we can close the dirptr */
3014 if(close_after_request || (finished && close_if_end)) {
3015 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3016 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3019 if (backup_priv) {
3020 unbecome_root();
3023 /* Set up the return parameter block */
3024 SSVAL(params,0,numentries);
3025 SSVAL(params,2,finished);
3026 SSVAL(params,4,0); /* Never an EA error */
3027 SSVAL(params,6,last_entry_off);
3029 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3030 max_data_bytes);
3032 return;
3035 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3037 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3038 return objid;
3041 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3043 SMB_ASSERT(extended_info != NULL);
3045 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3046 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3047 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3048 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3049 #ifdef SAMBA_VERSION_REVISION
3050 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3051 #endif
3052 extended_info->samba_subversion = 0;
3053 #ifdef SAMBA_VERSION_RC_RELEASE
3054 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3055 #else
3056 #ifdef SAMBA_VERSION_PRE_RELEASE
3057 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3058 #endif
3059 #endif
3060 #ifdef SAMBA_VERSION_VENDOR_PATCH
3061 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3062 #endif
3063 extended_info->samba_gitcommitdate = 0;
3064 #ifdef SAMBA_VERSION_COMMIT_TIME
3065 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3066 #endif
3068 memset(extended_info->samba_version_string, 0,
3069 sizeof(extended_info->samba_version_string));
3071 snprintf (extended_info->samba_version_string,
3072 sizeof(extended_info->samba_version_string),
3073 "%s", samba_version_string());
3076 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3077 TALLOC_CTX *mem_ctx,
3078 uint16_t info_level,
3079 uint16_t flags2,
3080 unsigned int max_data_bytes,
3081 struct smb_filename *fname,
3082 char **ppdata,
3083 int *ret_data_len)
3085 char *pdata, *end_data;
3086 int data_len = 0, len;
3087 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3088 int snum = SNUM(conn);
3089 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3090 char *filename = NULL;
3091 uint32 additional_flags = 0;
3092 struct smb_filename smb_fname;
3093 SMB_STRUCT_STAT st;
3095 if (fname == NULL || fname->base_name == NULL) {
3096 filename = ".";
3097 } else {
3098 filename = fname->base_name;
3101 if (IS_IPC(conn)) {
3102 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3103 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3104 "info level (0x%x) on IPC$.\n",
3105 (unsigned int)info_level));
3106 return NT_STATUS_ACCESS_DENIED;
3110 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3112 ZERO_STRUCT(smb_fname);
3113 smb_fname.base_name = discard_const_p(char, filename);
3115 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3116 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3117 return map_nt_error_from_unix(errno);
3120 st = smb_fname.st;
3122 *ppdata = (char *)SMB_REALLOC(
3123 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3124 if (*ppdata == NULL) {
3125 return NT_STATUS_NO_MEMORY;
3128 pdata = *ppdata;
3129 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3130 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3132 switch (info_level) {
3133 case SMB_INFO_ALLOCATION:
3135 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3136 data_len = 18;
3137 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3138 return map_nt_error_from_unix(errno);
3141 block_size = lp_block_size(snum);
3142 if (bsize < block_size) {
3143 uint64_t factor = block_size/bsize;
3144 bsize = block_size;
3145 dsize /= factor;
3146 dfree /= factor;
3148 if (bsize > block_size) {
3149 uint64_t factor = bsize/block_size;
3150 bsize = block_size;
3151 dsize *= factor;
3152 dfree *= factor;
3154 bytes_per_sector = 512;
3155 sectors_per_unit = bsize/bytes_per_sector;
3157 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3158 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3159 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3161 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3162 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3163 SIVAL(pdata,l1_cUnit,dsize);
3164 SIVAL(pdata,l1_cUnitAvail,dfree);
3165 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3166 break;
3169 case SMB_INFO_VOLUME:
3170 /* Return volume name */
3172 * Add volume serial number - hash of a combination of
3173 * the called hostname and the service name.
3175 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3177 * Win2k3 and previous mess this up by sending a name length
3178 * one byte short. I believe only older clients (OS/2 Win9x) use
3179 * this call so try fixing this by adding a terminating null to
3180 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3182 len = srvstr_push(
3183 pdata, flags2,
3184 pdata+l2_vol_szVolLabel, vname,
3185 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3186 STR_NOALIGN|STR_TERMINATE);
3187 SCVAL(pdata,l2_vol_cch,len);
3188 data_len = l2_vol_szVolLabel + len;
3189 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3190 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3191 len, vname));
3192 break;
3194 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3195 case SMB_FS_ATTRIBUTE_INFORMATION:
3197 additional_flags = 0;
3198 #if defined(HAVE_SYS_QUOTAS)
3199 additional_flags |= FILE_VOLUME_QUOTAS;
3200 #endif
3202 if(lp_nt_acl_support(SNUM(conn))) {
3203 additional_flags |= FILE_PERSISTENT_ACLS;
3206 /* Capabilities are filled in at connection time through STATVFS call */
3207 additional_flags |= conn->fs_capabilities;
3208 additional_flags |= lp_parm_int(conn->params->service,
3209 "share", "fake_fscaps",
3212 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3213 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3214 additional_flags); /* FS ATTRIBUTES */
3216 SIVAL(pdata,4,255); /* Max filename component length */
3217 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3218 and will think we can't do long filenames */
3219 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3220 PTR_DIFF(end_data, pdata+12),
3221 STR_UNICODE);
3222 SIVAL(pdata,8,len);
3223 data_len = 12 + len;
3224 break;
3226 case SMB_QUERY_FS_LABEL_INFO:
3227 case SMB_FS_LABEL_INFORMATION:
3228 len = srvstr_push(pdata, flags2, pdata+4, vname,
3229 PTR_DIFF(end_data, pdata+4), 0);
3230 data_len = 4 + len;
3231 SIVAL(pdata,0,len);
3232 break;
3234 case SMB_QUERY_FS_VOLUME_INFO:
3235 case SMB_FS_VOLUME_INFORMATION:
3238 * Add volume serial number - hash of a combination of
3239 * the called hostname and the service name.
3241 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3242 (str_checksum(get_local_machine_name())<<16));
3244 /* Max label len is 32 characters. */
3245 len = srvstr_push(pdata, flags2, pdata+18, vname,
3246 PTR_DIFF(end_data, pdata+18),
3247 STR_UNICODE);
3248 SIVAL(pdata,12,len);
3249 data_len = 18+len;
3251 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3252 (int)strlen(vname),vname,
3253 lp_servicename(talloc_tos(), snum)));
3254 break;
3256 case SMB_QUERY_FS_SIZE_INFO:
3257 case SMB_FS_SIZE_INFORMATION:
3259 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3260 data_len = 24;
3261 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3262 return map_nt_error_from_unix(errno);
3264 block_size = lp_block_size(snum);
3265 if (bsize < block_size) {
3266 uint64_t factor = block_size/bsize;
3267 bsize = block_size;
3268 dsize /= factor;
3269 dfree /= factor;
3271 if (bsize > block_size) {
3272 uint64_t factor = bsize/block_size;
3273 bsize = block_size;
3274 dsize *= factor;
3275 dfree *= factor;
3277 bytes_per_sector = 512;
3278 sectors_per_unit = bsize/bytes_per_sector;
3279 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3280 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3281 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3282 SBIG_UINT(pdata,0,dsize);
3283 SBIG_UINT(pdata,8,dfree);
3284 SIVAL(pdata,16,sectors_per_unit);
3285 SIVAL(pdata,20,bytes_per_sector);
3286 break;
3289 case SMB_FS_FULL_SIZE_INFORMATION:
3291 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3292 data_len = 32;
3293 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3294 return map_nt_error_from_unix(errno);
3296 block_size = lp_block_size(snum);
3297 if (bsize < block_size) {
3298 uint64_t factor = block_size/bsize;
3299 bsize = block_size;
3300 dsize /= factor;
3301 dfree /= factor;
3303 if (bsize > block_size) {
3304 uint64_t factor = bsize/block_size;
3305 bsize = block_size;
3306 dsize *= factor;
3307 dfree *= factor;
3309 bytes_per_sector = 512;
3310 sectors_per_unit = bsize/bytes_per_sector;
3311 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3312 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3313 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3314 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3315 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3316 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3317 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3318 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3319 break;
3322 case SMB_QUERY_FS_DEVICE_INFO:
3323 case SMB_FS_DEVICE_INFORMATION:
3325 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3327 if (!CAN_WRITE(conn)) {
3328 characteristics |= FILE_READ_ONLY_DEVICE;
3330 data_len = 8;
3331 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3332 SIVAL(pdata,4,characteristics);
3333 break;
3336 #ifdef HAVE_SYS_QUOTAS
3337 case SMB_FS_QUOTA_INFORMATION:
3339 * what we have to send --metze:
3341 * Unknown1: 24 NULL bytes
3342 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3344 * Quota Flags: 2 byte :
3345 * Unknown3: 6 NULL bytes
3347 * 48 bytes total
3349 * details for Quota Flags:
3351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3354 * 0x0001 Enable Quotas: enable quota for this fs
3358 /* we need to fake up a fsp here,
3359 * because its not send in this call
3361 files_struct fsp;
3362 SMB_NTQUOTA_STRUCT quotas;
3364 ZERO_STRUCT(fsp);
3365 ZERO_STRUCT(quotas);
3367 fsp.conn = conn;
3368 fsp.fnum = FNUM_FIELD_INVALID;
3370 /* access check */
3371 if (get_current_uid(conn) != 0) {
3372 DEBUG(0,("set_user_quota: access_denied "
3373 "service [%s] user [%s]\n",
3374 lp_servicename(talloc_tos(), SNUM(conn)),
3375 conn->session_info->unix_info->unix_name));
3376 return NT_STATUS_ACCESS_DENIED;
3379 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3380 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3381 return map_nt_error_from_unix(errno);
3384 data_len = 48;
3386 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3387 lp_servicename(talloc_tos(), SNUM(conn))));
3389 /* Unknown1 24 NULL bytes*/
3390 SBIG_UINT(pdata,0,(uint64_t)0);
3391 SBIG_UINT(pdata,8,(uint64_t)0);
3392 SBIG_UINT(pdata,16,(uint64_t)0);
3394 /* Default Soft Quota 8 bytes */
3395 SBIG_UINT(pdata,24,quotas.softlim);
3397 /* Default Hard Quota 8 bytes */
3398 SBIG_UINT(pdata,32,quotas.hardlim);
3400 /* Quota flag 2 bytes */
3401 SSVAL(pdata,40,quotas.qflags);
3403 /* Unknown3 6 NULL bytes */
3404 SSVAL(pdata,42,0);
3405 SIVAL(pdata,44,0);
3407 break;
3409 #endif /* HAVE_SYS_QUOTAS */
3410 case SMB_FS_OBJECTID_INFORMATION:
3412 unsigned char objid[16];
3413 struct smb_extended_info extended_info;
3414 memcpy(pdata,create_volume_objectid(conn, objid),16);
3415 samba_extended_info_version (&extended_info);
3416 SIVAL(pdata,16,extended_info.samba_magic);
3417 SIVAL(pdata,20,extended_info.samba_version);
3418 SIVAL(pdata,24,extended_info.samba_subversion);
3419 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3420 memcpy(pdata+36,extended_info.samba_version_string,28);
3421 data_len = 64;
3422 break;
3426 * Query the version and capabilities of the CIFS UNIX extensions
3427 * in use.
3430 case SMB_QUERY_CIFS_UNIX_INFO:
3432 bool large_write = lp_min_receive_file_size() &&
3433 !srv_is_signing_active(conn->sconn);
3434 bool large_read = !srv_is_signing_active(conn->sconn);
3435 int encrypt_caps = 0;
3437 if (!lp_unix_extensions()) {
3438 return NT_STATUS_INVALID_LEVEL;
3441 switch (conn->encrypt_level) {
3442 case SMB_SIGNING_OFF:
3443 encrypt_caps = 0;
3444 break;
3445 case SMB_SIGNING_IF_REQUIRED:
3446 case SMB_SIGNING_DEFAULT:
3447 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3448 break;
3449 case SMB_SIGNING_REQUIRED:
3450 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3451 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3452 large_write = false;
3453 large_read = false;
3454 break;
3457 data_len = 12;
3458 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3459 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3461 /* We have POSIX ACLs, pathname, encryption,
3462 * large read/write, and locking capability. */
3464 SBIG_UINT(pdata,4,((uint64_t)(
3465 CIFS_UNIX_POSIX_ACLS_CAP|
3466 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3467 CIFS_UNIX_FCNTL_LOCKS_CAP|
3468 CIFS_UNIX_EXTATTR_CAP|
3469 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3470 encrypt_caps|
3471 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3472 (large_write ?
3473 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3474 break;
3477 case SMB_QUERY_POSIX_FS_INFO:
3479 int rc;
3480 vfs_statvfs_struct svfs;
3482 if (!lp_unix_extensions()) {
3483 return NT_STATUS_INVALID_LEVEL;
3486 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3488 if (!rc) {
3489 data_len = 56;
3490 SIVAL(pdata,0,svfs.OptimalTransferSize);
3491 SIVAL(pdata,4,svfs.BlockSize);
3492 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3493 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3494 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3495 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3496 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3497 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3499 #ifdef EOPNOTSUPP
3500 } else if (rc == EOPNOTSUPP) {
3501 return NT_STATUS_INVALID_LEVEL;
3502 #endif /* EOPNOTSUPP */
3503 } else {
3504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3505 return NT_STATUS_DOS(ERRSRV, ERRerror);
3507 break;
3510 case SMB_QUERY_POSIX_WHOAMI:
3512 uint32_t flags = 0;
3513 uint32_t sid_bytes;
3514 int i;
3516 if (!lp_unix_extensions()) {
3517 return NT_STATUS_INVALID_LEVEL;
3520 if (max_data_bytes < 40) {
3521 return NT_STATUS_BUFFER_TOO_SMALL;
3524 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3525 flags |= SMB_WHOAMI_GUEST;
3528 /* NOTE: 8 bytes for UID/GID, irrespective of native
3529 * platform size. This matches
3530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3532 data_len = 4 /* flags */
3533 + 4 /* flag mask */
3534 + 8 /* uid */
3535 + 8 /* gid */
3536 + 4 /* ngroups */
3537 + 4 /* num_sids */
3538 + 4 /* SID bytes */
3539 + 4 /* pad/reserved */
3540 + (conn->session_info->unix_token->ngroups * 8)
3541 /* groups list */
3542 + (conn->session_info->security_token->num_sids *
3543 SID_MAX_SIZE)
3544 /* SID list */;
3546 SIVAL(pdata, 0, flags);
3547 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3548 SBIG_UINT(pdata, 8,
3549 (uint64_t)conn->session_info->unix_token->uid);
3550 SBIG_UINT(pdata, 16,
3551 (uint64_t)conn->session_info->unix_token->gid);
3554 if (data_len >= max_data_bytes) {
3555 /* Potential overflow, skip the GIDs and SIDs. */
3557 SIVAL(pdata, 24, 0); /* num_groups */
3558 SIVAL(pdata, 28, 0); /* num_sids */
3559 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3560 SIVAL(pdata, 36, 0); /* reserved */
3562 data_len = 40;
3563 break;
3566 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3567 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3569 /* We walk the SID list twice, but this call is fairly
3570 * infrequent, and I don't expect that it's performance
3571 * sensitive -- jpeach
3573 for (i = 0, sid_bytes = 0;
3574 i < conn->session_info->security_token->num_sids; ++i) {
3575 sid_bytes += ndr_size_dom_sid(
3576 &conn->session_info->security_token->sids[i],
3580 /* SID list byte count */
3581 SIVAL(pdata, 32, sid_bytes);
3583 /* 4 bytes pad/reserved - must be zero */
3584 SIVAL(pdata, 36, 0);
3585 data_len = 40;
3587 /* GID list */
3588 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3589 SBIG_UINT(pdata, data_len,
3590 (uint64_t)conn->session_info->unix_token->groups[i]);
3591 data_len += 8;
3594 /* SID list */
3595 for (i = 0;
3596 i < conn->session_info->security_token->num_sids; ++i) {
3597 int sid_len = ndr_size_dom_sid(
3598 &conn->session_info->security_token->sids[i],
3601 sid_linearize(pdata + data_len, sid_len,
3602 &conn->session_info->security_token->sids[i]);
3603 data_len += sid_len;
3606 break;
3609 case SMB_MAC_QUERY_FS_INFO:
3611 * Thursby MAC extension... ONLY on NTFS filesystems
3612 * once we do streams then we don't need this
3614 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3615 data_len = 88;
3616 SIVAL(pdata,84,0x100); /* Don't support mac... */
3617 break;
3619 /* drop through */
3620 default:
3621 return NT_STATUS_INVALID_LEVEL;
3624 *ret_data_len = data_len;
3625 return NT_STATUS_OK;
3628 /****************************************************************************
3629 Reply to a TRANS2_QFSINFO (query filesystem info).
3630 ****************************************************************************/
3632 static void call_trans2qfsinfo(connection_struct *conn,
3633 struct smb_request *req,
3634 char **pparams, int total_params,
3635 char **ppdata, int total_data,
3636 unsigned int max_data_bytes)
3638 char *params = *pparams;
3639 uint16_t info_level;
3640 int data_len = 0;
3641 NTSTATUS status;
3643 if (total_params < 2) {
3644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3645 return;
3648 info_level = SVAL(params,0);
3650 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3651 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3652 DEBUG(0,("call_trans2qfsinfo: encryption required "
3653 "and info level 0x%x sent.\n",
3654 (unsigned int)info_level));
3655 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3656 return;
3660 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3662 status = smbd_do_qfsinfo(conn, req,
3663 info_level,
3664 req->flags2,
3665 max_data_bytes,
3666 NULL,
3667 ppdata, &data_len);
3668 if (!NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3670 return;
3673 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3674 max_data_bytes);
3676 DEBUG( 4, ( "%s info_level = %d\n",
3677 smb_fn_name(req->cmd), info_level) );
3679 return;
3682 /****************************************************************************
3683 Reply to a TRANS2_SETFSINFO (set filesystem info).
3684 ****************************************************************************/
3686 static void call_trans2setfsinfo(connection_struct *conn,
3687 struct smb_request *req,
3688 char **pparams, int total_params,
3689 char **ppdata, int total_data,
3690 unsigned int max_data_bytes)
3692 struct smbd_server_connection *sconn = req->sconn;
3693 char *pdata = *ppdata;
3694 char *params = *pparams;
3695 uint16 info_level;
3697 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3698 lp_servicename(talloc_tos(), SNUM(conn))));
3700 /* */
3701 if (total_params < 4) {
3702 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3703 total_params));
3704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3705 return;
3708 info_level = SVAL(params,2);
3710 if (IS_IPC(conn)) {
3711 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3712 info_level != SMB_SET_CIFS_UNIX_INFO) {
3713 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3714 "info level (0x%x) on IPC$.\n",
3715 (unsigned int)info_level));
3716 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3717 return;
3721 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3722 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3723 DEBUG(0,("call_trans2setfsinfo: encryption required "
3724 "and info level 0x%x sent.\n",
3725 (unsigned int)info_level));
3726 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3727 return;
3731 switch(info_level) {
3732 case SMB_SET_CIFS_UNIX_INFO:
3733 if (!lp_unix_extensions()) {
3734 DEBUG(2,("call_trans2setfsinfo: "
3735 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3736 "unix extensions off\n"));
3737 reply_nterror(req,
3738 NT_STATUS_INVALID_LEVEL);
3739 return;
3742 /* There should be 12 bytes of capabilities set. */
3743 if (total_data < 12) {
3744 reply_nterror(
3745 req,
3746 NT_STATUS_INVALID_PARAMETER);
3747 return;
3749 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3750 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3751 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3752 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3753 /* Just print these values for now. */
3754 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3755 "major = %u, minor = %u cap_low = 0x%x, "
3756 "cap_high = 0x%xn",
3757 (unsigned int)sconn->
3758 smb1.unix_info.client_major,
3759 (unsigned int)sconn->
3760 smb1.unix_info.client_minor,
3761 (unsigned int)sconn->
3762 smb1.unix_info.client_cap_low,
3763 (unsigned int)sconn->
3764 smb1.unix_info.client_cap_high));
3766 /* Here is where we must switch to posix pathname processing... */
3767 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3768 lp_set_posix_pathnames();
3769 mangle_change_to_posix();
3772 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3773 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3774 /* Client that knows how to do posix locks,
3775 * but not posix open/mkdir operations. Set a
3776 * default type for read/write checks. */
3778 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3781 break;
3783 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3785 NTSTATUS status;
3786 size_t param_len = 0;
3787 size_t data_len = total_data;
3789 if (!lp_unix_extensions()) {
3790 reply_nterror(
3791 req,
3792 NT_STATUS_INVALID_LEVEL);
3793 return;
3796 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3797 reply_nterror(
3798 req,
3799 NT_STATUS_NOT_SUPPORTED);
3800 return;
3803 if (req->sconn->smb1.echo_handler.trusted_fde) {
3804 DEBUG( 2,("call_trans2setfsinfo: "
3805 "request transport encryption disabled"
3806 "with 'fork echo handler = yes'\n"));
3807 reply_nterror(
3808 req,
3809 NT_STATUS_NOT_SUPPORTED);
3810 return;
3813 DEBUG( 4,("call_trans2setfsinfo: "
3814 "request transport encryption.\n"));
3816 status = srv_request_encryption_setup(conn,
3817 (unsigned char **)ppdata,
3818 &data_len,
3819 (unsigned char **)pparams,
3820 &param_len);
3822 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3823 !NT_STATUS_IS_OK(status)) {
3824 reply_nterror(req, status);
3825 return;
3828 send_trans2_replies(conn, req,
3829 *pparams,
3830 param_len,
3831 *ppdata,
3832 data_len,
3833 max_data_bytes);
3835 if (NT_STATUS_IS_OK(status)) {
3836 /* Server-side transport
3837 * encryption is now *on*. */
3838 status = srv_encryption_start(conn);
3839 if (!NT_STATUS_IS_OK(status)) {
3840 char *reason = talloc_asprintf(talloc_tos(),
3841 "Failure in setting "
3842 "up encrypted transport: %s",
3843 nt_errstr(status));
3844 exit_server_cleanly(reason);
3847 return;
3850 case SMB_FS_QUOTA_INFORMATION:
3852 files_struct *fsp = NULL;
3853 SMB_NTQUOTA_STRUCT quotas;
3855 ZERO_STRUCT(quotas);
3857 /* access check */
3858 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3859 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3860 lp_servicename(talloc_tos(), SNUM(conn)),
3861 conn->session_info->unix_info->unix_name));
3862 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3863 return;
3866 /* note: normaly there're 48 bytes,
3867 * but we didn't use the last 6 bytes for now
3868 * --metze
3870 fsp = file_fsp(req, SVAL(params,0));
3872 if (!check_fsp_ntquota_handle(conn, req,
3873 fsp)) {
3874 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3875 reply_nterror(
3876 req, NT_STATUS_INVALID_HANDLE);
3877 return;
3880 if (total_data < 42) {
3881 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3882 total_data));
3883 reply_nterror(
3884 req,
3885 NT_STATUS_INVALID_PARAMETER);
3886 return;
3889 /* unknown_1 24 NULL bytes in pdata*/
3891 /* the soft quotas 8 bytes (uint64_t)*/
3892 quotas.softlim = BVAL(pdata,24);
3894 /* the hard quotas 8 bytes (uint64_t)*/
3895 quotas.hardlim = BVAL(pdata,32);
3897 /* quota_flags 2 bytes **/
3898 quotas.qflags = SVAL(pdata,40);
3900 /* unknown_2 6 NULL bytes follow*/
3902 /* now set the quotas */
3903 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3904 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3905 reply_nterror(req, map_nt_error_from_unix(errno));
3906 return;
3909 break;
3911 default:
3912 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3913 info_level));
3914 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3915 return;
3916 break;
3920 * sending this reply works fine,
3921 * but I'm not sure it's the same
3922 * like windows do...
3923 * --metze
3925 reply_outbuf(req, 10, 0);
3928 #if defined(HAVE_POSIX_ACLS)
3929 /****************************************************************************
3930 Utility function to count the number of entries in a POSIX acl.
3931 ****************************************************************************/
3933 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3935 unsigned int ace_count = 0;
3936 int entry_id = SMB_ACL_FIRST_ENTRY;
3937 SMB_ACL_ENTRY_T entry;
3939 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3940 /* get_next... */
3941 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3942 entry_id = SMB_ACL_NEXT_ENTRY;
3944 ace_count++;
3946 return ace_count;
3949 /****************************************************************************
3950 Utility function to marshall a POSIX acl into wire format.
3951 ****************************************************************************/
3953 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3955 int entry_id = SMB_ACL_FIRST_ENTRY;
3956 SMB_ACL_ENTRY_T entry;
3958 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3959 SMB_ACL_TAG_T tagtype;
3960 SMB_ACL_PERMSET_T permset;
3961 unsigned char perms = 0;
3962 unsigned int own_grp;
3964 /* get_next... */
3965 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3966 entry_id = SMB_ACL_NEXT_ENTRY;
3969 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3970 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3971 return False;
3974 if (sys_acl_get_permset(entry, &permset) == -1) {
3975 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3976 return False;
3979 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3980 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3981 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3983 SCVAL(pdata,1,perms);
3985 switch (tagtype) {
3986 case SMB_ACL_USER_OBJ:
3987 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3988 own_grp = (unsigned int)pst->st_ex_uid;
3989 SIVAL(pdata,2,own_grp);
3990 SIVAL(pdata,6,0);
3991 break;
3992 case SMB_ACL_USER:
3994 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3995 if (!puid) {
3996 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3997 return False;
3999 own_grp = (unsigned int)*puid;
4000 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4001 SIVAL(pdata,2,own_grp);
4002 SIVAL(pdata,6,0);
4003 break;
4005 case SMB_ACL_GROUP_OBJ:
4006 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4007 own_grp = (unsigned int)pst->st_ex_gid;
4008 SIVAL(pdata,2,own_grp);
4009 SIVAL(pdata,6,0);
4010 break;
4011 case SMB_ACL_GROUP:
4013 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4014 if (!pgid) {
4015 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4016 return False;
4018 own_grp = (unsigned int)*pgid;
4019 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4020 SIVAL(pdata,2,own_grp);
4021 SIVAL(pdata,6,0);
4022 break;
4024 case SMB_ACL_MASK:
4025 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4026 SIVAL(pdata,2,0xFFFFFFFF);
4027 SIVAL(pdata,6,0xFFFFFFFF);
4028 break;
4029 case SMB_ACL_OTHER:
4030 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4031 SIVAL(pdata,2,0xFFFFFFFF);
4032 SIVAL(pdata,6,0xFFFFFFFF);
4033 break;
4034 default:
4035 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4036 return False;
4038 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4041 return True;
4043 #endif
4045 /****************************************************************************
4046 Store the FILE_UNIX_BASIC info.
4047 ****************************************************************************/
4049 static char *store_file_unix_basic(connection_struct *conn,
4050 char *pdata,
4051 files_struct *fsp,
4052 const SMB_STRUCT_STAT *psbuf)
4054 uint64_t file_index = get_FileIndex(conn, psbuf);
4055 dev_t devno;
4057 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4058 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4060 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4061 pdata += 8;
4063 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4064 pdata += 8;
4066 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4067 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4068 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4069 pdata += 24;
4071 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4072 SIVAL(pdata,4,0);
4073 pdata += 8;
4075 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4076 SIVAL(pdata,4,0);
4077 pdata += 8;
4079 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4080 pdata += 4;
4082 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4083 devno = psbuf->st_ex_rdev;
4084 } else {
4085 devno = psbuf->st_ex_dev;
4088 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4089 SIVAL(pdata,4,0);
4090 pdata += 8;
4092 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4093 SIVAL(pdata,4,0);
4094 pdata += 8;
4096 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4097 pdata += 8;
4099 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4100 SIVAL(pdata,4,0);
4101 pdata += 8;
4103 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4104 SIVAL(pdata,4,0);
4105 pdata += 8;
4107 return pdata;
4110 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4111 * the chflags(2) (or equivalent) flags.
4113 * XXX: this really should be behind the VFS interface. To do this, we would
4114 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4115 * Each VFS module could then implement its own mapping as appropriate for the
4116 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4118 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4119 info2_flags_map[] =
4121 #ifdef UF_NODUMP
4122 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4123 #endif
4125 #ifdef UF_IMMUTABLE
4126 { UF_IMMUTABLE, EXT_IMMUTABLE },
4127 #endif
4129 #ifdef UF_APPEND
4130 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4131 #endif
4133 #ifdef UF_HIDDEN
4134 { UF_HIDDEN, EXT_HIDDEN },
4135 #endif
4137 /* Do not remove. We need to guarantee that this array has at least one
4138 * entry to build on HP-UX.
4140 { 0, 0 }
4144 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4145 uint32 *smb_fflags, uint32 *smb_fmask)
4147 int i;
4149 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4150 *smb_fmask |= info2_flags_map[i].smb_fflag;
4151 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4152 *smb_fflags |= info2_flags_map[i].smb_fflag;
4157 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4158 const uint32 smb_fflags,
4159 const uint32 smb_fmask,
4160 int *stat_fflags)
4162 uint32 max_fmask = 0;
4163 int i;
4165 *stat_fflags = psbuf->st_ex_flags;
4167 /* For each flags requested in smb_fmask, check the state of the
4168 * corresponding flag in smb_fflags and set or clear the matching
4169 * stat flag.
4172 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4173 max_fmask |= info2_flags_map[i].smb_fflag;
4174 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4175 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4176 *stat_fflags |= info2_flags_map[i].stat_fflag;
4177 } else {
4178 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4183 /* If smb_fmask is asking to set any bits that are not supported by
4184 * our flag mappings, we should fail.
4186 if ((smb_fmask & max_fmask) != smb_fmask) {
4187 return False;
4190 return True;
4194 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4195 * of file flags and birth (create) time.
4197 static char *store_file_unix_basic_info2(connection_struct *conn,
4198 char *pdata,
4199 files_struct *fsp,
4200 const SMB_STRUCT_STAT *psbuf)
4202 uint32 file_flags = 0;
4203 uint32 flags_mask = 0;
4205 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4207 /* Create (birth) time 64 bit */
4208 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4209 pdata += 8;
4211 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4212 SIVAL(pdata, 0, file_flags); /* flags */
4213 SIVAL(pdata, 4, flags_mask); /* mask */
4214 pdata += 8;
4216 return pdata;
4219 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4220 const struct stream_struct *streams,
4221 char *data,
4222 unsigned int max_data_bytes,
4223 unsigned int *data_size)
4225 unsigned int i;
4226 unsigned int ofs = 0;
4228 for (i = 0; i < num_streams; i++) {
4229 unsigned int next_offset;
4230 size_t namelen;
4231 smb_ucs2_t *namebuf;
4233 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4234 streams[i].name, &namelen) ||
4235 namelen <= 2)
4237 return NT_STATUS_INVALID_PARAMETER;
4241 * name_buf is now null-terminated, we need to marshall as not
4242 * terminated
4245 namelen -= 2;
4248 * We cannot overflow ...
4250 if ((ofs + 24 + namelen) > max_data_bytes) {
4251 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4252 i));
4253 TALLOC_FREE(namebuf);
4254 return STATUS_BUFFER_OVERFLOW;
4257 SIVAL(data, ofs+4, namelen);
4258 SOFF_T(data, ofs+8, streams[i].size);
4259 SOFF_T(data, ofs+16, streams[i].alloc_size);
4260 memcpy(data+ofs+24, namebuf, namelen);
4261 TALLOC_FREE(namebuf);
4263 next_offset = ofs + 24 + namelen;
4265 if (i == num_streams-1) {
4266 SIVAL(data, ofs, 0);
4268 else {
4269 unsigned int align = ndr_align_size(next_offset, 8);
4271 if ((next_offset + align) > max_data_bytes) {
4272 DEBUG(10, ("refusing to overflow align "
4273 "reply at stream %u\n",
4274 i));
4275 TALLOC_FREE(namebuf);
4276 return STATUS_BUFFER_OVERFLOW;
4279 memset(data+next_offset, 0, align);
4280 next_offset += align;
4282 SIVAL(data, ofs, next_offset - ofs);
4283 ofs = next_offset;
4286 ofs = next_offset;
4289 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4291 *data_size = ofs;
4293 return NT_STATUS_OK;
4296 /****************************************************************************
4297 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4298 ****************************************************************************/
4300 static void call_trans2qpipeinfo(connection_struct *conn,
4301 struct smb_request *req,
4302 unsigned int tran_call,
4303 char **pparams, int total_params,
4304 char **ppdata, int total_data,
4305 unsigned int max_data_bytes)
4307 char *params = *pparams;
4308 char *pdata = *ppdata;
4309 unsigned int data_size = 0;
4310 unsigned int param_size = 2;
4311 uint16 info_level;
4312 files_struct *fsp;
4314 if (!params) {
4315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4316 return;
4319 if (total_params < 4) {
4320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4321 return;
4324 fsp = file_fsp(req, SVAL(params,0));
4325 if (!fsp_is_np(fsp)) {
4326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4327 return;
4330 info_level = SVAL(params,2);
4332 *pparams = (char *)SMB_REALLOC(*pparams,2);
4333 if (*pparams == NULL) {
4334 reply_nterror(req, NT_STATUS_NO_MEMORY);
4335 return;
4337 params = *pparams;
4338 SSVAL(params,0,0);
4339 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4340 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4341 if (*ppdata == NULL ) {
4342 reply_nterror(req, NT_STATUS_NO_MEMORY);
4343 return;
4345 pdata = *ppdata;
4347 switch (info_level) {
4348 case SMB_FILE_STANDARD_INFORMATION:
4349 memset(pdata,0,24);
4350 SOFF_T(pdata,0,4096LL);
4351 SIVAL(pdata,16,1);
4352 SIVAL(pdata,20,1);
4353 data_size = 24;
4354 break;
4356 default:
4357 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4358 return;
4361 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4362 max_data_bytes);
4364 return;
4367 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4368 TALLOC_CTX *mem_ctx,
4369 uint16_t info_level,
4370 files_struct *fsp,
4371 struct smb_filename *smb_fname,
4372 bool delete_pending,
4373 struct timespec write_time_ts,
4374 struct ea_list *ea_list,
4375 int lock_data_count,
4376 char *lock_data,
4377 uint16_t flags2,
4378 unsigned int max_data_bytes,
4379 char **ppdata,
4380 unsigned int *pdata_size)
4382 char *pdata = *ppdata;
4383 char *dstart, *dend;
4384 unsigned int data_size;
4385 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4386 time_t create_time, mtime, atime, c_time;
4387 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4388 char *p;
4389 char *base_name;
4390 char *dos_fname;
4391 int mode;
4392 int nlink;
4393 NTSTATUS status;
4394 uint64_t file_size = 0;
4395 uint64_t pos = 0;
4396 uint64_t allocation_size = 0;
4397 uint64_t file_index = 0;
4398 uint32_t access_mask = 0;
4400 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4401 return NT_STATUS_INVALID_LEVEL;
4404 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4405 smb_fname_str_dbg(smb_fname),
4406 fsp_fnum_dbg(fsp),
4407 info_level, max_data_bytes));
4409 mode = dos_mode(conn, smb_fname);
4410 nlink = psbuf->st_ex_nlink;
4412 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4413 nlink = 1;
4416 if ((nlink > 0) && delete_pending) {
4417 nlink -= 1;
4420 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4421 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4422 if (*ppdata == NULL) {
4423 return NT_STATUS_NO_MEMORY;
4425 pdata = *ppdata;
4426 dstart = pdata;
4427 dend = dstart + data_size - 1;
4429 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4430 update_stat_ex_mtime(psbuf, write_time_ts);
4433 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4434 mtime_ts = psbuf->st_ex_mtime;
4435 atime_ts = psbuf->st_ex_atime;
4436 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4438 if (lp_dos_filetime_resolution(SNUM(conn))) {
4439 dos_filetime_timespec(&create_time_ts);
4440 dos_filetime_timespec(&mtime_ts);
4441 dos_filetime_timespec(&atime_ts);
4442 dos_filetime_timespec(&ctime_ts);
4445 create_time = convert_timespec_to_time_t(create_time_ts);
4446 mtime = convert_timespec_to_time_t(mtime_ts);
4447 atime = convert_timespec_to_time_t(atime_ts);
4448 c_time = convert_timespec_to_time_t(ctime_ts);
4450 p = strrchr_m(smb_fname->base_name,'/');
4451 if (!p)
4452 base_name = smb_fname->base_name;
4453 else
4454 base_name = p+1;
4456 /* NT expects the name to be in an exact form of the *full*
4457 filename. See the trans2 torture test */
4458 if (ISDOT(base_name)) {
4459 dos_fname = talloc_strdup(mem_ctx, "\\");
4460 if (!dos_fname) {
4461 return NT_STATUS_NO_MEMORY;
4463 } else {
4464 dos_fname = talloc_asprintf(mem_ctx,
4465 "\\%s",
4466 smb_fname->base_name);
4467 if (!dos_fname) {
4468 return NT_STATUS_NO_MEMORY;
4470 if (is_ntfs_stream_smb_fname(smb_fname)) {
4471 dos_fname = talloc_asprintf(dos_fname, "%s",
4472 smb_fname->stream_name);
4473 if (!dos_fname) {
4474 return NT_STATUS_NO_MEMORY;
4478 string_replace(dos_fname, '/', '\\');
4481 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4483 if (!fsp) {
4484 /* Do we have this path open ? */
4485 files_struct *fsp1;
4486 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4487 fsp1 = file_find_di_first(conn->sconn, fileid);
4488 if (fsp1 && fsp1->initial_allocation_size) {
4489 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4493 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4494 file_size = get_file_size_stat(psbuf);
4497 if (fsp) {
4498 pos = fsp->fh->position_information;
4501 if (fsp) {
4502 access_mask = fsp->access_mask;
4503 } else {
4504 /* GENERIC_EXECUTE mapping from Windows */
4505 access_mask = 0x12019F;
4508 /* This should be an index number - looks like
4509 dev/ino to me :-)
4511 I think this causes us to fail the IFSKIT
4512 BasicFileInformationTest. -tpot */
4513 file_index = get_FileIndex(conn, psbuf);
4515 switch (info_level) {
4516 case SMB_INFO_STANDARD:
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4518 data_size = 22;
4519 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4520 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4521 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4522 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4523 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4524 SSVAL(pdata,l1_attrFile,mode);
4525 break;
4527 case SMB_INFO_QUERY_EA_SIZE:
4529 unsigned int ea_size =
4530 estimate_ea_size(conn, fsp,
4531 smb_fname);
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4533 data_size = 26;
4534 srv_put_dos_date2(pdata,0,create_time);
4535 srv_put_dos_date2(pdata,4,atime);
4536 srv_put_dos_date2(pdata,8,mtime); /* write time */
4537 SIVAL(pdata,12,(uint32)file_size);
4538 SIVAL(pdata,16,(uint32)allocation_size);
4539 SSVAL(pdata,20,mode);
4540 SIVAL(pdata,22,ea_size);
4541 break;
4544 case SMB_INFO_IS_NAME_VALID:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4546 if (fsp) {
4547 /* os/2 needs this ? really ?*/
4548 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4550 /* This is only reached for qpathinfo */
4551 data_size = 0;
4552 break;
4554 case SMB_INFO_QUERY_EAS_FROM_LIST:
4556 size_t total_ea_len = 0;
4557 struct ea_list *ea_file_list = NULL;
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4560 status =
4561 get_ea_list_from_file(mem_ctx, conn, fsp,
4562 smb_fname,
4563 &total_ea_len, &ea_file_list);
4564 if (!NT_STATUS_IS_OK(status)) {
4565 return status;
4568 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4570 if (!ea_list || (total_ea_len > data_size)) {
4571 data_size = 4;
4572 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4573 break;
4576 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4577 break;
4580 case SMB_INFO_QUERY_ALL_EAS:
4582 /* We have data_size bytes to put EA's into. */
4583 size_t total_ea_len = 0;
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4586 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4587 smb_fname,
4588 &total_ea_len, &ea_list);
4589 if (!NT_STATUS_IS_OK(status)) {
4590 return status;
4593 if (!ea_list || (total_ea_len > data_size)) {
4594 data_size = 4;
4595 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4596 break;
4599 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4600 break;
4603 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4605 /* This is FileFullEaInformation - 0xF which maps to
4606 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4608 /* We have data_size bytes to put EA's into. */
4609 size_t total_ea_len = 0;
4610 struct ea_list *ea_file_list = NULL;
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4614 /*TODO: add filtering and index handling */
4616 status =
4617 get_ea_list_from_file(mem_ctx, conn, fsp,
4618 smb_fname,
4619 &total_ea_len, &ea_file_list);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 return status;
4623 if (!ea_file_list) {
4624 return NT_STATUS_NO_EAS_ON_FILE;
4627 status = fill_ea_chained_buffer(mem_ctx,
4628 pdata,
4629 data_size,
4630 &data_size,
4631 conn, ea_file_list);
4632 if (!NT_STATUS_IS_OK(status)) {
4633 return status;
4635 break;
4638 case SMB_FILE_BASIC_INFORMATION:
4639 case SMB_QUERY_FILE_BASIC_INFO:
4641 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4643 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4644 } else {
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4646 data_size = 40;
4647 SIVAL(pdata,36,0);
4649 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4650 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4651 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4652 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4653 SIVAL(pdata,32,mode);
4655 DEBUG(5,("SMB_QFBI - "));
4656 DEBUG(5,("create: %s ", ctime(&create_time)));
4657 DEBUG(5,("access: %s ", ctime(&atime)));
4658 DEBUG(5,("write: %s ", ctime(&mtime)));
4659 DEBUG(5,("change: %s ", ctime(&c_time)));
4660 DEBUG(5,("mode: %x\n", mode));
4661 break;
4663 case SMB_FILE_STANDARD_INFORMATION:
4664 case SMB_QUERY_FILE_STANDARD_INFO:
4666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4667 data_size = 24;
4668 SOFF_T(pdata,0,allocation_size);
4669 SOFF_T(pdata,8,file_size);
4670 SIVAL(pdata,16,nlink);
4671 SCVAL(pdata,20,delete_pending?1:0);
4672 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4673 SSVAL(pdata,22,0); /* Padding. */
4674 break;
4676 case SMB_FILE_EA_INFORMATION:
4677 case SMB_QUERY_FILE_EA_INFO:
4679 unsigned int ea_size =
4680 estimate_ea_size(conn, fsp, smb_fname);
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4682 data_size = 4;
4683 SIVAL(pdata,0,ea_size);
4684 break;
4687 /* Get the 8.3 name - used if NT SMB was negotiated. */
4688 case SMB_QUERY_FILE_ALT_NAME_INFO:
4689 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4691 int len;
4692 char mangled_name[13];
4693 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4694 if (!name_to_8_3(base_name,mangled_name,
4695 True,conn->params)) {
4696 return NT_STATUS_NO_MEMORY;
4698 len = srvstr_push(dstart, flags2,
4699 pdata+4, mangled_name,
4700 PTR_DIFF(dend, pdata+4),
4701 STR_UNICODE);
4702 data_size = 4 + len;
4703 SIVAL(pdata,0,len);
4704 break;
4707 case SMB_QUERY_FILE_NAME_INFO:
4709 int len;
4711 this must be *exactly* right for ACLs on mapped drives to work
4713 len = srvstr_push(dstart, flags2,
4714 pdata+4, dos_fname,
4715 PTR_DIFF(dend, pdata+4),
4716 STR_UNICODE);
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4718 data_size = 4 + len;
4719 SIVAL(pdata,0,len);
4720 break;
4723 case SMB_FILE_ALLOCATION_INFORMATION:
4724 case SMB_QUERY_FILE_ALLOCATION_INFO:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4726 data_size = 8;
4727 SOFF_T(pdata,0,allocation_size);
4728 break;
4730 case SMB_FILE_END_OF_FILE_INFORMATION:
4731 case SMB_QUERY_FILE_END_OF_FILEINFO:
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4733 data_size = 8;
4734 SOFF_T(pdata,0,file_size);
4735 break;
4737 case SMB_QUERY_FILE_ALL_INFO:
4738 case SMB_FILE_ALL_INFORMATION:
4740 int len;
4741 unsigned int ea_size =
4742 estimate_ea_size(conn, fsp, smb_fname);
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4744 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4745 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4746 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4747 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4748 SIVAL(pdata,32,mode);
4749 SIVAL(pdata,36,0); /* padding. */
4750 pdata += 40;
4751 SOFF_T(pdata,0,allocation_size);
4752 SOFF_T(pdata,8,file_size);
4753 SIVAL(pdata,16,nlink);
4754 SCVAL(pdata,20,delete_pending);
4755 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4756 SSVAL(pdata,22,0);
4757 pdata += 24;
4758 SIVAL(pdata,0,ea_size);
4759 pdata += 4; /* EA info */
4760 len = srvstr_push(dstart, flags2,
4761 pdata+4, dos_fname,
4762 PTR_DIFF(dend, pdata+4),
4763 STR_UNICODE);
4764 SIVAL(pdata,0,len);
4765 pdata += 4 + len;
4766 data_size = PTR_DIFF(pdata,(*ppdata));
4767 break;
4770 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4772 int len;
4773 unsigned int ea_size =
4774 estimate_ea_size(conn, fsp, smb_fname);
4775 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4776 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4777 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4778 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4779 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4780 SIVAL(pdata, 0x20, mode);
4781 SIVAL(pdata, 0x24, 0); /* padding. */
4782 SBVAL(pdata, 0x28, allocation_size);
4783 SBVAL(pdata, 0x30, file_size);
4784 SIVAL(pdata, 0x38, nlink);
4785 SCVAL(pdata, 0x3C, delete_pending);
4786 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4787 SSVAL(pdata, 0x3E, 0); /* padding */
4788 SBVAL(pdata, 0x40, file_index);
4789 SIVAL(pdata, 0x48, ea_size);
4790 SIVAL(pdata, 0x4C, access_mask);
4791 SBVAL(pdata, 0x50, pos);
4792 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4793 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4795 pdata += 0x60;
4797 len = srvstr_push(dstart, flags2,
4798 pdata+4, dos_fname,
4799 PTR_DIFF(dend, pdata+4),
4800 STR_UNICODE);
4801 SIVAL(pdata,0,len);
4802 pdata += 4 + len;
4803 data_size = PTR_DIFF(pdata,(*ppdata));
4804 break;
4806 case SMB_FILE_INTERNAL_INFORMATION:
4808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4809 SBVAL(pdata, 0, file_index);
4810 data_size = 8;
4811 break;
4813 case SMB_FILE_ACCESS_INFORMATION:
4814 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4815 SIVAL(pdata, 0, access_mask);
4816 data_size = 4;
4817 break;
4819 case SMB_FILE_NAME_INFORMATION:
4820 /* Pathname with leading '\'. */
4822 size_t byte_len;
4823 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4825 SIVAL(pdata,0,byte_len);
4826 data_size = 4 + byte_len;
4827 break;
4830 case SMB_FILE_DISPOSITION_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4832 data_size = 1;
4833 SCVAL(pdata,0,delete_pending);
4834 break;
4836 case SMB_FILE_POSITION_INFORMATION:
4837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4838 data_size = 8;
4839 SOFF_T(pdata,0,pos);
4840 break;
4842 case SMB_FILE_MODE_INFORMATION:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4844 SIVAL(pdata,0,mode);
4845 data_size = 4;
4846 break;
4848 case SMB_FILE_ALIGNMENT_INFORMATION:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4850 SIVAL(pdata,0,0); /* No alignment needed. */
4851 data_size = 4;
4852 break;
4855 * NT4 server just returns "invalid query" to this - if we try
4856 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4857 * want this. JRA.
4859 /* The first statement above is false - verified using Thursby
4860 * client against NT4 -- gcolley.
4862 case SMB_QUERY_FILE_STREAM_INFO:
4863 case SMB_FILE_STREAM_INFORMATION: {
4864 unsigned int num_streams = 0;
4865 struct stream_struct *streams = NULL;
4867 DEBUG(10,("smbd_do_qfilepathinfo: "
4868 "SMB_FILE_STREAM_INFORMATION\n"));
4870 if (is_ntfs_stream_smb_fname(smb_fname)) {
4871 return NT_STATUS_INVALID_PARAMETER;
4874 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4875 talloc_tos(), &num_streams, &streams);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 DEBUG(10, ("could not get stream info: %s\n",
4879 nt_errstr(status)));
4880 return status;
4883 status = marshall_stream_info(num_streams, streams,
4884 pdata, max_data_bytes,
4885 &data_size);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 DEBUG(10, ("marshall_stream_info failed: %s\n",
4889 nt_errstr(status)));
4890 TALLOC_FREE(streams);
4891 return status;
4894 TALLOC_FREE(streams);
4896 break;
4898 case SMB_QUERY_COMPRESSION_INFO:
4899 case SMB_FILE_COMPRESSION_INFORMATION:
4900 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4901 SOFF_T(pdata,0,file_size);
4902 SIVAL(pdata,8,0); /* ??? */
4903 SIVAL(pdata,12,0); /* ??? */
4904 data_size = 16;
4905 break;
4907 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4908 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4909 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4910 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4911 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4912 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4913 SOFF_T(pdata,32,allocation_size);
4914 SOFF_T(pdata,40,file_size);
4915 SIVAL(pdata,48,mode);
4916 SIVAL(pdata,52,0); /* ??? */
4917 data_size = 56;
4918 break;
4920 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4921 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4922 SIVAL(pdata,0,mode);
4923 SIVAL(pdata,4,0);
4924 data_size = 8;
4925 break;
4928 * CIFS UNIX Extensions.
4931 case SMB_QUERY_FILE_UNIX_BASIC:
4933 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4934 data_size = PTR_DIFF(pdata,(*ppdata));
4936 DEBUG(4,("smbd_do_qfilepathinfo: "
4937 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4938 dump_data(4, (uint8_t *)(*ppdata), data_size);
4940 break;
4942 case SMB_QUERY_FILE_UNIX_INFO2:
4944 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4945 data_size = PTR_DIFF(pdata,(*ppdata));
4948 int i;
4949 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4951 for (i=0; i<100; i++)
4952 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4953 DEBUG(4,("\n"));
4956 break;
4958 case SMB_QUERY_FILE_UNIX_LINK:
4960 int len;
4961 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4963 if (!buffer) {
4964 return NT_STATUS_NO_MEMORY;
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4968 #ifdef S_ISLNK
4969 if(!S_ISLNK(psbuf->st_ex_mode)) {
4970 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4972 #else
4973 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4974 #endif
4975 len = SMB_VFS_READLINK(conn,
4976 smb_fname->base_name,
4977 buffer, PATH_MAX);
4978 if (len == -1) {
4979 return map_nt_error_from_unix(errno);
4981 buffer[len] = 0;
4982 len = srvstr_push(dstart, flags2,
4983 pdata, buffer,
4984 PTR_DIFF(dend, pdata),
4985 STR_TERMINATE);
4986 pdata += len;
4987 data_size = PTR_DIFF(pdata,(*ppdata));
4989 break;
4992 #if defined(HAVE_POSIX_ACLS)
4993 case SMB_QUERY_POSIX_ACL:
4995 SMB_ACL_T file_acl = NULL;
4996 SMB_ACL_T def_acl = NULL;
4997 uint16 num_file_acls = 0;
4998 uint16 num_def_acls = 0;
5000 if (fsp && fsp->fh->fd != -1) {
5001 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5002 talloc_tos());
5003 } else {
5004 file_acl =
5005 SMB_VFS_SYS_ACL_GET_FILE(conn,
5006 smb_fname->base_name,
5007 SMB_ACL_TYPE_ACCESS,
5008 talloc_tos());
5011 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5012 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5013 "not implemented on "
5014 "filesystem containing %s\n",
5015 smb_fname->base_name));
5016 return NT_STATUS_NOT_IMPLEMENTED;
5019 if (S_ISDIR(psbuf->st_ex_mode)) {
5020 if (fsp && fsp->is_directory) {
5021 def_acl =
5022 SMB_VFS_SYS_ACL_GET_FILE(
5023 conn,
5024 fsp->fsp_name->base_name,
5025 SMB_ACL_TYPE_DEFAULT,
5026 talloc_tos());
5027 } else {
5028 def_acl =
5029 SMB_VFS_SYS_ACL_GET_FILE(
5030 conn,
5031 smb_fname->base_name,
5032 SMB_ACL_TYPE_DEFAULT,
5033 talloc_tos());
5035 def_acl = free_empty_sys_acl(conn, def_acl);
5038 num_file_acls = count_acl_entries(conn, file_acl);
5039 num_def_acls = count_acl_entries(conn, def_acl);
5041 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5042 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5043 data_size,
5044 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5045 SMB_POSIX_ACL_HEADER_SIZE) ));
5046 if (file_acl) {
5047 TALLOC_FREE(file_acl);
5049 if (def_acl) {
5050 TALLOC_FREE(def_acl);
5052 return NT_STATUS_BUFFER_TOO_SMALL;
5055 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5056 SSVAL(pdata,2,num_file_acls);
5057 SSVAL(pdata,4,num_def_acls);
5058 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5059 if (file_acl) {
5060 TALLOC_FREE(file_acl);
5062 if (def_acl) {
5063 TALLOC_FREE(def_acl);
5065 return NT_STATUS_INTERNAL_ERROR;
5067 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5068 if (file_acl) {
5069 TALLOC_FREE(file_acl);
5071 if (def_acl) {
5072 TALLOC_FREE(def_acl);
5074 return NT_STATUS_INTERNAL_ERROR;
5077 if (file_acl) {
5078 TALLOC_FREE(file_acl);
5080 if (def_acl) {
5081 TALLOC_FREE(def_acl);
5083 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5084 break;
5086 #endif
5089 case SMB_QUERY_POSIX_LOCK:
5091 uint64_t count;
5092 uint64_t offset;
5093 uint64_t smblctx;
5094 enum brl_type lock_type;
5096 /* We need an open file with a real fd for this. */
5097 if (!fsp || fsp->fh->fd == -1) {
5098 return NT_STATUS_INVALID_LEVEL;
5101 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5102 return NT_STATUS_INVALID_PARAMETER;
5105 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5106 case POSIX_LOCK_TYPE_READ:
5107 lock_type = READ_LOCK;
5108 break;
5109 case POSIX_LOCK_TYPE_WRITE:
5110 lock_type = WRITE_LOCK;
5111 break;
5112 case POSIX_LOCK_TYPE_UNLOCK:
5113 default:
5114 /* There's no point in asking for an unlock... */
5115 return NT_STATUS_INVALID_PARAMETER;
5118 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5119 #if defined(HAVE_LONGLONG)
5120 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5121 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5122 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5123 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5124 #else /* HAVE_LONGLONG */
5125 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5126 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5127 #endif /* HAVE_LONGLONG */
5129 status = query_lock(fsp,
5130 &smblctx,
5131 &count,
5132 &offset,
5133 &lock_type,
5134 POSIX_LOCK);
5136 if (ERROR_WAS_LOCK_DENIED(status)) {
5137 /* Here we need to report who has it locked... */
5138 data_size = POSIX_LOCK_DATA_SIZE;
5140 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5141 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5142 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5143 #if defined(HAVE_LONGLONG)
5144 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5145 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5146 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5147 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5148 #else /* HAVE_LONGLONG */
5149 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5150 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5151 #endif /* HAVE_LONGLONG */
5153 } else if (NT_STATUS_IS_OK(status)) {
5154 /* For success we just return a copy of what we sent
5155 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5156 data_size = POSIX_LOCK_DATA_SIZE;
5157 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5158 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5159 } else {
5160 return status;
5162 break;
5165 default:
5166 return NT_STATUS_INVALID_LEVEL;
5169 *pdata_size = data_size;
5170 return NT_STATUS_OK;
5173 /****************************************************************************
5174 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5175 file name or file id).
5176 ****************************************************************************/
5178 static void call_trans2qfilepathinfo(connection_struct *conn,
5179 struct smb_request *req,
5180 unsigned int tran_call,
5181 char **pparams, int total_params,
5182 char **ppdata, int total_data,
5183 unsigned int max_data_bytes)
5185 char *params = *pparams;
5186 char *pdata = *ppdata;
5187 uint16 info_level;
5188 unsigned int data_size = 0;
5189 unsigned int param_size = 2;
5190 struct smb_filename *smb_fname = NULL;
5191 bool delete_pending = False;
5192 struct timespec write_time_ts;
5193 files_struct *fsp = NULL;
5194 struct file_id fileid;
5195 struct ea_list *ea_list = NULL;
5196 int lock_data_count = 0;
5197 char *lock_data = NULL;
5198 NTSTATUS status = NT_STATUS_OK;
5200 if (!params) {
5201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5202 return;
5205 ZERO_STRUCT(write_time_ts);
5207 if (tran_call == TRANSACT2_QFILEINFO) {
5208 if (total_params < 4) {
5209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5210 return;
5213 if (IS_IPC(conn)) {
5214 call_trans2qpipeinfo(conn, req, tran_call,
5215 pparams, total_params,
5216 ppdata, total_data,
5217 max_data_bytes);
5218 return;
5221 fsp = file_fsp(req, SVAL(params,0));
5222 info_level = SVAL(params,2);
5224 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5226 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5227 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5228 return;
5231 /* Initial check for valid fsp ptr. */
5232 if (!check_fsp_open(conn, req, fsp)) {
5233 return;
5236 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5237 &smb_fname);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 reply_nterror(req, status);
5240 return;
5243 if(fsp->fake_file_handle) {
5245 * This is actually for the QUOTA_FAKE_FILE --metze
5248 /* We know this name is ok, it's already passed the checks. */
5250 } else if(fsp->fh->fd == -1) {
5252 * This is actually a QFILEINFO on a directory
5253 * handle (returned from an NT SMB). NT5.0 seems
5254 * to do this call. JRA.
5257 if (INFO_LEVEL_IS_UNIX(info_level)) {
5258 /* Always do lstat for UNIX calls. */
5259 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5260 DEBUG(3,("call_trans2qfilepathinfo: "
5261 "SMB_VFS_LSTAT of %s failed "
5262 "(%s)\n",
5263 smb_fname_str_dbg(smb_fname),
5264 strerror(errno)));
5265 reply_nterror(req,
5266 map_nt_error_from_unix(errno));
5267 return;
5269 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5270 DEBUG(3,("call_trans2qfilepathinfo: "
5271 "SMB_VFS_STAT of %s failed (%s)\n",
5272 smb_fname_str_dbg(smb_fname),
5273 strerror(errno)));
5274 reply_nterror(req,
5275 map_nt_error_from_unix(errno));
5276 return;
5279 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5280 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5281 } else {
5283 * Original code - this is an open file.
5285 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5286 DEBUG(3, ("fstat of %s failed (%s)\n",
5287 fsp_fnum_dbg(fsp), strerror(errno)));
5288 reply_nterror(req,
5289 map_nt_error_from_unix(errno));
5290 return;
5292 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5293 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5296 } else {
5297 uint32_t name_hash;
5298 char *fname = NULL;
5299 uint32_t ucf_flags = 0;
5301 /* qpathinfo */
5302 if (total_params < 7) {
5303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5304 return;
5307 info_level = SVAL(params,0);
5309 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5311 if (INFO_LEVEL_IS_UNIX(info_level)) {
5312 if (!lp_unix_extensions()) {
5313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5314 return;
5316 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5317 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5318 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5319 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5323 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5324 total_params - 6,
5325 STR_TERMINATE, &status);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 reply_nterror(req, status);
5328 return;
5331 status = filename_convert(req,
5332 conn,
5333 req->flags2 & FLAGS2_DFS_PATHNAMES,
5334 fname,
5335 ucf_flags,
5336 NULL,
5337 &smb_fname);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5340 reply_botherror(req,
5341 NT_STATUS_PATH_NOT_COVERED,
5342 ERRSRV, ERRbadpath);
5343 return;
5345 reply_nterror(req, status);
5346 return;
5349 /* If this is a stream, check if there is a delete_pending. */
5350 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5351 && is_ntfs_stream_smb_fname(smb_fname)) {
5352 struct smb_filename *smb_fname_base = NULL;
5354 /* Create an smb_filename with stream_name == NULL. */
5355 status =
5356 create_synthetic_smb_fname(talloc_tos(),
5357 smb_fname->base_name,
5358 NULL, NULL,
5359 &smb_fname_base);
5360 if (!NT_STATUS_IS_OK(status)) {
5361 reply_nterror(req, status);
5362 return;
5365 if (INFO_LEVEL_IS_UNIX(info_level)) {
5366 /* Always do lstat for UNIX calls. */
5367 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5368 DEBUG(3,("call_trans2qfilepathinfo: "
5369 "SMB_VFS_LSTAT of %s failed "
5370 "(%s)\n",
5371 smb_fname_str_dbg(smb_fname_base),
5372 strerror(errno)));
5373 TALLOC_FREE(smb_fname_base);
5374 reply_nterror(req,
5375 map_nt_error_from_unix(errno));
5376 return;
5378 } else {
5379 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5380 DEBUG(3,("call_trans2qfilepathinfo: "
5381 "fileinfo of %s failed "
5382 "(%s)\n",
5383 smb_fname_str_dbg(smb_fname_base),
5384 strerror(errno)));
5385 TALLOC_FREE(smb_fname_base);
5386 reply_nterror(req,
5387 map_nt_error_from_unix(errno));
5388 return;
5392 status = file_name_hash(conn,
5393 smb_fname_str_dbg(smb_fname_base),
5394 &name_hash);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 TALLOC_FREE(smb_fname_base);
5397 reply_nterror(req, status);
5398 return;
5401 fileid = vfs_file_id_from_sbuf(conn,
5402 &smb_fname_base->st);
5403 TALLOC_FREE(smb_fname_base);
5404 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5405 if (delete_pending) {
5406 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5407 return;
5411 if (INFO_LEVEL_IS_UNIX(info_level)) {
5412 /* Always do lstat for UNIX calls. */
5413 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5414 DEBUG(3,("call_trans2qfilepathinfo: "
5415 "SMB_VFS_LSTAT of %s failed (%s)\n",
5416 smb_fname_str_dbg(smb_fname),
5417 strerror(errno)));
5418 reply_nterror(req,
5419 map_nt_error_from_unix(errno));
5420 return;
5423 } else {
5424 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5425 DEBUG(3,("call_trans2qfilepathinfo: "
5426 "SMB_VFS_STAT of %s failed (%s)\n",
5427 smb_fname_str_dbg(smb_fname),
5428 strerror(errno)));
5429 reply_nterror(req,
5430 map_nt_error_from_unix(errno));
5431 return;
5435 status = file_name_hash(conn,
5436 smb_fname_str_dbg(smb_fname),
5437 &name_hash);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 reply_nterror(req, status);
5440 return;
5443 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5444 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5445 if (delete_pending) {
5446 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5447 return;
5451 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5452 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5453 fsp_fnum_dbg(fsp),
5454 info_level,tran_call,total_data));
5456 /* Pull out any data sent here before we realloc. */
5457 switch (info_level) {
5458 case SMB_INFO_QUERY_EAS_FROM_LIST:
5460 /* Pull any EA list from the data portion. */
5461 uint32 ea_size;
5463 if (total_data < 4) {
5464 reply_nterror(
5465 req, NT_STATUS_INVALID_PARAMETER);
5466 return;
5468 ea_size = IVAL(pdata,0);
5470 if (total_data > 0 && ea_size != total_data) {
5471 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5472 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5473 reply_nterror(
5474 req, NT_STATUS_INVALID_PARAMETER);
5475 return;
5478 if (!lp_ea_support(SNUM(conn))) {
5479 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5480 return;
5483 /* Pull out the list of names. */
5484 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5485 if (!ea_list) {
5486 reply_nterror(
5487 req, NT_STATUS_INVALID_PARAMETER);
5488 return;
5490 break;
5493 case SMB_QUERY_POSIX_LOCK:
5495 if (fsp == NULL || fsp->fh->fd == -1) {
5496 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5497 return;
5500 if (total_data != POSIX_LOCK_DATA_SIZE) {
5501 reply_nterror(
5502 req, NT_STATUS_INVALID_PARAMETER);
5503 return;
5506 /* Copy the lock range data. */
5507 lock_data = (char *)talloc_memdup(
5508 req, pdata, total_data);
5509 if (!lock_data) {
5510 reply_nterror(req, NT_STATUS_NO_MEMORY);
5511 return;
5513 lock_data_count = total_data;
5515 default:
5516 break;
5519 *pparams = (char *)SMB_REALLOC(*pparams,2);
5520 if (*pparams == NULL) {
5521 reply_nterror(req, NT_STATUS_NO_MEMORY);
5522 return;
5524 params = *pparams;
5525 SSVAL(params,0,0);
5528 * draft-leach-cifs-v1-spec-02.txt
5529 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5530 * says:
5532 * The requested information is placed in the Data portion of the
5533 * transaction response. For the information levels greater than 0x100,
5534 * the transaction response has 1 parameter word which should be
5535 * ignored by the client.
5537 * However Windows only follows this rule for the IS_NAME_VALID call.
5539 switch (info_level) {
5540 case SMB_INFO_IS_NAME_VALID:
5541 param_size = 0;
5542 break;
5545 if ((info_level & 0xFF00) == 0xFF00) {
5547 * We use levels that start with 0xFF00
5548 * internally to represent SMB2 specific levels
5550 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5551 return;
5554 status = smbd_do_qfilepathinfo(conn, req, info_level,
5555 fsp, smb_fname,
5556 delete_pending, write_time_ts,
5557 ea_list,
5558 lock_data_count, lock_data,
5559 req->flags2, max_data_bytes,
5560 ppdata, &data_size);
5561 if (!NT_STATUS_IS_OK(status)) {
5562 reply_nterror(req, status);
5563 return;
5566 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5567 max_data_bytes);
5569 return;
5572 /****************************************************************************
5573 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5574 code.
5575 ****************************************************************************/
5577 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5578 connection_struct *conn,
5579 struct smb_request *req,
5580 bool overwrite_if_exists,
5581 const struct smb_filename *smb_fname_old,
5582 struct smb_filename *smb_fname_new)
5584 NTSTATUS status = NT_STATUS_OK;
5586 /* source must already exist. */
5587 if (!VALID_STAT(smb_fname_old->st)) {
5588 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5591 if (VALID_STAT(smb_fname_new->st)) {
5592 if (overwrite_if_exists) {
5593 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5594 return NT_STATUS_FILE_IS_A_DIRECTORY;
5596 status = unlink_internals(conn,
5597 req,
5598 FILE_ATTRIBUTE_NORMAL,
5599 smb_fname_new,
5600 false);
5601 if (!NT_STATUS_IS_OK(status)) {
5602 return status;
5604 } else {
5605 /* Disallow if newname already exists. */
5606 return NT_STATUS_OBJECT_NAME_COLLISION;
5610 /* No links from a directory. */
5611 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5612 return NT_STATUS_FILE_IS_A_DIRECTORY;
5615 /* Setting a hardlink to/from a stream isn't currently supported. */
5616 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5617 is_ntfs_stream_smb_fname(smb_fname_new)) {
5618 return NT_STATUS_INVALID_PARAMETER;
5621 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5622 smb_fname_old->base_name, smb_fname_new->base_name));
5624 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5625 smb_fname_new->base_name) != 0) {
5626 status = map_nt_error_from_unix(errno);
5627 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5628 nt_errstr(status), smb_fname_old->base_name,
5629 smb_fname_new->base_name));
5631 return status;
5634 /****************************************************************************
5635 Deal with setting the time from any of the setfilepathinfo functions.
5636 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5637 calling this function.
5638 ****************************************************************************/
5640 NTSTATUS smb_set_file_time(connection_struct *conn,
5641 files_struct *fsp,
5642 const struct smb_filename *smb_fname,
5643 struct smb_file_time *ft,
5644 bool setting_write_time)
5646 struct smb_filename smb_fname_base;
5647 uint32 action =
5648 FILE_NOTIFY_CHANGE_LAST_ACCESS
5649 |FILE_NOTIFY_CHANGE_LAST_WRITE
5650 |FILE_NOTIFY_CHANGE_CREATION;
5652 if (!VALID_STAT(smb_fname->st)) {
5653 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5656 /* get some defaults (no modifications) if any info is zero or -1. */
5657 if (null_timespec(ft->create_time)) {
5658 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5661 if (null_timespec(ft->atime)) {
5662 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5665 if (null_timespec(ft->mtime)) {
5666 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5669 if (!setting_write_time) {
5670 /* ft->mtime comes from change time, not write time. */
5671 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5674 /* Ensure the resolution is the correct for
5675 * what we can store on this filesystem. */
5677 round_timespec(conn->ts_res, &ft->create_time);
5678 round_timespec(conn->ts_res, &ft->ctime);
5679 round_timespec(conn->ts_res, &ft->atime);
5680 round_timespec(conn->ts_res, &ft->mtime);
5682 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5683 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5684 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5685 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5686 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5687 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5688 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5689 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5691 if (setting_write_time) {
5693 * This was a Windows setfileinfo on an open file.
5694 * NT does this a lot. We also need to
5695 * set the time here, as it can be read by
5696 * FindFirst/FindNext and with the patch for bug #2045
5697 * in smbd/fileio.c it ensures that this timestamp is
5698 * kept sticky even after a write. We save the request
5699 * away and will set it on file close and after a write. JRA.
5702 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5703 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5705 if (fsp != NULL) {
5706 if (fsp->base_fsp) {
5707 set_sticky_write_time_fsp(fsp->base_fsp,
5708 ft->mtime);
5709 } else {
5710 set_sticky_write_time_fsp(fsp, ft->mtime);
5712 } else {
5713 set_sticky_write_time_path(
5714 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5715 ft->mtime);
5719 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5721 /* Always call ntimes on the base, even if a stream was passed in. */
5722 smb_fname_base = *smb_fname;
5723 smb_fname_base.stream_name = NULL;
5725 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5726 return map_nt_error_from_unix(errno);
5729 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5730 smb_fname->base_name);
5731 return NT_STATUS_OK;
5734 /****************************************************************************
5735 Deal with setting the dosmode from any of the setfilepathinfo functions.
5736 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5737 done before calling this function.
5738 ****************************************************************************/
5740 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5741 const struct smb_filename *smb_fname,
5742 uint32 dosmode)
5744 struct smb_filename *smb_fname_base = NULL;
5745 NTSTATUS status;
5747 if (!VALID_STAT(smb_fname->st)) {
5748 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5751 /* Always operate on the base_name, even if a stream was passed in. */
5752 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5753 NULL, &smb_fname->st,
5754 &smb_fname_base);
5755 if (!NT_STATUS_IS_OK(status)) {
5756 return status;
5759 if (dosmode) {
5760 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5761 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5762 } else {
5763 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5767 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5769 /* check the mode isn't different, before changing it */
5770 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5771 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5772 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5773 (unsigned int)dosmode));
5775 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5776 false)) {
5777 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5778 "%s failed (%s)\n",
5779 smb_fname_str_dbg(smb_fname_base),
5780 strerror(errno)));
5781 status = map_nt_error_from_unix(errno);
5782 goto out;
5785 status = NT_STATUS_OK;
5786 out:
5787 TALLOC_FREE(smb_fname_base);
5788 return status;
5791 /****************************************************************************
5792 Deal with setting the size from any of the setfilepathinfo functions.
5793 ****************************************************************************/
5795 static NTSTATUS smb_set_file_size(connection_struct *conn,
5796 struct smb_request *req,
5797 files_struct *fsp,
5798 const struct smb_filename *smb_fname,
5799 const SMB_STRUCT_STAT *psbuf,
5800 off_t size,
5801 bool fail_after_createfile)
5803 NTSTATUS status = NT_STATUS_OK;
5804 struct smb_filename *smb_fname_tmp = NULL;
5805 files_struct *new_fsp = NULL;
5807 if (!VALID_STAT(*psbuf)) {
5808 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5811 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5813 if (size == get_file_size_stat(psbuf)) {
5814 return NT_STATUS_OK;
5817 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5818 smb_fname_str_dbg(smb_fname), (double)size));
5820 if (fsp && fsp->fh->fd != -1) {
5821 /* Handle based call. */
5822 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5823 return NT_STATUS_ACCESS_DENIED;
5826 if (vfs_set_filelen(fsp, size) == -1) {
5827 return map_nt_error_from_unix(errno);
5829 trigger_write_time_update_immediate(fsp);
5830 return NT_STATUS_OK;
5833 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5834 if (!NT_STATUS_IS_OK(status)) {
5835 return status;
5838 smb_fname_tmp->st = *psbuf;
5840 status = SMB_VFS_CREATE_FILE(
5841 conn, /* conn */
5842 req, /* req */
5843 0, /* root_dir_fid */
5844 smb_fname_tmp, /* fname */
5845 FILE_WRITE_DATA, /* access_mask */
5846 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5847 FILE_SHARE_DELETE),
5848 FILE_OPEN, /* create_disposition*/
5849 0, /* create_options */
5850 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5851 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5852 0, /* allocation_size */
5853 0, /* private_flags */
5854 NULL, /* sd */
5855 NULL, /* ea_list */
5856 &new_fsp, /* result */
5857 NULL); /* pinfo */
5859 TALLOC_FREE(smb_fname_tmp);
5861 if (!NT_STATUS_IS_OK(status)) {
5862 /* NB. We check for open_was_deferred in the caller. */
5863 return status;
5866 /* See RAW-SFILEINFO-END-OF-FILE */
5867 if (fail_after_createfile) {
5868 close_file(req, new_fsp,NORMAL_CLOSE);
5869 return NT_STATUS_INVALID_LEVEL;
5872 if (vfs_set_filelen(new_fsp, size) == -1) {
5873 status = map_nt_error_from_unix(errno);
5874 close_file(req, new_fsp,NORMAL_CLOSE);
5875 return status;
5878 trigger_write_time_update_immediate(new_fsp);
5879 close_file(req, new_fsp,NORMAL_CLOSE);
5880 return NT_STATUS_OK;
5883 /****************************************************************************
5884 Deal with SMB_INFO_SET_EA.
5885 ****************************************************************************/
5887 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5888 const char *pdata,
5889 int total_data,
5890 files_struct *fsp,
5891 const struct smb_filename *smb_fname)
5893 struct ea_list *ea_list = NULL;
5894 TALLOC_CTX *ctx = NULL;
5895 NTSTATUS status = NT_STATUS_OK;
5897 if (total_data < 10) {
5899 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5900 length. They seem to have no effect. Bug #3212. JRA */
5902 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5903 /* We're done. We only get EA info in this call. */
5904 return NT_STATUS_OK;
5907 return NT_STATUS_INVALID_PARAMETER;
5910 if (IVAL(pdata,0) > total_data) {
5911 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5912 IVAL(pdata,0), (unsigned int)total_data));
5913 return NT_STATUS_INVALID_PARAMETER;
5916 ctx = talloc_tos();
5917 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5918 if (!ea_list) {
5919 return NT_STATUS_INVALID_PARAMETER;
5922 status = set_ea(conn, fsp, smb_fname, ea_list);
5924 return status;
5927 /****************************************************************************
5928 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5929 ****************************************************************************/
5931 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5932 const char *pdata,
5933 int total_data,
5934 files_struct *fsp)
5936 struct ea_list *ea_list = NULL;
5937 NTSTATUS status;
5939 if (!fsp) {
5940 return NT_STATUS_INVALID_HANDLE;
5943 if (!lp_ea_support(SNUM(conn))) {
5944 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5945 "EA's not supported.\n",
5946 (unsigned int)total_data));
5947 return NT_STATUS_EAS_NOT_SUPPORTED;
5950 if (total_data < 10) {
5951 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5952 "too small.\n",
5953 (unsigned int)total_data));
5954 return NT_STATUS_INVALID_PARAMETER;
5957 ea_list = read_nttrans_ea_list(talloc_tos(),
5958 pdata,
5959 total_data);
5961 if (!ea_list) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5967 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5968 smb_fname_str_dbg(fsp->fsp_name),
5969 nt_errstr(status) ));
5971 return status;
5975 /****************************************************************************
5976 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5977 ****************************************************************************/
5979 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5980 const char *pdata,
5981 int total_data,
5982 files_struct *fsp,
5983 struct smb_filename *smb_fname)
5985 NTSTATUS status = NT_STATUS_OK;
5986 bool delete_on_close;
5987 uint32 dosmode = 0;
5989 if (total_data < 1) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 if (fsp == NULL) {
5994 return NT_STATUS_INVALID_HANDLE;
5997 delete_on_close = (CVAL(pdata,0) ? True : False);
5998 dosmode = dos_mode(conn, smb_fname);
6000 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6001 "delete_on_close = %u\n",
6002 smb_fname_str_dbg(smb_fname),
6003 (unsigned int)dosmode,
6004 (unsigned int)delete_on_close ));
6006 if (delete_on_close) {
6007 status = can_set_delete_on_close(fsp, dosmode);
6008 if (!NT_STATUS_IS_OK(status)) {
6009 return status;
6013 /* The set is across all open files on this dev/inode pair. */
6014 if (!set_delete_on_close(fsp, delete_on_close,
6015 conn->session_info->security_token,
6016 conn->session_info->unix_token)) {
6017 return NT_STATUS_ACCESS_DENIED;
6019 return NT_STATUS_OK;
6022 /****************************************************************************
6023 Deal with SMB_FILE_POSITION_INFORMATION.
6024 ****************************************************************************/
6026 static NTSTATUS smb_file_position_information(connection_struct *conn,
6027 const char *pdata,
6028 int total_data,
6029 files_struct *fsp)
6031 uint64_t position_information;
6033 if (total_data < 8) {
6034 return NT_STATUS_INVALID_PARAMETER;
6037 if (fsp == NULL) {
6038 /* Ignore on pathname based set. */
6039 return NT_STATUS_OK;
6042 position_information = (uint64_t)IVAL(pdata,0);
6043 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6045 DEBUG(10,("smb_file_position_information: Set file position "
6046 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6047 (double)position_information));
6048 fsp->fh->position_information = position_information;
6049 return NT_STATUS_OK;
6052 /****************************************************************************
6053 Deal with SMB_FILE_MODE_INFORMATION.
6054 ****************************************************************************/
6056 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6057 const char *pdata,
6058 int total_data)
6060 uint32 mode;
6062 if (total_data < 4) {
6063 return NT_STATUS_INVALID_PARAMETER;
6065 mode = IVAL(pdata,0);
6066 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6067 return NT_STATUS_INVALID_PARAMETER;
6069 return NT_STATUS_OK;
6072 /****************************************************************************
6073 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6074 ****************************************************************************/
6076 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6077 struct smb_request *req,
6078 const char *pdata,
6079 int total_data,
6080 const struct smb_filename *smb_fname)
6082 char *link_target = NULL;
6083 const char *newname = smb_fname->base_name;
6084 TALLOC_CTX *ctx = talloc_tos();
6086 /* Set a symbolic link. */
6087 /* Don't allow this if follow links is false. */
6089 if (total_data == 0) {
6090 return NT_STATUS_INVALID_PARAMETER;
6093 if (!lp_symlinks(SNUM(conn))) {
6094 return NT_STATUS_ACCESS_DENIED;
6097 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6098 total_data, STR_TERMINATE);
6100 if (!link_target) {
6101 return NT_STATUS_INVALID_PARAMETER;
6104 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6105 newname, link_target ));
6107 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6108 return map_nt_error_from_unix(errno);
6111 return NT_STATUS_OK;
6114 /****************************************************************************
6115 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6116 ****************************************************************************/
6118 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6119 struct smb_request *req,
6120 const char *pdata, int total_data,
6121 struct smb_filename *smb_fname_new)
6123 char *oldname = NULL;
6124 struct smb_filename *smb_fname_old = NULL;
6125 TALLOC_CTX *ctx = talloc_tos();
6126 NTSTATUS status = NT_STATUS_OK;
6128 /* Set a hard link. */
6129 if (total_data == 0) {
6130 return NT_STATUS_INVALID_PARAMETER;
6133 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6134 total_data, STR_TERMINATE, &status);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 return status;
6139 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6140 smb_fname_str_dbg(smb_fname_new), oldname));
6142 status = filename_convert(ctx,
6143 conn,
6144 req->flags2 & FLAGS2_DFS_PATHNAMES,
6145 oldname,
6147 NULL,
6148 &smb_fname_old);
6149 if (!NT_STATUS_IS_OK(status)) {
6150 return status;
6153 return hardlink_internals(ctx, conn, req, false,
6154 smb_fname_old, smb_fname_new);
6157 /****************************************************************************
6158 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6159 ****************************************************************************/
6161 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6162 struct smb_request *req,
6163 const char *pdata,
6164 int total_data,
6165 files_struct *fsp,
6166 struct smb_filename *smb_fname_src)
6168 bool overwrite;
6169 uint32_t len;
6170 char *newname = NULL;
6171 struct smb_filename *smb_fname_dst = NULL;
6172 NTSTATUS status = NT_STATUS_OK;
6173 TALLOC_CTX *ctx = talloc_tos();
6175 if (!fsp) {
6176 return NT_STATUS_INVALID_HANDLE;
6179 if (total_data < 20) {
6180 return NT_STATUS_INVALID_PARAMETER;
6183 overwrite = (CVAL(pdata,0) ? True : False);
6184 len = IVAL(pdata,16);
6186 if (len > (total_data - 20) || (len == 0)) {
6187 return NT_STATUS_INVALID_PARAMETER;
6190 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6191 &pdata[20], len, STR_TERMINATE,
6192 &status);
6193 if (!NT_STATUS_IS_OK(status)) {
6194 return status;
6197 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6198 newname));
6200 status = filename_convert(ctx,
6201 conn,
6202 req->flags2 & FLAGS2_DFS_PATHNAMES,
6203 newname,
6204 UCF_SAVE_LCOMP,
6205 NULL,
6206 &smb_fname_dst);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 return status;
6211 if (fsp->base_fsp) {
6212 /* newname must be a stream name. */
6213 if (newname[0] != ':') {
6214 return NT_STATUS_NOT_SUPPORTED;
6217 /* Create an smb_fname to call rename_internals_fsp() with. */
6218 status = create_synthetic_smb_fname(talloc_tos(),
6219 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6220 &smb_fname_dst);
6221 if (!NT_STATUS_IS_OK(status)) {
6222 goto out;
6226 * Set the original last component, since
6227 * rename_internals_fsp() requires it.
6229 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6230 newname);
6231 if (smb_fname_dst->original_lcomp == NULL) {
6232 status = NT_STATUS_NO_MEMORY;
6233 goto out;
6238 DEBUG(10,("smb2_file_rename_information: "
6239 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6240 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6241 smb_fname_str_dbg(smb_fname_dst)));
6242 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6243 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6244 overwrite);
6246 out:
6247 TALLOC_FREE(smb_fname_dst);
6248 return status;
6251 static NTSTATUS smb_file_link_information(connection_struct *conn,
6252 struct smb_request *req,
6253 const char *pdata,
6254 int total_data,
6255 files_struct *fsp,
6256 struct smb_filename *smb_fname_src)
6258 bool overwrite;
6259 uint32_t len;
6260 char *newname = NULL;
6261 struct smb_filename *smb_fname_dst = NULL;
6262 NTSTATUS status = NT_STATUS_OK;
6263 TALLOC_CTX *ctx = talloc_tos();
6265 if (!fsp) {
6266 return NT_STATUS_INVALID_HANDLE;
6269 if (total_data < 20) {
6270 return NT_STATUS_INVALID_PARAMETER;
6273 overwrite = (CVAL(pdata,0) ? true : false);
6274 len = IVAL(pdata,16);
6276 if (len > (total_data - 20) || (len == 0)) {
6277 return NT_STATUS_INVALID_PARAMETER;
6280 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6281 &pdata[20], len, STR_TERMINATE,
6282 &status);
6283 if (!NT_STATUS_IS_OK(status)) {
6284 return status;
6287 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6288 newname));
6290 status = filename_convert(ctx,
6291 conn,
6292 req->flags2 & FLAGS2_DFS_PATHNAMES,
6293 newname,
6294 UCF_SAVE_LCOMP,
6295 NULL,
6296 &smb_fname_dst);
6297 if (!NT_STATUS_IS_OK(status)) {
6298 return status;
6301 if (fsp->base_fsp) {
6302 /* No stream names. */
6303 return NT_STATUS_NOT_SUPPORTED;
6306 DEBUG(10,("smb_file_link_information: "
6307 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6308 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6309 smb_fname_str_dbg(smb_fname_dst)));
6310 status = hardlink_internals(ctx,
6311 conn,
6312 req,
6313 overwrite,
6314 fsp->fsp_name,
6315 smb_fname_dst);
6317 TALLOC_FREE(smb_fname_dst);
6318 return status;
6321 /****************************************************************************
6322 Deal with SMB_FILE_RENAME_INFORMATION.
6323 ****************************************************************************/
6325 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6326 struct smb_request *req,
6327 const char *pdata,
6328 int total_data,
6329 files_struct *fsp,
6330 struct smb_filename *smb_fname_src)
6332 bool overwrite;
6333 uint32 root_fid;
6334 uint32 len;
6335 char *newname = NULL;
6336 struct smb_filename *smb_fname_dst = NULL;
6337 bool dest_has_wcard = False;
6338 NTSTATUS status = NT_STATUS_OK;
6339 char *p;
6340 TALLOC_CTX *ctx = talloc_tos();
6342 if (total_data < 13) {
6343 return NT_STATUS_INVALID_PARAMETER;
6346 overwrite = (CVAL(pdata,0) ? True : False);
6347 root_fid = IVAL(pdata,4);
6348 len = IVAL(pdata,8);
6350 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6351 return NT_STATUS_INVALID_PARAMETER;
6354 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6355 len, 0, &status,
6356 &dest_has_wcard);
6357 if (!NT_STATUS_IS_OK(status)) {
6358 return status;
6361 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6362 newname));
6364 status = resolve_dfspath_wcard(ctx, conn,
6365 req->flags2 & FLAGS2_DFS_PATHNAMES,
6366 newname,
6367 true,
6368 !conn->sconn->using_smb2,
6369 &newname,
6370 &dest_has_wcard);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 return status;
6375 /* Check the new name has no '/' characters. */
6376 if (strchr_m(newname, '/')) {
6377 return NT_STATUS_NOT_SUPPORTED;
6380 if (fsp && fsp->base_fsp) {
6381 /* newname must be a stream name. */
6382 if (newname[0] != ':') {
6383 return NT_STATUS_NOT_SUPPORTED;
6386 /* Create an smb_fname to call rename_internals_fsp() with. */
6387 status = create_synthetic_smb_fname(talloc_tos(),
6388 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6389 &smb_fname_dst);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 goto out;
6395 * Set the original last component, since
6396 * rename_internals_fsp() requires it.
6398 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6399 newname);
6400 if (smb_fname_dst->original_lcomp == NULL) {
6401 status = NT_STATUS_NO_MEMORY;
6402 goto out;
6405 } else {
6407 * Build up an smb_fname_dst based on the filename passed in.
6408 * We basically just strip off the last component, and put on
6409 * the newname instead.
6411 char *base_name = NULL;
6413 /* newname must *not* be a stream name. */
6414 if (newname[0] == ':') {
6415 return NT_STATUS_NOT_SUPPORTED;
6419 * Strip off the last component (filename) of the path passed
6420 * in.
6422 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6423 if (!base_name) {
6424 return NT_STATUS_NO_MEMORY;
6426 p = strrchr_m(base_name, '/');
6427 if (p) {
6428 p[1] = '\0';
6429 } else {
6430 base_name = talloc_strdup(ctx, "");
6431 if (!base_name) {
6432 return NT_STATUS_NO_MEMORY;
6435 /* Append the new name. */
6436 base_name = talloc_asprintf_append(base_name,
6437 "%s",
6438 newname);
6439 if (!base_name) {
6440 return NT_STATUS_NO_MEMORY;
6443 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6444 (UCF_SAVE_LCOMP |
6445 (dest_has_wcard ?
6446 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6447 0)));
6449 /* If an error we expect this to be
6450 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6452 if (!NT_STATUS_IS_OK(status)) {
6453 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6454 status)) {
6455 goto out;
6457 /* Create an smb_fname to call rename_internals_fsp() */
6458 status = create_synthetic_smb_fname(ctx,
6459 base_name, NULL,
6460 NULL,
6461 &smb_fname_dst);
6462 if (!NT_STATUS_IS_OK(status)) {
6463 goto out;
6468 if (fsp) {
6469 DEBUG(10,("smb_file_rename_information: "
6470 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6471 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6472 smb_fname_str_dbg(smb_fname_dst)));
6473 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6474 overwrite);
6475 } else {
6476 DEBUG(10,("smb_file_rename_information: "
6477 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6478 smb_fname_str_dbg(smb_fname_src),
6479 smb_fname_str_dbg(smb_fname_dst)));
6480 status = rename_internals(ctx, conn, req, smb_fname_src,
6481 smb_fname_dst, 0, overwrite, false,
6482 dest_has_wcard,
6483 FILE_WRITE_ATTRIBUTES);
6485 out:
6486 TALLOC_FREE(smb_fname_dst);
6487 return status;
6490 /****************************************************************************
6491 Deal with SMB_SET_POSIX_ACL.
6492 ****************************************************************************/
6494 #if defined(HAVE_POSIX_ACLS)
6495 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6496 const char *pdata,
6497 int total_data,
6498 files_struct *fsp,
6499 const struct smb_filename *smb_fname)
6501 uint16 posix_acl_version;
6502 uint16 num_file_acls;
6503 uint16 num_def_acls;
6504 bool valid_file_acls = True;
6505 bool valid_def_acls = True;
6507 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6508 return NT_STATUS_INVALID_PARAMETER;
6510 posix_acl_version = SVAL(pdata,0);
6511 num_file_acls = SVAL(pdata,2);
6512 num_def_acls = SVAL(pdata,4);
6514 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6515 valid_file_acls = False;
6516 num_file_acls = 0;
6519 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6520 valid_def_acls = False;
6521 num_def_acls = 0;
6524 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6525 return NT_STATUS_INVALID_PARAMETER;
6528 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6529 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6530 return NT_STATUS_INVALID_PARAMETER;
6533 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6534 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6535 (unsigned int)num_file_acls,
6536 (unsigned int)num_def_acls));
6538 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6539 smb_fname->base_name, num_file_acls,
6540 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6541 return map_nt_error_from_unix(errno);
6544 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6545 smb_fname->base_name, &smb_fname->st, num_def_acls,
6546 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6547 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6548 return map_nt_error_from_unix(errno);
6550 return NT_STATUS_OK;
6552 #endif
6554 /****************************************************************************
6555 Deal with SMB_SET_POSIX_LOCK.
6556 ****************************************************************************/
6558 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6559 struct smb_request *req,
6560 const char *pdata,
6561 int total_data,
6562 files_struct *fsp)
6564 uint64_t count;
6565 uint64_t offset;
6566 uint64_t smblctx;
6567 bool blocking_lock = False;
6568 enum brl_type lock_type;
6570 NTSTATUS status = NT_STATUS_OK;
6572 if (fsp == NULL || fsp->fh->fd == -1) {
6573 return NT_STATUS_INVALID_HANDLE;
6576 if (total_data != POSIX_LOCK_DATA_SIZE) {
6577 return NT_STATUS_INVALID_PARAMETER;
6580 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6581 case POSIX_LOCK_TYPE_READ:
6582 lock_type = READ_LOCK;
6583 break;
6584 case POSIX_LOCK_TYPE_WRITE:
6585 /* Return the right POSIX-mappable error code for files opened read-only. */
6586 if (!fsp->can_write) {
6587 return NT_STATUS_INVALID_HANDLE;
6589 lock_type = WRITE_LOCK;
6590 break;
6591 case POSIX_LOCK_TYPE_UNLOCK:
6592 lock_type = UNLOCK_LOCK;
6593 break;
6594 default:
6595 return NT_STATUS_INVALID_PARAMETER;
6598 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6599 blocking_lock = False;
6600 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6601 blocking_lock = True;
6602 } else {
6603 return NT_STATUS_INVALID_PARAMETER;
6606 if (!lp_blocking_locks(SNUM(conn))) {
6607 blocking_lock = False;
6610 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6611 #if defined(HAVE_LONGLONG)
6612 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6613 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6614 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6615 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6616 #else /* HAVE_LONGLONG */
6617 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6618 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6619 #endif /* HAVE_LONGLONG */
6621 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6622 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6623 fsp_str_dbg(fsp),
6624 (unsigned int)lock_type,
6625 (unsigned long long)smblctx,
6626 (double)count,
6627 (double)offset ));
6629 if (lock_type == UNLOCK_LOCK) {
6630 status = do_unlock(req->sconn->msg_ctx,
6631 fsp,
6632 smblctx,
6633 count,
6634 offset,
6635 POSIX_LOCK);
6636 } else {
6637 uint64_t block_smblctx;
6639 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6640 fsp,
6641 smblctx,
6642 count,
6643 offset,
6644 lock_type,
6645 POSIX_LOCK,
6646 blocking_lock,
6647 &status,
6648 &block_smblctx,
6649 NULL);
6651 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6653 * A blocking lock was requested. Package up
6654 * this smb into a queued request and push it
6655 * onto the blocking lock queue.
6657 if(push_blocking_lock_request(br_lck,
6658 req,
6659 fsp,
6660 -1, /* infinite timeout. */
6662 smblctx,
6663 lock_type,
6664 POSIX_LOCK,
6665 offset,
6666 count,
6667 block_smblctx)) {
6668 TALLOC_FREE(br_lck);
6669 return status;
6672 TALLOC_FREE(br_lck);
6675 return status;
6678 /****************************************************************************
6679 Deal with SMB_SET_FILE_BASIC_INFO.
6680 ****************************************************************************/
6682 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6683 const char *pdata,
6684 int total_data,
6685 files_struct *fsp,
6686 const struct smb_filename *smb_fname)
6688 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6689 struct smb_file_time ft;
6690 uint32 dosmode = 0;
6691 NTSTATUS status = NT_STATUS_OK;
6693 ZERO_STRUCT(ft);
6695 if (total_data < 36) {
6696 return NT_STATUS_INVALID_PARAMETER;
6699 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 return status;
6704 /* Set the attributes */
6705 dosmode = IVAL(pdata,32);
6706 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 return status;
6711 /* create time */
6712 ft.create_time = interpret_long_date(pdata);
6714 /* access time */
6715 ft.atime = interpret_long_date(pdata+8);
6717 /* write time. */
6718 ft.mtime = interpret_long_date(pdata+16);
6720 /* change time. */
6721 ft.ctime = interpret_long_date(pdata+24);
6723 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6724 smb_fname_str_dbg(smb_fname)));
6726 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6727 true);
6730 /****************************************************************************
6731 Deal with SMB_INFO_STANDARD.
6732 ****************************************************************************/
6734 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6735 const char *pdata,
6736 int total_data,
6737 files_struct *fsp,
6738 const struct smb_filename *smb_fname)
6740 NTSTATUS status;
6741 struct smb_file_time ft;
6743 ZERO_STRUCT(ft);
6745 if (total_data < 12) {
6746 return NT_STATUS_INVALID_PARAMETER;
6749 /* create time */
6750 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6751 /* access time */
6752 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6753 /* write time */
6754 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6756 DEBUG(10,("smb_set_info_standard: file %s\n",
6757 smb_fname_str_dbg(smb_fname)));
6759 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6760 if (!NT_STATUS_IS_OK(status)) {
6761 return status;
6764 return smb_set_file_time(conn,
6765 fsp,
6766 smb_fname,
6767 &ft,
6768 true);
6771 /****************************************************************************
6772 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6773 ****************************************************************************/
6775 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6776 struct smb_request *req,
6777 const char *pdata,
6778 int total_data,
6779 files_struct *fsp,
6780 struct smb_filename *smb_fname)
6782 uint64_t allocation_size = 0;
6783 NTSTATUS status = NT_STATUS_OK;
6784 files_struct *new_fsp = NULL;
6786 if (!VALID_STAT(smb_fname->st)) {
6787 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6790 if (total_data < 8) {
6791 return NT_STATUS_INVALID_PARAMETER;
6794 allocation_size = (uint64_t)IVAL(pdata,0);
6795 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6796 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6797 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6798 (double)allocation_size));
6800 if (allocation_size) {
6801 allocation_size = smb_roundup(conn, allocation_size);
6804 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6805 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6806 (double)allocation_size));
6808 if (fsp && fsp->fh->fd != -1) {
6809 /* Open file handle. */
6810 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6811 return NT_STATUS_ACCESS_DENIED;
6814 /* Only change if needed. */
6815 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6816 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6817 return map_nt_error_from_unix(errno);
6820 /* But always update the time. */
6822 * This is equivalent to a write. Ensure it's seen immediately
6823 * if there are no pending writes.
6825 trigger_write_time_update_immediate(fsp);
6826 return NT_STATUS_OK;
6829 /* Pathname or stat or directory file. */
6830 status = SMB_VFS_CREATE_FILE(
6831 conn, /* conn */
6832 req, /* req */
6833 0, /* root_dir_fid */
6834 smb_fname, /* fname */
6835 FILE_WRITE_DATA, /* access_mask */
6836 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6837 FILE_SHARE_DELETE),
6838 FILE_OPEN, /* create_disposition*/
6839 0, /* create_options */
6840 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6841 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6842 0, /* allocation_size */
6843 0, /* private_flags */
6844 NULL, /* sd */
6845 NULL, /* ea_list */
6846 &new_fsp, /* result */
6847 NULL); /* pinfo */
6849 if (!NT_STATUS_IS_OK(status)) {
6850 /* NB. We check for open_was_deferred in the caller. */
6851 return status;
6854 /* Only change if needed. */
6855 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6856 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6857 status = map_nt_error_from_unix(errno);
6858 close_file(req, new_fsp, NORMAL_CLOSE);
6859 return status;
6863 /* Changing the allocation size should set the last mod time. */
6865 * This is equivalent to a write. Ensure it's seen immediately
6866 * if there are no pending writes.
6868 trigger_write_time_update_immediate(new_fsp);
6870 close_file(req, new_fsp, NORMAL_CLOSE);
6871 return NT_STATUS_OK;
6874 /****************************************************************************
6875 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6876 ****************************************************************************/
6878 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6879 struct smb_request *req,
6880 const char *pdata,
6881 int total_data,
6882 files_struct *fsp,
6883 const struct smb_filename *smb_fname,
6884 bool fail_after_createfile)
6886 off_t size;
6888 if (total_data < 8) {
6889 return NT_STATUS_INVALID_PARAMETER;
6892 size = IVAL(pdata,0);
6893 size |= (((off_t)IVAL(pdata,4)) << 32);
6894 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6895 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6896 (double)size));
6898 return smb_set_file_size(conn, req,
6899 fsp,
6900 smb_fname,
6901 &smb_fname->st,
6902 size,
6903 fail_after_createfile);
6906 /****************************************************************************
6907 Allow a UNIX info mknod.
6908 ****************************************************************************/
6910 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6911 const char *pdata,
6912 int total_data,
6913 const struct smb_filename *smb_fname)
6915 uint32 file_type = IVAL(pdata,56);
6916 #if defined(HAVE_MAKEDEV)
6917 uint32 dev_major = IVAL(pdata,60);
6918 uint32 dev_minor = IVAL(pdata,68);
6919 #endif
6920 SMB_DEV_T dev = (SMB_DEV_T)0;
6921 uint32 raw_unixmode = IVAL(pdata,84);
6922 NTSTATUS status;
6923 mode_t unixmode;
6925 if (total_data < 100) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6930 PERM_NEW_FILE, &unixmode);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 return status;
6935 #if defined(HAVE_MAKEDEV)
6936 dev = makedev(dev_major, dev_minor);
6937 #endif
6939 switch (file_type) {
6940 #if defined(S_IFIFO)
6941 case UNIX_TYPE_FIFO:
6942 unixmode |= S_IFIFO;
6943 break;
6944 #endif
6945 #if defined(S_IFSOCK)
6946 case UNIX_TYPE_SOCKET:
6947 unixmode |= S_IFSOCK;
6948 break;
6949 #endif
6950 #if defined(S_IFCHR)
6951 case UNIX_TYPE_CHARDEV:
6952 unixmode |= S_IFCHR;
6953 break;
6954 #endif
6955 #if defined(S_IFBLK)
6956 case UNIX_TYPE_BLKDEV:
6957 unixmode |= S_IFBLK;
6958 break;
6959 #endif
6960 default:
6961 return NT_STATUS_INVALID_PARAMETER;
6964 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6965 "%.0f mode 0%o for file %s\n", (double)dev,
6966 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6968 /* Ok - do the mknod. */
6969 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6970 return map_nt_error_from_unix(errno);
6973 /* If any of the other "set" calls fail we
6974 * don't want to end up with a half-constructed mknod.
6977 if (lp_inherit_perms(SNUM(conn))) {
6978 char *parent;
6979 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6980 &parent, NULL)) {
6981 return NT_STATUS_NO_MEMORY;
6983 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6984 unixmode);
6985 TALLOC_FREE(parent);
6988 return NT_STATUS_OK;
6991 /****************************************************************************
6992 Deal with SMB_SET_FILE_UNIX_BASIC.
6993 ****************************************************************************/
6995 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6996 struct smb_request *req,
6997 const char *pdata,
6998 int total_data,
6999 files_struct *fsp,
7000 const struct smb_filename *smb_fname)
7002 struct smb_file_time ft;
7003 uint32 raw_unixmode;
7004 mode_t unixmode;
7005 off_t size = 0;
7006 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7007 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7008 NTSTATUS status = NT_STATUS_OK;
7009 bool delete_on_fail = False;
7010 enum perm_type ptype;
7011 files_struct *all_fsps = NULL;
7012 bool modify_mtime = true;
7013 struct file_id id;
7014 struct smb_filename *smb_fname_tmp = NULL;
7015 SMB_STRUCT_STAT sbuf;
7017 ZERO_STRUCT(ft);
7019 if (total_data < 100) {
7020 return NT_STATUS_INVALID_PARAMETER;
7023 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7024 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7025 size=IVAL(pdata,0); /* first 8 Bytes are size */
7026 size |= (((off_t)IVAL(pdata,4)) << 32);
7029 ft.atime = interpret_long_date(pdata+24); /* access_time */
7030 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7031 set_owner = (uid_t)IVAL(pdata,40);
7032 set_grp = (gid_t)IVAL(pdata,48);
7033 raw_unixmode = IVAL(pdata,84);
7035 if (VALID_STAT(smb_fname->st)) {
7036 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7037 ptype = PERM_EXISTING_DIR;
7038 } else {
7039 ptype = PERM_EXISTING_FILE;
7041 } else {
7042 ptype = PERM_NEW_FILE;
7045 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7046 ptype, &unixmode);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 return status;
7051 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7052 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7053 smb_fname_str_dbg(smb_fname), (double)size,
7054 (unsigned int)set_owner, (unsigned int)set_grp,
7055 (int)raw_unixmode));
7057 sbuf = smb_fname->st;
7059 if (!VALID_STAT(sbuf)) {
7061 * The only valid use of this is to create character and block
7062 * devices, and named pipes. This is deprecated (IMHO) and
7063 * a new info level should be used for mknod. JRA.
7066 status = smb_unix_mknod(conn,
7067 pdata,
7068 total_data,
7069 smb_fname);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 return status;
7074 status = copy_smb_filename(talloc_tos(), smb_fname,
7075 &smb_fname_tmp);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 return status;
7080 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7081 status = map_nt_error_from_unix(errno);
7082 TALLOC_FREE(smb_fname_tmp);
7083 SMB_VFS_UNLINK(conn, smb_fname);
7084 return status;
7087 sbuf = smb_fname_tmp->st;
7088 smb_fname = smb_fname_tmp;
7090 /* Ensure we don't try and change anything else. */
7091 raw_unixmode = SMB_MODE_NO_CHANGE;
7092 size = get_file_size_stat(&sbuf);
7093 ft.atime = sbuf.st_ex_atime;
7094 ft.mtime = sbuf.st_ex_mtime;
7096 * We continue here as we might want to change the
7097 * owner uid/gid.
7099 delete_on_fail = True;
7102 #if 1
7103 /* Horrible backwards compatibility hack as an old server bug
7104 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7105 * */
7107 if (!size) {
7108 size = get_file_size_stat(&sbuf);
7110 #endif
7113 * Deal with the UNIX specific mode set.
7116 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7117 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7118 "setting mode 0%o for file %s\n",
7119 (unsigned int)unixmode,
7120 smb_fname_str_dbg(smb_fname)));
7121 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7122 return map_nt_error_from_unix(errno);
7127 * Deal with the UNIX specific uid set.
7130 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7131 (sbuf.st_ex_uid != set_owner)) {
7132 int ret;
7134 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7135 "changing owner %u for path %s\n",
7136 (unsigned int)set_owner,
7137 smb_fname_str_dbg(smb_fname)));
7139 if (S_ISLNK(sbuf.st_ex_mode)) {
7140 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7141 set_owner, (gid_t)-1);
7142 } else {
7143 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7144 set_owner, (gid_t)-1);
7147 if (ret != 0) {
7148 status = map_nt_error_from_unix(errno);
7149 if (delete_on_fail) {
7150 SMB_VFS_UNLINK(conn, smb_fname);
7152 return status;
7157 * Deal with the UNIX specific gid set.
7160 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7161 (sbuf.st_ex_gid != set_grp)) {
7162 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7163 "changing group %u for file %s\n",
7164 (unsigned int)set_owner,
7165 smb_fname_str_dbg(smb_fname)));
7166 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7167 set_grp) != 0) {
7168 status = map_nt_error_from_unix(errno);
7169 if (delete_on_fail) {
7170 SMB_VFS_UNLINK(conn, smb_fname);
7172 return status;
7176 /* Deal with any size changes. */
7178 status = smb_set_file_size(conn, req,
7179 fsp,
7180 smb_fname,
7181 &sbuf,
7182 size,
7183 false);
7184 if (!NT_STATUS_IS_OK(status)) {
7185 return status;
7188 /* Deal with any time changes. */
7189 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7190 /* No change, don't cancel anything. */
7191 return status;
7194 id = vfs_file_id_from_sbuf(conn, &sbuf);
7195 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7196 all_fsps = file_find_di_next(all_fsps)) {
7198 * We're setting the time explicitly for UNIX.
7199 * Cancel any pending changes over all handles.
7201 all_fsps->update_write_time_on_close = false;
7202 TALLOC_FREE(all_fsps->update_write_time_event);
7206 * Override the "setting_write_time"
7207 * parameter here as it almost does what
7208 * we need. Just remember if we modified
7209 * mtime and send the notify ourselves.
7211 if (null_timespec(ft.mtime)) {
7212 modify_mtime = false;
7215 status = smb_set_file_time(conn,
7216 fsp,
7217 smb_fname,
7218 &ft,
7219 false);
7220 if (modify_mtime) {
7221 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7222 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7224 return status;
7227 /****************************************************************************
7228 Deal with SMB_SET_FILE_UNIX_INFO2.
7229 ****************************************************************************/
7231 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7232 struct smb_request *req,
7233 const char *pdata,
7234 int total_data,
7235 files_struct *fsp,
7236 const struct smb_filename *smb_fname)
7238 NTSTATUS status;
7239 uint32 smb_fflags;
7240 uint32 smb_fmask;
7242 if (total_data < 116) {
7243 return NT_STATUS_INVALID_PARAMETER;
7246 /* Start by setting all the fields that are common between UNIX_BASIC
7247 * and UNIX_INFO2.
7249 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7250 fsp, smb_fname);
7251 if (!NT_STATUS_IS_OK(status)) {
7252 return status;
7255 smb_fflags = IVAL(pdata, 108);
7256 smb_fmask = IVAL(pdata, 112);
7258 /* NB: We should only attempt to alter the file flags if the client
7259 * sends a non-zero mask.
7261 if (smb_fmask != 0) {
7262 int stat_fflags = 0;
7264 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7265 smb_fmask, &stat_fflags)) {
7266 /* Client asked to alter a flag we don't understand. */
7267 return NT_STATUS_INVALID_PARAMETER;
7270 if (fsp && fsp->fh->fd != -1) {
7271 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7272 return NT_STATUS_NOT_SUPPORTED;
7273 } else {
7274 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7275 stat_fflags) != 0) {
7276 return map_nt_error_from_unix(errno);
7281 /* XXX: need to add support for changing the create_time here. You
7282 * can do this for paths on Darwin with setattrlist(2). The right way
7283 * to hook this up is probably by extending the VFS utimes interface.
7286 return NT_STATUS_OK;
7289 /****************************************************************************
7290 Create a directory with POSIX semantics.
7291 ****************************************************************************/
7293 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7294 struct smb_request *req,
7295 char **ppdata,
7296 int total_data,
7297 struct smb_filename *smb_fname,
7298 int *pdata_return_size)
7300 NTSTATUS status = NT_STATUS_OK;
7301 uint32 raw_unixmode = 0;
7302 uint32 mod_unixmode = 0;
7303 mode_t unixmode = (mode_t)0;
7304 files_struct *fsp = NULL;
7305 uint16 info_level_return = 0;
7306 int info;
7307 char *pdata = *ppdata;
7309 if (total_data < 18) {
7310 return NT_STATUS_INVALID_PARAMETER;
7313 raw_unixmode = IVAL(pdata,8);
7314 /* Next 4 bytes are not yet defined. */
7316 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7317 PERM_NEW_DIR, &unixmode);
7318 if (!NT_STATUS_IS_OK(status)) {
7319 return status;
7322 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7324 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7325 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7327 status = SMB_VFS_CREATE_FILE(
7328 conn, /* conn */
7329 req, /* req */
7330 0, /* root_dir_fid */
7331 smb_fname, /* fname */
7332 FILE_READ_ATTRIBUTES, /* access_mask */
7333 FILE_SHARE_NONE, /* share_access */
7334 FILE_CREATE, /* create_disposition*/
7335 FILE_DIRECTORY_FILE, /* create_options */
7336 mod_unixmode, /* file_attributes */
7337 0, /* oplock_request */
7338 0, /* allocation_size */
7339 0, /* private_flags */
7340 NULL, /* sd */
7341 NULL, /* ea_list */
7342 &fsp, /* result */
7343 &info); /* pinfo */
7345 if (NT_STATUS_IS_OK(status)) {
7346 close_file(req, fsp, NORMAL_CLOSE);
7349 info_level_return = SVAL(pdata,16);
7351 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7352 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7353 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7354 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7355 } else {
7356 *pdata_return_size = 12;
7359 /* Realloc the data size */
7360 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7361 if (*ppdata == NULL) {
7362 *pdata_return_size = 0;
7363 return NT_STATUS_NO_MEMORY;
7365 pdata = *ppdata;
7367 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7368 SSVAL(pdata,2,0); /* No fnum. */
7369 SIVAL(pdata,4,info); /* Was directory created. */
7371 switch (info_level_return) {
7372 case SMB_QUERY_FILE_UNIX_BASIC:
7373 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7374 SSVAL(pdata,10,0); /* Padding. */
7375 store_file_unix_basic(conn, pdata + 12, fsp,
7376 &smb_fname->st);
7377 break;
7378 case SMB_QUERY_FILE_UNIX_INFO2:
7379 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7380 SSVAL(pdata,10,0); /* Padding. */
7381 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7382 &smb_fname->st);
7383 break;
7384 default:
7385 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7386 SSVAL(pdata,10,0); /* Padding. */
7387 break;
7390 return status;
7393 /****************************************************************************
7394 Open/Create a file with POSIX semantics.
7395 ****************************************************************************/
7397 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7398 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7400 static NTSTATUS smb_posix_open(connection_struct *conn,
7401 struct smb_request *req,
7402 char **ppdata,
7403 int total_data,
7404 struct smb_filename *smb_fname,
7405 int *pdata_return_size)
7407 bool extended_oplock_granted = False;
7408 char *pdata = *ppdata;
7409 uint32 flags = 0;
7410 uint32 wire_open_mode = 0;
7411 uint32 raw_unixmode = 0;
7412 uint32 mod_unixmode = 0;
7413 uint32 create_disp = 0;
7414 uint32 access_mask = 0;
7415 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7416 NTSTATUS status = NT_STATUS_OK;
7417 mode_t unixmode = (mode_t)0;
7418 files_struct *fsp = NULL;
7419 int oplock_request = 0;
7420 int info = 0;
7421 uint16 info_level_return = 0;
7423 if (total_data < 18) {
7424 return NT_STATUS_INVALID_PARAMETER;
7427 flags = IVAL(pdata,0);
7428 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7429 if (oplock_request) {
7430 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7433 wire_open_mode = IVAL(pdata,4);
7435 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7436 return smb_posix_mkdir(conn, req,
7437 ppdata,
7438 total_data,
7439 smb_fname,
7440 pdata_return_size);
7443 switch (wire_open_mode & SMB_ACCMODE) {
7444 case SMB_O_RDONLY:
7445 access_mask = SMB_O_RDONLY_MAPPING;
7446 break;
7447 case SMB_O_WRONLY:
7448 access_mask = SMB_O_WRONLY_MAPPING;
7449 break;
7450 case SMB_O_RDWR:
7451 access_mask = (SMB_O_RDONLY_MAPPING|
7452 SMB_O_WRONLY_MAPPING);
7453 break;
7454 default:
7455 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7456 (unsigned int)wire_open_mode ));
7457 return NT_STATUS_INVALID_PARAMETER;
7460 wire_open_mode &= ~SMB_ACCMODE;
7462 /* First take care of O_CREAT|O_EXCL interactions. */
7463 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7464 case (SMB_O_CREAT | SMB_O_EXCL):
7465 /* File exists fail. File not exist create. */
7466 create_disp = FILE_CREATE;
7467 break;
7468 case SMB_O_CREAT:
7469 /* File exists open. File not exist create. */
7470 create_disp = FILE_OPEN_IF;
7471 break;
7472 case SMB_O_EXCL:
7473 /* O_EXCL on its own without O_CREAT is undefined.
7474 We deliberately ignore it as some versions of
7475 Linux CIFSFS can send a bare O_EXCL on the
7476 wire which other filesystems in the kernel
7477 ignore. See bug 9519 for details. */
7479 /* Fallthrough. */
7481 case 0:
7482 /* File exists open. File not exist fail. */
7483 create_disp = FILE_OPEN;
7484 break;
7485 default:
7486 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7487 (unsigned int)wire_open_mode ));
7488 return NT_STATUS_INVALID_PARAMETER;
7491 /* Next factor in the effects of O_TRUNC. */
7492 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7494 if (wire_open_mode & SMB_O_TRUNC) {
7495 switch (create_disp) {
7496 case FILE_CREATE:
7497 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7498 /* Leave create_disp alone as
7499 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7501 /* File exists fail. File not exist create. */
7502 break;
7503 case FILE_OPEN_IF:
7504 /* SMB_O_CREAT | SMB_O_TRUNC */
7505 /* File exists overwrite. File not exist create. */
7506 create_disp = FILE_OVERWRITE_IF;
7507 break;
7508 case FILE_OPEN:
7509 /* SMB_O_TRUNC */
7510 /* File exists overwrite. File not exist fail. */
7511 create_disp = FILE_OVERWRITE;
7512 break;
7513 default:
7514 /* Cannot get here. */
7515 smb_panic("smb_posix_open: logic error");
7516 return NT_STATUS_INVALID_PARAMETER;
7520 raw_unixmode = IVAL(pdata,8);
7521 /* Next 4 bytes are not yet defined. */
7523 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7524 (VALID_STAT(smb_fname->st) ?
7525 PERM_EXISTING_FILE : PERM_NEW_FILE),
7526 &unixmode);
7528 if (!NT_STATUS_IS_OK(status)) {
7529 return status;
7532 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7534 if (wire_open_mode & SMB_O_SYNC) {
7535 create_options |= FILE_WRITE_THROUGH;
7537 if (wire_open_mode & SMB_O_APPEND) {
7538 access_mask |= FILE_APPEND_DATA;
7540 if (wire_open_mode & SMB_O_DIRECT) {
7541 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7544 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7545 VALID_STAT_OF_DIR(smb_fname->st)) {
7546 if (access_mask != SMB_O_RDONLY_MAPPING) {
7547 return NT_STATUS_FILE_IS_A_DIRECTORY;
7549 create_options &= ~FILE_NON_DIRECTORY_FILE;
7550 create_options |= FILE_DIRECTORY_FILE;
7553 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7554 smb_fname_str_dbg(smb_fname),
7555 (unsigned int)wire_open_mode,
7556 (unsigned int)unixmode ));
7558 status = SMB_VFS_CREATE_FILE(
7559 conn, /* conn */
7560 req, /* req */
7561 0, /* root_dir_fid */
7562 smb_fname, /* fname */
7563 access_mask, /* access_mask */
7564 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7565 FILE_SHARE_DELETE),
7566 create_disp, /* create_disposition*/
7567 create_options, /* create_options */
7568 mod_unixmode, /* file_attributes */
7569 oplock_request, /* oplock_request */
7570 0, /* allocation_size */
7571 0, /* private_flags */
7572 NULL, /* sd */
7573 NULL, /* ea_list */
7574 &fsp, /* result */
7575 &info); /* pinfo */
7577 if (!NT_STATUS_IS_OK(status)) {
7578 return status;
7581 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7582 extended_oplock_granted = True;
7585 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7586 extended_oplock_granted = True;
7589 info_level_return = SVAL(pdata,16);
7591 /* Allocate the correct return size. */
7593 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7594 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7595 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7596 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7597 } else {
7598 *pdata_return_size = 12;
7601 /* Realloc the data size */
7602 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7603 if (*ppdata == NULL) {
7604 close_file(req, fsp, ERROR_CLOSE);
7605 *pdata_return_size = 0;
7606 return NT_STATUS_NO_MEMORY;
7608 pdata = *ppdata;
7610 if (extended_oplock_granted) {
7611 if (flags & REQUEST_BATCH_OPLOCK) {
7612 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7613 } else {
7614 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7616 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7617 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7618 } else {
7619 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7622 SSVAL(pdata,2,fsp->fnum);
7623 SIVAL(pdata,4,info); /* Was file created etc. */
7625 switch (info_level_return) {
7626 case SMB_QUERY_FILE_UNIX_BASIC:
7627 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7628 SSVAL(pdata,10,0); /* padding. */
7629 store_file_unix_basic(conn, pdata + 12, fsp,
7630 &smb_fname->st);
7631 break;
7632 case SMB_QUERY_FILE_UNIX_INFO2:
7633 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7634 SSVAL(pdata,10,0); /* padding. */
7635 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7636 &smb_fname->st);
7637 break;
7638 default:
7639 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7640 SSVAL(pdata,10,0); /* padding. */
7641 break;
7643 return NT_STATUS_OK;
7646 /****************************************************************************
7647 Delete a file with POSIX semantics.
7648 ****************************************************************************/
7650 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7651 struct smb_request *req,
7652 const char *pdata,
7653 int total_data,
7654 struct smb_filename *smb_fname)
7656 NTSTATUS status = NT_STATUS_OK;
7657 files_struct *fsp = NULL;
7658 uint16 flags = 0;
7659 char del = 1;
7660 int info = 0;
7661 int create_options = 0;
7662 int i;
7663 struct share_mode_lock *lck = NULL;
7665 if (total_data < 2) {
7666 return NT_STATUS_INVALID_PARAMETER;
7669 flags = SVAL(pdata,0);
7671 if (!VALID_STAT(smb_fname->st)) {
7672 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7675 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7676 !VALID_STAT_OF_DIR(smb_fname->st)) {
7677 return NT_STATUS_NOT_A_DIRECTORY;
7680 DEBUG(10,("smb_posix_unlink: %s %s\n",
7681 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7682 smb_fname_str_dbg(smb_fname)));
7684 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7685 create_options |= FILE_DIRECTORY_FILE;
7688 status = SMB_VFS_CREATE_FILE(
7689 conn, /* conn */
7690 req, /* req */
7691 0, /* root_dir_fid */
7692 smb_fname, /* fname */
7693 DELETE_ACCESS, /* access_mask */
7694 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7695 FILE_SHARE_DELETE),
7696 FILE_OPEN, /* create_disposition*/
7697 create_options, /* create_options */
7698 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7699 0, /* oplock_request */
7700 0, /* allocation_size */
7701 0, /* private_flags */
7702 NULL, /* sd */
7703 NULL, /* ea_list */
7704 &fsp, /* result */
7705 &info); /* pinfo */
7707 if (!NT_STATUS_IS_OK(status)) {
7708 return status;
7712 * Don't lie to client. If we can't really delete due to
7713 * non-POSIX opens return SHARING_VIOLATION.
7716 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7717 if (lck == NULL) {
7718 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7719 "lock for file %s\n", fsp_str_dbg(fsp)));
7720 close_file(req, fsp, NORMAL_CLOSE);
7721 return NT_STATUS_INVALID_PARAMETER;
7725 * See if others still have the file open. If this is the case, then
7726 * don't delete. If all opens are POSIX delete we can set the delete
7727 * on close disposition.
7729 for (i=0; i<lck->data->num_share_modes; i++) {
7730 struct share_mode_entry *e = &lck->data->share_modes[i];
7731 if (is_valid_share_mode_entry(e)) {
7732 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7733 continue;
7735 if (share_mode_stale_pid(lck->data, i)) {
7736 continue;
7738 /* Fail with sharing violation. */
7739 TALLOC_FREE(lck);
7740 close_file(req, fsp, NORMAL_CLOSE);
7741 return NT_STATUS_SHARING_VIOLATION;
7746 * Set the delete on close.
7748 status = smb_set_file_disposition_info(conn,
7749 &del,
7751 fsp,
7752 smb_fname);
7754 TALLOC_FREE(lck);
7756 if (!NT_STATUS_IS_OK(status)) {
7757 close_file(req, fsp, NORMAL_CLOSE);
7758 return status;
7760 return close_file(req, fsp, NORMAL_CLOSE);
7763 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7764 struct smb_request *req,
7765 TALLOC_CTX *mem_ctx,
7766 uint16_t info_level,
7767 files_struct *fsp,
7768 struct smb_filename *smb_fname,
7769 char **ppdata, int total_data,
7770 int *ret_data_size)
7772 char *pdata = *ppdata;
7773 NTSTATUS status = NT_STATUS_OK;
7774 int data_return_size = 0;
7776 *ret_data_size = 0;
7778 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7779 return NT_STATUS_INVALID_LEVEL;
7782 if (!CAN_WRITE(conn)) {
7783 /* Allow POSIX opens. The open path will deny
7784 * any non-readonly opens. */
7785 if (info_level != SMB_POSIX_PATH_OPEN) {
7786 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7790 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7791 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7792 fsp_fnum_dbg(fsp),
7793 info_level, total_data));
7795 switch (info_level) {
7797 case SMB_INFO_STANDARD:
7799 status = smb_set_info_standard(conn,
7800 pdata,
7801 total_data,
7802 fsp,
7803 smb_fname);
7804 break;
7807 case SMB_INFO_SET_EA:
7809 status = smb_info_set_ea(conn,
7810 pdata,
7811 total_data,
7812 fsp,
7813 smb_fname);
7814 break;
7817 case SMB_SET_FILE_BASIC_INFO:
7818 case SMB_FILE_BASIC_INFORMATION:
7820 status = smb_set_file_basic_info(conn,
7821 pdata,
7822 total_data,
7823 fsp,
7824 smb_fname);
7825 break;
7828 case SMB_FILE_ALLOCATION_INFORMATION:
7829 case SMB_SET_FILE_ALLOCATION_INFO:
7831 status = smb_set_file_allocation_info(conn, req,
7832 pdata,
7833 total_data,
7834 fsp,
7835 smb_fname);
7836 break;
7839 case SMB_FILE_END_OF_FILE_INFORMATION:
7840 case SMB_SET_FILE_END_OF_FILE_INFO:
7843 * XP/Win7 both fail after the createfile with
7844 * SMB_SET_FILE_END_OF_FILE_INFO but not
7845 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7846 * The level is known here, so pass it down
7847 * appropriately.
7849 bool should_fail =
7850 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7852 status = smb_set_file_end_of_file_info(conn, req,
7853 pdata,
7854 total_data,
7855 fsp,
7856 smb_fname,
7857 should_fail);
7858 break;
7861 case SMB_FILE_DISPOSITION_INFORMATION:
7862 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7864 #if 0
7865 /* JRA - We used to just ignore this on a path ?
7866 * Shouldn't this be invalid level on a pathname
7867 * based call ?
7869 if (tran_call != TRANSACT2_SETFILEINFO) {
7870 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7872 #endif
7873 status = smb_set_file_disposition_info(conn,
7874 pdata,
7875 total_data,
7876 fsp,
7877 smb_fname);
7878 break;
7881 case SMB_FILE_POSITION_INFORMATION:
7883 status = smb_file_position_information(conn,
7884 pdata,
7885 total_data,
7886 fsp);
7887 break;
7890 case SMB_FILE_FULL_EA_INFORMATION:
7892 status = smb_set_file_full_ea_info(conn,
7893 pdata,
7894 total_data,
7895 fsp);
7896 break;
7899 /* From tridge Samba4 :
7900 * MODE_INFORMATION in setfileinfo (I have no
7901 * idea what "mode information" on a file is - it takes a value of 0,
7902 * 2, 4 or 6. What could it be?).
7905 case SMB_FILE_MODE_INFORMATION:
7907 status = smb_file_mode_information(conn,
7908 pdata,
7909 total_data);
7910 break;
7914 * CIFS UNIX extensions.
7917 case SMB_SET_FILE_UNIX_BASIC:
7919 status = smb_set_file_unix_basic(conn, req,
7920 pdata,
7921 total_data,
7922 fsp,
7923 smb_fname);
7924 break;
7927 case SMB_SET_FILE_UNIX_INFO2:
7929 status = smb_set_file_unix_info2(conn, req,
7930 pdata,
7931 total_data,
7932 fsp,
7933 smb_fname);
7934 break;
7937 case SMB_SET_FILE_UNIX_LINK:
7939 if (fsp) {
7940 /* We must have a pathname for this. */
7941 return NT_STATUS_INVALID_LEVEL;
7943 status = smb_set_file_unix_link(conn, req, pdata,
7944 total_data, smb_fname);
7945 break;
7948 case SMB_SET_FILE_UNIX_HLINK:
7950 if (fsp) {
7951 /* We must have a pathname for this. */
7952 return NT_STATUS_INVALID_LEVEL;
7954 status = smb_set_file_unix_hlink(conn, req,
7955 pdata, total_data,
7956 smb_fname);
7957 break;
7960 case SMB_FILE_RENAME_INFORMATION:
7962 status = smb_file_rename_information(conn, req,
7963 pdata, total_data,
7964 fsp, smb_fname);
7965 break;
7968 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7970 /* SMB2 rename information. */
7971 status = smb2_file_rename_information(conn, req,
7972 pdata, total_data,
7973 fsp, smb_fname);
7974 break;
7977 case SMB_FILE_LINK_INFORMATION:
7979 status = smb_file_link_information(conn, req,
7980 pdata, total_data,
7981 fsp, smb_fname);
7982 break;
7985 #if defined(HAVE_POSIX_ACLS)
7986 case SMB_SET_POSIX_ACL:
7988 status = smb_set_posix_acl(conn,
7989 pdata,
7990 total_data,
7991 fsp,
7992 smb_fname);
7993 break;
7995 #endif
7997 case SMB_SET_POSIX_LOCK:
7999 if (!fsp) {
8000 return NT_STATUS_INVALID_LEVEL;
8002 status = smb_set_posix_lock(conn, req,
8003 pdata, total_data, fsp);
8004 break;
8007 case SMB_POSIX_PATH_OPEN:
8009 if (fsp) {
8010 /* We must have a pathname for this. */
8011 return NT_STATUS_INVALID_LEVEL;
8014 status = smb_posix_open(conn, req,
8015 ppdata,
8016 total_data,
8017 smb_fname,
8018 &data_return_size);
8019 break;
8022 case SMB_POSIX_PATH_UNLINK:
8024 if (fsp) {
8025 /* We must have a pathname for this. */
8026 return NT_STATUS_INVALID_LEVEL;
8029 status = smb_posix_unlink(conn, req,
8030 pdata,
8031 total_data,
8032 smb_fname);
8033 break;
8036 default:
8037 return NT_STATUS_INVALID_LEVEL;
8040 if (!NT_STATUS_IS_OK(status)) {
8041 return status;
8044 *ret_data_size = data_return_size;
8045 return NT_STATUS_OK;
8048 /****************************************************************************
8049 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8050 ****************************************************************************/
8052 static void call_trans2setfilepathinfo(connection_struct *conn,
8053 struct smb_request *req,
8054 unsigned int tran_call,
8055 char **pparams, int total_params,
8056 char **ppdata, int total_data,
8057 unsigned int max_data_bytes)
8059 char *params = *pparams;
8060 char *pdata = *ppdata;
8061 uint16 info_level;
8062 struct smb_filename *smb_fname = NULL;
8063 files_struct *fsp = NULL;
8064 NTSTATUS status = NT_STATUS_OK;
8065 int data_return_size = 0;
8067 if (!params) {
8068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8069 return;
8072 if (tran_call == TRANSACT2_SETFILEINFO) {
8073 if (total_params < 4) {
8074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8075 return;
8078 fsp = file_fsp(req, SVAL(params,0));
8079 /* Basic check for non-null fsp. */
8080 if (!check_fsp_open(conn, req, fsp)) {
8081 return;
8083 info_level = SVAL(params,2);
8085 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8086 &smb_fname);
8087 if (!NT_STATUS_IS_OK(status)) {
8088 reply_nterror(req, status);
8089 return;
8092 if(fsp->fh->fd == -1) {
8094 * This is actually a SETFILEINFO on a directory
8095 * handle (returned from an NT SMB). NT5.0 seems
8096 * to do this call. JRA.
8098 if (INFO_LEVEL_IS_UNIX(info_level)) {
8099 /* Always do lstat for UNIX calls. */
8100 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8101 DEBUG(3,("call_trans2setfilepathinfo: "
8102 "SMB_VFS_LSTAT of %s failed "
8103 "(%s)\n",
8104 smb_fname_str_dbg(smb_fname),
8105 strerror(errno)));
8106 reply_nterror(req, map_nt_error_from_unix(errno));
8107 return;
8109 } else {
8110 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8111 DEBUG(3,("call_trans2setfilepathinfo: "
8112 "fileinfo of %s failed (%s)\n",
8113 smb_fname_str_dbg(smb_fname),
8114 strerror(errno)));
8115 reply_nterror(req, map_nt_error_from_unix(errno));
8116 return;
8119 } else if (fsp->print_file) {
8121 * Doing a DELETE_ON_CLOSE should cancel a print job.
8123 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8124 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8126 DEBUG(3,("call_trans2setfilepathinfo: "
8127 "Cancelling print job (%s)\n",
8128 fsp_str_dbg(fsp)));
8130 SSVAL(params,0,0);
8131 send_trans2_replies(conn, req, params, 2,
8132 *ppdata, 0,
8133 max_data_bytes);
8134 return;
8135 } else {
8136 reply_nterror(req,
8137 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8138 return;
8140 } else {
8142 * Original code - this is an open file.
8144 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8145 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8146 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8147 strerror(errno)));
8148 reply_nterror(req, map_nt_error_from_unix(errno));
8149 return;
8152 } else {
8153 char *fname = NULL;
8154 uint32_t ucf_flags = 0;
8156 /* set path info */
8157 if (total_params < 7) {
8158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8159 return;
8162 info_level = SVAL(params,0);
8163 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8164 total_params - 6, STR_TERMINATE,
8165 &status);
8166 if (!NT_STATUS_IS_OK(status)) {
8167 reply_nterror(req, status);
8168 return;
8171 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8172 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8173 info_level == SMB_FILE_RENAME_INFORMATION ||
8174 info_level == SMB_POSIX_PATH_UNLINK) {
8175 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8178 status = filename_convert(req, conn,
8179 req->flags2 & FLAGS2_DFS_PATHNAMES,
8180 fname,
8181 ucf_flags,
8182 NULL,
8183 &smb_fname);
8184 if (!NT_STATUS_IS_OK(status)) {
8185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8186 reply_botherror(req,
8187 NT_STATUS_PATH_NOT_COVERED,
8188 ERRSRV, ERRbadpath);
8189 return;
8191 reply_nterror(req, status);
8192 return;
8195 if (INFO_LEVEL_IS_UNIX(info_level)) {
8197 * For CIFS UNIX extensions the target name may not exist.
8200 /* Always do lstat for UNIX calls. */
8201 SMB_VFS_LSTAT(conn, smb_fname);
8203 } else if (!VALID_STAT(smb_fname->st) &&
8204 SMB_VFS_STAT(conn, smb_fname)) {
8205 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8206 "%s failed (%s)\n",
8207 smb_fname_str_dbg(smb_fname),
8208 strerror(errno)));
8209 reply_nterror(req, map_nt_error_from_unix(errno));
8210 return;
8214 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8215 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8216 fsp_fnum_dbg(fsp),
8217 info_level,total_data));
8219 /* Realloc the parameter size */
8220 *pparams = (char *)SMB_REALLOC(*pparams,2);
8221 if (*pparams == NULL) {
8222 reply_nterror(req, NT_STATUS_NO_MEMORY);
8223 return;
8225 params = *pparams;
8227 SSVAL(params,0,0);
8229 status = smbd_do_setfilepathinfo(conn, req, req,
8230 info_level,
8231 fsp,
8232 smb_fname,
8233 ppdata, total_data,
8234 &data_return_size);
8235 if (!NT_STATUS_IS_OK(status)) {
8236 if (open_was_deferred(req->sconn, req->mid)) {
8237 /* We have re-scheduled this call. */
8238 return;
8240 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8241 /* We have re-scheduled this call. */
8242 return;
8244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8246 ERRSRV, ERRbadpath);
8247 return;
8249 if (info_level == SMB_POSIX_PATH_OPEN) {
8250 reply_openerror(req, status);
8251 return;
8254 reply_nterror(req, status);
8255 return;
8258 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8259 max_data_bytes);
8261 return;
8264 /****************************************************************************
8265 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8266 ****************************************************************************/
8268 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8269 char **pparams, int total_params,
8270 char **ppdata, int total_data,
8271 unsigned int max_data_bytes)
8273 struct smb_filename *smb_dname = NULL;
8274 char *params = *pparams;
8275 char *pdata = *ppdata;
8276 char *directory = NULL;
8277 NTSTATUS status = NT_STATUS_OK;
8278 struct ea_list *ea_list = NULL;
8279 TALLOC_CTX *ctx = talloc_tos();
8281 if (!CAN_WRITE(conn)) {
8282 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8283 return;
8286 if (total_params < 5) {
8287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8288 return;
8291 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8292 total_params - 4, STR_TERMINATE,
8293 &status);
8294 if (!NT_STATUS_IS_OK(status)) {
8295 reply_nterror(req, status);
8296 return;
8299 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8301 status = filename_convert(ctx,
8302 conn,
8303 req->flags2 & FLAGS2_DFS_PATHNAMES,
8304 directory,
8306 NULL,
8307 &smb_dname);
8309 if (!NT_STATUS_IS_OK(status)) {
8310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8311 reply_botherror(req,
8312 NT_STATUS_PATH_NOT_COVERED,
8313 ERRSRV, ERRbadpath);
8314 return;
8316 reply_nterror(req, status);
8317 return;
8321 * OS/2 workplace shell seems to send SET_EA requests of "null"
8322 * length (4 bytes containing IVAL 4).
8323 * They seem to have no effect. Bug #3212. JRA.
8326 if (total_data && (total_data != 4)) {
8327 /* Any data in this call is an EA list. */
8328 if (total_data < 10) {
8329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8330 goto out;
8333 if (IVAL(pdata,0) > total_data) {
8334 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8335 IVAL(pdata,0), (unsigned int)total_data));
8336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8337 goto out;
8340 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8341 total_data - 4);
8342 if (!ea_list) {
8343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8344 goto out;
8347 if (!lp_ea_support(SNUM(conn))) {
8348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8349 goto out;
8352 /* If total_data == 4 Windows doesn't care what values
8353 * are placed in that field, it just ignores them.
8354 * The System i QNTC IBM SMB client puts bad values here,
8355 * so ignore them. */
8357 status = create_directory(conn, req, smb_dname);
8359 if (!NT_STATUS_IS_OK(status)) {
8360 reply_nterror(req, status);
8361 goto out;
8364 /* Try and set any given EA. */
8365 if (ea_list) {
8366 status = set_ea(conn, NULL, smb_dname, ea_list);
8367 if (!NT_STATUS_IS_OK(status)) {
8368 reply_nterror(req, status);
8369 goto out;
8373 /* Realloc the parameter and data sizes */
8374 *pparams = (char *)SMB_REALLOC(*pparams,2);
8375 if(*pparams == NULL) {
8376 reply_nterror(req, NT_STATUS_NO_MEMORY);
8377 goto out;
8379 params = *pparams;
8381 SSVAL(params,0,0);
8383 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8385 out:
8386 TALLOC_FREE(smb_dname);
8387 return;
8390 /****************************************************************************
8391 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8392 We don't actually do this - we just send a null response.
8393 ****************************************************************************/
8395 static void call_trans2findnotifyfirst(connection_struct *conn,
8396 struct smb_request *req,
8397 char **pparams, int total_params,
8398 char **ppdata, int total_data,
8399 unsigned int max_data_bytes)
8401 char *params = *pparams;
8402 uint16 info_level;
8404 if (total_params < 6) {
8405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 return;
8409 info_level = SVAL(params,4);
8410 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8412 switch (info_level) {
8413 case 1:
8414 case 2:
8415 break;
8416 default:
8417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8418 return;
8421 /* Realloc the parameter and data sizes */
8422 *pparams = (char *)SMB_REALLOC(*pparams,6);
8423 if (*pparams == NULL) {
8424 reply_nterror(req, NT_STATUS_NO_MEMORY);
8425 return;
8427 params = *pparams;
8429 SSVAL(params,0,fnf_handle);
8430 SSVAL(params,2,0); /* No changes */
8431 SSVAL(params,4,0); /* No EA errors */
8433 fnf_handle++;
8435 if(fnf_handle == 0)
8436 fnf_handle = 257;
8438 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8440 return;
8443 /****************************************************************************
8444 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8445 changes). Currently this does nothing.
8446 ****************************************************************************/
8448 static void call_trans2findnotifynext(connection_struct *conn,
8449 struct smb_request *req,
8450 char **pparams, int total_params,
8451 char **ppdata, int total_data,
8452 unsigned int max_data_bytes)
8454 char *params = *pparams;
8456 DEBUG(3,("call_trans2findnotifynext\n"));
8458 /* Realloc the parameter and data sizes */
8459 *pparams = (char *)SMB_REALLOC(*pparams,4);
8460 if (*pparams == NULL) {
8461 reply_nterror(req, NT_STATUS_NO_MEMORY);
8462 return;
8464 params = *pparams;
8466 SSVAL(params,0,0); /* No changes */
8467 SSVAL(params,2,0); /* No EA errors */
8469 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8471 return;
8474 /****************************************************************************
8475 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8476 ****************************************************************************/
8478 static void call_trans2getdfsreferral(connection_struct *conn,
8479 struct smb_request *req,
8480 char **pparams, int total_params,
8481 char **ppdata, int total_data,
8482 unsigned int max_data_bytes)
8484 char *params = *pparams;
8485 char *pathname = NULL;
8486 int reply_size = 0;
8487 int max_referral_level;
8488 NTSTATUS status = NT_STATUS_OK;
8489 TALLOC_CTX *ctx = talloc_tos();
8491 DEBUG(10,("call_trans2getdfsreferral\n"));
8493 if (total_params < 3) {
8494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8495 return;
8498 max_referral_level = SVAL(params,0);
8500 if(!lp_host_msdfs()) {
8501 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8502 return;
8505 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8506 total_params - 2, STR_TERMINATE);
8507 if (!pathname) {
8508 reply_nterror(req, NT_STATUS_NOT_FOUND);
8509 return;
8511 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8512 ppdata,&status)) < 0) {
8513 reply_nterror(req, status);
8514 return;
8517 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8518 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8519 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8521 return;
8524 #define LMCAT_SPL 0x53
8525 #define LMFUNC_GETJOBID 0x60
8527 /****************************************************************************
8528 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8529 ****************************************************************************/
8531 static void call_trans2ioctl(connection_struct *conn,
8532 struct smb_request *req,
8533 char **pparams, int total_params,
8534 char **ppdata, int total_data,
8535 unsigned int max_data_bytes)
8537 char *pdata = *ppdata;
8538 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8540 /* check for an invalid fid before proceeding */
8542 if (!fsp) {
8543 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8544 return;
8547 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8548 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8549 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8550 if (*ppdata == NULL) {
8551 reply_nterror(req, NT_STATUS_NO_MEMORY);
8552 return;
8554 pdata = *ppdata;
8556 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8557 CAN ACCEPT THIS IN UNICODE. JRA. */
8559 /* Job number */
8560 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8562 srvstr_push(pdata, req->flags2, pdata + 2,
8563 lp_netbios_name(), 15,
8564 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8565 srvstr_push(pdata, req->flags2, pdata+18,
8566 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8567 STR_ASCII|STR_TERMINATE); /* Service name */
8568 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8569 max_data_bytes);
8570 return;
8573 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8574 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8577 /****************************************************************************
8578 Reply to a SMBfindclose (stop trans2 directory search).
8579 ****************************************************************************/
8581 void reply_findclose(struct smb_request *req)
8583 int dptr_num;
8584 struct smbd_server_connection *sconn = req->sconn;
8586 START_PROFILE(SMBfindclose);
8588 if (req->wct < 1) {
8589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8590 END_PROFILE(SMBfindclose);
8591 return;
8594 dptr_num = SVALS(req->vwv+0, 0);
8596 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8598 dptr_close(sconn, &dptr_num);
8600 reply_outbuf(req, 0, 0);
8602 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8604 END_PROFILE(SMBfindclose);
8605 return;
8608 /****************************************************************************
8609 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8610 ****************************************************************************/
8612 void reply_findnclose(struct smb_request *req)
8614 int dptr_num;
8616 START_PROFILE(SMBfindnclose);
8618 if (req->wct < 1) {
8619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8620 END_PROFILE(SMBfindnclose);
8621 return;
8624 dptr_num = SVAL(req->vwv+0, 0);
8626 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8628 /* We never give out valid handles for a
8629 findnotifyfirst - so any dptr_num is ok here.
8630 Just ignore it. */
8632 reply_outbuf(req, 0, 0);
8634 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8636 END_PROFILE(SMBfindnclose);
8637 return;
8640 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8641 struct trans_state *state)
8643 if (get_Protocol() >= PROTOCOL_NT1) {
8644 req->flags2 |= 0x40; /* IS_LONG_NAME */
8645 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8648 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8649 if (state->call != TRANSACT2_QFSINFO &&
8650 state->call != TRANSACT2_SETFSINFO) {
8651 DEBUG(0,("handle_trans2: encryption required "
8652 "with call 0x%x\n",
8653 (unsigned int)state->call));
8654 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8655 return;
8659 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8661 /* Now we must call the relevant TRANS2 function */
8662 switch(state->call) {
8663 case TRANSACT2_OPEN:
8665 START_PROFILE(Trans2_open);
8666 call_trans2open(conn, req,
8667 &state->param, state->total_param,
8668 &state->data, state->total_data,
8669 state->max_data_return);
8670 END_PROFILE(Trans2_open);
8671 break;
8674 case TRANSACT2_FINDFIRST:
8676 START_PROFILE(Trans2_findfirst);
8677 call_trans2findfirst(conn, req,
8678 &state->param, state->total_param,
8679 &state->data, state->total_data,
8680 state->max_data_return);
8681 END_PROFILE(Trans2_findfirst);
8682 break;
8685 case TRANSACT2_FINDNEXT:
8687 START_PROFILE(Trans2_findnext);
8688 call_trans2findnext(conn, req,
8689 &state->param, state->total_param,
8690 &state->data, state->total_data,
8691 state->max_data_return);
8692 END_PROFILE(Trans2_findnext);
8693 break;
8696 case TRANSACT2_QFSINFO:
8698 START_PROFILE(Trans2_qfsinfo);
8699 call_trans2qfsinfo(conn, req,
8700 &state->param, state->total_param,
8701 &state->data, state->total_data,
8702 state->max_data_return);
8703 END_PROFILE(Trans2_qfsinfo);
8704 break;
8707 case TRANSACT2_SETFSINFO:
8709 START_PROFILE(Trans2_setfsinfo);
8710 call_trans2setfsinfo(conn, req,
8711 &state->param, state->total_param,
8712 &state->data, state->total_data,
8713 state->max_data_return);
8714 END_PROFILE(Trans2_setfsinfo);
8715 break;
8718 case TRANSACT2_QPATHINFO:
8719 case TRANSACT2_QFILEINFO:
8721 START_PROFILE(Trans2_qpathinfo);
8722 call_trans2qfilepathinfo(conn, req, state->call,
8723 &state->param, state->total_param,
8724 &state->data, state->total_data,
8725 state->max_data_return);
8726 END_PROFILE(Trans2_qpathinfo);
8727 break;
8730 case TRANSACT2_SETPATHINFO:
8731 case TRANSACT2_SETFILEINFO:
8733 START_PROFILE(Trans2_setpathinfo);
8734 call_trans2setfilepathinfo(conn, req, state->call,
8735 &state->param, state->total_param,
8736 &state->data, state->total_data,
8737 state->max_data_return);
8738 END_PROFILE(Trans2_setpathinfo);
8739 break;
8742 case TRANSACT2_FINDNOTIFYFIRST:
8744 START_PROFILE(Trans2_findnotifyfirst);
8745 call_trans2findnotifyfirst(conn, req,
8746 &state->param, state->total_param,
8747 &state->data, state->total_data,
8748 state->max_data_return);
8749 END_PROFILE(Trans2_findnotifyfirst);
8750 break;
8753 case TRANSACT2_FINDNOTIFYNEXT:
8755 START_PROFILE(Trans2_findnotifynext);
8756 call_trans2findnotifynext(conn, req,
8757 &state->param, state->total_param,
8758 &state->data, state->total_data,
8759 state->max_data_return);
8760 END_PROFILE(Trans2_findnotifynext);
8761 break;
8764 case TRANSACT2_MKDIR:
8766 START_PROFILE(Trans2_mkdir);
8767 call_trans2mkdir(conn, req,
8768 &state->param, state->total_param,
8769 &state->data, state->total_data,
8770 state->max_data_return);
8771 END_PROFILE(Trans2_mkdir);
8772 break;
8775 case TRANSACT2_GET_DFS_REFERRAL:
8777 START_PROFILE(Trans2_get_dfs_referral);
8778 call_trans2getdfsreferral(conn, req,
8779 &state->param, state->total_param,
8780 &state->data, state->total_data,
8781 state->max_data_return);
8782 END_PROFILE(Trans2_get_dfs_referral);
8783 break;
8786 case TRANSACT2_IOCTL:
8788 START_PROFILE(Trans2_ioctl);
8789 call_trans2ioctl(conn, req,
8790 &state->param, state->total_param,
8791 &state->data, state->total_data,
8792 state->max_data_return);
8793 END_PROFILE(Trans2_ioctl);
8794 break;
8797 default:
8798 /* Error in request */
8799 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8800 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8804 /****************************************************************************
8805 Reply to a SMBtrans2.
8806 ****************************************************************************/
8808 void reply_trans2(struct smb_request *req)
8810 connection_struct *conn = req->conn;
8811 unsigned int dsoff;
8812 unsigned int dscnt;
8813 unsigned int psoff;
8814 unsigned int pscnt;
8815 unsigned int tran_call;
8816 struct trans_state *state;
8817 NTSTATUS result;
8819 START_PROFILE(SMBtrans2);
8821 if (req->wct < 14) {
8822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8823 END_PROFILE(SMBtrans2);
8824 return;
8827 dsoff = SVAL(req->vwv+12, 0);
8828 dscnt = SVAL(req->vwv+11, 0);
8829 psoff = SVAL(req->vwv+10, 0);
8830 pscnt = SVAL(req->vwv+9, 0);
8831 tran_call = SVAL(req->vwv+14, 0);
8833 result = allow_new_trans(conn->pending_trans, req->mid);
8834 if (!NT_STATUS_IS_OK(result)) {
8835 DEBUG(2, ("Got invalid trans2 request: %s\n",
8836 nt_errstr(result)));
8837 reply_nterror(req, result);
8838 END_PROFILE(SMBtrans2);
8839 return;
8842 if (IS_IPC(conn)) {
8843 switch (tran_call) {
8844 /* List the allowed trans2 calls on IPC$ */
8845 case TRANSACT2_OPEN:
8846 case TRANSACT2_GET_DFS_REFERRAL:
8847 case TRANSACT2_QFILEINFO:
8848 case TRANSACT2_QFSINFO:
8849 case TRANSACT2_SETFSINFO:
8850 break;
8851 default:
8852 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8853 END_PROFILE(SMBtrans2);
8854 return;
8858 if ((state = talloc(conn, struct trans_state)) == NULL) {
8859 DEBUG(0, ("talloc failed\n"));
8860 reply_nterror(req, NT_STATUS_NO_MEMORY);
8861 END_PROFILE(SMBtrans2);
8862 return;
8865 state->cmd = SMBtrans2;
8867 state->mid = req->mid;
8868 state->vuid = req->vuid;
8869 state->setup_count = SVAL(req->vwv+13, 0);
8870 state->setup = NULL;
8871 state->total_param = SVAL(req->vwv+0, 0);
8872 state->param = NULL;
8873 state->total_data = SVAL(req->vwv+1, 0);
8874 state->data = NULL;
8875 state->max_param_return = SVAL(req->vwv+2, 0);
8876 state->max_data_return = SVAL(req->vwv+3, 0);
8877 state->max_setup_return = SVAL(req->vwv+4, 0);
8878 state->close_on_completion = BITSETW(req->vwv+5, 0);
8879 state->one_way = BITSETW(req->vwv+5, 1);
8881 state->call = tran_call;
8883 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8884 is so as a sanity check */
8885 if (state->setup_count != 1) {
8887 * Need to have rc=0 for ioctl to get job id for OS/2.
8888 * Network printing will fail if function is not successful.
8889 * Similar function in reply.c will be used if protocol
8890 * is LANMAN1.0 instead of LM1.2X002.
8891 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8892 * outbuf doesn't have to be set(only job id is used).
8894 if ( (state->setup_count == 4)
8895 && (tran_call == TRANSACT2_IOCTL)
8896 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8897 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8898 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8899 } else {
8900 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8901 DEBUG(2,("Transaction is %d\n",tran_call));
8902 TALLOC_FREE(state);
8903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8904 END_PROFILE(SMBtrans2);
8905 return;
8909 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8910 goto bad_param;
8912 if (state->total_data) {
8914 if (trans_oob(state->total_data, 0, dscnt)
8915 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8916 goto bad_param;
8919 /* Can't use talloc here, the core routines do realloc on the
8920 * params and data. */
8921 state->data = (char *)SMB_MALLOC(state->total_data);
8922 if (state->data == NULL) {
8923 DEBUG(0,("reply_trans2: data malloc fail for %u "
8924 "bytes !\n", (unsigned int)state->total_data));
8925 TALLOC_FREE(state);
8926 reply_nterror(req, NT_STATUS_NO_MEMORY);
8927 END_PROFILE(SMBtrans2);
8928 return;
8931 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8934 if (state->total_param) {
8936 if (trans_oob(state->total_param, 0, pscnt)
8937 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8938 goto bad_param;
8941 /* Can't use talloc here, the core routines do realloc on the
8942 * params and data. */
8943 state->param = (char *)SMB_MALLOC(state->total_param);
8944 if (state->param == NULL) {
8945 DEBUG(0,("reply_trans: param malloc fail for %u "
8946 "bytes !\n", (unsigned int)state->total_param));
8947 SAFE_FREE(state->data);
8948 TALLOC_FREE(state);
8949 reply_nterror(req, NT_STATUS_NO_MEMORY);
8950 END_PROFILE(SMBtrans2);
8951 return;
8954 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8957 state->received_data = dscnt;
8958 state->received_param = pscnt;
8960 if ((state->received_param == state->total_param) &&
8961 (state->received_data == state->total_data)) {
8963 handle_trans2(conn, req, state);
8965 SAFE_FREE(state->data);
8966 SAFE_FREE(state->param);
8967 TALLOC_FREE(state);
8968 END_PROFILE(SMBtrans2);
8969 return;
8972 DLIST_ADD(conn->pending_trans, state);
8974 /* We need to send an interim response then receive the rest
8975 of the parameter/data bytes */
8976 reply_outbuf(req, 0, 0);
8977 show_msg((char *)req->outbuf);
8978 END_PROFILE(SMBtrans2);
8979 return;
8981 bad_param:
8983 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8984 SAFE_FREE(state->data);
8985 SAFE_FREE(state->param);
8986 TALLOC_FREE(state);
8987 END_PROFILE(SMBtrans2);
8988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8992 /****************************************************************************
8993 Reply to a SMBtranss2
8994 ****************************************************************************/
8996 void reply_transs2(struct smb_request *req)
8998 connection_struct *conn = req->conn;
8999 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9000 struct trans_state *state;
9002 START_PROFILE(SMBtranss2);
9004 show_msg((const char *)req->inbuf);
9006 /* Windows clients expect all replies to
9007 a transact secondary (SMBtranss2 0x33)
9008 to have a command code of transact
9009 (SMBtrans2 0x32). See bug #8989
9010 and also [MS-CIFS] section 2.2.4.47.2
9011 for details.
9013 req->cmd = SMBtrans2;
9015 if (req->wct < 8) {
9016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9017 END_PROFILE(SMBtranss2);
9018 return;
9021 for (state = conn->pending_trans; state != NULL;
9022 state = state->next) {
9023 if (state->mid == req->mid) {
9024 break;
9028 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9030 END_PROFILE(SMBtranss2);
9031 return;
9034 /* Revise state->total_param and state->total_data in case they have
9035 changed downwards */
9037 if (SVAL(req->vwv+0, 0) < state->total_param)
9038 state->total_param = SVAL(req->vwv+0, 0);
9039 if (SVAL(req->vwv+1, 0) < state->total_data)
9040 state->total_data = SVAL(req->vwv+1, 0);
9042 pcnt = SVAL(req->vwv+2, 0);
9043 poff = SVAL(req->vwv+3, 0);
9044 pdisp = SVAL(req->vwv+4, 0);
9046 dcnt = SVAL(req->vwv+5, 0);
9047 doff = SVAL(req->vwv+6, 0);
9048 ddisp = SVAL(req->vwv+7, 0);
9050 state->received_param += pcnt;
9051 state->received_data += dcnt;
9053 if ((state->received_data > state->total_data) ||
9054 (state->received_param > state->total_param))
9055 goto bad_param;
9057 if (pcnt) {
9058 if (trans_oob(state->total_param, pdisp, pcnt)
9059 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9060 goto bad_param;
9062 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9065 if (dcnt) {
9066 if (trans_oob(state->total_data, ddisp, dcnt)
9067 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9068 goto bad_param;
9070 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9073 if ((state->received_param < state->total_param) ||
9074 (state->received_data < state->total_data)) {
9075 END_PROFILE(SMBtranss2);
9076 return;
9079 handle_trans2(conn, req, state);
9081 DLIST_REMOVE(conn->pending_trans, state);
9082 SAFE_FREE(state->data);
9083 SAFE_FREE(state->param);
9084 TALLOC_FREE(state);
9086 END_PROFILE(SMBtranss2);
9087 return;
9089 bad_param:
9091 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9092 DLIST_REMOVE(conn->pending_trans, state);
9093 SAFE_FREE(state->data);
9094 SAFE_FREE(state->param);
9095 TALLOC_FREE(state);
9096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9097 END_PROFILE(SMBtranss2);
9098 return;