s3:smbd: use req->xconn to send_trans2_replies()
[Samba.git] / source3 / smbd / trans2.c
blob9a02a74d2c200d9cea9bc33d185f662b3d05fc53
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("%s: ea_namelist size = %u\n",
262 __func__, (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbXsrv_connection *xconn = req->xconn;
863 struct smbd_server_connection *sconn = xconn->sconn;
864 int max_send = xconn->smb1.sessions.max_send;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
869 for OS/2. */
871 if (max_data_bytes > 0 && datasize > max_data_bytes) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes, datasize ));
874 datasize = data_to_send = max_data_bytes;
875 overflow = True;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send == 0 && data_to_send == 0) {
881 reply_outbuf(req, 10, 0);
882 if (NT_STATUS_V(status)) {
883 uint8_t eclass;
884 uint32_t ecode;
885 ntstatus_to_dos(status, &eclass, &ecode);
886 error_packet_set((char *)req->outbuf,
887 eclass, ecode, status,
888 __LINE__,__FILE__);
890 show_msg((char *)req->outbuf);
891 if (!srv_send_smb(sconn,
892 (char *)req->outbuf,
893 true, req->seqnum+1,
894 IS_CONN_ENCRYPTED(conn),
895 &req->pcd)) {
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req->outbuf);
899 return;
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send % 4) != 0) && (data_to_send != 0))
907 data_alignment_offset = 4 - (params_to_send % 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space = max_send - (smb_size
914 + 2 * 10 /* wct */
915 + alignment_offset
916 + data_alignment_offset);
918 if (useable_space < 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send || data_to_send) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime = params_to_send + data_to_send;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime = MIN(total_sent_thistime, useable_space);
939 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
940 + data_alignment_offset);
942 /* Set total params and data to be sent */
943 SSVAL(req->outbuf,smb_tprcnt,paramsize);
944 SSVAL(req->outbuf,smb_tdrcnt,datasize);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime = MIN(params_to_send,useable_space);
951 data_sent_thistime = useable_space - params_sent_thistime;
952 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
954 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req->outbuf,smb_proff,
962 ((smb_buf(req->outbuf)+alignment_offset)
963 - smb_base(req->outbuf)));
965 if(params_sent_thistime == 0)
966 SSVAL(req->outbuf,smb_prdisp,0);
967 else
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req->outbuf,smb_prdisp,pp - params);
971 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
972 if(data_sent_thistime == 0) {
973 SSVAL(req->outbuf,smb_droff,0);
974 SSVAL(req->outbuf,smb_drdisp, 0);
975 } else {
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req->outbuf, smb_droff,
979 ((smb_buf(req->outbuf)+alignment_offset)
980 - smb_base(req->outbuf))
981 + params_sent_thistime + data_alignment_offset);
982 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
985 /* Initialize the padding for alignment */
987 if (alignment_offset != 0) {
988 memset(smb_buf(req->outbuf), 0, alignment_offset);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime) {
994 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
995 params_sent_thistime);
998 /* Copy in the data bytes */
999 if(data_sent_thistime) {
1000 if (data_alignment_offset != 0) {
1001 memset((smb_buf(req->outbuf)+alignment_offset+
1002 params_sent_thistime), 0,
1003 data_alignment_offset);
1005 memcpy(smb_buf(req->outbuf)+alignment_offset
1006 +params_sent_thistime+data_alignment_offset,
1007 pd,data_sent_thistime);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime, data_sent_thistime, useable_space));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send, data_to_send, paramsize, datasize));
1015 if (overflow) {
1016 error_packet_set((char *)req->outbuf,
1017 ERRDOS,ERRbufferoverflow,
1018 STATUS_BUFFER_OVERFLOW,
1019 __LINE__,__FILE__);
1020 } else if (NT_STATUS_V(status)) {
1021 uint8_t eclass;
1022 uint32_t ecode;
1023 ntstatus_to_dos(status, &eclass, &ecode);
1024 error_packet_set((char *)req->outbuf,
1025 eclass, ecode, status,
1026 __LINE__,__FILE__);
1029 /* Send the packet */
1030 show_msg((char *)req->outbuf);
1031 if (!srv_send_smb(sconn,
1032 (char *)req->outbuf,
1033 true, req->seqnum+1,
1034 IS_CONN_ENCRYPTED(conn),
1035 &req->pcd))
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req->outbuf);
1040 pp += params_sent_thistime;
1041 pd += data_sent_thistime;
1043 params_to_send -= params_sent_thistime;
1044 data_to_send -= data_sent_thistime;
1046 /* Sanity check */
1047 if(params_to_send < 0 || data_to_send < 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send, data_to_send));
1050 return;
1054 return;
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct *conn,
1062 struct smb_request *req,
1063 char **pparams, int total_params,
1064 char **ppdata, int total_data,
1065 unsigned int max_data_bytes)
1067 struct smb_filename *smb_fname = NULL;
1068 char *params = *pparams;
1069 char *pdata = *ppdata;
1070 int deny_mode;
1071 int32 open_attr;
1072 bool oplock_request;
1073 #if 0
1074 bool return_additional_info;
1075 int16 open_sattr;
1076 time_t open_time;
1077 #endif
1078 int open_ofun;
1079 uint32 open_size;
1080 char *pname;
1081 char *fname = NULL;
1082 off_t size=0;
1083 int fattr=0,mtime=0;
1084 SMB_INO_T inode = 0;
1085 int smb_action = 0;
1086 files_struct *fsp;
1087 struct ea_list *ea_list = NULL;
1088 uint16 flags = 0;
1089 NTSTATUS status;
1090 uint32 access_mask;
1091 uint32 share_mode;
1092 uint32 create_disposition;
1093 uint32 create_options = 0;
1094 uint32_t private_flags = 0;
1095 TALLOC_CTX *ctx = talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params < 29) {
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1103 goto out;
1106 flags = SVAL(params, 0);
1107 deny_mode = SVAL(params, 2);
1108 open_attr = SVAL(params,6);
1109 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1110 if (oplock_request) {
1111 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1114 #if 0
1115 return_additional_info = BITSETW(params,0);
1116 open_sattr = SVAL(params, 4);
1117 open_time = make_unix_date3(params+8);
1118 #endif
1119 open_ofun = SVAL(params,12);
1120 open_size = IVAL(params,14);
1121 pname = &params[28];
1123 if (IS_IPC(conn)) {
1124 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1125 goto out;
1128 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1129 total_params - 28, STR_TERMINATE,
1130 &status);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 reply_nterror(req, status);
1133 goto out;
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1138 (unsigned int)open_ofun, open_size));
1140 status = filename_convert(ctx,
1141 conn,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1143 fname,
1145 NULL,
1146 &smb_fname);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req,
1150 NT_STATUS_PATH_NOT_COVERED,
1151 ERRSRV, ERRbadpath);
1152 goto out;
1154 reply_nterror(req, status);
1155 goto out;
1158 if (open_ofun == 0) {
1159 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1160 goto out;
1163 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1164 open_ofun,
1165 &access_mask, &share_mode,
1166 &create_disposition,
1167 &create_options,
1168 &private_flags)) {
1169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1170 goto out;
1173 /* Any data in this call is an EA list. */
1174 if (total_data && (total_data != 4)) {
1175 if (total_data < 10) {
1176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1177 goto out;
1180 if (IVAL(pdata,0) > total_data) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata,0), (unsigned int)total_data));
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1184 goto out;
1187 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1188 total_data - 4);
1189 if (!ea_list) {
1190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1191 goto out;
1194 if (!lp_ea_support(SNUM(conn))) {
1195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1196 goto out;
1199 if (ea_list_has_invalid_name(ea_list)) {
1200 int param_len = 30;
1201 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1202 if(*pparams == NULL ) {
1203 reply_nterror(req, NT_STATUS_NO_MEMORY);
1204 goto out;
1206 params = *pparams;
1207 memset(params, '\0', param_len);
1208 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1209 params, param_len, NULL, 0, max_data_bytes);
1210 goto out;
1214 status = SMB_VFS_CREATE_FILE(
1215 conn, /* conn */
1216 req, /* req */
1217 0, /* root_dir_fid */
1218 smb_fname, /* fname */
1219 access_mask, /* access_mask */
1220 share_mode, /* share_access */
1221 create_disposition, /* create_disposition*/
1222 create_options, /* create_options */
1223 open_attr, /* file_attributes */
1224 oplock_request, /* oplock_request */
1225 open_size, /* allocation_size */
1226 private_flags,
1227 NULL, /* sd */
1228 ea_list, /* ea_list */
1229 &fsp, /* result */
1230 &smb_action); /* psbuf */
1232 if (!NT_STATUS_IS_OK(status)) {
1233 if (open_was_deferred(req->sconn, req->mid)) {
1234 /* We have re-scheduled this call. */
1235 goto out;
1237 reply_openerror(req, status);
1238 goto out;
1241 size = get_file_size_stat(&smb_fname->st);
1242 fattr = dos_mode(conn, smb_fname);
1243 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1244 inode = smb_fname->st.st_ex_ino;
1245 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1246 close_file(req, fsp, ERROR_CLOSE);
1247 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1248 goto out;
1251 /* Realloc the size of parameters and data we will return */
1252 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1253 if(*pparams == NULL ) {
1254 reply_nterror(req, NT_STATUS_NO_MEMORY);
1255 goto out;
1257 params = *pparams;
1259 SSVAL(params,0,fsp->fnum);
1260 SSVAL(params,2,fattr);
1261 srv_put_dos_date2(params,4, mtime);
1262 SIVAL(params,8, (uint32)size);
1263 SSVAL(params,12,deny_mode);
1264 SSVAL(params,14,0); /* open_type - file or directory. */
1265 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1267 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1268 smb_action |= EXTENDED_OPLOCK_GRANTED;
1271 SSVAL(params,18,smb_action);
1274 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1276 SIVAL(params,20,inode);
1277 SSVAL(params,24,0); /* Padding. */
1278 if (flags & 8) {
1279 uint32 ea_size = estimate_ea_size(conn, fsp,
1280 smb_fname);
1281 SIVAL(params, 26, ea_size);
1282 } else {
1283 SIVAL(params, 26, 0);
1286 /* Send the required number of replies */
1287 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1288 out:
1289 TALLOC_FREE(smb_fname);
1292 /*********************************************************
1293 Routine to check if a given string matches exactly.
1294 as a special case a mask of "." does NOT match. That
1295 is required for correct wildcard semantics
1296 Case can be significant or not.
1297 **********************************************************/
1299 static bool exact_match(bool has_wild,
1300 bool case_sensitive,
1301 const char *str,
1302 const char *mask)
1304 if (mask[0] == '.' && mask[1] == 0) {
1305 return false;
1308 if (has_wild) {
1309 return false;
1312 if (case_sensitive) {
1313 return strcmp(str,mask)==0;
1314 } else {
1315 return strcasecmp_m(str,mask) == 0;
1319 /****************************************************************************
1320 Return the filetype for UNIX extensions.
1321 ****************************************************************************/
1323 static uint32 unix_filetype(mode_t mode)
1325 if(S_ISREG(mode))
1326 return UNIX_TYPE_FILE;
1327 else if(S_ISDIR(mode))
1328 return UNIX_TYPE_DIR;
1329 #ifdef S_ISLNK
1330 else if(S_ISLNK(mode))
1331 return UNIX_TYPE_SYMLINK;
1332 #endif
1333 #ifdef S_ISCHR
1334 else if(S_ISCHR(mode))
1335 return UNIX_TYPE_CHARDEV;
1336 #endif
1337 #ifdef S_ISBLK
1338 else if(S_ISBLK(mode))
1339 return UNIX_TYPE_BLKDEV;
1340 #endif
1341 #ifdef S_ISFIFO
1342 else if(S_ISFIFO(mode))
1343 return UNIX_TYPE_FIFO;
1344 #endif
1345 #ifdef S_ISSOCK
1346 else if(S_ISSOCK(mode))
1347 return UNIX_TYPE_SOCKET;
1348 #endif
1350 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1351 return UNIX_TYPE_UNKNOWN;
1354 /****************************************************************************
1355 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1356 ****************************************************************************/
1358 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1360 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1361 const SMB_STRUCT_STAT *psbuf,
1362 uint32 perms,
1363 enum perm_type ptype,
1364 mode_t *ret_perms)
1366 mode_t ret = 0;
1368 if (perms == SMB_MODE_NO_CHANGE) {
1369 if (!VALID_STAT(*psbuf)) {
1370 return NT_STATUS_INVALID_PARAMETER;
1371 } else {
1372 *ret_perms = psbuf->st_ex_mode;
1373 return NT_STATUS_OK;
1377 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1378 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1379 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1380 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1381 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1382 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1383 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1384 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1385 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1386 #ifdef S_ISVTX
1387 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1388 #endif
1389 #ifdef S_ISGID
1390 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1391 #endif
1392 #ifdef S_ISUID
1393 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1394 #endif
1396 if (ptype == PERM_NEW_FILE) {
1398 * "create mask"/"force create mode" are
1399 * only applied to new files, not existing ones.
1401 ret &= lp_create_mask(SNUM(conn));
1402 /* Add in force bits */
1403 ret |= lp_force_create_mode(SNUM(conn));
1404 } else if (ptype == PERM_NEW_DIR) {
1406 * "directory mask"/"force directory mode" are
1407 * only applied to new directories, not existing ones.
1409 ret &= lp_directory_mask(SNUM(conn));
1410 /* Add in force bits */
1411 ret |= lp_force_directory_mode(SNUM(conn));
1414 *ret_perms = ret;
1415 return NT_STATUS_OK;
1418 /****************************************************************************
1419 Needed to show the msdfs symlinks as directories. Modifies psbuf
1420 to be a directory if it's a msdfs link.
1421 ****************************************************************************/
1423 static bool check_msdfs_link(connection_struct *conn,
1424 const char *pathname,
1425 SMB_STRUCT_STAT *psbuf)
1427 int saved_errno = errno;
1428 if(lp_host_msdfs() &&
1429 lp_msdfs_root(SNUM(conn)) &&
1430 is_msdfs_link(conn, pathname, psbuf)) {
1432 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1433 "as a directory\n",
1434 pathname));
1435 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1436 errno = saved_errno;
1437 return true;
1439 errno = saved_errno;
1440 return false;
1444 /****************************************************************************
1445 Get a level dependent lanman2 dir entry.
1446 ****************************************************************************/
1448 struct smbd_dirptr_lanman2_state {
1449 connection_struct *conn;
1450 uint32_t info_level;
1451 bool check_mangled_names;
1452 bool has_wild;
1453 bool got_exact_match;
1456 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1457 void *private_data,
1458 const char *dname,
1459 const char *mask,
1460 char **_fname)
1462 struct smbd_dirptr_lanman2_state *state =
1463 (struct smbd_dirptr_lanman2_state *)private_data;
1464 bool ok;
1465 char mangled_name[13]; /* mangled 8.3 name. */
1466 bool got_match;
1467 const char *fname;
1469 /* Mangle fname if it's an illegal name. */
1470 if (mangle_must_mangle(dname, state->conn->params)) {
1471 ok = name_to_8_3(dname, mangled_name,
1472 true, state->conn->params);
1473 if (!ok) {
1474 return false;
1476 fname = mangled_name;
1477 } else {
1478 fname = dname;
1481 got_match = exact_match(state->has_wild,
1482 state->conn->case_sensitive,
1483 fname, mask);
1484 state->got_exact_match = got_match;
1485 if (!got_match) {
1486 got_match = mask_match(fname, mask,
1487 state->conn->case_sensitive);
1490 if(!got_match && state->check_mangled_names &&
1491 !mangle_is_8_3(fname, false, state->conn->params)) {
1493 * It turns out that NT matches wildcards against
1494 * both long *and* short names. This may explain some
1495 * of the wildcard wierdness from old DOS clients
1496 * that some people have been seeing.... JRA.
1498 /* Force the mangling into 8.3. */
1499 ok = name_to_8_3(fname, mangled_name,
1500 false, state->conn->params);
1501 if (!ok) {
1502 return false;
1505 got_match = exact_match(state->has_wild,
1506 state->conn->case_sensitive,
1507 mangled_name, mask);
1508 state->got_exact_match = got_match;
1509 if (!got_match) {
1510 got_match = mask_match(mangled_name, mask,
1511 state->conn->case_sensitive);
1515 if (!got_match) {
1516 return false;
1519 *_fname = talloc_strdup(ctx, fname);
1520 if (*_fname == NULL) {
1521 return false;
1524 return true;
1527 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1528 void *private_data,
1529 struct smb_filename *smb_fname,
1530 uint32_t *_mode)
1532 struct smbd_dirptr_lanman2_state *state =
1533 (struct smbd_dirptr_lanman2_state *)private_data;
1534 bool ms_dfs_link = false;
1535 uint32_t mode = 0;
1537 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1538 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1539 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1540 "Couldn't lstat [%s] (%s)\n",
1541 smb_fname_str_dbg(smb_fname),
1542 strerror(errno)));
1543 return false;
1545 } else if (!VALID_STAT(smb_fname->st) &&
1546 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1547 /* Needed to show the msdfs symlinks as
1548 * directories */
1550 ms_dfs_link = check_msdfs_link(state->conn,
1551 smb_fname->base_name,
1552 &smb_fname->st);
1553 if (!ms_dfs_link) {
1554 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1555 "Couldn't stat [%s] (%s)\n",
1556 smb_fname_str_dbg(smb_fname),
1557 strerror(errno)));
1558 return false;
1562 if (ms_dfs_link) {
1563 mode = dos_mode_msdfs(state->conn, smb_fname);
1564 } else {
1565 mode = dos_mode(state->conn, smb_fname);
1568 *_mode = mode;
1569 return true;
1572 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1573 connection_struct *conn,
1574 uint16_t flags2,
1575 uint32_t info_level,
1576 struct ea_list *name_list,
1577 bool check_mangled_names,
1578 bool requires_resume_key,
1579 uint32_t mode,
1580 const char *fname,
1581 const struct smb_filename *smb_fname,
1582 int space_remaining,
1583 uint8_t align,
1584 bool do_pad,
1585 char *base_data,
1586 char **ppdata,
1587 char *end_data,
1588 bool *out_of_space,
1589 uint64_t *last_entry_off)
1591 char *p, *q, *pdata = *ppdata;
1592 uint32_t reskey=0;
1593 uint64_t file_size = 0;
1594 uint64_t allocation_size = 0;
1595 uint64_t file_index = 0;
1596 uint32_t len;
1597 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1598 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1599 char *nameptr;
1600 char *last_entry_ptr;
1601 bool was_8_3;
1602 int off;
1603 int pad = 0;
1605 *out_of_space = false;
1607 ZERO_STRUCT(mdate_ts);
1608 ZERO_STRUCT(adate_ts);
1609 ZERO_STRUCT(create_date_ts);
1610 ZERO_STRUCT(cdate_ts);
1612 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1613 file_size = get_file_size_stat(&smb_fname->st);
1615 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1617 file_index = get_FileIndex(conn, &smb_fname->st);
1619 mdate_ts = smb_fname->st.st_ex_mtime;
1620 adate_ts = smb_fname->st.st_ex_atime;
1621 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1622 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1624 if (lp_dos_filetime_resolution(SNUM(conn))) {
1625 dos_filetime_timespec(&create_date_ts);
1626 dos_filetime_timespec(&mdate_ts);
1627 dos_filetime_timespec(&adate_ts);
1628 dos_filetime_timespec(&cdate_ts);
1631 create_date = convert_timespec_to_time_t(create_date_ts);
1632 mdate = convert_timespec_to_time_t(mdate_ts);
1633 adate = convert_timespec_to_time_t(adate_ts);
1635 /* align the record */
1636 SMB_ASSERT(align >= 1);
1638 off = (int)PTR_DIFF(pdata, base_data);
1639 pad = (off + (align-1)) & ~(align-1);
1640 pad -= off;
1642 if (pad && pad > space_remaining) {
1643 *out_of_space = true;
1644 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1645 "for padding (wanted %u, had %d)\n",
1646 (unsigned int)pad,
1647 space_remaining ));
1648 return false; /* Not finished - just out of space */
1651 off += pad;
1652 /* initialize padding to 0 */
1653 if (pad) {
1654 memset(pdata, 0, pad);
1656 space_remaining -= pad;
1658 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1659 space_remaining ));
1661 pdata += pad;
1662 p = pdata;
1663 last_entry_ptr = p;
1665 pad = 0;
1666 off = 0;
1668 switch (info_level) {
1669 case SMB_FIND_INFO_STANDARD:
1670 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1671 if(requires_resume_key) {
1672 SIVAL(p,0,reskey);
1673 p += 4;
1675 srv_put_dos_date2(p,0,create_date);
1676 srv_put_dos_date2(p,4,adate);
1677 srv_put_dos_date2(p,8,mdate);
1678 SIVAL(p,12,(uint32)file_size);
1679 SIVAL(p,16,(uint32)allocation_size);
1680 SSVAL(p,20,mode);
1681 p += 23;
1682 nameptr = p;
1683 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1684 p += ucs2_align(base_data, p, 0);
1686 len = srvstr_push(base_data, flags2, p,
1687 fname, PTR_DIFF(end_data, p),
1688 STR_TERMINATE);
1689 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1690 if (len > 2) {
1691 SCVAL(nameptr, -1, len - 2);
1692 } else {
1693 SCVAL(nameptr, -1, 0);
1695 } else {
1696 if (len > 1) {
1697 SCVAL(nameptr, -1, len - 1);
1698 } else {
1699 SCVAL(nameptr, -1, 0);
1702 p += len;
1703 break;
1705 case SMB_FIND_EA_SIZE:
1706 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1707 if (requires_resume_key) {
1708 SIVAL(p,0,reskey);
1709 p += 4;
1711 srv_put_dos_date2(p,0,create_date);
1712 srv_put_dos_date2(p,4,adate);
1713 srv_put_dos_date2(p,8,mdate);
1714 SIVAL(p,12,(uint32)file_size);
1715 SIVAL(p,16,(uint32)allocation_size);
1716 SSVAL(p,20,mode);
1718 unsigned int ea_size = estimate_ea_size(conn, NULL,
1719 smb_fname);
1720 SIVAL(p,22,ea_size); /* Extended attributes */
1722 p += 27;
1723 nameptr = p - 1;
1724 len = srvstr_push(base_data, flags2,
1725 p, fname, PTR_DIFF(end_data, p),
1726 STR_TERMINATE | STR_NOALIGN);
1727 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1728 if (len > 2) {
1729 len -= 2;
1730 } else {
1731 len = 0;
1733 } else {
1734 if (len > 1) {
1735 len -= 1;
1736 } else {
1737 len = 0;
1740 SCVAL(nameptr,0,len);
1741 p += len;
1742 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1743 break;
1745 case SMB_FIND_EA_LIST:
1747 struct ea_list *file_list = NULL;
1748 size_t ea_len = 0;
1749 NTSTATUS status;
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1752 if (!name_list) {
1753 return false;
1755 if (requires_resume_key) {
1756 SIVAL(p,0,reskey);
1757 p += 4;
1759 srv_put_dos_date2(p,0,create_date);
1760 srv_put_dos_date2(p,4,adate);
1761 srv_put_dos_date2(p,8,mdate);
1762 SIVAL(p,12,(uint32)file_size);
1763 SIVAL(p,16,(uint32)allocation_size);
1764 SSVAL(p,20,mode);
1765 p += 22; /* p now points to the EA area. */
1767 status = get_ea_list_from_file(ctx, conn, NULL,
1768 smb_fname,
1769 &ea_len, &file_list);
1770 if (!NT_STATUS_IS_OK(status)) {
1771 file_list = NULL;
1773 name_list = ea_list_union(name_list, file_list, &ea_len);
1775 /* We need to determine if this entry will fit in the space available. */
1776 /* Max string size is 255 bytes. */
1777 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1778 *out_of_space = true;
1779 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1780 "(wanted %u, had %d)\n",
1781 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1782 space_remaining ));
1783 return False; /* Not finished - just out of space */
1786 /* Push the ea_data followed by the name. */
1787 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1788 nameptr = p;
1789 len = srvstr_push(base_data, flags2,
1790 p + 1, fname, PTR_DIFF(end_data, p+1),
1791 STR_TERMINATE | STR_NOALIGN);
1792 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1793 if (len > 2) {
1794 len -= 2;
1795 } else {
1796 len = 0;
1798 } else {
1799 if (len > 1) {
1800 len -= 1;
1801 } else {
1802 len = 0;
1805 SCVAL(nameptr,0,len);
1806 p += len + 1;
1807 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1808 break;
1811 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1812 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1813 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1814 p += 4;
1815 SIVAL(p,0,reskey); p += 4;
1816 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1819 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1820 SOFF_T(p,0,file_size); p += 8;
1821 SOFF_T(p,0,allocation_size); p += 8;
1822 SIVAL(p,0,mode); p += 4;
1823 q = p; p += 4; /* q is placeholder for name length. */
1824 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1825 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1826 } else {
1827 unsigned int ea_size = estimate_ea_size(conn, NULL,
1828 smb_fname);
1829 SIVAL(p,0,ea_size); /* Extended attributes */
1831 p += 4;
1832 /* Clear the short name buffer. This is
1833 * IMPORTANT as not doing so will trigger
1834 * a Win2k client bug. JRA.
1836 if (!was_8_3 && check_mangled_names) {
1837 char mangled_name[13]; /* mangled 8.3 name. */
1838 if (!name_to_8_3(fname,mangled_name,True,
1839 conn->params)) {
1840 /* Error - mangle failed ! */
1841 memset(mangled_name,'\0',12);
1843 mangled_name[12] = 0;
1844 len = srvstr_push(base_data, flags2,
1845 p+2, mangled_name, 24,
1846 STR_UPPER|STR_UNICODE);
1847 if (len < 24) {
1848 memset(p + 2 + len,'\0',24 - len);
1850 SSVAL(p, 0, len);
1851 } else {
1852 memset(p,'\0',26);
1854 p += 2 + 24;
1855 len = srvstr_push(base_data, flags2, p,
1856 fname, PTR_DIFF(end_data, p),
1857 STR_TERMINATE_ASCII);
1858 SIVAL(q,0,len);
1859 p += len;
1861 len = PTR_DIFF(p, pdata);
1862 pad = (len + (align-1)) & ~(align-1);
1864 * offset to the next entry, the caller
1865 * will overwrite it for the last entry
1866 * that's why we always include the padding
1868 SIVAL(pdata,0,pad);
1870 * set padding to zero
1872 if (do_pad) {
1873 memset(p, 0, pad - len);
1874 p = pdata + pad;
1875 } else {
1876 p = pdata + len;
1878 break;
1880 case SMB_FIND_FILE_DIRECTORY_INFO:
1881 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1882 p += 4;
1883 SIVAL(p,0,reskey); p += 4;
1884 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1888 SOFF_T(p,0,file_size); p += 8;
1889 SOFF_T(p,0,allocation_size); p += 8;
1890 SIVAL(p,0,mode); p += 4;
1891 len = srvstr_push(base_data, flags2,
1892 p + 4, fname, PTR_DIFF(end_data, p+4),
1893 STR_TERMINATE_ASCII);
1894 SIVAL(p,0,len);
1895 p += 4 + len;
1897 len = PTR_DIFF(p, pdata);
1898 pad = (len + (align-1)) & ~(align-1);
1900 * offset to the next entry, the caller
1901 * will overwrite it for the last entry
1902 * that's why we always include the padding
1904 SIVAL(pdata,0,pad);
1906 * set padding to zero
1908 if (do_pad) {
1909 memset(p, 0, pad - len);
1910 p = pdata + pad;
1911 } else {
1912 p = pdata + len;
1914 break;
1916 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1917 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1918 p += 4;
1919 SIVAL(p,0,reskey); p += 4;
1920 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1923 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1924 SOFF_T(p,0,file_size); p += 8;
1925 SOFF_T(p,0,allocation_size); p += 8;
1926 SIVAL(p,0,mode); p += 4;
1927 q = p; p += 4; /* q is placeholder for name length. */
1929 unsigned int ea_size = estimate_ea_size(conn, NULL,
1930 smb_fname);
1931 SIVAL(p,0,ea_size); /* Extended attributes */
1932 p +=4;
1934 len = srvstr_push(base_data, flags2, p,
1935 fname, PTR_DIFF(end_data, p),
1936 STR_TERMINATE_ASCII);
1937 SIVAL(q, 0, len);
1938 p += len;
1940 len = PTR_DIFF(p, pdata);
1941 pad = (len + (align-1)) & ~(align-1);
1943 * offset to the next entry, the caller
1944 * will overwrite it for the last entry
1945 * that's why we always include the padding
1947 SIVAL(pdata,0,pad);
1949 * set padding to zero
1951 if (do_pad) {
1952 memset(p, 0, pad - len);
1953 p = pdata + pad;
1954 } else {
1955 p = pdata + len;
1957 break;
1959 case SMB_FIND_FILE_NAMES_INFO:
1960 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1961 p += 4;
1962 SIVAL(p,0,reskey); p += 4;
1963 p += 4;
1964 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1965 acl on a dir (tridge) */
1966 len = srvstr_push(base_data, flags2, p,
1967 fname, PTR_DIFF(end_data, p),
1968 STR_TERMINATE_ASCII);
1969 SIVAL(p, -4, len);
1970 p += len;
1972 len = PTR_DIFF(p, pdata);
1973 pad = (len + (align-1)) & ~(align-1);
1975 * offset to the next entry, the caller
1976 * will overwrite it for the last entry
1977 * that's why we always include the padding
1979 SIVAL(pdata,0,pad);
1981 * set padding to zero
1983 if (do_pad) {
1984 memset(p, 0, pad - len);
1985 p = pdata + pad;
1986 } else {
1987 p = pdata + len;
1989 break;
1991 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1992 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1993 p += 4;
1994 SIVAL(p,0,reskey); p += 4;
1995 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1998 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1999 SOFF_T(p,0,file_size); p += 8;
2000 SOFF_T(p,0,allocation_size); p += 8;
2001 SIVAL(p,0,mode); p += 4;
2002 q = p; p += 4; /* q is placeholder for name length. */
2003 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2004 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2005 } else {
2006 unsigned int ea_size = estimate_ea_size(conn, NULL,
2007 smb_fname);
2008 SIVAL(p,0,ea_size); /* Extended attributes */
2010 p += 4;
2011 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2012 SBVAL(p,0,file_index); p += 8;
2013 len = srvstr_push(base_data, flags2, p,
2014 fname, PTR_DIFF(end_data, p),
2015 STR_TERMINATE_ASCII);
2016 SIVAL(q, 0, len);
2017 p += len;
2019 len = PTR_DIFF(p, pdata);
2020 pad = (len + (align-1)) & ~(align-1);
2022 * offset to the next entry, the caller
2023 * will overwrite it for the last entry
2024 * that's why we always include the padding
2026 SIVAL(pdata,0,pad);
2028 * set padding to zero
2030 if (do_pad) {
2031 memset(p, 0, pad - len);
2032 p = pdata + pad;
2033 } else {
2034 p = pdata + len;
2036 break;
2038 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2039 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2040 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2041 p += 4;
2042 SIVAL(p,0,reskey); p += 4;
2043 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2046 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2047 SOFF_T(p,0,file_size); p += 8;
2048 SOFF_T(p,0,allocation_size); p += 8;
2049 SIVAL(p,0,mode); p += 4;
2050 q = p; p += 4; /* q is placeholder for name length */
2051 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2052 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2053 } else {
2054 unsigned int ea_size = estimate_ea_size(conn, NULL,
2055 smb_fname);
2056 SIVAL(p,0,ea_size); /* Extended attributes */
2058 p += 4;
2059 /* Clear the short name buffer. This is
2060 * IMPORTANT as not doing so will trigger
2061 * a Win2k client bug. JRA.
2063 if (!was_8_3 && check_mangled_names) {
2064 char mangled_name[13]; /* mangled 8.3 name. */
2065 if (!name_to_8_3(fname,mangled_name,True,
2066 conn->params)) {
2067 /* Error - mangle failed ! */
2068 memset(mangled_name,'\0',12);
2070 mangled_name[12] = 0;
2071 len = srvstr_push(base_data, flags2,
2072 p+2, mangled_name, 24,
2073 STR_UPPER|STR_UNICODE);
2074 SSVAL(p, 0, len);
2075 if (len < 24) {
2076 memset(p + 2 + len,'\0',24 - len);
2078 SSVAL(p, 0, len);
2079 } else {
2080 memset(p,'\0',26);
2082 p += 26;
2083 SSVAL(p,0,0); p += 2; /* Reserved ? */
2084 SBVAL(p,0,file_index); p += 8;
2085 len = srvstr_push(base_data, flags2, p,
2086 fname, PTR_DIFF(end_data, p),
2087 STR_TERMINATE_ASCII);
2088 SIVAL(q,0,len);
2089 p += len;
2091 len = PTR_DIFF(p, pdata);
2092 pad = (len + (align-1)) & ~(align-1);
2094 * offset to the next entry, the caller
2095 * will overwrite it for the last entry
2096 * that's why we always include the padding
2098 SIVAL(pdata,0,pad);
2100 * set padding to zero
2102 if (do_pad) {
2103 memset(p, 0, pad - len);
2104 p = pdata + pad;
2105 } else {
2106 p = pdata + len;
2108 break;
2110 /* CIFS UNIX Extension. */
2112 case SMB_FIND_FILE_UNIX:
2113 case SMB_FIND_FILE_UNIX_INFO2:
2114 p+= 4;
2115 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2117 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2119 if (info_level == SMB_FIND_FILE_UNIX) {
2120 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2121 p = store_file_unix_basic(conn, p,
2122 NULL, &smb_fname->st);
2123 len = srvstr_push(base_data, flags2, p,
2124 fname, PTR_DIFF(end_data, p),
2125 STR_TERMINATE);
2126 } else {
2127 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2128 p = store_file_unix_basic_info2(conn, p,
2129 NULL, &smb_fname->st);
2130 nameptr = p;
2131 p += 4;
2132 len = srvstr_push(base_data, flags2, p, fname,
2133 PTR_DIFF(end_data, p), 0);
2134 SIVAL(nameptr, 0, len);
2137 p += len;
2139 len = PTR_DIFF(p, pdata);
2140 pad = (len + (align-1)) & ~(align-1);
2142 * offset to the next entry, the caller
2143 * will overwrite it for the last entry
2144 * that's why we always include the padding
2146 SIVAL(pdata,0,pad);
2148 * set padding to zero
2150 if (do_pad) {
2151 memset(p, 0, pad - len);
2152 p = pdata + pad;
2153 } else {
2154 p = pdata + len;
2156 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2158 break;
2160 default:
2161 return false;
2164 if (PTR_DIFF(p,pdata) > space_remaining) {
2165 *out_of_space = true;
2166 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2167 "(wanted %u, had %d)\n",
2168 (unsigned int)PTR_DIFF(p,pdata),
2169 space_remaining ));
2170 return false; /* Not finished - just out of space */
2173 /* Setup the last entry pointer, as an offset from base_data */
2174 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2175 /* Advance the data pointer to the next slot */
2176 *ppdata = p;
2178 return true;
2181 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2182 connection_struct *conn,
2183 struct dptr_struct *dirptr,
2184 uint16 flags2,
2185 const char *path_mask,
2186 uint32 dirtype,
2187 int info_level,
2188 int requires_resume_key,
2189 bool dont_descend,
2190 bool ask_sharemode,
2191 uint8_t align,
2192 bool do_pad,
2193 char **ppdata,
2194 char *base_data,
2195 char *end_data,
2196 int space_remaining,
2197 bool *out_of_space,
2198 bool *got_exact_match,
2199 int *_last_entry_off,
2200 struct ea_list *name_list)
2202 const char *p;
2203 const char *mask = NULL;
2204 long prev_dirpos = 0;
2205 uint32_t mode = 0;
2206 char *fname = NULL;
2207 struct smb_filename *smb_fname = NULL;
2208 struct smbd_dirptr_lanman2_state state;
2209 bool ok;
2210 uint64_t last_entry_off = 0;
2212 ZERO_STRUCT(state);
2213 state.conn = conn;
2214 state.info_level = info_level;
2215 state.check_mangled_names = lp_mangled_names(conn->params);
2216 state.has_wild = dptr_has_wild(dirptr);
2217 state.got_exact_match = false;
2219 *out_of_space = false;
2220 *got_exact_match = false;
2222 p = strrchr_m(path_mask,'/');
2223 if(p != NULL) {
2224 if(p[1] == '\0') {
2225 mask = "*.*";
2226 } else {
2227 mask = p+1;
2229 } else {
2230 mask = path_mask;
2233 ok = smbd_dirptr_get_entry(ctx,
2234 dirptr,
2235 mask,
2236 dirtype,
2237 dont_descend,
2238 ask_sharemode,
2239 smbd_dirptr_lanman2_match_fn,
2240 smbd_dirptr_lanman2_mode_fn,
2241 &state,
2242 &fname,
2243 &smb_fname,
2244 &mode,
2245 &prev_dirpos);
2246 if (!ok) {
2247 return false;
2250 *got_exact_match = state.got_exact_match;
2252 ok = smbd_marshall_dir_entry(ctx,
2253 conn,
2254 flags2,
2255 info_level,
2256 name_list,
2257 state.check_mangled_names,
2258 requires_resume_key,
2259 mode,
2260 fname,
2261 smb_fname,
2262 space_remaining,
2263 align,
2264 do_pad,
2265 base_data,
2266 ppdata,
2267 end_data,
2268 out_of_space,
2269 &last_entry_off);
2270 TALLOC_FREE(fname);
2271 TALLOC_FREE(smb_fname);
2272 if (*out_of_space) {
2273 dptr_SeekDir(dirptr, prev_dirpos);
2274 return false;
2276 if (!ok) {
2277 return false;
2280 *_last_entry_off = last_entry_off;
2281 return true;
2284 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2285 connection_struct *conn,
2286 struct dptr_struct *dirptr,
2287 uint16 flags2,
2288 const char *path_mask,
2289 uint32 dirtype,
2290 int info_level,
2291 bool requires_resume_key,
2292 bool dont_descend,
2293 bool ask_sharemode,
2294 char **ppdata,
2295 char *base_data,
2296 char *end_data,
2297 int space_remaining,
2298 bool *out_of_space,
2299 bool *got_exact_match,
2300 int *last_entry_off,
2301 struct ea_list *name_list)
2303 uint8_t align = 4;
2304 const bool do_pad = true;
2306 if (info_level >= 1 && info_level <= 3) {
2307 /* No alignment on earlier info levels. */
2308 align = 1;
2311 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2312 path_mask, dirtype, info_level,
2313 requires_resume_key, dont_descend, ask_sharemode,
2314 align, do_pad,
2315 ppdata, base_data, end_data,
2316 space_remaining,
2317 out_of_space, got_exact_match,
2318 last_entry_off, name_list);
2321 /****************************************************************************
2322 Reply to a TRANS2_FINDFIRST.
2323 ****************************************************************************/
2325 static void call_trans2findfirst(connection_struct *conn,
2326 struct smb_request *req,
2327 char **pparams, int total_params,
2328 char **ppdata, int total_data,
2329 unsigned int max_data_bytes)
2331 /* We must be careful here that we don't return more than the
2332 allowed number of data bytes. If this means returning fewer than
2333 maxentries then so be it. We assume that the redirector has
2334 enough room for the fixed number of parameter bytes it has
2335 requested. */
2336 struct smb_filename *smb_dname = NULL;
2337 char *params = *pparams;
2338 char *pdata = *ppdata;
2339 char *data_end;
2340 uint32 dirtype;
2341 int maxentries;
2342 uint16 findfirst_flags;
2343 bool close_after_first;
2344 bool close_if_end;
2345 bool requires_resume_key;
2346 int info_level;
2347 char *directory = NULL;
2348 char *mask = NULL;
2349 char *p;
2350 int last_entry_off=0;
2351 int dptr_num = -1;
2352 int numentries = 0;
2353 int i;
2354 bool finished = False;
2355 bool dont_descend = False;
2356 bool out_of_space = False;
2357 int space_remaining;
2358 bool mask_contains_wcard = False;
2359 struct ea_list *ea_list = NULL;
2360 NTSTATUS ntstatus = NT_STATUS_OK;
2361 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2362 TALLOC_CTX *ctx = talloc_tos();
2363 struct dptr_struct *dirptr = NULL;
2364 struct smbd_server_connection *sconn = req->sconn;
2365 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2366 bool backup_priv = false;
2368 if (total_params < 13) {
2369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2370 goto out;
2373 dirtype = SVAL(params,0);
2374 maxentries = SVAL(params,2);
2375 findfirst_flags = SVAL(params,4);
2376 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2377 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2378 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2379 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2380 security_token_has_privilege(get_current_nttok(conn),
2381 SEC_PRIV_BACKUP));
2383 info_level = SVAL(params,6);
2385 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2386 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2387 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2388 (int)backup_priv,
2389 info_level, max_data_bytes));
2391 if (!maxentries) {
2392 /* W2K3 seems to treat zero as 1. */
2393 maxentries = 1;
2396 switch (info_level) {
2397 case SMB_FIND_INFO_STANDARD:
2398 case SMB_FIND_EA_SIZE:
2399 case SMB_FIND_EA_LIST:
2400 case SMB_FIND_FILE_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2402 case SMB_FIND_FILE_NAMES_INFO:
2403 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2404 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2405 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2406 break;
2407 case SMB_FIND_FILE_UNIX:
2408 case SMB_FIND_FILE_UNIX_INFO2:
2409 /* Always use filesystem for UNIX mtime query. */
2410 ask_sharemode = false;
2411 if (!lp_unix_extensions()) {
2412 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2413 goto out;
2415 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2416 break;
2417 default:
2418 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2419 goto out;
2422 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2423 params+12, total_params - 12,
2424 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2425 if (!NT_STATUS_IS_OK(ntstatus)) {
2426 reply_nterror(req, ntstatus);
2427 goto out;
2430 if (backup_priv) {
2431 become_root();
2432 ntstatus = filename_convert_with_privilege(ctx,
2433 conn,
2434 req,
2435 directory,
2436 ucf_flags,
2437 &mask_contains_wcard,
2438 &smb_dname);
2439 } else {
2440 ntstatus = filename_convert(ctx, conn,
2441 req->flags2 & FLAGS2_DFS_PATHNAMES,
2442 directory,
2443 ucf_flags,
2444 &mask_contains_wcard,
2445 &smb_dname);
2448 if (!NT_STATUS_IS_OK(ntstatus)) {
2449 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2450 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2451 ERRSRV, ERRbadpath);
2452 goto out;
2454 reply_nterror(req, ntstatus);
2455 goto out;
2458 mask = smb_dname->original_lcomp;
2460 directory = smb_dname->base_name;
2462 p = strrchr_m(directory,'/');
2463 if(p == NULL) {
2464 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2465 if((directory[0] == '.') && (directory[1] == '\0')) {
2466 mask = talloc_strdup(ctx,"*");
2467 if (!mask) {
2468 reply_nterror(req, NT_STATUS_NO_MEMORY);
2469 goto out;
2471 mask_contains_wcard = True;
2473 } else {
2474 *p = 0;
2477 if (p == NULL || p == directory) {
2478 /* Ensure we don't have a directory name of "". */
2479 directory = talloc_strdup(talloc_tos(), ".");
2480 if (!directory) {
2481 reply_nterror(req, NT_STATUS_NO_MEMORY);
2482 goto out;
2486 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2488 if (info_level == SMB_FIND_EA_LIST) {
2489 uint32 ea_size;
2491 if (total_data < 4) {
2492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2493 goto out;
2496 ea_size = IVAL(pdata,0);
2497 if (ea_size != total_data) {
2498 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2499 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2501 goto out;
2504 if (!lp_ea_support(SNUM(conn))) {
2505 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2506 goto out;
2509 /* Pull out the list of names. */
2510 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2511 if (!ea_list) {
2512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2513 goto out;
2517 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2519 goto out;
2522 *ppdata = (char *)SMB_REALLOC(
2523 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2524 if(*ppdata == NULL ) {
2525 reply_nterror(req, NT_STATUS_NO_MEMORY);
2526 goto out;
2528 pdata = *ppdata;
2529 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2531 /* Realloc the params space */
2532 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2533 if (*pparams == NULL) {
2534 reply_nterror(req, NT_STATUS_NO_MEMORY);
2535 goto out;
2537 params = *pparams;
2539 /* Save the wildcard match and attribs we are using on this directory -
2540 needed as lanman2 assumes these are being saved between calls */
2542 ntstatus = dptr_create(conn,
2543 req,
2544 NULL, /* fsp */
2545 directory,
2546 False,
2547 True,
2548 req->smbpid,
2549 mask,
2550 mask_contains_wcard,
2551 dirtype,
2552 &dirptr);
2554 if (!NT_STATUS_IS_OK(ntstatus)) {
2555 reply_nterror(req, ntstatus);
2556 goto out;
2559 if (backup_priv) {
2560 /* Remember this in case we have
2561 to do a findnext. */
2562 dptr_set_priv(dirptr);
2565 dptr_num = dptr_dnum(dirptr);
2566 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2568 /* Initialize per TRANS2_FIND_FIRST operation data */
2569 dptr_init_search_op(dirptr);
2571 /* We don't need to check for VOL here as this is returned by
2572 a different TRANS2 call. */
2574 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2575 directory,lp_dont_descend(ctx, SNUM(conn))));
2576 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2577 dont_descend = True;
2579 p = pdata;
2580 space_remaining = max_data_bytes;
2581 out_of_space = False;
2583 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2584 bool got_exact_match = False;
2586 /* this is a heuristic to avoid seeking the dirptr except when
2587 absolutely necessary. It allows for a filename of about 40 chars */
2588 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2589 out_of_space = True;
2590 finished = False;
2591 } else {
2592 finished = !get_lanman2_dir_entry(ctx,
2593 conn,
2594 dirptr,
2595 req->flags2,
2596 mask,dirtype,info_level,
2597 requires_resume_key,dont_descend,
2598 ask_sharemode,
2599 &p,pdata,data_end,
2600 space_remaining, &out_of_space,
2601 &got_exact_match,
2602 &last_entry_off, ea_list);
2605 if (finished && out_of_space)
2606 finished = False;
2608 if (!finished && !out_of_space)
2609 numentries++;
2612 * As an optimisation if we know we aren't looking
2613 * for a wildcard name (ie. the name matches the wildcard exactly)
2614 * then we can finish on any (first) match.
2615 * This speeds up large directory searches. JRA.
2618 if(got_exact_match)
2619 finished = True;
2621 /* Ensure space_remaining never goes -ve. */
2622 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2623 space_remaining = 0;
2624 out_of_space = true;
2625 } else {
2626 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2630 /* Check if we can close the dirptr */
2631 if(close_after_first || (finished && close_if_end)) {
2632 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2633 dptr_close(sconn, &dptr_num);
2637 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2638 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2639 * the protocol level is less than NT1. Tested with smbclient. JRA.
2640 * This should fix the OS/2 client bug #2335.
2643 if(numentries == 0) {
2644 dptr_close(sconn, &dptr_num);
2645 if (get_Protocol() < PROTOCOL_NT1) {
2646 reply_force_doserror(req, ERRDOS, ERRnofiles);
2647 goto out;
2648 } else {
2649 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2650 ERRDOS, ERRbadfile);
2651 goto out;
2655 /* At this point pdata points to numentries directory entries. */
2657 /* Set up the return parameter block */
2658 SSVAL(params,0,dptr_num);
2659 SSVAL(params,2,numentries);
2660 SSVAL(params,4,finished);
2661 SSVAL(params,6,0); /* Never an EA error */
2662 SSVAL(params,8,last_entry_off);
2664 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2665 max_data_bytes);
2667 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2668 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2669 if (!directory) {
2670 reply_nterror(req, NT_STATUS_NO_MEMORY);
2674 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2675 smb_fn_name(req->cmd),
2676 mask, directory, dirtype, numentries ) );
2679 * Force a name mangle here to ensure that the
2680 * mask as an 8.3 name is top of the mangled cache.
2681 * The reasons for this are subtle. Don't remove
2682 * this code unless you know what you are doing
2683 * (see PR#13758). JRA.
2686 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2687 char mangled_name[13];
2688 name_to_8_3(mask, mangled_name, True, conn->params);
2690 out:
2692 if (backup_priv) {
2693 unbecome_root();
2696 TALLOC_FREE(smb_dname);
2697 return;
2700 /****************************************************************************
2701 Reply to a TRANS2_FINDNEXT.
2702 ****************************************************************************/
2704 static void call_trans2findnext(connection_struct *conn,
2705 struct smb_request *req,
2706 char **pparams, int total_params,
2707 char **ppdata, int total_data,
2708 unsigned int max_data_bytes)
2710 /* We must be careful here that we don't return more than the
2711 allowed number of data bytes. If this means returning fewer than
2712 maxentries then so be it. We assume that the redirector has
2713 enough room for the fixed number of parameter bytes it has
2714 requested. */
2715 char *params = *pparams;
2716 char *pdata = *ppdata;
2717 char *data_end;
2718 int dptr_num;
2719 int maxentries;
2720 uint16 info_level;
2721 uint32 resume_key;
2722 uint16 findnext_flags;
2723 bool close_after_request;
2724 bool close_if_end;
2725 bool requires_resume_key;
2726 bool continue_bit;
2727 bool mask_contains_wcard = False;
2728 char *resume_name = NULL;
2729 const char *mask = NULL;
2730 const char *directory = NULL;
2731 char *p = NULL;
2732 uint16 dirtype;
2733 int numentries = 0;
2734 int i, last_entry_off=0;
2735 bool finished = False;
2736 bool dont_descend = False;
2737 bool out_of_space = False;
2738 int space_remaining;
2739 struct ea_list *ea_list = NULL;
2740 NTSTATUS ntstatus = NT_STATUS_OK;
2741 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2742 TALLOC_CTX *ctx = talloc_tos();
2743 struct dptr_struct *dirptr;
2744 struct smbd_server_connection *sconn = req->sconn;
2745 bool backup_priv = false;
2747 if (total_params < 13) {
2748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2749 return;
2752 dptr_num = SVAL(params,0);
2753 maxentries = SVAL(params,2);
2754 info_level = SVAL(params,4);
2755 resume_key = IVAL(params,6);
2756 findnext_flags = SVAL(params,10);
2757 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2758 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2759 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2760 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2762 if (!continue_bit) {
2763 /* We only need resume_name if continue_bit is zero. */
2764 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2765 params+12,
2766 total_params - 12, STR_TERMINATE, &ntstatus,
2767 &mask_contains_wcard);
2768 if (!NT_STATUS_IS_OK(ntstatus)) {
2769 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2770 complain (it thinks we're asking for the directory above the shared
2771 path or an invalid name). Catch this as the resume name is only compared, never used in
2772 a file access. JRA. */
2773 srvstr_pull_talloc(ctx, params, req->flags2,
2774 &resume_name, params+12,
2775 total_params - 12,
2776 STR_TERMINATE);
2778 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2779 reply_nterror(req, ntstatus);
2780 return;
2785 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2786 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2787 resume_key = %d resume name = %s continue=%d level = %d\n",
2788 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2789 requires_resume_key, resume_key,
2790 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2792 if (!maxentries) {
2793 /* W2K3 seems to treat zero as 1. */
2794 maxentries = 1;
2797 switch (info_level) {
2798 case SMB_FIND_INFO_STANDARD:
2799 case SMB_FIND_EA_SIZE:
2800 case SMB_FIND_EA_LIST:
2801 case SMB_FIND_FILE_DIRECTORY_INFO:
2802 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2803 case SMB_FIND_FILE_NAMES_INFO:
2804 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2805 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2806 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2807 break;
2808 case SMB_FIND_FILE_UNIX:
2809 case SMB_FIND_FILE_UNIX_INFO2:
2810 /* Always use filesystem for UNIX mtime query. */
2811 ask_sharemode = false;
2812 if (!lp_unix_extensions()) {
2813 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2814 return;
2816 break;
2817 default:
2818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2819 return;
2822 if (info_level == SMB_FIND_EA_LIST) {
2823 uint32 ea_size;
2825 if (total_data < 4) {
2826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 return;
2830 ea_size = IVAL(pdata,0);
2831 if (ea_size != total_data) {
2832 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2833 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2835 return;
2838 if (!lp_ea_support(SNUM(conn))) {
2839 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2840 return;
2843 /* Pull out the list of names. */
2844 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2845 if (!ea_list) {
2846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2847 return;
2851 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2853 return;
2856 *ppdata = (char *)SMB_REALLOC(
2857 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2858 if(*ppdata == NULL) {
2859 reply_nterror(req, NT_STATUS_NO_MEMORY);
2860 return;
2863 pdata = *ppdata;
2864 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2866 /* Realloc the params space */
2867 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2868 if(*pparams == NULL ) {
2869 reply_nterror(req, NT_STATUS_NO_MEMORY);
2870 return;
2873 params = *pparams;
2875 /* Check that the dptr is valid */
2876 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2877 reply_nterror(req, STATUS_NO_MORE_FILES);
2878 return;
2881 directory = dptr_path(sconn, dptr_num);
2883 /* Get the wildcard mask from the dptr */
2884 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2885 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2886 reply_nterror(req, STATUS_NO_MORE_FILES);
2887 return;
2890 /* Get the attr mask from the dptr */
2891 dirtype = dptr_attr(sconn, dptr_num);
2893 backup_priv = dptr_get_priv(dirptr);
2895 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2896 "backup_priv = %d\n",
2897 dptr_num, mask, dirtype,
2898 (long)dirptr,
2899 dptr_TellDir(dirptr),
2900 (int)backup_priv));
2902 /* Initialize per TRANS2_FIND_NEXT operation data */
2903 dptr_init_search_op(dirptr);
2905 /* We don't need to check for VOL here as this is returned by
2906 a different TRANS2 call. */
2908 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2909 directory,lp_dont_descend(ctx, SNUM(conn))));
2910 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2911 dont_descend = True;
2913 p = pdata;
2914 space_remaining = max_data_bytes;
2915 out_of_space = False;
2917 if (backup_priv) {
2918 become_root();
2922 * Seek to the correct position. We no longer use the resume key but
2923 * depend on the last file name instead.
2926 if(!continue_bit && resume_name && *resume_name) {
2927 SMB_STRUCT_STAT st;
2929 long current_pos = 0;
2931 * Remember, name_to_8_3 is called by
2932 * get_lanman2_dir_entry(), so the resume name
2933 * could be mangled. Ensure we check the unmangled name.
2936 if (mangle_is_mangled(resume_name, conn->params)) {
2937 char *new_resume_name = NULL;
2938 mangle_lookup_name_from_8_3(ctx,
2939 resume_name,
2940 &new_resume_name,
2941 conn->params);
2942 if (new_resume_name) {
2943 resume_name = new_resume_name;
2948 * Fix for NT redirector problem triggered by resume key indexes
2949 * changing between directory scans. We now return a resume key of 0
2950 * and instead look for the filename to continue from (also given
2951 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2952 * findfirst/findnext (as is usual) then the directory pointer
2953 * should already be at the correct place.
2956 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2957 } /* end if resume_name && !continue_bit */
2959 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2960 bool got_exact_match = False;
2962 /* this is a heuristic to avoid seeking the dirptr except when
2963 absolutely necessary. It allows for a filename of about 40 chars */
2964 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2965 out_of_space = True;
2966 finished = False;
2967 } else {
2968 finished = !get_lanman2_dir_entry(ctx,
2969 conn,
2970 dirptr,
2971 req->flags2,
2972 mask,dirtype,info_level,
2973 requires_resume_key,dont_descend,
2974 ask_sharemode,
2975 &p,pdata,data_end,
2976 space_remaining, &out_of_space,
2977 &got_exact_match,
2978 &last_entry_off, ea_list);
2981 if (finished && out_of_space)
2982 finished = False;
2984 if (!finished && !out_of_space)
2985 numentries++;
2988 * As an optimisation if we know we aren't looking
2989 * for a wildcard name (ie. the name matches the wildcard exactly)
2990 * then we can finish on any (first) match.
2991 * This speeds up large directory searches. JRA.
2994 if(got_exact_match)
2995 finished = True;
2997 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3000 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3001 smb_fn_name(req->cmd),
3002 mask, directory, dirtype, numentries ) );
3004 /* Check if we can close the dirptr */
3005 if(close_after_request || (finished && close_if_end)) {
3006 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3007 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3010 if (backup_priv) {
3011 unbecome_root();
3014 /* Set up the return parameter block */
3015 SSVAL(params,0,numentries);
3016 SSVAL(params,2,finished);
3017 SSVAL(params,4,0); /* Never an EA error */
3018 SSVAL(params,6,last_entry_off);
3020 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3021 max_data_bytes);
3023 return;
3026 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3028 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3029 return objid;
3032 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3034 SMB_ASSERT(extended_info != NULL);
3036 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3037 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3038 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3039 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3040 #ifdef SAMBA_VERSION_REVISION
3041 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3042 #endif
3043 extended_info->samba_subversion = 0;
3044 #ifdef SAMBA_VERSION_RC_RELEASE
3045 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3046 #else
3047 #ifdef SAMBA_VERSION_PRE_RELEASE
3048 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3049 #endif
3050 #endif
3051 #ifdef SAMBA_VERSION_VENDOR_PATCH
3052 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3053 #endif
3054 extended_info->samba_gitcommitdate = 0;
3055 #ifdef SAMBA_VERSION_COMMIT_TIME
3056 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3057 #endif
3059 memset(extended_info->samba_version_string, 0,
3060 sizeof(extended_info->samba_version_string));
3062 snprintf (extended_info->samba_version_string,
3063 sizeof(extended_info->samba_version_string),
3064 "%s", samba_version_string());
3067 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3068 connection_struct *conn,
3069 TALLOC_CTX *mem_ctx,
3070 uint16_t info_level,
3071 uint16_t flags2,
3072 unsigned int max_data_bytes,
3073 size_t *fixed_portion,
3074 struct smb_filename *fname,
3075 char **ppdata,
3076 int *ret_data_len)
3078 char *pdata, *end_data;
3079 int data_len = 0, len;
3080 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3081 int snum = SNUM(conn);
3082 const char *fstype = lp_fstype(SNUM(conn));
3083 const char *filename = NULL;
3084 uint32 additional_flags = 0;
3085 struct smb_filename smb_fname;
3086 SMB_STRUCT_STAT st;
3087 NTSTATUS status = NT_STATUS_OK;
3089 if (fname == NULL || fname->base_name == NULL) {
3090 filename = ".";
3091 } else {
3092 filename = fname->base_name;
3095 if (IS_IPC(conn)) {
3096 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3097 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3098 "info level (0x%x) on IPC$.\n",
3099 (unsigned int)info_level));
3100 return NT_STATUS_ACCESS_DENIED;
3104 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3106 ZERO_STRUCT(smb_fname);
3107 smb_fname.base_name = discard_const_p(char, filename);
3109 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3110 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3111 return map_nt_error_from_unix(errno);
3114 st = smb_fname.st;
3116 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3117 return NT_STATUS_INVALID_PARAMETER;
3120 *ppdata = (char *)SMB_REALLOC(
3121 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3122 if (*ppdata == NULL) {
3123 return NT_STATUS_NO_MEMORY;
3126 pdata = *ppdata;
3127 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3128 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3130 *fixed_portion = 0;
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 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3225 /* the client only requested a portion of the
3226 file system name */
3227 data_len = max_data_bytes;
3228 status = STATUS_BUFFER_OVERFLOW;
3230 *fixed_portion = 16;
3231 break;
3233 case SMB_QUERY_FS_LABEL_INFO:
3234 case SMB_FS_LABEL_INFORMATION:
3235 len = srvstr_push(pdata, flags2, pdata+4, vname,
3236 PTR_DIFF(end_data, pdata+4), 0);
3237 data_len = 4 + len;
3238 SIVAL(pdata,0,len);
3239 break;
3241 case SMB_QUERY_FS_VOLUME_INFO:
3242 case SMB_FS_VOLUME_INFORMATION:
3245 * Add volume serial number - hash of a combination of
3246 * the called hostname and the service name.
3248 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3249 (str_checksum(get_local_machine_name())<<16));
3251 /* Max label len is 32 characters. */
3252 len = srvstr_push(pdata, flags2, pdata+18, vname,
3253 PTR_DIFF(end_data, pdata+18),
3254 STR_UNICODE);
3255 SIVAL(pdata,12,len);
3256 data_len = 18+len;
3258 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3259 (int)strlen(vname),vname,
3260 lp_servicename(talloc_tos(), snum)));
3261 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3262 /* the client only requested a portion of the
3263 volume label */
3264 data_len = max_data_bytes;
3265 status = STATUS_BUFFER_OVERFLOW;
3267 *fixed_portion = 24;
3268 break;
3270 case SMB_QUERY_FS_SIZE_INFO:
3271 case SMB_FS_SIZE_INFORMATION:
3273 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3274 data_len = 24;
3275 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3276 return map_nt_error_from_unix(errno);
3278 block_size = lp_block_size(snum);
3279 if (bsize < block_size) {
3280 uint64_t factor = block_size/bsize;
3281 bsize = block_size;
3282 dsize /= factor;
3283 dfree /= factor;
3285 if (bsize > block_size) {
3286 uint64_t factor = bsize/block_size;
3287 bsize = block_size;
3288 dsize *= factor;
3289 dfree *= factor;
3291 bytes_per_sector = 512;
3292 sectors_per_unit = bsize/bytes_per_sector;
3293 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3294 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3295 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3296 SBIG_UINT(pdata,0,dsize);
3297 SBIG_UINT(pdata,8,dfree);
3298 SIVAL(pdata,16,sectors_per_unit);
3299 SIVAL(pdata,20,bytes_per_sector);
3300 *fixed_portion = 24;
3301 break;
3304 case SMB_FS_FULL_SIZE_INFORMATION:
3306 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3307 data_len = 32;
3308 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3309 return map_nt_error_from_unix(errno);
3311 block_size = lp_block_size(snum);
3312 if (bsize < block_size) {
3313 uint64_t factor = block_size/bsize;
3314 bsize = block_size;
3315 dsize /= factor;
3316 dfree /= factor;
3318 if (bsize > block_size) {
3319 uint64_t factor = bsize/block_size;
3320 bsize = block_size;
3321 dsize *= factor;
3322 dfree *= factor;
3324 bytes_per_sector = 512;
3325 sectors_per_unit = bsize/bytes_per_sector;
3326 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3327 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3328 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3329 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3330 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3331 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3332 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3333 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3334 *fixed_portion = 32;
3335 break;
3338 case SMB_QUERY_FS_DEVICE_INFO:
3339 case SMB_FS_DEVICE_INFORMATION:
3341 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3343 if (!CAN_WRITE(conn)) {
3344 characteristics |= FILE_READ_ONLY_DEVICE;
3346 data_len = 8;
3347 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3348 SIVAL(pdata,4,characteristics);
3349 *fixed_portion = 8;
3350 break;
3353 #ifdef HAVE_SYS_QUOTAS
3354 case SMB_FS_QUOTA_INFORMATION:
3356 * what we have to send --metze:
3358 * Unknown1: 24 NULL bytes
3359 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3360 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3361 * Quota Flags: 2 byte :
3362 * Unknown3: 6 NULL bytes
3364 * 48 bytes total
3366 * details for Quota Flags:
3368 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3369 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3370 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3371 * 0x0001 Enable Quotas: enable quota for this fs
3375 /* we need to fake up a fsp here,
3376 * because its not send in this call
3378 files_struct fsp;
3379 SMB_NTQUOTA_STRUCT quotas;
3381 ZERO_STRUCT(fsp);
3382 ZERO_STRUCT(quotas);
3384 fsp.conn = conn;
3385 fsp.fnum = FNUM_FIELD_INVALID;
3387 /* access check */
3388 if (get_current_uid(conn) != 0) {
3389 DEBUG(0,("get_user_quota: access_denied "
3390 "service [%s] user [%s]\n",
3391 lp_servicename(talloc_tos(), SNUM(conn)),
3392 conn->session_info->unix_info->unix_name));
3393 return NT_STATUS_ACCESS_DENIED;
3396 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3397 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3398 return map_nt_error_from_unix(errno);
3401 data_len = 48;
3403 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3404 lp_servicename(talloc_tos(), SNUM(conn))));
3406 /* Unknown1 24 NULL bytes*/
3407 SBIG_UINT(pdata,0,(uint64_t)0);
3408 SBIG_UINT(pdata,8,(uint64_t)0);
3409 SBIG_UINT(pdata,16,(uint64_t)0);
3411 /* Default Soft Quota 8 bytes */
3412 SBIG_UINT(pdata,24,quotas.softlim);
3414 /* Default Hard Quota 8 bytes */
3415 SBIG_UINT(pdata,32,quotas.hardlim);
3417 /* Quota flag 2 bytes */
3418 SSVAL(pdata,40,quotas.qflags);
3420 /* Unknown3 6 NULL bytes */
3421 SSVAL(pdata,42,0);
3422 SIVAL(pdata,44,0);
3424 break;
3426 #endif /* HAVE_SYS_QUOTAS */
3427 case SMB_FS_OBJECTID_INFORMATION:
3429 unsigned char objid[16];
3430 struct smb_extended_info extended_info;
3431 memcpy(pdata,create_volume_objectid(conn, objid),16);
3432 samba_extended_info_version (&extended_info);
3433 SIVAL(pdata,16,extended_info.samba_magic);
3434 SIVAL(pdata,20,extended_info.samba_version);
3435 SIVAL(pdata,24,extended_info.samba_subversion);
3436 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3437 memcpy(pdata+36,extended_info.samba_version_string,28);
3438 data_len = 64;
3439 break;
3443 * Query the version and capabilities of the CIFS UNIX extensions
3444 * in use.
3447 case SMB_QUERY_CIFS_UNIX_INFO:
3449 bool large_write = lp_min_receive_file_size() &&
3450 !srv_is_signing_active(xconn);
3451 bool large_read = !srv_is_signing_active(xconn);
3452 int encrypt_caps = 0;
3454 if (!lp_unix_extensions()) {
3455 return NT_STATUS_INVALID_LEVEL;
3458 switch (conn->encrypt_level) {
3459 case SMB_SIGNING_OFF:
3460 encrypt_caps = 0;
3461 break;
3462 case SMB_SIGNING_IF_REQUIRED:
3463 case SMB_SIGNING_DEFAULT:
3464 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3465 break;
3466 case SMB_SIGNING_REQUIRED:
3467 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3468 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3469 large_write = false;
3470 large_read = false;
3471 break;
3474 data_len = 12;
3475 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3476 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3478 /* We have POSIX ACLs, pathname, encryption,
3479 * large read/write, and locking capability. */
3481 SBIG_UINT(pdata,4,((uint64_t)(
3482 CIFS_UNIX_POSIX_ACLS_CAP|
3483 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3484 CIFS_UNIX_FCNTL_LOCKS_CAP|
3485 CIFS_UNIX_EXTATTR_CAP|
3486 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3487 encrypt_caps|
3488 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3489 (large_write ?
3490 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3491 break;
3494 case SMB_QUERY_POSIX_FS_INFO:
3496 int rc;
3497 vfs_statvfs_struct svfs;
3499 if (!lp_unix_extensions()) {
3500 return NT_STATUS_INVALID_LEVEL;
3503 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3505 if (!rc) {
3506 data_len = 56;
3507 SIVAL(pdata,0,svfs.OptimalTransferSize);
3508 SIVAL(pdata,4,svfs.BlockSize);
3509 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3510 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3511 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3512 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3513 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3514 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3515 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3516 #ifdef EOPNOTSUPP
3517 } else if (rc == EOPNOTSUPP) {
3518 return NT_STATUS_INVALID_LEVEL;
3519 #endif /* EOPNOTSUPP */
3520 } else {
3521 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3522 return NT_STATUS_DOS(ERRSRV, ERRerror);
3524 break;
3527 case SMB_QUERY_POSIX_WHOAMI:
3529 uint32_t flags = 0;
3530 uint32_t sid_bytes;
3531 int i;
3533 if (!lp_unix_extensions()) {
3534 return NT_STATUS_INVALID_LEVEL;
3537 if (max_data_bytes < 40) {
3538 return NT_STATUS_BUFFER_TOO_SMALL;
3541 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3542 flags |= SMB_WHOAMI_GUEST;
3545 /* NOTE: 8 bytes for UID/GID, irrespective of native
3546 * platform size. This matches
3547 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3549 data_len = 4 /* flags */
3550 + 4 /* flag mask */
3551 + 8 /* uid */
3552 + 8 /* gid */
3553 + 4 /* ngroups */
3554 + 4 /* num_sids */
3555 + 4 /* SID bytes */
3556 + 4 /* pad/reserved */
3557 + (conn->session_info->unix_token->ngroups * 8)
3558 /* groups list */
3559 + (conn->session_info->security_token->num_sids *
3560 SID_MAX_SIZE)
3561 /* SID list */;
3563 SIVAL(pdata, 0, flags);
3564 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3565 SBIG_UINT(pdata, 8,
3566 (uint64_t)conn->session_info->unix_token->uid);
3567 SBIG_UINT(pdata, 16,
3568 (uint64_t)conn->session_info->unix_token->gid);
3571 if (data_len >= max_data_bytes) {
3572 /* Potential overflow, skip the GIDs and SIDs. */
3574 SIVAL(pdata, 24, 0); /* num_groups */
3575 SIVAL(pdata, 28, 0); /* num_sids */
3576 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3577 SIVAL(pdata, 36, 0); /* reserved */
3579 data_len = 40;
3580 break;
3583 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3584 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3586 /* We walk the SID list twice, but this call is fairly
3587 * infrequent, and I don't expect that it's performance
3588 * sensitive -- jpeach
3590 for (i = 0, sid_bytes = 0;
3591 i < conn->session_info->security_token->num_sids; ++i) {
3592 sid_bytes += ndr_size_dom_sid(
3593 &conn->session_info->security_token->sids[i],
3597 /* SID list byte count */
3598 SIVAL(pdata, 32, sid_bytes);
3600 /* 4 bytes pad/reserved - must be zero */
3601 SIVAL(pdata, 36, 0);
3602 data_len = 40;
3604 /* GID list */
3605 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3606 SBIG_UINT(pdata, data_len,
3607 (uint64_t)conn->session_info->unix_token->groups[i]);
3608 data_len += 8;
3611 /* SID list */
3612 for (i = 0;
3613 i < conn->session_info->security_token->num_sids; ++i) {
3614 int sid_len = ndr_size_dom_sid(
3615 &conn->session_info->security_token->sids[i],
3618 sid_linearize(pdata + data_len, sid_len,
3619 &conn->session_info->security_token->sids[i]);
3620 data_len += sid_len;
3623 break;
3626 case SMB_MAC_QUERY_FS_INFO:
3628 * Thursby MAC extension... ONLY on NTFS filesystems
3629 * once we do streams then we don't need this
3631 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3632 data_len = 88;
3633 SIVAL(pdata,84,0x100); /* Don't support mac... */
3634 break;
3636 /* drop through */
3637 default:
3638 return NT_STATUS_INVALID_LEVEL;
3641 *ret_data_len = data_len;
3642 return status;
3645 /****************************************************************************
3646 Reply to a TRANS2_QFSINFO (query filesystem info).
3647 ****************************************************************************/
3649 static void call_trans2qfsinfo(connection_struct *conn,
3650 struct smb_request *req,
3651 char **pparams, int total_params,
3652 char **ppdata, int total_data,
3653 unsigned int max_data_bytes)
3655 char *params = *pparams;
3656 uint16_t info_level;
3657 int data_len = 0;
3658 size_t fixed_portion;
3659 NTSTATUS status;
3661 if (total_params < 2) {
3662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3663 return;
3666 info_level = SVAL(params,0);
3668 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3669 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3670 DEBUG(0,("call_trans2qfsinfo: encryption required "
3671 "and info level 0x%x sent.\n",
3672 (unsigned int)info_level));
3673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3674 return;
3678 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3680 status = smbd_do_qfsinfo(req->xconn, conn, req,
3681 info_level,
3682 req->flags2,
3683 max_data_bytes,
3684 &fixed_portion,
3685 NULL,
3686 ppdata, &data_len);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 reply_nterror(req, status);
3689 return;
3692 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3693 max_data_bytes);
3695 DEBUG( 4, ( "%s info_level = %d\n",
3696 smb_fn_name(req->cmd), info_level) );
3698 return;
3701 /****************************************************************************
3702 Reply to a TRANS2_SETFSINFO (set filesystem info).
3703 ****************************************************************************/
3705 static void call_trans2setfsinfo(connection_struct *conn,
3706 struct smb_request *req,
3707 char **pparams, int total_params,
3708 char **ppdata, int total_data,
3709 unsigned int max_data_bytes)
3711 struct smbXsrv_connection *xconn = req->xconn;
3712 char *pdata = *ppdata;
3713 char *params = *pparams;
3714 uint16 info_level;
3716 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3717 lp_servicename(talloc_tos(), SNUM(conn))));
3719 /* */
3720 if (total_params < 4) {
3721 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3722 total_params));
3723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3724 return;
3727 info_level = SVAL(params,2);
3729 if (IS_IPC(conn)) {
3730 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3731 info_level != SMB_SET_CIFS_UNIX_INFO) {
3732 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3733 "info level (0x%x) on IPC$.\n",
3734 (unsigned int)info_level));
3735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3736 return;
3740 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3741 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3742 DEBUG(0,("call_trans2setfsinfo: encryption required "
3743 "and info level 0x%x sent.\n",
3744 (unsigned int)info_level));
3745 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3746 return;
3750 switch(info_level) {
3751 case SMB_SET_CIFS_UNIX_INFO:
3752 if (!lp_unix_extensions()) {
3753 DEBUG(2,("call_trans2setfsinfo: "
3754 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3755 "unix extensions off\n"));
3756 reply_nterror(req,
3757 NT_STATUS_INVALID_LEVEL);
3758 return;
3761 /* There should be 12 bytes of capabilities set. */
3762 if (total_data < 12) {
3763 reply_nterror(
3764 req,
3765 NT_STATUS_INVALID_PARAMETER);
3766 return;
3768 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3769 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3770 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3771 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3772 /* Just print these values for now. */
3773 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3774 "major = %u, minor = %u cap_low = 0x%x, "
3775 "cap_high = 0x%xn",
3776 (unsigned int)xconn->
3777 smb1.unix_info.client_major,
3778 (unsigned int)xconn->
3779 smb1.unix_info.client_minor,
3780 (unsigned int)xconn->
3781 smb1.unix_info.client_cap_low,
3782 (unsigned int)xconn->
3783 smb1.unix_info.client_cap_high));
3785 /* Here is where we must switch to posix pathname processing... */
3786 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3787 lp_set_posix_pathnames();
3788 mangle_change_to_posix();
3791 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3792 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3793 /* Client that knows how to do posix locks,
3794 * but not posix open/mkdir operations. Set a
3795 * default type for read/write checks. */
3797 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3800 break;
3802 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3804 NTSTATUS status;
3805 size_t param_len = 0;
3806 size_t data_len = total_data;
3808 if (!lp_unix_extensions()) {
3809 reply_nterror(
3810 req,
3811 NT_STATUS_INVALID_LEVEL);
3812 return;
3815 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3816 reply_nterror(
3817 req,
3818 NT_STATUS_NOT_SUPPORTED);
3819 return;
3822 if (xconn->smb1.echo_handler.trusted_fde) {
3823 DEBUG( 2,("call_trans2setfsinfo: "
3824 "request transport encryption disabled"
3825 "with 'fork echo handler = yes'\n"));
3826 reply_nterror(
3827 req,
3828 NT_STATUS_NOT_SUPPORTED);
3829 return;
3832 DEBUG( 4,("call_trans2setfsinfo: "
3833 "request transport encryption.\n"));
3835 status = srv_request_encryption_setup(conn,
3836 (unsigned char **)ppdata,
3837 &data_len,
3838 (unsigned char **)pparams,
3839 &param_len);
3841 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3842 !NT_STATUS_IS_OK(status)) {
3843 reply_nterror(req, status);
3844 return;
3847 send_trans2_replies(conn, req,
3848 NT_STATUS_OK,
3849 *pparams,
3850 param_len,
3851 *ppdata,
3852 data_len,
3853 max_data_bytes);
3855 if (NT_STATUS_IS_OK(status)) {
3856 /* Server-side transport
3857 * encryption is now *on*. */
3858 status = srv_encryption_start(conn);
3859 if (!NT_STATUS_IS_OK(status)) {
3860 char *reason = talloc_asprintf(talloc_tos(),
3861 "Failure in setting "
3862 "up encrypted transport: %s",
3863 nt_errstr(status));
3864 exit_server_cleanly(reason);
3867 return;
3870 case SMB_FS_QUOTA_INFORMATION:
3872 files_struct *fsp = NULL;
3873 SMB_NTQUOTA_STRUCT quotas;
3875 ZERO_STRUCT(quotas);
3877 /* access check */
3878 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3879 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3880 lp_servicename(talloc_tos(), SNUM(conn)),
3881 conn->session_info->unix_info->unix_name));
3882 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3883 return;
3886 /* note: normaly there're 48 bytes,
3887 * but we didn't use the last 6 bytes for now
3888 * --metze
3890 fsp = file_fsp(req, SVAL(params,0));
3892 if (!check_fsp_ntquota_handle(conn, req,
3893 fsp)) {
3894 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3895 reply_nterror(
3896 req, NT_STATUS_INVALID_HANDLE);
3897 return;
3900 if (total_data < 42) {
3901 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3902 total_data));
3903 reply_nterror(
3904 req,
3905 NT_STATUS_INVALID_PARAMETER);
3906 return;
3909 /* unknown_1 24 NULL bytes in pdata*/
3911 /* the soft quotas 8 bytes (uint64_t)*/
3912 quotas.softlim = BVAL(pdata,24);
3914 /* the hard quotas 8 bytes (uint64_t)*/
3915 quotas.hardlim = BVAL(pdata,32);
3917 /* quota_flags 2 bytes **/
3918 quotas.qflags = SVAL(pdata,40);
3920 /* unknown_2 6 NULL bytes follow*/
3922 /* now set the quotas */
3923 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3924 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3925 reply_nterror(req, map_nt_error_from_unix(errno));
3926 return;
3929 break;
3931 default:
3932 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3933 info_level));
3934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3935 return;
3936 break;
3940 * sending this reply works fine,
3941 * but I'm not sure it's the same
3942 * like windows do...
3943 * --metze
3945 reply_outbuf(req, 10, 0);
3948 #if defined(HAVE_POSIX_ACLS)
3949 /****************************************************************************
3950 Utility function to count the number of entries in a POSIX acl.
3951 ****************************************************************************/
3953 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3955 unsigned int ace_count = 0;
3956 int entry_id = SMB_ACL_FIRST_ENTRY;
3957 SMB_ACL_ENTRY_T entry;
3959 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3960 /* get_next... */
3961 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3962 entry_id = SMB_ACL_NEXT_ENTRY;
3964 ace_count++;
3966 return ace_count;
3969 /****************************************************************************
3970 Utility function to marshall a POSIX acl into wire format.
3971 ****************************************************************************/
3973 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3975 int entry_id = SMB_ACL_FIRST_ENTRY;
3976 SMB_ACL_ENTRY_T entry;
3978 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3979 SMB_ACL_TAG_T tagtype;
3980 SMB_ACL_PERMSET_T permset;
3981 unsigned char perms = 0;
3982 unsigned int own_grp;
3984 /* get_next... */
3985 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3986 entry_id = SMB_ACL_NEXT_ENTRY;
3989 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3990 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3991 return False;
3994 if (sys_acl_get_permset(entry, &permset) == -1) {
3995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3996 return False;
3999 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4000 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4001 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4003 SCVAL(pdata,1,perms);
4005 switch (tagtype) {
4006 case SMB_ACL_USER_OBJ:
4007 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4008 own_grp = (unsigned int)pst->st_ex_uid;
4009 SIVAL(pdata,2,own_grp);
4010 SIVAL(pdata,6,0);
4011 break;
4012 case SMB_ACL_USER:
4014 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4015 if (!puid) {
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4017 return False;
4019 own_grp = (unsigned int)*puid;
4020 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4021 SIVAL(pdata,2,own_grp);
4022 SIVAL(pdata,6,0);
4023 break;
4025 case SMB_ACL_GROUP_OBJ:
4026 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4027 own_grp = (unsigned int)pst->st_ex_gid;
4028 SIVAL(pdata,2,own_grp);
4029 SIVAL(pdata,6,0);
4030 break;
4031 case SMB_ACL_GROUP:
4033 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4034 if (!pgid) {
4035 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4036 return False;
4038 own_grp = (unsigned int)*pgid;
4039 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4040 SIVAL(pdata,2,own_grp);
4041 SIVAL(pdata,6,0);
4042 break;
4044 case SMB_ACL_MASK:
4045 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4046 SIVAL(pdata,2,0xFFFFFFFF);
4047 SIVAL(pdata,6,0xFFFFFFFF);
4048 break;
4049 case SMB_ACL_OTHER:
4050 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4051 SIVAL(pdata,2,0xFFFFFFFF);
4052 SIVAL(pdata,6,0xFFFFFFFF);
4053 break;
4054 default:
4055 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4056 return False;
4058 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4061 return True;
4063 #endif
4065 /****************************************************************************
4066 Store the FILE_UNIX_BASIC info.
4067 ****************************************************************************/
4069 static char *store_file_unix_basic(connection_struct *conn,
4070 char *pdata,
4071 files_struct *fsp,
4072 const SMB_STRUCT_STAT *psbuf)
4074 uint64_t file_index = get_FileIndex(conn, psbuf);
4075 dev_t devno;
4077 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4078 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4080 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4081 pdata += 8;
4083 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4084 pdata += 8;
4086 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4087 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4088 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4089 pdata += 24;
4091 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4092 SIVAL(pdata,4,0);
4093 pdata += 8;
4095 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4096 SIVAL(pdata,4,0);
4097 pdata += 8;
4099 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4100 pdata += 4;
4102 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4103 devno = psbuf->st_ex_rdev;
4104 } else {
4105 devno = psbuf->st_ex_dev;
4108 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4109 SIVAL(pdata,4,0);
4110 pdata += 8;
4112 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4113 SIVAL(pdata,4,0);
4114 pdata += 8;
4116 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4117 pdata += 8;
4119 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4120 SIVAL(pdata,4,0);
4121 pdata += 8;
4123 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4124 SIVAL(pdata,4,0);
4125 pdata += 8;
4127 return pdata;
4130 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4131 * the chflags(2) (or equivalent) flags.
4133 * XXX: this really should be behind the VFS interface. To do this, we would
4134 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4135 * Each VFS module could then implement its own mapping as appropriate for the
4136 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4138 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4139 info2_flags_map[] =
4141 #ifdef UF_NODUMP
4142 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4143 #endif
4145 #ifdef UF_IMMUTABLE
4146 { UF_IMMUTABLE, EXT_IMMUTABLE },
4147 #endif
4149 #ifdef UF_APPEND
4150 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4151 #endif
4153 #ifdef UF_HIDDEN
4154 { UF_HIDDEN, EXT_HIDDEN },
4155 #endif
4157 /* Do not remove. We need to guarantee that this array has at least one
4158 * entry to build on HP-UX.
4160 { 0, 0 }
4164 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4165 uint32 *smb_fflags, uint32 *smb_fmask)
4167 int i;
4169 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4170 *smb_fmask |= info2_flags_map[i].smb_fflag;
4171 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4172 *smb_fflags |= info2_flags_map[i].smb_fflag;
4177 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4178 const uint32 smb_fflags,
4179 const uint32 smb_fmask,
4180 int *stat_fflags)
4182 uint32 max_fmask = 0;
4183 int i;
4185 *stat_fflags = psbuf->st_ex_flags;
4187 /* For each flags requested in smb_fmask, check the state of the
4188 * corresponding flag in smb_fflags and set or clear the matching
4189 * stat flag.
4192 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4193 max_fmask |= info2_flags_map[i].smb_fflag;
4194 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4195 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4196 *stat_fflags |= info2_flags_map[i].stat_fflag;
4197 } else {
4198 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4203 /* If smb_fmask is asking to set any bits that are not supported by
4204 * our flag mappings, we should fail.
4206 if ((smb_fmask & max_fmask) != smb_fmask) {
4207 return False;
4210 return True;
4214 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4215 * of file flags and birth (create) time.
4217 static char *store_file_unix_basic_info2(connection_struct *conn,
4218 char *pdata,
4219 files_struct *fsp,
4220 const SMB_STRUCT_STAT *psbuf)
4222 uint32 file_flags = 0;
4223 uint32 flags_mask = 0;
4225 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4227 /* Create (birth) time 64 bit */
4228 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4229 pdata += 8;
4231 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4232 SIVAL(pdata, 0, file_flags); /* flags */
4233 SIVAL(pdata, 4, flags_mask); /* mask */
4234 pdata += 8;
4236 return pdata;
4239 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4240 const struct stream_struct *streams,
4241 char *data,
4242 unsigned int max_data_bytes,
4243 unsigned int *data_size)
4245 unsigned int i;
4246 unsigned int ofs = 0;
4248 if (max_data_bytes < 32) {
4249 return NT_STATUS_INFO_LENGTH_MISMATCH;
4252 for (i = 0; i < num_streams; i++) {
4253 unsigned int next_offset;
4254 size_t namelen;
4255 smb_ucs2_t *namebuf;
4257 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4258 streams[i].name, &namelen) ||
4259 namelen <= 2)
4261 return NT_STATUS_INVALID_PARAMETER;
4265 * name_buf is now null-terminated, we need to marshall as not
4266 * terminated
4269 namelen -= 2;
4272 * We cannot overflow ...
4274 if ((ofs + 24 + namelen) > max_data_bytes) {
4275 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4276 i));
4277 TALLOC_FREE(namebuf);
4278 return STATUS_BUFFER_OVERFLOW;
4281 SIVAL(data, ofs+4, namelen);
4282 SOFF_T(data, ofs+8, streams[i].size);
4283 SOFF_T(data, ofs+16, streams[i].alloc_size);
4284 memcpy(data+ofs+24, namebuf, namelen);
4285 TALLOC_FREE(namebuf);
4287 next_offset = ofs + 24 + namelen;
4289 if (i == num_streams-1) {
4290 SIVAL(data, ofs, 0);
4292 else {
4293 unsigned int align = ndr_align_size(next_offset, 8);
4295 if ((next_offset + align) > max_data_bytes) {
4296 DEBUG(10, ("refusing to overflow align "
4297 "reply at stream %u\n",
4298 i));
4299 TALLOC_FREE(namebuf);
4300 return STATUS_BUFFER_OVERFLOW;
4303 memset(data+next_offset, 0, align);
4304 next_offset += align;
4306 SIVAL(data, ofs, next_offset - ofs);
4307 ofs = next_offset;
4310 ofs = next_offset;
4313 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4315 *data_size = ofs;
4317 return NT_STATUS_OK;
4320 /****************************************************************************
4321 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4322 ****************************************************************************/
4324 static void call_trans2qpipeinfo(connection_struct *conn,
4325 struct smb_request *req,
4326 unsigned int tran_call,
4327 char **pparams, int total_params,
4328 char **ppdata, int total_data,
4329 unsigned int max_data_bytes)
4331 char *params = *pparams;
4332 char *pdata = *ppdata;
4333 unsigned int data_size = 0;
4334 unsigned int param_size = 2;
4335 uint16 info_level;
4336 files_struct *fsp;
4338 if (!params) {
4339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4340 return;
4343 if (total_params < 4) {
4344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4345 return;
4348 fsp = file_fsp(req, SVAL(params,0));
4349 if (!fsp_is_np(fsp)) {
4350 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4351 return;
4354 info_level = SVAL(params,2);
4356 *pparams = (char *)SMB_REALLOC(*pparams,2);
4357 if (*pparams == NULL) {
4358 reply_nterror(req, NT_STATUS_NO_MEMORY);
4359 return;
4361 params = *pparams;
4362 SSVAL(params,0,0);
4363 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4365 return;
4367 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4368 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4369 if (*ppdata == NULL ) {
4370 reply_nterror(req, NT_STATUS_NO_MEMORY);
4371 return;
4373 pdata = *ppdata;
4375 switch (info_level) {
4376 case SMB_FILE_STANDARD_INFORMATION:
4377 memset(pdata,0,24);
4378 SOFF_T(pdata,0,4096LL);
4379 SIVAL(pdata,16,1);
4380 SIVAL(pdata,20,1);
4381 data_size = 24;
4382 break;
4384 default:
4385 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4386 return;
4389 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4390 max_data_bytes);
4392 return;
4395 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4396 TALLOC_CTX *mem_ctx,
4397 uint16_t info_level,
4398 files_struct *fsp,
4399 struct smb_filename *smb_fname,
4400 bool delete_pending,
4401 struct timespec write_time_ts,
4402 struct ea_list *ea_list,
4403 int lock_data_count,
4404 char *lock_data,
4405 uint16_t flags2,
4406 unsigned int max_data_bytes,
4407 size_t *fixed_portion,
4408 char **ppdata,
4409 unsigned int *pdata_size)
4411 char *pdata = *ppdata;
4412 char *dstart, *dend;
4413 unsigned int data_size;
4414 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4415 time_t create_time, mtime, atime, c_time;
4416 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4417 char *p;
4418 char *base_name;
4419 char *dos_fname;
4420 int mode;
4421 int nlink;
4422 NTSTATUS status;
4423 uint64_t file_size = 0;
4424 uint64_t pos = 0;
4425 uint64_t allocation_size = 0;
4426 uint64_t file_index = 0;
4427 uint32_t access_mask = 0;
4429 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4430 return NT_STATUS_INVALID_LEVEL;
4433 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4434 smb_fname_str_dbg(smb_fname),
4435 fsp_fnum_dbg(fsp),
4436 info_level, max_data_bytes));
4438 mode = dos_mode(conn, smb_fname);
4439 nlink = psbuf->st_ex_nlink;
4441 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4442 nlink = 1;
4445 if ((nlink > 0) && delete_pending) {
4446 nlink -= 1;
4449 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4450 return NT_STATUS_INVALID_PARAMETER;
4453 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4454 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4455 if (*ppdata == NULL) {
4456 return NT_STATUS_NO_MEMORY;
4458 pdata = *ppdata;
4459 dstart = pdata;
4460 dend = dstart + data_size - 1;
4462 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4463 update_stat_ex_mtime(psbuf, write_time_ts);
4466 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4467 mtime_ts = psbuf->st_ex_mtime;
4468 atime_ts = psbuf->st_ex_atime;
4469 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4471 if (lp_dos_filetime_resolution(SNUM(conn))) {
4472 dos_filetime_timespec(&create_time_ts);
4473 dos_filetime_timespec(&mtime_ts);
4474 dos_filetime_timespec(&atime_ts);
4475 dos_filetime_timespec(&ctime_ts);
4478 create_time = convert_timespec_to_time_t(create_time_ts);
4479 mtime = convert_timespec_to_time_t(mtime_ts);
4480 atime = convert_timespec_to_time_t(atime_ts);
4481 c_time = convert_timespec_to_time_t(ctime_ts);
4483 p = strrchr_m(smb_fname->base_name,'/');
4484 if (!p)
4485 base_name = smb_fname->base_name;
4486 else
4487 base_name = p+1;
4489 /* NT expects the name to be in an exact form of the *full*
4490 filename. See the trans2 torture test */
4491 if (ISDOT(base_name)) {
4492 dos_fname = talloc_strdup(mem_ctx, "\\");
4493 if (!dos_fname) {
4494 return NT_STATUS_NO_MEMORY;
4496 } else {
4497 dos_fname = talloc_asprintf(mem_ctx,
4498 "\\%s",
4499 smb_fname->base_name);
4500 if (!dos_fname) {
4501 return NT_STATUS_NO_MEMORY;
4503 if (is_ntfs_stream_smb_fname(smb_fname)) {
4504 dos_fname = talloc_asprintf(dos_fname, "%s",
4505 smb_fname->stream_name);
4506 if (!dos_fname) {
4507 return NT_STATUS_NO_MEMORY;
4511 string_replace(dos_fname, '/', '\\');
4514 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4516 if (!fsp) {
4517 /* Do we have this path open ? */
4518 files_struct *fsp1;
4519 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4520 fsp1 = file_find_di_first(conn->sconn, fileid);
4521 if (fsp1 && fsp1->initial_allocation_size) {
4522 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4526 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4527 file_size = get_file_size_stat(psbuf);
4530 if (fsp) {
4531 pos = fsp->fh->position_information;
4534 if (fsp) {
4535 access_mask = fsp->access_mask;
4536 } else {
4537 /* GENERIC_EXECUTE mapping from Windows */
4538 access_mask = 0x12019F;
4541 /* This should be an index number - looks like
4542 dev/ino to me :-)
4544 I think this causes us to fail the IFSKIT
4545 BasicFileInformationTest. -tpot */
4546 file_index = get_FileIndex(conn, psbuf);
4548 *fixed_portion = 0;
4550 switch (info_level) {
4551 case SMB_INFO_STANDARD:
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4553 data_size = 22;
4554 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4555 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4556 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4557 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4558 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4559 SSVAL(pdata,l1_attrFile,mode);
4560 break;
4562 case SMB_INFO_QUERY_EA_SIZE:
4564 unsigned int ea_size =
4565 estimate_ea_size(conn, fsp,
4566 smb_fname);
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4568 data_size = 26;
4569 srv_put_dos_date2(pdata,0,create_time);
4570 srv_put_dos_date2(pdata,4,atime);
4571 srv_put_dos_date2(pdata,8,mtime); /* write time */
4572 SIVAL(pdata,12,(uint32)file_size);
4573 SIVAL(pdata,16,(uint32)allocation_size);
4574 SSVAL(pdata,20,mode);
4575 SIVAL(pdata,22,ea_size);
4576 break;
4579 case SMB_INFO_IS_NAME_VALID:
4580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4581 if (fsp) {
4582 /* os/2 needs this ? really ?*/
4583 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4585 /* This is only reached for qpathinfo */
4586 data_size = 0;
4587 break;
4589 case SMB_INFO_QUERY_EAS_FROM_LIST:
4591 size_t total_ea_len = 0;
4592 struct ea_list *ea_file_list = NULL;
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4595 status =
4596 get_ea_list_from_file(mem_ctx, conn, fsp,
4597 smb_fname,
4598 &total_ea_len, &ea_file_list);
4599 if (!NT_STATUS_IS_OK(status)) {
4600 return status;
4603 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4605 if (!ea_list || (total_ea_len > data_size)) {
4606 data_size = 4;
4607 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4608 break;
4611 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4612 break;
4615 case SMB_INFO_QUERY_ALL_EAS:
4617 /* We have data_size bytes to put EA's into. */
4618 size_t total_ea_len = 0;
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4621 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4622 smb_fname,
4623 &total_ea_len, &ea_list);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 return status;
4628 if (!ea_list || (total_ea_len > data_size)) {
4629 data_size = 4;
4630 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4631 break;
4634 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4635 break;
4638 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4640 /* This is FileFullEaInformation - 0xF which maps to
4641 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4643 /* We have data_size bytes to put EA's into. */
4644 size_t total_ea_len = 0;
4645 struct ea_list *ea_file_list = NULL;
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4649 /*TODO: add filtering and index handling */
4651 status =
4652 get_ea_list_from_file(mem_ctx, conn, fsp,
4653 smb_fname,
4654 &total_ea_len, &ea_file_list);
4655 if (!NT_STATUS_IS_OK(status)) {
4656 return status;
4658 if (!ea_file_list) {
4659 return NT_STATUS_NO_EAS_ON_FILE;
4662 status = fill_ea_chained_buffer(mem_ctx,
4663 pdata,
4664 data_size,
4665 &data_size,
4666 conn, ea_file_list);
4667 if (!NT_STATUS_IS_OK(status)) {
4668 return status;
4670 break;
4673 case SMB_FILE_BASIC_INFORMATION:
4674 case SMB_QUERY_FILE_BASIC_INFO:
4676 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4678 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4679 } else {
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4681 data_size = 40;
4682 SIVAL(pdata,36,0);
4684 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4685 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4686 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4687 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4688 SIVAL(pdata,32,mode);
4690 DEBUG(5,("SMB_QFBI - "));
4691 DEBUG(5,("create: %s ", ctime(&create_time)));
4692 DEBUG(5,("access: %s ", ctime(&atime)));
4693 DEBUG(5,("write: %s ", ctime(&mtime)));
4694 DEBUG(5,("change: %s ", ctime(&c_time)));
4695 DEBUG(5,("mode: %x\n", mode));
4696 *fixed_portion = data_size;
4697 break;
4699 case SMB_FILE_STANDARD_INFORMATION:
4700 case SMB_QUERY_FILE_STANDARD_INFO:
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4703 data_size = 24;
4704 SOFF_T(pdata,0,allocation_size);
4705 SOFF_T(pdata,8,file_size);
4706 SIVAL(pdata,16,nlink);
4707 SCVAL(pdata,20,delete_pending?1:0);
4708 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4709 SSVAL(pdata,22,0); /* Padding. */
4710 *fixed_portion = 24;
4711 break;
4713 case SMB_FILE_EA_INFORMATION:
4714 case SMB_QUERY_FILE_EA_INFO:
4716 unsigned int ea_size =
4717 estimate_ea_size(conn, fsp, smb_fname);
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4719 data_size = 4;
4720 *fixed_portion = 4;
4721 SIVAL(pdata,0,ea_size);
4722 break;
4725 /* Get the 8.3 name - used if NT SMB was negotiated. */
4726 case SMB_QUERY_FILE_ALT_NAME_INFO:
4727 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4729 int len;
4730 char mangled_name[13];
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4732 if (!name_to_8_3(base_name,mangled_name,
4733 True,conn->params)) {
4734 return NT_STATUS_NO_MEMORY;
4736 len = srvstr_push(dstart, flags2,
4737 pdata+4, mangled_name,
4738 PTR_DIFF(dend, pdata+4),
4739 STR_UNICODE);
4740 data_size = 4 + len;
4741 SIVAL(pdata,0,len);
4742 *fixed_portion = 8;
4743 break;
4746 case SMB_QUERY_FILE_NAME_INFO:
4748 int len;
4750 this must be *exactly* right for ACLs on mapped drives to work
4752 len = srvstr_push(dstart, flags2,
4753 pdata+4, dos_fname,
4754 PTR_DIFF(dend, pdata+4),
4755 STR_UNICODE);
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4757 data_size = 4 + len;
4758 SIVAL(pdata,0,len);
4759 break;
4762 case SMB_FILE_ALLOCATION_INFORMATION:
4763 case SMB_QUERY_FILE_ALLOCATION_INFO:
4764 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4765 data_size = 8;
4766 SOFF_T(pdata,0,allocation_size);
4767 break;
4769 case SMB_FILE_END_OF_FILE_INFORMATION:
4770 case SMB_QUERY_FILE_END_OF_FILEINFO:
4771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4772 data_size = 8;
4773 SOFF_T(pdata,0,file_size);
4774 break;
4776 case SMB_QUERY_FILE_ALL_INFO:
4777 case SMB_FILE_ALL_INFORMATION:
4779 int len;
4780 unsigned int ea_size =
4781 estimate_ea_size(conn, fsp, smb_fname);
4782 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4783 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4784 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4785 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4786 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4787 SIVAL(pdata,32,mode);
4788 SIVAL(pdata,36,0); /* padding. */
4789 pdata += 40;
4790 SOFF_T(pdata,0,allocation_size);
4791 SOFF_T(pdata,8,file_size);
4792 SIVAL(pdata,16,nlink);
4793 SCVAL(pdata,20,delete_pending);
4794 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4795 SSVAL(pdata,22,0);
4796 pdata += 24;
4797 SIVAL(pdata,0,ea_size);
4798 pdata += 4; /* EA info */
4799 len = srvstr_push(dstart, flags2,
4800 pdata+4, dos_fname,
4801 PTR_DIFF(dend, pdata+4),
4802 STR_UNICODE);
4803 SIVAL(pdata,0,len);
4804 pdata += 4 + len;
4805 data_size = PTR_DIFF(pdata,(*ppdata));
4806 *fixed_portion = 10;
4807 break;
4810 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4812 int len;
4813 unsigned int ea_size =
4814 estimate_ea_size(conn, fsp, smb_fname);
4815 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4816 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4817 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4818 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4819 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4820 SIVAL(pdata, 0x20, mode);
4821 SIVAL(pdata, 0x24, 0); /* padding. */
4822 SBVAL(pdata, 0x28, allocation_size);
4823 SBVAL(pdata, 0x30, file_size);
4824 SIVAL(pdata, 0x38, nlink);
4825 SCVAL(pdata, 0x3C, delete_pending);
4826 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4827 SSVAL(pdata, 0x3E, 0); /* padding */
4828 SBVAL(pdata, 0x40, file_index);
4829 SIVAL(pdata, 0x48, ea_size);
4830 SIVAL(pdata, 0x4C, access_mask);
4831 SBVAL(pdata, 0x50, pos);
4832 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4833 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4835 pdata += 0x60;
4837 len = srvstr_push(dstart, flags2,
4838 pdata+4, dos_fname,
4839 PTR_DIFF(dend, pdata+4),
4840 STR_UNICODE);
4841 SIVAL(pdata,0,len);
4842 pdata += 4 + len;
4843 data_size = PTR_DIFF(pdata,(*ppdata));
4844 *fixed_portion = 104;
4845 break;
4847 case SMB_FILE_INTERNAL_INFORMATION:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4850 SBVAL(pdata, 0, file_index);
4851 data_size = 8;
4852 *fixed_portion = 8;
4853 break;
4855 case SMB_FILE_ACCESS_INFORMATION:
4856 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4857 SIVAL(pdata, 0, access_mask);
4858 data_size = 4;
4859 *fixed_portion = 4;
4860 break;
4862 case SMB_FILE_NAME_INFORMATION:
4863 /* Pathname with leading '\'. */
4865 size_t byte_len;
4866 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4867 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4868 SIVAL(pdata,0,byte_len);
4869 data_size = 4 + byte_len;
4870 break;
4873 case SMB_FILE_DISPOSITION_INFORMATION:
4874 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4875 data_size = 1;
4876 SCVAL(pdata,0,delete_pending);
4877 *fixed_portion = 1;
4878 break;
4880 case SMB_FILE_POSITION_INFORMATION:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4882 data_size = 8;
4883 SOFF_T(pdata,0,pos);
4884 *fixed_portion = 8;
4885 break;
4887 case SMB_FILE_MODE_INFORMATION:
4888 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4889 SIVAL(pdata,0,mode);
4890 data_size = 4;
4891 *fixed_portion = 4;
4892 break;
4894 case SMB_FILE_ALIGNMENT_INFORMATION:
4895 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4896 SIVAL(pdata,0,0); /* No alignment needed. */
4897 data_size = 4;
4898 *fixed_portion = 4;
4899 break;
4902 * NT4 server just returns "invalid query" to this - if we try
4903 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4904 * want this. JRA.
4906 /* The first statement above is false - verified using Thursby
4907 * client against NT4 -- gcolley.
4909 case SMB_QUERY_FILE_STREAM_INFO:
4910 case SMB_FILE_STREAM_INFORMATION: {
4911 unsigned int num_streams = 0;
4912 struct stream_struct *streams = NULL;
4914 DEBUG(10,("smbd_do_qfilepathinfo: "
4915 "SMB_FILE_STREAM_INFORMATION\n"));
4917 if (is_ntfs_stream_smb_fname(smb_fname)) {
4918 return NT_STATUS_INVALID_PARAMETER;
4921 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4922 talloc_tos(), &num_streams, &streams);
4924 if (!NT_STATUS_IS_OK(status)) {
4925 DEBUG(10, ("could not get stream info: %s\n",
4926 nt_errstr(status)));
4927 return status;
4930 status = marshall_stream_info(num_streams, streams,
4931 pdata, max_data_bytes,
4932 &data_size);
4934 if (!NT_STATUS_IS_OK(status)) {
4935 DEBUG(10, ("marshall_stream_info failed: %s\n",
4936 nt_errstr(status)));
4937 TALLOC_FREE(streams);
4938 return status;
4941 TALLOC_FREE(streams);
4943 *fixed_portion = 32;
4945 break;
4947 case SMB_QUERY_COMPRESSION_INFO:
4948 case SMB_FILE_COMPRESSION_INFORMATION:
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4950 SOFF_T(pdata,0,file_size);
4951 SIVAL(pdata,8,0); /* ??? */
4952 SIVAL(pdata,12,0); /* ??? */
4953 data_size = 16;
4954 *fixed_portion = 16;
4955 break;
4957 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4959 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4960 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4961 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4962 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4963 SOFF_T(pdata,32,allocation_size);
4964 SOFF_T(pdata,40,file_size);
4965 SIVAL(pdata,48,mode);
4966 SIVAL(pdata,52,0); /* ??? */
4967 data_size = 56;
4968 *fixed_portion = 56;
4969 break;
4971 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4972 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4973 SIVAL(pdata,0,mode);
4974 SIVAL(pdata,4,0);
4975 data_size = 8;
4976 *fixed_portion = 8;
4977 break;
4980 * CIFS UNIX Extensions.
4983 case SMB_QUERY_FILE_UNIX_BASIC:
4985 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4986 data_size = PTR_DIFF(pdata,(*ppdata));
4988 DEBUG(4,("smbd_do_qfilepathinfo: "
4989 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4990 dump_data(4, (uint8_t *)(*ppdata), data_size);
4992 break;
4994 case SMB_QUERY_FILE_UNIX_INFO2:
4996 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4997 data_size = PTR_DIFF(pdata,(*ppdata));
5000 int i;
5001 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5003 for (i=0; i<100; i++)
5004 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5005 DEBUG(4,("\n"));
5008 break;
5010 case SMB_QUERY_FILE_UNIX_LINK:
5012 int len;
5013 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5015 if (!buffer) {
5016 return NT_STATUS_NO_MEMORY;
5019 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5020 #ifdef S_ISLNK
5021 if(!S_ISLNK(psbuf->st_ex_mode)) {
5022 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5024 #else
5025 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5026 #endif
5027 len = SMB_VFS_READLINK(conn,
5028 smb_fname->base_name,
5029 buffer, PATH_MAX);
5030 if (len == -1) {
5031 return map_nt_error_from_unix(errno);
5033 buffer[len] = 0;
5034 len = srvstr_push(dstart, flags2,
5035 pdata, buffer,
5036 PTR_DIFF(dend, pdata),
5037 STR_TERMINATE);
5038 pdata += len;
5039 data_size = PTR_DIFF(pdata,(*ppdata));
5041 break;
5044 #if defined(HAVE_POSIX_ACLS)
5045 case SMB_QUERY_POSIX_ACL:
5047 SMB_ACL_T file_acl = NULL;
5048 SMB_ACL_T def_acl = NULL;
5049 uint16 num_file_acls = 0;
5050 uint16 num_def_acls = 0;
5052 if (fsp && fsp->fh->fd != -1) {
5053 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5054 talloc_tos());
5055 } else {
5056 file_acl =
5057 SMB_VFS_SYS_ACL_GET_FILE(conn,
5058 smb_fname->base_name,
5059 SMB_ACL_TYPE_ACCESS,
5060 talloc_tos());
5063 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5064 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5065 "not implemented on "
5066 "filesystem containing %s\n",
5067 smb_fname->base_name));
5068 return NT_STATUS_NOT_IMPLEMENTED;
5071 if (S_ISDIR(psbuf->st_ex_mode)) {
5072 if (fsp && fsp->is_directory) {
5073 def_acl =
5074 SMB_VFS_SYS_ACL_GET_FILE(
5075 conn,
5076 fsp->fsp_name->base_name,
5077 SMB_ACL_TYPE_DEFAULT,
5078 talloc_tos());
5079 } else {
5080 def_acl =
5081 SMB_VFS_SYS_ACL_GET_FILE(
5082 conn,
5083 smb_fname->base_name,
5084 SMB_ACL_TYPE_DEFAULT,
5085 talloc_tos());
5087 def_acl = free_empty_sys_acl(conn, def_acl);
5090 num_file_acls = count_acl_entries(conn, file_acl);
5091 num_def_acls = count_acl_entries(conn, def_acl);
5093 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5094 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5095 data_size,
5096 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5097 SMB_POSIX_ACL_HEADER_SIZE) ));
5098 if (file_acl) {
5099 TALLOC_FREE(file_acl);
5101 if (def_acl) {
5102 TALLOC_FREE(def_acl);
5104 return NT_STATUS_BUFFER_TOO_SMALL;
5107 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5108 SSVAL(pdata,2,num_file_acls);
5109 SSVAL(pdata,4,num_def_acls);
5110 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5111 if (file_acl) {
5112 TALLOC_FREE(file_acl);
5114 if (def_acl) {
5115 TALLOC_FREE(def_acl);
5117 return NT_STATUS_INTERNAL_ERROR;
5119 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5120 if (file_acl) {
5121 TALLOC_FREE(file_acl);
5123 if (def_acl) {
5124 TALLOC_FREE(def_acl);
5126 return NT_STATUS_INTERNAL_ERROR;
5129 if (file_acl) {
5130 TALLOC_FREE(file_acl);
5132 if (def_acl) {
5133 TALLOC_FREE(def_acl);
5135 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5136 break;
5138 #endif
5141 case SMB_QUERY_POSIX_LOCK:
5143 uint64_t count;
5144 uint64_t offset;
5145 uint64_t smblctx;
5146 enum brl_type lock_type;
5148 /* We need an open file with a real fd for this. */
5149 if (!fsp || fsp->fh->fd == -1) {
5150 return NT_STATUS_INVALID_LEVEL;
5153 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5154 return NT_STATUS_INVALID_PARAMETER;
5157 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5158 case POSIX_LOCK_TYPE_READ:
5159 lock_type = READ_LOCK;
5160 break;
5161 case POSIX_LOCK_TYPE_WRITE:
5162 lock_type = WRITE_LOCK;
5163 break;
5164 case POSIX_LOCK_TYPE_UNLOCK:
5165 default:
5166 /* There's no point in asking for an unlock... */
5167 return NT_STATUS_INVALID_PARAMETER;
5170 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5171 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5172 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5174 status = query_lock(fsp,
5175 &smblctx,
5176 &count,
5177 &offset,
5178 &lock_type,
5179 POSIX_LOCK);
5181 if (ERROR_WAS_LOCK_DENIED(status)) {
5182 /* Here we need to report who has it locked... */
5183 data_size = POSIX_LOCK_DATA_SIZE;
5185 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5186 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5187 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5188 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5189 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5191 } else if (NT_STATUS_IS_OK(status)) {
5192 /* For success we just return a copy of what we sent
5193 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5194 data_size = POSIX_LOCK_DATA_SIZE;
5195 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5196 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5197 } else {
5198 return status;
5200 break;
5203 default:
5204 return NT_STATUS_INVALID_LEVEL;
5207 *pdata_size = data_size;
5208 return NT_STATUS_OK;
5211 /****************************************************************************
5212 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5213 file name or file id).
5214 ****************************************************************************/
5216 static void call_trans2qfilepathinfo(connection_struct *conn,
5217 struct smb_request *req,
5218 unsigned int tran_call,
5219 char **pparams, int total_params,
5220 char **ppdata, int total_data,
5221 unsigned int max_data_bytes)
5223 char *params = *pparams;
5224 char *pdata = *ppdata;
5225 uint16 info_level;
5226 unsigned int data_size = 0;
5227 unsigned int param_size = 2;
5228 struct smb_filename *smb_fname = NULL;
5229 bool delete_pending = False;
5230 struct timespec write_time_ts;
5231 files_struct *fsp = NULL;
5232 struct file_id fileid;
5233 struct ea_list *ea_list = NULL;
5234 int lock_data_count = 0;
5235 char *lock_data = NULL;
5236 size_t fixed_portion;
5237 NTSTATUS status = NT_STATUS_OK;
5239 if (!params) {
5240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5241 return;
5244 ZERO_STRUCT(write_time_ts);
5246 if (tran_call == TRANSACT2_QFILEINFO) {
5247 if (total_params < 4) {
5248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5249 return;
5252 if (IS_IPC(conn)) {
5253 call_trans2qpipeinfo(conn, req, tran_call,
5254 pparams, total_params,
5255 ppdata, total_data,
5256 max_data_bytes);
5257 return;
5260 fsp = file_fsp(req, SVAL(params,0));
5261 info_level = SVAL(params,2);
5263 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5265 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5266 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5267 return;
5270 /* Initial check for valid fsp ptr. */
5271 if (!check_fsp_open(conn, req, fsp)) {
5272 return;
5275 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5276 if (smb_fname == NULL) {
5277 reply_nterror(req, NT_STATUS_NO_MEMORY);
5278 return;
5281 if(fsp->fake_file_handle) {
5283 * This is actually for the QUOTA_FAKE_FILE --metze
5286 /* We know this name is ok, it's already passed the checks. */
5288 } else if(fsp->fh->fd == -1) {
5290 * This is actually a QFILEINFO on a directory
5291 * handle (returned from an NT SMB). NT5.0 seems
5292 * to do this call. JRA.
5295 if (INFO_LEVEL_IS_UNIX(info_level)) {
5296 /* Always do lstat for UNIX calls. */
5297 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "SMB_VFS_LSTAT of %s failed "
5300 "(%s)\n",
5301 smb_fname_str_dbg(smb_fname),
5302 strerror(errno)));
5303 reply_nterror(req,
5304 map_nt_error_from_unix(errno));
5305 return;
5307 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5308 DEBUG(3,("call_trans2qfilepathinfo: "
5309 "SMB_VFS_STAT of %s failed (%s)\n",
5310 smb_fname_str_dbg(smb_fname),
5311 strerror(errno)));
5312 reply_nterror(req,
5313 map_nt_error_from_unix(errno));
5314 return;
5317 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5318 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5319 } else {
5321 * Original code - this is an open file.
5323 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5324 DEBUG(3, ("fstat of %s failed (%s)\n",
5325 fsp_fnum_dbg(fsp), strerror(errno)));
5326 reply_nterror(req,
5327 map_nt_error_from_unix(errno));
5328 return;
5330 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5331 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5334 } else {
5335 uint32_t name_hash;
5336 char *fname = NULL;
5337 uint32_t ucf_flags = 0;
5339 /* qpathinfo */
5340 if (total_params < 7) {
5341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5342 return;
5345 info_level = SVAL(params,0);
5347 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5349 if (INFO_LEVEL_IS_UNIX(info_level)) {
5350 if (!lp_unix_extensions()) {
5351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5352 return;
5354 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5355 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5356 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5357 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5361 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5362 total_params - 6,
5363 STR_TERMINATE, &status);
5364 if (!NT_STATUS_IS_OK(status)) {
5365 reply_nterror(req, status);
5366 return;
5369 status = filename_convert(req,
5370 conn,
5371 req->flags2 & FLAGS2_DFS_PATHNAMES,
5372 fname,
5373 ucf_flags,
5374 NULL,
5375 &smb_fname);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5378 reply_botherror(req,
5379 NT_STATUS_PATH_NOT_COVERED,
5380 ERRSRV, ERRbadpath);
5381 return;
5383 reply_nterror(req, status);
5384 return;
5387 /* If this is a stream, check if there is a delete_pending. */
5388 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5389 && is_ntfs_stream_smb_fname(smb_fname)) {
5390 struct smb_filename *smb_fname_base;
5392 /* Create an smb_filename with stream_name == NULL. */
5393 smb_fname_base = synthetic_smb_fname(
5394 talloc_tos(), smb_fname->base_name,
5395 NULL, NULL);
5396 if (smb_fname_base == NULL) {
5397 reply_nterror(req, NT_STATUS_NO_MEMORY);
5398 return;
5401 if (INFO_LEVEL_IS_UNIX(info_level)) {
5402 /* Always do lstat for UNIX calls. */
5403 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5404 DEBUG(3,("call_trans2qfilepathinfo: "
5405 "SMB_VFS_LSTAT of %s failed "
5406 "(%s)\n",
5407 smb_fname_str_dbg(smb_fname_base),
5408 strerror(errno)));
5409 TALLOC_FREE(smb_fname_base);
5410 reply_nterror(req,
5411 map_nt_error_from_unix(errno));
5412 return;
5414 } else {
5415 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5416 DEBUG(3,("call_trans2qfilepathinfo: "
5417 "fileinfo of %s failed "
5418 "(%s)\n",
5419 smb_fname_str_dbg(smb_fname_base),
5420 strerror(errno)));
5421 TALLOC_FREE(smb_fname_base);
5422 reply_nterror(req,
5423 map_nt_error_from_unix(errno));
5424 return;
5428 status = file_name_hash(conn,
5429 smb_fname_str_dbg(smb_fname_base),
5430 &name_hash);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 TALLOC_FREE(smb_fname_base);
5433 reply_nterror(req, status);
5434 return;
5437 fileid = vfs_file_id_from_sbuf(conn,
5438 &smb_fname_base->st);
5439 TALLOC_FREE(smb_fname_base);
5440 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5441 if (delete_pending) {
5442 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5443 return;
5447 if (INFO_LEVEL_IS_UNIX(info_level)) {
5448 /* Always do lstat for UNIX calls. */
5449 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5450 DEBUG(3,("call_trans2qfilepathinfo: "
5451 "SMB_VFS_LSTAT of %s failed (%s)\n",
5452 smb_fname_str_dbg(smb_fname),
5453 strerror(errno)));
5454 reply_nterror(req,
5455 map_nt_error_from_unix(errno));
5456 return;
5459 } else {
5460 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5461 DEBUG(3,("call_trans2qfilepathinfo: "
5462 "SMB_VFS_STAT of %s failed (%s)\n",
5463 smb_fname_str_dbg(smb_fname),
5464 strerror(errno)));
5465 reply_nterror(req,
5466 map_nt_error_from_unix(errno));
5467 return;
5471 status = file_name_hash(conn,
5472 smb_fname_str_dbg(smb_fname),
5473 &name_hash);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 reply_nterror(req, status);
5476 return;
5479 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5480 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5481 if (delete_pending) {
5482 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5483 return;
5487 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5488 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5489 fsp_fnum_dbg(fsp),
5490 info_level,tran_call,total_data));
5492 /* Pull out any data sent here before we realloc. */
5493 switch (info_level) {
5494 case SMB_INFO_QUERY_EAS_FROM_LIST:
5496 /* Pull any EA list from the data portion. */
5497 uint32 ea_size;
5499 if (total_data < 4) {
5500 reply_nterror(
5501 req, NT_STATUS_INVALID_PARAMETER);
5502 return;
5504 ea_size = IVAL(pdata,0);
5506 if (total_data > 0 && ea_size != total_data) {
5507 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5508 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5509 reply_nterror(
5510 req, NT_STATUS_INVALID_PARAMETER);
5511 return;
5514 if (!lp_ea_support(SNUM(conn))) {
5515 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5516 return;
5519 /* Pull out the list of names. */
5520 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5521 if (!ea_list) {
5522 reply_nterror(
5523 req, NT_STATUS_INVALID_PARAMETER);
5524 return;
5526 break;
5529 case SMB_QUERY_POSIX_LOCK:
5531 if (fsp == NULL || fsp->fh->fd == -1) {
5532 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5533 return;
5536 if (total_data != POSIX_LOCK_DATA_SIZE) {
5537 reply_nterror(
5538 req, NT_STATUS_INVALID_PARAMETER);
5539 return;
5542 /* Copy the lock range data. */
5543 lock_data = (char *)talloc_memdup(
5544 req, pdata, total_data);
5545 if (!lock_data) {
5546 reply_nterror(req, NT_STATUS_NO_MEMORY);
5547 return;
5549 lock_data_count = total_data;
5551 default:
5552 break;
5555 *pparams = (char *)SMB_REALLOC(*pparams,2);
5556 if (*pparams == NULL) {
5557 reply_nterror(req, NT_STATUS_NO_MEMORY);
5558 return;
5560 params = *pparams;
5561 SSVAL(params,0,0);
5564 * draft-leach-cifs-v1-spec-02.txt
5565 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5566 * says:
5568 * The requested information is placed in the Data portion of the
5569 * transaction response. For the information levels greater than 0x100,
5570 * the transaction response has 1 parameter word which should be
5571 * ignored by the client.
5573 * However Windows only follows this rule for the IS_NAME_VALID call.
5575 switch (info_level) {
5576 case SMB_INFO_IS_NAME_VALID:
5577 param_size = 0;
5578 break;
5581 if ((info_level & 0xFF00) == 0xFF00) {
5583 * We use levels that start with 0xFF00
5584 * internally to represent SMB2 specific levels
5586 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5587 return;
5590 status = smbd_do_qfilepathinfo(conn, req, info_level,
5591 fsp, smb_fname,
5592 delete_pending, write_time_ts,
5593 ea_list,
5594 lock_data_count, lock_data,
5595 req->flags2, max_data_bytes,
5596 &fixed_portion,
5597 ppdata, &data_size);
5598 if (!NT_STATUS_IS_OK(status)) {
5599 reply_nterror(req, status);
5600 return;
5602 if (fixed_portion > max_data_bytes) {
5603 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5604 return;
5607 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5608 max_data_bytes);
5610 return;
5613 /****************************************************************************
5614 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5615 code.
5616 ****************************************************************************/
5618 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5619 connection_struct *conn,
5620 struct smb_request *req,
5621 bool overwrite_if_exists,
5622 const struct smb_filename *smb_fname_old,
5623 struct smb_filename *smb_fname_new)
5625 NTSTATUS status = NT_STATUS_OK;
5627 /* source must already exist. */
5628 if (!VALID_STAT(smb_fname_old->st)) {
5629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5632 if (VALID_STAT(smb_fname_new->st)) {
5633 if (overwrite_if_exists) {
5634 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5635 return NT_STATUS_FILE_IS_A_DIRECTORY;
5637 status = unlink_internals(conn,
5638 req,
5639 FILE_ATTRIBUTE_NORMAL,
5640 smb_fname_new,
5641 false);
5642 if (!NT_STATUS_IS_OK(status)) {
5643 return status;
5645 } else {
5646 /* Disallow if newname already exists. */
5647 return NT_STATUS_OBJECT_NAME_COLLISION;
5651 /* No links from a directory. */
5652 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5653 return NT_STATUS_FILE_IS_A_DIRECTORY;
5656 /* Setting a hardlink to/from a stream isn't currently supported. */
5657 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5658 is_ntfs_stream_smb_fname(smb_fname_new)) {
5659 return NT_STATUS_INVALID_PARAMETER;
5662 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5663 smb_fname_old->base_name, smb_fname_new->base_name));
5665 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5666 smb_fname_new->base_name) != 0) {
5667 status = map_nt_error_from_unix(errno);
5668 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5669 nt_errstr(status), smb_fname_old->base_name,
5670 smb_fname_new->base_name));
5672 return status;
5675 /****************************************************************************
5676 Deal with setting the time from any of the setfilepathinfo functions.
5677 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5678 calling this function.
5679 ****************************************************************************/
5681 NTSTATUS smb_set_file_time(connection_struct *conn,
5682 files_struct *fsp,
5683 const struct smb_filename *smb_fname,
5684 struct smb_file_time *ft,
5685 bool setting_write_time)
5687 struct smb_filename smb_fname_base;
5688 uint32 action =
5689 FILE_NOTIFY_CHANGE_LAST_ACCESS
5690 |FILE_NOTIFY_CHANGE_LAST_WRITE
5691 |FILE_NOTIFY_CHANGE_CREATION;
5693 if (!VALID_STAT(smb_fname->st)) {
5694 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5697 /* get some defaults (no modifications) if any info is zero or -1. */
5698 if (null_timespec(ft->create_time)) {
5699 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5702 if (null_timespec(ft->atime)) {
5703 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5706 if (null_timespec(ft->mtime)) {
5707 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5710 if (!setting_write_time) {
5711 /* ft->mtime comes from change time, not write time. */
5712 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5715 /* Ensure the resolution is the correct for
5716 * what we can store on this filesystem. */
5718 round_timespec(conn->ts_res, &ft->create_time);
5719 round_timespec(conn->ts_res, &ft->ctime);
5720 round_timespec(conn->ts_res, &ft->atime);
5721 round_timespec(conn->ts_res, &ft->mtime);
5723 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5724 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5725 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5726 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5727 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5728 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5729 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5730 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5732 if (setting_write_time) {
5734 * This was a Windows setfileinfo on an open file.
5735 * NT does this a lot. We also need to
5736 * set the time here, as it can be read by
5737 * FindFirst/FindNext and with the patch for bug #2045
5738 * in smbd/fileio.c it ensures that this timestamp is
5739 * kept sticky even after a write. We save the request
5740 * away and will set it on file close and after a write. JRA.
5743 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5744 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5746 if (fsp != NULL) {
5747 if (fsp->base_fsp) {
5748 set_sticky_write_time_fsp(fsp->base_fsp,
5749 ft->mtime);
5750 } else {
5751 set_sticky_write_time_fsp(fsp, ft->mtime);
5753 } else {
5754 set_sticky_write_time_path(
5755 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5756 ft->mtime);
5760 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5762 /* Always call ntimes on the base, even if a stream was passed in. */
5763 smb_fname_base = *smb_fname;
5764 smb_fname_base.stream_name = NULL;
5766 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5767 return map_nt_error_from_unix(errno);
5770 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5771 smb_fname->base_name);
5772 return NT_STATUS_OK;
5775 /****************************************************************************
5776 Deal with setting the dosmode from any of the setfilepathinfo functions.
5777 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5778 done before calling this function.
5779 ****************************************************************************/
5781 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5782 const struct smb_filename *smb_fname,
5783 uint32 dosmode)
5785 struct smb_filename *smb_fname_base;
5786 NTSTATUS status;
5788 if (!VALID_STAT(smb_fname->st)) {
5789 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5792 /* Always operate on the base_name, even if a stream was passed in. */
5793 smb_fname_base = synthetic_smb_fname(
5794 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5795 if (smb_fname_base == NULL) {
5796 return NT_STATUS_NO_MEMORY;
5799 if (dosmode) {
5800 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5801 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5802 } else {
5803 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5807 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5809 /* check the mode isn't different, before changing it */
5810 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5811 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5812 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5813 (unsigned int)dosmode));
5815 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5816 false)) {
5817 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5818 "%s failed (%s)\n",
5819 smb_fname_str_dbg(smb_fname_base),
5820 strerror(errno)));
5821 status = map_nt_error_from_unix(errno);
5822 goto out;
5825 status = NT_STATUS_OK;
5826 out:
5827 TALLOC_FREE(smb_fname_base);
5828 return status;
5831 /****************************************************************************
5832 Deal with setting the size from any of the setfilepathinfo functions.
5833 ****************************************************************************/
5835 static NTSTATUS smb_set_file_size(connection_struct *conn,
5836 struct smb_request *req,
5837 files_struct *fsp,
5838 const struct smb_filename *smb_fname,
5839 const SMB_STRUCT_STAT *psbuf,
5840 off_t size,
5841 bool fail_after_createfile)
5843 NTSTATUS status = NT_STATUS_OK;
5844 struct smb_filename *smb_fname_tmp = NULL;
5845 files_struct *new_fsp = NULL;
5847 if (!VALID_STAT(*psbuf)) {
5848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5851 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5853 if (size == get_file_size_stat(psbuf)) {
5854 return NT_STATUS_OK;
5857 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5858 smb_fname_str_dbg(smb_fname), (double)size));
5860 if (fsp && fsp->fh->fd != -1) {
5861 /* Handle based call. */
5862 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5863 return NT_STATUS_ACCESS_DENIED;
5866 if (vfs_set_filelen(fsp, size) == -1) {
5867 return map_nt_error_from_unix(errno);
5869 trigger_write_time_update_immediate(fsp);
5870 return NT_STATUS_OK;
5873 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5874 if (smb_fname_tmp == NULL) {
5875 return NT_STATUS_NO_MEMORY;
5878 smb_fname_tmp->st = *psbuf;
5880 status = SMB_VFS_CREATE_FILE(
5881 conn, /* conn */
5882 req, /* req */
5883 0, /* root_dir_fid */
5884 smb_fname_tmp, /* fname */
5885 FILE_WRITE_DATA, /* access_mask */
5886 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5887 FILE_SHARE_DELETE),
5888 FILE_OPEN, /* create_disposition*/
5889 0, /* create_options */
5890 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5891 0, /* oplock_request */
5892 0, /* allocation_size */
5893 0, /* private_flags */
5894 NULL, /* sd */
5895 NULL, /* ea_list */
5896 &new_fsp, /* result */
5897 NULL); /* pinfo */
5899 TALLOC_FREE(smb_fname_tmp);
5901 if (!NT_STATUS_IS_OK(status)) {
5902 /* NB. We check for open_was_deferred in the caller. */
5903 return status;
5906 /* See RAW-SFILEINFO-END-OF-FILE */
5907 if (fail_after_createfile) {
5908 close_file(req, new_fsp,NORMAL_CLOSE);
5909 return NT_STATUS_INVALID_LEVEL;
5912 if (vfs_set_filelen(new_fsp, size) == -1) {
5913 status = map_nt_error_from_unix(errno);
5914 close_file(req, new_fsp,NORMAL_CLOSE);
5915 return status;
5918 trigger_write_time_update_immediate(new_fsp);
5919 close_file(req, new_fsp,NORMAL_CLOSE);
5920 return NT_STATUS_OK;
5923 /****************************************************************************
5924 Deal with SMB_INFO_SET_EA.
5925 ****************************************************************************/
5927 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5928 const char *pdata,
5929 int total_data,
5930 files_struct *fsp,
5931 const struct smb_filename *smb_fname)
5933 struct ea_list *ea_list = NULL;
5934 TALLOC_CTX *ctx = NULL;
5935 NTSTATUS status = NT_STATUS_OK;
5937 if (total_data < 10) {
5939 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5940 length. They seem to have no effect. Bug #3212. JRA */
5942 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5943 /* We're done. We only get EA info in this call. */
5944 return NT_STATUS_OK;
5947 return NT_STATUS_INVALID_PARAMETER;
5950 if (IVAL(pdata,0) > total_data) {
5951 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5952 IVAL(pdata,0), (unsigned int)total_data));
5953 return NT_STATUS_INVALID_PARAMETER;
5956 ctx = talloc_tos();
5957 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5958 if (!ea_list) {
5959 return NT_STATUS_INVALID_PARAMETER;
5962 status = set_ea(conn, fsp, smb_fname, ea_list);
5964 return status;
5967 /****************************************************************************
5968 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5969 ****************************************************************************/
5971 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5972 const char *pdata,
5973 int total_data,
5974 files_struct *fsp)
5976 struct ea_list *ea_list = NULL;
5977 NTSTATUS status;
5979 if (!fsp) {
5980 return NT_STATUS_INVALID_HANDLE;
5983 if (!lp_ea_support(SNUM(conn))) {
5984 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5985 "EA's not supported.\n",
5986 (unsigned int)total_data));
5987 return NT_STATUS_EAS_NOT_SUPPORTED;
5990 if (total_data < 10) {
5991 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5992 "too small.\n",
5993 (unsigned int)total_data));
5994 return NT_STATUS_INVALID_PARAMETER;
5997 ea_list = read_nttrans_ea_list(talloc_tos(),
5998 pdata,
5999 total_data);
6001 if (!ea_list) {
6002 return NT_STATUS_INVALID_PARAMETER;
6005 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6007 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6008 smb_fname_str_dbg(fsp->fsp_name),
6009 nt_errstr(status) ));
6011 return status;
6015 /****************************************************************************
6016 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6017 ****************************************************************************/
6019 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6020 const char *pdata,
6021 int total_data,
6022 files_struct *fsp,
6023 struct smb_filename *smb_fname)
6025 NTSTATUS status = NT_STATUS_OK;
6026 bool delete_on_close;
6027 uint32 dosmode = 0;
6029 if (total_data < 1) {
6030 return NT_STATUS_INVALID_PARAMETER;
6033 if (fsp == NULL) {
6034 return NT_STATUS_INVALID_HANDLE;
6037 delete_on_close = (CVAL(pdata,0) ? True : False);
6038 dosmode = dos_mode(conn, smb_fname);
6040 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6041 "delete_on_close = %u\n",
6042 smb_fname_str_dbg(smb_fname),
6043 (unsigned int)dosmode,
6044 (unsigned int)delete_on_close ));
6046 if (delete_on_close) {
6047 status = can_set_delete_on_close(fsp, dosmode);
6048 if (!NT_STATUS_IS_OK(status)) {
6049 return status;
6053 /* The set is across all open files on this dev/inode pair. */
6054 if (!set_delete_on_close(fsp, delete_on_close,
6055 conn->session_info->security_token,
6056 conn->session_info->unix_token)) {
6057 return NT_STATUS_ACCESS_DENIED;
6059 return NT_STATUS_OK;
6062 /****************************************************************************
6063 Deal with SMB_FILE_POSITION_INFORMATION.
6064 ****************************************************************************/
6066 static NTSTATUS smb_file_position_information(connection_struct *conn,
6067 const char *pdata,
6068 int total_data,
6069 files_struct *fsp)
6071 uint64_t position_information;
6073 if (total_data < 8) {
6074 return NT_STATUS_INVALID_PARAMETER;
6077 if (fsp == NULL) {
6078 /* Ignore on pathname based set. */
6079 return NT_STATUS_OK;
6082 position_information = (uint64_t)IVAL(pdata,0);
6083 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6085 DEBUG(10,("smb_file_position_information: Set file position "
6086 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6087 (double)position_information));
6088 fsp->fh->position_information = position_information;
6089 return NT_STATUS_OK;
6092 /****************************************************************************
6093 Deal with SMB_FILE_MODE_INFORMATION.
6094 ****************************************************************************/
6096 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6097 const char *pdata,
6098 int total_data)
6100 uint32 mode;
6102 if (total_data < 4) {
6103 return NT_STATUS_INVALID_PARAMETER;
6105 mode = IVAL(pdata,0);
6106 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6107 return NT_STATUS_INVALID_PARAMETER;
6109 return NT_STATUS_OK;
6112 /****************************************************************************
6113 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6117 struct smb_request *req,
6118 const char *pdata,
6119 int total_data,
6120 const struct smb_filename *smb_fname)
6122 char *link_target = NULL;
6123 const char *newname = smb_fname->base_name;
6124 TALLOC_CTX *ctx = talloc_tos();
6126 /* Set a symbolic link. */
6127 /* Don't allow this if follow links is false. */
6129 if (total_data == 0) {
6130 return NT_STATUS_INVALID_PARAMETER;
6133 if (!lp_follow_symlinks(SNUM(conn))) {
6134 return NT_STATUS_ACCESS_DENIED;
6137 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6138 total_data, STR_TERMINATE);
6140 if (!link_target) {
6141 return NT_STATUS_INVALID_PARAMETER;
6144 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6145 newname, link_target ));
6147 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6148 return map_nt_error_from_unix(errno);
6151 return NT_STATUS_OK;
6154 /****************************************************************************
6155 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6156 ****************************************************************************/
6158 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6159 struct smb_request *req,
6160 const char *pdata, int total_data,
6161 struct smb_filename *smb_fname_new)
6163 char *oldname = NULL;
6164 struct smb_filename *smb_fname_old = NULL;
6165 TALLOC_CTX *ctx = talloc_tos();
6166 NTSTATUS status = NT_STATUS_OK;
6168 /* Set a hard link. */
6169 if (total_data == 0) {
6170 return NT_STATUS_INVALID_PARAMETER;
6173 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6174 total_data, STR_TERMINATE, &status);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 return status;
6179 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6180 smb_fname_str_dbg(smb_fname_new), oldname));
6182 status = filename_convert(ctx,
6183 conn,
6184 req->flags2 & FLAGS2_DFS_PATHNAMES,
6185 oldname,
6187 NULL,
6188 &smb_fname_old);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 return status;
6193 return hardlink_internals(ctx, conn, req, false,
6194 smb_fname_old, smb_fname_new);
6197 /****************************************************************************
6198 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6199 ****************************************************************************/
6201 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6202 struct smb_request *req,
6203 const char *pdata,
6204 int total_data,
6205 files_struct *fsp,
6206 struct smb_filename *smb_fname_src)
6208 bool overwrite;
6209 uint32_t len;
6210 char *newname = NULL;
6211 struct smb_filename *smb_fname_dst = NULL;
6212 NTSTATUS status = NT_STATUS_OK;
6213 TALLOC_CTX *ctx = talloc_tos();
6215 if (!fsp) {
6216 return NT_STATUS_INVALID_HANDLE;
6219 if (total_data < 20) {
6220 return NT_STATUS_INVALID_PARAMETER;
6223 overwrite = (CVAL(pdata,0) ? True : False);
6224 len = IVAL(pdata,16);
6226 if (len > (total_data - 20) || (len == 0)) {
6227 return NT_STATUS_INVALID_PARAMETER;
6230 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6231 &pdata[20], len, STR_TERMINATE,
6232 &status);
6233 if (!NT_STATUS_IS_OK(status)) {
6234 return status;
6237 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6238 newname));
6240 status = filename_convert(ctx,
6241 conn,
6242 req->flags2 & FLAGS2_DFS_PATHNAMES,
6243 newname,
6244 UCF_SAVE_LCOMP,
6245 NULL,
6246 &smb_fname_dst);
6247 if (!NT_STATUS_IS_OK(status)) {
6248 return status;
6251 if (fsp->base_fsp) {
6252 /* newname must be a stream name. */
6253 if (newname[0] != ':') {
6254 return NT_STATUS_NOT_SUPPORTED;
6257 /* Create an smb_fname to call rename_internals_fsp() with. */
6258 smb_fname_dst = synthetic_smb_fname(
6259 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6260 newname, NULL);
6261 if (smb_fname_dst == NULL) {
6262 status = NT_STATUS_NO_MEMORY;
6263 goto out;
6267 * Set the original last component, since
6268 * rename_internals_fsp() requires it.
6270 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6271 newname);
6272 if (smb_fname_dst->original_lcomp == NULL) {
6273 status = NT_STATUS_NO_MEMORY;
6274 goto out;
6279 DEBUG(10,("smb2_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6281 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6282 smb_fname_str_dbg(smb_fname_dst)));
6283 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6284 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6285 overwrite);
6287 out:
6288 TALLOC_FREE(smb_fname_dst);
6289 return status;
6292 static NTSTATUS smb_file_link_information(connection_struct *conn,
6293 struct smb_request *req,
6294 const char *pdata,
6295 int total_data,
6296 files_struct *fsp,
6297 struct smb_filename *smb_fname_src)
6299 bool overwrite;
6300 uint32_t len;
6301 char *newname = NULL;
6302 struct smb_filename *smb_fname_dst = NULL;
6303 NTSTATUS status = NT_STATUS_OK;
6304 TALLOC_CTX *ctx = talloc_tos();
6306 if (!fsp) {
6307 return NT_STATUS_INVALID_HANDLE;
6310 if (total_data < 20) {
6311 return NT_STATUS_INVALID_PARAMETER;
6314 overwrite = (CVAL(pdata,0) ? true : false);
6315 len = IVAL(pdata,16);
6317 if (len > (total_data - 20) || (len == 0)) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6322 &pdata[20], len, STR_TERMINATE,
6323 &status);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 return status;
6328 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6329 newname));
6331 status = filename_convert(ctx,
6332 conn,
6333 req->flags2 & FLAGS2_DFS_PATHNAMES,
6334 newname,
6335 UCF_SAVE_LCOMP,
6336 NULL,
6337 &smb_fname_dst);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 return status;
6342 if (fsp->base_fsp) {
6343 /* No stream names. */
6344 return NT_STATUS_NOT_SUPPORTED;
6347 DEBUG(10,("smb_file_link_information: "
6348 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6349 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6350 smb_fname_str_dbg(smb_fname_dst)));
6351 status = hardlink_internals(ctx,
6352 conn,
6353 req,
6354 overwrite,
6355 fsp->fsp_name,
6356 smb_fname_dst);
6358 TALLOC_FREE(smb_fname_dst);
6359 return status;
6362 /****************************************************************************
6363 Deal with SMB_FILE_RENAME_INFORMATION.
6364 ****************************************************************************/
6366 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6367 struct smb_request *req,
6368 const char *pdata,
6369 int total_data,
6370 files_struct *fsp,
6371 struct smb_filename *smb_fname_src)
6373 bool overwrite;
6374 uint32 root_fid;
6375 uint32 len;
6376 char *newname = NULL;
6377 struct smb_filename *smb_fname_dst = NULL;
6378 bool dest_has_wcard = False;
6379 NTSTATUS status = NT_STATUS_OK;
6380 char *p;
6381 TALLOC_CTX *ctx = talloc_tos();
6383 if (total_data < 13) {
6384 return NT_STATUS_INVALID_PARAMETER;
6387 overwrite = (CVAL(pdata,0) ? True : False);
6388 root_fid = IVAL(pdata,4);
6389 len = IVAL(pdata,8);
6391 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6392 return NT_STATUS_INVALID_PARAMETER;
6395 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6396 len, 0, &status,
6397 &dest_has_wcard);
6398 if (!NT_STATUS_IS_OK(status)) {
6399 return status;
6402 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6403 newname));
6405 status = resolve_dfspath_wcard(ctx, conn,
6406 req->flags2 & FLAGS2_DFS_PATHNAMES,
6407 newname,
6408 true,
6409 !conn->sconn->using_smb2,
6410 &newname,
6411 &dest_has_wcard);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 return status;
6416 /* Check the new name has no '/' characters. */
6417 if (strchr_m(newname, '/')) {
6418 return NT_STATUS_NOT_SUPPORTED;
6421 if (fsp && fsp->base_fsp) {
6422 /* newname must be a stream name. */
6423 if (newname[0] != ':') {
6424 return NT_STATUS_NOT_SUPPORTED;
6427 /* Create an smb_fname to call rename_internals_fsp() with. */
6428 smb_fname_dst = synthetic_smb_fname(
6429 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6430 newname, NULL);
6431 if (smb_fname_dst == NULL) {
6432 status = NT_STATUS_NO_MEMORY;
6433 goto out;
6437 * Set the original last component, since
6438 * rename_internals_fsp() requires it.
6440 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6441 newname);
6442 if (smb_fname_dst->original_lcomp == NULL) {
6443 status = NT_STATUS_NO_MEMORY;
6444 goto out;
6447 } else {
6449 * Build up an smb_fname_dst based on the filename passed in.
6450 * We basically just strip off the last component, and put on
6451 * the newname instead.
6453 char *base_name = NULL;
6455 /* newname must *not* be a stream name. */
6456 if (newname[0] == ':') {
6457 return NT_STATUS_NOT_SUPPORTED;
6461 * Strip off the last component (filename) of the path passed
6462 * in.
6464 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6465 if (!base_name) {
6466 return NT_STATUS_NO_MEMORY;
6468 p = strrchr_m(base_name, '/');
6469 if (p) {
6470 p[1] = '\0';
6471 } else {
6472 base_name = talloc_strdup(ctx, "");
6473 if (!base_name) {
6474 return NT_STATUS_NO_MEMORY;
6477 /* Append the new name. */
6478 base_name = talloc_asprintf_append(base_name,
6479 "%s",
6480 newname);
6481 if (!base_name) {
6482 return NT_STATUS_NO_MEMORY;
6485 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6486 (UCF_SAVE_LCOMP |
6487 (dest_has_wcard ?
6488 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6489 0)));
6491 /* If an error we expect this to be
6492 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6494 if (!NT_STATUS_IS_OK(status)) {
6495 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6496 status)) {
6497 goto out;
6499 /* Create an smb_fname to call rename_internals_fsp() */
6500 smb_fname_dst = synthetic_smb_fname(
6501 ctx, base_name, NULL, NULL);
6502 if (smb_fname_dst == NULL) {
6503 status = NT_STATUS_NO_MEMORY;
6504 goto out;
6509 if (fsp) {
6510 DEBUG(10,("smb_file_rename_information: "
6511 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6512 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6513 smb_fname_str_dbg(smb_fname_dst)));
6514 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6515 overwrite);
6516 } else {
6517 DEBUG(10,("smb_file_rename_information: "
6518 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6519 smb_fname_str_dbg(smb_fname_src),
6520 smb_fname_str_dbg(smb_fname_dst)));
6521 status = rename_internals(ctx, conn, req, smb_fname_src,
6522 smb_fname_dst, 0, overwrite, false,
6523 dest_has_wcard,
6524 FILE_WRITE_ATTRIBUTES);
6526 out:
6527 TALLOC_FREE(smb_fname_dst);
6528 return status;
6531 /****************************************************************************
6532 Deal with SMB_SET_POSIX_ACL.
6533 ****************************************************************************/
6535 #if defined(HAVE_POSIX_ACLS)
6536 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6537 const char *pdata,
6538 int total_data,
6539 files_struct *fsp,
6540 const struct smb_filename *smb_fname)
6542 uint16 posix_acl_version;
6543 uint16 num_file_acls;
6544 uint16 num_def_acls;
6545 bool valid_file_acls = True;
6546 bool valid_def_acls = True;
6548 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6549 return NT_STATUS_INVALID_PARAMETER;
6551 posix_acl_version = SVAL(pdata,0);
6552 num_file_acls = SVAL(pdata,2);
6553 num_def_acls = SVAL(pdata,4);
6555 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6556 valid_file_acls = False;
6557 num_file_acls = 0;
6560 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6561 valid_def_acls = False;
6562 num_def_acls = 0;
6565 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6570 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6571 return NT_STATUS_INVALID_PARAMETER;
6574 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6575 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6576 (unsigned int)num_file_acls,
6577 (unsigned int)num_def_acls));
6579 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6580 smb_fname->base_name, num_file_acls,
6581 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6582 return map_nt_error_from_unix(errno);
6585 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6586 smb_fname->base_name, &smb_fname->st, num_def_acls,
6587 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6588 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6589 return map_nt_error_from_unix(errno);
6591 return NT_STATUS_OK;
6593 #endif
6595 /****************************************************************************
6596 Deal with SMB_SET_POSIX_LOCK.
6597 ****************************************************************************/
6599 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6600 struct smb_request *req,
6601 const char *pdata,
6602 int total_data,
6603 files_struct *fsp)
6605 uint64_t count;
6606 uint64_t offset;
6607 uint64_t smblctx;
6608 bool blocking_lock = False;
6609 enum brl_type lock_type;
6611 NTSTATUS status = NT_STATUS_OK;
6613 if (fsp == NULL || fsp->fh->fd == -1) {
6614 return NT_STATUS_INVALID_HANDLE;
6617 if (total_data != POSIX_LOCK_DATA_SIZE) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6622 case POSIX_LOCK_TYPE_READ:
6623 lock_type = READ_LOCK;
6624 break;
6625 case POSIX_LOCK_TYPE_WRITE:
6626 /* Return the right POSIX-mappable error code for files opened read-only. */
6627 if (!fsp->can_write) {
6628 return NT_STATUS_INVALID_HANDLE;
6630 lock_type = WRITE_LOCK;
6631 break;
6632 case POSIX_LOCK_TYPE_UNLOCK:
6633 lock_type = UNLOCK_LOCK;
6634 break;
6635 default:
6636 return NT_STATUS_INVALID_PARAMETER;
6639 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6640 blocking_lock = False;
6641 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6642 blocking_lock = True;
6643 } else {
6644 return NT_STATUS_INVALID_PARAMETER;
6647 if (!lp_blocking_locks(SNUM(conn))) {
6648 blocking_lock = False;
6651 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6652 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6653 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6654 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6655 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6657 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6658 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6659 fsp_str_dbg(fsp),
6660 (unsigned int)lock_type,
6661 (unsigned long long)smblctx,
6662 (double)count,
6663 (double)offset ));
6665 if (lock_type == UNLOCK_LOCK) {
6666 status = do_unlock(req->sconn->msg_ctx,
6667 fsp,
6668 smblctx,
6669 count,
6670 offset,
6671 POSIX_LOCK);
6672 } else {
6673 uint64_t block_smblctx;
6675 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6676 fsp,
6677 smblctx,
6678 count,
6679 offset,
6680 lock_type,
6681 POSIX_LOCK,
6682 blocking_lock,
6683 &status,
6684 &block_smblctx);
6686 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6688 * A blocking lock was requested. Package up
6689 * this smb into a queued request and push it
6690 * onto the blocking lock queue.
6692 if(push_blocking_lock_request(br_lck,
6693 req,
6694 fsp,
6695 -1, /* infinite timeout. */
6697 smblctx,
6698 lock_type,
6699 POSIX_LOCK,
6700 offset,
6701 count,
6702 block_smblctx)) {
6703 TALLOC_FREE(br_lck);
6704 return status;
6707 TALLOC_FREE(br_lck);
6710 return status;
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_BASIC_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6718 const char *pdata,
6719 int total_data,
6720 files_struct *fsp,
6721 const struct smb_filename *smb_fname)
6723 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6724 struct smb_file_time ft;
6725 uint32 dosmode = 0;
6726 NTSTATUS status = NT_STATUS_OK;
6728 ZERO_STRUCT(ft);
6730 if (total_data < 36) {
6731 return NT_STATUS_INVALID_PARAMETER;
6734 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 return status;
6739 /* Set the attributes */
6740 dosmode = IVAL(pdata,32);
6741 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 return status;
6746 /* create time */
6747 ft.create_time = interpret_long_date(pdata);
6749 /* access time */
6750 ft.atime = interpret_long_date(pdata+8);
6752 /* write time. */
6753 ft.mtime = interpret_long_date(pdata+16);
6755 /* change time. */
6756 ft.ctime = interpret_long_date(pdata+24);
6758 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6759 smb_fname_str_dbg(smb_fname)));
6761 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6762 true);
6765 /****************************************************************************
6766 Deal with SMB_INFO_STANDARD.
6767 ****************************************************************************/
6769 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6770 const char *pdata,
6771 int total_data,
6772 files_struct *fsp,
6773 const struct smb_filename *smb_fname)
6775 NTSTATUS status;
6776 struct smb_file_time ft;
6778 ZERO_STRUCT(ft);
6780 if (total_data < 12) {
6781 return NT_STATUS_INVALID_PARAMETER;
6784 /* create time */
6785 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6786 /* access time */
6787 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6788 /* write time */
6789 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6791 DEBUG(10,("smb_set_info_standard: file %s\n",
6792 smb_fname_str_dbg(smb_fname)));
6794 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 return status;
6799 return smb_set_file_time(conn,
6800 fsp,
6801 smb_fname,
6802 &ft,
6803 true);
6806 /****************************************************************************
6807 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6808 ****************************************************************************/
6810 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6811 struct smb_request *req,
6812 const char *pdata,
6813 int total_data,
6814 files_struct *fsp,
6815 struct smb_filename *smb_fname)
6817 uint64_t allocation_size = 0;
6818 NTSTATUS status = NT_STATUS_OK;
6819 files_struct *new_fsp = NULL;
6821 if (!VALID_STAT(smb_fname->st)) {
6822 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6825 if (total_data < 8) {
6826 return NT_STATUS_INVALID_PARAMETER;
6829 allocation_size = (uint64_t)IVAL(pdata,0);
6830 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6831 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6832 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6833 (double)allocation_size));
6835 if (allocation_size) {
6836 allocation_size = smb_roundup(conn, allocation_size);
6839 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6840 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6841 (double)allocation_size));
6843 if (fsp && fsp->fh->fd != -1) {
6844 /* Open file handle. */
6845 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6846 return NT_STATUS_ACCESS_DENIED;
6849 /* Only change if needed. */
6850 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6851 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6852 return map_nt_error_from_unix(errno);
6855 /* But always update the time. */
6857 * This is equivalent to a write. Ensure it's seen immediately
6858 * if there are no pending writes.
6860 trigger_write_time_update_immediate(fsp);
6861 return NT_STATUS_OK;
6864 /* Pathname or stat or directory file. */
6865 status = SMB_VFS_CREATE_FILE(
6866 conn, /* conn */
6867 req, /* req */
6868 0, /* root_dir_fid */
6869 smb_fname, /* fname */
6870 FILE_WRITE_DATA, /* access_mask */
6871 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6872 FILE_SHARE_DELETE),
6873 FILE_OPEN, /* create_disposition*/
6874 0, /* create_options */
6875 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6876 0, /* oplock_request */
6877 0, /* allocation_size */
6878 0, /* private_flags */
6879 NULL, /* sd */
6880 NULL, /* ea_list */
6881 &new_fsp, /* result */
6882 NULL); /* pinfo */
6884 if (!NT_STATUS_IS_OK(status)) {
6885 /* NB. We check for open_was_deferred in the caller. */
6886 return status;
6889 /* Only change if needed. */
6890 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6891 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6892 status = map_nt_error_from_unix(errno);
6893 close_file(req, new_fsp, NORMAL_CLOSE);
6894 return status;
6898 /* Changing the allocation size should set the last mod time. */
6900 * This is equivalent to a write. Ensure it's seen immediately
6901 * if there are no pending writes.
6903 trigger_write_time_update_immediate(new_fsp);
6904 close_file(req, new_fsp, NORMAL_CLOSE);
6905 return NT_STATUS_OK;
6908 /****************************************************************************
6909 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6910 ****************************************************************************/
6912 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6913 struct smb_request *req,
6914 const char *pdata,
6915 int total_data,
6916 files_struct *fsp,
6917 const struct smb_filename *smb_fname,
6918 bool fail_after_createfile)
6920 off_t size;
6922 if (total_data < 8) {
6923 return NT_STATUS_INVALID_PARAMETER;
6926 size = IVAL(pdata,0);
6927 size |= (((off_t)IVAL(pdata,4)) << 32);
6928 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6929 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6930 (double)size));
6932 return smb_set_file_size(conn, req,
6933 fsp,
6934 smb_fname,
6935 &smb_fname->st,
6936 size,
6937 fail_after_createfile);
6940 /****************************************************************************
6941 Allow a UNIX info mknod.
6942 ****************************************************************************/
6944 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6945 const char *pdata,
6946 int total_data,
6947 const struct smb_filename *smb_fname)
6949 uint32 file_type = IVAL(pdata,56);
6950 #if defined(HAVE_MAKEDEV)
6951 uint32 dev_major = IVAL(pdata,60);
6952 uint32 dev_minor = IVAL(pdata,68);
6953 #endif
6954 SMB_DEV_T dev = (SMB_DEV_T)0;
6955 uint32 raw_unixmode = IVAL(pdata,84);
6956 NTSTATUS status;
6957 mode_t unixmode;
6959 if (total_data < 100) {
6960 return NT_STATUS_INVALID_PARAMETER;
6963 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6964 PERM_NEW_FILE, &unixmode);
6965 if (!NT_STATUS_IS_OK(status)) {
6966 return status;
6969 #if defined(HAVE_MAKEDEV)
6970 dev = makedev(dev_major, dev_minor);
6971 #endif
6973 switch (file_type) {
6974 #if defined(S_IFIFO)
6975 case UNIX_TYPE_FIFO:
6976 unixmode |= S_IFIFO;
6977 break;
6978 #endif
6979 #if defined(S_IFSOCK)
6980 case UNIX_TYPE_SOCKET:
6981 unixmode |= S_IFSOCK;
6982 break;
6983 #endif
6984 #if defined(S_IFCHR)
6985 case UNIX_TYPE_CHARDEV:
6986 unixmode |= S_IFCHR;
6987 break;
6988 #endif
6989 #if defined(S_IFBLK)
6990 case UNIX_TYPE_BLKDEV:
6991 unixmode |= S_IFBLK;
6992 break;
6993 #endif
6994 default:
6995 return NT_STATUS_INVALID_PARAMETER;
6998 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6999 "%.0f mode 0%o for file %s\n", (double)dev,
7000 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7002 /* Ok - do the mknod. */
7003 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7004 return map_nt_error_from_unix(errno);
7007 /* If any of the other "set" calls fail we
7008 * don't want to end up with a half-constructed mknod.
7011 if (lp_inherit_permissions(SNUM(conn))) {
7012 char *parent;
7013 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7014 &parent, NULL)) {
7015 return NT_STATUS_NO_MEMORY;
7017 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7018 unixmode);
7019 TALLOC_FREE(parent);
7022 return NT_STATUS_OK;
7025 /****************************************************************************
7026 Deal with SMB_SET_FILE_UNIX_BASIC.
7027 ****************************************************************************/
7029 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7030 struct smb_request *req,
7031 const char *pdata,
7032 int total_data,
7033 files_struct *fsp,
7034 const struct smb_filename *smb_fname)
7036 struct smb_file_time ft;
7037 uint32 raw_unixmode;
7038 mode_t unixmode;
7039 off_t size = 0;
7040 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7041 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7042 NTSTATUS status = NT_STATUS_OK;
7043 bool delete_on_fail = False;
7044 enum perm_type ptype;
7045 files_struct *all_fsps = NULL;
7046 bool modify_mtime = true;
7047 struct file_id id;
7048 struct smb_filename *smb_fname_tmp = NULL;
7049 SMB_STRUCT_STAT sbuf;
7051 ZERO_STRUCT(ft);
7053 if (total_data < 100) {
7054 return NT_STATUS_INVALID_PARAMETER;
7057 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7058 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7059 size=IVAL(pdata,0); /* first 8 Bytes are size */
7060 size |= (((off_t)IVAL(pdata,4)) << 32);
7063 ft.atime = interpret_long_date(pdata+24); /* access_time */
7064 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7065 set_owner = (uid_t)IVAL(pdata,40);
7066 set_grp = (gid_t)IVAL(pdata,48);
7067 raw_unixmode = IVAL(pdata,84);
7069 if (VALID_STAT(smb_fname->st)) {
7070 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7071 ptype = PERM_EXISTING_DIR;
7072 } else {
7073 ptype = PERM_EXISTING_FILE;
7075 } else {
7076 ptype = PERM_NEW_FILE;
7079 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7080 ptype, &unixmode);
7081 if (!NT_STATUS_IS_OK(status)) {
7082 return status;
7085 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7086 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7087 smb_fname_str_dbg(smb_fname), (double)size,
7088 (unsigned int)set_owner, (unsigned int)set_grp,
7089 (int)raw_unixmode));
7091 sbuf = smb_fname->st;
7093 if (!VALID_STAT(sbuf)) {
7095 * The only valid use of this is to create character and block
7096 * devices, and named pipes. This is deprecated (IMHO) and
7097 * a new info level should be used for mknod. JRA.
7100 status = smb_unix_mknod(conn,
7101 pdata,
7102 total_data,
7103 smb_fname);
7104 if (!NT_STATUS_IS_OK(status)) {
7105 return status;
7108 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7109 if (smb_fname_tmp == NULL) {
7110 return NT_STATUS_NO_MEMORY;
7113 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7114 status = map_nt_error_from_unix(errno);
7115 TALLOC_FREE(smb_fname_tmp);
7116 SMB_VFS_UNLINK(conn, smb_fname);
7117 return status;
7120 sbuf = smb_fname_tmp->st;
7121 smb_fname = smb_fname_tmp;
7123 /* Ensure we don't try and change anything else. */
7124 raw_unixmode = SMB_MODE_NO_CHANGE;
7125 size = get_file_size_stat(&sbuf);
7126 ft.atime = sbuf.st_ex_atime;
7127 ft.mtime = sbuf.st_ex_mtime;
7129 * We continue here as we might want to change the
7130 * owner uid/gid.
7132 delete_on_fail = True;
7135 #if 1
7136 /* Horrible backwards compatibility hack as an old server bug
7137 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7138 * */
7140 if (!size) {
7141 size = get_file_size_stat(&sbuf);
7143 #endif
7146 * Deal with the UNIX specific mode set.
7149 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7150 int ret;
7152 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7153 "setting mode 0%o for file %s\n",
7154 (unsigned int)unixmode,
7155 smb_fname_str_dbg(smb_fname)));
7156 if (fsp && fsp->fh->fd != -1) {
7157 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7158 } else {
7159 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7161 if (ret != 0) {
7162 return map_nt_error_from_unix(errno);
7167 * Deal with the UNIX specific uid set.
7170 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7171 (sbuf.st_ex_uid != set_owner)) {
7172 int ret;
7174 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7175 "changing owner %u for path %s\n",
7176 (unsigned int)set_owner,
7177 smb_fname_str_dbg(smb_fname)));
7179 if (fsp && fsp->fh->fd != -1) {
7180 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7181 } else {
7183 * UNIX extensions calls must always operate
7184 * on symlinks.
7186 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7187 set_owner, (gid_t)-1);
7190 if (ret != 0) {
7191 status = map_nt_error_from_unix(errno);
7192 if (delete_on_fail) {
7193 SMB_VFS_UNLINK(conn, smb_fname);
7195 return status;
7200 * Deal with the UNIX specific gid set.
7203 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7204 (sbuf.st_ex_gid != set_grp)) {
7205 int ret;
7207 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7208 "changing group %u for file %s\n",
7209 (unsigned int)set_owner,
7210 smb_fname_str_dbg(smb_fname)));
7211 if (fsp && fsp->fh->fd != -1) {
7212 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7213 } else {
7215 * UNIX extensions calls must always operate
7216 * on symlinks.
7218 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7219 set_grp);
7221 if (ret != 0) {
7222 status = map_nt_error_from_unix(errno);
7223 if (delete_on_fail) {
7224 SMB_VFS_UNLINK(conn, smb_fname);
7226 return status;
7230 /* Deal with any size changes. */
7232 status = smb_set_file_size(conn, req,
7233 fsp,
7234 smb_fname,
7235 &sbuf,
7236 size,
7237 false);
7238 if (!NT_STATUS_IS_OK(status)) {
7239 return status;
7242 /* Deal with any time changes. */
7243 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7244 /* No change, don't cancel anything. */
7245 return status;
7248 id = vfs_file_id_from_sbuf(conn, &sbuf);
7249 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7250 all_fsps = file_find_di_next(all_fsps)) {
7252 * We're setting the time explicitly for UNIX.
7253 * Cancel any pending changes over all handles.
7255 all_fsps->update_write_time_on_close = false;
7256 TALLOC_FREE(all_fsps->update_write_time_event);
7260 * Override the "setting_write_time"
7261 * parameter here as it almost does what
7262 * we need. Just remember if we modified
7263 * mtime and send the notify ourselves.
7265 if (null_timespec(ft.mtime)) {
7266 modify_mtime = false;
7269 status = smb_set_file_time(conn,
7270 fsp,
7271 smb_fname,
7272 &ft,
7273 false);
7274 if (modify_mtime) {
7275 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7276 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7278 return status;
7281 /****************************************************************************
7282 Deal with SMB_SET_FILE_UNIX_INFO2.
7283 ****************************************************************************/
7285 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7286 struct smb_request *req,
7287 const char *pdata,
7288 int total_data,
7289 files_struct *fsp,
7290 const struct smb_filename *smb_fname)
7292 NTSTATUS status;
7293 uint32 smb_fflags;
7294 uint32 smb_fmask;
7296 if (total_data < 116) {
7297 return NT_STATUS_INVALID_PARAMETER;
7300 /* Start by setting all the fields that are common between UNIX_BASIC
7301 * and UNIX_INFO2.
7303 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7304 fsp, smb_fname);
7305 if (!NT_STATUS_IS_OK(status)) {
7306 return status;
7309 smb_fflags = IVAL(pdata, 108);
7310 smb_fmask = IVAL(pdata, 112);
7312 /* NB: We should only attempt to alter the file flags if the client
7313 * sends a non-zero mask.
7315 if (smb_fmask != 0) {
7316 int stat_fflags = 0;
7318 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7319 smb_fmask, &stat_fflags)) {
7320 /* Client asked to alter a flag we don't understand. */
7321 return NT_STATUS_INVALID_PARAMETER;
7324 if (fsp && fsp->fh->fd != -1) {
7325 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7326 return NT_STATUS_NOT_SUPPORTED;
7327 } else {
7328 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7329 stat_fflags) != 0) {
7330 return map_nt_error_from_unix(errno);
7335 /* XXX: need to add support for changing the create_time here. You
7336 * can do this for paths on Darwin with setattrlist(2). The right way
7337 * to hook this up is probably by extending the VFS utimes interface.
7340 return NT_STATUS_OK;
7343 /****************************************************************************
7344 Create a directory with POSIX semantics.
7345 ****************************************************************************/
7347 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7348 struct smb_request *req,
7349 char **ppdata,
7350 int total_data,
7351 struct smb_filename *smb_fname,
7352 int *pdata_return_size)
7354 NTSTATUS status = NT_STATUS_OK;
7355 uint32 raw_unixmode = 0;
7356 uint32 mod_unixmode = 0;
7357 mode_t unixmode = (mode_t)0;
7358 files_struct *fsp = NULL;
7359 uint16 info_level_return = 0;
7360 int info;
7361 char *pdata = *ppdata;
7363 if (total_data < 18) {
7364 return NT_STATUS_INVALID_PARAMETER;
7367 raw_unixmode = IVAL(pdata,8);
7368 /* Next 4 bytes are not yet defined. */
7370 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7371 PERM_NEW_DIR, &unixmode);
7372 if (!NT_STATUS_IS_OK(status)) {
7373 return status;
7376 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7378 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7379 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7381 status = SMB_VFS_CREATE_FILE(
7382 conn, /* conn */
7383 req, /* req */
7384 0, /* root_dir_fid */
7385 smb_fname, /* fname */
7386 FILE_READ_ATTRIBUTES, /* access_mask */
7387 FILE_SHARE_NONE, /* share_access */
7388 FILE_CREATE, /* create_disposition*/
7389 FILE_DIRECTORY_FILE, /* create_options */
7390 mod_unixmode, /* file_attributes */
7391 0, /* oplock_request */
7392 0, /* allocation_size */
7393 0, /* private_flags */
7394 NULL, /* sd */
7395 NULL, /* ea_list */
7396 &fsp, /* result */
7397 &info); /* pinfo */
7399 if (NT_STATUS_IS_OK(status)) {
7400 close_file(req, fsp, NORMAL_CLOSE);
7403 info_level_return = SVAL(pdata,16);
7405 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7406 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7407 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7408 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7409 } else {
7410 *pdata_return_size = 12;
7413 /* Realloc the data size */
7414 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7415 if (*ppdata == NULL) {
7416 *pdata_return_size = 0;
7417 return NT_STATUS_NO_MEMORY;
7419 pdata = *ppdata;
7421 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7422 SSVAL(pdata,2,0); /* No fnum. */
7423 SIVAL(pdata,4,info); /* Was directory created. */
7425 switch (info_level_return) {
7426 case SMB_QUERY_FILE_UNIX_BASIC:
7427 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7428 SSVAL(pdata,10,0); /* Padding. */
7429 store_file_unix_basic(conn, pdata + 12, fsp,
7430 &smb_fname->st);
7431 break;
7432 case SMB_QUERY_FILE_UNIX_INFO2:
7433 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7434 SSVAL(pdata,10,0); /* Padding. */
7435 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7436 &smb_fname->st);
7437 break;
7438 default:
7439 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7440 SSVAL(pdata,10,0); /* Padding. */
7441 break;
7444 return status;
7447 /****************************************************************************
7448 Open/Create a file with POSIX semantics.
7449 ****************************************************************************/
7451 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7452 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7454 static NTSTATUS smb_posix_open(connection_struct *conn,
7455 struct smb_request *req,
7456 char **ppdata,
7457 int total_data,
7458 struct smb_filename *smb_fname,
7459 int *pdata_return_size)
7461 bool extended_oplock_granted = False;
7462 char *pdata = *ppdata;
7463 uint32 flags = 0;
7464 uint32 wire_open_mode = 0;
7465 uint32 raw_unixmode = 0;
7466 uint32 mod_unixmode = 0;
7467 uint32 create_disp = 0;
7468 uint32 access_mask = 0;
7469 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7470 NTSTATUS status = NT_STATUS_OK;
7471 mode_t unixmode = (mode_t)0;
7472 files_struct *fsp = NULL;
7473 int oplock_request = 0;
7474 int info = 0;
7475 uint16 info_level_return = 0;
7477 if (total_data < 18) {
7478 return NT_STATUS_INVALID_PARAMETER;
7481 flags = IVAL(pdata,0);
7482 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7483 if (oplock_request) {
7484 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7487 wire_open_mode = IVAL(pdata,4);
7489 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7490 return smb_posix_mkdir(conn, req,
7491 ppdata,
7492 total_data,
7493 smb_fname,
7494 pdata_return_size);
7497 switch (wire_open_mode & SMB_ACCMODE) {
7498 case SMB_O_RDONLY:
7499 access_mask = SMB_O_RDONLY_MAPPING;
7500 break;
7501 case SMB_O_WRONLY:
7502 access_mask = SMB_O_WRONLY_MAPPING;
7503 break;
7504 case SMB_O_RDWR:
7505 access_mask = (SMB_O_RDONLY_MAPPING|
7506 SMB_O_WRONLY_MAPPING);
7507 break;
7508 default:
7509 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7510 (unsigned int)wire_open_mode ));
7511 return NT_STATUS_INVALID_PARAMETER;
7514 wire_open_mode &= ~SMB_ACCMODE;
7516 /* First take care of O_CREAT|O_EXCL interactions. */
7517 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7518 case (SMB_O_CREAT | SMB_O_EXCL):
7519 /* File exists fail. File not exist create. */
7520 create_disp = FILE_CREATE;
7521 break;
7522 case SMB_O_CREAT:
7523 /* File exists open. File not exist create. */
7524 create_disp = FILE_OPEN_IF;
7525 break;
7526 case SMB_O_EXCL:
7527 /* O_EXCL on its own without O_CREAT is undefined.
7528 We deliberately ignore it as some versions of
7529 Linux CIFSFS can send a bare O_EXCL on the
7530 wire which other filesystems in the kernel
7531 ignore. See bug 9519 for details. */
7533 /* Fallthrough. */
7535 case 0:
7536 /* File exists open. File not exist fail. */
7537 create_disp = FILE_OPEN;
7538 break;
7539 default:
7540 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7541 (unsigned int)wire_open_mode ));
7542 return NT_STATUS_INVALID_PARAMETER;
7545 /* Next factor in the effects of O_TRUNC. */
7546 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7548 if (wire_open_mode & SMB_O_TRUNC) {
7549 switch (create_disp) {
7550 case FILE_CREATE:
7551 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7552 /* Leave create_disp alone as
7553 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7555 /* File exists fail. File not exist create. */
7556 break;
7557 case FILE_OPEN_IF:
7558 /* SMB_O_CREAT | SMB_O_TRUNC */
7559 /* File exists overwrite. File not exist create. */
7560 create_disp = FILE_OVERWRITE_IF;
7561 break;
7562 case FILE_OPEN:
7563 /* SMB_O_TRUNC */
7564 /* File exists overwrite. File not exist fail. */
7565 create_disp = FILE_OVERWRITE;
7566 break;
7567 default:
7568 /* Cannot get here. */
7569 smb_panic("smb_posix_open: logic error");
7570 return NT_STATUS_INVALID_PARAMETER;
7574 raw_unixmode = IVAL(pdata,8);
7575 /* Next 4 bytes are not yet defined. */
7577 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7578 (VALID_STAT(smb_fname->st) ?
7579 PERM_EXISTING_FILE : PERM_NEW_FILE),
7580 &unixmode);
7582 if (!NT_STATUS_IS_OK(status)) {
7583 return status;
7586 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7588 if (wire_open_mode & SMB_O_SYNC) {
7589 create_options |= FILE_WRITE_THROUGH;
7591 if (wire_open_mode & SMB_O_APPEND) {
7592 access_mask |= FILE_APPEND_DATA;
7594 if (wire_open_mode & SMB_O_DIRECT) {
7595 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7598 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7599 VALID_STAT_OF_DIR(smb_fname->st)) {
7600 if (access_mask != SMB_O_RDONLY_MAPPING) {
7601 return NT_STATUS_FILE_IS_A_DIRECTORY;
7603 create_options &= ~FILE_NON_DIRECTORY_FILE;
7604 create_options |= FILE_DIRECTORY_FILE;
7607 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7608 smb_fname_str_dbg(smb_fname),
7609 (unsigned int)wire_open_mode,
7610 (unsigned int)unixmode ));
7612 status = SMB_VFS_CREATE_FILE(
7613 conn, /* conn */
7614 req, /* req */
7615 0, /* root_dir_fid */
7616 smb_fname, /* fname */
7617 access_mask, /* access_mask */
7618 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7619 FILE_SHARE_DELETE),
7620 create_disp, /* create_disposition*/
7621 create_options, /* create_options */
7622 mod_unixmode, /* file_attributes */
7623 oplock_request, /* oplock_request */
7624 0, /* allocation_size */
7625 0, /* private_flags */
7626 NULL, /* sd */
7627 NULL, /* ea_list */
7628 &fsp, /* result */
7629 &info); /* pinfo */
7631 if (!NT_STATUS_IS_OK(status)) {
7632 return status;
7635 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7636 extended_oplock_granted = True;
7639 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7640 extended_oplock_granted = True;
7643 info_level_return = SVAL(pdata,16);
7645 /* Allocate the correct return size. */
7647 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7648 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7649 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7650 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7651 } else {
7652 *pdata_return_size = 12;
7655 /* Realloc the data size */
7656 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7657 if (*ppdata == NULL) {
7658 close_file(req, fsp, ERROR_CLOSE);
7659 *pdata_return_size = 0;
7660 return NT_STATUS_NO_MEMORY;
7662 pdata = *ppdata;
7664 if (extended_oplock_granted) {
7665 if (flags & REQUEST_BATCH_OPLOCK) {
7666 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7667 } else {
7668 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7670 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7671 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7672 } else {
7673 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7676 SSVAL(pdata,2,fsp->fnum);
7677 SIVAL(pdata,4,info); /* Was file created etc. */
7679 switch (info_level_return) {
7680 case SMB_QUERY_FILE_UNIX_BASIC:
7681 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7682 SSVAL(pdata,10,0); /* padding. */
7683 store_file_unix_basic(conn, pdata + 12, fsp,
7684 &smb_fname->st);
7685 break;
7686 case SMB_QUERY_FILE_UNIX_INFO2:
7687 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7688 SSVAL(pdata,10,0); /* padding. */
7689 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7690 &smb_fname->st);
7691 break;
7692 default:
7693 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7694 SSVAL(pdata,10,0); /* padding. */
7695 break;
7697 return NT_STATUS_OK;
7700 /****************************************************************************
7701 Delete a file with POSIX semantics.
7702 ****************************************************************************/
7704 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7705 struct smb_request *req,
7706 const char *pdata,
7707 int total_data,
7708 struct smb_filename *smb_fname)
7710 NTSTATUS status = NT_STATUS_OK;
7711 files_struct *fsp = NULL;
7712 uint16 flags = 0;
7713 char del = 1;
7714 int info = 0;
7715 int create_options = 0;
7716 int i;
7717 struct share_mode_lock *lck = NULL;
7719 if (total_data < 2) {
7720 return NT_STATUS_INVALID_PARAMETER;
7723 flags = SVAL(pdata,0);
7725 if (!VALID_STAT(smb_fname->st)) {
7726 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7729 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7730 !VALID_STAT_OF_DIR(smb_fname->st)) {
7731 return NT_STATUS_NOT_A_DIRECTORY;
7734 DEBUG(10,("smb_posix_unlink: %s %s\n",
7735 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7736 smb_fname_str_dbg(smb_fname)));
7738 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7739 create_options |= FILE_DIRECTORY_FILE;
7742 status = SMB_VFS_CREATE_FILE(
7743 conn, /* conn */
7744 req, /* req */
7745 0, /* root_dir_fid */
7746 smb_fname, /* fname */
7747 DELETE_ACCESS, /* access_mask */
7748 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7749 FILE_SHARE_DELETE),
7750 FILE_OPEN, /* create_disposition*/
7751 create_options, /* create_options */
7752 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7753 0, /* oplock_request */
7754 0, /* allocation_size */
7755 0, /* private_flags */
7756 NULL, /* sd */
7757 NULL, /* ea_list */
7758 &fsp, /* result */
7759 &info); /* pinfo */
7761 if (!NT_STATUS_IS_OK(status)) {
7762 return status;
7766 * Don't lie to client. If we can't really delete due to
7767 * non-POSIX opens return SHARING_VIOLATION.
7770 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7771 if (lck == NULL) {
7772 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7773 "lock for file %s\n", fsp_str_dbg(fsp)));
7774 close_file(req, fsp, NORMAL_CLOSE);
7775 return NT_STATUS_INVALID_PARAMETER;
7779 * See if others still have the file open. If this is the case, then
7780 * don't delete. If all opens are POSIX delete we can set the delete
7781 * on close disposition.
7783 for (i=0; i<lck->data->num_share_modes; i++) {
7784 struct share_mode_entry *e = &lck->data->share_modes[i];
7785 if (is_valid_share_mode_entry(e)) {
7786 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7787 continue;
7789 if (share_mode_stale_pid(lck->data, i)) {
7790 continue;
7792 /* Fail with sharing violation. */
7793 TALLOC_FREE(lck);
7794 close_file(req, fsp, NORMAL_CLOSE);
7795 return NT_STATUS_SHARING_VIOLATION;
7800 * Set the delete on close.
7802 status = smb_set_file_disposition_info(conn,
7803 &del,
7805 fsp,
7806 smb_fname);
7808 TALLOC_FREE(lck);
7810 if (!NT_STATUS_IS_OK(status)) {
7811 close_file(req, fsp, NORMAL_CLOSE);
7812 return status;
7814 return close_file(req, fsp, NORMAL_CLOSE);
7817 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7818 struct smb_request *req,
7819 TALLOC_CTX *mem_ctx,
7820 uint16_t info_level,
7821 files_struct *fsp,
7822 struct smb_filename *smb_fname,
7823 char **ppdata, int total_data,
7824 int *ret_data_size)
7826 char *pdata = *ppdata;
7827 NTSTATUS status = NT_STATUS_OK;
7828 int data_return_size = 0;
7830 *ret_data_size = 0;
7832 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7833 return NT_STATUS_INVALID_LEVEL;
7836 if (!CAN_WRITE(conn)) {
7837 /* Allow POSIX opens. The open path will deny
7838 * any non-readonly opens. */
7839 if (info_level != SMB_POSIX_PATH_OPEN) {
7840 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7844 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7845 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7846 fsp_fnum_dbg(fsp),
7847 info_level, total_data));
7849 switch (info_level) {
7851 case SMB_INFO_STANDARD:
7853 status = smb_set_info_standard(conn,
7854 pdata,
7855 total_data,
7856 fsp,
7857 smb_fname);
7858 break;
7861 case SMB_INFO_SET_EA:
7863 status = smb_info_set_ea(conn,
7864 pdata,
7865 total_data,
7866 fsp,
7867 smb_fname);
7868 break;
7871 case SMB_SET_FILE_BASIC_INFO:
7872 case SMB_FILE_BASIC_INFORMATION:
7874 status = smb_set_file_basic_info(conn,
7875 pdata,
7876 total_data,
7877 fsp,
7878 smb_fname);
7879 break;
7882 case SMB_FILE_ALLOCATION_INFORMATION:
7883 case SMB_SET_FILE_ALLOCATION_INFO:
7885 status = smb_set_file_allocation_info(conn, req,
7886 pdata,
7887 total_data,
7888 fsp,
7889 smb_fname);
7890 break;
7893 case SMB_FILE_END_OF_FILE_INFORMATION:
7894 case SMB_SET_FILE_END_OF_FILE_INFO:
7897 * XP/Win7 both fail after the createfile with
7898 * SMB_SET_FILE_END_OF_FILE_INFO but not
7899 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7900 * The level is known here, so pass it down
7901 * appropriately.
7903 bool should_fail =
7904 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7906 status = smb_set_file_end_of_file_info(conn, req,
7907 pdata,
7908 total_data,
7909 fsp,
7910 smb_fname,
7911 should_fail);
7912 break;
7915 case SMB_FILE_DISPOSITION_INFORMATION:
7916 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7918 #if 0
7919 /* JRA - We used to just ignore this on a path ?
7920 * Shouldn't this be invalid level on a pathname
7921 * based call ?
7923 if (tran_call != TRANSACT2_SETFILEINFO) {
7924 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7926 #endif
7927 status = smb_set_file_disposition_info(conn,
7928 pdata,
7929 total_data,
7930 fsp,
7931 smb_fname);
7932 break;
7935 case SMB_FILE_POSITION_INFORMATION:
7937 status = smb_file_position_information(conn,
7938 pdata,
7939 total_data,
7940 fsp);
7941 break;
7944 case SMB_FILE_FULL_EA_INFORMATION:
7946 status = smb_set_file_full_ea_info(conn,
7947 pdata,
7948 total_data,
7949 fsp);
7950 break;
7953 /* From tridge Samba4 :
7954 * MODE_INFORMATION in setfileinfo (I have no
7955 * idea what "mode information" on a file is - it takes a value of 0,
7956 * 2, 4 or 6. What could it be?).
7959 case SMB_FILE_MODE_INFORMATION:
7961 status = smb_file_mode_information(conn,
7962 pdata,
7963 total_data);
7964 break;
7968 * CIFS UNIX extensions.
7971 case SMB_SET_FILE_UNIX_BASIC:
7973 status = smb_set_file_unix_basic(conn, req,
7974 pdata,
7975 total_data,
7976 fsp,
7977 smb_fname);
7978 break;
7981 case SMB_SET_FILE_UNIX_INFO2:
7983 status = smb_set_file_unix_info2(conn, req,
7984 pdata,
7985 total_data,
7986 fsp,
7987 smb_fname);
7988 break;
7991 case SMB_SET_FILE_UNIX_LINK:
7993 if (fsp) {
7994 /* We must have a pathname for this. */
7995 return NT_STATUS_INVALID_LEVEL;
7997 status = smb_set_file_unix_link(conn, req, pdata,
7998 total_data, smb_fname);
7999 break;
8002 case SMB_SET_FILE_UNIX_HLINK:
8004 if (fsp) {
8005 /* We must have a pathname for this. */
8006 return NT_STATUS_INVALID_LEVEL;
8008 status = smb_set_file_unix_hlink(conn, req,
8009 pdata, total_data,
8010 smb_fname);
8011 break;
8014 case SMB_FILE_RENAME_INFORMATION:
8016 status = smb_file_rename_information(conn, req,
8017 pdata, total_data,
8018 fsp, smb_fname);
8019 break;
8022 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8024 /* SMB2 rename information. */
8025 status = smb2_file_rename_information(conn, req,
8026 pdata, total_data,
8027 fsp, smb_fname);
8028 break;
8031 case SMB_FILE_LINK_INFORMATION:
8033 status = smb_file_link_information(conn, req,
8034 pdata, total_data,
8035 fsp, smb_fname);
8036 break;
8039 #if defined(HAVE_POSIX_ACLS)
8040 case SMB_SET_POSIX_ACL:
8042 status = smb_set_posix_acl(conn,
8043 pdata,
8044 total_data,
8045 fsp,
8046 smb_fname);
8047 break;
8049 #endif
8051 case SMB_SET_POSIX_LOCK:
8053 if (!fsp) {
8054 return NT_STATUS_INVALID_LEVEL;
8056 status = smb_set_posix_lock(conn, req,
8057 pdata, total_data, fsp);
8058 break;
8061 case SMB_POSIX_PATH_OPEN:
8063 if (fsp) {
8064 /* We must have a pathname for this. */
8065 return NT_STATUS_INVALID_LEVEL;
8068 status = smb_posix_open(conn, req,
8069 ppdata,
8070 total_data,
8071 smb_fname,
8072 &data_return_size);
8073 break;
8076 case SMB_POSIX_PATH_UNLINK:
8078 if (fsp) {
8079 /* We must have a pathname for this. */
8080 return NT_STATUS_INVALID_LEVEL;
8083 status = smb_posix_unlink(conn, req,
8084 pdata,
8085 total_data,
8086 smb_fname);
8087 break;
8090 default:
8091 return NT_STATUS_INVALID_LEVEL;
8094 if (!NT_STATUS_IS_OK(status)) {
8095 return status;
8098 *ret_data_size = data_return_size;
8099 return NT_STATUS_OK;
8102 /****************************************************************************
8103 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8104 ****************************************************************************/
8106 static void call_trans2setfilepathinfo(connection_struct *conn,
8107 struct smb_request *req,
8108 unsigned int tran_call,
8109 char **pparams, int total_params,
8110 char **ppdata, int total_data,
8111 unsigned int max_data_bytes)
8113 char *params = *pparams;
8114 char *pdata = *ppdata;
8115 uint16 info_level;
8116 struct smb_filename *smb_fname = NULL;
8117 files_struct *fsp = NULL;
8118 NTSTATUS status = NT_STATUS_OK;
8119 int data_return_size = 0;
8121 if (!params) {
8122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8123 return;
8126 if (tran_call == TRANSACT2_SETFILEINFO) {
8127 if (total_params < 4) {
8128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8129 return;
8132 fsp = file_fsp(req, SVAL(params,0));
8133 /* Basic check for non-null fsp. */
8134 if (!check_fsp_open(conn, req, fsp)) {
8135 return;
8137 info_level = SVAL(params,2);
8139 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8140 if (smb_fname == NULL) {
8141 reply_nterror(req, NT_STATUS_NO_MEMORY);
8142 return;
8145 if(fsp->fh->fd == -1) {
8147 * This is actually a SETFILEINFO on a directory
8148 * handle (returned from an NT SMB). NT5.0 seems
8149 * to do this call. JRA.
8151 if (INFO_LEVEL_IS_UNIX(info_level)) {
8152 /* Always do lstat for UNIX calls. */
8153 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8154 DEBUG(3,("call_trans2setfilepathinfo: "
8155 "SMB_VFS_LSTAT of %s failed "
8156 "(%s)\n",
8157 smb_fname_str_dbg(smb_fname),
8158 strerror(errno)));
8159 reply_nterror(req, map_nt_error_from_unix(errno));
8160 return;
8162 } else {
8163 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8164 DEBUG(3,("call_trans2setfilepathinfo: "
8165 "fileinfo of %s failed (%s)\n",
8166 smb_fname_str_dbg(smb_fname),
8167 strerror(errno)));
8168 reply_nterror(req, map_nt_error_from_unix(errno));
8169 return;
8172 } else if (fsp->print_file) {
8174 * Doing a DELETE_ON_CLOSE should cancel a print job.
8176 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8177 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8179 DEBUG(3,("call_trans2setfilepathinfo: "
8180 "Cancelling print job (%s)\n",
8181 fsp_str_dbg(fsp)));
8183 SSVAL(params,0,0);
8184 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8185 *ppdata, 0,
8186 max_data_bytes);
8187 return;
8188 } else {
8189 reply_nterror(req,
8190 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8191 return;
8193 } else {
8195 * Original code - this is an open file.
8197 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8198 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8199 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8200 strerror(errno)));
8201 reply_nterror(req, map_nt_error_from_unix(errno));
8202 return;
8205 } else {
8206 char *fname = NULL;
8207 uint32_t ucf_flags = 0;
8209 /* set path info */
8210 if (total_params < 7) {
8211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8212 return;
8215 info_level = SVAL(params,0);
8216 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8217 total_params - 6, STR_TERMINATE,
8218 &status);
8219 if (!NT_STATUS_IS_OK(status)) {
8220 reply_nterror(req, status);
8221 return;
8224 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8225 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8226 info_level == SMB_FILE_RENAME_INFORMATION ||
8227 info_level == SMB_POSIX_PATH_UNLINK) {
8228 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8231 status = filename_convert(req, conn,
8232 req->flags2 & FLAGS2_DFS_PATHNAMES,
8233 fname,
8234 ucf_flags,
8235 NULL,
8236 &smb_fname);
8237 if (!NT_STATUS_IS_OK(status)) {
8238 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8239 reply_botherror(req,
8240 NT_STATUS_PATH_NOT_COVERED,
8241 ERRSRV, ERRbadpath);
8242 return;
8244 reply_nterror(req, status);
8245 return;
8248 if (INFO_LEVEL_IS_UNIX(info_level)) {
8250 * For CIFS UNIX extensions the target name may not exist.
8253 /* Always do lstat for UNIX calls. */
8254 SMB_VFS_LSTAT(conn, smb_fname);
8256 } else if (!VALID_STAT(smb_fname->st) &&
8257 SMB_VFS_STAT(conn, smb_fname)) {
8258 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8259 "%s failed (%s)\n",
8260 smb_fname_str_dbg(smb_fname),
8261 strerror(errno)));
8262 reply_nterror(req, map_nt_error_from_unix(errno));
8263 return;
8267 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8268 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8269 fsp_fnum_dbg(fsp),
8270 info_level,total_data));
8272 /* Realloc the parameter size */
8273 *pparams = (char *)SMB_REALLOC(*pparams,2);
8274 if (*pparams == NULL) {
8275 reply_nterror(req, NT_STATUS_NO_MEMORY);
8276 return;
8278 params = *pparams;
8280 SSVAL(params,0,0);
8282 status = smbd_do_setfilepathinfo(conn, req, req,
8283 info_level,
8284 fsp,
8285 smb_fname,
8286 ppdata, total_data,
8287 &data_return_size);
8288 if (!NT_STATUS_IS_OK(status)) {
8289 if (open_was_deferred(req->sconn, req->mid)) {
8290 /* We have re-scheduled this call. */
8291 return;
8293 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8294 /* We have re-scheduled this call. */
8295 return;
8297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8298 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8299 ERRSRV, ERRbadpath);
8300 return;
8302 if (info_level == SMB_POSIX_PATH_OPEN) {
8303 reply_openerror(req, status);
8304 return;
8308 * Invalid EA name needs to return 2 param bytes,
8309 * not a zero-length error packet.
8311 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8312 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8313 max_data_bytes);
8314 } else {
8315 reply_nterror(req, status);
8317 return;
8320 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8321 max_data_bytes);
8323 return;
8326 /****************************************************************************
8327 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8328 ****************************************************************************/
8330 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8331 char **pparams, int total_params,
8332 char **ppdata, int total_data,
8333 unsigned int max_data_bytes)
8335 struct smb_filename *smb_dname = NULL;
8336 char *params = *pparams;
8337 char *pdata = *ppdata;
8338 char *directory = NULL;
8339 NTSTATUS status = NT_STATUS_OK;
8340 struct ea_list *ea_list = NULL;
8341 TALLOC_CTX *ctx = talloc_tos();
8343 if (!CAN_WRITE(conn)) {
8344 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8345 return;
8348 if (total_params < 5) {
8349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8350 return;
8353 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8354 total_params - 4, STR_TERMINATE,
8355 &status);
8356 if (!NT_STATUS_IS_OK(status)) {
8357 reply_nterror(req, status);
8358 return;
8361 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8363 status = filename_convert(ctx,
8364 conn,
8365 req->flags2 & FLAGS2_DFS_PATHNAMES,
8366 directory,
8368 NULL,
8369 &smb_dname);
8371 if (!NT_STATUS_IS_OK(status)) {
8372 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8373 reply_botherror(req,
8374 NT_STATUS_PATH_NOT_COVERED,
8375 ERRSRV, ERRbadpath);
8376 return;
8378 reply_nterror(req, status);
8379 return;
8383 * OS/2 workplace shell seems to send SET_EA requests of "null"
8384 * length (4 bytes containing IVAL 4).
8385 * They seem to have no effect. Bug #3212. JRA.
8388 if (total_data && (total_data != 4)) {
8389 /* Any data in this call is an EA list. */
8390 if (total_data < 10) {
8391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8392 goto out;
8395 if (IVAL(pdata,0) > total_data) {
8396 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8397 IVAL(pdata,0), (unsigned int)total_data));
8398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8399 goto out;
8402 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8403 total_data - 4);
8404 if (!ea_list) {
8405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 goto out;
8409 if (!lp_ea_support(SNUM(conn))) {
8410 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8411 goto out;
8414 /* If total_data == 4 Windows doesn't care what values
8415 * are placed in that field, it just ignores them.
8416 * The System i QNTC IBM SMB client puts bad values here,
8417 * so ignore them. */
8419 status = create_directory(conn, req, smb_dname);
8421 if (!NT_STATUS_IS_OK(status)) {
8422 reply_nterror(req, status);
8423 goto out;
8426 /* Try and set any given EA. */
8427 if (ea_list) {
8428 status = set_ea(conn, NULL, smb_dname, ea_list);
8429 if (!NT_STATUS_IS_OK(status)) {
8430 reply_nterror(req, status);
8431 goto out;
8435 /* Realloc the parameter and data sizes */
8436 *pparams = (char *)SMB_REALLOC(*pparams,2);
8437 if(*pparams == NULL) {
8438 reply_nterror(req, NT_STATUS_NO_MEMORY);
8439 goto out;
8441 params = *pparams;
8443 SSVAL(params,0,0);
8445 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8447 out:
8448 TALLOC_FREE(smb_dname);
8449 return;
8452 /****************************************************************************
8453 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8454 We don't actually do this - we just send a null response.
8455 ****************************************************************************/
8457 static void call_trans2findnotifyfirst(connection_struct *conn,
8458 struct smb_request *req,
8459 char **pparams, int total_params,
8460 char **ppdata, int total_data,
8461 unsigned int max_data_bytes)
8463 char *params = *pparams;
8464 uint16 info_level;
8466 if (total_params < 6) {
8467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8468 return;
8471 info_level = SVAL(params,4);
8472 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8474 switch (info_level) {
8475 case 1:
8476 case 2:
8477 break;
8478 default:
8479 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8480 return;
8483 /* Realloc the parameter and data sizes */
8484 *pparams = (char *)SMB_REALLOC(*pparams,6);
8485 if (*pparams == NULL) {
8486 reply_nterror(req, NT_STATUS_NO_MEMORY);
8487 return;
8489 params = *pparams;
8491 SSVAL(params,0,fnf_handle);
8492 SSVAL(params,2,0); /* No changes */
8493 SSVAL(params,4,0); /* No EA errors */
8495 fnf_handle++;
8497 if(fnf_handle == 0)
8498 fnf_handle = 257;
8500 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8502 return;
8505 /****************************************************************************
8506 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8507 changes). Currently this does nothing.
8508 ****************************************************************************/
8510 static void call_trans2findnotifynext(connection_struct *conn,
8511 struct smb_request *req,
8512 char **pparams, int total_params,
8513 char **ppdata, int total_data,
8514 unsigned int max_data_bytes)
8516 char *params = *pparams;
8518 DEBUG(3,("call_trans2findnotifynext\n"));
8520 /* Realloc the parameter and data sizes */
8521 *pparams = (char *)SMB_REALLOC(*pparams,4);
8522 if (*pparams == NULL) {
8523 reply_nterror(req, NT_STATUS_NO_MEMORY);
8524 return;
8526 params = *pparams;
8528 SSVAL(params,0,0); /* No changes */
8529 SSVAL(params,2,0); /* No EA errors */
8531 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8533 return;
8536 /****************************************************************************
8537 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8538 ****************************************************************************/
8540 static void call_trans2getdfsreferral(connection_struct *conn,
8541 struct smb_request *req,
8542 char **pparams, int total_params,
8543 char **ppdata, int total_data,
8544 unsigned int max_data_bytes)
8546 char *params = *pparams;
8547 char *pathname = NULL;
8548 int reply_size = 0;
8549 int max_referral_level;
8550 NTSTATUS status = NT_STATUS_OK;
8551 TALLOC_CTX *ctx = talloc_tos();
8553 DEBUG(10,("call_trans2getdfsreferral\n"));
8555 if (total_params < 3) {
8556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8557 return;
8560 max_referral_level = SVAL(params,0);
8562 if(!lp_host_msdfs()) {
8563 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8564 return;
8567 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8568 total_params - 2, STR_TERMINATE);
8569 if (!pathname) {
8570 reply_nterror(req, NT_STATUS_NOT_FOUND);
8571 return;
8573 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8574 ppdata,&status)) < 0) {
8575 reply_nterror(req, status);
8576 return;
8579 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8580 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8581 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8583 return;
8586 #define LMCAT_SPL 0x53
8587 #define LMFUNC_GETJOBID 0x60
8589 /****************************************************************************
8590 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8591 ****************************************************************************/
8593 static void call_trans2ioctl(connection_struct *conn,
8594 struct smb_request *req,
8595 char **pparams, int total_params,
8596 char **ppdata, int total_data,
8597 unsigned int max_data_bytes)
8599 char *pdata = *ppdata;
8600 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8602 /* check for an invalid fid before proceeding */
8604 if (!fsp) {
8605 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8606 return;
8609 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8610 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8611 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8612 if (*ppdata == NULL) {
8613 reply_nterror(req, NT_STATUS_NO_MEMORY);
8614 return;
8616 pdata = *ppdata;
8618 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8619 CAN ACCEPT THIS IN UNICODE. JRA. */
8621 /* Job number */
8622 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8624 srvstr_push(pdata, req->flags2, pdata + 2,
8625 lp_netbios_name(), 15,
8626 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8627 srvstr_push(pdata, req->flags2, pdata+18,
8628 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8629 STR_ASCII|STR_TERMINATE); /* Service name */
8630 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8631 max_data_bytes);
8632 return;
8635 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8636 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8639 /****************************************************************************
8640 Reply to a SMBfindclose (stop trans2 directory search).
8641 ****************************************************************************/
8643 void reply_findclose(struct smb_request *req)
8645 int dptr_num;
8646 struct smbd_server_connection *sconn = req->sconn;
8648 START_PROFILE(SMBfindclose);
8650 if (req->wct < 1) {
8651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8652 END_PROFILE(SMBfindclose);
8653 return;
8656 dptr_num = SVALS(req->vwv+0, 0);
8658 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8660 dptr_close(sconn, &dptr_num);
8662 reply_outbuf(req, 0, 0);
8664 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8666 END_PROFILE(SMBfindclose);
8667 return;
8670 /****************************************************************************
8671 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8672 ****************************************************************************/
8674 void reply_findnclose(struct smb_request *req)
8676 int dptr_num;
8678 START_PROFILE(SMBfindnclose);
8680 if (req->wct < 1) {
8681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8682 END_PROFILE(SMBfindnclose);
8683 return;
8686 dptr_num = SVAL(req->vwv+0, 0);
8688 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8690 /* We never give out valid handles for a
8691 findnotifyfirst - so any dptr_num is ok here.
8692 Just ignore it. */
8694 reply_outbuf(req, 0, 0);
8696 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8698 END_PROFILE(SMBfindnclose);
8699 return;
8702 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8703 struct trans_state *state)
8705 if (get_Protocol() >= PROTOCOL_NT1) {
8706 req->flags2 |= 0x40; /* IS_LONG_NAME */
8707 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8710 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8711 if (state->call != TRANSACT2_QFSINFO &&
8712 state->call != TRANSACT2_SETFSINFO) {
8713 DEBUG(0,("handle_trans2: encryption required "
8714 "with call 0x%x\n",
8715 (unsigned int)state->call));
8716 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8717 return;
8721 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8723 /* Now we must call the relevant TRANS2 function */
8724 switch(state->call) {
8725 case TRANSACT2_OPEN:
8727 START_PROFILE(Trans2_open);
8728 call_trans2open(conn, req,
8729 &state->param, state->total_param,
8730 &state->data, state->total_data,
8731 state->max_data_return);
8732 END_PROFILE(Trans2_open);
8733 break;
8736 case TRANSACT2_FINDFIRST:
8738 START_PROFILE(Trans2_findfirst);
8739 call_trans2findfirst(conn, req,
8740 &state->param, state->total_param,
8741 &state->data, state->total_data,
8742 state->max_data_return);
8743 END_PROFILE(Trans2_findfirst);
8744 break;
8747 case TRANSACT2_FINDNEXT:
8749 START_PROFILE(Trans2_findnext);
8750 call_trans2findnext(conn, req,
8751 &state->param, state->total_param,
8752 &state->data, state->total_data,
8753 state->max_data_return);
8754 END_PROFILE(Trans2_findnext);
8755 break;
8758 case TRANSACT2_QFSINFO:
8760 START_PROFILE(Trans2_qfsinfo);
8761 call_trans2qfsinfo(conn, req,
8762 &state->param, state->total_param,
8763 &state->data, state->total_data,
8764 state->max_data_return);
8765 END_PROFILE(Trans2_qfsinfo);
8766 break;
8769 case TRANSACT2_SETFSINFO:
8771 START_PROFILE(Trans2_setfsinfo);
8772 call_trans2setfsinfo(conn, req,
8773 &state->param, state->total_param,
8774 &state->data, state->total_data,
8775 state->max_data_return);
8776 END_PROFILE(Trans2_setfsinfo);
8777 break;
8780 case TRANSACT2_QPATHINFO:
8781 case TRANSACT2_QFILEINFO:
8783 START_PROFILE(Trans2_qpathinfo);
8784 call_trans2qfilepathinfo(conn, req, state->call,
8785 &state->param, state->total_param,
8786 &state->data, state->total_data,
8787 state->max_data_return);
8788 END_PROFILE(Trans2_qpathinfo);
8789 break;
8792 case TRANSACT2_SETPATHINFO:
8793 case TRANSACT2_SETFILEINFO:
8795 START_PROFILE(Trans2_setpathinfo);
8796 call_trans2setfilepathinfo(conn, req, state->call,
8797 &state->param, state->total_param,
8798 &state->data, state->total_data,
8799 state->max_data_return);
8800 END_PROFILE(Trans2_setpathinfo);
8801 break;
8804 case TRANSACT2_FINDNOTIFYFIRST:
8806 START_PROFILE(Trans2_findnotifyfirst);
8807 call_trans2findnotifyfirst(conn, req,
8808 &state->param, state->total_param,
8809 &state->data, state->total_data,
8810 state->max_data_return);
8811 END_PROFILE(Trans2_findnotifyfirst);
8812 break;
8815 case TRANSACT2_FINDNOTIFYNEXT:
8817 START_PROFILE(Trans2_findnotifynext);
8818 call_trans2findnotifynext(conn, req,
8819 &state->param, state->total_param,
8820 &state->data, state->total_data,
8821 state->max_data_return);
8822 END_PROFILE(Trans2_findnotifynext);
8823 break;
8826 case TRANSACT2_MKDIR:
8828 START_PROFILE(Trans2_mkdir);
8829 call_trans2mkdir(conn, req,
8830 &state->param, state->total_param,
8831 &state->data, state->total_data,
8832 state->max_data_return);
8833 END_PROFILE(Trans2_mkdir);
8834 break;
8837 case TRANSACT2_GET_DFS_REFERRAL:
8839 START_PROFILE(Trans2_get_dfs_referral);
8840 call_trans2getdfsreferral(conn, req,
8841 &state->param, state->total_param,
8842 &state->data, state->total_data,
8843 state->max_data_return);
8844 END_PROFILE(Trans2_get_dfs_referral);
8845 break;
8848 case TRANSACT2_IOCTL:
8850 START_PROFILE(Trans2_ioctl);
8851 call_trans2ioctl(conn, req,
8852 &state->param, state->total_param,
8853 &state->data, state->total_data,
8854 state->max_data_return);
8855 END_PROFILE(Trans2_ioctl);
8856 break;
8859 default:
8860 /* Error in request */
8861 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8862 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8866 /****************************************************************************
8867 Reply to a SMBtrans2.
8868 ****************************************************************************/
8870 void reply_trans2(struct smb_request *req)
8872 connection_struct *conn = req->conn;
8873 unsigned int dsoff;
8874 unsigned int dscnt;
8875 unsigned int psoff;
8876 unsigned int pscnt;
8877 unsigned int tran_call;
8878 struct trans_state *state;
8879 NTSTATUS result;
8881 START_PROFILE(SMBtrans2);
8883 if (req->wct < 14) {
8884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8885 END_PROFILE(SMBtrans2);
8886 return;
8889 dsoff = SVAL(req->vwv+12, 0);
8890 dscnt = SVAL(req->vwv+11, 0);
8891 psoff = SVAL(req->vwv+10, 0);
8892 pscnt = SVAL(req->vwv+9, 0);
8893 tran_call = SVAL(req->vwv+14, 0);
8895 result = allow_new_trans(conn->pending_trans, req->mid);
8896 if (!NT_STATUS_IS_OK(result)) {
8897 DEBUG(2, ("Got invalid trans2 request: %s\n",
8898 nt_errstr(result)));
8899 reply_nterror(req, result);
8900 END_PROFILE(SMBtrans2);
8901 return;
8904 if (IS_IPC(conn)) {
8905 switch (tran_call) {
8906 /* List the allowed trans2 calls on IPC$ */
8907 case TRANSACT2_OPEN:
8908 case TRANSACT2_GET_DFS_REFERRAL:
8909 case TRANSACT2_QFILEINFO:
8910 case TRANSACT2_QFSINFO:
8911 case TRANSACT2_SETFSINFO:
8912 break;
8913 default:
8914 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8915 END_PROFILE(SMBtrans2);
8916 return;
8920 if ((state = talloc(conn, struct trans_state)) == NULL) {
8921 DEBUG(0, ("talloc failed\n"));
8922 reply_nterror(req, NT_STATUS_NO_MEMORY);
8923 END_PROFILE(SMBtrans2);
8924 return;
8927 state->cmd = SMBtrans2;
8929 state->mid = req->mid;
8930 state->vuid = req->vuid;
8931 state->setup_count = SVAL(req->vwv+13, 0);
8932 state->setup = NULL;
8933 state->total_param = SVAL(req->vwv+0, 0);
8934 state->param = NULL;
8935 state->total_data = SVAL(req->vwv+1, 0);
8936 state->data = NULL;
8937 state->max_param_return = SVAL(req->vwv+2, 0);
8938 state->max_data_return = SVAL(req->vwv+3, 0);
8939 state->max_setup_return = SVAL(req->vwv+4, 0);
8940 state->close_on_completion = BITSETW(req->vwv+5, 0);
8941 state->one_way = BITSETW(req->vwv+5, 1);
8943 state->call = tran_call;
8945 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8946 is so as a sanity check */
8947 if (state->setup_count != 1) {
8949 * Need to have rc=0 for ioctl to get job id for OS/2.
8950 * Network printing will fail if function is not successful.
8951 * Similar function in reply.c will be used if protocol
8952 * is LANMAN1.0 instead of LM1.2X002.
8953 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8954 * outbuf doesn't have to be set(only job id is used).
8956 if ( (state->setup_count == 4)
8957 && (tran_call == TRANSACT2_IOCTL)
8958 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8959 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8960 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8961 } else {
8962 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8963 DEBUG(2,("Transaction is %d\n",tran_call));
8964 TALLOC_FREE(state);
8965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8966 END_PROFILE(SMBtrans2);
8967 return;
8971 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8972 goto bad_param;
8974 if (state->total_data) {
8976 if (trans_oob(state->total_data, 0, dscnt)
8977 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8978 goto bad_param;
8981 /* Can't use talloc here, the core routines do realloc on the
8982 * params and data. */
8983 state->data = (char *)SMB_MALLOC(state->total_data);
8984 if (state->data == NULL) {
8985 DEBUG(0,("reply_trans2: data malloc fail for %u "
8986 "bytes !\n", (unsigned int)state->total_data));
8987 TALLOC_FREE(state);
8988 reply_nterror(req, NT_STATUS_NO_MEMORY);
8989 END_PROFILE(SMBtrans2);
8990 return;
8993 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8996 if (state->total_param) {
8998 if (trans_oob(state->total_param, 0, pscnt)
8999 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9000 goto bad_param;
9003 /* Can't use talloc here, the core routines do realloc on the
9004 * params and data. */
9005 state->param = (char *)SMB_MALLOC(state->total_param);
9006 if (state->param == NULL) {
9007 DEBUG(0,("reply_trans: param malloc fail for %u "
9008 "bytes !\n", (unsigned int)state->total_param));
9009 SAFE_FREE(state->data);
9010 TALLOC_FREE(state);
9011 reply_nterror(req, NT_STATUS_NO_MEMORY);
9012 END_PROFILE(SMBtrans2);
9013 return;
9016 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9019 state->received_data = dscnt;
9020 state->received_param = pscnt;
9022 if ((state->received_param == state->total_param) &&
9023 (state->received_data == state->total_data)) {
9025 handle_trans2(conn, req, state);
9027 SAFE_FREE(state->data);
9028 SAFE_FREE(state->param);
9029 TALLOC_FREE(state);
9030 END_PROFILE(SMBtrans2);
9031 return;
9034 DLIST_ADD(conn->pending_trans, state);
9036 /* We need to send an interim response then receive the rest
9037 of the parameter/data bytes */
9038 reply_outbuf(req, 0, 0);
9039 show_msg((char *)req->outbuf);
9040 END_PROFILE(SMBtrans2);
9041 return;
9043 bad_param:
9045 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9046 SAFE_FREE(state->data);
9047 SAFE_FREE(state->param);
9048 TALLOC_FREE(state);
9049 END_PROFILE(SMBtrans2);
9050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9054 /****************************************************************************
9055 Reply to a SMBtranss2
9056 ****************************************************************************/
9058 void reply_transs2(struct smb_request *req)
9060 connection_struct *conn = req->conn;
9061 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9062 struct trans_state *state;
9064 START_PROFILE(SMBtranss2);
9066 show_msg((const char *)req->inbuf);
9068 /* Windows clients expect all replies to
9069 a transact secondary (SMBtranss2 0x33)
9070 to have a command code of transact
9071 (SMBtrans2 0x32). See bug #8989
9072 and also [MS-CIFS] section 2.2.4.47.2
9073 for details.
9075 req->cmd = SMBtrans2;
9077 if (req->wct < 8) {
9078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9079 END_PROFILE(SMBtranss2);
9080 return;
9083 for (state = conn->pending_trans; state != NULL;
9084 state = state->next) {
9085 if (state->mid == req->mid) {
9086 break;
9090 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9092 END_PROFILE(SMBtranss2);
9093 return;
9096 /* Revise state->total_param and state->total_data in case they have
9097 changed downwards */
9099 if (SVAL(req->vwv+0, 0) < state->total_param)
9100 state->total_param = SVAL(req->vwv+0, 0);
9101 if (SVAL(req->vwv+1, 0) < state->total_data)
9102 state->total_data = SVAL(req->vwv+1, 0);
9104 pcnt = SVAL(req->vwv+2, 0);
9105 poff = SVAL(req->vwv+3, 0);
9106 pdisp = SVAL(req->vwv+4, 0);
9108 dcnt = SVAL(req->vwv+5, 0);
9109 doff = SVAL(req->vwv+6, 0);
9110 ddisp = SVAL(req->vwv+7, 0);
9112 state->received_param += pcnt;
9113 state->received_data += dcnt;
9115 if ((state->received_data > state->total_data) ||
9116 (state->received_param > state->total_param))
9117 goto bad_param;
9119 if (pcnt) {
9120 if (trans_oob(state->total_param, pdisp, pcnt)
9121 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9122 goto bad_param;
9124 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9127 if (dcnt) {
9128 if (trans_oob(state->total_data, ddisp, dcnt)
9129 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9130 goto bad_param;
9132 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9135 if ((state->received_param < state->total_param) ||
9136 (state->received_data < state->total_data)) {
9137 END_PROFILE(SMBtranss2);
9138 return;
9141 handle_trans2(conn, req, state);
9143 DLIST_REMOVE(conn->pending_trans, state);
9144 SAFE_FREE(state->data);
9145 SAFE_FREE(state->param);
9146 TALLOC_FREE(state);
9148 END_PROFILE(SMBtranss2);
9149 return;
9151 bad_param:
9153 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9154 DLIST_REMOVE(conn->pending_trans, state);
9155 SAFE_FREE(state->data);
9156 SAFE_FREE(state->param);
9157 TALLOC_FREE(state);
9158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9159 END_PROFILE(SMBtranss2);
9160 return;