ctdb-logging: Move variable debug_extra from debug.*
[Samba.git] / source3 / smbd / trans2.c
blob1e2c02e12d5f574843233b09eaa1d6fbe93d4720
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 NULL, /* lease */
1226 open_size, /* allocation_size */
1227 private_flags,
1228 NULL, /* sd */
1229 ea_list, /* ea_list */
1230 &fsp, /* result */
1231 &smb_action); /* psbuf */
1233 if (!NT_STATUS_IS_OK(status)) {
1234 if (open_was_deferred(req->sconn, req->mid)) {
1235 /* We have re-scheduled this call. */
1236 goto out;
1238 reply_openerror(req, status);
1239 goto out;
1242 size = get_file_size_stat(&smb_fname->st);
1243 fattr = dos_mode(conn, smb_fname);
1244 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1245 inode = smb_fname->st.st_ex_ino;
1246 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1247 close_file(req, fsp, ERROR_CLOSE);
1248 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1249 goto out;
1252 /* Realloc the size of parameters and data we will return */
1253 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1254 if(*pparams == NULL ) {
1255 reply_nterror(req, NT_STATUS_NO_MEMORY);
1256 goto out;
1258 params = *pparams;
1260 SSVAL(params,0,fsp->fnum);
1261 SSVAL(params,2,fattr);
1262 srv_put_dos_date2(params,4, mtime);
1263 SIVAL(params,8, (uint32)size);
1264 SSVAL(params,12,deny_mode);
1265 SSVAL(params,14,0); /* open_type - file or directory. */
1266 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1268 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1269 smb_action |= EXTENDED_OPLOCK_GRANTED;
1272 SSVAL(params,18,smb_action);
1275 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1277 SIVAL(params,20,inode);
1278 SSVAL(params,24,0); /* Padding. */
1279 if (flags & 8) {
1280 uint32 ea_size = estimate_ea_size(conn, fsp,
1281 smb_fname);
1282 SIVAL(params, 26, ea_size);
1283 } else {
1284 SIVAL(params, 26, 0);
1287 /* Send the required number of replies */
1288 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1289 out:
1290 TALLOC_FREE(smb_fname);
1293 /*********************************************************
1294 Routine to check if a given string matches exactly.
1295 as a special case a mask of "." does NOT match. That
1296 is required for correct wildcard semantics
1297 Case can be significant or not.
1298 **********************************************************/
1300 static bool exact_match(bool has_wild,
1301 bool case_sensitive,
1302 const char *str,
1303 const char *mask)
1305 if (mask[0] == '.' && mask[1] == 0) {
1306 return false;
1309 if (has_wild) {
1310 return false;
1313 if (case_sensitive) {
1314 return strcmp(str,mask)==0;
1315 } else {
1316 return strcasecmp_m(str,mask) == 0;
1320 /****************************************************************************
1321 Return the filetype for UNIX extensions.
1322 ****************************************************************************/
1324 static uint32 unix_filetype(mode_t mode)
1326 if(S_ISREG(mode))
1327 return UNIX_TYPE_FILE;
1328 else if(S_ISDIR(mode))
1329 return UNIX_TYPE_DIR;
1330 #ifdef S_ISLNK
1331 else if(S_ISLNK(mode))
1332 return UNIX_TYPE_SYMLINK;
1333 #endif
1334 #ifdef S_ISCHR
1335 else if(S_ISCHR(mode))
1336 return UNIX_TYPE_CHARDEV;
1337 #endif
1338 #ifdef S_ISBLK
1339 else if(S_ISBLK(mode))
1340 return UNIX_TYPE_BLKDEV;
1341 #endif
1342 #ifdef S_ISFIFO
1343 else if(S_ISFIFO(mode))
1344 return UNIX_TYPE_FIFO;
1345 #endif
1346 #ifdef S_ISSOCK
1347 else if(S_ISSOCK(mode))
1348 return UNIX_TYPE_SOCKET;
1349 #endif
1351 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1352 return UNIX_TYPE_UNKNOWN;
1355 /****************************************************************************
1356 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1357 ****************************************************************************/
1359 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1361 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1362 const SMB_STRUCT_STAT *psbuf,
1363 uint32 perms,
1364 enum perm_type ptype,
1365 mode_t *ret_perms)
1367 mode_t ret = 0;
1369 if (perms == SMB_MODE_NO_CHANGE) {
1370 if (!VALID_STAT(*psbuf)) {
1371 return NT_STATUS_INVALID_PARAMETER;
1372 } else {
1373 *ret_perms = psbuf->st_ex_mode;
1374 return NT_STATUS_OK;
1378 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1379 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1380 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1381 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1382 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1383 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1384 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1385 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1386 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1387 #ifdef S_ISVTX
1388 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1389 #endif
1390 #ifdef S_ISGID
1391 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1392 #endif
1393 #ifdef S_ISUID
1394 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1395 #endif
1397 if (ptype == PERM_NEW_FILE) {
1399 * "create mask"/"force create mode" are
1400 * only applied to new files, not existing ones.
1402 ret &= lp_create_mask(SNUM(conn));
1403 /* Add in force bits */
1404 ret |= lp_force_create_mode(SNUM(conn));
1405 } else if (ptype == PERM_NEW_DIR) {
1407 * "directory mask"/"force directory mode" are
1408 * only applied to new directories, not existing ones.
1410 ret &= lp_directory_mask(SNUM(conn));
1411 /* Add in force bits */
1412 ret |= lp_force_directory_mode(SNUM(conn));
1415 *ret_perms = ret;
1416 return NT_STATUS_OK;
1419 /****************************************************************************
1420 Needed to show the msdfs symlinks as directories. Modifies psbuf
1421 to be a directory if it's a msdfs link.
1422 ****************************************************************************/
1424 static bool check_msdfs_link(connection_struct *conn,
1425 const char *pathname,
1426 SMB_STRUCT_STAT *psbuf)
1428 int saved_errno = errno;
1429 if(lp_host_msdfs() &&
1430 lp_msdfs_root(SNUM(conn)) &&
1431 is_msdfs_link(conn, pathname, psbuf)) {
1433 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1434 "as a directory\n",
1435 pathname));
1436 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1437 errno = saved_errno;
1438 return true;
1440 errno = saved_errno;
1441 return false;
1445 /****************************************************************************
1446 Get a level dependent lanman2 dir entry.
1447 ****************************************************************************/
1449 struct smbd_dirptr_lanman2_state {
1450 connection_struct *conn;
1451 uint32_t info_level;
1452 bool check_mangled_names;
1453 bool has_wild;
1454 bool got_exact_match;
1457 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1458 void *private_data,
1459 const char *dname,
1460 const char *mask,
1461 char **_fname)
1463 struct smbd_dirptr_lanman2_state *state =
1464 (struct smbd_dirptr_lanman2_state *)private_data;
1465 bool ok;
1466 char mangled_name[13]; /* mangled 8.3 name. */
1467 bool got_match;
1468 const char *fname;
1470 /* Mangle fname if it's an illegal name. */
1471 if (mangle_must_mangle(dname, state->conn->params)) {
1472 ok = name_to_8_3(dname, mangled_name,
1473 true, state->conn->params);
1474 if (!ok) {
1475 return false;
1477 fname = mangled_name;
1478 } else {
1479 fname = dname;
1482 got_match = exact_match(state->has_wild,
1483 state->conn->case_sensitive,
1484 fname, mask);
1485 state->got_exact_match = got_match;
1486 if (!got_match) {
1487 got_match = mask_match(fname, mask,
1488 state->conn->case_sensitive);
1491 if(!got_match && state->check_mangled_names &&
1492 !mangle_is_8_3(fname, false, state->conn->params)) {
1494 * It turns out that NT matches wildcards against
1495 * both long *and* short names. This may explain some
1496 * of the wildcard wierdness from old DOS clients
1497 * that some people have been seeing.... JRA.
1499 /* Force the mangling into 8.3. */
1500 ok = name_to_8_3(fname, mangled_name,
1501 false, state->conn->params);
1502 if (!ok) {
1503 return false;
1506 got_match = exact_match(state->has_wild,
1507 state->conn->case_sensitive,
1508 mangled_name, mask);
1509 state->got_exact_match = got_match;
1510 if (!got_match) {
1511 got_match = mask_match(mangled_name, mask,
1512 state->conn->case_sensitive);
1516 if (!got_match) {
1517 return false;
1520 *_fname = talloc_strdup(ctx, fname);
1521 if (*_fname == NULL) {
1522 return false;
1525 return true;
1528 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1529 void *private_data,
1530 struct smb_filename *smb_fname,
1531 uint32_t *_mode)
1533 struct smbd_dirptr_lanman2_state *state =
1534 (struct smbd_dirptr_lanman2_state *)private_data;
1535 bool ms_dfs_link = false;
1536 uint32_t mode = 0;
1538 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1539 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1540 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1541 "Couldn't lstat [%s] (%s)\n",
1542 smb_fname_str_dbg(smb_fname),
1543 strerror(errno)));
1544 return false;
1546 } else if (!VALID_STAT(smb_fname->st) &&
1547 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1548 /* Needed to show the msdfs symlinks as
1549 * directories */
1551 ms_dfs_link = check_msdfs_link(state->conn,
1552 smb_fname->base_name,
1553 &smb_fname->st);
1554 if (!ms_dfs_link) {
1555 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1556 "Couldn't stat [%s] (%s)\n",
1557 smb_fname_str_dbg(smb_fname),
1558 strerror(errno)));
1559 return false;
1563 if (ms_dfs_link) {
1564 mode = dos_mode_msdfs(state->conn, smb_fname);
1565 } else {
1566 mode = dos_mode(state->conn, smb_fname);
1569 *_mode = mode;
1570 return true;
1573 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1574 connection_struct *conn,
1575 uint16_t flags2,
1576 uint32_t info_level,
1577 struct ea_list *name_list,
1578 bool check_mangled_names,
1579 bool requires_resume_key,
1580 uint32_t mode,
1581 const char *fname,
1582 const struct smb_filename *smb_fname,
1583 int space_remaining,
1584 uint8_t align,
1585 bool do_pad,
1586 char *base_data,
1587 char **ppdata,
1588 char *end_data,
1589 bool *out_of_space,
1590 uint64_t *last_entry_off)
1592 char *p, *q, *pdata = *ppdata;
1593 uint32_t reskey=0;
1594 uint64_t file_size = 0;
1595 uint64_t allocation_size = 0;
1596 uint64_t file_index = 0;
1597 uint32_t len;
1598 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1599 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1600 char *nameptr;
1601 char *last_entry_ptr;
1602 bool was_8_3;
1603 int off;
1604 int pad = 0;
1606 *out_of_space = false;
1608 ZERO_STRUCT(mdate_ts);
1609 ZERO_STRUCT(adate_ts);
1610 ZERO_STRUCT(create_date_ts);
1611 ZERO_STRUCT(cdate_ts);
1613 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1614 file_size = get_file_size_stat(&smb_fname->st);
1616 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1618 file_index = get_FileIndex(conn, &smb_fname->st);
1620 mdate_ts = smb_fname->st.st_ex_mtime;
1621 adate_ts = smb_fname->st.st_ex_atime;
1622 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1623 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1625 if (lp_dos_filetime_resolution(SNUM(conn))) {
1626 dos_filetime_timespec(&create_date_ts);
1627 dos_filetime_timespec(&mdate_ts);
1628 dos_filetime_timespec(&adate_ts);
1629 dos_filetime_timespec(&cdate_ts);
1632 create_date = convert_timespec_to_time_t(create_date_ts);
1633 mdate = convert_timespec_to_time_t(mdate_ts);
1634 adate = convert_timespec_to_time_t(adate_ts);
1636 /* align the record */
1637 SMB_ASSERT(align >= 1);
1639 off = (int)PTR_DIFF(pdata, base_data);
1640 pad = (off + (align-1)) & ~(align-1);
1641 pad -= off;
1643 if (pad && pad > space_remaining) {
1644 *out_of_space = true;
1645 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1646 "for padding (wanted %u, had %d)\n",
1647 (unsigned int)pad,
1648 space_remaining ));
1649 return false; /* Not finished - just out of space */
1652 off += pad;
1653 /* initialize padding to 0 */
1654 if (pad) {
1655 memset(pdata, 0, pad);
1657 space_remaining -= pad;
1659 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1660 space_remaining ));
1662 pdata += pad;
1663 p = pdata;
1664 last_entry_ptr = p;
1666 pad = 0;
1667 off = 0;
1669 switch (info_level) {
1670 case SMB_FIND_INFO_STANDARD:
1671 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1672 if(requires_resume_key) {
1673 SIVAL(p,0,reskey);
1674 p += 4;
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1681 SSVAL(p,20,mode);
1682 p += 23;
1683 nameptr = p;
1684 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1685 p += ucs2_align(base_data, p, 0);
1687 len = srvstr_push(base_data, flags2, p,
1688 fname, PTR_DIFF(end_data, p),
1689 STR_TERMINATE);
1690 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1691 if (len > 2) {
1692 SCVAL(nameptr, -1, len - 2);
1693 } else {
1694 SCVAL(nameptr, -1, 0);
1696 } else {
1697 if (len > 1) {
1698 SCVAL(nameptr, -1, len - 1);
1699 } else {
1700 SCVAL(nameptr, -1, 0);
1703 p += len;
1704 break;
1706 case SMB_FIND_EA_SIZE:
1707 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1708 if (requires_resume_key) {
1709 SIVAL(p,0,reskey);
1710 p += 4;
1712 srv_put_dos_date2(p,0,create_date);
1713 srv_put_dos_date2(p,4,adate);
1714 srv_put_dos_date2(p,8,mdate);
1715 SIVAL(p,12,(uint32)file_size);
1716 SIVAL(p,16,(uint32)allocation_size);
1717 SSVAL(p,20,mode);
1719 unsigned int ea_size = estimate_ea_size(conn, NULL,
1720 smb_fname);
1721 SIVAL(p,22,ea_size); /* Extended attributes */
1723 p += 27;
1724 nameptr = p - 1;
1725 len = srvstr_push(base_data, flags2,
1726 p, fname, PTR_DIFF(end_data, p),
1727 STR_TERMINATE | STR_NOALIGN);
1728 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1729 if (len > 2) {
1730 len -= 2;
1731 } else {
1732 len = 0;
1734 } else {
1735 if (len > 1) {
1736 len -= 1;
1737 } else {
1738 len = 0;
1741 SCVAL(nameptr,0,len);
1742 p += len;
1743 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1744 break;
1746 case SMB_FIND_EA_LIST:
1748 struct ea_list *file_list = NULL;
1749 size_t ea_len = 0;
1750 NTSTATUS status;
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1753 if (!name_list) {
1754 return false;
1756 if (requires_resume_key) {
1757 SIVAL(p,0,reskey);
1758 p += 4;
1760 srv_put_dos_date2(p,0,create_date);
1761 srv_put_dos_date2(p,4,adate);
1762 srv_put_dos_date2(p,8,mdate);
1763 SIVAL(p,12,(uint32)file_size);
1764 SIVAL(p,16,(uint32)allocation_size);
1765 SSVAL(p,20,mode);
1766 p += 22; /* p now points to the EA area. */
1768 status = get_ea_list_from_file(ctx, conn, NULL,
1769 smb_fname,
1770 &ea_len, &file_list);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 file_list = NULL;
1774 name_list = ea_list_union(name_list, file_list, &ea_len);
1776 /* We need to determine if this entry will fit in the space available. */
1777 /* Max string size is 255 bytes. */
1778 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1779 *out_of_space = true;
1780 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1781 "(wanted %u, had %d)\n",
1782 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1783 space_remaining ));
1784 return False; /* Not finished - just out of space */
1787 /* Push the ea_data followed by the name. */
1788 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1789 nameptr = p;
1790 len = srvstr_push(base_data, flags2,
1791 p + 1, fname, PTR_DIFF(end_data, p+1),
1792 STR_TERMINATE | STR_NOALIGN);
1793 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1794 if (len > 2) {
1795 len -= 2;
1796 } else {
1797 len = 0;
1799 } else {
1800 if (len > 1) {
1801 len -= 1;
1802 } else {
1803 len = 0;
1806 SCVAL(nameptr,0,len);
1807 p += len + 1;
1808 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1809 break;
1812 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1813 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1814 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1815 p += 4;
1816 SIVAL(p,0,reskey); p += 4;
1817 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1819 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1820 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1821 SOFF_T(p,0,file_size); p += 8;
1822 SOFF_T(p,0,allocation_size); p += 8;
1823 SIVAL(p,0,mode); p += 4;
1824 q = p; p += 4; /* q is placeholder for name length. */
1825 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1826 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1827 } else {
1828 unsigned int ea_size = estimate_ea_size(conn, NULL,
1829 smb_fname);
1830 SIVAL(p,0,ea_size); /* Extended attributes */
1832 p += 4;
1833 /* Clear the short name buffer. This is
1834 * IMPORTANT as not doing so will trigger
1835 * a Win2k client bug. JRA.
1837 if (!was_8_3 && check_mangled_names) {
1838 char mangled_name[13]; /* mangled 8.3 name. */
1839 if (!name_to_8_3(fname,mangled_name,True,
1840 conn->params)) {
1841 /* Error - mangle failed ! */
1842 memset(mangled_name,'\0',12);
1844 mangled_name[12] = 0;
1845 len = srvstr_push(base_data, flags2,
1846 p+2, mangled_name, 24,
1847 STR_UPPER|STR_UNICODE);
1848 if (len < 24) {
1849 memset(p + 2 + len,'\0',24 - len);
1851 SSVAL(p, 0, len);
1852 } else {
1853 memset(p,'\0',26);
1855 p += 2 + 24;
1856 len = srvstr_push(base_data, flags2, p,
1857 fname, PTR_DIFF(end_data, p),
1858 STR_TERMINATE_ASCII);
1859 SIVAL(q,0,len);
1860 p += len;
1862 len = PTR_DIFF(p, pdata);
1863 pad = (len + (align-1)) & ~(align-1);
1865 * offset to the next entry, the caller
1866 * will overwrite it for the last entry
1867 * that's why we always include the padding
1869 SIVAL(pdata,0,pad);
1871 * set padding to zero
1873 if (do_pad) {
1874 memset(p, 0, pad - len);
1875 p = pdata + pad;
1876 } else {
1877 p = pdata + len;
1879 break;
1881 case SMB_FIND_FILE_DIRECTORY_INFO:
1882 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1883 p += 4;
1884 SIVAL(p,0,reskey); p += 4;
1885 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1888 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1889 SOFF_T(p,0,file_size); p += 8;
1890 SOFF_T(p,0,allocation_size); p += 8;
1891 SIVAL(p,0,mode); p += 4;
1892 len = srvstr_push(base_data, flags2,
1893 p + 4, fname, PTR_DIFF(end_data, p+4),
1894 STR_TERMINATE_ASCII);
1895 SIVAL(p,0,len);
1896 p += 4 + len;
1898 len = PTR_DIFF(p, pdata);
1899 pad = (len + (align-1)) & ~(align-1);
1901 * offset to the next entry, the caller
1902 * will overwrite it for the last entry
1903 * that's why we always include the padding
1905 SIVAL(pdata,0,pad);
1907 * set padding to zero
1909 if (do_pad) {
1910 memset(p, 0, pad - len);
1911 p = pdata + pad;
1912 } else {
1913 p = pdata + len;
1915 break;
1917 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1918 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1919 p += 4;
1920 SIVAL(p,0,reskey); p += 4;
1921 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1923 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1924 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1925 SOFF_T(p,0,file_size); p += 8;
1926 SOFF_T(p,0,allocation_size); p += 8;
1927 SIVAL(p,0,mode); p += 4;
1928 q = p; p += 4; /* q is placeholder for name length. */
1930 unsigned int ea_size = estimate_ea_size(conn, NULL,
1931 smb_fname);
1932 SIVAL(p,0,ea_size); /* Extended attributes */
1933 p +=4;
1935 len = srvstr_push(base_data, flags2, p,
1936 fname, PTR_DIFF(end_data, p),
1937 STR_TERMINATE_ASCII);
1938 SIVAL(q, 0, len);
1939 p += len;
1941 len = PTR_DIFF(p, pdata);
1942 pad = (len + (align-1)) & ~(align-1);
1944 * offset to the next entry, the caller
1945 * will overwrite it for the last entry
1946 * that's why we always include the padding
1948 SIVAL(pdata,0,pad);
1950 * set padding to zero
1952 if (do_pad) {
1953 memset(p, 0, pad - len);
1954 p = pdata + pad;
1955 } else {
1956 p = pdata + len;
1958 break;
1960 case SMB_FIND_FILE_NAMES_INFO:
1961 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1962 p += 4;
1963 SIVAL(p,0,reskey); p += 4;
1964 p += 4;
1965 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1966 acl on a dir (tridge) */
1967 len = srvstr_push(base_data, flags2, p,
1968 fname, PTR_DIFF(end_data, p),
1969 STR_TERMINATE_ASCII);
1970 SIVAL(p, -4, len);
1971 p += len;
1973 len = PTR_DIFF(p, pdata);
1974 pad = (len + (align-1)) & ~(align-1);
1976 * offset to the next entry, the caller
1977 * will overwrite it for the last entry
1978 * that's why we always include the padding
1980 SIVAL(pdata,0,pad);
1982 * set padding to zero
1984 if (do_pad) {
1985 memset(p, 0, pad - len);
1986 p = pdata + pad;
1987 } else {
1988 p = pdata + len;
1990 break;
1992 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1994 p += 4;
1995 SIVAL(p,0,reskey); p += 4;
1996 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1998 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1999 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2000 SOFF_T(p,0,file_size); p += 8;
2001 SOFF_T(p,0,allocation_size); p += 8;
2002 SIVAL(p,0,mode); p += 4;
2003 q = p; p += 4; /* q is placeholder for name length. */
2004 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2005 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2006 } else {
2007 unsigned int ea_size = estimate_ea_size(conn, NULL,
2008 smb_fname);
2009 SIVAL(p,0,ea_size); /* Extended attributes */
2011 p += 4;
2012 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2013 SBVAL(p,0,file_index); p += 8;
2014 len = srvstr_push(base_data, flags2, p,
2015 fname, PTR_DIFF(end_data, p),
2016 STR_TERMINATE_ASCII);
2017 SIVAL(q, 0, len);
2018 p += len;
2020 len = PTR_DIFF(p, pdata);
2021 pad = (len + (align-1)) & ~(align-1);
2023 * offset to the next entry, the caller
2024 * will overwrite it for the last entry
2025 * that's why we always include the padding
2027 SIVAL(pdata,0,pad);
2029 * set padding to zero
2031 if (do_pad) {
2032 memset(p, 0, pad - len);
2033 p = pdata + pad;
2034 } else {
2035 p = pdata + len;
2037 break;
2039 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2040 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2041 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2042 p += 4;
2043 SIVAL(p,0,reskey); p += 4;
2044 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2046 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2047 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2048 SOFF_T(p,0,file_size); p += 8;
2049 SOFF_T(p,0,allocation_size); p += 8;
2050 SIVAL(p,0,mode); p += 4;
2051 q = p; p += 4; /* q is placeholder for name length */
2052 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2053 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2054 } else {
2055 unsigned int ea_size = estimate_ea_size(conn, NULL,
2056 smb_fname);
2057 SIVAL(p,0,ea_size); /* Extended attributes */
2059 p += 4;
2060 /* Clear the short name buffer. This is
2061 * IMPORTANT as not doing so will trigger
2062 * a Win2k client bug. JRA.
2064 if (!was_8_3 && check_mangled_names) {
2065 char mangled_name[13]; /* mangled 8.3 name. */
2066 if (!name_to_8_3(fname,mangled_name,True,
2067 conn->params)) {
2068 /* Error - mangle failed ! */
2069 memset(mangled_name,'\0',12);
2071 mangled_name[12] = 0;
2072 len = srvstr_push(base_data, flags2,
2073 p+2, mangled_name, 24,
2074 STR_UPPER|STR_UNICODE);
2075 SSVAL(p, 0, len);
2076 if (len < 24) {
2077 memset(p + 2 + len,'\0',24 - len);
2079 SSVAL(p, 0, len);
2080 } else {
2081 memset(p,'\0',26);
2083 p += 26;
2084 SSVAL(p,0,0); p += 2; /* Reserved ? */
2085 SBVAL(p,0,file_index); p += 8;
2086 len = srvstr_push(base_data, flags2, p,
2087 fname, PTR_DIFF(end_data, p),
2088 STR_TERMINATE_ASCII);
2089 SIVAL(q,0,len);
2090 p += len;
2092 len = PTR_DIFF(p, pdata);
2093 pad = (len + (align-1)) & ~(align-1);
2095 * offset to the next entry, the caller
2096 * will overwrite it for the last entry
2097 * that's why we always include the padding
2099 SIVAL(pdata,0,pad);
2101 * set padding to zero
2103 if (do_pad) {
2104 memset(p, 0, pad - len);
2105 p = pdata + pad;
2106 } else {
2107 p = pdata + len;
2109 break;
2111 /* CIFS UNIX Extension. */
2113 case SMB_FIND_FILE_UNIX:
2114 case SMB_FIND_FILE_UNIX_INFO2:
2115 p+= 4;
2116 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2118 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2120 if (info_level == SMB_FIND_FILE_UNIX) {
2121 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2122 p = store_file_unix_basic(conn, p,
2123 NULL, &smb_fname->st);
2124 len = srvstr_push(base_data, flags2, p,
2125 fname, PTR_DIFF(end_data, p),
2126 STR_TERMINATE);
2127 } else {
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2129 p = store_file_unix_basic_info2(conn, p,
2130 NULL, &smb_fname->st);
2131 nameptr = p;
2132 p += 4;
2133 len = srvstr_push(base_data, flags2, p, fname,
2134 PTR_DIFF(end_data, p), 0);
2135 SIVAL(nameptr, 0, len);
2138 p += len;
2140 len = PTR_DIFF(p, pdata);
2141 pad = (len + (align-1)) & ~(align-1);
2143 * offset to the next entry, the caller
2144 * will overwrite it for the last entry
2145 * that's why we always include the padding
2147 SIVAL(pdata,0,pad);
2149 * set padding to zero
2151 if (do_pad) {
2152 memset(p, 0, pad - len);
2153 p = pdata + pad;
2154 } else {
2155 p = pdata + len;
2157 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2159 break;
2161 default:
2162 return false;
2165 if (PTR_DIFF(p,pdata) > space_remaining) {
2166 *out_of_space = true;
2167 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2168 "(wanted %u, had %d)\n",
2169 (unsigned int)PTR_DIFF(p,pdata),
2170 space_remaining ));
2171 return false; /* Not finished - just out of space */
2174 /* Setup the last entry pointer, as an offset from base_data */
2175 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2176 /* Advance the data pointer to the next slot */
2177 *ppdata = p;
2179 return true;
2182 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2183 connection_struct *conn,
2184 struct dptr_struct *dirptr,
2185 uint16 flags2,
2186 const char *path_mask,
2187 uint32 dirtype,
2188 int info_level,
2189 int requires_resume_key,
2190 bool dont_descend,
2191 bool ask_sharemode,
2192 uint8_t align,
2193 bool do_pad,
2194 char **ppdata,
2195 char *base_data,
2196 char *end_data,
2197 int space_remaining,
2198 bool *out_of_space,
2199 bool *got_exact_match,
2200 int *_last_entry_off,
2201 struct ea_list *name_list)
2203 const char *p;
2204 const char *mask = NULL;
2205 long prev_dirpos = 0;
2206 uint32_t mode = 0;
2207 char *fname = NULL;
2208 struct smb_filename *smb_fname = NULL;
2209 struct smbd_dirptr_lanman2_state state;
2210 bool ok;
2211 uint64_t last_entry_off = 0;
2213 ZERO_STRUCT(state);
2214 state.conn = conn;
2215 state.info_level = info_level;
2216 state.check_mangled_names = lp_mangled_names(conn->params);
2217 state.has_wild = dptr_has_wild(dirptr);
2218 state.got_exact_match = false;
2220 *out_of_space = false;
2221 *got_exact_match = false;
2223 p = strrchr_m(path_mask,'/');
2224 if(p != NULL) {
2225 if(p[1] == '\0') {
2226 mask = "*.*";
2227 } else {
2228 mask = p+1;
2230 } else {
2231 mask = path_mask;
2234 ok = smbd_dirptr_get_entry(ctx,
2235 dirptr,
2236 mask,
2237 dirtype,
2238 dont_descend,
2239 ask_sharemode,
2240 smbd_dirptr_lanman2_match_fn,
2241 smbd_dirptr_lanman2_mode_fn,
2242 &state,
2243 &fname,
2244 &smb_fname,
2245 &mode,
2246 &prev_dirpos);
2247 if (!ok) {
2248 return false;
2251 *got_exact_match = state.got_exact_match;
2253 ok = smbd_marshall_dir_entry(ctx,
2254 conn,
2255 flags2,
2256 info_level,
2257 name_list,
2258 state.check_mangled_names,
2259 requires_resume_key,
2260 mode,
2261 fname,
2262 smb_fname,
2263 space_remaining,
2264 align,
2265 do_pad,
2266 base_data,
2267 ppdata,
2268 end_data,
2269 out_of_space,
2270 &last_entry_off);
2271 TALLOC_FREE(fname);
2272 TALLOC_FREE(smb_fname);
2273 if (*out_of_space) {
2274 dptr_SeekDir(dirptr, prev_dirpos);
2275 return false;
2277 if (!ok) {
2278 return false;
2281 *_last_entry_off = last_entry_off;
2282 return true;
2285 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2286 connection_struct *conn,
2287 struct dptr_struct *dirptr,
2288 uint16 flags2,
2289 const char *path_mask,
2290 uint32 dirtype,
2291 int info_level,
2292 bool requires_resume_key,
2293 bool dont_descend,
2294 bool ask_sharemode,
2295 char **ppdata,
2296 char *base_data,
2297 char *end_data,
2298 int space_remaining,
2299 bool *out_of_space,
2300 bool *got_exact_match,
2301 int *last_entry_off,
2302 struct ea_list *name_list)
2304 uint8_t align = 4;
2305 const bool do_pad = true;
2307 if (info_level >= 1 && info_level <= 3) {
2308 /* No alignment on earlier info levels. */
2309 align = 1;
2312 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2313 path_mask, dirtype, info_level,
2314 requires_resume_key, dont_descend, ask_sharemode,
2315 align, do_pad,
2316 ppdata, base_data, end_data,
2317 space_remaining,
2318 out_of_space, got_exact_match,
2319 last_entry_off, name_list);
2322 /****************************************************************************
2323 Reply to a TRANS2_FINDFIRST.
2324 ****************************************************************************/
2326 static void call_trans2findfirst(connection_struct *conn,
2327 struct smb_request *req,
2328 char **pparams, int total_params,
2329 char **ppdata, int total_data,
2330 unsigned int max_data_bytes)
2332 /* We must be careful here that we don't return more than the
2333 allowed number of data bytes. If this means returning fewer than
2334 maxentries then so be it. We assume that the redirector has
2335 enough room for the fixed number of parameter bytes it has
2336 requested. */
2337 struct smb_filename *smb_dname = NULL;
2338 char *params = *pparams;
2339 char *pdata = *ppdata;
2340 char *data_end;
2341 uint32 dirtype;
2342 int maxentries;
2343 uint16 findfirst_flags;
2344 bool close_after_first;
2345 bool close_if_end;
2346 bool requires_resume_key;
2347 int info_level;
2348 char *directory = NULL;
2349 char *mask = NULL;
2350 char *p;
2351 int last_entry_off=0;
2352 int dptr_num = -1;
2353 int numentries = 0;
2354 int i;
2355 bool finished = False;
2356 bool dont_descend = False;
2357 bool out_of_space = False;
2358 int space_remaining;
2359 bool mask_contains_wcard = False;
2360 struct ea_list *ea_list = NULL;
2361 NTSTATUS ntstatus = NT_STATUS_OK;
2362 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2363 TALLOC_CTX *ctx = talloc_tos();
2364 struct dptr_struct *dirptr = NULL;
2365 struct smbd_server_connection *sconn = req->sconn;
2366 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2367 bool backup_priv = false;
2369 if (total_params < 13) {
2370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 goto out;
2374 dirtype = SVAL(params,0);
2375 maxentries = SVAL(params,2);
2376 findfirst_flags = SVAL(params,4);
2377 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2378 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2379 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2380 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2381 security_token_has_privilege(get_current_nttok(conn),
2382 SEC_PRIV_BACKUP));
2384 info_level = SVAL(params,6);
2386 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2387 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2388 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2389 (int)backup_priv,
2390 info_level, max_data_bytes));
2392 if (!maxentries) {
2393 /* W2K3 seems to treat zero as 1. */
2394 maxentries = 1;
2397 switch (info_level) {
2398 case SMB_FIND_INFO_STANDARD:
2399 case SMB_FIND_EA_SIZE:
2400 case SMB_FIND_EA_LIST:
2401 case SMB_FIND_FILE_DIRECTORY_INFO:
2402 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2403 case SMB_FIND_FILE_NAMES_INFO:
2404 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2405 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2406 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2407 break;
2408 case SMB_FIND_FILE_UNIX:
2409 case SMB_FIND_FILE_UNIX_INFO2:
2410 /* Always use filesystem for UNIX mtime query. */
2411 ask_sharemode = false;
2412 if (!lp_unix_extensions()) {
2413 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2414 goto out;
2416 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2417 break;
2418 default:
2419 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2420 goto out;
2423 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2424 params+12, total_params - 12,
2425 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2426 if (!NT_STATUS_IS_OK(ntstatus)) {
2427 reply_nterror(req, ntstatus);
2428 goto out;
2431 if (backup_priv) {
2432 become_root();
2433 ntstatus = filename_convert_with_privilege(ctx,
2434 conn,
2435 req,
2436 directory,
2437 ucf_flags,
2438 &mask_contains_wcard,
2439 &smb_dname);
2440 } else {
2441 ntstatus = filename_convert(ctx, conn,
2442 req->flags2 & FLAGS2_DFS_PATHNAMES,
2443 directory,
2444 ucf_flags,
2445 &mask_contains_wcard,
2446 &smb_dname);
2449 if (!NT_STATUS_IS_OK(ntstatus)) {
2450 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2451 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2452 ERRSRV, ERRbadpath);
2453 goto out;
2455 reply_nterror(req, ntstatus);
2456 goto out;
2459 mask = smb_dname->original_lcomp;
2461 directory = smb_dname->base_name;
2463 p = strrchr_m(directory,'/');
2464 if(p == NULL) {
2465 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2466 if((directory[0] == '.') && (directory[1] == '\0')) {
2467 mask = talloc_strdup(ctx,"*");
2468 if (!mask) {
2469 reply_nterror(req, NT_STATUS_NO_MEMORY);
2470 goto out;
2472 mask_contains_wcard = True;
2474 } else {
2475 *p = 0;
2478 if (p == NULL || p == directory) {
2479 /* Ensure we don't have a directory name of "". */
2480 directory = talloc_strdup(talloc_tos(), ".");
2481 if (!directory) {
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 goto out;
2487 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2489 if (info_level == SMB_FIND_EA_LIST) {
2490 uint32 ea_size;
2492 if (total_data < 4) {
2493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2494 goto out;
2497 ea_size = IVAL(pdata,0);
2498 if (ea_size != total_data) {
2499 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2500 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2502 goto out;
2505 if (!lp_ea_support(SNUM(conn))) {
2506 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2507 goto out;
2510 /* Pull out the list of names. */
2511 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2512 if (!ea_list) {
2513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2514 goto out;
2518 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2520 goto out;
2523 *ppdata = (char *)SMB_REALLOC(
2524 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2525 if(*ppdata == NULL ) {
2526 reply_nterror(req, NT_STATUS_NO_MEMORY);
2527 goto out;
2529 pdata = *ppdata;
2530 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2532 /* Realloc the params space */
2533 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2534 if (*pparams == NULL) {
2535 reply_nterror(req, NT_STATUS_NO_MEMORY);
2536 goto out;
2538 params = *pparams;
2540 /* Save the wildcard match and attribs we are using on this directory -
2541 needed as lanman2 assumes these are being saved between calls */
2543 ntstatus = dptr_create(conn,
2544 req,
2545 NULL, /* fsp */
2546 directory,
2547 False,
2548 True,
2549 req->smbpid,
2550 mask,
2551 mask_contains_wcard,
2552 dirtype,
2553 &dirptr);
2555 if (!NT_STATUS_IS_OK(ntstatus)) {
2556 reply_nterror(req, ntstatus);
2557 goto out;
2560 if (backup_priv) {
2561 /* Remember this in case we have
2562 to do a findnext. */
2563 dptr_set_priv(dirptr);
2566 dptr_num = dptr_dnum(dirptr);
2567 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2569 /* Initialize per TRANS2_FIND_FIRST operation data */
2570 dptr_init_search_op(dirptr);
2572 /* We don't need to check for VOL here as this is returned by
2573 a different TRANS2 call. */
2575 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2576 directory,lp_dont_descend(ctx, SNUM(conn))));
2577 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2578 dont_descend = True;
2580 p = pdata;
2581 space_remaining = max_data_bytes;
2582 out_of_space = False;
2584 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2585 bool got_exact_match = False;
2587 /* this is a heuristic to avoid seeking the dirptr except when
2588 absolutely necessary. It allows for a filename of about 40 chars */
2589 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2590 out_of_space = True;
2591 finished = False;
2592 } else {
2593 finished = !get_lanman2_dir_entry(ctx,
2594 conn,
2595 dirptr,
2596 req->flags2,
2597 mask,dirtype,info_level,
2598 requires_resume_key,dont_descend,
2599 ask_sharemode,
2600 &p,pdata,data_end,
2601 space_remaining, &out_of_space,
2602 &got_exact_match,
2603 &last_entry_off, ea_list);
2606 if (finished && out_of_space)
2607 finished = False;
2609 if (!finished && !out_of_space)
2610 numentries++;
2613 * As an optimisation if we know we aren't looking
2614 * for a wildcard name (ie. the name matches the wildcard exactly)
2615 * then we can finish on any (first) match.
2616 * This speeds up large directory searches. JRA.
2619 if(got_exact_match)
2620 finished = True;
2622 /* Ensure space_remaining never goes -ve. */
2623 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2624 space_remaining = 0;
2625 out_of_space = true;
2626 } else {
2627 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2631 /* Check if we can close the dirptr */
2632 if(close_after_first || (finished && close_if_end)) {
2633 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2634 dptr_close(sconn, &dptr_num);
2638 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2639 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2640 * the protocol level is less than NT1. Tested with smbclient. JRA.
2641 * This should fix the OS/2 client bug #2335.
2644 if(numentries == 0) {
2645 dptr_close(sconn, &dptr_num);
2646 if (get_Protocol() < PROTOCOL_NT1) {
2647 reply_force_doserror(req, ERRDOS, ERRnofiles);
2648 goto out;
2649 } else {
2650 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2651 ERRDOS, ERRbadfile);
2652 goto out;
2656 /* At this point pdata points to numentries directory entries. */
2658 /* Set up the return parameter block */
2659 SSVAL(params,0,dptr_num);
2660 SSVAL(params,2,numentries);
2661 SSVAL(params,4,finished);
2662 SSVAL(params,6,0); /* Never an EA error */
2663 SSVAL(params,8,last_entry_off);
2665 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2666 max_data_bytes);
2668 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2669 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2670 if (!directory) {
2671 reply_nterror(req, NT_STATUS_NO_MEMORY);
2675 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2676 smb_fn_name(req->cmd),
2677 mask, directory, dirtype, numentries ) );
2680 * Force a name mangle here to ensure that the
2681 * mask as an 8.3 name is top of the mangled cache.
2682 * The reasons for this are subtle. Don't remove
2683 * this code unless you know what you are doing
2684 * (see PR#13758). JRA.
2687 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2688 char mangled_name[13];
2689 name_to_8_3(mask, mangled_name, True, conn->params);
2691 out:
2693 if (backup_priv) {
2694 unbecome_root();
2697 TALLOC_FREE(smb_dname);
2698 return;
2701 /****************************************************************************
2702 Reply to a TRANS2_FINDNEXT.
2703 ****************************************************************************/
2705 static void call_trans2findnext(connection_struct *conn,
2706 struct smb_request *req,
2707 char **pparams, int total_params,
2708 char **ppdata, int total_data,
2709 unsigned int max_data_bytes)
2711 /* We must be careful here that we don't return more than the
2712 allowed number of data bytes. If this means returning fewer than
2713 maxentries then so be it. We assume that the redirector has
2714 enough room for the fixed number of parameter bytes it has
2715 requested. */
2716 char *params = *pparams;
2717 char *pdata = *ppdata;
2718 char *data_end;
2719 int dptr_num;
2720 int maxentries;
2721 uint16 info_level;
2722 uint32 resume_key;
2723 uint16 findnext_flags;
2724 bool close_after_request;
2725 bool close_if_end;
2726 bool requires_resume_key;
2727 bool continue_bit;
2728 bool mask_contains_wcard = False;
2729 char *resume_name = NULL;
2730 const char *mask = NULL;
2731 const char *directory = NULL;
2732 char *p = NULL;
2733 uint16 dirtype;
2734 int numentries = 0;
2735 int i, last_entry_off=0;
2736 bool finished = False;
2737 bool dont_descend = False;
2738 bool out_of_space = False;
2739 int space_remaining;
2740 struct ea_list *ea_list = NULL;
2741 NTSTATUS ntstatus = NT_STATUS_OK;
2742 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2743 TALLOC_CTX *ctx = talloc_tos();
2744 struct dptr_struct *dirptr;
2745 struct smbd_server_connection *sconn = req->sconn;
2746 bool backup_priv = false;
2748 if (total_params < 13) {
2749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2750 return;
2753 dptr_num = SVAL(params,0);
2754 maxentries = SVAL(params,2);
2755 info_level = SVAL(params,4);
2756 resume_key = IVAL(params,6);
2757 findnext_flags = SVAL(params,10);
2758 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2759 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2760 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2761 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2763 if (!continue_bit) {
2764 /* We only need resume_name if continue_bit is zero. */
2765 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2766 params+12,
2767 total_params - 12, STR_TERMINATE, &ntstatus,
2768 &mask_contains_wcard);
2769 if (!NT_STATUS_IS_OK(ntstatus)) {
2770 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2771 complain (it thinks we're asking for the directory above the shared
2772 path or an invalid name). Catch this as the resume name is only compared, never used in
2773 a file access. JRA. */
2774 srvstr_pull_talloc(ctx, params, req->flags2,
2775 &resume_name, params+12,
2776 total_params - 12,
2777 STR_TERMINATE);
2779 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2780 reply_nterror(req, ntstatus);
2781 return;
2786 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2787 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2788 resume_key = %d resume name = %s continue=%d level = %d\n",
2789 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2790 requires_resume_key, resume_key,
2791 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2793 if (!maxentries) {
2794 /* W2K3 seems to treat zero as 1. */
2795 maxentries = 1;
2798 switch (info_level) {
2799 case SMB_FIND_INFO_STANDARD:
2800 case SMB_FIND_EA_SIZE:
2801 case SMB_FIND_EA_LIST:
2802 case SMB_FIND_FILE_DIRECTORY_INFO:
2803 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2804 case SMB_FIND_FILE_NAMES_INFO:
2805 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2806 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2807 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2808 break;
2809 case SMB_FIND_FILE_UNIX:
2810 case SMB_FIND_FILE_UNIX_INFO2:
2811 /* Always use filesystem for UNIX mtime query. */
2812 ask_sharemode = false;
2813 if (!lp_unix_extensions()) {
2814 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2815 return;
2817 break;
2818 default:
2819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2820 return;
2823 if (info_level == SMB_FIND_EA_LIST) {
2824 uint32 ea_size;
2826 if (total_data < 4) {
2827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2828 return;
2831 ea_size = IVAL(pdata,0);
2832 if (ea_size != total_data) {
2833 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2834 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2836 return;
2839 if (!lp_ea_support(SNUM(conn))) {
2840 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2841 return;
2844 /* Pull out the list of names. */
2845 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2846 if (!ea_list) {
2847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2848 return;
2852 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2854 return;
2857 *ppdata = (char *)SMB_REALLOC(
2858 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2859 if(*ppdata == NULL) {
2860 reply_nterror(req, NT_STATUS_NO_MEMORY);
2861 return;
2864 pdata = *ppdata;
2865 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2867 /* Realloc the params space */
2868 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2869 if(*pparams == NULL ) {
2870 reply_nterror(req, NT_STATUS_NO_MEMORY);
2871 return;
2874 params = *pparams;
2876 /* Check that the dptr is valid */
2877 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2878 reply_nterror(req, STATUS_NO_MORE_FILES);
2879 return;
2882 directory = dptr_path(sconn, dptr_num);
2884 /* Get the wildcard mask from the dptr */
2885 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2886 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2887 reply_nterror(req, STATUS_NO_MORE_FILES);
2888 return;
2891 /* Get the attr mask from the dptr */
2892 dirtype = dptr_attr(sconn, dptr_num);
2894 backup_priv = dptr_get_priv(dirptr);
2896 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2897 "backup_priv = %d\n",
2898 dptr_num, mask, dirtype,
2899 (long)dirptr,
2900 dptr_TellDir(dirptr),
2901 (int)backup_priv));
2903 /* Initialize per TRANS2_FIND_NEXT operation data */
2904 dptr_init_search_op(dirptr);
2906 /* We don't need to check for VOL here as this is returned by
2907 a different TRANS2 call. */
2909 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2910 directory,lp_dont_descend(ctx, SNUM(conn))));
2911 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2912 dont_descend = True;
2914 p = pdata;
2915 space_remaining = max_data_bytes;
2916 out_of_space = False;
2918 if (backup_priv) {
2919 become_root();
2923 * Seek to the correct position. We no longer use the resume key but
2924 * depend on the last file name instead.
2927 if(!continue_bit && resume_name && *resume_name) {
2928 SMB_STRUCT_STAT st;
2930 long current_pos = 0;
2932 * Remember, name_to_8_3 is called by
2933 * get_lanman2_dir_entry(), so the resume name
2934 * could be mangled. Ensure we check the unmangled name.
2937 if (mangle_is_mangled(resume_name, conn->params)) {
2938 char *new_resume_name = NULL;
2939 mangle_lookup_name_from_8_3(ctx,
2940 resume_name,
2941 &new_resume_name,
2942 conn->params);
2943 if (new_resume_name) {
2944 resume_name = new_resume_name;
2949 * Fix for NT redirector problem triggered by resume key indexes
2950 * changing between directory scans. We now return a resume key of 0
2951 * and instead look for the filename to continue from (also given
2952 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2953 * findfirst/findnext (as is usual) then the directory pointer
2954 * should already be at the correct place.
2957 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2958 } /* end if resume_name && !continue_bit */
2960 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2961 bool got_exact_match = False;
2963 /* this is a heuristic to avoid seeking the dirptr except when
2964 absolutely necessary. It allows for a filename of about 40 chars */
2965 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2966 out_of_space = True;
2967 finished = False;
2968 } else {
2969 finished = !get_lanman2_dir_entry(ctx,
2970 conn,
2971 dirptr,
2972 req->flags2,
2973 mask,dirtype,info_level,
2974 requires_resume_key,dont_descend,
2975 ask_sharemode,
2976 &p,pdata,data_end,
2977 space_remaining, &out_of_space,
2978 &got_exact_match,
2979 &last_entry_off, ea_list);
2982 if (finished && out_of_space)
2983 finished = False;
2985 if (!finished && !out_of_space)
2986 numentries++;
2989 * As an optimisation if we know we aren't looking
2990 * for a wildcard name (ie. the name matches the wildcard exactly)
2991 * then we can finish on any (first) match.
2992 * This speeds up large directory searches. JRA.
2995 if(got_exact_match)
2996 finished = True;
2998 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3001 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3002 smb_fn_name(req->cmd),
3003 mask, directory, dirtype, numentries ) );
3005 /* Check if we can close the dirptr */
3006 if(close_after_request || (finished && close_if_end)) {
3007 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3008 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3011 if (backup_priv) {
3012 unbecome_root();
3015 /* Set up the return parameter block */
3016 SSVAL(params,0,numentries);
3017 SSVAL(params,2,finished);
3018 SSVAL(params,4,0); /* Never an EA error */
3019 SSVAL(params,6,last_entry_off);
3021 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3022 max_data_bytes);
3024 return;
3027 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3029 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3030 return objid;
3033 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3035 SMB_ASSERT(extended_info != NULL);
3037 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3038 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3039 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3040 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3041 #ifdef SAMBA_VERSION_REVISION
3042 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3043 #endif
3044 extended_info->samba_subversion = 0;
3045 #ifdef SAMBA_VERSION_RC_RELEASE
3046 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3047 #else
3048 #ifdef SAMBA_VERSION_PRE_RELEASE
3049 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3050 #endif
3051 #endif
3052 #ifdef SAMBA_VERSION_VENDOR_PATCH
3053 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3054 #endif
3055 extended_info->samba_gitcommitdate = 0;
3056 #ifdef SAMBA_VERSION_COMMIT_TIME
3057 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3058 #endif
3060 memset(extended_info->samba_version_string, 0,
3061 sizeof(extended_info->samba_version_string));
3063 snprintf (extended_info->samba_version_string,
3064 sizeof(extended_info->samba_version_string),
3065 "%s", samba_version_string());
3068 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3069 connection_struct *conn,
3070 TALLOC_CTX *mem_ctx,
3071 uint16_t info_level,
3072 uint16_t flags2,
3073 unsigned int max_data_bytes,
3074 size_t *fixed_portion,
3075 struct smb_filename *fname,
3076 char **ppdata,
3077 int *ret_data_len)
3079 char *pdata, *end_data;
3080 int data_len = 0, len;
3081 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3082 int snum = SNUM(conn);
3083 const char *fstype = lp_fstype(SNUM(conn));
3084 const char *filename = NULL;
3085 uint32 additional_flags = 0;
3086 struct smb_filename smb_fname;
3087 SMB_STRUCT_STAT st;
3088 NTSTATUS status = NT_STATUS_OK;
3090 if (fname == NULL || fname->base_name == NULL) {
3091 filename = ".";
3092 } else {
3093 filename = fname->base_name;
3096 if (IS_IPC(conn)) {
3097 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3098 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3099 "info level (0x%x) on IPC$.\n",
3100 (unsigned int)info_level));
3101 return NT_STATUS_ACCESS_DENIED;
3105 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3107 ZERO_STRUCT(smb_fname);
3108 smb_fname.base_name = discard_const_p(char, filename);
3110 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3111 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3112 return map_nt_error_from_unix(errno);
3115 st = smb_fname.st;
3117 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3118 return NT_STATUS_INVALID_PARAMETER;
3121 *ppdata = (char *)SMB_REALLOC(
3122 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3123 if (*ppdata == NULL) {
3124 return NT_STATUS_NO_MEMORY;
3127 pdata = *ppdata;
3128 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3129 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3131 *fixed_portion = 0;
3133 switch (info_level) {
3134 case SMB_INFO_ALLOCATION:
3136 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3137 data_len = 18;
3138 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3139 return map_nt_error_from_unix(errno);
3142 block_size = lp_block_size(snum);
3143 if (bsize < block_size) {
3144 uint64_t factor = block_size/bsize;
3145 bsize = block_size;
3146 dsize /= factor;
3147 dfree /= factor;
3149 if (bsize > block_size) {
3150 uint64_t factor = bsize/block_size;
3151 bsize = block_size;
3152 dsize *= factor;
3153 dfree *= factor;
3155 bytes_per_sector = 512;
3156 sectors_per_unit = bsize/bytes_per_sector;
3158 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3159 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3160 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3162 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3163 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3164 SIVAL(pdata,l1_cUnit,dsize);
3165 SIVAL(pdata,l1_cUnitAvail,dfree);
3166 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3167 break;
3170 case SMB_INFO_VOLUME:
3171 /* Return volume name */
3173 * Add volume serial number - hash of a combination of
3174 * the called hostname and the service name.
3176 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3178 * Win2k3 and previous mess this up by sending a name length
3179 * one byte short. I believe only older clients (OS/2 Win9x) use
3180 * this call so try fixing this by adding a terminating null to
3181 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3183 len = srvstr_push(
3184 pdata, flags2,
3185 pdata+l2_vol_szVolLabel, vname,
3186 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3187 STR_NOALIGN|STR_TERMINATE);
3188 SCVAL(pdata,l2_vol_cch,len);
3189 data_len = l2_vol_szVolLabel + len;
3190 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3191 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3192 len, vname));
3193 break;
3195 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3196 case SMB_FS_ATTRIBUTE_INFORMATION:
3198 additional_flags = 0;
3199 #if defined(HAVE_SYS_QUOTAS)
3200 additional_flags |= FILE_VOLUME_QUOTAS;
3201 #endif
3203 if(lp_nt_acl_support(SNUM(conn))) {
3204 additional_flags |= FILE_PERSISTENT_ACLS;
3207 /* Capabilities are filled in at connection time through STATVFS call */
3208 additional_flags |= conn->fs_capabilities;
3209 additional_flags |= lp_parm_int(conn->params->service,
3210 "share", "fake_fscaps",
3213 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3214 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3215 additional_flags); /* FS ATTRIBUTES */
3217 SIVAL(pdata,4,255); /* Max filename component length */
3218 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3219 and will think we can't do long filenames */
3220 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3221 PTR_DIFF(end_data, pdata+12),
3222 STR_UNICODE);
3223 SIVAL(pdata,8,len);
3224 data_len = 12 + len;
3225 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3226 /* the client only requested a portion of the
3227 file system name */
3228 data_len = max_data_bytes;
3229 status = STATUS_BUFFER_OVERFLOW;
3231 *fixed_portion = 16;
3232 break;
3234 case SMB_QUERY_FS_LABEL_INFO:
3235 case SMB_FS_LABEL_INFORMATION:
3236 len = srvstr_push(pdata, flags2, pdata+4, vname,
3237 PTR_DIFF(end_data, pdata+4), 0);
3238 data_len = 4 + len;
3239 SIVAL(pdata,0,len);
3240 break;
3242 case SMB_QUERY_FS_VOLUME_INFO:
3243 case SMB_FS_VOLUME_INFORMATION:
3246 * Add volume serial number - hash of a combination of
3247 * the called hostname and the service name.
3249 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3250 (str_checksum(get_local_machine_name())<<16));
3252 /* Max label len is 32 characters. */
3253 len = srvstr_push(pdata, flags2, pdata+18, vname,
3254 PTR_DIFF(end_data, pdata+18),
3255 STR_UNICODE);
3256 SIVAL(pdata,12,len);
3257 data_len = 18+len;
3259 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3260 (int)strlen(vname),vname,
3261 lp_servicename(talloc_tos(), snum)));
3262 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3263 /* the client only requested a portion of the
3264 volume label */
3265 data_len = max_data_bytes;
3266 status = STATUS_BUFFER_OVERFLOW;
3268 *fixed_portion = 24;
3269 break;
3271 case SMB_QUERY_FS_SIZE_INFO:
3272 case SMB_FS_SIZE_INFORMATION:
3274 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3275 data_len = 24;
3276 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno);
3279 block_size = lp_block_size(snum);
3280 if (bsize < block_size) {
3281 uint64_t factor = block_size/bsize;
3282 bsize = block_size;
3283 dsize /= factor;
3284 dfree /= factor;
3286 if (bsize > block_size) {
3287 uint64_t factor = bsize/block_size;
3288 bsize = block_size;
3289 dsize *= factor;
3290 dfree *= factor;
3292 bytes_per_sector = 512;
3293 sectors_per_unit = bsize/bytes_per_sector;
3294 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3295 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3296 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3297 SBIG_UINT(pdata,0,dsize);
3298 SBIG_UINT(pdata,8,dfree);
3299 SIVAL(pdata,16,sectors_per_unit);
3300 SIVAL(pdata,20,bytes_per_sector);
3301 *fixed_portion = 24;
3302 break;
3305 case SMB_FS_FULL_SIZE_INFORMATION:
3307 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3308 data_len = 32;
3309 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3310 return map_nt_error_from_unix(errno);
3312 block_size = lp_block_size(snum);
3313 if (bsize < block_size) {
3314 uint64_t factor = block_size/bsize;
3315 bsize = block_size;
3316 dsize /= factor;
3317 dfree /= factor;
3319 if (bsize > block_size) {
3320 uint64_t factor = bsize/block_size;
3321 bsize = block_size;
3322 dsize *= factor;
3323 dfree *= factor;
3325 bytes_per_sector = 512;
3326 sectors_per_unit = bsize/bytes_per_sector;
3327 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3328 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3329 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3330 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3331 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3332 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3333 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3334 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3335 *fixed_portion = 32;
3336 break;
3339 case SMB_QUERY_FS_DEVICE_INFO:
3340 case SMB_FS_DEVICE_INFORMATION:
3342 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3344 if (!CAN_WRITE(conn)) {
3345 characteristics |= FILE_READ_ONLY_DEVICE;
3347 data_len = 8;
3348 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3349 SIVAL(pdata,4,characteristics);
3350 *fixed_portion = 8;
3351 break;
3354 #ifdef HAVE_SYS_QUOTAS
3355 case SMB_FS_QUOTA_INFORMATION:
3357 * what we have to send --metze:
3359 * Unknown1: 24 NULL bytes
3360 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3361 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3362 * Quota Flags: 2 byte :
3363 * Unknown3: 6 NULL bytes
3365 * 48 bytes total
3367 * details for Quota Flags:
3369 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3370 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3371 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3372 * 0x0001 Enable Quotas: enable quota for this fs
3376 /* we need to fake up a fsp here,
3377 * because its not send in this call
3379 files_struct fsp;
3380 SMB_NTQUOTA_STRUCT quotas;
3382 ZERO_STRUCT(fsp);
3383 ZERO_STRUCT(quotas);
3385 fsp.conn = conn;
3386 fsp.fnum = FNUM_FIELD_INVALID;
3388 /* access check */
3389 if (get_current_uid(conn) != 0) {
3390 DEBUG(0,("get_user_quota: access_denied "
3391 "service [%s] user [%s]\n",
3392 lp_servicename(talloc_tos(), SNUM(conn)),
3393 conn->session_info->unix_info->unix_name));
3394 return NT_STATUS_ACCESS_DENIED;
3397 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3398 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3399 return map_nt_error_from_unix(errno);
3402 data_len = 48;
3404 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3405 lp_servicename(talloc_tos(), SNUM(conn))));
3407 /* Unknown1 24 NULL bytes*/
3408 SBIG_UINT(pdata,0,(uint64_t)0);
3409 SBIG_UINT(pdata,8,(uint64_t)0);
3410 SBIG_UINT(pdata,16,(uint64_t)0);
3412 /* Default Soft Quota 8 bytes */
3413 SBIG_UINT(pdata,24,quotas.softlim);
3415 /* Default Hard Quota 8 bytes */
3416 SBIG_UINT(pdata,32,quotas.hardlim);
3418 /* Quota flag 2 bytes */
3419 SSVAL(pdata,40,quotas.qflags);
3421 /* Unknown3 6 NULL bytes */
3422 SSVAL(pdata,42,0);
3423 SIVAL(pdata,44,0);
3425 break;
3427 #endif /* HAVE_SYS_QUOTAS */
3428 case SMB_FS_OBJECTID_INFORMATION:
3430 unsigned char objid[16];
3431 struct smb_extended_info extended_info;
3432 memcpy(pdata,create_volume_objectid(conn, objid),16);
3433 samba_extended_info_version (&extended_info);
3434 SIVAL(pdata,16,extended_info.samba_magic);
3435 SIVAL(pdata,20,extended_info.samba_version);
3436 SIVAL(pdata,24,extended_info.samba_subversion);
3437 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3438 memcpy(pdata+36,extended_info.samba_version_string,28);
3439 data_len = 64;
3440 break;
3444 * Query the version and capabilities of the CIFS UNIX extensions
3445 * in use.
3448 case SMB_QUERY_CIFS_UNIX_INFO:
3450 bool large_write = lp_min_receive_file_size() &&
3451 !srv_is_signing_active(xconn);
3452 bool large_read = !srv_is_signing_active(xconn);
3453 int encrypt_caps = 0;
3455 if (!lp_unix_extensions()) {
3456 return NT_STATUS_INVALID_LEVEL;
3459 switch (conn->encrypt_level) {
3460 case SMB_SIGNING_OFF:
3461 encrypt_caps = 0;
3462 break;
3463 case SMB_SIGNING_IF_REQUIRED:
3464 case SMB_SIGNING_DEFAULT:
3465 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3466 break;
3467 case SMB_SIGNING_REQUIRED:
3468 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3469 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3470 large_write = false;
3471 large_read = false;
3472 break;
3475 data_len = 12;
3476 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3477 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3479 /* We have POSIX ACLs, pathname, encryption,
3480 * large read/write, and locking capability. */
3482 SBIG_UINT(pdata,4,((uint64_t)(
3483 CIFS_UNIX_POSIX_ACLS_CAP|
3484 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3485 CIFS_UNIX_FCNTL_LOCKS_CAP|
3486 CIFS_UNIX_EXTATTR_CAP|
3487 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3488 encrypt_caps|
3489 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3490 (large_write ?
3491 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3492 break;
3495 case SMB_QUERY_POSIX_FS_INFO:
3497 int rc;
3498 vfs_statvfs_struct svfs;
3500 if (!lp_unix_extensions()) {
3501 return NT_STATUS_INVALID_LEVEL;
3504 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3506 if (!rc) {
3507 data_len = 56;
3508 SIVAL(pdata,0,svfs.OptimalTransferSize);
3509 SIVAL(pdata,4,svfs.BlockSize);
3510 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3511 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3512 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3513 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3514 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3515 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3516 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3517 #ifdef EOPNOTSUPP
3518 } else if (rc == EOPNOTSUPP) {
3519 return NT_STATUS_INVALID_LEVEL;
3520 #endif /* EOPNOTSUPP */
3521 } else {
3522 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3523 return NT_STATUS_DOS(ERRSRV, ERRerror);
3525 break;
3528 case SMB_QUERY_POSIX_WHOAMI:
3530 uint32_t flags = 0;
3531 uint32_t sid_bytes;
3532 int i;
3534 if (!lp_unix_extensions()) {
3535 return NT_STATUS_INVALID_LEVEL;
3538 if (max_data_bytes < 40) {
3539 return NT_STATUS_BUFFER_TOO_SMALL;
3542 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3543 flags |= SMB_WHOAMI_GUEST;
3546 /* NOTE: 8 bytes for UID/GID, irrespective of native
3547 * platform size. This matches
3548 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3550 data_len = 4 /* flags */
3551 + 4 /* flag mask */
3552 + 8 /* uid */
3553 + 8 /* gid */
3554 + 4 /* ngroups */
3555 + 4 /* num_sids */
3556 + 4 /* SID bytes */
3557 + 4 /* pad/reserved */
3558 + (conn->session_info->unix_token->ngroups * 8)
3559 /* groups list */
3560 + (conn->session_info->security_token->num_sids *
3561 SID_MAX_SIZE)
3562 /* SID list */;
3564 SIVAL(pdata, 0, flags);
3565 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3566 SBIG_UINT(pdata, 8,
3567 (uint64_t)conn->session_info->unix_token->uid);
3568 SBIG_UINT(pdata, 16,
3569 (uint64_t)conn->session_info->unix_token->gid);
3572 if (data_len >= max_data_bytes) {
3573 /* Potential overflow, skip the GIDs and SIDs. */
3575 SIVAL(pdata, 24, 0); /* num_groups */
3576 SIVAL(pdata, 28, 0); /* num_sids */
3577 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3578 SIVAL(pdata, 36, 0); /* reserved */
3580 data_len = 40;
3581 break;
3584 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3585 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3587 /* We walk the SID list twice, but this call is fairly
3588 * infrequent, and I don't expect that it's performance
3589 * sensitive -- jpeach
3591 for (i = 0, sid_bytes = 0;
3592 i < conn->session_info->security_token->num_sids; ++i) {
3593 sid_bytes += ndr_size_dom_sid(
3594 &conn->session_info->security_token->sids[i],
3598 /* SID list byte count */
3599 SIVAL(pdata, 32, sid_bytes);
3601 /* 4 bytes pad/reserved - must be zero */
3602 SIVAL(pdata, 36, 0);
3603 data_len = 40;
3605 /* GID list */
3606 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3607 SBIG_UINT(pdata, data_len,
3608 (uint64_t)conn->session_info->unix_token->groups[i]);
3609 data_len += 8;
3612 /* SID list */
3613 for (i = 0;
3614 i < conn->session_info->security_token->num_sids; ++i) {
3615 int sid_len = ndr_size_dom_sid(
3616 &conn->session_info->security_token->sids[i],
3619 sid_linearize(pdata + data_len, sid_len,
3620 &conn->session_info->security_token->sids[i]);
3621 data_len += sid_len;
3624 break;
3627 case SMB_MAC_QUERY_FS_INFO:
3629 * Thursby MAC extension... ONLY on NTFS filesystems
3630 * once we do streams then we don't need this
3632 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3633 data_len = 88;
3634 SIVAL(pdata,84,0x100); /* Don't support mac... */
3635 break;
3637 /* drop through */
3638 default:
3639 return NT_STATUS_INVALID_LEVEL;
3642 *ret_data_len = data_len;
3643 return status;
3646 /****************************************************************************
3647 Reply to a TRANS2_QFSINFO (query filesystem info).
3648 ****************************************************************************/
3650 static void call_trans2qfsinfo(connection_struct *conn,
3651 struct smb_request *req,
3652 char **pparams, int total_params,
3653 char **ppdata, int total_data,
3654 unsigned int max_data_bytes)
3656 char *params = *pparams;
3657 uint16_t info_level;
3658 int data_len = 0;
3659 size_t fixed_portion;
3660 NTSTATUS status;
3662 if (total_params < 2) {
3663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3664 return;
3667 info_level = SVAL(params,0);
3669 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3670 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3671 DEBUG(0,("call_trans2qfsinfo: encryption required "
3672 "and info level 0x%x sent.\n",
3673 (unsigned int)info_level));
3674 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3675 return;
3679 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3681 status = smbd_do_qfsinfo(req->xconn, conn, req,
3682 info_level,
3683 req->flags2,
3684 max_data_bytes,
3685 &fixed_portion,
3686 NULL,
3687 ppdata, &data_len);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 reply_nterror(req, status);
3690 return;
3693 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3694 max_data_bytes);
3696 DEBUG( 4, ( "%s info_level = %d\n",
3697 smb_fn_name(req->cmd), info_level) );
3699 return;
3702 /****************************************************************************
3703 Reply to a TRANS2_SETFSINFO (set filesystem info).
3704 ****************************************************************************/
3706 static void call_trans2setfsinfo(connection_struct *conn,
3707 struct smb_request *req,
3708 char **pparams, int total_params,
3709 char **ppdata, int total_data,
3710 unsigned int max_data_bytes)
3712 struct smbXsrv_connection *xconn = req->xconn;
3713 char *pdata = *ppdata;
3714 char *params = *pparams;
3715 uint16 info_level;
3717 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3718 lp_servicename(talloc_tos(), SNUM(conn))));
3720 /* */
3721 if (total_params < 4) {
3722 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3723 total_params));
3724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3725 return;
3728 info_level = SVAL(params,2);
3730 if (IS_IPC(conn)) {
3731 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3732 info_level != SMB_SET_CIFS_UNIX_INFO) {
3733 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3734 "info level (0x%x) on IPC$.\n",
3735 (unsigned int)info_level));
3736 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3737 return;
3741 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3742 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3743 DEBUG(0,("call_trans2setfsinfo: encryption required "
3744 "and info level 0x%x sent.\n",
3745 (unsigned int)info_level));
3746 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3747 return;
3751 switch(info_level) {
3752 case SMB_SET_CIFS_UNIX_INFO:
3753 if (!lp_unix_extensions()) {
3754 DEBUG(2,("call_trans2setfsinfo: "
3755 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3756 "unix extensions off\n"));
3757 reply_nterror(req,
3758 NT_STATUS_INVALID_LEVEL);
3759 return;
3762 /* There should be 12 bytes of capabilities set. */
3763 if (total_data < 12) {
3764 reply_nterror(
3765 req,
3766 NT_STATUS_INVALID_PARAMETER);
3767 return;
3769 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3770 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3771 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3772 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3773 /* Just print these values for now. */
3774 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3775 "major = %u, minor = %u cap_low = 0x%x, "
3776 "cap_high = 0x%xn",
3777 (unsigned int)xconn->
3778 smb1.unix_info.client_major,
3779 (unsigned int)xconn->
3780 smb1.unix_info.client_minor,
3781 (unsigned int)xconn->
3782 smb1.unix_info.client_cap_low,
3783 (unsigned int)xconn->
3784 smb1.unix_info.client_cap_high));
3786 /* Here is where we must switch to posix pathname processing... */
3787 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3788 lp_set_posix_pathnames();
3789 mangle_change_to_posix();
3792 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3793 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3794 /* Client that knows how to do posix locks,
3795 * but not posix open/mkdir operations. Set a
3796 * default type for read/write checks. */
3798 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3801 break;
3803 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3805 NTSTATUS status;
3806 size_t param_len = 0;
3807 size_t data_len = total_data;
3809 if (!lp_unix_extensions()) {
3810 reply_nterror(
3811 req,
3812 NT_STATUS_INVALID_LEVEL);
3813 return;
3816 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3817 reply_nterror(
3818 req,
3819 NT_STATUS_NOT_SUPPORTED);
3820 return;
3823 if (xconn->smb1.echo_handler.trusted_fde) {
3824 DEBUG( 2,("call_trans2setfsinfo: "
3825 "request transport encryption disabled"
3826 "with 'fork echo handler = yes'\n"));
3827 reply_nterror(
3828 req,
3829 NT_STATUS_NOT_SUPPORTED);
3830 return;
3833 DEBUG( 4,("call_trans2setfsinfo: "
3834 "request transport encryption.\n"));
3836 status = srv_request_encryption_setup(conn,
3837 (unsigned char **)ppdata,
3838 &data_len,
3839 (unsigned char **)pparams,
3840 &param_len);
3842 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3843 !NT_STATUS_IS_OK(status)) {
3844 reply_nterror(req, status);
3845 return;
3848 send_trans2_replies(conn, req,
3849 NT_STATUS_OK,
3850 *pparams,
3851 param_len,
3852 *ppdata,
3853 data_len,
3854 max_data_bytes);
3856 if (NT_STATUS_IS_OK(status)) {
3857 /* Server-side transport
3858 * encryption is now *on*. */
3859 status = srv_encryption_start(conn);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 char *reason = talloc_asprintf(talloc_tos(),
3862 "Failure in setting "
3863 "up encrypted transport: %s",
3864 nt_errstr(status));
3865 exit_server_cleanly(reason);
3868 return;
3871 case SMB_FS_QUOTA_INFORMATION:
3873 files_struct *fsp = NULL;
3874 SMB_NTQUOTA_STRUCT quotas;
3876 ZERO_STRUCT(quotas);
3878 /* access check */
3879 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3880 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3881 lp_servicename(talloc_tos(), SNUM(conn)),
3882 conn->session_info->unix_info->unix_name));
3883 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3884 return;
3887 /* note: normaly there're 48 bytes,
3888 * but we didn't use the last 6 bytes for now
3889 * --metze
3891 fsp = file_fsp(req, SVAL(params,0));
3893 if (!check_fsp_ntquota_handle(conn, req,
3894 fsp)) {
3895 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3896 reply_nterror(
3897 req, NT_STATUS_INVALID_HANDLE);
3898 return;
3901 if (total_data < 42) {
3902 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3903 total_data));
3904 reply_nterror(
3905 req,
3906 NT_STATUS_INVALID_PARAMETER);
3907 return;
3910 /* unknown_1 24 NULL bytes in pdata*/
3912 /* the soft quotas 8 bytes (uint64_t)*/
3913 quotas.softlim = BVAL(pdata,24);
3915 /* the hard quotas 8 bytes (uint64_t)*/
3916 quotas.hardlim = BVAL(pdata,32);
3918 /* quota_flags 2 bytes **/
3919 quotas.qflags = SVAL(pdata,40);
3921 /* unknown_2 6 NULL bytes follow*/
3923 /* now set the quotas */
3924 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3925 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3926 reply_nterror(req, map_nt_error_from_unix(errno));
3927 return;
3930 break;
3932 default:
3933 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3934 info_level));
3935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3936 return;
3937 break;
3941 * sending this reply works fine,
3942 * but I'm not sure it's the same
3943 * like windows do...
3944 * --metze
3946 reply_outbuf(req, 10, 0);
3949 #if defined(HAVE_POSIX_ACLS)
3950 /****************************************************************************
3951 Utility function to count the number of entries in a POSIX acl.
3952 ****************************************************************************/
3954 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3956 unsigned int ace_count = 0;
3957 int entry_id = SMB_ACL_FIRST_ENTRY;
3958 SMB_ACL_ENTRY_T entry;
3960 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3961 /* get_next... */
3962 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3963 entry_id = SMB_ACL_NEXT_ENTRY;
3965 ace_count++;
3967 return ace_count;
3970 /****************************************************************************
3971 Utility function to marshall a POSIX acl into wire format.
3972 ****************************************************************************/
3974 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3976 int entry_id = SMB_ACL_FIRST_ENTRY;
3977 SMB_ACL_ENTRY_T entry;
3979 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3980 SMB_ACL_TAG_T tagtype;
3981 SMB_ACL_PERMSET_T permset;
3982 unsigned char perms = 0;
3983 unsigned int own_grp;
3985 /* get_next... */
3986 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3987 entry_id = SMB_ACL_NEXT_ENTRY;
3990 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3991 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3992 return False;
3995 if (sys_acl_get_permset(entry, &permset) == -1) {
3996 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3997 return False;
4000 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4001 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4002 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4004 SCVAL(pdata,1,perms);
4006 switch (tagtype) {
4007 case SMB_ACL_USER_OBJ:
4008 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4009 own_grp = (unsigned int)pst->st_ex_uid;
4010 SIVAL(pdata,2,own_grp);
4011 SIVAL(pdata,6,0);
4012 break;
4013 case SMB_ACL_USER:
4015 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4016 if (!puid) {
4017 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4018 return False;
4020 own_grp = (unsigned int)*puid;
4021 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4022 SIVAL(pdata,2,own_grp);
4023 SIVAL(pdata,6,0);
4024 break;
4026 case SMB_ACL_GROUP_OBJ:
4027 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4028 own_grp = (unsigned int)pst->st_ex_gid;
4029 SIVAL(pdata,2,own_grp);
4030 SIVAL(pdata,6,0);
4031 break;
4032 case SMB_ACL_GROUP:
4034 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4035 if (!pgid) {
4036 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4037 return False;
4039 own_grp = (unsigned int)*pgid;
4040 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4041 SIVAL(pdata,2,own_grp);
4042 SIVAL(pdata,6,0);
4043 break;
4045 case SMB_ACL_MASK:
4046 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4047 SIVAL(pdata,2,0xFFFFFFFF);
4048 SIVAL(pdata,6,0xFFFFFFFF);
4049 break;
4050 case SMB_ACL_OTHER:
4051 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4052 SIVAL(pdata,2,0xFFFFFFFF);
4053 SIVAL(pdata,6,0xFFFFFFFF);
4054 break;
4055 default:
4056 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4057 return False;
4059 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4062 return True;
4064 #endif
4066 /****************************************************************************
4067 Store the FILE_UNIX_BASIC info.
4068 ****************************************************************************/
4070 static char *store_file_unix_basic(connection_struct *conn,
4071 char *pdata,
4072 files_struct *fsp,
4073 const SMB_STRUCT_STAT *psbuf)
4075 uint64_t file_index = get_FileIndex(conn, psbuf);
4076 dev_t devno;
4078 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4079 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4081 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4082 pdata += 8;
4084 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4085 pdata += 8;
4087 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4088 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4089 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4090 pdata += 24;
4092 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4093 SIVAL(pdata,4,0);
4094 pdata += 8;
4096 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4097 SIVAL(pdata,4,0);
4098 pdata += 8;
4100 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4101 pdata += 4;
4103 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4104 devno = psbuf->st_ex_rdev;
4105 } else {
4106 devno = psbuf->st_ex_dev;
4109 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4110 SIVAL(pdata,4,0);
4111 pdata += 8;
4113 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4114 SIVAL(pdata,4,0);
4115 pdata += 8;
4117 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4118 pdata += 8;
4120 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4121 SIVAL(pdata,4,0);
4122 pdata += 8;
4124 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4125 SIVAL(pdata,4,0);
4126 pdata += 8;
4128 return pdata;
4131 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4132 * the chflags(2) (or equivalent) flags.
4134 * XXX: this really should be behind the VFS interface. To do this, we would
4135 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4136 * Each VFS module could then implement its own mapping as appropriate for the
4137 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4139 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4140 info2_flags_map[] =
4142 #ifdef UF_NODUMP
4143 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4144 #endif
4146 #ifdef UF_IMMUTABLE
4147 { UF_IMMUTABLE, EXT_IMMUTABLE },
4148 #endif
4150 #ifdef UF_APPEND
4151 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4152 #endif
4154 #ifdef UF_HIDDEN
4155 { UF_HIDDEN, EXT_HIDDEN },
4156 #endif
4158 /* Do not remove. We need to guarantee that this array has at least one
4159 * entry to build on HP-UX.
4161 { 0, 0 }
4165 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4166 uint32 *smb_fflags, uint32 *smb_fmask)
4168 int i;
4170 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4171 *smb_fmask |= info2_flags_map[i].smb_fflag;
4172 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4173 *smb_fflags |= info2_flags_map[i].smb_fflag;
4178 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4179 const uint32 smb_fflags,
4180 const uint32 smb_fmask,
4181 int *stat_fflags)
4183 uint32 max_fmask = 0;
4184 int i;
4186 *stat_fflags = psbuf->st_ex_flags;
4188 /* For each flags requested in smb_fmask, check the state of the
4189 * corresponding flag in smb_fflags and set or clear the matching
4190 * stat flag.
4193 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4194 max_fmask |= info2_flags_map[i].smb_fflag;
4195 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4196 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4197 *stat_fflags |= info2_flags_map[i].stat_fflag;
4198 } else {
4199 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4204 /* If smb_fmask is asking to set any bits that are not supported by
4205 * our flag mappings, we should fail.
4207 if ((smb_fmask & max_fmask) != smb_fmask) {
4208 return False;
4211 return True;
4215 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4216 * of file flags and birth (create) time.
4218 static char *store_file_unix_basic_info2(connection_struct *conn,
4219 char *pdata,
4220 files_struct *fsp,
4221 const SMB_STRUCT_STAT *psbuf)
4223 uint32 file_flags = 0;
4224 uint32 flags_mask = 0;
4226 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4228 /* Create (birth) time 64 bit */
4229 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4230 pdata += 8;
4232 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4233 SIVAL(pdata, 0, file_flags); /* flags */
4234 SIVAL(pdata, 4, flags_mask); /* mask */
4235 pdata += 8;
4237 return pdata;
4240 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4241 const struct stream_struct *streams,
4242 char *data,
4243 unsigned int max_data_bytes,
4244 unsigned int *data_size)
4246 unsigned int i;
4247 unsigned int ofs = 0;
4249 if (max_data_bytes < 32) {
4250 return NT_STATUS_INFO_LENGTH_MISMATCH;
4253 for (i = 0; i < num_streams; i++) {
4254 unsigned int next_offset;
4255 size_t namelen;
4256 smb_ucs2_t *namebuf;
4258 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4259 streams[i].name, &namelen) ||
4260 namelen <= 2)
4262 return NT_STATUS_INVALID_PARAMETER;
4266 * name_buf is now null-terminated, we need to marshall as not
4267 * terminated
4270 namelen -= 2;
4273 * We cannot overflow ...
4275 if ((ofs + 24 + namelen) > max_data_bytes) {
4276 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4277 i));
4278 TALLOC_FREE(namebuf);
4279 return STATUS_BUFFER_OVERFLOW;
4282 SIVAL(data, ofs+4, namelen);
4283 SOFF_T(data, ofs+8, streams[i].size);
4284 SOFF_T(data, ofs+16, streams[i].alloc_size);
4285 memcpy(data+ofs+24, namebuf, namelen);
4286 TALLOC_FREE(namebuf);
4288 next_offset = ofs + 24 + namelen;
4290 if (i == num_streams-1) {
4291 SIVAL(data, ofs, 0);
4293 else {
4294 unsigned int align = ndr_align_size(next_offset, 8);
4296 if ((next_offset + align) > max_data_bytes) {
4297 DEBUG(10, ("refusing to overflow align "
4298 "reply at stream %u\n",
4299 i));
4300 TALLOC_FREE(namebuf);
4301 return STATUS_BUFFER_OVERFLOW;
4304 memset(data+next_offset, 0, align);
4305 next_offset += align;
4307 SIVAL(data, ofs, next_offset - ofs);
4308 ofs = next_offset;
4311 ofs = next_offset;
4314 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4316 *data_size = ofs;
4318 return NT_STATUS_OK;
4321 /****************************************************************************
4322 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4323 ****************************************************************************/
4325 static void call_trans2qpipeinfo(connection_struct *conn,
4326 struct smb_request *req,
4327 unsigned int tran_call,
4328 char **pparams, int total_params,
4329 char **ppdata, int total_data,
4330 unsigned int max_data_bytes)
4332 char *params = *pparams;
4333 char *pdata = *ppdata;
4334 unsigned int data_size = 0;
4335 unsigned int param_size = 2;
4336 uint16 info_level;
4337 files_struct *fsp;
4339 if (!params) {
4340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4341 return;
4344 if (total_params < 4) {
4345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4346 return;
4349 fsp = file_fsp(req, SVAL(params,0));
4350 if (!fsp_is_np(fsp)) {
4351 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4352 return;
4355 info_level = SVAL(params,2);
4357 *pparams = (char *)SMB_REALLOC(*pparams,2);
4358 if (*pparams == NULL) {
4359 reply_nterror(req, NT_STATUS_NO_MEMORY);
4360 return;
4362 params = *pparams;
4363 SSVAL(params,0,0);
4364 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4366 return;
4368 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4369 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4370 if (*ppdata == NULL ) {
4371 reply_nterror(req, NT_STATUS_NO_MEMORY);
4372 return;
4374 pdata = *ppdata;
4376 switch (info_level) {
4377 case SMB_FILE_STANDARD_INFORMATION:
4378 memset(pdata,0,24);
4379 SOFF_T(pdata,0,4096LL);
4380 SIVAL(pdata,16,1);
4381 SIVAL(pdata,20,1);
4382 data_size = 24;
4383 break;
4385 default:
4386 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4387 return;
4390 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4391 max_data_bytes);
4393 return;
4396 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4397 TALLOC_CTX *mem_ctx,
4398 uint16_t info_level,
4399 files_struct *fsp,
4400 struct smb_filename *smb_fname,
4401 bool delete_pending,
4402 struct timespec write_time_ts,
4403 struct ea_list *ea_list,
4404 int lock_data_count,
4405 char *lock_data,
4406 uint16_t flags2,
4407 unsigned int max_data_bytes,
4408 size_t *fixed_portion,
4409 char **ppdata,
4410 unsigned int *pdata_size)
4412 char *pdata = *ppdata;
4413 char *dstart, *dend;
4414 unsigned int data_size;
4415 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4416 time_t create_time, mtime, atime, c_time;
4417 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4418 char *p;
4419 char *base_name;
4420 char *dos_fname;
4421 int mode;
4422 int nlink;
4423 NTSTATUS status;
4424 uint64_t file_size = 0;
4425 uint64_t pos = 0;
4426 uint64_t allocation_size = 0;
4427 uint64_t file_index = 0;
4428 uint32_t access_mask = 0;
4430 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4431 return NT_STATUS_INVALID_LEVEL;
4434 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4435 smb_fname_str_dbg(smb_fname),
4436 fsp_fnum_dbg(fsp),
4437 info_level, max_data_bytes));
4439 mode = dos_mode(conn, smb_fname);
4440 nlink = psbuf->st_ex_nlink;
4442 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4443 nlink = 1;
4446 if ((nlink > 0) && delete_pending) {
4447 nlink -= 1;
4450 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4451 return NT_STATUS_INVALID_PARAMETER;
4454 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4455 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4456 if (*ppdata == NULL) {
4457 return NT_STATUS_NO_MEMORY;
4459 pdata = *ppdata;
4460 dstart = pdata;
4461 dend = dstart + data_size - 1;
4463 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4464 update_stat_ex_mtime(psbuf, write_time_ts);
4467 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4468 mtime_ts = psbuf->st_ex_mtime;
4469 atime_ts = psbuf->st_ex_atime;
4470 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4472 if (lp_dos_filetime_resolution(SNUM(conn))) {
4473 dos_filetime_timespec(&create_time_ts);
4474 dos_filetime_timespec(&mtime_ts);
4475 dos_filetime_timespec(&atime_ts);
4476 dos_filetime_timespec(&ctime_ts);
4479 create_time = convert_timespec_to_time_t(create_time_ts);
4480 mtime = convert_timespec_to_time_t(mtime_ts);
4481 atime = convert_timespec_to_time_t(atime_ts);
4482 c_time = convert_timespec_to_time_t(ctime_ts);
4484 p = strrchr_m(smb_fname->base_name,'/');
4485 if (!p)
4486 base_name = smb_fname->base_name;
4487 else
4488 base_name = p+1;
4490 /* NT expects the name to be in an exact form of the *full*
4491 filename. See the trans2 torture test */
4492 if (ISDOT(base_name)) {
4493 dos_fname = talloc_strdup(mem_ctx, "\\");
4494 if (!dos_fname) {
4495 return NT_STATUS_NO_MEMORY;
4497 } else {
4498 dos_fname = talloc_asprintf(mem_ctx,
4499 "\\%s",
4500 smb_fname->base_name);
4501 if (!dos_fname) {
4502 return NT_STATUS_NO_MEMORY;
4504 if (is_ntfs_stream_smb_fname(smb_fname)) {
4505 dos_fname = talloc_asprintf(dos_fname, "%s",
4506 smb_fname->stream_name);
4507 if (!dos_fname) {
4508 return NT_STATUS_NO_MEMORY;
4512 string_replace(dos_fname, '/', '\\');
4515 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4517 if (!fsp) {
4518 /* Do we have this path open ? */
4519 files_struct *fsp1;
4520 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4521 fsp1 = file_find_di_first(conn->sconn, fileid);
4522 if (fsp1 && fsp1->initial_allocation_size) {
4523 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4527 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4528 file_size = get_file_size_stat(psbuf);
4531 if (fsp) {
4532 pos = fsp->fh->position_information;
4535 if (fsp) {
4536 access_mask = fsp->access_mask;
4537 } else {
4538 /* GENERIC_EXECUTE mapping from Windows */
4539 access_mask = 0x12019F;
4542 /* This should be an index number - looks like
4543 dev/ino to me :-)
4545 I think this causes us to fail the IFSKIT
4546 BasicFileInformationTest. -tpot */
4547 file_index = get_FileIndex(conn, psbuf);
4549 *fixed_portion = 0;
4551 switch (info_level) {
4552 case SMB_INFO_STANDARD:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4554 data_size = 22;
4555 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4556 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4557 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4558 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4559 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4560 SSVAL(pdata,l1_attrFile,mode);
4561 break;
4563 case SMB_INFO_QUERY_EA_SIZE:
4565 unsigned int ea_size =
4566 estimate_ea_size(conn, fsp,
4567 smb_fname);
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4569 data_size = 26;
4570 srv_put_dos_date2(pdata,0,create_time);
4571 srv_put_dos_date2(pdata,4,atime);
4572 srv_put_dos_date2(pdata,8,mtime); /* write time */
4573 SIVAL(pdata,12,(uint32)file_size);
4574 SIVAL(pdata,16,(uint32)allocation_size);
4575 SSVAL(pdata,20,mode);
4576 SIVAL(pdata,22,ea_size);
4577 break;
4580 case SMB_INFO_IS_NAME_VALID:
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4582 if (fsp) {
4583 /* os/2 needs this ? really ?*/
4584 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4586 /* This is only reached for qpathinfo */
4587 data_size = 0;
4588 break;
4590 case SMB_INFO_QUERY_EAS_FROM_LIST:
4592 size_t total_ea_len = 0;
4593 struct ea_list *ea_file_list = NULL;
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4596 status =
4597 get_ea_list_from_file(mem_ctx, conn, fsp,
4598 smb_fname,
4599 &total_ea_len, &ea_file_list);
4600 if (!NT_STATUS_IS_OK(status)) {
4601 return status;
4604 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4606 if (!ea_list || (total_ea_len > data_size)) {
4607 data_size = 4;
4608 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4609 break;
4612 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4613 break;
4616 case SMB_INFO_QUERY_ALL_EAS:
4618 /* We have data_size bytes to put EA's into. */
4619 size_t total_ea_len = 0;
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4622 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4623 smb_fname,
4624 &total_ea_len, &ea_list);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 return status;
4629 if (!ea_list || (total_ea_len > data_size)) {
4630 data_size = 4;
4631 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4632 break;
4635 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4636 break;
4639 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4641 /* This is FileFullEaInformation - 0xF which maps to
4642 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4644 /* We have data_size bytes to put EA's into. */
4645 size_t total_ea_len = 0;
4646 struct ea_list *ea_file_list = NULL;
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4650 /*TODO: add filtering and index handling */
4652 status =
4653 get_ea_list_from_file(mem_ctx, conn, fsp,
4654 smb_fname,
4655 &total_ea_len, &ea_file_list);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 return status;
4659 if (!ea_file_list) {
4660 return NT_STATUS_NO_EAS_ON_FILE;
4663 status = fill_ea_chained_buffer(mem_ctx,
4664 pdata,
4665 data_size,
4666 &data_size,
4667 conn, ea_file_list);
4668 if (!NT_STATUS_IS_OK(status)) {
4669 return status;
4671 break;
4674 case SMB_FILE_BASIC_INFORMATION:
4675 case SMB_QUERY_FILE_BASIC_INFO:
4677 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4679 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4680 } else {
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4682 data_size = 40;
4683 SIVAL(pdata,36,0);
4685 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4686 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4687 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4688 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4689 SIVAL(pdata,32,mode);
4691 DEBUG(5,("SMB_QFBI - "));
4692 DEBUG(5,("create: %s ", ctime(&create_time)));
4693 DEBUG(5,("access: %s ", ctime(&atime)));
4694 DEBUG(5,("write: %s ", ctime(&mtime)));
4695 DEBUG(5,("change: %s ", ctime(&c_time)));
4696 DEBUG(5,("mode: %x\n", mode));
4697 *fixed_portion = data_size;
4698 break;
4700 case SMB_FILE_STANDARD_INFORMATION:
4701 case SMB_QUERY_FILE_STANDARD_INFO:
4703 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4704 data_size = 24;
4705 SOFF_T(pdata,0,allocation_size);
4706 SOFF_T(pdata,8,file_size);
4707 SIVAL(pdata,16,nlink);
4708 SCVAL(pdata,20,delete_pending?1:0);
4709 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4710 SSVAL(pdata,22,0); /* Padding. */
4711 *fixed_portion = 24;
4712 break;
4714 case SMB_FILE_EA_INFORMATION:
4715 case SMB_QUERY_FILE_EA_INFO:
4717 unsigned int ea_size =
4718 estimate_ea_size(conn, fsp, smb_fname);
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4720 data_size = 4;
4721 *fixed_portion = 4;
4722 SIVAL(pdata,0,ea_size);
4723 break;
4726 /* Get the 8.3 name - used if NT SMB was negotiated. */
4727 case SMB_QUERY_FILE_ALT_NAME_INFO:
4728 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4730 int len;
4731 char mangled_name[13];
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4733 if (!name_to_8_3(base_name,mangled_name,
4734 True,conn->params)) {
4735 return NT_STATUS_NO_MEMORY;
4737 len = srvstr_push(dstart, flags2,
4738 pdata+4, mangled_name,
4739 PTR_DIFF(dend, pdata+4),
4740 STR_UNICODE);
4741 data_size = 4 + len;
4742 SIVAL(pdata,0,len);
4743 *fixed_portion = 8;
4744 break;
4747 case SMB_QUERY_FILE_NAME_INFO:
4749 int len;
4751 this must be *exactly* right for ACLs on mapped drives to work
4753 len = srvstr_push(dstart, flags2,
4754 pdata+4, dos_fname,
4755 PTR_DIFF(dend, pdata+4),
4756 STR_UNICODE);
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4758 data_size = 4 + len;
4759 SIVAL(pdata,0,len);
4760 break;
4763 case SMB_FILE_ALLOCATION_INFORMATION:
4764 case SMB_QUERY_FILE_ALLOCATION_INFO:
4765 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4766 data_size = 8;
4767 SOFF_T(pdata,0,allocation_size);
4768 break;
4770 case SMB_FILE_END_OF_FILE_INFORMATION:
4771 case SMB_QUERY_FILE_END_OF_FILEINFO:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4773 data_size = 8;
4774 SOFF_T(pdata,0,file_size);
4775 break;
4777 case SMB_QUERY_FILE_ALL_INFO:
4778 case SMB_FILE_ALL_INFORMATION:
4780 int len;
4781 unsigned int ea_size =
4782 estimate_ea_size(conn, fsp, smb_fname);
4783 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4784 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4785 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4786 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4787 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4788 SIVAL(pdata,32,mode);
4789 SIVAL(pdata,36,0); /* padding. */
4790 pdata += 40;
4791 SOFF_T(pdata,0,allocation_size);
4792 SOFF_T(pdata,8,file_size);
4793 SIVAL(pdata,16,nlink);
4794 SCVAL(pdata,20,delete_pending);
4795 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4796 SSVAL(pdata,22,0);
4797 pdata += 24;
4798 SIVAL(pdata,0,ea_size);
4799 pdata += 4; /* EA info */
4800 len = srvstr_push(dstart, flags2,
4801 pdata+4, dos_fname,
4802 PTR_DIFF(dend, pdata+4),
4803 STR_UNICODE);
4804 SIVAL(pdata,0,len);
4805 pdata += 4 + len;
4806 data_size = PTR_DIFF(pdata,(*ppdata));
4807 *fixed_portion = 10;
4808 break;
4811 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4813 int len;
4814 unsigned int ea_size =
4815 estimate_ea_size(conn, fsp, smb_fname);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4817 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4818 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4819 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4820 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4821 SIVAL(pdata, 0x20, mode);
4822 SIVAL(pdata, 0x24, 0); /* padding. */
4823 SBVAL(pdata, 0x28, allocation_size);
4824 SBVAL(pdata, 0x30, file_size);
4825 SIVAL(pdata, 0x38, nlink);
4826 SCVAL(pdata, 0x3C, delete_pending);
4827 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4828 SSVAL(pdata, 0x3E, 0); /* padding */
4829 SBVAL(pdata, 0x40, file_index);
4830 SIVAL(pdata, 0x48, ea_size);
4831 SIVAL(pdata, 0x4C, access_mask);
4832 SBVAL(pdata, 0x50, pos);
4833 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4834 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4836 pdata += 0x60;
4838 len = srvstr_push(dstart, flags2,
4839 pdata+4, dos_fname,
4840 PTR_DIFF(dend, pdata+4),
4841 STR_UNICODE);
4842 SIVAL(pdata,0,len);
4843 pdata += 4 + len;
4844 data_size = PTR_DIFF(pdata,(*ppdata));
4845 *fixed_portion = 104;
4846 break;
4848 case SMB_FILE_INTERNAL_INFORMATION:
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4851 SBVAL(pdata, 0, file_index);
4852 data_size = 8;
4853 *fixed_portion = 8;
4854 break;
4856 case SMB_FILE_ACCESS_INFORMATION:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4858 SIVAL(pdata, 0, access_mask);
4859 data_size = 4;
4860 *fixed_portion = 4;
4861 break;
4863 case SMB_FILE_NAME_INFORMATION:
4864 /* Pathname with leading '\'. */
4866 size_t byte_len;
4867 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4868 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4869 SIVAL(pdata,0,byte_len);
4870 data_size = 4 + byte_len;
4871 break;
4874 case SMB_FILE_DISPOSITION_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4876 data_size = 1;
4877 SCVAL(pdata,0,delete_pending);
4878 *fixed_portion = 1;
4879 break;
4881 case SMB_FILE_POSITION_INFORMATION:
4882 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4883 data_size = 8;
4884 SOFF_T(pdata,0,pos);
4885 *fixed_portion = 8;
4886 break;
4888 case SMB_FILE_MODE_INFORMATION:
4889 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4890 SIVAL(pdata,0,mode);
4891 data_size = 4;
4892 *fixed_portion = 4;
4893 break;
4895 case SMB_FILE_ALIGNMENT_INFORMATION:
4896 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4897 SIVAL(pdata,0,0); /* No alignment needed. */
4898 data_size = 4;
4899 *fixed_portion = 4;
4900 break;
4903 * NT4 server just returns "invalid query" to this - if we try
4904 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4905 * want this. JRA.
4907 /* The first statement above is false - verified using Thursby
4908 * client against NT4 -- gcolley.
4910 case SMB_QUERY_FILE_STREAM_INFO:
4911 case SMB_FILE_STREAM_INFORMATION: {
4912 unsigned int num_streams = 0;
4913 struct stream_struct *streams = NULL;
4915 DEBUG(10,("smbd_do_qfilepathinfo: "
4916 "SMB_FILE_STREAM_INFORMATION\n"));
4918 if (is_ntfs_stream_smb_fname(smb_fname)) {
4919 return NT_STATUS_INVALID_PARAMETER;
4922 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4923 talloc_tos(), &num_streams, &streams);
4925 if (!NT_STATUS_IS_OK(status)) {
4926 DEBUG(10, ("could not get stream info: %s\n",
4927 nt_errstr(status)));
4928 return status;
4931 status = marshall_stream_info(num_streams, streams,
4932 pdata, max_data_bytes,
4933 &data_size);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 DEBUG(10, ("marshall_stream_info failed: %s\n",
4937 nt_errstr(status)));
4938 TALLOC_FREE(streams);
4939 return status;
4942 TALLOC_FREE(streams);
4944 *fixed_portion = 32;
4946 break;
4948 case SMB_QUERY_COMPRESSION_INFO:
4949 case SMB_FILE_COMPRESSION_INFORMATION:
4950 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4951 SOFF_T(pdata,0,file_size);
4952 SIVAL(pdata,8,0); /* ??? */
4953 SIVAL(pdata,12,0); /* ??? */
4954 data_size = 16;
4955 *fixed_portion = 16;
4956 break;
4958 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4960 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4961 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4962 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4963 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4964 SOFF_T(pdata,32,allocation_size);
4965 SOFF_T(pdata,40,file_size);
4966 SIVAL(pdata,48,mode);
4967 SIVAL(pdata,52,0); /* ??? */
4968 data_size = 56;
4969 *fixed_portion = 56;
4970 break;
4972 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4973 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4974 SIVAL(pdata,0,mode);
4975 SIVAL(pdata,4,0);
4976 data_size = 8;
4977 *fixed_portion = 8;
4978 break;
4981 * CIFS UNIX Extensions.
4984 case SMB_QUERY_FILE_UNIX_BASIC:
4986 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4987 data_size = PTR_DIFF(pdata,(*ppdata));
4989 DEBUG(4,("smbd_do_qfilepathinfo: "
4990 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4991 dump_data(4, (uint8_t *)(*ppdata), data_size);
4993 break;
4995 case SMB_QUERY_FILE_UNIX_INFO2:
4997 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4998 data_size = PTR_DIFF(pdata,(*ppdata));
5001 int i;
5002 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5004 for (i=0; i<100; i++)
5005 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5006 DEBUG(4,("\n"));
5009 break;
5011 case SMB_QUERY_FILE_UNIX_LINK:
5013 int len;
5014 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5016 if (!buffer) {
5017 return NT_STATUS_NO_MEMORY;
5020 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5021 #ifdef S_ISLNK
5022 if(!S_ISLNK(psbuf->st_ex_mode)) {
5023 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5025 #else
5026 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5027 #endif
5028 len = SMB_VFS_READLINK(conn,
5029 smb_fname->base_name,
5030 buffer, PATH_MAX);
5031 if (len == -1) {
5032 return map_nt_error_from_unix(errno);
5034 buffer[len] = 0;
5035 len = srvstr_push(dstart, flags2,
5036 pdata, buffer,
5037 PTR_DIFF(dend, pdata),
5038 STR_TERMINATE);
5039 pdata += len;
5040 data_size = PTR_DIFF(pdata,(*ppdata));
5042 break;
5045 #if defined(HAVE_POSIX_ACLS)
5046 case SMB_QUERY_POSIX_ACL:
5048 SMB_ACL_T file_acl = NULL;
5049 SMB_ACL_T def_acl = NULL;
5050 uint16 num_file_acls = 0;
5051 uint16 num_def_acls = 0;
5053 if (fsp && fsp->fh->fd != -1) {
5054 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5055 talloc_tos());
5056 } else {
5057 file_acl =
5058 SMB_VFS_SYS_ACL_GET_FILE(conn,
5059 smb_fname->base_name,
5060 SMB_ACL_TYPE_ACCESS,
5061 talloc_tos());
5064 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5065 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5066 "not implemented on "
5067 "filesystem containing %s\n",
5068 smb_fname->base_name));
5069 return NT_STATUS_NOT_IMPLEMENTED;
5072 if (S_ISDIR(psbuf->st_ex_mode)) {
5073 if (fsp && fsp->is_directory) {
5074 def_acl =
5075 SMB_VFS_SYS_ACL_GET_FILE(
5076 conn,
5077 fsp->fsp_name->base_name,
5078 SMB_ACL_TYPE_DEFAULT,
5079 talloc_tos());
5080 } else {
5081 def_acl =
5082 SMB_VFS_SYS_ACL_GET_FILE(
5083 conn,
5084 smb_fname->base_name,
5085 SMB_ACL_TYPE_DEFAULT,
5086 talloc_tos());
5088 def_acl = free_empty_sys_acl(conn, def_acl);
5091 num_file_acls = count_acl_entries(conn, file_acl);
5092 num_def_acls = count_acl_entries(conn, def_acl);
5094 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5095 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5096 data_size,
5097 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5098 SMB_POSIX_ACL_HEADER_SIZE) ));
5099 if (file_acl) {
5100 TALLOC_FREE(file_acl);
5102 if (def_acl) {
5103 TALLOC_FREE(def_acl);
5105 return NT_STATUS_BUFFER_TOO_SMALL;
5108 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5109 SSVAL(pdata,2,num_file_acls);
5110 SSVAL(pdata,4,num_def_acls);
5111 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5112 if (file_acl) {
5113 TALLOC_FREE(file_acl);
5115 if (def_acl) {
5116 TALLOC_FREE(def_acl);
5118 return NT_STATUS_INTERNAL_ERROR;
5120 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5121 if (file_acl) {
5122 TALLOC_FREE(file_acl);
5124 if (def_acl) {
5125 TALLOC_FREE(def_acl);
5127 return NT_STATUS_INTERNAL_ERROR;
5130 if (file_acl) {
5131 TALLOC_FREE(file_acl);
5133 if (def_acl) {
5134 TALLOC_FREE(def_acl);
5136 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5137 break;
5139 #endif
5142 case SMB_QUERY_POSIX_LOCK:
5144 uint64_t count;
5145 uint64_t offset;
5146 uint64_t smblctx;
5147 enum brl_type lock_type;
5149 /* We need an open file with a real fd for this. */
5150 if (!fsp || fsp->fh->fd == -1) {
5151 return NT_STATUS_INVALID_LEVEL;
5154 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5155 return NT_STATUS_INVALID_PARAMETER;
5158 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5159 case POSIX_LOCK_TYPE_READ:
5160 lock_type = READ_LOCK;
5161 break;
5162 case POSIX_LOCK_TYPE_WRITE:
5163 lock_type = WRITE_LOCK;
5164 break;
5165 case POSIX_LOCK_TYPE_UNLOCK:
5166 default:
5167 /* There's no point in asking for an unlock... */
5168 return NT_STATUS_INVALID_PARAMETER;
5171 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5172 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5173 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5175 status = query_lock(fsp,
5176 &smblctx,
5177 &count,
5178 &offset,
5179 &lock_type,
5180 POSIX_LOCK);
5182 if (ERROR_WAS_LOCK_DENIED(status)) {
5183 /* Here we need to report who has it locked... */
5184 data_size = POSIX_LOCK_DATA_SIZE;
5186 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5187 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5188 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5189 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5190 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5192 } else if (NT_STATUS_IS_OK(status)) {
5193 /* For success we just return a copy of what we sent
5194 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5195 data_size = POSIX_LOCK_DATA_SIZE;
5196 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5197 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5198 } else {
5199 return status;
5201 break;
5204 default:
5205 return NT_STATUS_INVALID_LEVEL;
5208 *pdata_size = data_size;
5209 return NT_STATUS_OK;
5212 /****************************************************************************
5213 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5214 file name or file id).
5215 ****************************************************************************/
5217 static void call_trans2qfilepathinfo(connection_struct *conn,
5218 struct smb_request *req,
5219 unsigned int tran_call,
5220 char **pparams, int total_params,
5221 char **ppdata, int total_data,
5222 unsigned int max_data_bytes)
5224 char *params = *pparams;
5225 char *pdata = *ppdata;
5226 uint16 info_level;
5227 unsigned int data_size = 0;
5228 unsigned int param_size = 2;
5229 struct smb_filename *smb_fname = NULL;
5230 bool delete_pending = False;
5231 struct timespec write_time_ts;
5232 files_struct *fsp = NULL;
5233 struct file_id fileid;
5234 struct ea_list *ea_list = NULL;
5235 int lock_data_count = 0;
5236 char *lock_data = NULL;
5237 size_t fixed_portion;
5238 NTSTATUS status = NT_STATUS_OK;
5240 if (!params) {
5241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5242 return;
5245 ZERO_STRUCT(write_time_ts);
5247 if (tran_call == TRANSACT2_QFILEINFO) {
5248 if (total_params < 4) {
5249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5250 return;
5253 if (IS_IPC(conn)) {
5254 call_trans2qpipeinfo(conn, req, tran_call,
5255 pparams, total_params,
5256 ppdata, total_data,
5257 max_data_bytes);
5258 return;
5261 fsp = file_fsp(req, SVAL(params,0));
5262 info_level = SVAL(params,2);
5264 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5266 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5267 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5268 return;
5271 /* Initial check for valid fsp ptr. */
5272 if (!check_fsp_open(conn, req, fsp)) {
5273 return;
5276 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5277 if (smb_fname == NULL) {
5278 reply_nterror(req, NT_STATUS_NO_MEMORY);
5279 return;
5282 if(fsp->fake_file_handle) {
5284 * This is actually for the QUOTA_FAKE_FILE --metze
5287 /* We know this name is ok, it's already passed the checks. */
5289 } else if(fsp->fh->fd == -1) {
5291 * This is actually a QFILEINFO on a directory
5292 * handle (returned from an NT SMB). NT5.0 seems
5293 * to do this call. JRA.
5296 if (INFO_LEVEL_IS_UNIX(info_level)) {
5297 /* Always do lstat for UNIX calls. */
5298 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_LSTAT of %s failed "
5301 "(%s)\n",
5302 smb_fname_str_dbg(smb_fname),
5303 strerror(errno)));
5304 reply_nterror(req,
5305 map_nt_error_from_unix(errno));
5306 return;
5308 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5309 DEBUG(3,("call_trans2qfilepathinfo: "
5310 "SMB_VFS_STAT of %s failed (%s)\n",
5311 smb_fname_str_dbg(smb_fname),
5312 strerror(errno)));
5313 reply_nterror(req,
5314 map_nt_error_from_unix(errno));
5315 return;
5318 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5319 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5320 } else {
5322 * Original code - this is an open file.
5324 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5325 DEBUG(3, ("fstat of %s failed (%s)\n",
5326 fsp_fnum_dbg(fsp), strerror(errno)));
5327 reply_nterror(req,
5328 map_nt_error_from_unix(errno));
5329 return;
5331 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5332 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5335 } else {
5336 uint32_t name_hash;
5337 char *fname = NULL;
5338 uint32_t ucf_flags = 0;
5340 /* qpathinfo */
5341 if (total_params < 7) {
5342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5343 return;
5346 info_level = SVAL(params,0);
5348 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5350 if (INFO_LEVEL_IS_UNIX(info_level)) {
5351 if (!lp_unix_extensions()) {
5352 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5353 return;
5355 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5356 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5357 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5358 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5362 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5363 total_params - 6,
5364 STR_TERMINATE, &status);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 reply_nterror(req, status);
5367 return;
5370 status = filename_convert(req,
5371 conn,
5372 req->flags2 & FLAGS2_DFS_PATHNAMES,
5373 fname,
5374 ucf_flags,
5375 NULL,
5376 &smb_fname);
5377 if (!NT_STATUS_IS_OK(status)) {
5378 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5379 reply_botherror(req,
5380 NT_STATUS_PATH_NOT_COVERED,
5381 ERRSRV, ERRbadpath);
5382 return;
5384 reply_nterror(req, status);
5385 return;
5388 /* If this is a stream, check if there is a delete_pending. */
5389 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5390 && is_ntfs_stream_smb_fname(smb_fname)) {
5391 struct smb_filename *smb_fname_base;
5393 /* Create an smb_filename with stream_name == NULL. */
5394 smb_fname_base = synthetic_smb_fname(
5395 talloc_tos(), smb_fname->base_name,
5396 NULL, NULL);
5397 if (smb_fname_base == NULL) {
5398 reply_nterror(req, NT_STATUS_NO_MEMORY);
5399 return;
5402 if (INFO_LEVEL_IS_UNIX(info_level)) {
5403 /* Always do lstat for UNIX calls. */
5404 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5405 DEBUG(3,("call_trans2qfilepathinfo: "
5406 "SMB_VFS_LSTAT of %s failed "
5407 "(%s)\n",
5408 smb_fname_str_dbg(smb_fname_base),
5409 strerror(errno)));
5410 TALLOC_FREE(smb_fname_base);
5411 reply_nterror(req,
5412 map_nt_error_from_unix(errno));
5413 return;
5415 } else {
5416 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5417 DEBUG(3,("call_trans2qfilepathinfo: "
5418 "fileinfo of %s failed "
5419 "(%s)\n",
5420 smb_fname_str_dbg(smb_fname_base),
5421 strerror(errno)));
5422 TALLOC_FREE(smb_fname_base);
5423 reply_nterror(req,
5424 map_nt_error_from_unix(errno));
5425 return;
5429 status = file_name_hash(conn,
5430 smb_fname_str_dbg(smb_fname_base),
5431 &name_hash);
5432 if (!NT_STATUS_IS_OK(status)) {
5433 TALLOC_FREE(smb_fname_base);
5434 reply_nterror(req, status);
5435 return;
5438 fileid = vfs_file_id_from_sbuf(conn,
5439 &smb_fname_base->st);
5440 TALLOC_FREE(smb_fname_base);
5441 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5442 if (delete_pending) {
5443 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5444 return;
5448 if (INFO_LEVEL_IS_UNIX(info_level)) {
5449 /* Always do lstat for UNIX calls. */
5450 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5451 DEBUG(3,("call_trans2qfilepathinfo: "
5452 "SMB_VFS_LSTAT of %s failed (%s)\n",
5453 smb_fname_str_dbg(smb_fname),
5454 strerror(errno)));
5455 reply_nterror(req,
5456 map_nt_error_from_unix(errno));
5457 return;
5460 } else {
5461 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5462 DEBUG(3,("call_trans2qfilepathinfo: "
5463 "SMB_VFS_STAT of %s failed (%s)\n",
5464 smb_fname_str_dbg(smb_fname),
5465 strerror(errno)));
5466 reply_nterror(req,
5467 map_nt_error_from_unix(errno));
5468 return;
5472 status = file_name_hash(conn,
5473 smb_fname_str_dbg(smb_fname),
5474 &name_hash);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 reply_nterror(req, status);
5477 return;
5480 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5481 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5482 if (delete_pending) {
5483 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5484 return;
5488 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5489 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5490 fsp_fnum_dbg(fsp),
5491 info_level,tran_call,total_data));
5493 /* Pull out any data sent here before we realloc. */
5494 switch (info_level) {
5495 case SMB_INFO_QUERY_EAS_FROM_LIST:
5497 /* Pull any EA list from the data portion. */
5498 uint32 ea_size;
5500 if (total_data < 4) {
5501 reply_nterror(
5502 req, NT_STATUS_INVALID_PARAMETER);
5503 return;
5505 ea_size = IVAL(pdata,0);
5507 if (total_data > 0 && ea_size != total_data) {
5508 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5509 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5510 reply_nterror(
5511 req, NT_STATUS_INVALID_PARAMETER);
5512 return;
5515 if (!lp_ea_support(SNUM(conn))) {
5516 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5517 return;
5520 /* Pull out the list of names. */
5521 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5522 if (!ea_list) {
5523 reply_nterror(
5524 req, NT_STATUS_INVALID_PARAMETER);
5525 return;
5527 break;
5530 case SMB_QUERY_POSIX_LOCK:
5532 if (fsp == NULL || fsp->fh->fd == -1) {
5533 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5534 return;
5537 if (total_data != POSIX_LOCK_DATA_SIZE) {
5538 reply_nterror(
5539 req, NT_STATUS_INVALID_PARAMETER);
5540 return;
5543 /* Copy the lock range data. */
5544 lock_data = (char *)talloc_memdup(
5545 req, pdata, total_data);
5546 if (!lock_data) {
5547 reply_nterror(req, NT_STATUS_NO_MEMORY);
5548 return;
5550 lock_data_count = total_data;
5552 default:
5553 break;
5556 *pparams = (char *)SMB_REALLOC(*pparams,2);
5557 if (*pparams == NULL) {
5558 reply_nterror(req, NT_STATUS_NO_MEMORY);
5559 return;
5561 params = *pparams;
5562 SSVAL(params,0,0);
5565 * draft-leach-cifs-v1-spec-02.txt
5566 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5567 * says:
5569 * The requested information is placed in the Data portion of the
5570 * transaction response. For the information levels greater than 0x100,
5571 * the transaction response has 1 parameter word which should be
5572 * ignored by the client.
5574 * However Windows only follows this rule for the IS_NAME_VALID call.
5576 switch (info_level) {
5577 case SMB_INFO_IS_NAME_VALID:
5578 param_size = 0;
5579 break;
5582 if ((info_level & 0xFF00) == 0xFF00) {
5584 * We use levels that start with 0xFF00
5585 * internally to represent SMB2 specific levels
5587 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5588 return;
5591 status = smbd_do_qfilepathinfo(conn, req, info_level,
5592 fsp, smb_fname,
5593 delete_pending, write_time_ts,
5594 ea_list,
5595 lock_data_count, lock_data,
5596 req->flags2, max_data_bytes,
5597 &fixed_portion,
5598 ppdata, &data_size);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 reply_nterror(req, status);
5601 return;
5603 if (fixed_portion > max_data_bytes) {
5604 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5605 return;
5608 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5609 max_data_bytes);
5611 return;
5614 /****************************************************************************
5615 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5616 code.
5617 ****************************************************************************/
5619 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5620 connection_struct *conn,
5621 struct smb_request *req,
5622 bool overwrite_if_exists,
5623 const struct smb_filename *smb_fname_old,
5624 struct smb_filename *smb_fname_new)
5626 NTSTATUS status = NT_STATUS_OK;
5628 /* source must already exist. */
5629 if (!VALID_STAT(smb_fname_old->st)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5633 if (VALID_STAT(smb_fname_new->st)) {
5634 if (overwrite_if_exists) {
5635 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5636 return NT_STATUS_FILE_IS_A_DIRECTORY;
5638 status = unlink_internals(conn,
5639 req,
5640 FILE_ATTRIBUTE_NORMAL,
5641 smb_fname_new,
5642 false);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 return status;
5646 } else {
5647 /* Disallow if newname already exists. */
5648 return NT_STATUS_OBJECT_NAME_COLLISION;
5652 /* No links from a directory. */
5653 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5654 return NT_STATUS_FILE_IS_A_DIRECTORY;
5657 /* Setting a hardlink to/from a stream isn't currently supported. */
5658 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5659 is_ntfs_stream_smb_fname(smb_fname_new)) {
5660 return NT_STATUS_INVALID_PARAMETER;
5663 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5664 smb_fname_old->base_name, smb_fname_new->base_name));
5666 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5667 smb_fname_new->base_name) != 0) {
5668 status = map_nt_error_from_unix(errno);
5669 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5670 nt_errstr(status), smb_fname_old->base_name,
5671 smb_fname_new->base_name));
5673 return status;
5676 /****************************************************************************
5677 Deal with setting the time from any of the setfilepathinfo functions.
5678 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5679 calling this function.
5680 ****************************************************************************/
5682 NTSTATUS smb_set_file_time(connection_struct *conn,
5683 files_struct *fsp,
5684 const struct smb_filename *smb_fname,
5685 struct smb_file_time *ft,
5686 bool setting_write_time)
5688 struct smb_filename smb_fname_base;
5689 uint32 action =
5690 FILE_NOTIFY_CHANGE_LAST_ACCESS
5691 |FILE_NOTIFY_CHANGE_LAST_WRITE
5692 |FILE_NOTIFY_CHANGE_CREATION;
5694 if (!VALID_STAT(smb_fname->st)) {
5695 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5698 /* get some defaults (no modifications) if any info is zero or -1. */
5699 if (null_timespec(ft->create_time)) {
5700 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5703 if (null_timespec(ft->atime)) {
5704 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5707 if (null_timespec(ft->mtime)) {
5708 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5711 if (!setting_write_time) {
5712 /* ft->mtime comes from change time, not write time. */
5713 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5716 /* Ensure the resolution is the correct for
5717 * what we can store on this filesystem. */
5719 round_timespec(conn->ts_res, &ft->create_time);
5720 round_timespec(conn->ts_res, &ft->ctime);
5721 round_timespec(conn->ts_res, &ft->atime);
5722 round_timespec(conn->ts_res, &ft->mtime);
5724 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5725 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5726 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5727 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5728 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5729 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5730 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5731 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5733 if (setting_write_time) {
5735 * This was a Windows setfileinfo on an open file.
5736 * NT does this a lot. We also need to
5737 * set the time here, as it can be read by
5738 * FindFirst/FindNext and with the patch for bug #2045
5739 * in smbd/fileio.c it ensures that this timestamp is
5740 * kept sticky even after a write. We save the request
5741 * away and will set it on file close and after a write. JRA.
5744 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5745 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5747 if (fsp != NULL) {
5748 if (fsp->base_fsp) {
5749 set_sticky_write_time_fsp(fsp->base_fsp,
5750 ft->mtime);
5751 } else {
5752 set_sticky_write_time_fsp(fsp, ft->mtime);
5754 } else {
5755 set_sticky_write_time_path(
5756 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5757 ft->mtime);
5761 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5763 /* Always call ntimes on the base, even if a stream was passed in. */
5764 smb_fname_base = *smb_fname;
5765 smb_fname_base.stream_name = NULL;
5767 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5768 return map_nt_error_from_unix(errno);
5771 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5772 smb_fname->base_name);
5773 return NT_STATUS_OK;
5776 /****************************************************************************
5777 Deal with setting the dosmode from any of the setfilepathinfo functions.
5778 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5779 done before calling this function.
5780 ****************************************************************************/
5782 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5783 const struct smb_filename *smb_fname,
5784 uint32 dosmode)
5786 struct smb_filename *smb_fname_base;
5787 NTSTATUS status;
5789 if (!VALID_STAT(smb_fname->st)) {
5790 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5793 /* Always operate on the base_name, even if a stream was passed in. */
5794 smb_fname_base = synthetic_smb_fname(
5795 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5796 if (smb_fname_base == NULL) {
5797 return NT_STATUS_NO_MEMORY;
5800 if (dosmode) {
5801 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5802 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5803 } else {
5804 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5808 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5810 /* check the mode isn't different, before changing it */
5811 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5812 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5813 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5814 (unsigned int)dosmode));
5816 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5817 false)) {
5818 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5819 "%s failed (%s)\n",
5820 smb_fname_str_dbg(smb_fname_base),
5821 strerror(errno)));
5822 status = map_nt_error_from_unix(errno);
5823 goto out;
5826 status = NT_STATUS_OK;
5827 out:
5828 TALLOC_FREE(smb_fname_base);
5829 return status;
5832 /****************************************************************************
5833 Deal with setting the size from any of the setfilepathinfo functions.
5834 ****************************************************************************/
5836 static NTSTATUS smb_set_file_size(connection_struct *conn,
5837 struct smb_request *req,
5838 files_struct *fsp,
5839 const struct smb_filename *smb_fname,
5840 const SMB_STRUCT_STAT *psbuf,
5841 off_t size,
5842 bool fail_after_createfile)
5844 NTSTATUS status = NT_STATUS_OK;
5845 struct smb_filename *smb_fname_tmp = NULL;
5846 files_struct *new_fsp = NULL;
5848 if (!VALID_STAT(*psbuf)) {
5849 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5852 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5854 if (size == get_file_size_stat(psbuf)) {
5855 return NT_STATUS_OK;
5858 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5859 smb_fname_str_dbg(smb_fname), (double)size));
5861 if (fsp && fsp->fh->fd != -1) {
5862 /* Handle based call. */
5863 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5864 return NT_STATUS_ACCESS_DENIED;
5867 if (vfs_set_filelen(fsp, size) == -1) {
5868 return map_nt_error_from_unix(errno);
5870 trigger_write_time_update_immediate(fsp);
5871 return NT_STATUS_OK;
5874 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5875 if (smb_fname_tmp == NULL) {
5876 return NT_STATUS_NO_MEMORY;
5879 smb_fname_tmp->st = *psbuf;
5881 status = SMB_VFS_CREATE_FILE(
5882 conn, /* conn */
5883 req, /* req */
5884 0, /* root_dir_fid */
5885 smb_fname_tmp, /* fname */
5886 FILE_WRITE_DATA, /* access_mask */
5887 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5888 FILE_SHARE_DELETE),
5889 FILE_OPEN, /* create_disposition*/
5890 0, /* create_options */
5891 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5892 0, /* oplock_request */
5893 NULL, /* lease */
5894 0, /* allocation_size */
5895 0, /* private_flags */
5896 NULL, /* sd */
5897 NULL, /* ea_list */
5898 &new_fsp, /* result */
5899 NULL); /* pinfo */
5901 TALLOC_FREE(smb_fname_tmp);
5903 if (!NT_STATUS_IS_OK(status)) {
5904 /* NB. We check for open_was_deferred in the caller. */
5905 return status;
5908 /* See RAW-SFILEINFO-END-OF-FILE */
5909 if (fail_after_createfile) {
5910 close_file(req, new_fsp,NORMAL_CLOSE);
5911 return NT_STATUS_INVALID_LEVEL;
5914 if (vfs_set_filelen(new_fsp, size) == -1) {
5915 status = map_nt_error_from_unix(errno);
5916 close_file(req, new_fsp,NORMAL_CLOSE);
5917 return status;
5920 trigger_write_time_update_immediate(new_fsp);
5921 close_file(req, new_fsp,NORMAL_CLOSE);
5922 return NT_STATUS_OK;
5925 /****************************************************************************
5926 Deal with SMB_INFO_SET_EA.
5927 ****************************************************************************/
5929 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5930 const char *pdata,
5931 int total_data,
5932 files_struct *fsp,
5933 const struct smb_filename *smb_fname)
5935 struct ea_list *ea_list = NULL;
5936 TALLOC_CTX *ctx = NULL;
5937 NTSTATUS status = NT_STATUS_OK;
5939 if (total_data < 10) {
5941 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5942 length. They seem to have no effect. Bug #3212. JRA */
5944 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5945 /* We're done. We only get EA info in this call. */
5946 return NT_STATUS_OK;
5949 return NT_STATUS_INVALID_PARAMETER;
5952 if (IVAL(pdata,0) > total_data) {
5953 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5954 IVAL(pdata,0), (unsigned int)total_data));
5955 return NT_STATUS_INVALID_PARAMETER;
5958 ctx = talloc_tos();
5959 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5960 if (!ea_list) {
5961 return NT_STATUS_INVALID_PARAMETER;
5964 status = set_ea(conn, fsp, smb_fname, ea_list);
5966 return status;
5969 /****************************************************************************
5970 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5971 ****************************************************************************/
5973 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5974 const char *pdata,
5975 int total_data,
5976 files_struct *fsp)
5978 struct ea_list *ea_list = NULL;
5979 NTSTATUS status;
5981 if (!fsp) {
5982 return NT_STATUS_INVALID_HANDLE;
5985 if (!lp_ea_support(SNUM(conn))) {
5986 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5987 "EA's not supported.\n",
5988 (unsigned int)total_data));
5989 return NT_STATUS_EAS_NOT_SUPPORTED;
5992 if (total_data < 10) {
5993 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5994 "too small.\n",
5995 (unsigned int)total_data));
5996 return NT_STATUS_INVALID_PARAMETER;
5999 ea_list = read_nttrans_ea_list(talloc_tos(),
6000 pdata,
6001 total_data);
6003 if (!ea_list) {
6004 return NT_STATUS_INVALID_PARAMETER;
6007 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6009 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6010 smb_fname_str_dbg(fsp->fsp_name),
6011 nt_errstr(status) ));
6013 return status;
6017 /****************************************************************************
6018 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6019 ****************************************************************************/
6021 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6022 const char *pdata,
6023 int total_data,
6024 files_struct *fsp,
6025 struct smb_filename *smb_fname)
6027 NTSTATUS status = NT_STATUS_OK;
6028 bool delete_on_close;
6029 uint32 dosmode = 0;
6031 if (total_data < 1) {
6032 return NT_STATUS_INVALID_PARAMETER;
6035 if (fsp == NULL) {
6036 return NT_STATUS_INVALID_HANDLE;
6039 delete_on_close = (CVAL(pdata,0) ? True : False);
6040 dosmode = dos_mode(conn, smb_fname);
6042 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6043 "delete_on_close = %u\n",
6044 smb_fname_str_dbg(smb_fname),
6045 (unsigned int)dosmode,
6046 (unsigned int)delete_on_close ));
6048 if (delete_on_close) {
6049 status = can_set_delete_on_close(fsp, dosmode);
6050 if (!NT_STATUS_IS_OK(status)) {
6051 return status;
6055 /* The set is across all open files on this dev/inode pair. */
6056 if (!set_delete_on_close(fsp, delete_on_close,
6057 conn->session_info->security_token,
6058 conn->session_info->unix_token)) {
6059 return NT_STATUS_ACCESS_DENIED;
6061 return NT_STATUS_OK;
6064 /****************************************************************************
6065 Deal with SMB_FILE_POSITION_INFORMATION.
6066 ****************************************************************************/
6068 static NTSTATUS smb_file_position_information(connection_struct *conn,
6069 const char *pdata,
6070 int total_data,
6071 files_struct *fsp)
6073 uint64_t position_information;
6075 if (total_data < 8) {
6076 return NT_STATUS_INVALID_PARAMETER;
6079 if (fsp == NULL) {
6080 /* Ignore on pathname based set. */
6081 return NT_STATUS_OK;
6084 position_information = (uint64_t)IVAL(pdata,0);
6085 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6087 DEBUG(10,("smb_file_position_information: Set file position "
6088 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6089 (double)position_information));
6090 fsp->fh->position_information = position_information;
6091 return NT_STATUS_OK;
6094 /****************************************************************************
6095 Deal with SMB_FILE_MODE_INFORMATION.
6096 ****************************************************************************/
6098 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6099 const char *pdata,
6100 int total_data)
6102 uint32 mode;
6104 if (total_data < 4) {
6105 return NT_STATUS_INVALID_PARAMETER;
6107 mode = IVAL(pdata,0);
6108 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6109 return NT_STATUS_INVALID_PARAMETER;
6111 return NT_STATUS_OK;
6114 /****************************************************************************
6115 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6116 ****************************************************************************/
6118 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6119 struct smb_request *req,
6120 const char *pdata,
6121 int total_data,
6122 const struct smb_filename *smb_fname)
6124 char *link_target = NULL;
6125 const char *newname = smb_fname->base_name;
6126 TALLOC_CTX *ctx = talloc_tos();
6128 /* Set a symbolic link. */
6129 /* Don't allow this if follow links is false. */
6131 if (total_data == 0) {
6132 return NT_STATUS_INVALID_PARAMETER;
6135 if (!lp_follow_symlinks(SNUM(conn))) {
6136 return NT_STATUS_ACCESS_DENIED;
6139 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6140 total_data, STR_TERMINATE);
6142 if (!link_target) {
6143 return NT_STATUS_INVALID_PARAMETER;
6146 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6147 newname, link_target ));
6149 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6150 return map_nt_error_from_unix(errno);
6153 return NT_STATUS_OK;
6156 /****************************************************************************
6157 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6158 ****************************************************************************/
6160 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6161 struct smb_request *req,
6162 const char *pdata, int total_data,
6163 struct smb_filename *smb_fname_new)
6165 char *oldname = NULL;
6166 struct smb_filename *smb_fname_old = NULL;
6167 TALLOC_CTX *ctx = talloc_tos();
6168 NTSTATUS status = NT_STATUS_OK;
6170 /* Set a hard link. */
6171 if (total_data == 0) {
6172 return NT_STATUS_INVALID_PARAMETER;
6175 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6176 total_data, STR_TERMINATE, &status);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 return status;
6181 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6182 smb_fname_str_dbg(smb_fname_new), oldname));
6184 status = filename_convert(ctx,
6185 conn,
6186 req->flags2 & FLAGS2_DFS_PATHNAMES,
6187 oldname,
6189 NULL,
6190 &smb_fname_old);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 return status;
6195 return hardlink_internals(ctx, conn, req, false,
6196 smb_fname_old, smb_fname_new);
6199 /****************************************************************************
6200 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6201 ****************************************************************************/
6203 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6204 struct smb_request *req,
6205 const char *pdata,
6206 int total_data,
6207 files_struct *fsp,
6208 struct smb_filename *smb_fname_src)
6210 bool overwrite;
6211 uint32_t len;
6212 char *newname = NULL;
6213 struct smb_filename *smb_fname_dst = NULL;
6214 NTSTATUS status = NT_STATUS_OK;
6215 TALLOC_CTX *ctx = talloc_tos();
6217 if (!fsp) {
6218 return NT_STATUS_INVALID_HANDLE;
6221 if (total_data < 20) {
6222 return NT_STATUS_INVALID_PARAMETER;
6225 overwrite = (CVAL(pdata,0) ? True : False);
6226 len = IVAL(pdata,16);
6228 if (len > (total_data - 20) || (len == 0)) {
6229 return NT_STATUS_INVALID_PARAMETER;
6232 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6233 &pdata[20], len, STR_TERMINATE,
6234 &status);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 return status;
6239 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6240 newname));
6242 status = filename_convert(ctx,
6243 conn,
6244 req->flags2 & FLAGS2_DFS_PATHNAMES,
6245 newname,
6246 UCF_SAVE_LCOMP,
6247 NULL,
6248 &smb_fname_dst);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 return status;
6253 if (fsp->base_fsp) {
6254 /* newname must be a stream name. */
6255 if (newname[0] != ':') {
6256 return NT_STATUS_NOT_SUPPORTED;
6259 /* Create an smb_fname to call rename_internals_fsp() with. */
6260 smb_fname_dst = synthetic_smb_fname(
6261 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6262 newname, NULL);
6263 if (smb_fname_dst == NULL) {
6264 status = NT_STATUS_NO_MEMORY;
6265 goto out;
6269 * Set the original last component, since
6270 * rename_internals_fsp() requires it.
6272 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6273 newname);
6274 if (smb_fname_dst->original_lcomp == NULL) {
6275 status = NT_STATUS_NO_MEMORY;
6276 goto out;
6281 DEBUG(10,("smb2_file_rename_information: "
6282 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6283 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6284 smb_fname_str_dbg(smb_fname_dst)));
6285 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6286 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6287 overwrite);
6289 out:
6290 TALLOC_FREE(smb_fname_dst);
6291 return status;
6294 static NTSTATUS smb_file_link_information(connection_struct *conn,
6295 struct smb_request *req,
6296 const char *pdata,
6297 int total_data,
6298 files_struct *fsp,
6299 struct smb_filename *smb_fname_src)
6301 bool overwrite;
6302 uint32_t len;
6303 char *newname = NULL;
6304 struct smb_filename *smb_fname_dst = NULL;
6305 NTSTATUS status = NT_STATUS_OK;
6306 TALLOC_CTX *ctx = talloc_tos();
6308 if (!fsp) {
6309 return NT_STATUS_INVALID_HANDLE;
6312 if (total_data < 20) {
6313 return NT_STATUS_INVALID_PARAMETER;
6316 overwrite = (CVAL(pdata,0) ? true : false);
6317 len = IVAL(pdata,16);
6319 if (len > (total_data - 20) || (len == 0)) {
6320 return NT_STATUS_INVALID_PARAMETER;
6323 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6324 &pdata[20], len, STR_TERMINATE,
6325 &status);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 return status;
6330 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6331 newname));
6333 status = filename_convert(ctx,
6334 conn,
6335 req->flags2 & FLAGS2_DFS_PATHNAMES,
6336 newname,
6337 UCF_SAVE_LCOMP,
6338 NULL,
6339 &smb_fname_dst);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 return status;
6344 if (fsp->base_fsp) {
6345 /* No stream names. */
6346 return NT_STATUS_NOT_SUPPORTED;
6349 DEBUG(10,("smb_file_link_information: "
6350 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6351 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6352 smb_fname_str_dbg(smb_fname_dst)));
6353 status = hardlink_internals(ctx,
6354 conn,
6355 req,
6356 overwrite,
6357 fsp->fsp_name,
6358 smb_fname_dst);
6360 TALLOC_FREE(smb_fname_dst);
6361 return status;
6364 /****************************************************************************
6365 Deal with SMB_FILE_RENAME_INFORMATION.
6366 ****************************************************************************/
6368 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6369 struct smb_request *req,
6370 const char *pdata,
6371 int total_data,
6372 files_struct *fsp,
6373 struct smb_filename *smb_fname_src)
6375 bool overwrite;
6376 uint32 root_fid;
6377 uint32 len;
6378 char *newname = NULL;
6379 struct smb_filename *smb_fname_dst = NULL;
6380 bool dest_has_wcard = False;
6381 NTSTATUS status = NT_STATUS_OK;
6382 char *p;
6383 TALLOC_CTX *ctx = talloc_tos();
6385 if (total_data < 13) {
6386 return NT_STATUS_INVALID_PARAMETER;
6389 overwrite = (CVAL(pdata,0) ? True : False);
6390 root_fid = IVAL(pdata,4);
6391 len = IVAL(pdata,8);
6393 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6394 return NT_STATUS_INVALID_PARAMETER;
6397 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6398 len, 0, &status,
6399 &dest_has_wcard);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 return status;
6404 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6405 newname));
6407 status = resolve_dfspath_wcard(ctx, conn,
6408 req->flags2 & FLAGS2_DFS_PATHNAMES,
6409 newname,
6410 true,
6411 !conn->sconn->using_smb2,
6412 &newname,
6413 &dest_has_wcard);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 return status;
6418 /* Check the new name has no '/' characters. */
6419 if (strchr_m(newname, '/')) {
6420 return NT_STATUS_NOT_SUPPORTED;
6423 if (fsp && fsp->base_fsp) {
6424 /* newname must be a stream name. */
6425 if (newname[0] != ':') {
6426 return NT_STATUS_NOT_SUPPORTED;
6429 /* Create an smb_fname to call rename_internals_fsp() with. */
6430 smb_fname_dst = synthetic_smb_fname(
6431 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6432 newname, NULL);
6433 if (smb_fname_dst == NULL) {
6434 status = NT_STATUS_NO_MEMORY;
6435 goto out;
6439 * Set the original last component, since
6440 * rename_internals_fsp() requires it.
6442 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6443 newname);
6444 if (smb_fname_dst->original_lcomp == NULL) {
6445 status = NT_STATUS_NO_MEMORY;
6446 goto out;
6449 } else {
6451 * Build up an smb_fname_dst based on the filename passed in.
6452 * We basically just strip off the last component, and put on
6453 * the newname instead.
6455 char *base_name = NULL;
6457 /* newname must *not* be a stream name. */
6458 if (newname[0] == ':') {
6459 return NT_STATUS_NOT_SUPPORTED;
6463 * Strip off the last component (filename) of the path passed
6464 * in.
6466 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6467 if (!base_name) {
6468 return NT_STATUS_NO_MEMORY;
6470 p = strrchr_m(base_name, '/');
6471 if (p) {
6472 p[1] = '\0';
6473 } else {
6474 base_name = talloc_strdup(ctx, "");
6475 if (!base_name) {
6476 return NT_STATUS_NO_MEMORY;
6479 /* Append the new name. */
6480 base_name = talloc_asprintf_append(base_name,
6481 "%s",
6482 newname);
6483 if (!base_name) {
6484 return NT_STATUS_NO_MEMORY;
6487 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6488 (UCF_SAVE_LCOMP |
6489 (dest_has_wcard ?
6490 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6491 0)));
6493 /* If an error we expect this to be
6494 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6496 if (!NT_STATUS_IS_OK(status)) {
6497 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6498 status)) {
6499 goto out;
6501 /* Create an smb_fname to call rename_internals_fsp() */
6502 smb_fname_dst = synthetic_smb_fname(
6503 ctx, base_name, NULL, NULL);
6504 if (smb_fname_dst == NULL) {
6505 status = NT_STATUS_NO_MEMORY;
6506 goto out;
6511 if (fsp) {
6512 DEBUG(10,("smb_file_rename_information: "
6513 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6514 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6515 smb_fname_str_dbg(smb_fname_dst)));
6516 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6517 overwrite);
6518 } else {
6519 DEBUG(10,("smb_file_rename_information: "
6520 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6521 smb_fname_str_dbg(smb_fname_src),
6522 smb_fname_str_dbg(smb_fname_dst)));
6523 status = rename_internals(ctx, conn, req, smb_fname_src,
6524 smb_fname_dst, 0, overwrite, false,
6525 dest_has_wcard,
6526 FILE_WRITE_ATTRIBUTES);
6528 out:
6529 TALLOC_FREE(smb_fname_dst);
6530 return status;
6533 /****************************************************************************
6534 Deal with SMB_SET_POSIX_ACL.
6535 ****************************************************************************/
6537 #if defined(HAVE_POSIX_ACLS)
6538 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6539 const char *pdata,
6540 int total_data,
6541 files_struct *fsp,
6542 const struct smb_filename *smb_fname)
6544 uint16 posix_acl_version;
6545 uint16 num_file_acls;
6546 uint16 num_def_acls;
6547 bool valid_file_acls = True;
6548 bool valid_def_acls = True;
6550 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6551 return NT_STATUS_INVALID_PARAMETER;
6553 posix_acl_version = SVAL(pdata,0);
6554 num_file_acls = SVAL(pdata,2);
6555 num_def_acls = SVAL(pdata,4);
6557 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6558 valid_file_acls = False;
6559 num_file_acls = 0;
6562 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6563 valid_def_acls = False;
6564 num_def_acls = 0;
6567 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6572 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6573 return NT_STATUS_INVALID_PARAMETER;
6576 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6577 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6578 (unsigned int)num_file_acls,
6579 (unsigned int)num_def_acls));
6581 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6582 smb_fname->base_name, num_file_acls,
6583 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6584 return map_nt_error_from_unix(errno);
6587 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6588 smb_fname->base_name, &smb_fname->st, num_def_acls,
6589 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6590 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6591 return map_nt_error_from_unix(errno);
6593 return NT_STATUS_OK;
6595 #endif
6597 /****************************************************************************
6598 Deal with SMB_SET_POSIX_LOCK.
6599 ****************************************************************************/
6601 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6602 struct smb_request *req,
6603 const char *pdata,
6604 int total_data,
6605 files_struct *fsp)
6607 uint64_t count;
6608 uint64_t offset;
6609 uint64_t smblctx;
6610 bool blocking_lock = False;
6611 enum brl_type lock_type;
6613 NTSTATUS status = NT_STATUS_OK;
6615 if (fsp == NULL || fsp->fh->fd == -1) {
6616 return NT_STATUS_INVALID_HANDLE;
6619 if (total_data != POSIX_LOCK_DATA_SIZE) {
6620 return NT_STATUS_INVALID_PARAMETER;
6623 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6624 case POSIX_LOCK_TYPE_READ:
6625 lock_type = READ_LOCK;
6626 break;
6627 case POSIX_LOCK_TYPE_WRITE:
6628 /* Return the right POSIX-mappable error code for files opened read-only. */
6629 if (!fsp->can_write) {
6630 return NT_STATUS_INVALID_HANDLE;
6632 lock_type = WRITE_LOCK;
6633 break;
6634 case POSIX_LOCK_TYPE_UNLOCK:
6635 lock_type = UNLOCK_LOCK;
6636 break;
6637 default:
6638 return NT_STATUS_INVALID_PARAMETER;
6641 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6642 blocking_lock = False;
6643 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6644 blocking_lock = True;
6645 } else {
6646 return NT_STATUS_INVALID_PARAMETER;
6649 if (!lp_blocking_locks(SNUM(conn))) {
6650 blocking_lock = False;
6653 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6654 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6655 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6656 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6657 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6659 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6660 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6661 fsp_str_dbg(fsp),
6662 (unsigned int)lock_type,
6663 (unsigned long long)smblctx,
6664 (double)count,
6665 (double)offset ));
6667 if (lock_type == UNLOCK_LOCK) {
6668 status = do_unlock(req->sconn->msg_ctx,
6669 fsp,
6670 smblctx,
6671 count,
6672 offset,
6673 POSIX_LOCK);
6674 } else {
6675 uint64_t block_smblctx;
6677 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6678 fsp,
6679 smblctx,
6680 count,
6681 offset,
6682 lock_type,
6683 POSIX_LOCK,
6684 blocking_lock,
6685 &status,
6686 &block_smblctx);
6688 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6690 * A blocking lock was requested. Package up
6691 * this smb into a queued request and push it
6692 * onto the blocking lock queue.
6694 if(push_blocking_lock_request(br_lck,
6695 req,
6696 fsp,
6697 -1, /* infinite timeout. */
6699 smblctx,
6700 lock_type,
6701 POSIX_LOCK,
6702 offset,
6703 count,
6704 block_smblctx)) {
6705 TALLOC_FREE(br_lck);
6706 return status;
6709 TALLOC_FREE(br_lck);
6712 return status;
6715 /****************************************************************************
6716 Deal with SMB_SET_FILE_BASIC_INFO.
6717 ****************************************************************************/
6719 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6720 const char *pdata,
6721 int total_data,
6722 files_struct *fsp,
6723 const struct smb_filename *smb_fname)
6725 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6726 struct smb_file_time ft;
6727 uint32 dosmode = 0;
6728 NTSTATUS status = NT_STATUS_OK;
6730 ZERO_STRUCT(ft);
6732 if (total_data < 36) {
6733 return NT_STATUS_INVALID_PARAMETER;
6736 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 return status;
6741 /* Set the attributes */
6742 dosmode = IVAL(pdata,32);
6743 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 return status;
6748 /* create time */
6749 ft.create_time = interpret_long_date(pdata);
6751 /* access time */
6752 ft.atime = interpret_long_date(pdata+8);
6754 /* write time. */
6755 ft.mtime = interpret_long_date(pdata+16);
6757 /* change time. */
6758 ft.ctime = interpret_long_date(pdata+24);
6760 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6761 smb_fname_str_dbg(smb_fname)));
6763 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6764 true);
6767 /****************************************************************************
6768 Deal with SMB_INFO_STANDARD.
6769 ****************************************************************************/
6771 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6772 const char *pdata,
6773 int total_data,
6774 files_struct *fsp,
6775 const struct smb_filename *smb_fname)
6777 NTSTATUS status;
6778 struct smb_file_time ft;
6780 ZERO_STRUCT(ft);
6782 if (total_data < 12) {
6783 return NT_STATUS_INVALID_PARAMETER;
6786 /* create time */
6787 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6788 /* access time */
6789 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6790 /* write time */
6791 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6793 DEBUG(10,("smb_set_info_standard: file %s\n",
6794 smb_fname_str_dbg(smb_fname)));
6796 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6797 if (!NT_STATUS_IS_OK(status)) {
6798 return status;
6801 return smb_set_file_time(conn,
6802 fsp,
6803 smb_fname,
6804 &ft,
6805 true);
6808 /****************************************************************************
6809 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6810 ****************************************************************************/
6812 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6813 struct smb_request *req,
6814 const char *pdata,
6815 int total_data,
6816 files_struct *fsp,
6817 struct smb_filename *smb_fname)
6819 uint64_t allocation_size = 0;
6820 NTSTATUS status = NT_STATUS_OK;
6821 files_struct *new_fsp = NULL;
6823 if (!VALID_STAT(smb_fname->st)) {
6824 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6827 if (total_data < 8) {
6828 return NT_STATUS_INVALID_PARAMETER;
6831 allocation_size = (uint64_t)IVAL(pdata,0);
6832 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6833 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6834 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6835 (double)allocation_size));
6837 if (allocation_size) {
6838 allocation_size = smb_roundup(conn, allocation_size);
6841 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6842 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6843 (double)allocation_size));
6845 if (fsp && fsp->fh->fd != -1) {
6846 /* Open file handle. */
6847 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6848 return NT_STATUS_ACCESS_DENIED;
6851 /* Only change if needed. */
6852 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6853 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6854 return map_nt_error_from_unix(errno);
6857 /* But always update the time. */
6859 * This is equivalent to a write. Ensure it's seen immediately
6860 * if there are no pending writes.
6862 trigger_write_time_update_immediate(fsp);
6863 return NT_STATUS_OK;
6866 /* Pathname or stat or directory file. */
6867 status = SMB_VFS_CREATE_FILE(
6868 conn, /* conn */
6869 req, /* req */
6870 0, /* root_dir_fid */
6871 smb_fname, /* fname */
6872 FILE_WRITE_DATA, /* access_mask */
6873 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6874 FILE_SHARE_DELETE),
6875 FILE_OPEN, /* create_disposition*/
6876 0, /* create_options */
6877 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6878 0, /* oplock_request */
6879 NULL, /* lease */
6880 0, /* allocation_size */
6881 0, /* private_flags */
6882 NULL, /* sd */
6883 NULL, /* ea_list */
6884 &new_fsp, /* result */
6885 NULL); /* pinfo */
6887 if (!NT_STATUS_IS_OK(status)) {
6888 /* NB. We check for open_was_deferred in the caller. */
6889 return status;
6892 /* Only change if needed. */
6893 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6894 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6895 status = map_nt_error_from_unix(errno);
6896 close_file(req, new_fsp, NORMAL_CLOSE);
6897 return status;
6901 /* Changing the allocation size should set the last mod time. */
6903 * This is equivalent to a write. Ensure it's seen immediately
6904 * if there are no pending writes.
6906 trigger_write_time_update_immediate(new_fsp);
6907 close_file(req, new_fsp, NORMAL_CLOSE);
6908 return NT_STATUS_OK;
6911 /****************************************************************************
6912 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6913 ****************************************************************************/
6915 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6916 struct smb_request *req,
6917 const char *pdata,
6918 int total_data,
6919 files_struct *fsp,
6920 const struct smb_filename *smb_fname,
6921 bool fail_after_createfile)
6923 off_t size;
6925 if (total_data < 8) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 size = IVAL(pdata,0);
6930 size |= (((off_t)IVAL(pdata,4)) << 32);
6931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6932 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6933 (double)size));
6935 return smb_set_file_size(conn, req,
6936 fsp,
6937 smb_fname,
6938 &smb_fname->st,
6939 size,
6940 fail_after_createfile);
6943 /****************************************************************************
6944 Allow a UNIX info mknod.
6945 ****************************************************************************/
6947 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6948 const char *pdata,
6949 int total_data,
6950 const struct smb_filename *smb_fname)
6952 uint32 file_type = IVAL(pdata,56);
6953 #if defined(HAVE_MAKEDEV)
6954 uint32 dev_major = IVAL(pdata,60);
6955 uint32 dev_minor = IVAL(pdata,68);
6956 #endif
6957 SMB_DEV_T dev = (SMB_DEV_T)0;
6958 uint32 raw_unixmode = IVAL(pdata,84);
6959 NTSTATUS status;
6960 mode_t unixmode;
6962 if (total_data < 100) {
6963 return NT_STATUS_INVALID_PARAMETER;
6966 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6967 PERM_NEW_FILE, &unixmode);
6968 if (!NT_STATUS_IS_OK(status)) {
6969 return status;
6972 #if defined(HAVE_MAKEDEV)
6973 dev = makedev(dev_major, dev_minor);
6974 #endif
6976 switch (file_type) {
6977 #if defined(S_IFIFO)
6978 case UNIX_TYPE_FIFO:
6979 unixmode |= S_IFIFO;
6980 break;
6981 #endif
6982 #if defined(S_IFSOCK)
6983 case UNIX_TYPE_SOCKET:
6984 unixmode |= S_IFSOCK;
6985 break;
6986 #endif
6987 #if defined(S_IFCHR)
6988 case UNIX_TYPE_CHARDEV:
6989 unixmode |= S_IFCHR;
6990 break;
6991 #endif
6992 #if defined(S_IFBLK)
6993 case UNIX_TYPE_BLKDEV:
6994 unixmode |= S_IFBLK;
6995 break;
6996 #endif
6997 default:
6998 return NT_STATUS_INVALID_PARAMETER;
7001 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7002 "%.0f mode 0%o for file %s\n", (double)dev,
7003 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7005 /* Ok - do the mknod. */
7006 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7007 return map_nt_error_from_unix(errno);
7010 /* If any of the other "set" calls fail we
7011 * don't want to end up with a half-constructed mknod.
7014 if (lp_inherit_permissions(SNUM(conn))) {
7015 char *parent;
7016 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7017 &parent, NULL)) {
7018 return NT_STATUS_NO_MEMORY;
7020 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7021 unixmode);
7022 TALLOC_FREE(parent);
7025 return NT_STATUS_OK;
7028 /****************************************************************************
7029 Deal with SMB_SET_FILE_UNIX_BASIC.
7030 ****************************************************************************/
7032 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7033 struct smb_request *req,
7034 const char *pdata,
7035 int total_data,
7036 files_struct *fsp,
7037 const struct smb_filename *smb_fname)
7039 struct smb_file_time ft;
7040 uint32 raw_unixmode;
7041 mode_t unixmode;
7042 off_t size = 0;
7043 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7044 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7045 NTSTATUS status = NT_STATUS_OK;
7046 bool delete_on_fail = False;
7047 enum perm_type ptype;
7048 files_struct *all_fsps = NULL;
7049 bool modify_mtime = true;
7050 struct file_id id;
7051 struct smb_filename *smb_fname_tmp = NULL;
7052 SMB_STRUCT_STAT sbuf;
7054 ZERO_STRUCT(ft);
7056 if (total_data < 100) {
7057 return NT_STATUS_INVALID_PARAMETER;
7060 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7061 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7062 size=IVAL(pdata,0); /* first 8 Bytes are size */
7063 size |= (((off_t)IVAL(pdata,4)) << 32);
7066 ft.atime = interpret_long_date(pdata+24); /* access_time */
7067 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7068 set_owner = (uid_t)IVAL(pdata,40);
7069 set_grp = (gid_t)IVAL(pdata,48);
7070 raw_unixmode = IVAL(pdata,84);
7072 if (VALID_STAT(smb_fname->st)) {
7073 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7074 ptype = PERM_EXISTING_DIR;
7075 } else {
7076 ptype = PERM_EXISTING_FILE;
7078 } else {
7079 ptype = PERM_NEW_FILE;
7082 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7083 ptype, &unixmode);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 return status;
7088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7089 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7090 smb_fname_str_dbg(smb_fname), (double)size,
7091 (unsigned int)set_owner, (unsigned int)set_grp,
7092 (int)raw_unixmode));
7094 sbuf = smb_fname->st;
7096 if (!VALID_STAT(sbuf)) {
7098 * The only valid use of this is to create character and block
7099 * devices, and named pipes. This is deprecated (IMHO) and
7100 * a new info level should be used for mknod. JRA.
7103 status = smb_unix_mknod(conn,
7104 pdata,
7105 total_data,
7106 smb_fname);
7107 if (!NT_STATUS_IS_OK(status)) {
7108 return status;
7111 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7112 if (smb_fname_tmp == NULL) {
7113 return NT_STATUS_NO_MEMORY;
7116 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7117 status = map_nt_error_from_unix(errno);
7118 TALLOC_FREE(smb_fname_tmp);
7119 SMB_VFS_UNLINK(conn, smb_fname);
7120 return status;
7123 sbuf = smb_fname_tmp->st;
7124 smb_fname = smb_fname_tmp;
7126 /* Ensure we don't try and change anything else. */
7127 raw_unixmode = SMB_MODE_NO_CHANGE;
7128 size = get_file_size_stat(&sbuf);
7129 ft.atime = sbuf.st_ex_atime;
7130 ft.mtime = sbuf.st_ex_mtime;
7132 * We continue here as we might want to change the
7133 * owner uid/gid.
7135 delete_on_fail = True;
7138 #if 1
7139 /* Horrible backwards compatibility hack as an old server bug
7140 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7141 * */
7143 if (!size) {
7144 size = get_file_size_stat(&sbuf);
7146 #endif
7149 * Deal with the UNIX specific mode set.
7152 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7153 int ret;
7155 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7156 "setting mode 0%o for file %s\n",
7157 (unsigned int)unixmode,
7158 smb_fname_str_dbg(smb_fname)));
7159 if (fsp && fsp->fh->fd != -1) {
7160 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7161 } else {
7162 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7164 if (ret != 0) {
7165 return map_nt_error_from_unix(errno);
7170 * Deal with the UNIX specific uid set.
7173 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7174 (sbuf.st_ex_uid != set_owner)) {
7175 int ret;
7177 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7178 "changing owner %u for path %s\n",
7179 (unsigned int)set_owner,
7180 smb_fname_str_dbg(smb_fname)));
7182 if (fsp && fsp->fh->fd != -1) {
7183 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7184 } else {
7186 * UNIX extensions calls must always operate
7187 * on symlinks.
7189 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7190 set_owner, (gid_t)-1);
7193 if (ret != 0) {
7194 status = map_nt_error_from_unix(errno);
7195 if (delete_on_fail) {
7196 SMB_VFS_UNLINK(conn, smb_fname);
7198 return status;
7203 * Deal with the UNIX specific gid set.
7206 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7207 (sbuf.st_ex_gid != set_grp)) {
7208 int ret;
7210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7211 "changing group %u for file %s\n",
7212 (unsigned int)set_owner,
7213 smb_fname_str_dbg(smb_fname)));
7214 if (fsp && fsp->fh->fd != -1) {
7215 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7216 } else {
7218 * UNIX extensions calls must always operate
7219 * on symlinks.
7221 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7222 set_grp);
7224 if (ret != 0) {
7225 status = map_nt_error_from_unix(errno);
7226 if (delete_on_fail) {
7227 SMB_VFS_UNLINK(conn, smb_fname);
7229 return status;
7233 /* Deal with any size changes. */
7235 status = smb_set_file_size(conn, req,
7236 fsp,
7237 smb_fname,
7238 &sbuf,
7239 size,
7240 false);
7241 if (!NT_STATUS_IS_OK(status)) {
7242 return status;
7245 /* Deal with any time changes. */
7246 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7247 /* No change, don't cancel anything. */
7248 return status;
7251 id = vfs_file_id_from_sbuf(conn, &sbuf);
7252 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7253 all_fsps = file_find_di_next(all_fsps)) {
7255 * We're setting the time explicitly for UNIX.
7256 * Cancel any pending changes over all handles.
7258 all_fsps->update_write_time_on_close = false;
7259 TALLOC_FREE(all_fsps->update_write_time_event);
7263 * Override the "setting_write_time"
7264 * parameter here as it almost does what
7265 * we need. Just remember if we modified
7266 * mtime and send the notify ourselves.
7268 if (null_timespec(ft.mtime)) {
7269 modify_mtime = false;
7272 status = smb_set_file_time(conn,
7273 fsp,
7274 smb_fname,
7275 &ft,
7276 false);
7277 if (modify_mtime) {
7278 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7279 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7281 return status;
7284 /****************************************************************************
7285 Deal with SMB_SET_FILE_UNIX_INFO2.
7286 ****************************************************************************/
7288 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7289 struct smb_request *req,
7290 const char *pdata,
7291 int total_data,
7292 files_struct *fsp,
7293 const struct smb_filename *smb_fname)
7295 NTSTATUS status;
7296 uint32 smb_fflags;
7297 uint32 smb_fmask;
7299 if (total_data < 116) {
7300 return NT_STATUS_INVALID_PARAMETER;
7303 /* Start by setting all the fields that are common between UNIX_BASIC
7304 * and UNIX_INFO2.
7306 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7307 fsp, smb_fname);
7308 if (!NT_STATUS_IS_OK(status)) {
7309 return status;
7312 smb_fflags = IVAL(pdata, 108);
7313 smb_fmask = IVAL(pdata, 112);
7315 /* NB: We should only attempt to alter the file flags if the client
7316 * sends a non-zero mask.
7318 if (smb_fmask != 0) {
7319 int stat_fflags = 0;
7321 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7322 smb_fmask, &stat_fflags)) {
7323 /* Client asked to alter a flag we don't understand. */
7324 return NT_STATUS_INVALID_PARAMETER;
7327 if (fsp && fsp->fh->fd != -1) {
7328 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7329 return NT_STATUS_NOT_SUPPORTED;
7330 } else {
7331 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7332 stat_fflags) != 0) {
7333 return map_nt_error_from_unix(errno);
7338 /* XXX: need to add support for changing the create_time here. You
7339 * can do this for paths on Darwin with setattrlist(2). The right way
7340 * to hook this up is probably by extending the VFS utimes interface.
7343 return NT_STATUS_OK;
7346 /****************************************************************************
7347 Create a directory with POSIX semantics.
7348 ****************************************************************************/
7350 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7351 struct smb_request *req,
7352 char **ppdata,
7353 int total_data,
7354 struct smb_filename *smb_fname,
7355 int *pdata_return_size)
7357 NTSTATUS status = NT_STATUS_OK;
7358 uint32 raw_unixmode = 0;
7359 uint32 mod_unixmode = 0;
7360 mode_t unixmode = (mode_t)0;
7361 files_struct *fsp = NULL;
7362 uint16 info_level_return = 0;
7363 int info;
7364 char *pdata = *ppdata;
7366 if (total_data < 18) {
7367 return NT_STATUS_INVALID_PARAMETER;
7370 raw_unixmode = IVAL(pdata,8);
7371 /* Next 4 bytes are not yet defined. */
7373 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7374 PERM_NEW_DIR, &unixmode);
7375 if (!NT_STATUS_IS_OK(status)) {
7376 return status;
7379 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7381 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7382 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7384 status = SMB_VFS_CREATE_FILE(
7385 conn, /* conn */
7386 req, /* req */
7387 0, /* root_dir_fid */
7388 smb_fname, /* fname */
7389 FILE_READ_ATTRIBUTES, /* access_mask */
7390 FILE_SHARE_NONE, /* share_access */
7391 FILE_CREATE, /* create_disposition*/
7392 FILE_DIRECTORY_FILE, /* create_options */
7393 mod_unixmode, /* file_attributes */
7394 0, /* oplock_request */
7395 NULL, /* lease */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7398 NULL, /* sd */
7399 NULL, /* ea_list */
7400 &fsp, /* result */
7401 &info); /* pinfo */
7403 if (NT_STATUS_IS_OK(status)) {
7404 close_file(req, fsp, NORMAL_CLOSE);
7407 info_level_return = SVAL(pdata,16);
7409 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7410 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7411 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7412 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7413 } else {
7414 *pdata_return_size = 12;
7417 /* Realloc the data size */
7418 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7419 if (*ppdata == NULL) {
7420 *pdata_return_size = 0;
7421 return NT_STATUS_NO_MEMORY;
7423 pdata = *ppdata;
7425 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7426 SSVAL(pdata,2,0); /* No fnum. */
7427 SIVAL(pdata,4,info); /* Was directory created. */
7429 switch (info_level_return) {
7430 case SMB_QUERY_FILE_UNIX_BASIC:
7431 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7432 SSVAL(pdata,10,0); /* Padding. */
7433 store_file_unix_basic(conn, pdata + 12, fsp,
7434 &smb_fname->st);
7435 break;
7436 case SMB_QUERY_FILE_UNIX_INFO2:
7437 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7438 SSVAL(pdata,10,0); /* Padding. */
7439 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7440 &smb_fname->st);
7441 break;
7442 default:
7443 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7444 SSVAL(pdata,10,0); /* Padding. */
7445 break;
7448 return status;
7451 /****************************************************************************
7452 Open/Create a file with POSIX semantics.
7453 ****************************************************************************/
7455 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7456 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7458 static NTSTATUS smb_posix_open(connection_struct *conn,
7459 struct smb_request *req,
7460 char **ppdata,
7461 int total_data,
7462 struct smb_filename *smb_fname,
7463 int *pdata_return_size)
7465 bool extended_oplock_granted = False;
7466 char *pdata = *ppdata;
7467 uint32 flags = 0;
7468 uint32 wire_open_mode = 0;
7469 uint32 raw_unixmode = 0;
7470 uint32 mod_unixmode = 0;
7471 uint32 create_disp = 0;
7472 uint32 access_mask = 0;
7473 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7474 NTSTATUS status = NT_STATUS_OK;
7475 mode_t unixmode = (mode_t)0;
7476 files_struct *fsp = NULL;
7477 int oplock_request = 0;
7478 int info = 0;
7479 uint16 info_level_return = 0;
7481 if (total_data < 18) {
7482 return NT_STATUS_INVALID_PARAMETER;
7485 flags = IVAL(pdata,0);
7486 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7487 if (oplock_request) {
7488 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7491 wire_open_mode = IVAL(pdata,4);
7493 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7494 return smb_posix_mkdir(conn, req,
7495 ppdata,
7496 total_data,
7497 smb_fname,
7498 pdata_return_size);
7501 switch (wire_open_mode & SMB_ACCMODE) {
7502 case SMB_O_RDONLY:
7503 access_mask = SMB_O_RDONLY_MAPPING;
7504 break;
7505 case SMB_O_WRONLY:
7506 access_mask = SMB_O_WRONLY_MAPPING;
7507 break;
7508 case SMB_O_RDWR:
7509 access_mask = (SMB_O_RDONLY_MAPPING|
7510 SMB_O_WRONLY_MAPPING);
7511 break;
7512 default:
7513 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7514 (unsigned int)wire_open_mode ));
7515 return NT_STATUS_INVALID_PARAMETER;
7518 wire_open_mode &= ~SMB_ACCMODE;
7520 /* First take care of O_CREAT|O_EXCL interactions. */
7521 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7522 case (SMB_O_CREAT | SMB_O_EXCL):
7523 /* File exists fail. File not exist create. */
7524 create_disp = FILE_CREATE;
7525 break;
7526 case SMB_O_CREAT:
7527 /* File exists open. File not exist create. */
7528 create_disp = FILE_OPEN_IF;
7529 break;
7530 case SMB_O_EXCL:
7531 /* O_EXCL on its own without O_CREAT is undefined.
7532 We deliberately ignore it as some versions of
7533 Linux CIFSFS can send a bare O_EXCL on the
7534 wire which other filesystems in the kernel
7535 ignore. See bug 9519 for details. */
7537 /* Fallthrough. */
7539 case 0:
7540 /* File exists open. File not exist fail. */
7541 create_disp = FILE_OPEN;
7542 break;
7543 default:
7544 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7545 (unsigned int)wire_open_mode ));
7546 return NT_STATUS_INVALID_PARAMETER;
7549 /* Next factor in the effects of O_TRUNC. */
7550 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7552 if (wire_open_mode & SMB_O_TRUNC) {
7553 switch (create_disp) {
7554 case FILE_CREATE:
7555 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7556 /* Leave create_disp alone as
7557 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7559 /* File exists fail. File not exist create. */
7560 break;
7561 case FILE_OPEN_IF:
7562 /* SMB_O_CREAT | SMB_O_TRUNC */
7563 /* File exists overwrite. File not exist create. */
7564 create_disp = FILE_OVERWRITE_IF;
7565 break;
7566 case FILE_OPEN:
7567 /* SMB_O_TRUNC */
7568 /* File exists overwrite. File not exist fail. */
7569 create_disp = FILE_OVERWRITE;
7570 break;
7571 default:
7572 /* Cannot get here. */
7573 smb_panic("smb_posix_open: logic error");
7574 return NT_STATUS_INVALID_PARAMETER;
7578 raw_unixmode = IVAL(pdata,8);
7579 /* Next 4 bytes are not yet defined. */
7581 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7582 (VALID_STAT(smb_fname->st) ?
7583 PERM_EXISTING_FILE : PERM_NEW_FILE),
7584 &unixmode);
7586 if (!NT_STATUS_IS_OK(status)) {
7587 return status;
7590 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7592 if (wire_open_mode & SMB_O_SYNC) {
7593 create_options |= FILE_WRITE_THROUGH;
7595 if (wire_open_mode & SMB_O_APPEND) {
7596 access_mask |= FILE_APPEND_DATA;
7598 if (wire_open_mode & SMB_O_DIRECT) {
7599 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7602 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7603 VALID_STAT_OF_DIR(smb_fname->st)) {
7604 if (access_mask != SMB_O_RDONLY_MAPPING) {
7605 return NT_STATUS_FILE_IS_A_DIRECTORY;
7607 create_options &= ~FILE_NON_DIRECTORY_FILE;
7608 create_options |= FILE_DIRECTORY_FILE;
7611 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7612 smb_fname_str_dbg(smb_fname),
7613 (unsigned int)wire_open_mode,
7614 (unsigned int)unixmode ));
7616 status = SMB_VFS_CREATE_FILE(
7617 conn, /* conn */
7618 req, /* req */
7619 0, /* root_dir_fid */
7620 smb_fname, /* fname */
7621 access_mask, /* access_mask */
7622 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7623 FILE_SHARE_DELETE),
7624 create_disp, /* create_disposition*/
7625 create_options, /* create_options */
7626 mod_unixmode, /* file_attributes */
7627 oplock_request, /* oplock_request */
7628 NULL, /* lease */
7629 0, /* allocation_size */
7630 0, /* private_flags */
7631 NULL, /* sd */
7632 NULL, /* ea_list */
7633 &fsp, /* result */
7634 &info); /* pinfo */
7636 if (!NT_STATUS_IS_OK(status)) {
7637 return status;
7640 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7641 extended_oplock_granted = True;
7644 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7645 extended_oplock_granted = True;
7648 info_level_return = SVAL(pdata,16);
7650 /* Allocate the correct return size. */
7652 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7653 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7654 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7655 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7656 } else {
7657 *pdata_return_size = 12;
7660 /* Realloc the data size */
7661 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7662 if (*ppdata == NULL) {
7663 close_file(req, fsp, ERROR_CLOSE);
7664 *pdata_return_size = 0;
7665 return NT_STATUS_NO_MEMORY;
7667 pdata = *ppdata;
7669 if (extended_oplock_granted) {
7670 if (flags & REQUEST_BATCH_OPLOCK) {
7671 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7672 } else {
7673 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7675 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7676 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7677 } else {
7678 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7681 SSVAL(pdata,2,fsp->fnum);
7682 SIVAL(pdata,4,info); /* Was file created etc. */
7684 switch (info_level_return) {
7685 case SMB_QUERY_FILE_UNIX_BASIC:
7686 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7687 SSVAL(pdata,10,0); /* padding. */
7688 store_file_unix_basic(conn, pdata + 12, fsp,
7689 &smb_fname->st);
7690 break;
7691 case SMB_QUERY_FILE_UNIX_INFO2:
7692 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7693 SSVAL(pdata,10,0); /* padding. */
7694 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7695 &smb_fname->st);
7696 break;
7697 default:
7698 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7699 SSVAL(pdata,10,0); /* padding. */
7700 break;
7702 return NT_STATUS_OK;
7705 /****************************************************************************
7706 Delete a file with POSIX semantics.
7707 ****************************************************************************/
7709 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7710 struct smb_request *req,
7711 const char *pdata,
7712 int total_data,
7713 struct smb_filename *smb_fname)
7715 NTSTATUS status = NT_STATUS_OK;
7716 files_struct *fsp = NULL;
7717 uint16 flags = 0;
7718 char del = 1;
7719 int info = 0;
7720 int create_options = 0;
7721 int i;
7722 struct share_mode_lock *lck = NULL;
7724 if (total_data < 2) {
7725 return NT_STATUS_INVALID_PARAMETER;
7728 flags = SVAL(pdata,0);
7730 if (!VALID_STAT(smb_fname->st)) {
7731 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7734 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7735 !VALID_STAT_OF_DIR(smb_fname->st)) {
7736 return NT_STATUS_NOT_A_DIRECTORY;
7739 DEBUG(10,("smb_posix_unlink: %s %s\n",
7740 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7741 smb_fname_str_dbg(smb_fname)));
7743 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7744 create_options |= FILE_DIRECTORY_FILE;
7747 status = SMB_VFS_CREATE_FILE(
7748 conn, /* conn */
7749 req, /* req */
7750 0, /* root_dir_fid */
7751 smb_fname, /* fname */
7752 DELETE_ACCESS, /* access_mask */
7753 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7754 FILE_SHARE_DELETE),
7755 FILE_OPEN, /* create_disposition*/
7756 create_options, /* create_options */
7757 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7758 0, /* oplock_request */
7759 NULL, /* lease */
7760 0, /* allocation_size */
7761 0, /* private_flags */
7762 NULL, /* sd */
7763 NULL, /* ea_list */
7764 &fsp, /* result */
7765 &info); /* pinfo */
7767 if (!NT_STATUS_IS_OK(status)) {
7768 return status;
7772 * Don't lie to client. If we can't really delete due to
7773 * non-POSIX opens return SHARING_VIOLATION.
7776 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7777 if (lck == NULL) {
7778 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7779 "lock for file %s\n", fsp_str_dbg(fsp)));
7780 close_file(req, fsp, NORMAL_CLOSE);
7781 return NT_STATUS_INVALID_PARAMETER;
7785 * See if others still have the file open. If this is the case, then
7786 * don't delete. If all opens are POSIX delete we can set the delete
7787 * on close disposition.
7789 for (i=0; i<lck->data->num_share_modes; i++) {
7790 struct share_mode_entry *e = &lck->data->share_modes[i];
7791 if (is_valid_share_mode_entry(e)) {
7792 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7793 continue;
7795 if (share_mode_stale_pid(lck->data, i)) {
7796 continue;
7798 /* Fail with sharing violation. */
7799 TALLOC_FREE(lck);
7800 close_file(req, fsp, NORMAL_CLOSE);
7801 return NT_STATUS_SHARING_VIOLATION;
7806 * Set the delete on close.
7808 status = smb_set_file_disposition_info(conn,
7809 &del,
7811 fsp,
7812 smb_fname);
7814 TALLOC_FREE(lck);
7816 if (!NT_STATUS_IS_OK(status)) {
7817 close_file(req, fsp, NORMAL_CLOSE);
7818 return status;
7820 return close_file(req, fsp, NORMAL_CLOSE);
7823 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7824 struct smb_request *req,
7825 TALLOC_CTX *mem_ctx,
7826 uint16_t info_level,
7827 files_struct *fsp,
7828 struct smb_filename *smb_fname,
7829 char **ppdata, int total_data,
7830 int *ret_data_size)
7832 char *pdata = *ppdata;
7833 NTSTATUS status = NT_STATUS_OK;
7834 int data_return_size = 0;
7836 *ret_data_size = 0;
7838 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7839 return NT_STATUS_INVALID_LEVEL;
7842 if (!CAN_WRITE(conn)) {
7843 /* Allow POSIX opens. The open path will deny
7844 * any non-readonly opens. */
7845 if (info_level != SMB_POSIX_PATH_OPEN) {
7846 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7850 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7851 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7852 fsp_fnum_dbg(fsp),
7853 info_level, total_data));
7855 switch (info_level) {
7857 case SMB_INFO_STANDARD:
7859 status = smb_set_info_standard(conn,
7860 pdata,
7861 total_data,
7862 fsp,
7863 smb_fname);
7864 break;
7867 case SMB_INFO_SET_EA:
7869 status = smb_info_set_ea(conn,
7870 pdata,
7871 total_data,
7872 fsp,
7873 smb_fname);
7874 break;
7877 case SMB_SET_FILE_BASIC_INFO:
7878 case SMB_FILE_BASIC_INFORMATION:
7880 status = smb_set_file_basic_info(conn,
7881 pdata,
7882 total_data,
7883 fsp,
7884 smb_fname);
7885 break;
7888 case SMB_FILE_ALLOCATION_INFORMATION:
7889 case SMB_SET_FILE_ALLOCATION_INFO:
7891 status = smb_set_file_allocation_info(conn, req,
7892 pdata,
7893 total_data,
7894 fsp,
7895 smb_fname);
7896 break;
7899 case SMB_FILE_END_OF_FILE_INFORMATION:
7900 case SMB_SET_FILE_END_OF_FILE_INFO:
7903 * XP/Win7 both fail after the createfile with
7904 * SMB_SET_FILE_END_OF_FILE_INFO but not
7905 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7906 * The level is known here, so pass it down
7907 * appropriately.
7909 bool should_fail =
7910 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7912 status = smb_set_file_end_of_file_info(conn, req,
7913 pdata,
7914 total_data,
7915 fsp,
7916 smb_fname,
7917 should_fail);
7918 break;
7921 case SMB_FILE_DISPOSITION_INFORMATION:
7922 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7924 #if 0
7925 /* JRA - We used to just ignore this on a path ?
7926 * Shouldn't this be invalid level on a pathname
7927 * based call ?
7929 if (tran_call != TRANSACT2_SETFILEINFO) {
7930 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7932 #endif
7933 status = smb_set_file_disposition_info(conn,
7934 pdata,
7935 total_data,
7936 fsp,
7937 smb_fname);
7938 break;
7941 case SMB_FILE_POSITION_INFORMATION:
7943 status = smb_file_position_information(conn,
7944 pdata,
7945 total_data,
7946 fsp);
7947 break;
7950 case SMB_FILE_FULL_EA_INFORMATION:
7952 status = smb_set_file_full_ea_info(conn,
7953 pdata,
7954 total_data,
7955 fsp);
7956 break;
7959 /* From tridge Samba4 :
7960 * MODE_INFORMATION in setfileinfo (I have no
7961 * idea what "mode information" on a file is - it takes a value of 0,
7962 * 2, 4 or 6. What could it be?).
7965 case SMB_FILE_MODE_INFORMATION:
7967 status = smb_file_mode_information(conn,
7968 pdata,
7969 total_data);
7970 break;
7974 * CIFS UNIX extensions.
7977 case SMB_SET_FILE_UNIX_BASIC:
7979 status = smb_set_file_unix_basic(conn, req,
7980 pdata,
7981 total_data,
7982 fsp,
7983 smb_fname);
7984 break;
7987 case SMB_SET_FILE_UNIX_INFO2:
7989 status = smb_set_file_unix_info2(conn, req,
7990 pdata,
7991 total_data,
7992 fsp,
7993 smb_fname);
7994 break;
7997 case SMB_SET_FILE_UNIX_LINK:
7999 if (fsp) {
8000 /* We must have a pathname for this. */
8001 return NT_STATUS_INVALID_LEVEL;
8003 status = smb_set_file_unix_link(conn, req, pdata,
8004 total_data, smb_fname);
8005 break;
8008 case SMB_SET_FILE_UNIX_HLINK:
8010 if (fsp) {
8011 /* We must have a pathname for this. */
8012 return NT_STATUS_INVALID_LEVEL;
8014 status = smb_set_file_unix_hlink(conn, req,
8015 pdata, total_data,
8016 smb_fname);
8017 break;
8020 case SMB_FILE_RENAME_INFORMATION:
8022 status = smb_file_rename_information(conn, req,
8023 pdata, total_data,
8024 fsp, smb_fname);
8025 break;
8028 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8030 /* SMB2 rename information. */
8031 status = smb2_file_rename_information(conn, req,
8032 pdata, total_data,
8033 fsp, smb_fname);
8034 break;
8037 case SMB_FILE_LINK_INFORMATION:
8039 status = smb_file_link_information(conn, req,
8040 pdata, total_data,
8041 fsp, smb_fname);
8042 break;
8045 #if defined(HAVE_POSIX_ACLS)
8046 case SMB_SET_POSIX_ACL:
8048 status = smb_set_posix_acl(conn,
8049 pdata,
8050 total_data,
8051 fsp,
8052 smb_fname);
8053 break;
8055 #endif
8057 case SMB_SET_POSIX_LOCK:
8059 if (!fsp) {
8060 return NT_STATUS_INVALID_LEVEL;
8062 status = smb_set_posix_lock(conn, req,
8063 pdata, total_data, fsp);
8064 break;
8067 case SMB_POSIX_PATH_OPEN:
8069 if (fsp) {
8070 /* We must have a pathname for this. */
8071 return NT_STATUS_INVALID_LEVEL;
8074 status = smb_posix_open(conn, req,
8075 ppdata,
8076 total_data,
8077 smb_fname,
8078 &data_return_size);
8079 break;
8082 case SMB_POSIX_PATH_UNLINK:
8084 if (fsp) {
8085 /* We must have a pathname for this. */
8086 return NT_STATUS_INVALID_LEVEL;
8089 status = smb_posix_unlink(conn, req,
8090 pdata,
8091 total_data,
8092 smb_fname);
8093 break;
8096 default:
8097 return NT_STATUS_INVALID_LEVEL;
8100 if (!NT_STATUS_IS_OK(status)) {
8101 return status;
8104 *ret_data_size = data_return_size;
8105 return NT_STATUS_OK;
8108 /****************************************************************************
8109 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8110 ****************************************************************************/
8112 static void call_trans2setfilepathinfo(connection_struct *conn,
8113 struct smb_request *req,
8114 unsigned int tran_call,
8115 char **pparams, int total_params,
8116 char **ppdata, int total_data,
8117 unsigned int max_data_bytes)
8119 char *params = *pparams;
8120 char *pdata = *ppdata;
8121 uint16 info_level;
8122 struct smb_filename *smb_fname = NULL;
8123 files_struct *fsp = NULL;
8124 NTSTATUS status = NT_STATUS_OK;
8125 int data_return_size = 0;
8127 if (!params) {
8128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8129 return;
8132 if (tran_call == TRANSACT2_SETFILEINFO) {
8133 if (total_params < 4) {
8134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8135 return;
8138 fsp = file_fsp(req, SVAL(params,0));
8139 /* Basic check for non-null fsp. */
8140 if (!check_fsp_open(conn, req, fsp)) {
8141 return;
8143 info_level = SVAL(params,2);
8145 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8146 if (smb_fname == NULL) {
8147 reply_nterror(req, NT_STATUS_NO_MEMORY);
8148 return;
8151 if(fsp->fh->fd == -1) {
8153 * This is actually a SETFILEINFO on a directory
8154 * handle (returned from an NT SMB). NT5.0 seems
8155 * to do this call. JRA.
8157 if (INFO_LEVEL_IS_UNIX(info_level)) {
8158 /* Always do lstat for UNIX calls. */
8159 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8160 DEBUG(3,("call_trans2setfilepathinfo: "
8161 "SMB_VFS_LSTAT of %s failed "
8162 "(%s)\n",
8163 smb_fname_str_dbg(smb_fname),
8164 strerror(errno)));
8165 reply_nterror(req, map_nt_error_from_unix(errno));
8166 return;
8168 } else {
8169 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8170 DEBUG(3,("call_trans2setfilepathinfo: "
8171 "fileinfo of %s failed (%s)\n",
8172 smb_fname_str_dbg(smb_fname),
8173 strerror(errno)));
8174 reply_nterror(req, map_nt_error_from_unix(errno));
8175 return;
8178 } else if (fsp->print_file) {
8180 * Doing a DELETE_ON_CLOSE should cancel a print job.
8182 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8183 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8185 DEBUG(3,("call_trans2setfilepathinfo: "
8186 "Cancelling print job (%s)\n",
8187 fsp_str_dbg(fsp)));
8189 SSVAL(params,0,0);
8190 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8191 *ppdata, 0,
8192 max_data_bytes);
8193 return;
8194 } else {
8195 reply_nterror(req,
8196 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8197 return;
8199 } else {
8201 * Original code - this is an open file.
8203 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8204 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8205 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8206 strerror(errno)));
8207 reply_nterror(req, map_nt_error_from_unix(errno));
8208 return;
8211 } else {
8212 char *fname = NULL;
8213 uint32_t ucf_flags = 0;
8215 /* set path info */
8216 if (total_params < 7) {
8217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8218 return;
8221 info_level = SVAL(params,0);
8222 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8223 total_params - 6, STR_TERMINATE,
8224 &status);
8225 if (!NT_STATUS_IS_OK(status)) {
8226 reply_nterror(req, status);
8227 return;
8230 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8231 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8232 info_level == SMB_FILE_RENAME_INFORMATION ||
8233 info_level == SMB_POSIX_PATH_UNLINK) {
8234 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8237 status = filename_convert(req, conn,
8238 req->flags2 & FLAGS2_DFS_PATHNAMES,
8239 fname,
8240 ucf_flags,
8241 NULL,
8242 &smb_fname);
8243 if (!NT_STATUS_IS_OK(status)) {
8244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8245 reply_botherror(req,
8246 NT_STATUS_PATH_NOT_COVERED,
8247 ERRSRV, ERRbadpath);
8248 return;
8250 reply_nterror(req, status);
8251 return;
8254 if (INFO_LEVEL_IS_UNIX(info_level)) {
8256 * For CIFS UNIX extensions the target name may not exist.
8259 /* Always do lstat for UNIX calls. */
8260 SMB_VFS_LSTAT(conn, smb_fname);
8262 } else if (!VALID_STAT(smb_fname->st) &&
8263 SMB_VFS_STAT(conn, smb_fname)) {
8264 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8265 "%s failed (%s)\n",
8266 smb_fname_str_dbg(smb_fname),
8267 strerror(errno)));
8268 reply_nterror(req, map_nt_error_from_unix(errno));
8269 return;
8273 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8274 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8275 fsp_fnum_dbg(fsp),
8276 info_level,total_data));
8278 /* Realloc the parameter size */
8279 *pparams = (char *)SMB_REALLOC(*pparams,2);
8280 if (*pparams == NULL) {
8281 reply_nterror(req, NT_STATUS_NO_MEMORY);
8282 return;
8284 params = *pparams;
8286 SSVAL(params,0,0);
8288 status = smbd_do_setfilepathinfo(conn, req, req,
8289 info_level,
8290 fsp,
8291 smb_fname,
8292 ppdata, total_data,
8293 &data_return_size);
8294 if (!NT_STATUS_IS_OK(status)) {
8295 if (open_was_deferred(req->sconn, req->mid)) {
8296 /* We have re-scheduled this call. */
8297 return;
8299 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8300 /* We have re-scheduled this call. */
8301 return;
8303 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8304 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8305 ERRSRV, ERRbadpath);
8306 return;
8308 if (info_level == SMB_POSIX_PATH_OPEN) {
8309 reply_openerror(req, status);
8310 return;
8314 * Invalid EA name needs to return 2 param bytes,
8315 * not a zero-length error packet.
8317 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8318 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8319 max_data_bytes);
8320 } else {
8321 reply_nterror(req, status);
8323 return;
8326 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8327 max_data_bytes);
8329 return;
8332 /****************************************************************************
8333 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8334 ****************************************************************************/
8336 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8337 char **pparams, int total_params,
8338 char **ppdata, int total_data,
8339 unsigned int max_data_bytes)
8341 struct smb_filename *smb_dname = NULL;
8342 char *params = *pparams;
8343 char *pdata = *ppdata;
8344 char *directory = NULL;
8345 NTSTATUS status = NT_STATUS_OK;
8346 struct ea_list *ea_list = NULL;
8347 TALLOC_CTX *ctx = talloc_tos();
8349 if (!CAN_WRITE(conn)) {
8350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8351 return;
8354 if (total_params < 5) {
8355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8356 return;
8359 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8360 total_params - 4, STR_TERMINATE,
8361 &status);
8362 if (!NT_STATUS_IS_OK(status)) {
8363 reply_nterror(req, status);
8364 return;
8367 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8369 status = filename_convert(ctx,
8370 conn,
8371 req->flags2 & FLAGS2_DFS_PATHNAMES,
8372 directory,
8374 NULL,
8375 &smb_dname);
8377 if (!NT_STATUS_IS_OK(status)) {
8378 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8379 reply_botherror(req,
8380 NT_STATUS_PATH_NOT_COVERED,
8381 ERRSRV, ERRbadpath);
8382 return;
8384 reply_nterror(req, status);
8385 return;
8389 * OS/2 workplace shell seems to send SET_EA requests of "null"
8390 * length (4 bytes containing IVAL 4).
8391 * They seem to have no effect. Bug #3212. JRA.
8394 if (total_data && (total_data != 4)) {
8395 /* Any data in this call is an EA list. */
8396 if (total_data < 10) {
8397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8398 goto out;
8401 if (IVAL(pdata,0) > total_data) {
8402 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8403 IVAL(pdata,0), (unsigned int)total_data));
8404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8405 goto out;
8408 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8409 total_data - 4);
8410 if (!ea_list) {
8411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8412 goto out;
8415 if (!lp_ea_support(SNUM(conn))) {
8416 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8417 goto out;
8420 /* If total_data == 4 Windows doesn't care what values
8421 * are placed in that field, it just ignores them.
8422 * The System i QNTC IBM SMB client puts bad values here,
8423 * so ignore them. */
8425 status = create_directory(conn, req, smb_dname);
8427 if (!NT_STATUS_IS_OK(status)) {
8428 reply_nterror(req, status);
8429 goto out;
8432 /* Try and set any given EA. */
8433 if (ea_list) {
8434 status = set_ea(conn, NULL, smb_dname, ea_list);
8435 if (!NT_STATUS_IS_OK(status)) {
8436 reply_nterror(req, status);
8437 goto out;
8441 /* Realloc the parameter and data sizes */
8442 *pparams = (char *)SMB_REALLOC(*pparams,2);
8443 if(*pparams == NULL) {
8444 reply_nterror(req, NT_STATUS_NO_MEMORY);
8445 goto out;
8447 params = *pparams;
8449 SSVAL(params,0,0);
8451 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8453 out:
8454 TALLOC_FREE(smb_dname);
8455 return;
8458 /****************************************************************************
8459 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8460 We don't actually do this - we just send a null response.
8461 ****************************************************************************/
8463 static void call_trans2findnotifyfirst(connection_struct *conn,
8464 struct smb_request *req,
8465 char **pparams, int total_params,
8466 char **ppdata, int total_data,
8467 unsigned int max_data_bytes)
8469 char *params = *pparams;
8470 uint16 info_level;
8472 if (total_params < 6) {
8473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8474 return;
8477 info_level = SVAL(params,4);
8478 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8480 switch (info_level) {
8481 case 1:
8482 case 2:
8483 break;
8484 default:
8485 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8486 return;
8489 /* Realloc the parameter and data sizes */
8490 *pparams = (char *)SMB_REALLOC(*pparams,6);
8491 if (*pparams == NULL) {
8492 reply_nterror(req, NT_STATUS_NO_MEMORY);
8493 return;
8495 params = *pparams;
8497 SSVAL(params,0,fnf_handle);
8498 SSVAL(params,2,0); /* No changes */
8499 SSVAL(params,4,0); /* No EA errors */
8501 fnf_handle++;
8503 if(fnf_handle == 0)
8504 fnf_handle = 257;
8506 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8508 return;
8511 /****************************************************************************
8512 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8513 changes). Currently this does nothing.
8514 ****************************************************************************/
8516 static void call_trans2findnotifynext(connection_struct *conn,
8517 struct smb_request *req,
8518 char **pparams, int total_params,
8519 char **ppdata, int total_data,
8520 unsigned int max_data_bytes)
8522 char *params = *pparams;
8524 DEBUG(3,("call_trans2findnotifynext\n"));
8526 /* Realloc the parameter and data sizes */
8527 *pparams = (char *)SMB_REALLOC(*pparams,4);
8528 if (*pparams == NULL) {
8529 reply_nterror(req, NT_STATUS_NO_MEMORY);
8530 return;
8532 params = *pparams;
8534 SSVAL(params,0,0); /* No changes */
8535 SSVAL(params,2,0); /* No EA errors */
8537 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8539 return;
8542 /****************************************************************************
8543 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8544 ****************************************************************************/
8546 static void call_trans2getdfsreferral(connection_struct *conn,
8547 struct smb_request *req,
8548 char **pparams, int total_params,
8549 char **ppdata, int total_data,
8550 unsigned int max_data_bytes)
8552 char *params = *pparams;
8553 char *pathname = NULL;
8554 int reply_size = 0;
8555 int max_referral_level;
8556 NTSTATUS status = NT_STATUS_OK;
8557 TALLOC_CTX *ctx = talloc_tos();
8559 DEBUG(10,("call_trans2getdfsreferral\n"));
8561 if (total_params < 3) {
8562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8563 return;
8566 max_referral_level = SVAL(params,0);
8568 if(!lp_host_msdfs()) {
8569 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8570 return;
8573 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8574 total_params - 2, STR_TERMINATE);
8575 if (!pathname) {
8576 reply_nterror(req, NT_STATUS_NOT_FOUND);
8577 return;
8579 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8580 ppdata,&status)) < 0) {
8581 reply_nterror(req, status);
8582 return;
8585 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8586 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8587 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8589 return;
8592 #define LMCAT_SPL 0x53
8593 #define LMFUNC_GETJOBID 0x60
8595 /****************************************************************************
8596 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8597 ****************************************************************************/
8599 static void call_trans2ioctl(connection_struct *conn,
8600 struct smb_request *req,
8601 char **pparams, int total_params,
8602 char **ppdata, int total_data,
8603 unsigned int max_data_bytes)
8605 char *pdata = *ppdata;
8606 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8608 /* check for an invalid fid before proceeding */
8610 if (!fsp) {
8611 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8612 return;
8615 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8616 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8617 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8618 if (*ppdata == NULL) {
8619 reply_nterror(req, NT_STATUS_NO_MEMORY);
8620 return;
8622 pdata = *ppdata;
8624 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8625 CAN ACCEPT THIS IN UNICODE. JRA. */
8627 /* Job number */
8628 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8630 srvstr_push(pdata, req->flags2, pdata + 2,
8631 lp_netbios_name(), 15,
8632 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8633 srvstr_push(pdata, req->flags2, pdata+18,
8634 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8635 STR_ASCII|STR_TERMINATE); /* Service name */
8636 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8637 max_data_bytes);
8638 return;
8641 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8642 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8645 /****************************************************************************
8646 Reply to a SMBfindclose (stop trans2 directory search).
8647 ****************************************************************************/
8649 void reply_findclose(struct smb_request *req)
8651 int dptr_num;
8652 struct smbd_server_connection *sconn = req->sconn;
8654 START_PROFILE(SMBfindclose);
8656 if (req->wct < 1) {
8657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8658 END_PROFILE(SMBfindclose);
8659 return;
8662 dptr_num = SVALS(req->vwv+0, 0);
8664 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8666 dptr_close(sconn, &dptr_num);
8668 reply_outbuf(req, 0, 0);
8670 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8672 END_PROFILE(SMBfindclose);
8673 return;
8676 /****************************************************************************
8677 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8678 ****************************************************************************/
8680 void reply_findnclose(struct smb_request *req)
8682 int dptr_num;
8684 START_PROFILE(SMBfindnclose);
8686 if (req->wct < 1) {
8687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8688 END_PROFILE(SMBfindnclose);
8689 return;
8692 dptr_num = SVAL(req->vwv+0, 0);
8694 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8696 /* We never give out valid handles for a
8697 findnotifyfirst - so any dptr_num is ok here.
8698 Just ignore it. */
8700 reply_outbuf(req, 0, 0);
8702 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8704 END_PROFILE(SMBfindnclose);
8705 return;
8708 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8709 struct trans_state *state)
8711 if (get_Protocol() >= PROTOCOL_NT1) {
8712 req->flags2 |= 0x40; /* IS_LONG_NAME */
8713 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8716 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8717 if (state->call != TRANSACT2_QFSINFO &&
8718 state->call != TRANSACT2_SETFSINFO) {
8719 DEBUG(0,("handle_trans2: encryption required "
8720 "with call 0x%x\n",
8721 (unsigned int)state->call));
8722 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8723 return;
8727 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8729 /* Now we must call the relevant TRANS2 function */
8730 switch(state->call) {
8731 case TRANSACT2_OPEN:
8733 START_PROFILE(Trans2_open);
8734 call_trans2open(conn, req,
8735 &state->param, state->total_param,
8736 &state->data, state->total_data,
8737 state->max_data_return);
8738 END_PROFILE(Trans2_open);
8739 break;
8742 case TRANSACT2_FINDFIRST:
8744 START_PROFILE(Trans2_findfirst);
8745 call_trans2findfirst(conn, req,
8746 &state->param, state->total_param,
8747 &state->data, state->total_data,
8748 state->max_data_return);
8749 END_PROFILE(Trans2_findfirst);
8750 break;
8753 case TRANSACT2_FINDNEXT:
8755 START_PROFILE(Trans2_findnext);
8756 call_trans2findnext(conn, req,
8757 &state->param, state->total_param,
8758 &state->data, state->total_data,
8759 state->max_data_return);
8760 END_PROFILE(Trans2_findnext);
8761 break;
8764 case TRANSACT2_QFSINFO:
8766 START_PROFILE(Trans2_qfsinfo);
8767 call_trans2qfsinfo(conn, req,
8768 &state->param, state->total_param,
8769 &state->data, state->total_data,
8770 state->max_data_return);
8771 END_PROFILE(Trans2_qfsinfo);
8772 break;
8775 case TRANSACT2_SETFSINFO:
8777 START_PROFILE(Trans2_setfsinfo);
8778 call_trans2setfsinfo(conn, req,
8779 &state->param, state->total_param,
8780 &state->data, state->total_data,
8781 state->max_data_return);
8782 END_PROFILE(Trans2_setfsinfo);
8783 break;
8786 case TRANSACT2_QPATHINFO:
8787 case TRANSACT2_QFILEINFO:
8789 START_PROFILE(Trans2_qpathinfo);
8790 call_trans2qfilepathinfo(conn, req, state->call,
8791 &state->param, state->total_param,
8792 &state->data, state->total_data,
8793 state->max_data_return);
8794 END_PROFILE(Trans2_qpathinfo);
8795 break;
8798 case TRANSACT2_SETPATHINFO:
8799 case TRANSACT2_SETFILEINFO:
8801 START_PROFILE(Trans2_setpathinfo);
8802 call_trans2setfilepathinfo(conn, req, state->call,
8803 &state->param, state->total_param,
8804 &state->data, state->total_data,
8805 state->max_data_return);
8806 END_PROFILE(Trans2_setpathinfo);
8807 break;
8810 case TRANSACT2_FINDNOTIFYFIRST:
8812 START_PROFILE(Trans2_findnotifyfirst);
8813 call_trans2findnotifyfirst(conn, req,
8814 &state->param, state->total_param,
8815 &state->data, state->total_data,
8816 state->max_data_return);
8817 END_PROFILE(Trans2_findnotifyfirst);
8818 break;
8821 case TRANSACT2_FINDNOTIFYNEXT:
8823 START_PROFILE(Trans2_findnotifynext);
8824 call_trans2findnotifynext(conn, req,
8825 &state->param, state->total_param,
8826 &state->data, state->total_data,
8827 state->max_data_return);
8828 END_PROFILE(Trans2_findnotifynext);
8829 break;
8832 case TRANSACT2_MKDIR:
8834 START_PROFILE(Trans2_mkdir);
8835 call_trans2mkdir(conn, req,
8836 &state->param, state->total_param,
8837 &state->data, state->total_data,
8838 state->max_data_return);
8839 END_PROFILE(Trans2_mkdir);
8840 break;
8843 case TRANSACT2_GET_DFS_REFERRAL:
8845 START_PROFILE(Trans2_get_dfs_referral);
8846 call_trans2getdfsreferral(conn, req,
8847 &state->param, state->total_param,
8848 &state->data, state->total_data,
8849 state->max_data_return);
8850 END_PROFILE(Trans2_get_dfs_referral);
8851 break;
8854 case TRANSACT2_IOCTL:
8856 START_PROFILE(Trans2_ioctl);
8857 call_trans2ioctl(conn, req,
8858 &state->param, state->total_param,
8859 &state->data, state->total_data,
8860 state->max_data_return);
8861 END_PROFILE(Trans2_ioctl);
8862 break;
8865 default:
8866 /* Error in request */
8867 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8868 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8872 /****************************************************************************
8873 Reply to a SMBtrans2.
8874 ****************************************************************************/
8876 void reply_trans2(struct smb_request *req)
8878 connection_struct *conn = req->conn;
8879 unsigned int dsoff;
8880 unsigned int dscnt;
8881 unsigned int psoff;
8882 unsigned int pscnt;
8883 unsigned int tran_call;
8884 struct trans_state *state;
8885 NTSTATUS result;
8887 START_PROFILE(SMBtrans2);
8889 if (req->wct < 14) {
8890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8891 END_PROFILE(SMBtrans2);
8892 return;
8895 dsoff = SVAL(req->vwv+12, 0);
8896 dscnt = SVAL(req->vwv+11, 0);
8897 psoff = SVAL(req->vwv+10, 0);
8898 pscnt = SVAL(req->vwv+9, 0);
8899 tran_call = SVAL(req->vwv+14, 0);
8901 result = allow_new_trans(conn->pending_trans, req->mid);
8902 if (!NT_STATUS_IS_OK(result)) {
8903 DEBUG(2, ("Got invalid trans2 request: %s\n",
8904 nt_errstr(result)));
8905 reply_nterror(req, result);
8906 END_PROFILE(SMBtrans2);
8907 return;
8910 if (IS_IPC(conn)) {
8911 switch (tran_call) {
8912 /* List the allowed trans2 calls on IPC$ */
8913 case TRANSACT2_OPEN:
8914 case TRANSACT2_GET_DFS_REFERRAL:
8915 case TRANSACT2_QFILEINFO:
8916 case TRANSACT2_QFSINFO:
8917 case TRANSACT2_SETFSINFO:
8918 break;
8919 default:
8920 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8921 END_PROFILE(SMBtrans2);
8922 return;
8926 if ((state = talloc(conn, struct trans_state)) == NULL) {
8927 DEBUG(0, ("talloc failed\n"));
8928 reply_nterror(req, NT_STATUS_NO_MEMORY);
8929 END_PROFILE(SMBtrans2);
8930 return;
8933 state->cmd = SMBtrans2;
8935 state->mid = req->mid;
8936 state->vuid = req->vuid;
8937 state->setup_count = SVAL(req->vwv+13, 0);
8938 state->setup = NULL;
8939 state->total_param = SVAL(req->vwv+0, 0);
8940 state->param = NULL;
8941 state->total_data = SVAL(req->vwv+1, 0);
8942 state->data = NULL;
8943 state->max_param_return = SVAL(req->vwv+2, 0);
8944 state->max_data_return = SVAL(req->vwv+3, 0);
8945 state->max_setup_return = SVAL(req->vwv+4, 0);
8946 state->close_on_completion = BITSETW(req->vwv+5, 0);
8947 state->one_way = BITSETW(req->vwv+5, 1);
8949 state->call = tran_call;
8951 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8952 is so as a sanity check */
8953 if (state->setup_count != 1) {
8955 * Need to have rc=0 for ioctl to get job id for OS/2.
8956 * Network printing will fail if function is not successful.
8957 * Similar function in reply.c will be used if protocol
8958 * is LANMAN1.0 instead of LM1.2X002.
8959 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8960 * outbuf doesn't have to be set(only job id is used).
8962 if ( (state->setup_count == 4)
8963 && (tran_call == TRANSACT2_IOCTL)
8964 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8965 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8966 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8967 } else {
8968 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8969 DEBUG(2,("Transaction is %d\n",tran_call));
8970 TALLOC_FREE(state);
8971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8972 END_PROFILE(SMBtrans2);
8973 return;
8977 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8978 goto bad_param;
8980 if (state->total_data) {
8982 if (trans_oob(state->total_data, 0, dscnt)
8983 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8984 goto bad_param;
8987 /* Can't use talloc here, the core routines do realloc on the
8988 * params and data. */
8989 state->data = (char *)SMB_MALLOC(state->total_data);
8990 if (state->data == NULL) {
8991 DEBUG(0,("reply_trans2: data malloc fail for %u "
8992 "bytes !\n", (unsigned int)state->total_data));
8993 TALLOC_FREE(state);
8994 reply_nterror(req, NT_STATUS_NO_MEMORY);
8995 END_PROFILE(SMBtrans2);
8996 return;
8999 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9002 if (state->total_param) {
9004 if (trans_oob(state->total_param, 0, pscnt)
9005 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9006 goto bad_param;
9009 /* Can't use talloc here, the core routines do realloc on the
9010 * params and data. */
9011 state->param = (char *)SMB_MALLOC(state->total_param);
9012 if (state->param == NULL) {
9013 DEBUG(0,("reply_trans: param malloc fail for %u "
9014 "bytes !\n", (unsigned int)state->total_param));
9015 SAFE_FREE(state->data);
9016 TALLOC_FREE(state);
9017 reply_nterror(req, NT_STATUS_NO_MEMORY);
9018 END_PROFILE(SMBtrans2);
9019 return;
9022 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9025 state->received_data = dscnt;
9026 state->received_param = pscnt;
9028 if ((state->received_param == state->total_param) &&
9029 (state->received_data == state->total_data)) {
9031 handle_trans2(conn, req, state);
9033 SAFE_FREE(state->data);
9034 SAFE_FREE(state->param);
9035 TALLOC_FREE(state);
9036 END_PROFILE(SMBtrans2);
9037 return;
9040 DLIST_ADD(conn->pending_trans, state);
9042 /* We need to send an interim response then receive the rest
9043 of the parameter/data bytes */
9044 reply_outbuf(req, 0, 0);
9045 show_msg((char *)req->outbuf);
9046 END_PROFILE(SMBtrans2);
9047 return;
9049 bad_param:
9051 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9052 SAFE_FREE(state->data);
9053 SAFE_FREE(state->param);
9054 TALLOC_FREE(state);
9055 END_PROFILE(SMBtrans2);
9056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9060 /****************************************************************************
9061 Reply to a SMBtranss2
9062 ****************************************************************************/
9064 void reply_transs2(struct smb_request *req)
9066 connection_struct *conn = req->conn;
9067 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9068 struct trans_state *state;
9070 START_PROFILE(SMBtranss2);
9072 show_msg((const char *)req->inbuf);
9074 /* Windows clients expect all replies to
9075 a transact secondary (SMBtranss2 0x33)
9076 to have a command code of transact
9077 (SMBtrans2 0x32). See bug #8989
9078 and also [MS-CIFS] section 2.2.4.47.2
9079 for details.
9081 req->cmd = SMBtrans2;
9083 if (req->wct < 8) {
9084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9085 END_PROFILE(SMBtranss2);
9086 return;
9089 for (state = conn->pending_trans; state != NULL;
9090 state = state->next) {
9091 if (state->mid == req->mid) {
9092 break;
9096 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9098 END_PROFILE(SMBtranss2);
9099 return;
9102 /* Revise state->total_param and state->total_data in case they have
9103 changed downwards */
9105 if (SVAL(req->vwv+0, 0) < state->total_param)
9106 state->total_param = SVAL(req->vwv+0, 0);
9107 if (SVAL(req->vwv+1, 0) < state->total_data)
9108 state->total_data = SVAL(req->vwv+1, 0);
9110 pcnt = SVAL(req->vwv+2, 0);
9111 poff = SVAL(req->vwv+3, 0);
9112 pdisp = SVAL(req->vwv+4, 0);
9114 dcnt = SVAL(req->vwv+5, 0);
9115 doff = SVAL(req->vwv+6, 0);
9116 ddisp = SVAL(req->vwv+7, 0);
9118 state->received_param += pcnt;
9119 state->received_data += dcnt;
9121 if ((state->received_data > state->total_data) ||
9122 (state->received_param > state->total_param))
9123 goto bad_param;
9125 if (pcnt) {
9126 if (trans_oob(state->total_param, pdisp, pcnt)
9127 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9128 goto bad_param;
9130 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9133 if (dcnt) {
9134 if (trans_oob(state->total_data, ddisp, dcnt)
9135 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9136 goto bad_param;
9138 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9141 if ((state->received_param < state->total_param) ||
9142 (state->received_data < state->total_data)) {
9143 END_PROFILE(SMBtranss2);
9144 return;
9147 handle_trans2(conn, req, state);
9149 DLIST_REMOVE(conn->pending_trans, state);
9150 SAFE_FREE(state->data);
9151 SAFE_FREE(state->param);
9152 TALLOC_FREE(state);
9154 END_PROFILE(SMBtranss2);
9155 return;
9157 bad_param:
9159 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9160 DLIST_REMOVE(conn->pending_trans, state);
9161 SAFE_FREE(state->data);
9162 SAFE_FREE(state->param);
9163 TALLOC_FREE(state);
9164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9165 END_PROFILE(SMBtranss2);
9166 return;