s3:smbd: pass down vuid as uint64_t in lanman.c
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob3787fa972173f087ceb9953c1946a8c399b65c52
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 access_mask);
71 if (!NT_STATUS_IS_OK(status)) {
72 return status;
75 return NT_STATUS_OK;
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
92 return val;
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
103 uint64_t file_index;
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
109 return file_index;
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
125 SAMBA_XATTR_MARKER,
126 XATTR_NTACL_NAME,
127 NULL
130 int i;
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
134 return true;
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
138 return true;
140 return false;
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
153 char *val = NULL;
154 ssize_t sizeret;
156 again:
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
159 if (!val) {
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 } else {
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
170 attr_size = 65536;
171 goto again;
174 if (sizeret == -1) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
181 pea->flags = 0;
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
184 } else {
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
188 TALLOC_FREE(val);
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
193 return NT_STATUS_OK;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
204 char *p;
205 char **names, **tmp;
206 size_t num_names;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
214 return NT_STATUS_OK;
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
222 if (names == NULL) {
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
233 TALLOC_FREE(names);
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
239 ea_namelist_size);
240 } else {
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
242 ea_namelist_size);
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
248 else {
249 break;
253 if (sizeret == -1) {
254 TALLOC_FREE(names);
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
261 if (sizeret == 0) {
262 TALLOC_FREE(names);
263 if (pnames) {
264 *pnames = NULL;
266 *pnum_names = 0;
267 return NT_STATUS_OK;
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
275 TALLOC_FREE(names);
276 return NT_STATUS_INTERNAL_ERROR;
280 * count the names
282 num_names = 0;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
285 num_names += 1;
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
289 if (tmp == NULL) {
290 DEBUG(0, ("talloc failed\n"));
291 TALLOC_FREE(names);
292 return NT_STATUS_NO_MEMORY;
295 names = tmp;
296 num_names = 0;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
302 if (pnames) {
303 *pnames = names;
304 } else {
305 TALLOC_FREE(names);
307 *pnum_names = num_names;
308 return NT_STATUS_OK;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len)
318 /* Get a list of all xattrs. Max namesize is 64k. */
319 size_t i, num_names;
320 char **names;
321 struct ea_list *ea_list_head = NULL;
322 NTSTATUS status;
324 *pea_total_len = 0;
326 if (!lp_ea_support(SNUM(conn))) {
327 return NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
334 return NULL;
337 for (i=0; i<num_names; i++) {
338 struct ea_list *listp;
339 fstring dos_ea_name;
341 if (strnequal(names[i], "system.", 7)
342 || samba_private_attr_name(names[i]))
343 continue;
345 listp = talloc(mem_ctx, struct ea_list);
346 if (listp == NULL) {
347 return NULL;
350 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
351 fname, names[i],
352 &listp->ea))) {
353 return NULL;
356 push_ascii_fstring(dos_ea_name, listp->ea.name);
358 *pea_total_len +=
359 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
361 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
362 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
363 (unsigned int)listp->ea.value.length));
365 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
369 /* Add on 4 for total length. */
370 if (*pea_total_len) {
371 *pea_total_len += 4;
374 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
375 (unsigned int)*pea_total_len));
377 return ea_list_head;
380 /****************************************************************************
381 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
382 that was filled.
383 ****************************************************************************/
385 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
386 connection_struct *conn, struct ea_list *ea_list)
388 unsigned int ret_data_size = 4;
389 char *p = pdata;
391 SMB_ASSERT(total_data_size >= 4);
393 if (!lp_ea_support(SNUM(conn))) {
394 SIVAL(pdata,4,0);
395 return 4;
398 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
399 size_t dos_namelen;
400 fstring dos_ea_name;
401 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
402 dos_namelen = strlen(dos_ea_name);
403 if (dos_namelen > 255 || dos_namelen == 0) {
404 break;
406 if (ea_list->ea.value.length > 65535) {
407 break;
409 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
410 break;
413 /* We know we have room. */
414 SCVAL(p,0,ea_list->ea.flags);
415 SCVAL(p,1,dos_namelen);
416 SSVAL(p,2,ea_list->ea.value.length);
417 strlcpy(p+4, dos_ea_name, dos_namelen+1);
418 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
420 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
421 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
424 ret_data_size = PTR_DIFF(p, pdata);
425 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
426 SIVAL(pdata,0,ret_data_size);
427 return ret_data_size;
430 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
431 char *pdata,
432 unsigned int total_data_size,
433 unsigned int *ret_data_size,
434 connection_struct *conn,
435 struct ea_list *ea_list)
437 uint8_t *p = (uint8_t *)pdata;
438 uint8_t *last_start = NULL;
440 *ret_data_size = 0;
442 if (!lp_ea_support(SNUM(conn))) {
443 return NT_STATUS_NO_EAS_ON_FILE;
446 for (; ea_list; ea_list = ea_list->next) {
447 size_t dos_namelen;
448 fstring dos_ea_name;
449 size_t this_size;
451 if (last_start) {
452 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
454 last_start = p;
456 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
457 dos_namelen = strlen(dos_ea_name);
458 if (dos_namelen > 255 || dos_namelen == 0) {
459 return NT_STATUS_INTERNAL_ERROR;
461 if (ea_list->ea.value.length > 65535) {
462 return NT_STATUS_INTERNAL_ERROR;
465 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
467 if (ea_list->next) {
468 size_t pad = 4 - (this_size % 4);
469 this_size += pad;
472 if (this_size > total_data_size) {
473 return NT_STATUS_INFO_LENGTH_MISMATCH;
476 /* We know we have room. */
477 SIVAL(p, 0x00, 0); /* next offset */
478 SCVAL(p, 0x04, ea_list->ea.flags);
479 SCVAL(p, 0x05, dos_namelen);
480 SSVAL(p, 0x06, ea_list->ea.value.length);
481 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
482 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
484 total_data_size -= this_size;
485 p += this_size;
488 *ret_data_size = PTR_DIFF(p, pdata);
489 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
490 return NT_STATUS_OK;
493 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
495 size_t total_ea_len = 0;
496 TALLOC_CTX *mem_ctx = NULL;
498 if (!lp_ea_support(SNUM(conn))) {
499 return 0;
501 mem_ctx = talloc_tos();
502 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
503 return total_ea_len;
506 /****************************************************************************
507 Ensure the EA name is case insensitive by matching any existing EA name.
508 ****************************************************************************/
510 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
512 size_t total_ea_len;
513 TALLOC_CTX *mem_ctx = talloc_tos();
514 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
516 for (; ea_list; ea_list = ea_list->next) {
517 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
518 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
519 &unix_ea_name[5], ea_list->ea.name));
520 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
521 break;
526 /****************************************************************************
527 Set or delete an extended attribute.
528 ****************************************************************************/
530 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
531 const struct smb_filename *smb_fname, struct ea_list *ea_list)
533 NTSTATUS status;
534 char *fname = NULL;
536 if (!lp_ea_support(SNUM(conn))) {
537 return NT_STATUS_EAS_NOT_SUPPORTED;
540 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
541 if (!NT_STATUS_IS_OK(status)) {
542 return status;
545 /* For now setting EAs on streams isn't supported. */
546 fname = smb_fname->base_name;
548 for (;ea_list; ea_list = ea_list->next) {
549 int ret;
550 fstring unix_ea_name;
552 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
553 fstrcat(unix_ea_name, ea_list->ea.name);
555 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
557 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
559 if (samba_private_attr_name(unix_ea_name)) {
560 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
561 return NT_STATUS_ACCESS_DENIED;
564 if (ea_list->ea.value.length == 0) {
565 /* Remove the attribute. */
566 if (fsp && (fsp->fh->fd != -1)) {
567 DEBUG(10,("set_ea: deleting ea name %s on "
568 "file %s by file descriptor.\n",
569 unix_ea_name, fsp_str_dbg(fsp)));
570 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
571 } else {
572 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
573 unix_ea_name, fname));
574 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
576 #ifdef ENOATTR
577 /* Removing a non existent attribute always succeeds. */
578 if (ret == -1 && errno == ENOATTR) {
579 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
580 unix_ea_name));
581 ret = 0;
583 #endif
584 } else {
585 if (fsp && (fsp->fh->fd != -1)) {
586 DEBUG(10,("set_ea: setting ea name %s on file "
587 "%s by file descriptor.\n",
588 unix_ea_name, fsp_str_dbg(fsp)));
589 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
590 ea_list->ea.value.data, ea_list->ea.value.length, 0);
591 } else {
592 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
593 unix_ea_name, fname));
594 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
595 ea_list->ea.value.data, ea_list->ea.value.length, 0);
599 if (ret == -1) {
600 #ifdef ENOTSUP
601 if (errno == ENOTSUP) {
602 return NT_STATUS_EAS_NOT_SUPPORTED;
604 #endif
605 return map_nt_error_from_unix(errno);
609 return NT_STATUS_OK;
611 /****************************************************************************
612 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
613 ****************************************************************************/
615 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
617 struct ea_list *ea_list_head = NULL;
618 size_t converted_size, offset = 0;
620 while (offset + 2 < data_size) {
621 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
622 unsigned int namelen = CVAL(pdata,offset);
624 offset++; /* Go past the namelen byte. */
626 /* integer wrap paranioa. */
627 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
628 (offset > data_size) || (namelen > data_size) ||
629 (offset + namelen >= data_size)) {
630 break;
632 /* Ensure the name is null terminated. */
633 if (pdata[offset + namelen] != '\0') {
634 return NULL;
636 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
637 &converted_size)) {
638 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
639 "failed: %s", strerror(errno)));
641 if (!eal->ea.name) {
642 return NULL;
645 offset += (namelen + 1); /* Go past the name + terminating zero. */
646 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
647 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
650 return ea_list_head;
653 /****************************************************************************
654 Read one EA list entry from the buffer.
655 ****************************************************************************/
657 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
659 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
660 uint16 val_len;
661 unsigned int namelen;
662 size_t converted_size;
664 if (!eal) {
665 return NULL;
668 if (data_size < 6) {
669 return NULL;
672 eal->ea.flags = CVAL(pdata,0);
673 namelen = CVAL(pdata,1);
674 val_len = SVAL(pdata,2);
676 if (4 + namelen + 1 + val_len > data_size) {
677 return NULL;
680 /* Ensure the name is null terminated. */
681 if (pdata[namelen + 4] != '\0') {
682 return NULL;
684 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
685 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
686 strerror(errno)));
688 if (!eal->ea.name) {
689 return NULL;
692 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
693 if (!eal->ea.value.data) {
694 return NULL;
697 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
699 /* Ensure we're null terminated just in case we print the value. */
700 eal->ea.value.data[val_len] = '\0';
701 /* But don't count the null. */
702 eal->ea.value.length--;
704 if (pbytes_used) {
705 *pbytes_used = 4 + namelen + 1 + val_len;
708 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
709 dump_data(10, eal->ea.value.data, eal->ea.value.length);
711 return eal;
714 /****************************************************************************
715 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
716 ****************************************************************************/
718 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
720 struct ea_list *ea_list_head = NULL;
721 size_t offset = 0;
722 size_t bytes_used = 0;
724 while (offset < data_size) {
725 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
727 if (!eal) {
728 return NULL;
731 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
732 offset += bytes_used;
735 return ea_list_head;
738 /****************************************************************************
739 Count the total EA size needed.
740 ****************************************************************************/
742 static size_t ea_list_size(struct ea_list *ealist)
744 fstring dos_ea_name;
745 struct ea_list *listp;
746 size_t ret = 0;
748 for (listp = ealist; listp; listp = listp->next) {
749 push_ascii_fstring(dos_ea_name, listp->ea.name);
750 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
752 /* Add on 4 for total length. */
753 if (ret) {
754 ret += 4;
757 return ret;
760 /****************************************************************************
761 Return a union of EA's from a file list and a list of names.
762 The TALLOC context for the two lists *MUST* be identical as we steal
763 memory from one list to add to another. JRA.
764 ****************************************************************************/
766 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
768 struct ea_list *nlistp, *flistp;
770 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
771 for (flistp = file_list; flistp; flistp = flistp->next) {
772 if (strequal(nlistp->ea.name, flistp->ea.name)) {
773 break;
777 if (flistp) {
778 /* Copy the data from this entry. */
779 nlistp->ea.flags = flistp->ea.flags;
780 nlistp->ea.value = flistp->ea.value;
781 } else {
782 /* Null entry. */
783 nlistp->ea.flags = 0;
784 ZERO_STRUCT(nlistp->ea.value);
788 *total_ea_len = ea_list_size(name_list);
789 return name_list;
792 /****************************************************************************
793 Send the required number of replies back.
794 We assume all fields other than the data fields are
795 set correctly for the type of call.
796 HACK ! Always assumes smb_setup field is zero.
797 ****************************************************************************/
799 void send_trans2_replies(connection_struct *conn,
800 struct smb_request *req,
801 const char *params,
802 int paramsize,
803 const char *pdata,
804 int datasize,
805 int max_data_bytes)
807 /* As we are using a protocol > LANMAN1 then the max_send
808 variable must have been set in the sessetupX call.
809 This takes precedence over the max_xmit field in the
810 global struct. These different max_xmit variables should
811 be merged as this is now too confusing */
813 int data_to_send = datasize;
814 int params_to_send = paramsize;
815 int useable_space;
816 const char *pp = params;
817 const char *pd = pdata;
818 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
819 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
820 int data_alignment_offset = 0;
821 bool overflow = False;
822 struct smbd_server_connection *sconn = req->sconn;
823 int max_send = sconn->smb1.sessions.max_send;
825 /* Modify the data_to_send and datasize and set the error if
826 we're trying to send more than max_data_bytes. We still send
827 the part of the packet(s) that fit. Strange, but needed
828 for OS/2. */
830 if (max_data_bytes > 0 && datasize > max_data_bytes) {
831 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
832 max_data_bytes, datasize ));
833 datasize = data_to_send = max_data_bytes;
834 overflow = True;
837 /* If there genuinely are no parameters or data to send just send the empty packet */
839 if(params_to_send == 0 && data_to_send == 0) {
840 reply_outbuf(req, 10, 0);
841 show_msg((char *)req->outbuf);
842 if (!srv_send_smb(sconn,
843 (char *)req->outbuf,
844 true, req->seqnum+1,
845 IS_CONN_ENCRYPTED(conn),
846 &req->pcd)) {
847 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
849 TALLOC_FREE(req->outbuf);
850 return;
853 /* When sending params and data ensure that both are nicely aligned */
854 /* Only do this alignment when there is also data to send - else
855 can cause NT redirector problems. */
857 if (((params_to_send % 4) != 0) && (data_to_send != 0))
858 data_alignment_offset = 4 - (params_to_send % 4);
860 /* Space is bufsize minus Netbios over TCP header minus SMB header */
861 /* The alignment_offset is to align the param bytes on an even byte
862 boundary. NT 4.0 Beta needs this to work correctly. */
864 useable_space = max_send - (smb_size
865 + 2 * 10 /* wct */
866 + alignment_offset
867 + data_alignment_offset);
869 if (useable_space < 0) {
870 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
871 "= %d!!!", useable_space));
872 exit_server_cleanly("send_trans2_replies: Not enough space");
875 while (params_to_send || data_to_send) {
876 /* Calculate whether we will totally or partially fill this packet */
878 total_sent_thistime = params_to_send + data_to_send;
880 /* We can never send more than useable_space */
882 * Note that 'useable_space' does not include the alignment offsets,
883 * but we must include the alignment offsets in the calculation of
884 * the length of the data we send over the wire, as the alignment offsets
885 * are sent here. Fix from Marc_Jacobsen@hp.com.
888 total_sent_thistime = MIN(total_sent_thistime, useable_space);
890 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
891 + data_alignment_offset);
894 * We might have SMBtrans2s in req which was transferred to
895 * the outbuf, fix that.
897 SCVAL(req->outbuf, smb_com, SMBtrans2);
899 /* Set total params and data to be sent */
900 SSVAL(req->outbuf,smb_tprcnt,paramsize);
901 SSVAL(req->outbuf,smb_tdrcnt,datasize);
903 /* Calculate how many parameters and data we can fit into
904 * this packet. Parameters get precedence
907 params_sent_thistime = MIN(params_to_send,useable_space);
908 data_sent_thistime = useable_space - params_sent_thistime;
909 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
911 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
913 /* smb_proff is the offset from the start of the SMB header to the
914 parameter bytes, however the first 4 bytes of outbuf are
915 the Netbios over TCP header. Thus use smb_base() to subtract
916 them from the calculation */
918 SSVAL(req->outbuf,smb_proff,
919 ((smb_buf(req->outbuf)+alignment_offset)
920 - smb_base(req->outbuf)));
922 if(params_sent_thistime == 0)
923 SSVAL(req->outbuf,smb_prdisp,0);
924 else
925 /* Absolute displacement of param bytes sent in this packet */
926 SSVAL(req->outbuf,smb_prdisp,pp - params);
928 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
929 if(data_sent_thistime == 0) {
930 SSVAL(req->outbuf,smb_droff,0);
931 SSVAL(req->outbuf,smb_drdisp, 0);
932 } else {
933 /* The offset of the data bytes is the offset of the
934 parameter bytes plus the number of parameters being sent this time */
935 SSVAL(req->outbuf, smb_droff,
936 ((smb_buf(req->outbuf)+alignment_offset)
937 - smb_base(req->outbuf))
938 + params_sent_thistime + data_alignment_offset);
939 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
942 /* Initialize the padding for alignment */
944 if (alignment_offset != 0) {
945 memset(smb_buf(req->outbuf), 0, alignment_offset);
948 /* Copy the param bytes into the packet */
950 if(params_sent_thistime) {
951 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
952 params_sent_thistime);
955 /* Copy in the data bytes */
956 if(data_sent_thistime) {
957 if (data_alignment_offset != 0) {
958 memset((smb_buf(req->outbuf)+alignment_offset+
959 params_sent_thistime), 0,
960 data_alignment_offset);
962 memcpy(smb_buf(req->outbuf)+alignment_offset
963 +params_sent_thistime+data_alignment_offset,
964 pd,data_sent_thistime);
967 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
968 params_sent_thistime, data_sent_thistime, useable_space));
969 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
970 params_to_send, data_to_send, paramsize, datasize));
972 if (overflow) {
973 error_packet_set((char *)req->outbuf,
974 ERRDOS,ERRbufferoverflow,
975 STATUS_BUFFER_OVERFLOW,
976 __LINE__,__FILE__);
979 /* Send the packet */
980 show_msg((char *)req->outbuf);
981 if (!srv_send_smb(sconn,
982 (char *)req->outbuf,
983 true, req->seqnum+1,
984 IS_CONN_ENCRYPTED(conn),
985 &req->pcd))
986 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
988 TALLOC_FREE(req->outbuf);
990 pp += params_sent_thistime;
991 pd += data_sent_thistime;
993 params_to_send -= params_sent_thistime;
994 data_to_send -= data_sent_thistime;
996 /* Sanity check */
997 if(params_to_send < 0 || data_to_send < 0) {
998 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
999 params_to_send, data_to_send));
1000 return;
1004 return;
1007 /****************************************************************************
1008 Reply to a TRANSACT2_OPEN.
1009 ****************************************************************************/
1011 static void call_trans2open(connection_struct *conn,
1012 struct smb_request *req,
1013 char **pparams, int total_params,
1014 char **ppdata, int total_data,
1015 unsigned int max_data_bytes)
1017 struct smb_filename *smb_fname = NULL;
1018 char *params = *pparams;
1019 char *pdata = *ppdata;
1020 int deny_mode;
1021 int32 open_attr;
1022 bool oplock_request;
1023 #if 0
1024 bool return_additional_info;
1025 int16 open_sattr;
1026 time_t open_time;
1027 #endif
1028 int open_ofun;
1029 uint32 open_size;
1030 char *pname;
1031 char *fname = NULL;
1032 off_t size=0;
1033 int fattr=0,mtime=0;
1034 SMB_INO_T inode = 0;
1035 int smb_action = 0;
1036 files_struct *fsp;
1037 struct ea_list *ea_list = NULL;
1038 uint16 flags = 0;
1039 NTSTATUS status;
1040 uint32 access_mask;
1041 uint32 share_mode;
1042 uint32 create_disposition;
1043 uint32 create_options = 0;
1044 uint32_t private_flags = 0;
1045 TALLOC_CTX *ctx = talloc_tos();
1048 * Ensure we have enough parameters to perform the operation.
1051 if (total_params < 29) {
1052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1053 goto out;
1056 flags = SVAL(params, 0);
1057 deny_mode = SVAL(params, 2);
1058 open_attr = SVAL(params,6);
1059 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1060 if (oplock_request) {
1061 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1064 #if 0
1065 return_additional_info = BITSETW(params,0);
1066 open_sattr = SVAL(params, 4);
1067 open_time = make_unix_date3(params+8);
1068 #endif
1069 open_ofun = SVAL(params,12);
1070 open_size = IVAL(params,14);
1071 pname = &params[28];
1073 if (IS_IPC(conn)) {
1074 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1075 goto out;
1078 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1079 total_params - 28, STR_TERMINATE,
1080 &status);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 reply_nterror(req, status);
1083 goto out;
1086 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1087 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1088 (unsigned int)open_ofun, open_size));
1090 status = filename_convert(ctx,
1091 conn,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1093 fname,
1095 NULL,
1096 &smb_fname);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req,
1100 NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1102 goto out;
1104 reply_nterror(req, status);
1105 goto out;
1108 if (open_ofun == 0) {
1109 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1110 goto out;
1113 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1114 open_ofun,
1115 &access_mask, &share_mode,
1116 &create_disposition,
1117 &create_options,
1118 &private_flags)) {
1119 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1120 goto out;
1123 /* Any data in this call is an EA list. */
1124 if (total_data && (total_data != 4)) {
1125 if (total_data < 10) {
1126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1127 goto out;
1130 if (IVAL(pdata,0) > total_data) {
1131 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1132 IVAL(pdata,0), (unsigned int)total_data));
1133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1134 goto out;
1137 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1138 total_data - 4);
1139 if (!ea_list) {
1140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1141 goto out;
1144 if (!lp_ea_support(SNUM(conn))) {
1145 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1146 goto out;
1150 status = SMB_VFS_CREATE_FILE(
1151 conn, /* conn */
1152 req, /* req */
1153 0, /* root_dir_fid */
1154 smb_fname, /* fname */
1155 access_mask, /* access_mask */
1156 share_mode, /* share_access */
1157 create_disposition, /* create_disposition*/
1158 create_options, /* create_options */
1159 open_attr, /* file_attributes */
1160 oplock_request, /* oplock_request */
1161 open_size, /* allocation_size */
1162 private_flags,
1163 NULL, /* sd */
1164 ea_list, /* ea_list */
1165 &fsp, /* result */
1166 &smb_action); /* psbuf */
1168 if (!NT_STATUS_IS_OK(status)) {
1169 if (open_was_deferred(req->sconn, req->mid)) {
1170 /* We have re-scheduled this call. */
1171 goto out;
1173 reply_openerror(req, status);
1174 goto out;
1177 size = get_file_size_stat(&smb_fname->st);
1178 fattr = dos_mode(conn, smb_fname);
1179 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1180 inode = smb_fname->st.st_ex_ino;
1181 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1182 close_file(req, fsp, ERROR_CLOSE);
1183 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1184 goto out;
1187 /* Realloc the size of parameters and data we will return */
1188 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1189 if(*pparams == NULL ) {
1190 reply_nterror(req, NT_STATUS_NO_MEMORY);
1191 goto out;
1193 params = *pparams;
1195 SSVAL(params,0,fsp->fnum);
1196 SSVAL(params,2,fattr);
1197 srv_put_dos_date2(params,4, mtime);
1198 SIVAL(params,8, (uint32)size);
1199 SSVAL(params,12,deny_mode);
1200 SSVAL(params,14,0); /* open_type - file or directory. */
1201 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1203 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1204 smb_action |= EXTENDED_OPLOCK_GRANTED;
1207 SSVAL(params,18,smb_action);
1210 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1212 SIVAL(params,20,inode);
1213 SSVAL(params,24,0); /* Padding. */
1214 if (flags & 8) {
1215 uint32 ea_size = estimate_ea_size(conn, fsp,
1216 fsp->fsp_name->base_name);
1217 SIVAL(params, 26, ea_size);
1218 } else {
1219 SIVAL(params, 26, 0);
1222 /* Send the required number of replies */
1223 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1224 out:
1225 TALLOC_FREE(smb_fname);
1228 /*********************************************************
1229 Routine to check if a given string matches exactly.
1230 as a special case a mask of "." does NOT match. That
1231 is required for correct wildcard semantics
1232 Case can be significant or not.
1233 **********************************************************/
1235 static bool exact_match(bool has_wild,
1236 bool case_sensitive,
1237 const char *str,
1238 const char *mask)
1240 if (mask[0] == '.' && mask[1] == 0) {
1241 return false;
1244 if (has_wild) {
1245 return false;
1248 if (case_sensitive) {
1249 return strcmp(str,mask)==0;
1250 } else {
1251 return strcasecmp_m(str,mask) == 0;
1255 /****************************************************************************
1256 Return the filetype for UNIX extensions.
1257 ****************************************************************************/
1259 static uint32 unix_filetype(mode_t mode)
1261 if(S_ISREG(mode))
1262 return UNIX_TYPE_FILE;
1263 else if(S_ISDIR(mode))
1264 return UNIX_TYPE_DIR;
1265 #ifdef S_ISLNK
1266 else if(S_ISLNK(mode))
1267 return UNIX_TYPE_SYMLINK;
1268 #endif
1269 #ifdef S_ISCHR
1270 else if(S_ISCHR(mode))
1271 return UNIX_TYPE_CHARDEV;
1272 #endif
1273 #ifdef S_ISBLK
1274 else if(S_ISBLK(mode))
1275 return UNIX_TYPE_BLKDEV;
1276 #endif
1277 #ifdef S_ISFIFO
1278 else if(S_ISFIFO(mode))
1279 return UNIX_TYPE_FIFO;
1280 #endif
1281 #ifdef S_ISSOCK
1282 else if(S_ISSOCK(mode))
1283 return UNIX_TYPE_SOCKET;
1284 #endif
1286 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1287 return UNIX_TYPE_UNKNOWN;
1290 /****************************************************************************
1291 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1292 ****************************************************************************/
1294 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1296 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1297 const SMB_STRUCT_STAT *psbuf,
1298 uint32 perms,
1299 enum perm_type ptype,
1300 mode_t *ret_perms)
1302 mode_t ret = 0;
1304 if (perms == SMB_MODE_NO_CHANGE) {
1305 if (!VALID_STAT(*psbuf)) {
1306 return NT_STATUS_INVALID_PARAMETER;
1307 } else {
1308 *ret_perms = psbuf->st_ex_mode;
1309 return NT_STATUS_OK;
1313 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1314 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1315 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1316 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1317 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1318 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1319 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1320 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1321 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1322 #ifdef S_ISVTX
1323 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1324 #endif
1325 #ifdef S_ISGID
1326 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1327 #endif
1328 #ifdef S_ISUID
1329 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1330 #endif
1332 switch (ptype) {
1333 case PERM_NEW_FILE:
1334 /* Apply mode mask */
1335 ret &= lp_create_mask(SNUM(conn));
1336 /* Add in force bits */
1337 ret |= lp_force_create_mode(SNUM(conn));
1338 break;
1339 case PERM_NEW_DIR:
1340 ret &= lp_dir_mask(SNUM(conn));
1341 /* Add in force bits */
1342 ret |= lp_force_dir_mode(SNUM(conn));
1343 break;
1344 case PERM_EXISTING_FILE:
1345 /* Apply mode mask */
1346 ret &= lp_security_mask(SNUM(conn));
1347 /* Add in force bits */
1348 ret |= lp_force_security_mode(SNUM(conn));
1349 break;
1350 case PERM_EXISTING_DIR:
1351 /* Apply mode mask */
1352 ret &= lp_dir_security_mask(SNUM(conn));
1353 /* Add in force bits */
1354 ret |= lp_force_dir_security_mode(SNUM(conn));
1355 break;
1358 *ret_perms = ret;
1359 return NT_STATUS_OK;
1362 /****************************************************************************
1363 Needed to show the msdfs symlinks as directories. Modifies psbuf
1364 to be a directory if it's a msdfs link.
1365 ****************************************************************************/
1367 static bool check_msdfs_link(connection_struct *conn,
1368 const char *pathname,
1369 SMB_STRUCT_STAT *psbuf)
1371 int saved_errno = errno;
1372 if(lp_host_msdfs() &&
1373 lp_msdfs_root(SNUM(conn)) &&
1374 is_msdfs_link(conn, pathname, psbuf)) {
1376 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1377 "as a directory\n",
1378 pathname));
1379 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1380 errno = saved_errno;
1381 return true;
1383 errno = saved_errno;
1384 return false;
1388 /****************************************************************************
1389 Get a level dependent lanman2 dir entry.
1390 ****************************************************************************/
1392 struct smbd_dirptr_lanman2_state {
1393 connection_struct *conn;
1394 uint32_t info_level;
1395 bool check_mangled_names;
1396 bool has_wild;
1397 bool got_exact_match;
1400 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1401 void *private_data,
1402 const char *dname,
1403 const char *mask,
1404 char **_fname)
1406 struct smbd_dirptr_lanman2_state *state =
1407 (struct smbd_dirptr_lanman2_state *)private_data;
1408 bool ok;
1409 char mangled_name[13]; /* mangled 8.3 name. */
1410 bool got_match;
1411 const char *fname;
1413 /* Mangle fname if it's an illegal name. */
1414 if (mangle_must_mangle(dname, state->conn->params)) {
1415 ok = name_to_8_3(dname, mangled_name,
1416 true, state->conn->params);
1417 if (!ok) {
1418 return false;
1420 fname = mangled_name;
1421 } else {
1422 fname = dname;
1425 got_match = exact_match(state->has_wild,
1426 state->conn->case_sensitive,
1427 fname, mask);
1428 state->got_exact_match = got_match;
1429 if (!got_match) {
1430 got_match = mask_match(fname, mask,
1431 state->conn->case_sensitive);
1434 if(!got_match && state->check_mangled_names &&
1435 !mangle_is_8_3(fname, false, state->conn->params)) {
1437 * It turns out that NT matches wildcards against
1438 * both long *and* short names. This may explain some
1439 * of the wildcard wierdness from old DOS clients
1440 * that some people have been seeing.... JRA.
1442 /* Force the mangling into 8.3. */
1443 ok = name_to_8_3(fname, mangled_name,
1444 false, state->conn->params);
1445 if (!ok) {
1446 return false;
1449 got_match = exact_match(state->has_wild,
1450 state->conn->case_sensitive,
1451 mangled_name, mask);
1452 state->got_exact_match = got_match;
1453 if (!got_match) {
1454 got_match = mask_match(mangled_name, mask,
1455 state->conn->case_sensitive);
1459 if (!got_match) {
1460 return false;
1463 *_fname = talloc_strdup(ctx, fname);
1464 if (*_fname == NULL) {
1465 return false;
1468 return true;
1471 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1472 void *private_data,
1473 struct smb_filename *smb_fname,
1474 uint32_t *_mode)
1476 struct smbd_dirptr_lanman2_state *state =
1477 (struct smbd_dirptr_lanman2_state *)private_data;
1478 bool ms_dfs_link = false;
1479 uint32_t mode = 0;
1481 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1482 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1483 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1484 "Couldn't lstat [%s] (%s)\n",
1485 smb_fname_str_dbg(smb_fname),
1486 strerror(errno)));
1487 return false;
1489 } else if (!VALID_STAT(smb_fname->st) &&
1490 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1491 /* Needed to show the msdfs symlinks as
1492 * directories */
1494 ms_dfs_link = check_msdfs_link(state->conn,
1495 smb_fname->base_name,
1496 &smb_fname->st);
1497 if (!ms_dfs_link) {
1498 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1499 "Couldn't stat [%s] (%s)\n",
1500 smb_fname_str_dbg(smb_fname),
1501 strerror(errno)));
1502 return false;
1506 if (ms_dfs_link) {
1507 mode = dos_mode_msdfs(state->conn, smb_fname);
1508 } else {
1509 mode = dos_mode(state->conn, smb_fname);
1512 *_mode = mode;
1513 return true;
1516 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1517 connection_struct *conn,
1518 uint16_t flags2,
1519 uint32_t info_level,
1520 struct ea_list *name_list,
1521 bool check_mangled_names,
1522 bool requires_resume_key,
1523 uint32_t mode,
1524 const char *fname,
1525 const struct smb_filename *smb_fname,
1526 int space_remaining,
1527 uint8_t align,
1528 bool do_pad,
1529 char *base_data,
1530 char **ppdata,
1531 char *end_data,
1532 bool *out_of_space,
1533 uint64_t *last_entry_off)
1535 char *p, *q, *pdata = *ppdata;
1536 uint32_t reskey=0;
1537 uint64_t file_size = 0;
1538 uint64_t allocation_size = 0;
1539 uint64_t file_index = 0;
1540 uint32_t len;
1541 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1542 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1543 char *nameptr;
1544 char *last_entry_ptr;
1545 bool was_8_3;
1546 int off;
1547 int pad = 0;
1549 *out_of_space = false;
1551 ZERO_STRUCT(mdate_ts);
1552 ZERO_STRUCT(adate_ts);
1553 ZERO_STRUCT(create_date_ts);
1554 ZERO_STRUCT(cdate_ts);
1556 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1557 file_size = get_file_size_stat(&smb_fname->st);
1559 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1561 file_index = get_FileIndex(conn, &smb_fname->st);
1563 mdate_ts = smb_fname->st.st_ex_mtime;
1564 adate_ts = smb_fname->st.st_ex_atime;
1565 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1566 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1568 if (lp_dos_filetime_resolution(SNUM(conn))) {
1569 dos_filetime_timespec(&create_date_ts);
1570 dos_filetime_timespec(&mdate_ts);
1571 dos_filetime_timespec(&adate_ts);
1572 dos_filetime_timespec(&cdate_ts);
1575 create_date = convert_timespec_to_time_t(create_date_ts);
1576 mdate = convert_timespec_to_time_t(mdate_ts);
1577 adate = convert_timespec_to_time_t(adate_ts);
1579 /* align the record */
1580 SMB_ASSERT(align >= 1);
1582 off = (int)PTR_DIFF(pdata, base_data);
1583 pad = (off + (align-1)) & ~(align-1);
1584 pad -= off;
1586 if (pad && pad > space_remaining) {
1587 *out_of_space = true;
1588 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1589 "for padding (wanted %u, had %d)\n",
1590 (unsigned int)pad,
1591 space_remaining ));
1592 return false; /* Not finished - just out of space */
1595 off += pad;
1596 /* initialize padding to 0 */
1597 if (pad) {
1598 memset(pdata, 0, pad);
1600 space_remaining -= pad;
1602 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1603 space_remaining ));
1605 pdata += pad;
1606 p = pdata;
1607 last_entry_ptr = p;
1609 pad = 0;
1610 off = 0;
1612 switch (info_level) {
1613 case SMB_FIND_INFO_STANDARD:
1614 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1615 if(requires_resume_key) {
1616 SIVAL(p,0,reskey);
1617 p += 4;
1619 srv_put_dos_date2(p,0,create_date);
1620 srv_put_dos_date2(p,4,adate);
1621 srv_put_dos_date2(p,8,mdate);
1622 SIVAL(p,12,(uint32)file_size);
1623 SIVAL(p,16,(uint32)allocation_size);
1624 SSVAL(p,20,mode);
1625 p += 23;
1626 nameptr = p;
1627 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1628 p += ucs2_align(base_data, p, 0);
1630 len = srvstr_push(base_data, flags2, p,
1631 fname, PTR_DIFF(end_data, p),
1632 STR_TERMINATE);
1633 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1634 if (len > 2) {
1635 SCVAL(nameptr, -1, len - 2);
1636 } else {
1637 SCVAL(nameptr, -1, 0);
1639 } else {
1640 if (len > 1) {
1641 SCVAL(nameptr, -1, len - 1);
1642 } else {
1643 SCVAL(nameptr, -1, 0);
1646 p += len;
1647 break;
1649 case SMB_FIND_EA_SIZE:
1650 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1651 if (requires_resume_key) {
1652 SIVAL(p,0,reskey);
1653 p += 4;
1655 srv_put_dos_date2(p,0,create_date);
1656 srv_put_dos_date2(p,4,adate);
1657 srv_put_dos_date2(p,8,mdate);
1658 SIVAL(p,12,(uint32)file_size);
1659 SIVAL(p,16,(uint32)allocation_size);
1660 SSVAL(p,20,mode);
1662 unsigned int ea_size = estimate_ea_size(conn, NULL,
1663 smb_fname->base_name);
1664 SIVAL(p,22,ea_size); /* Extended attributes */
1666 p += 27;
1667 nameptr = p - 1;
1668 len = srvstr_push(base_data, flags2,
1669 p, fname, PTR_DIFF(end_data, p),
1670 STR_TERMINATE | STR_NOALIGN);
1671 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1672 if (len > 2) {
1673 len -= 2;
1674 } else {
1675 len = 0;
1677 } else {
1678 if (len > 1) {
1679 len -= 1;
1680 } else {
1681 len = 0;
1684 SCVAL(nameptr,0,len);
1685 p += len;
1686 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1687 break;
1689 case SMB_FIND_EA_LIST:
1691 struct ea_list *file_list = NULL;
1692 size_t ea_len = 0;
1694 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1695 if (!name_list) {
1696 return false;
1698 if (requires_resume_key) {
1699 SIVAL(p,0,reskey);
1700 p += 4;
1702 srv_put_dos_date2(p,0,create_date);
1703 srv_put_dos_date2(p,4,adate);
1704 srv_put_dos_date2(p,8,mdate);
1705 SIVAL(p,12,(uint32)file_size);
1706 SIVAL(p,16,(uint32)allocation_size);
1707 SSVAL(p,20,mode);
1708 p += 22; /* p now points to the EA area. */
1710 file_list = get_ea_list_from_file(ctx, conn, NULL,
1711 smb_fname->base_name,
1712 &ea_len);
1713 name_list = ea_list_union(name_list, file_list, &ea_len);
1715 /* We need to determine if this entry will fit in the space available. */
1716 /* Max string size is 255 bytes. */
1717 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1718 *out_of_space = true;
1719 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1720 "(wanted %u, had %d)\n",
1721 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1722 space_remaining ));
1723 return False; /* Not finished - just out of space */
1726 /* Push the ea_data followed by the name. */
1727 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1728 nameptr = p;
1729 len = srvstr_push(base_data, flags2,
1730 p + 1, fname, PTR_DIFF(end_data, p+1),
1731 STR_TERMINATE | STR_NOALIGN);
1732 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1733 if (len > 2) {
1734 len -= 2;
1735 } else {
1736 len = 0;
1738 } else {
1739 if (len > 1) {
1740 len -= 1;
1741 } else {
1742 len = 0;
1745 SCVAL(nameptr,0,len);
1746 p += len + 1;
1747 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1748 break;
1751 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1753 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1754 p += 4;
1755 SIVAL(p,0,reskey); p += 4;
1756 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1760 SOFF_T(p,0,file_size); p += 8;
1761 SOFF_T(p,0,allocation_size); p += 8;
1762 SIVAL(p,0,mode); p += 4;
1763 q = p; p += 4; /* q is placeholder for name length. */
1765 unsigned int ea_size = estimate_ea_size(conn, NULL,
1766 smb_fname->base_name);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p += 4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 char mangled_name[13]; /* mangled 8.3 name. */
1776 if (!name_to_8_3(fname,mangled_name,True,
1777 conn->params)) {
1778 /* Error - mangle failed ! */
1779 memset(mangled_name,'\0',12);
1781 mangled_name[12] = 0;
1782 len = srvstr_push(base_data, flags2,
1783 p+2, mangled_name, 24,
1784 STR_UPPER|STR_UNICODE);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 2 + 24;
1793 len = srvstr_push(base_data, flags2, p,
1794 fname, PTR_DIFF(end_data, p),
1795 STR_TERMINATE_ASCII);
1796 SIVAL(q,0,len);
1797 p += len;
1799 len = PTR_DIFF(p, pdata);
1800 pad = (len + (align-1)) & ~(align-1);
1802 * offset to the next entry, the caller
1803 * will overwrite it for the last entry
1804 * that's why we always include the padding
1806 SIVAL(pdata,0,pad);
1808 * set padding to zero
1810 if (do_pad) {
1811 memset(p, 0, pad - len);
1812 p = pdata + pad;
1813 } else {
1814 p = pdata + len;
1816 break;
1818 case SMB_FIND_FILE_DIRECTORY_INFO:
1819 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1820 p += 4;
1821 SIVAL(p,0,reskey); p += 4;
1822 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1826 SOFF_T(p,0,file_size); p += 8;
1827 SOFF_T(p,0,allocation_size); p += 8;
1828 SIVAL(p,0,mode); p += 4;
1829 len = srvstr_push(base_data, flags2,
1830 p + 4, fname, PTR_DIFF(end_data, p+4),
1831 STR_TERMINATE_ASCII);
1832 SIVAL(p,0,len);
1833 p += 4 + len;
1835 len = PTR_DIFF(p, pdata);
1836 pad = (len + (align-1)) & ~(align-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1842 SIVAL(pdata,0,pad);
1844 * set padding to zero
1846 if (do_pad) {
1847 memset(p, 0, pad - len);
1848 p = pdata + pad;
1849 } else {
1850 p = pdata + len;
1852 break;
1854 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1856 p += 4;
1857 SIVAL(p,0,reskey); p += 4;
1858 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1862 SOFF_T(p,0,file_size); p += 8;
1863 SOFF_T(p,0,allocation_size); p += 8;
1864 SIVAL(p,0,mode); p += 4;
1865 q = p; p += 4; /* q is placeholder for name length. */
1867 unsigned int ea_size = estimate_ea_size(conn, NULL,
1868 smb_fname->base_name);
1869 SIVAL(p,0,ea_size); /* Extended attributes */
1870 p +=4;
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1875 SIVAL(q, 0, len);
1876 p += len;
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1885 SIVAL(pdata,0,pad);
1887 * set padding to zero
1889 if (do_pad) {
1890 memset(p, 0, pad - len);
1891 p = pdata + pad;
1892 } else {
1893 p = pdata + len;
1895 break;
1897 case SMB_FIND_FILE_NAMES_INFO:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1899 p += 4;
1900 SIVAL(p,0,reskey); p += 4;
1901 p += 4;
1902 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1903 acl on a dir (tridge) */
1904 len = srvstr_push(base_data, flags2, p,
1905 fname, PTR_DIFF(end_data, p),
1906 STR_TERMINATE_ASCII);
1907 SIVAL(p, -4, len);
1908 p += len;
1910 len = PTR_DIFF(p, pdata);
1911 pad = (len + (align-1)) & ~(align-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1917 SIVAL(pdata,0,pad);
1919 * set padding to zero
1921 if (do_pad) {
1922 memset(p, 0, pad - len);
1923 p = pdata + pad;
1924 } else {
1925 p = pdata + len;
1927 break;
1929 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1931 p += 4;
1932 SIVAL(p,0,reskey); p += 4;
1933 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1937 SOFF_T(p,0,file_size); p += 8;
1938 SOFF_T(p,0,allocation_size); p += 8;
1939 SIVAL(p,0,mode); p += 4;
1940 q = p; p += 4; /* q is placeholder for name length. */
1942 unsigned int ea_size = estimate_ea_size(conn, NULL,
1943 smb_fname->base_name);
1944 SIVAL(p,0,ea_size); /* Extended attributes */
1945 p +=4;
1947 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1948 SBVAL(p,0,file_index); p += 8;
1949 len = srvstr_push(base_data, flags2, p,
1950 fname, PTR_DIFF(end_data, p),
1951 STR_TERMINATE_ASCII);
1952 SIVAL(q, 0, len);
1953 p += len;
1955 len = PTR_DIFF(p, pdata);
1956 pad = (len + (align-1)) & ~(align-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1962 SIVAL(pdata,0,pad);
1964 * set padding to zero
1966 if (do_pad) {
1967 memset(p, 0, pad - len);
1968 p = pdata + pad;
1969 } else {
1970 p = pdata + len;
1972 break;
1974 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1976 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1977 p += 4;
1978 SIVAL(p,0,reskey); p += 4;
1979 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1982 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1983 SOFF_T(p,0,file_size); p += 8;
1984 SOFF_T(p,0,allocation_size); p += 8;
1985 SIVAL(p,0,mode); p += 4;
1986 q = p; p += 4; /* q is placeholder for name length */
1988 unsigned int ea_size = estimate_ea_size(conn, NULL,
1989 smb_fname->base_name);
1990 SIVAL(p,0,ea_size); /* Extended attributes */
1991 p +=4;
1993 /* Clear the short name buffer. This is
1994 * IMPORTANT as not doing so will trigger
1995 * a Win2k client bug. JRA.
1997 if (!was_8_3 && check_mangled_names) {
1998 char mangled_name[13]; /* mangled 8.3 name. */
1999 if (!name_to_8_3(fname,mangled_name,True,
2000 conn->params)) {
2001 /* Error - mangle failed ! */
2002 memset(mangled_name,'\0',12);
2004 mangled_name[12] = 0;
2005 len = srvstr_push(base_data, flags2,
2006 p+2, mangled_name, 24,
2007 STR_UPPER|STR_UNICODE);
2008 SSVAL(p, 0, len);
2009 if (len < 24) {
2010 memset(p + 2 + len,'\0',24 - len);
2012 SSVAL(p, 0, len);
2013 } else {
2014 memset(p,'\0',26);
2016 p += 26;
2017 SSVAL(p,0,0); p += 2; /* Reserved ? */
2018 SBVAL(p,0,file_index); p += 8;
2019 len = srvstr_push(base_data, flags2, p,
2020 fname, PTR_DIFF(end_data, p),
2021 STR_TERMINATE_ASCII);
2022 SIVAL(q,0,len);
2023 p += len;
2025 len = PTR_DIFF(p, pdata);
2026 pad = (len + (align-1)) & ~(align-1);
2028 * offset to the next entry, the caller
2029 * will overwrite it for the last entry
2030 * that's why we always include the padding
2032 SIVAL(pdata,0,pad);
2034 * set padding to zero
2036 if (do_pad) {
2037 memset(p, 0, pad - len);
2038 p = pdata + pad;
2039 } else {
2040 p = pdata + len;
2042 break;
2044 /* CIFS UNIX Extension. */
2046 case SMB_FIND_FILE_UNIX:
2047 case SMB_FIND_FILE_UNIX_INFO2:
2048 p+= 4;
2049 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2051 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2053 if (info_level == SMB_FIND_FILE_UNIX) {
2054 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2055 p = store_file_unix_basic(conn, p,
2056 NULL, &smb_fname->st);
2057 len = srvstr_push(base_data, flags2, p,
2058 fname, PTR_DIFF(end_data, p),
2059 STR_TERMINATE);
2060 } else {
2061 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2062 p = store_file_unix_basic_info2(conn, p,
2063 NULL, &smb_fname->st);
2064 nameptr = p;
2065 p += 4;
2066 len = srvstr_push(base_data, flags2, p, fname,
2067 PTR_DIFF(end_data, p), 0);
2068 SIVAL(nameptr, 0, len);
2071 p += len;
2073 len = PTR_DIFF(p, pdata);
2074 pad = (len + (align-1)) & ~(align-1);
2076 * offset to the next entry, the caller
2077 * will overwrite it for the last entry
2078 * that's why we always include the padding
2080 SIVAL(pdata,0,pad);
2082 * set padding to zero
2084 if (do_pad) {
2085 memset(p, 0, pad - len);
2086 p = pdata + pad;
2087 } else {
2088 p = pdata + len;
2090 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2092 break;
2094 default:
2095 return false;
2098 if (PTR_DIFF(p,pdata) > space_remaining) {
2099 *out_of_space = true;
2100 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2101 "(wanted %u, had %d)\n",
2102 (unsigned int)PTR_DIFF(p,pdata),
2103 space_remaining ));
2104 return false; /* Not finished - just out of space */
2107 /* Setup the last entry pointer, as an offset from base_data */
2108 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2109 /* Advance the data pointer to the next slot */
2110 *ppdata = p;
2112 return true;
2115 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2116 connection_struct *conn,
2117 struct dptr_struct *dirptr,
2118 uint16 flags2,
2119 const char *path_mask,
2120 uint32 dirtype,
2121 int info_level,
2122 int requires_resume_key,
2123 bool dont_descend,
2124 bool ask_sharemode,
2125 uint8_t align,
2126 bool do_pad,
2127 char **ppdata,
2128 char *base_data,
2129 char *end_data,
2130 int space_remaining,
2131 bool *out_of_space,
2132 bool *got_exact_match,
2133 int *_last_entry_off,
2134 struct ea_list *name_list)
2136 const char *p;
2137 const char *mask = NULL;
2138 long prev_dirpos = 0;
2139 uint32_t mode = 0;
2140 char *fname = NULL;
2141 struct smb_filename *smb_fname = NULL;
2142 struct smbd_dirptr_lanman2_state state;
2143 bool ok;
2144 uint64_t last_entry_off = 0;
2146 ZERO_STRUCT(state);
2147 state.conn = conn;
2148 state.info_level = info_level;
2149 state.check_mangled_names = lp_manglednames(conn->params);
2150 state.has_wild = dptr_has_wild(dirptr);
2151 state.got_exact_match = false;
2153 *out_of_space = false;
2154 *got_exact_match = false;
2156 p = strrchr_m(path_mask,'/');
2157 if(p != NULL) {
2158 if(p[1] == '\0') {
2159 mask = "*.*";
2160 } else {
2161 mask = p+1;
2163 } else {
2164 mask = path_mask;
2167 ok = smbd_dirptr_get_entry(ctx,
2168 dirptr,
2169 mask,
2170 dirtype,
2171 dont_descend,
2172 ask_sharemode,
2173 smbd_dirptr_lanman2_match_fn,
2174 smbd_dirptr_lanman2_mode_fn,
2175 &state,
2176 &fname,
2177 &smb_fname,
2178 &mode,
2179 &prev_dirpos);
2180 if (!ok) {
2181 return false;
2184 *got_exact_match = state.got_exact_match;
2186 ok = smbd_marshall_dir_entry(ctx,
2187 conn,
2188 flags2,
2189 info_level,
2190 name_list,
2191 state.check_mangled_names,
2192 requires_resume_key,
2193 mode,
2194 fname,
2195 smb_fname,
2196 space_remaining,
2197 align,
2198 do_pad,
2199 base_data,
2200 ppdata,
2201 end_data,
2202 out_of_space,
2203 &last_entry_off);
2204 TALLOC_FREE(fname);
2205 TALLOC_FREE(smb_fname);
2206 if (*out_of_space) {
2207 dptr_SeekDir(dirptr, prev_dirpos);
2208 return false;
2210 if (!ok) {
2211 return false;
2214 *_last_entry_off = last_entry_off;
2215 return true;
2218 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2219 connection_struct *conn,
2220 struct dptr_struct *dirptr,
2221 uint16 flags2,
2222 const char *path_mask,
2223 uint32 dirtype,
2224 int info_level,
2225 bool requires_resume_key,
2226 bool dont_descend,
2227 bool ask_sharemode,
2228 char **ppdata,
2229 char *base_data,
2230 char *end_data,
2231 int space_remaining,
2232 bool *out_of_space,
2233 bool *got_exact_match,
2234 int *last_entry_off,
2235 struct ea_list *name_list)
2237 uint8_t align = 4;
2238 const bool do_pad = true;
2240 if (info_level >= 1 && info_level <= 3) {
2241 /* No alignment on earlier info levels. */
2242 align = 1;
2245 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2246 path_mask, dirtype, info_level,
2247 requires_resume_key, dont_descend, ask_sharemode,
2248 align, do_pad,
2249 ppdata, base_data, end_data,
2250 space_remaining,
2251 out_of_space, got_exact_match,
2252 last_entry_off, name_list);
2255 /****************************************************************************
2256 Reply to a TRANS2_FINDFIRST.
2257 ****************************************************************************/
2259 static void call_trans2findfirst(connection_struct *conn,
2260 struct smb_request *req,
2261 char **pparams, int total_params,
2262 char **ppdata, int total_data,
2263 unsigned int max_data_bytes)
2265 /* We must be careful here that we don't return more than the
2266 allowed number of data bytes. If this means returning fewer than
2267 maxentries then so be it. We assume that the redirector has
2268 enough room for the fixed number of parameter bytes it has
2269 requested. */
2270 struct smb_filename *smb_dname = NULL;
2271 char *params = *pparams;
2272 char *pdata = *ppdata;
2273 char *data_end;
2274 uint32 dirtype;
2275 int maxentries;
2276 uint16 findfirst_flags;
2277 bool close_after_first;
2278 bool close_if_end;
2279 bool requires_resume_key;
2280 int info_level;
2281 char *directory = NULL;
2282 char *mask = NULL;
2283 char *p;
2284 int last_entry_off=0;
2285 int dptr_num = -1;
2286 int numentries = 0;
2287 int i;
2288 bool finished = False;
2289 bool dont_descend = False;
2290 bool out_of_space = False;
2291 int space_remaining;
2292 bool mask_contains_wcard = False;
2293 struct ea_list *ea_list = NULL;
2294 NTSTATUS ntstatus = NT_STATUS_OK;
2295 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2296 TALLOC_CTX *ctx = talloc_tos();
2297 struct dptr_struct *dirptr = NULL;
2298 struct smbd_server_connection *sconn = req->sconn;
2299 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2300 bool backup_priv = false;
2302 if (total_params < 13) {
2303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2304 goto out;
2307 dirtype = SVAL(params,0);
2308 maxentries = SVAL(params,2);
2309 findfirst_flags = SVAL(params,4);
2310 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2311 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2312 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2313 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2314 security_token_has_privilege(get_current_nttok(conn),
2315 SEC_PRIV_BACKUP));
2317 info_level = SVAL(params,6);
2319 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2320 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2321 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2322 (int)backup_priv,
2323 info_level, max_data_bytes));
2325 if (!maxentries) {
2326 /* W2K3 seems to treat zero as 1. */
2327 maxentries = 1;
2330 switch (info_level) {
2331 case SMB_FIND_INFO_STANDARD:
2332 case SMB_FIND_EA_SIZE:
2333 case SMB_FIND_EA_LIST:
2334 case SMB_FIND_FILE_DIRECTORY_INFO:
2335 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2336 case SMB_FIND_FILE_NAMES_INFO:
2337 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2338 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2339 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2340 break;
2341 case SMB_FIND_FILE_UNIX:
2342 case SMB_FIND_FILE_UNIX_INFO2:
2343 /* Always use filesystem for UNIX mtime query. */
2344 ask_sharemode = false;
2345 if (!lp_unix_extensions()) {
2346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2347 goto out;
2349 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2350 break;
2351 default:
2352 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2353 goto out;
2356 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2357 params+12, total_params - 12,
2358 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2359 if (!NT_STATUS_IS_OK(ntstatus)) {
2360 reply_nterror(req, ntstatus);
2361 goto out;
2364 if (backup_priv) {
2365 become_root();
2366 ntstatus = filename_convert_with_privilege(ctx,
2367 conn,
2368 req,
2369 directory,
2370 ucf_flags,
2371 &mask_contains_wcard,
2372 &smb_dname);
2373 } else {
2374 ntstatus = filename_convert(ctx, conn,
2375 req->flags2 & FLAGS2_DFS_PATHNAMES,
2376 directory,
2377 ucf_flags,
2378 &mask_contains_wcard,
2379 &smb_dname);
2382 if (!NT_STATUS_IS_OK(ntstatus)) {
2383 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2384 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2385 ERRSRV, ERRbadpath);
2386 goto out;
2388 reply_nterror(req, ntstatus);
2389 goto out;
2392 mask = smb_dname->original_lcomp;
2394 directory = smb_dname->base_name;
2396 p = strrchr_m(directory,'/');
2397 if(p == NULL) {
2398 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2399 if((directory[0] == '.') && (directory[1] == '\0')) {
2400 mask = talloc_strdup(ctx,"*");
2401 if (!mask) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2403 goto out;
2405 mask_contains_wcard = True;
2407 } else {
2408 *p = 0;
2411 if (p == NULL || p == directory) {
2412 /* Ensure we don't have a directory name of "". */
2413 directory = talloc_strdup(talloc_tos(), ".");
2414 if (!directory) {
2415 reply_nterror(req, NT_STATUS_NO_MEMORY);
2416 goto out;
2420 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2422 if (info_level == SMB_FIND_EA_LIST) {
2423 uint32 ea_size;
2425 if (total_data < 4) {
2426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2427 goto out;
2430 ea_size = IVAL(pdata,0);
2431 if (ea_size != total_data) {
2432 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2433 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2435 goto out;
2438 if (!lp_ea_support(SNUM(conn))) {
2439 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2440 goto out;
2443 /* Pull out the list of names. */
2444 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2445 if (!ea_list) {
2446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2447 goto out;
2451 *ppdata = (char *)SMB_REALLOC(
2452 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2453 if(*ppdata == NULL ) {
2454 reply_nterror(req, NT_STATUS_NO_MEMORY);
2455 goto out;
2457 pdata = *ppdata;
2458 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2460 /* Realloc the params space */
2461 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2462 if (*pparams == NULL) {
2463 reply_nterror(req, NT_STATUS_NO_MEMORY);
2464 goto out;
2466 params = *pparams;
2468 /* Save the wildcard match and attribs we are using on this directory -
2469 needed as lanman2 assumes these are being saved between calls */
2471 ntstatus = dptr_create(conn,
2472 req,
2473 NULL, /* fsp */
2474 directory,
2475 False,
2476 True,
2477 req->smbpid,
2478 mask,
2479 mask_contains_wcard,
2480 dirtype,
2481 &dirptr);
2483 if (!NT_STATUS_IS_OK(ntstatus)) {
2484 reply_nterror(req, ntstatus);
2485 goto out;
2488 if (backup_priv) {
2489 /* Remember this in case we have
2490 to do a findnext. */
2491 dptr_set_priv(dirptr);
2494 dptr_num = dptr_dnum(dirptr);
2495 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2497 /* Initialize per TRANS2_FIND_FIRST operation data */
2498 dptr_init_search_op(dirptr);
2500 /* We don't need to check for VOL here as this is returned by
2501 a different TRANS2 call. */
2503 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2504 directory,lp_dontdescend(SNUM(conn))));
2505 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2506 dont_descend = True;
2508 p = pdata;
2509 space_remaining = max_data_bytes;
2510 out_of_space = False;
2512 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2513 bool got_exact_match = False;
2515 /* this is a heuristic to avoid seeking the dirptr except when
2516 absolutely necessary. It allows for a filename of about 40 chars */
2517 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2518 out_of_space = True;
2519 finished = False;
2520 } else {
2521 finished = !get_lanman2_dir_entry(ctx,
2522 conn,
2523 dirptr,
2524 req->flags2,
2525 mask,dirtype,info_level,
2526 requires_resume_key,dont_descend,
2527 ask_sharemode,
2528 &p,pdata,data_end,
2529 space_remaining, &out_of_space,
2530 &got_exact_match,
2531 &last_entry_off, ea_list);
2534 if (finished && out_of_space)
2535 finished = False;
2537 if (!finished && !out_of_space)
2538 numentries++;
2541 * As an optimisation if we know we aren't looking
2542 * for a wildcard name (ie. the name matches the wildcard exactly)
2543 * then we can finish on any (first) match.
2544 * This speeds up large directory searches. JRA.
2547 if(got_exact_match)
2548 finished = True;
2550 /* Ensure space_remaining never goes -ve. */
2551 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2552 space_remaining = 0;
2553 out_of_space = true;
2554 } else {
2555 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2559 /* Check if we can close the dirptr */
2560 if(close_after_first || (finished && close_if_end)) {
2561 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2562 dptr_close(sconn, &dptr_num);
2566 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2567 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2568 * the protocol level is less than NT1. Tested with smbclient. JRA.
2569 * This should fix the OS/2 client bug #2335.
2572 if(numentries == 0) {
2573 dptr_close(sconn, &dptr_num);
2574 if (get_Protocol() < PROTOCOL_NT1) {
2575 reply_force_doserror(req, ERRDOS, ERRnofiles);
2576 goto out;
2577 } else {
2578 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2579 ERRDOS, ERRbadfile);
2580 goto out;
2584 /* At this point pdata points to numentries directory entries. */
2586 /* Set up the return parameter block */
2587 SSVAL(params,0,dptr_num);
2588 SSVAL(params,2,numentries);
2589 SSVAL(params,4,finished);
2590 SSVAL(params,6,0); /* Never an EA error */
2591 SSVAL(params,8,last_entry_off);
2593 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2594 max_data_bytes);
2596 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2597 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2598 if (!directory) {
2599 reply_nterror(req, NT_STATUS_NO_MEMORY);
2603 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2604 smb_fn_name(req->cmd),
2605 mask, directory, dirtype, numentries ) );
2608 * Force a name mangle here to ensure that the
2609 * mask as an 8.3 name is top of the mangled cache.
2610 * The reasons for this are subtle. Don't remove
2611 * this code unless you know what you are doing
2612 * (see PR#13758). JRA.
2615 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2616 char mangled_name[13];
2617 name_to_8_3(mask, mangled_name, True, conn->params);
2619 out:
2621 if (backup_priv) {
2622 unbecome_root();
2625 TALLOC_FREE(smb_dname);
2626 return;
2629 /****************************************************************************
2630 Reply to a TRANS2_FINDNEXT.
2631 ****************************************************************************/
2633 static void call_trans2findnext(connection_struct *conn,
2634 struct smb_request *req,
2635 char **pparams, int total_params,
2636 char **ppdata, int total_data,
2637 unsigned int max_data_bytes)
2639 /* We must be careful here that we don't return more than the
2640 allowed number of data bytes. If this means returning fewer than
2641 maxentries then so be it. We assume that the redirector has
2642 enough room for the fixed number of parameter bytes it has
2643 requested. */
2644 char *params = *pparams;
2645 char *pdata = *ppdata;
2646 char *data_end;
2647 int dptr_num;
2648 int maxentries;
2649 uint16 info_level;
2650 uint32 resume_key;
2651 uint16 findnext_flags;
2652 bool close_after_request;
2653 bool close_if_end;
2654 bool requires_resume_key;
2655 bool continue_bit;
2656 bool mask_contains_wcard = False;
2657 char *resume_name = NULL;
2658 const char *mask = NULL;
2659 const char *directory = NULL;
2660 char *p = NULL;
2661 uint16 dirtype;
2662 int numentries = 0;
2663 int i, last_entry_off=0;
2664 bool finished = False;
2665 bool dont_descend = False;
2666 bool out_of_space = False;
2667 int space_remaining;
2668 struct ea_list *ea_list = NULL;
2669 NTSTATUS ntstatus = NT_STATUS_OK;
2670 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2671 TALLOC_CTX *ctx = talloc_tos();
2672 struct dptr_struct *dirptr;
2673 struct smbd_server_connection *sconn = req->sconn;
2674 bool backup_priv = false;
2676 if (total_params < 13) {
2677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2678 return;
2681 dptr_num = SVAL(params,0);
2682 maxentries = SVAL(params,2);
2683 info_level = SVAL(params,4);
2684 resume_key = IVAL(params,6);
2685 findnext_flags = SVAL(params,10);
2686 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2687 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2688 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2689 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2691 if (!continue_bit) {
2692 /* We only need resume_name if continue_bit is zero. */
2693 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2694 params+12,
2695 total_params - 12, STR_TERMINATE, &ntstatus,
2696 &mask_contains_wcard);
2697 if (!NT_STATUS_IS_OK(ntstatus)) {
2698 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2699 complain (it thinks we're asking for the directory above the shared
2700 path or an invalid name). Catch this as the resume name is only compared, never used in
2701 a file access. JRA. */
2702 srvstr_pull_talloc(ctx, params, req->flags2,
2703 &resume_name, params+12,
2704 total_params - 12,
2705 STR_TERMINATE);
2707 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2708 reply_nterror(req, ntstatus);
2709 return;
2714 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2715 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2716 resume_key = %d resume name = %s continue=%d level = %d\n",
2717 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2718 requires_resume_key, resume_key,
2719 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2721 if (!maxentries) {
2722 /* W2K3 seems to treat zero as 1. */
2723 maxentries = 1;
2726 switch (info_level) {
2727 case SMB_FIND_INFO_STANDARD:
2728 case SMB_FIND_EA_SIZE:
2729 case SMB_FIND_EA_LIST:
2730 case SMB_FIND_FILE_DIRECTORY_INFO:
2731 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2732 case SMB_FIND_FILE_NAMES_INFO:
2733 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2734 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2735 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2736 break;
2737 case SMB_FIND_FILE_UNIX:
2738 case SMB_FIND_FILE_UNIX_INFO2:
2739 /* Always use filesystem for UNIX mtime query. */
2740 ask_sharemode = false;
2741 if (!lp_unix_extensions()) {
2742 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2743 return;
2745 break;
2746 default:
2747 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2748 return;
2751 if (info_level == SMB_FIND_EA_LIST) {
2752 uint32 ea_size;
2754 if (total_data < 4) {
2755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2756 return;
2759 ea_size = IVAL(pdata,0);
2760 if (ea_size != total_data) {
2761 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2762 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2764 return;
2767 if (!lp_ea_support(SNUM(conn))) {
2768 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2769 return;
2772 /* Pull out the list of names. */
2773 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2774 if (!ea_list) {
2775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2776 return;
2780 *ppdata = (char *)SMB_REALLOC(
2781 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2782 if(*ppdata == NULL) {
2783 reply_nterror(req, NT_STATUS_NO_MEMORY);
2784 return;
2787 pdata = *ppdata;
2788 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2790 /* Realloc the params space */
2791 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2792 if(*pparams == NULL ) {
2793 reply_nterror(req, NT_STATUS_NO_MEMORY);
2794 return;
2797 params = *pparams;
2799 /* Check that the dptr is valid */
2800 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2801 reply_nterror(req, STATUS_NO_MORE_FILES);
2802 return;
2805 directory = dptr_path(sconn, dptr_num);
2807 /* Get the wildcard mask from the dptr */
2808 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2809 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2810 reply_nterror(req, STATUS_NO_MORE_FILES);
2811 return;
2814 /* Get the attr mask from the dptr */
2815 dirtype = dptr_attr(sconn, dptr_num);
2817 backup_priv = dptr_get_priv(dirptr);
2819 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2820 "backup_priv = %d\n",
2821 dptr_num, mask, dirtype,
2822 (long)dirptr,
2823 dptr_TellDir(dirptr),
2824 (int)backup_priv));
2826 /* Initialize per TRANS2_FIND_NEXT operation data */
2827 dptr_init_search_op(dirptr);
2829 /* We don't need to check for VOL here as this is returned by
2830 a different TRANS2 call. */
2832 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2833 directory,lp_dontdescend(SNUM(conn))));
2834 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2835 dont_descend = True;
2837 p = pdata;
2838 space_remaining = max_data_bytes;
2839 out_of_space = False;
2841 if (backup_priv) {
2842 become_root();
2846 * Seek to the correct position. We no longer use the resume key but
2847 * depend on the last file name instead.
2850 if(!continue_bit && resume_name && *resume_name) {
2851 SMB_STRUCT_STAT st;
2853 long current_pos = 0;
2855 * Remember, name_to_8_3 is called by
2856 * get_lanman2_dir_entry(), so the resume name
2857 * could be mangled. Ensure we check the unmangled name.
2860 if (mangle_is_mangled(resume_name, conn->params)) {
2861 char *new_resume_name = NULL;
2862 mangle_lookup_name_from_8_3(ctx,
2863 resume_name,
2864 &new_resume_name,
2865 conn->params);
2866 if (new_resume_name) {
2867 resume_name = new_resume_name;
2872 * Fix for NT redirector problem triggered by resume key indexes
2873 * changing between directory scans. We now return a resume key of 0
2874 * and instead look for the filename to continue from (also given
2875 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2876 * findfirst/findnext (as is usual) then the directory pointer
2877 * should already be at the correct place.
2880 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2881 } /* end if resume_name && !continue_bit */
2883 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2884 bool got_exact_match = False;
2886 /* this is a heuristic to avoid seeking the dirptr except when
2887 absolutely necessary. It allows for a filename of about 40 chars */
2888 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2889 out_of_space = True;
2890 finished = False;
2891 } else {
2892 finished = !get_lanman2_dir_entry(ctx,
2893 conn,
2894 dirptr,
2895 req->flags2,
2896 mask,dirtype,info_level,
2897 requires_resume_key,dont_descend,
2898 ask_sharemode,
2899 &p,pdata,data_end,
2900 space_remaining, &out_of_space,
2901 &got_exact_match,
2902 &last_entry_off, ea_list);
2905 if (finished && out_of_space)
2906 finished = False;
2908 if (!finished && !out_of_space)
2909 numentries++;
2912 * As an optimisation if we know we aren't looking
2913 * for a wildcard name (ie. the name matches the wildcard exactly)
2914 * then we can finish on any (first) match.
2915 * This speeds up large directory searches. JRA.
2918 if(got_exact_match)
2919 finished = True;
2921 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2924 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2925 smb_fn_name(req->cmd),
2926 mask, directory, dirtype, numentries ) );
2928 /* Check if we can close the dirptr */
2929 if(close_after_request || (finished && close_if_end)) {
2930 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2931 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2934 if (backup_priv) {
2935 unbecome_root();
2938 /* Set up the return parameter block */
2939 SSVAL(params,0,numentries);
2940 SSVAL(params,2,finished);
2941 SSVAL(params,4,0); /* Never an EA error */
2942 SSVAL(params,6,last_entry_off);
2944 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2945 max_data_bytes);
2947 return;
2950 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2952 E_md4hash(lp_servicename(SNUM(conn)),objid);
2953 return objid;
2956 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2958 SMB_ASSERT(extended_info != NULL);
2960 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2961 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2962 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2963 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2964 #ifdef SAMBA_VERSION_REVISION
2965 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2966 #endif
2967 extended_info->samba_subversion = 0;
2968 #ifdef SAMBA_VERSION_RC_RELEASE
2969 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2970 #else
2971 #ifdef SAMBA_VERSION_PRE_RELEASE
2972 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2973 #endif
2974 #endif
2975 #ifdef SAMBA_VERSION_VENDOR_PATCH
2976 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2977 #endif
2978 extended_info->samba_gitcommitdate = 0;
2979 #ifdef SAMBA_VERSION_COMMIT_TIME
2980 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2981 #endif
2983 memset(extended_info->samba_version_string, 0,
2984 sizeof(extended_info->samba_version_string));
2986 snprintf (extended_info->samba_version_string,
2987 sizeof(extended_info->samba_version_string),
2988 "%s", samba_version_string());
2991 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2992 TALLOC_CTX *mem_ctx,
2993 uint16_t info_level,
2994 uint16_t flags2,
2995 unsigned int max_data_bytes,
2996 char **ppdata,
2997 int *ret_data_len)
2999 char *pdata, *end_data;
3000 int data_len = 0, len;
3001 const char *vname = volume_label(SNUM(conn));
3002 int snum = SNUM(conn);
3003 char *fstype = lp_fstype(SNUM(conn));
3004 uint32 additional_flags = 0;
3005 struct smb_filename smb_fname_dot;
3006 SMB_STRUCT_STAT st;
3008 if (IS_IPC(conn)) {
3009 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3010 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3011 "info level (0x%x) on IPC$.\n",
3012 (unsigned int)info_level));
3013 return NT_STATUS_ACCESS_DENIED;
3017 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3019 ZERO_STRUCT(smb_fname_dot);
3020 smb_fname_dot.base_name = discard_const_p(char, ".");
3022 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3023 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3024 return map_nt_error_from_unix(errno);
3027 st = smb_fname_dot.st;
3029 *ppdata = (char *)SMB_REALLOC(
3030 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3031 if (*ppdata == NULL) {
3032 return NT_STATUS_NO_MEMORY;
3035 pdata = *ppdata;
3036 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3037 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3039 switch (info_level) {
3040 case SMB_INFO_ALLOCATION:
3042 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3043 data_len = 18;
3044 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3045 return map_nt_error_from_unix(errno);
3048 block_size = lp_block_size(snum);
3049 if (bsize < block_size) {
3050 uint64_t factor = block_size/bsize;
3051 bsize = block_size;
3052 dsize /= factor;
3053 dfree /= factor;
3055 if (bsize > block_size) {
3056 uint64_t factor = bsize/block_size;
3057 bsize = block_size;
3058 dsize *= factor;
3059 dfree *= factor;
3061 bytes_per_sector = 512;
3062 sectors_per_unit = bsize/bytes_per_sector;
3064 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3065 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3066 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3068 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3069 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3070 SIVAL(pdata,l1_cUnit,dsize);
3071 SIVAL(pdata,l1_cUnitAvail,dfree);
3072 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3073 break;
3076 case SMB_INFO_VOLUME:
3077 /* Return volume name */
3079 * Add volume serial number - hash of a combination of
3080 * the called hostname and the service name.
3082 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3084 * Win2k3 and previous mess this up by sending a name length
3085 * one byte short. I believe only older clients (OS/2 Win9x) use
3086 * this call so try fixing this by adding a terminating null to
3087 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3089 len = srvstr_push(
3090 pdata, flags2,
3091 pdata+l2_vol_szVolLabel, vname,
3092 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3093 STR_NOALIGN|STR_TERMINATE);
3094 SCVAL(pdata,l2_vol_cch,len);
3095 data_len = l2_vol_szVolLabel + len;
3096 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3097 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3098 len, vname));
3099 break;
3101 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3102 case SMB_FS_ATTRIBUTE_INFORMATION:
3104 additional_flags = 0;
3105 #if defined(HAVE_SYS_QUOTAS)
3106 additional_flags |= FILE_VOLUME_QUOTAS;
3107 #endif
3109 if(lp_nt_acl_support(SNUM(conn))) {
3110 additional_flags |= FILE_PERSISTENT_ACLS;
3113 /* Capabilities are filled in at connection time through STATVFS call */
3114 additional_flags |= conn->fs_capabilities;
3115 additional_flags |= lp_parm_int(conn->params->service,
3116 "share", "fake_fscaps",
3119 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3120 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3121 additional_flags); /* FS ATTRIBUTES */
3123 SIVAL(pdata,4,255); /* Max filename component length */
3124 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3125 and will think we can't do long filenames */
3126 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3127 PTR_DIFF(end_data, pdata+12),
3128 STR_UNICODE);
3129 SIVAL(pdata,8,len);
3130 data_len = 12 + len;
3131 break;
3133 case SMB_QUERY_FS_LABEL_INFO:
3134 case SMB_FS_LABEL_INFORMATION:
3135 len = srvstr_push(pdata, flags2, pdata+4, vname,
3136 PTR_DIFF(end_data, pdata+4), 0);
3137 data_len = 4 + len;
3138 SIVAL(pdata,0,len);
3139 break;
3141 case SMB_QUERY_FS_VOLUME_INFO:
3142 case SMB_FS_VOLUME_INFORMATION:
3145 * Add volume serial number - hash of a combination of
3146 * the called hostname and the service name.
3148 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3149 (str_checksum(get_local_machine_name())<<16));
3151 /* Max label len is 32 characters. */
3152 len = srvstr_push(pdata, flags2, pdata+18, vname,
3153 PTR_DIFF(end_data, pdata+18),
3154 STR_UNICODE);
3155 SIVAL(pdata,12,len);
3156 data_len = 18+len;
3158 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3159 (int)strlen(vname),vname, lp_servicename(snum)));
3160 break;
3162 case SMB_QUERY_FS_SIZE_INFO:
3163 case SMB_FS_SIZE_INFORMATION:
3165 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3166 data_len = 24;
3167 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3168 return map_nt_error_from_unix(errno);
3170 block_size = lp_block_size(snum);
3171 if (bsize < block_size) {
3172 uint64_t factor = block_size/bsize;
3173 bsize = block_size;
3174 dsize /= factor;
3175 dfree /= factor;
3177 if (bsize > block_size) {
3178 uint64_t factor = bsize/block_size;
3179 bsize = block_size;
3180 dsize *= factor;
3181 dfree *= factor;
3183 bytes_per_sector = 512;
3184 sectors_per_unit = bsize/bytes_per_sector;
3185 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3186 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3187 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3188 SBIG_UINT(pdata,0,dsize);
3189 SBIG_UINT(pdata,8,dfree);
3190 SIVAL(pdata,16,sectors_per_unit);
3191 SIVAL(pdata,20,bytes_per_sector);
3192 break;
3195 case SMB_FS_FULL_SIZE_INFORMATION:
3197 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3198 data_len = 32;
3199 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3200 return map_nt_error_from_unix(errno);
3202 block_size = lp_block_size(snum);
3203 if (bsize < block_size) {
3204 uint64_t factor = block_size/bsize;
3205 bsize = block_size;
3206 dsize /= factor;
3207 dfree /= factor;
3209 if (bsize > block_size) {
3210 uint64_t factor = bsize/block_size;
3211 bsize = block_size;
3212 dsize *= factor;
3213 dfree *= factor;
3215 bytes_per_sector = 512;
3216 sectors_per_unit = bsize/bytes_per_sector;
3217 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3218 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3219 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3220 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3221 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3222 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3223 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3224 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3225 break;
3228 case SMB_QUERY_FS_DEVICE_INFO:
3229 case SMB_FS_DEVICE_INFORMATION:
3231 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3233 if (!CAN_WRITE(conn)) {
3234 characteristics |= FILE_READ_ONLY_DEVICE;
3236 data_len = 8;
3237 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3238 SIVAL(pdata,4,characteristics);
3239 break;
3242 #ifdef HAVE_SYS_QUOTAS
3243 case SMB_FS_QUOTA_INFORMATION:
3245 * what we have to send --metze:
3247 * Unknown1: 24 NULL bytes
3248 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3249 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3250 * Quota Flags: 2 byte :
3251 * Unknown3: 6 NULL bytes
3253 * 48 bytes total
3255 * details for Quota Flags:
3257 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3258 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3259 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3260 * 0x0001 Enable Quotas: enable quota for this fs
3264 /* we need to fake up a fsp here,
3265 * because its not send in this call
3267 files_struct fsp;
3268 SMB_NTQUOTA_STRUCT quotas;
3270 ZERO_STRUCT(fsp);
3271 ZERO_STRUCT(quotas);
3273 fsp.conn = conn;
3274 fsp.fnum = -1;
3276 /* access check */
3277 if (get_current_uid(conn) != 0) {
3278 DEBUG(0,("set_user_quota: access_denied "
3279 "service [%s] user [%s]\n",
3280 lp_servicename(SNUM(conn)),
3281 conn->session_info->unix_info->unix_name));
3282 return NT_STATUS_ACCESS_DENIED;
3285 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3286 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3287 return map_nt_error_from_unix(errno);
3290 data_len = 48;
3292 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3293 lp_servicename(SNUM(conn))));
3295 /* Unknown1 24 NULL bytes*/
3296 SBIG_UINT(pdata,0,(uint64_t)0);
3297 SBIG_UINT(pdata,8,(uint64_t)0);
3298 SBIG_UINT(pdata,16,(uint64_t)0);
3300 /* Default Soft Quota 8 bytes */
3301 SBIG_UINT(pdata,24,quotas.softlim);
3303 /* Default Hard Quota 8 bytes */
3304 SBIG_UINT(pdata,32,quotas.hardlim);
3306 /* Quota flag 2 bytes */
3307 SSVAL(pdata,40,quotas.qflags);
3309 /* Unknown3 6 NULL bytes */
3310 SSVAL(pdata,42,0);
3311 SIVAL(pdata,44,0);
3313 break;
3315 #endif /* HAVE_SYS_QUOTAS */
3316 case SMB_FS_OBJECTID_INFORMATION:
3318 unsigned char objid[16];
3319 struct smb_extended_info extended_info;
3320 memcpy(pdata,create_volume_objectid(conn, objid),16);
3321 samba_extended_info_version (&extended_info);
3322 SIVAL(pdata,16,extended_info.samba_magic);
3323 SIVAL(pdata,20,extended_info.samba_version);
3324 SIVAL(pdata,24,extended_info.samba_subversion);
3325 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3326 memcpy(pdata+36,extended_info.samba_version_string,28);
3327 data_len = 64;
3328 break;
3332 * Query the version and capabilities of the CIFS UNIX extensions
3333 * in use.
3336 case SMB_QUERY_CIFS_UNIX_INFO:
3338 bool large_write = lp_min_receive_file_size() &&
3339 !srv_is_signing_active(conn->sconn);
3340 bool large_read = !srv_is_signing_active(conn->sconn);
3341 int encrypt_caps = 0;
3343 if (!lp_unix_extensions()) {
3344 return NT_STATUS_INVALID_LEVEL;
3347 switch (conn->encrypt_level) {
3348 case 0:
3349 encrypt_caps = 0;
3350 break;
3351 case 1:
3352 case Auto:
3353 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3354 break;
3355 case Required:
3356 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3357 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3358 large_write = false;
3359 large_read = false;
3360 break;
3363 data_len = 12;
3364 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3365 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3367 /* We have POSIX ACLs, pathname, encryption,
3368 * large read/write, and locking capability. */
3370 SBIG_UINT(pdata,4,((uint64_t)(
3371 CIFS_UNIX_POSIX_ACLS_CAP|
3372 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3373 CIFS_UNIX_FCNTL_LOCKS_CAP|
3374 CIFS_UNIX_EXTATTR_CAP|
3375 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3376 encrypt_caps|
3377 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3378 (large_write ?
3379 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3380 break;
3383 case SMB_QUERY_POSIX_FS_INFO:
3385 int rc;
3386 vfs_statvfs_struct svfs;
3388 if (!lp_unix_extensions()) {
3389 return NT_STATUS_INVALID_LEVEL;
3392 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3394 if (!rc) {
3395 data_len = 56;
3396 SIVAL(pdata,0,svfs.OptimalTransferSize);
3397 SIVAL(pdata,4,svfs.BlockSize);
3398 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3399 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3400 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3401 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3402 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3403 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3405 #ifdef EOPNOTSUPP
3406 } else if (rc == EOPNOTSUPP) {
3407 return NT_STATUS_INVALID_LEVEL;
3408 #endif /* EOPNOTSUPP */
3409 } else {
3410 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3411 return NT_STATUS_DOS(ERRSRV, ERRerror);
3413 break;
3416 case SMB_QUERY_POSIX_WHOAMI:
3418 uint32_t flags = 0;
3419 uint32_t sid_bytes;
3420 int i;
3422 if (!lp_unix_extensions()) {
3423 return NT_STATUS_INVALID_LEVEL;
3426 if (max_data_bytes < 40) {
3427 return NT_STATUS_BUFFER_TOO_SMALL;
3430 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3431 flags |= SMB_WHOAMI_GUEST;
3434 /* NOTE: 8 bytes for UID/GID, irrespective of native
3435 * platform size. This matches
3436 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3438 data_len = 4 /* flags */
3439 + 4 /* flag mask */
3440 + 8 /* uid */
3441 + 8 /* gid */
3442 + 4 /* ngroups */
3443 + 4 /* num_sids */
3444 + 4 /* SID bytes */
3445 + 4 /* pad/reserved */
3446 + (conn->session_info->unix_token->ngroups * 8)
3447 /* groups list */
3448 + (conn->session_info->security_token->num_sids *
3449 SID_MAX_SIZE)
3450 /* SID list */;
3452 SIVAL(pdata, 0, flags);
3453 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3454 SBIG_UINT(pdata, 8,
3455 (uint64_t)conn->session_info->unix_token->uid);
3456 SBIG_UINT(pdata, 16,
3457 (uint64_t)conn->session_info->unix_token->gid);
3460 if (data_len >= max_data_bytes) {
3461 /* Potential overflow, skip the GIDs and SIDs. */
3463 SIVAL(pdata, 24, 0); /* num_groups */
3464 SIVAL(pdata, 28, 0); /* num_sids */
3465 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3466 SIVAL(pdata, 36, 0); /* reserved */
3468 data_len = 40;
3469 break;
3472 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3473 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3475 /* We walk the SID list twice, but this call is fairly
3476 * infrequent, and I don't expect that it's performance
3477 * sensitive -- jpeach
3479 for (i = 0, sid_bytes = 0;
3480 i < conn->session_info->security_token->num_sids; ++i) {
3481 sid_bytes += ndr_size_dom_sid(
3482 &conn->session_info->security_token->sids[i],
3486 /* SID list byte count */
3487 SIVAL(pdata, 32, sid_bytes);
3489 /* 4 bytes pad/reserved - must be zero */
3490 SIVAL(pdata, 36, 0);
3491 data_len = 40;
3493 /* GID list */
3494 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3495 SBIG_UINT(pdata, data_len,
3496 (uint64_t)conn->session_info->unix_token->groups[i]);
3497 data_len += 8;
3500 /* SID list */
3501 for (i = 0;
3502 i < conn->session_info->security_token->num_sids; ++i) {
3503 int sid_len = ndr_size_dom_sid(
3504 &conn->session_info->security_token->sids[i],
3507 sid_linearize(pdata + data_len, sid_len,
3508 &conn->session_info->security_token->sids[i]);
3509 data_len += sid_len;
3512 break;
3515 case SMB_MAC_QUERY_FS_INFO:
3517 * Thursby MAC extension... ONLY on NTFS filesystems
3518 * once we do streams then we don't need this
3520 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3521 data_len = 88;
3522 SIVAL(pdata,84,0x100); /* Don't support mac... */
3523 break;
3525 /* drop through */
3526 default:
3527 return NT_STATUS_INVALID_LEVEL;
3530 *ret_data_len = data_len;
3531 return NT_STATUS_OK;
3534 /****************************************************************************
3535 Reply to a TRANS2_QFSINFO (query filesystem info).
3536 ****************************************************************************/
3538 static void call_trans2qfsinfo(connection_struct *conn,
3539 struct smb_request *req,
3540 char **pparams, int total_params,
3541 char **ppdata, int total_data,
3542 unsigned int max_data_bytes)
3544 char *params = *pparams;
3545 uint16_t info_level;
3546 int data_len = 0;
3547 NTSTATUS status;
3549 if (total_params < 2) {
3550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3551 return;
3554 info_level = SVAL(params,0);
3556 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3557 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3558 DEBUG(0,("call_trans2qfsinfo: encryption required "
3559 "and info level 0x%x sent.\n",
3560 (unsigned int)info_level));
3561 exit_server_cleanly("encryption required "
3562 "on connection");
3563 return;
3567 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3569 status = smbd_do_qfsinfo(conn, req,
3570 info_level,
3571 req->flags2,
3572 max_data_bytes,
3573 ppdata, &data_len);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 reply_nterror(req, status);
3576 return;
3579 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3580 max_data_bytes);
3582 DEBUG( 4, ( "%s info_level = %d\n",
3583 smb_fn_name(req->cmd), info_level) );
3585 return;
3588 /****************************************************************************
3589 Reply to a TRANS2_SETFSINFO (set filesystem info).
3590 ****************************************************************************/
3592 static void call_trans2setfsinfo(connection_struct *conn,
3593 struct smb_request *req,
3594 char **pparams, int total_params,
3595 char **ppdata, int total_data,
3596 unsigned int max_data_bytes)
3598 struct smbd_server_connection *sconn = req->sconn;
3599 char *pdata = *ppdata;
3600 char *params = *pparams;
3601 uint16 info_level;
3603 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3605 /* */
3606 if (total_params < 4) {
3607 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3608 total_params));
3609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3610 return;
3613 info_level = SVAL(params,2);
3615 if (IS_IPC(conn)) {
3616 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3617 info_level != SMB_SET_CIFS_UNIX_INFO) {
3618 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3619 "info level (0x%x) on IPC$.\n",
3620 (unsigned int)info_level));
3621 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3622 return;
3626 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3627 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3628 DEBUG(0,("call_trans2setfsinfo: encryption required "
3629 "and info level 0x%x sent.\n",
3630 (unsigned int)info_level));
3631 exit_server_cleanly("encryption required "
3632 "on connection");
3633 return;
3637 switch(info_level) {
3638 case SMB_SET_CIFS_UNIX_INFO:
3639 if (!lp_unix_extensions()) {
3640 DEBUG(2,("call_trans2setfsinfo: "
3641 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3642 "unix extensions off\n"));
3643 reply_nterror(req,
3644 NT_STATUS_INVALID_LEVEL);
3645 return;
3648 /* There should be 12 bytes of capabilities set. */
3649 if (total_data < 12) {
3650 reply_nterror(
3651 req,
3652 NT_STATUS_INVALID_PARAMETER);
3653 return;
3655 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3656 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3657 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3658 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3659 /* Just print these values for now. */
3660 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3661 "major = %u, minor = %u cap_low = 0x%x, "
3662 "cap_high = 0x%xn",
3663 (unsigned int)sconn->
3664 smb1.unix_info.client_major,
3665 (unsigned int)sconn->
3666 smb1.unix_info.client_minor,
3667 (unsigned int)sconn->
3668 smb1.unix_info.client_cap_low,
3669 (unsigned int)sconn->
3670 smb1.unix_info.client_cap_high));
3672 /* Here is where we must switch to posix pathname processing... */
3673 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3674 lp_set_posix_pathnames();
3675 mangle_change_to_posix();
3678 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3679 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3680 /* Client that knows how to do posix locks,
3681 * but not posix open/mkdir operations. Set a
3682 * default type for read/write checks. */
3684 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3687 break;
3689 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3691 NTSTATUS status;
3692 size_t param_len = 0;
3693 size_t data_len = total_data;
3695 if (!lp_unix_extensions()) {
3696 reply_nterror(
3697 req,
3698 NT_STATUS_INVALID_LEVEL);
3699 return;
3702 if (lp_smb_encrypt(SNUM(conn)) == false) {
3703 reply_nterror(
3704 req,
3705 NT_STATUS_NOT_SUPPORTED);
3706 return;
3709 if (req->sconn->smb1.echo_handler.trusted_fde) {
3710 DEBUG( 2,("call_trans2setfsinfo: "
3711 "request transport encryption disabled"
3712 "with 'fork echo handler = yes'\n"));
3713 reply_nterror(
3714 req,
3715 NT_STATUS_NOT_SUPPORTED);
3716 return;
3719 DEBUG( 4,("call_trans2setfsinfo: "
3720 "request transport encryption.\n"));
3722 status = srv_request_encryption_setup(conn,
3723 (unsigned char **)ppdata,
3724 &data_len,
3725 (unsigned char **)pparams,
3726 &param_len);
3728 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3729 !NT_STATUS_IS_OK(status)) {
3730 reply_nterror(req, status);
3731 return;
3734 send_trans2_replies(conn, req,
3735 *pparams,
3736 param_len,
3737 *ppdata,
3738 data_len,
3739 max_data_bytes);
3741 if (NT_STATUS_IS_OK(status)) {
3742 /* Server-side transport
3743 * encryption is now *on*. */
3744 status = srv_encryption_start(conn);
3745 if (!NT_STATUS_IS_OK(status)) {
3746 char *reason = talloc_asprintf(talloc_tos(),
3747 "Failure in setting "
3748 "up encrypted transport: %s",
3749 nt_errstr(status));
3750 exit_server_cleanly(reason);
3753 return;
3756 case SMB_FS_QUOTA_INFORMATION:
3758 files_struct *fsp = NULL;
3759 SMB_NTQUOTA_STRUCT quotas;
3761 ZERO_STRUCT(quotas);
3763 /* access check */
3764 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3765 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3766 lp_servicename(SNUM(conn)),
3767 conn->session_info->unix_info->unix_name));
3768 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3769 return;
3772 /* note: normaly there're 48 bytes,
3773 * but we didn't use the last 6 bytes for now
3774 * --metze
3776 fsp = file_fsp(req, SVAL(params,0));
3778 if (!check_fsp_ntquota_handle(conn, req,
3779 fsp)) {
3780 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3781 reply_nterror(
3782 req, NT_STATUS_INVALID_HANDLE);
3783 return;
3786 if (total_data < 42) {
3787 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3788 total_data));
3789 reply_nterror(
3790 req,
3791 NT_STATUS_INVALID_PARAMETER);
3792 return;
3795 /* unknown_1 24 NULL bytes in pdata*/
3797 /* the soft quotas 8 bytes (uint64_t)*/
3798 quotas.softlim = BVAL(pdata,24);
3800 /* the hard quotas 8 bytes (uint64_t)*/
3801 quotas.hardlim = BVAL(pdata,32);
3803 /* quota_flags 2 bytes **/
3804 quotas.qflags = SVAL(pdata,40);
3806 /* unknown_2 6 NULL bytes follow*/
3808 /* now set the quotas */
3809 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3810 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3811 reply_nterror(req, map_nt_error_from_unix(errno));
3812 return;
3815 break;
3817 default:
3818 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3819 info_level));
3820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3821 return;
3822 break;
3826 * sending this reply works fine,
3827 * but I'm not sure it's the same
3828 * like windows do...
3829 * --metze
3831 reply_outbuf(req, 10, 0);
3834 #if defined(HAVE_POSIX_ACLS)
3835 /****************************************************************************
3836 Utility function to count the number of entries in a POSIX acl.
3837 ****************************************************************************/
3839 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3841 unsigned int ace_count = 0;
3842 int entry_id = SMB_ACL_FIRST_ENTRY;
3843 SMB_ACL_ENTRY_T entry;
3845 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3846 /* get_next... */
3847 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3848 entry_id = SMB_ACL_NEXT_ENTRY;
3850 ace_count++;
3852 return ace_count;
3855 /****************************************************************************
3856 Utility function to marshall a POSIX acl into wire format.
3857 ****************************************************************************/
3859 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3861 int entry_id = SMB_ACL_FIRST_ENTRY;
3862 SMB_ACL_ENTRY_T entry;
3864 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3865 SMB_ACL_TAG_T tagtype;
3866 SMB_ACL_PERMSET_T permset;
3867 unsigned char perms = 0;
3868 unsigned int own_grp;
3870 /* get_next... */
3871 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3872 entry_id = SMB_ACL_NEXT_ENTRY;
3875 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3876 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3877 return False;
3880 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3881 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3882 return False;
3885 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3886 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3887 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3889 SCVAL(pdata,1,perms);
3891 switch (tagtype) {
3892 case SMB_ACL_USER_OBJ:
3893 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3894 own_grp = (unsigned int)pst->st_ex_uid;
3895 SIVAL(pdata,2,own_grp);
3896 SIVAL(pdata,6,0);
3897 break;
3898 case SMB_ACL_USER:
3900 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3901 if (!puid) {
3902 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3903 return False;
3905 own_grp = (unsigned int)*puid;
3906 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3907 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3908 SIVAL(pdata,2,own_grp);
3909 SIVAL(pdata,6,0);
3910 break;
3912 case SMB_ACL_GROUP_OBJ:
3913 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3914 own_grp = (unsigned int)pst->st_ex_gid;
3915 SIVAL(pdata,2,own_grp);
3916 SIVAL(pdata,6,0);
3917 break;
3918 case SMB_ACL_GROUP:
3920 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3921 if (!pgid) {
3922 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3923 return False;
3925 own_grp = (unsigned int)*pgid;
3926 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3927 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3928 SIVAL(pdata,2,own_grp);
3929 SIVAL(pdata,6,0);
3930 break;
3932 case SMB_ACL_MASK:
3933 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3934 SIVAL(pdata,2,0xFFFFFFFF);
3935 SIVAL(pdata,6,0xFFFFFFFF);
3936 break;
3937 case SMB_ACL_OTHER:
3938 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3939 SIVAL(pdata,2,0xFFFFFFFF);
3940 SIVAL(pdata,6,0xFFFFFFFF);
3941 break;
3942 default:
3943 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3944 return False;
3946 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3949 return True;
3951 #endif
3953 /****************************************************************************
3954 Store the FILE_UNIX_BASIC info.
3955 ****************************************************************************/
3957 static char *store_file_unix_basic(connection_struct *conn,
3958 char *pdata,
3959 files_struct *fsp,
3960 const SMB_STRUCT_STAT *psbuf)
3962 uint64_t file_index = get_FileIndex(conn, psbuf);
3963 dev_t devno;
3965 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3966 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3968 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3969 pdata += 8;
3971 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3972 pdata += 8;
3974 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3975 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3976 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3977 pdata += 24;
3979 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3980 SIVAL(pdata,4,0);
3981 pdata += 8;
3983 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3984 SIVAL(pdata,4,0);
3985 pdata += 8;
3987 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3988 pdata += 4;
3990 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3991 devno = psbuf->st_ex_rdev;
3992 } else {
3993 devno = psbuf->st_ex_dev;
3996 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
3997 SIVAL(pdata,4,0);
3998 pdata += 8;
4000 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4001 SIVAL(pdata,4,0);
4002 pdata += 8;
4004 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4005 pdata += 8;
4007 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4008 SIVAL(pdata,4,0);
4009 pdata += 8;
4011 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4012 SIVAL(pdata,4,0);
4013 pdata += 8;
4015 return pdata;
4018 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4019 * the chflags(2) (or equivalent) flags.
4021 * XXX: this really should be behind the VFS interface. To do this, we would
4022 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4023 * Each VFS module could then implement its own mapping as appropriate for the
4024 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4026 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4027 info2_flags_map[] =
4029 #ifdef UF_NODUMP
4030 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4031 #endif
4033 #ifdef UF_IMMUTABLE
4034 { UF_IMMUTABLE, EXT_IMMUTABLE },
4035 #endif
4037 #ifdef UF_APPEND
4038 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4039 #endif
4041 #ifdef UF_HIDDEN
4042 { UF_HIDDEN, EXT_HIDDEN },
4043 #endif
4045 /* Do not remove. We need to guarantee that this array has at least one
4046 * entry to build on HP-UX.
4048 { 0, 0 }
4052 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4053 uint32 *smb_fflags, uint32 *smb_fmask)
4055 int i;
4057 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4058 *smb_fmask |= info2_flags_map[i].smb_fflag;
4059 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4060 *smb_fflags |= info2_flags_map[i].smb_fflag;
4065 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4066 const uint32 smb_fflags,
4067 const uint32 smb_fmask,
4068 int *stat_fflags)
4070 uint32 max_fmask = 0;
4071 int i;
4073 *stat_fflags = psbuf->st_ex_flags;
4075 /* For each flags requested in smb_fmask, check the state of the
4076 * corresponding flag in smb_fflags and set or clear the matching
4077 * stat flag.
4080 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4081 max_fmask |= info2_flags_map[i].smb_fflag;
4082 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4083 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4084 *stat_fflags |= info2_flags_map[i].stat_fflag;
4085 } else {
4086 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4091 /* If smb_fmask is asking to set any bits that are not supported by
4092 * our flag mappings, we should fail.
4094 if ((smb_fmask & max_fmask) != smb_fmask) {
4095 return False;
4098 return True;
4102 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4103 * of file flags and birth (create) time.
4105 static char *store_file_unix_basic_info2(connection_struct *conn,
4106 char *pdata,
4107 files_struct *fsp,
4108 const SMB_STRUCT_STAT *psbuf)
4110 uint32 file_flags = 0;
4111 uint32 flags_mask = 0;
4113 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4115 /* Create (birth) time 64 bit */
4116 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4117 pdata += 8;
4119 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4120 SIVAL(pdata, 0, file_flags); /* flags */
4121 SIVAL(pdata, 4, flags_mask); /* mask */
4122 pdata += 8;
4124 return pdata;
4127 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4128 const struct stream_struct *streams,
4129 char *data,
4130 unsigned int max_data_bytes,
4131 unsigned int *data_size)
4133 unsigned int i;
4134 unsigned int ofs = 0;
4136 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4137 unsigned int next_offset;
4138 size_t namelen;
4139 smb_ucs2_t *namebuf;
4141 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4142 streams[i].name, &namelen) ||
4143 namelen <= 2)
4145 return NT_STATUS_INVALID_PARAMETER;
4149 * name_buf is now null-terminated, we need to marshall as not
4150 * terminated
4153 namelen -= 2;
4155 SIVAL(data, ofs+4, namelen);
4156 SOFF_T(data, ofs+8, streams[i].size);
4157 SOFF_T(data, ofs+16, streams[i].alloc_size);
4158 memcpy(data+ofs+24, namebuf, namelen);
4159 TALLOC_FREE(namebuf);
4161 next_offset = ofs + 24 + namelen;
4163 if (i == num_streams-1) {
4164 SIVAL(data, ofs, 0);
4166 else {
4167 unsigned int align = ndr_align_size(next_offset, 8);
4169 memset(data+next_offset, 0, align);
4170 next_offset += align;
4172 SIVAL(data, ofs, next_offset - ofs);
4173 ofs = next_offset;
4176 ofs = next_offset;
4179 *data_size = ofs;
4181 return NT_STATUS_OK;
4184 /****************************************************************************
4185 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4186 ****************************************************************************/
4188 static void call_trans2qpipeinfo(connection_struct *conn,
4189 struct smb_request *req,
4190 unsigned int tran_call,
4191 char **pparams, int total_params,
4192 char **ppdata, int total_data,
4193 unsigned int max_data_bytes)
4195 char *params = *pparams;
4196 char *pdata = *ppdata;
4197 unsigned int data_size = 0;
4198 unsigned int param_size = 2;
4199 uint16 info_level;
4200 files_struct *fsp;
4202 if (!params) {
4203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4204 return;
4207 if (total_params < 4) {
4208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4209 return;
4212 fsp = file_fsp(req, SVAL(params,0));
4213 if (!fsp_is_np(fsp)) {
4214 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4215 return;
4218 info_level = SVAL(params,2);
4220 *pparams = (char *)SMB_REALLOC(*pparams,2);
4221 if (*pparams == NULL) {
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4223 return;
4225 params = *pparams;
4226 SSVAL(params,0,0);
4227 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4228 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4229 if (*ppdata == NULL ) {
4230 reply_nterror(req, NT_STATUS_NO_MEMORY);
4231 return;
4233 pdata = *ppdata;
4235 switch (info_level) {
4236 case SMB_FILE_STANDARD_INFORMATION:
4237 memset(pdata,0,24);
4238 SOFF_T(pdata,0,4096LL);
4239 SIVAL(pdata,16,1);
4240 SIVAL(pdata,20,1);
4241 data_size = 24;
4242 break;
4244 default:
4245 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4246 return;
4249 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4250 max_data_bytes);
4252 return;
4255 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4256 TALLOC_CTX *mem_ctx,
4257 uint16_t info_level,
4258 files_struct *fsp,
4259 struct smb_filename *smb_fname,
4260 bool delete_pending,
4261 struct timespec write_time_ts,
4262 struct ea_list *ea_list,
4263 int lock_data_count,
4264 char *lock_data,
4265 uint16_t flags2,
4266 unsigned int max_data_bytes,
4267 char **ppdata,
4268 unsigned int *pdata_size)
4270 char *pdata = *ppdata;
4271 char *dstart, *dend;
4272 unsigned int data_size;
4273 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4274 time_t create_time, mtime, atime, c_time;
4275 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4276 char *p;
4277 char *base_name;
4278 char *dos_fname;
4279 int mode;
4280 int nlink;
4281 NTSTATUS status;
4282 uint64_t file_size = 0;
4283 uint64_t pos = 0;
4284 uint64_t allocation_size = 0;
4285 uint64_t file_index = 0;
4286 uint32_t access_mask = 0;
4288 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4289 return NT_STATUS_INVALID_LEVEL;
4292 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4293 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4294 info_level, max_data_bytes));
4296 mode = dos_mode(conn, smb_fname);
4297 nlink = psbuf->st_ex_nlink;
4299 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4300 nlink = 1;
4303 if ((nlink > 0) && delete_pending) {
4304 nlink -= 1;
4307 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4308 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4309 if (*ppdata == NULL) {
4310 return NT_STATUS_NO_MEMORY;
4312 pdata = *ppdata;
4313 dstart = pdata;
4314 dend = dstart + data_size - 1;
4316 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4317 update_stat_ex_mtime(psbuf, write_time_ts);
4320 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4321 mtime_ts = psbuf->st_ex_mtime;
4322 atime_ts = psbuf->st_ex_atime;
4323 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4325 if (lp_dos_filetime_resolution(SNUM(conn))) {
4326 dos_filetime_timespec(&create_time_ts);
4327 dos_filetime_timespec(&mtime_ts);
4328 dos_filetime_timespec(&atime_ts);
4329 dos_filetime_timespec(&ctime_ts);
4332 create_time = convert_timespec_to_time_t(create_time_ts);
4333 mtime = convert_timespec_to_time_t(mtime_ts);
4334 atime = convert_timespec_to_time_t(atime_ts);
4335 c_time = convert_timespec_to_time_t(ctime_ts);
4337 p = strrchr_m(smb_fname->base_name,'/');
4338 if (!p)
4339 base_name = smb_fname->base_name;
4340 else
4341 base_name = p+1;
4343 /* NT expects the name to be in an exact form of the *full*
4344 filename. See the trans2 torture test */
4345 if (ISDOT(base_name)) {
4346 dos_fname = talloc_strdup(mem_ctx, "\\");
4347 if (!dos_fname) {
4348 return NT_STATUS_NO_MEMORY;
4350 } else {
4351 dos_fname = talloc_asprintf(mem_ctx,
4352 "\\%s",
4353 smb_fname->base_name);
4354 if (!dos_fname) {
4355 return NT_STATUS_NO_MEMORY;
4357 if (is_ntfs_stream_smb_fname(smb_fname)) {
4358 dos_fname = talloc_asprintf(dos_fname, "%s",
4359 smb_fname->stream_name);
4360 if (!dos_fname) {
4361 return NT_STATUS_NO_MEMORY;
4365 string_replace(dos_fname, '/', '\\');
4368 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4370 if (!fsp) {
4371 /* Do we have this path open ? */
4372 files_struct *fsp1;
4373 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4374 fsp1 = file_find_di_first(conn->sconn, fileid);
4375 if (fsp1 && fsp1->initial_allocation_size) {
4376 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4380 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4381 file_size = get_file_size_stat(psbuf);
4384 if (fsp) {
4385 pos = fsp->fh->position_information;
4388 if (fsp) {
4389 access_mask = fsp->access_mask;
4390 } else {
4391 /* GENERIC_EXECUTE mapping from Windows */
4392 access_mask = 0x12019F;
4395 /* This should be an index number - looks like
4396 dev/ino to me :-)
4398 I think this causes us to fail the IFSKIT
4399 BasicFileInformationTest. -tpot */
4400 file_index = get_FileIndex(conn, psbuf);
4402 switch (info_level) {
4403 case SMB_INFO_STANDARD:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4405 data_size = 22;
4406 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4407 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4408 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4409 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4410 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4411 SSVAL(pdata,l1_attrFile,mode);
4412 break;
4414 case SMB_INFO_QUERY_EA_SIZE:
4416 unsigned int ea_size =
4417 estimate_ea_size(conn, fsp,
4418 smb_fname->base_name);
4419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4420 data_size = 26;
4421 srv_put_dos_date2(pdata,0,create_time);
4422 srv_put_dos_date2(pdata,4,atime);
4423 srv_put_dos_date2(pdata,8,mtime); /* write time */
4424 SIVAL(pdata,12,(uint32)file_size);
4425 SIVAL(pdata,16,(uint32)allocation_size);
4426 SSVAL(pdata,20,mode);
4427 SIVAL(pdata,22,ea_size);
4428 break;
4431 case SMB_INFO_IS_NAME_VALID:
4432 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4433 if (fsp) {
4434 /* os/2 needs this ? really ?*/
4435 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4437 /* This is only reached for qpathinfo */
4438 data_size = 0;
4439 break;
4441 case SMB_INFO_QUERY_EAS_FROM_LIST:
4443 size_t total_ea_len = 0;
4444 struct ea_list *ea_file_list = NULL;
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4448 ea_file_list =
4449 get_ea_list_from_file(mem_ctx, conn, fsp,
4450 smb_fname->base_name,
4451 &total_ea_len);
4452 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4454 if (!ea_list || (total_ea_len > data_size)) {
4455 data_size = 4;
4456 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4457 break;
4460 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4461 break;
4464 case SMB_INFO_QUERY_ALL_EAS:
4466 /* We have data_size bytes to put EA's into. */
4467 size_t total_ea_len = 0;
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4471 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4472 smb_fname->base_name,
4473 &total_ea_len);
4474 if (!ea_list || (total_ea_len > data_size)) {
4475 data_size = 4;
4476 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4477 break;
4480 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4481 break;
4484 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4486 /* This is FileFullEaInformation - 0xF which maps to
4487 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4489 /* We have data_size bytes to put EA's into. */
4490 size_t total_ea_len = 0;
4491 struct ea_list *ea_file_list = NULL;
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4495 /*TODO: add filtering and index handling */
4497 ea_file_list =
4498 get_ea_list_from_file(mem_ctx, conn, fsp,
4499 smb_fname->base_name,
4500 &total_ea_len);
4501 if (!ea_file_list) {
4502 return NT_STATUS_NO_EAS_ON_FILE;
4505 status = fill_ea_chained_buffer(mem_ctx,
4506 pdata,
4507 data_size,
4508 &data_size,
4509 conn, ea_file_list);
4510 if (!NT_STATUS_IS_OK(status)) {
4511 return status;
4513 break;
4516 case SMB_FILE_BASIC_INFORMATION:
4517 case SMB_QUERY_FILE_BASIC_INFO:
4519 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4521 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4522 } else {
4523 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4524 data_size = 40;
4525 SIVAL(pdata,36,0);
4527 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4528 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4529 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4530 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4531 SIVAL(pdata,32,mode);
4533 DEBUG(5,("SMB_QFBI - "));
4534 DEBUG(5,("create: %s ", ctime(&create_time)));
4535 DEBUG(5,("access: %s ", ctime(&atime)));
4536 DEBUG(5,("write: %s ", ctime(&mtime)));
4537 DEBUG(5,("change: %s ", ctime(&c_time)));
4538 DEBUG(5,("mode: %x\n", mode));
4539 break;
4541 case SMB_FILE_STANDARD_INFORMATION:
4542 case SMB_QUERY_FILE_STANDARD_INFO:
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4545 data_size = 24;
4546 SOFF_T(pdata,0,allocation_size);
4547 SOFF_T(pdata,8,file_size);
4548 SIVAL(pdata,16,nlink);
4549 SCVAL(pdata,20,delete_pending?1:0);
4550 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4551 SSVAL(pdata,22,0); /* Padding. */
4552 break;
4554 case SMB_FILE_EA_INFORMATION:
4555 case SMB_QUERY_FILE_EA_INFO:
4557 unsigned int ea_size =
4558 estimate_ea_size(conn, fsp, smb_fname->base_name);
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4560 data_size = 4;
4561 SIVAL(pdata,0,ea_size);
4562 break;
4565 /* Get the 8.3 name - used if NT SMB was negotiated. */
4566 case SMB_QUERY_FILE_ALT_NAME_INFO:
4567 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4569 int len;
4570 char mangled_name[13];
4571 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4572 if (!name_to_8_3(base_name,mangled_name,
4573 True,conn->params)) {
4574 return NT_STATUS_NO_MEMORY;
4576 len = srvstr_push(dstart, flags2,
4577 pdata+4, mangled_name,
4578 PTR_DIFF(dend, pdata+4),
4579 STR_UNICODE);
4580 data_size = 4 + len;
4581 SIVAL(pdata,0,len);
4582 break;
4585 case SMB_QUERY_FILE_NAME_INFO:
4587 int len;
4589 this must be *exactly* right for ACLs on mapped drives to work
4591 len = srvstr_push(dstart, flags2,
4592 pdata+4, dos_fname,
4593 PTR_DIFF(dend, pdata+4),
4594 STR_UNICODE);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4596 data_size = 4 + len;
4597 SIVAL(pdata,0,len);
4598 break;
4601 case SMB_FILE_ALLOCATION_INFORMATION:
4602 case SMB_QUERY_FILE_ALLOCATION_INFO:
4603 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4604 data_size = 8;
4605 SOFF_T(pdata,0,allocation_size);
4606 break;
4608 case SMB_FILE_END_OF_FILE_INFORMATION:
4609 case SMB_QUERY_FILE_END_OF_FILEINFO:
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4611 data_size = 8;
4612 SOFF_T(pdata,0,file_size);
4613 break;
4615 case SMB_QUERY_FILE_ALL_INFO:
4616 case SMB_FILE_ALL_INFORMATION:
4618 int len;
4619 unsigned int ea_size =
4620 estimate_ea_size(conn, fsp, smb_fname->base_name);
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4622 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4623 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4624 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4625 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4626 SIVAL(pdata,32,mode);
4627 SIVAL(pdata,36,0); /* padding. */
4628 pdata += 40;
4629 SOFF_T(pdata,0,allocation_size);
4630 SOFF_T(pdata,8,file_size);
4631 SIVAL(pdata,16,nlink);
4632 SCVAL(pdata,20,delete_pending);
4633 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4634 SSVAL(pdata,22,0);
4635 pdata += 24;
4636 SIVAL(pdata,0,ea_size);
4637 pdata += 4; /* EA info */
4638 len = srvstr_push(dstart, flags2,
4639 pdata+4, dos_fname,
4640 PTR_DIFF(dend, pdata+4),
4641 STR_UNICODE);
4642 SIVAL(pdata,0,len);
4643 pdata += 4 + len;
4644 data_size = PTR_DIFF(pdata,(*ppdata));
4645 break;
4648 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4650 int len;
4651 unsigned int ea_size =
4652 estimate_ea_size(conn, fsp, smb_fname->base_name);
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4654 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4655 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4656 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4657 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4658 SIVAL(pdata, 0x20, mode);
4659 SIVAL(pdata, 0x24, 0); /* padding. */
4660 SBVAL(pdata, 0x28, allocation_size);
4661 SBVAL(pdata, 0x30, file_size);
4662 SIVAL(pdata, 0x38, nlink);
4663 SCVAL(pdata, 0x3C, delete_pending);
4664 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4665 SSVAL(pdata, 0x3E, 0); /* padding */
4666 SBVAL(pdata, 0x40, file_index);
4667 SIVAL(pdata, 0x48, ea_size);
4668 SIVAL(pdata, 0x4C, access_mask);
4669 SBVAL(pdata, 0x50, pos);
4670 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4671 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4673 pdata += 0x60;
4675 len = srvstr_push(dstart, flags2,
4676 pdata+4, dos_fname,
4677 PTR_DIFF(dend, pdata+4),
4678 STR_UNICODE);
4679 SIVAL(pdata,0,len);
4680 pdata += 4 + len;
4681 data_size = PTR_DIFF(pdata,(*ppdata));
4682 break;
4684 case SMB_FILE_INTERNAL_INFORMATION:
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4687 SBVAL(pdata, 0, file_index);
4688 data_size = 8;
4689 break;
4691 case SMB_FILE_ACCESS_INFORMATION:
4692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4693 SIVAL(pdata, 0, access_mask);
4694 data_size = 4;
4695 break;
4697 case SMB_FILE_NAME_INFORMATION:
4698 /* Pathname with leading '\'. */
4700 size_t byte_len;
4701 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4703 SIVAL(pdata,0,byte_len);
4704 data_size = 4 + byte_len;
4705 break;
4708 case SMB_FILE_DISPOSITION_INFORMATION:
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4710 data_size = 1;
4711 SCVAL(pdata,0,delete_pending);
4712 break;
4714 case SMB_FILE_POSITION_INFORMATION:
4715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4716 data_size = 8;
4717 SOFF_T(pdata,0,pos);
4718 break;
4720 case SMB_FILE_MODE_INFORMATION:
4721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4722 SIVAL(pdata,0,mode);
4723 data_size = 4;
4724 break;
4726 case SMB_FILE_ALIGNMENT_INFORMATION:
4727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4728 SIVAL(pdata,0,0); /* No alignment needed. */
4729 data_size = 4;
4730 break;
4733 * NT4 server just returns "invalid query" to this - if we try
4734 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4735 * want this. JRA.
4737 /* The first statement above is false - verified using Thursby
4738 * client against NT4 -- gcolley.
4740 case SMB_QUERY_FILE_STREAM_INFO:
4741 case SMB_FILE_STREAM_INFORMATION: {
4742 unsigned int num_streams = 0;
4743 struct stream_struct *streams = NULL;
4745 DEBUG(10,("smbd_do_qfilepathinfo: "
4746 "SMB_FILE_STREAM_INFORMATION\n"));
4748 if (is_ntfs_stream_smb_fname(smb_fname)) {
4749 return NT_STATUS_INVALID_PARAMETER;
4752 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4753 talloc_tos(), &num_streams, &streams);
4755 if (!NT_STATUS_IS_OK(status)) {
4756 DEBUG(10, ("could not get stream info: %s\n",
4757 nt_errstr(status)));
4758 return status;
4761 status = marshall_stream_info(num_streams, streams,
4762 pdata, max_data_bytes,
4763 &data_size);
4765 if (!NT_STATUS_IS_OK(status)) {
4766 DEBUG(10, ("marshall_stream_info failed: %s\n",
4767 nt_errstr(status)));
4768 return status;
4771 TALLOC_FREE(streams);
4773 break;
4775 case SMB_QUERY_COMPRESSION_INFO:
4776 case SMB_FILE_COMPRESSION_INFORMATION:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4778 SOFF_T(pdata,0,file_size);
4779 SIVAL(pdata,8,0); /* ??? */
4780 SIVAL(pdata,12,0); /* ??? */
4781 data_size = 16;
4782 break;
4784 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4785 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4786 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4787 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4788 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4789 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4790 SOFF_T(pdata,32,allocation_size);
4791 SOFF_T(pdata,40,file_size);
4792 SIVAL(pdata,48,mode);
4793 SIVAL(pdata,52,0); /* ??? */
4794 data_size = 56;
4795 break;
4797 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4798 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4799 SIVAL(pdata,0,mode);
4800 SIVAL(pdata,4,0);
4801 data_size = 8;
4802 break;
4805 * CIFS UNIX Extensions.
4808 case SMB_QUERY_FILE_UNIX_BASIC:
4810 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4811 data_size = PTR_DIFF(pdata,(*ppdata));
4813 DEBUG(4,("smbd_do_qfilepathinfo: "
4814 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4815 dump_data(4, (uint8_t *)(*ppdata), data_size);
4817 break;
4819 case SMB_QUERY_FILE_UNIX_INFO2:
4821 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4822 data_size = PTR_DIFF(pdata,(*ppdata));
4825 int i;
4826 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4828 for (i=0; i<100; i++)
4829 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4830 DEBUG(4,("\n"));
4833 break;
4835 case SMB_QUERY_FILE_UNIX_LINK:
4837 int len;
4838 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4840 if (!buffer) {
4841 return NT_STATUS_NO_MEMORY;
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4845 #ifdef S_ISLNK
4846 if(!S_ISLNK(psbuf->st_ex_mode)) {
4847 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4849 #else
4850 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4851 #endif
4852 len = SMB_VFS_READLINK(conn,
4853 smb_fname->base_name,
4854 buffer, PATH_MAX);
4855 if (len == -1) {
4856 return map_nt_error_from_unix(errno);
4858 buffer[len] = 0;
4859 len = srvstr_push(dstart, flags2,
4860 pdata, buffer,
4861 PTR_DIFF(dend, pdata),
4862 STR_TERMINATE);
4863 pdata += len;
4864 data_size = PTR_DIFF(pdata,(*ppdata));
4866 break;
4869 #if defined(HAVE_POSIX_ACLS)
4870 case SMB_QUERY_POSIX_ACL:
4872 SMB_ACL_T file_acl = NULL;
4873 SMB_ACL_T def_acl = NULL;
4874 uint16 num_file_acls = 0;
4875 uint16 num_def_acls = 0;
4877 if (fsp && fsp->fh->fd != -1) {
4878 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4879 } else {
4880 file_acl =
4881 SMB_VFS_SYS_ACL_GET_FILE(conn,
4882 smb_fname->base_name,
4883 SMB_ACL_TYPE_ACCESS);
4886 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4887 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4888 "not implemented on "
4889 "filesystem containing %s\n",
4890 smb_fname->base_name));
4891 return NT_STATUS_NOT_IMPLEMENTED;
4894 if (S_ISDIR(psbuf->st_ex_mode)) {
4895 if (fsp && fsp->is_directory) {
4896 def_acl =
4897 SMB_VFS_SYS_ACL_GET_FILE(
4898 conn,
4899 fsp->fsp_name->base_name,
4900 SMB_ACL_TYPE_DEFAULT);
4901 } else {
4902 def_acl =
4903 SMB_VFS_SYS_ACL_GET_FILE(
4904 conn,
4905 smb_fname->base_name,
4906 SMB_ACL_TYPE_DEFAULT);
4908 def_acl = free_empty_sys_acl(conn, def_acl);
4911 num_file_acls = count_acl_entries(conn, file_acl);
4912 num_def_acls = count_acl_entries(conn, def_acl);
4914 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4915 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4916 data_size,
4917 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4918 SMB_POSIX_ACL_HEADER_SIZE) ));
4919 if (file_acl) {
4920 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4922 if (def_acl) {
4923 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4925 return NT_STATUS_BUFFER_TOO_SMALL;
4928 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4929 SSVAL(pdata,2,num_file_acls);
4930 SSVAL(pdata,4,num_def_acls);
4931 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4932 if (file_acl) {
4933 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4935 if (def_acl) {
4936 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4938 return NT_STATUS_INTERNAL_ERROR;
4940 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4941 if (file_acl) {
4942 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4944 if (def_acl) {
4945 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4947 return NT_STATUS_INTERNAL_ERROR;
4950 if (file_acl) {
4951 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4953 if (def_acl) {
4954 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4956 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4957 break;
4959 #endif
4962 case SMB_QUERY_POSIX_LOCK:
4964 uint64_t count;
4965 uint64_t offset;
4966 uint64_t smblctx;
4967 enum brl_type lock_type;
4969 /* We need an open file with a real fd for this. */
4970 if (!fsp || fsp->fh->fd == -1) {
4971 return NT_STATUS_INVALID_LEVEL;
4974 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4975 return NT_STATUS_INVALID_PARAMETER;
4978 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4979 case POSIX_LOCK_TYPE_READ:
4980 lock_type = READ_LOCK;
4981 break;
4982 case POSIX_LOCK_TYPE_WRITE:
4983 lock_type = WRITE_LOCK;
4984 break;
4985 case POSIX_LOCK_TYPE_UNLOCK:
4986 default:
4987 /* There's no point in asking for an unlock... */
4988 return NT_STATUS_INVALID_PARAMETER;
4991 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4992 #if defined(HAVE_LONGLONG)
4993 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4994 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4995 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4996 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4997 #else /* HAVE_LONGLONG */
4998 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4999 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5000 #endif /* HAVE_LONGLONG */
5002 status = query_lock(fsp,
5003 &smblctx,
5004 &count,
5005 &offset,
5006 &lock_type,
5007 POSIX_LOCK);
5009 if (ERROR_WAS_LOCK_DENIED(status)) {
5010 /* Here we need to report who has it locked... */
5011 data_size = POSIX_LOCK_DATA_SIZE;
5013 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5014 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5015 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5016 #if defined(HAVE_LONGLONG)
5017 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5018 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5019 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5020 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5021 #else /* HAVE_LONGLONG */
5022 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5023 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5024 #endif /* HAVE_LONGLONG */
5026 } else if (NT_STATUS_IS_OK(status)) {
5027 /* For success we just return a copy of what we sent
5028 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5029 data_size = POSIX_LOCK_DATA_SIZE;
5030 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5031 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5032 } else {
5033 return status;
5035 break;
5038 default:
5039 return NT_STATUS_INVALID_LEVEL;
5042 *pdata_size = data_size;
5043 return NT_STATUS_OK;
5046 /****************************************************************************
5047 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5048 file name or file id).
5049 ****************************************************************************/
5051 static void call_trans2qfilepathinfo(connection_struct *conn,
5052 struct smb_request *req,
5053 unsigned int tran_call,
5054 char **pparams, int total_params,
5055 char **ppdata, int total_data,
5056 unsigned int max_data_bytes)
5058 char *params = *pparams;
5059 char *pdata = *ppdata;
5060 uint16 info_level;
5061 unsigned int data_size = 0;
5062 unsigned int param_size = 2;
5063 struct smb_filename *smb_fname = NULL;
5064 bool delete_pending = False;
5065 struct timespec write_time_ts;
5066 files_struct *fsp = NULL;
5067 struct file_id fileid;
5068 struct ea_list *ea_list = NULL;
5069 int lock_data_count = 0;
5070 char *lock_data = NULL;
5071 NTSTATUS status = NT_STATUS_OK;
5073 if (!params) {
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5075 return;
5078 ZERO_STRUCT(write_time_ts);
5080 if (tran_call == TRANSACT2_QFILEINFO) {
5081 if (total_params < 4) {
5082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5083 return;
5086 if (IS_IPC(conn)) {
5087 call_trans2qpipeinfo(conn, req, tran_call,
5088 pparams, total_params,
5089 ppdata, total_data,
5090 max_data_bytes);
5091 return;
5094 fsp = file_fsp(req, SVAL(params,0));
5095 info_level = SVAL(params,2);
5097 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5099 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5100 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5101 return;
5104 /* Initial check for valid fsp ptr. */
5105 if (!check_fsp_open(conn, req, fsp)) {
5106 return;
5109 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5110 &smb_fname);
5111 if (!NT_STATUS_IS_OK(status)) {
5112 reply_nterror(req, status);
5113 return;
5116 if(fsp->fake_file_handle) {
5118 * This is actually for the QUOTA_FAKE_FILE --metze
5121 /* We know this name is ok, it's already passed the checks. */
5123 } else if(fsp->fh->fd == -1) {
5125 * This is actually a QFILEINFO on a directory
5126 * handle (returned from an NT SMB). NT5.0 seems
5127 * to do this call. JRA.
5130 if (INFO_LEVEL_IS_UNIX(info_level)) {
5131 /* Always do lstat for UNIX calls. */
5132 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5133 DEBUG(3,("call_trans2qfilepathinfo: "
5134 "SMB_VFS_LSTAT of %s failed "
5135 "(%s)\n",
5136 smb_fname_str_dbg(smb_fname),
5137 strerror(errno)));
5138 reply_nterror(req,
5139 map_nt_error_from_unix(errno));
5140 return;
5142 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5143 DEBUG(3,("call_trans2qfilepathinfo: "
5144 "SMB_VFS_STAT of %s failed (%s)\n",
5145 smb_fname_str_dbg(smb_fname),
5146 strerror(errno)));
5147 reply_nterror(req,
5148 map_nt_error_from_unix(errno));
5149 return;
5152 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5153 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5154 } else {
5156 * Original code - this is an open file.
5158 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5159 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5160 fsp->fnum, strerror(errno)));
5161 reply_nterror(req,
5162 map_nt_error_from_unix(errno));
5163 return;
5165 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5166 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5169 } else {
5170 uint32_t name_hash;
5171 char *fname = NULL;
5172 uint32_t ucf_flags = 0;
5174 /* qpathinfo */
5175 if (total_params < 7) {
5176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5177 return;
5180 info_level = SVAL(params,0);
5182 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5184 if (INFO_LEVEL_IS_UNIX(info_level)) {
5185 if (!lp_unix_extensions()) {
5186 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5187 return;
5189 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5190 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5191 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5192 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5196 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5197 total_params - 6,
5198 STR_TERMINATE, &status);
5199 if (!NT_STATUS_IS_OK(status)) {
5200 reply_nterror(req, status);
5201 return;
5204 status = filename_convert(req,
5205 conn,
5206 req->flags2 & FLAGS2_DFS_PATHNAMES,
5207 fname,
5208 ucf_flags,
5209 NULL,
5210 &smb_fname);
5211 if (!NT_STATUS_IS_OK(status)) {
5212 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5213 reply_botherror(req,
5214 NT_STATUS_PATH_NOT_COVERED,
5215 ERRSRV, ERRbadpath);
5216 return;
5218 reply_nterror(req, status);
5219 return;
5222 /* If this is a stream, check if there is a delete_pending. */
5223 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5224 && is_ntfs_stream_smb_fname(smb_fname)) {
5225 struct smb_filename *smb_fname_base = NULL;
5227 /* Create an smb_filename with stream_name == NULL. */
5228 status =
5229 create_synthetic_smb_fname(talloc_tos(),
5230 smb_fname->base_name,
5231 NULL, NULL,
5232 &smb_fname_base);
5233 if (!NT_STATUS_IS_OK(status)) {
5234 reply_nterror(req, status);
5235 return;
5238 if (INFO_LEVEL_IS_UNIX(info_level)) {
5239 /* Always do lstat for UNIX calls. */
5240 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5241 DEBUG(3,("call_trans2qfilepathinfo: "
5242 "SMB_VFS_LSTAT of %s failed "
5243 "(%s)\n",
5244 smb_fname_str_dbg(smb_fname_base),
5245 strerror(errno)));
5246 TALLOC_FREE(smb_fname_base);
5247 reply_nterror(req,
5248 map_nt_error_from_unix(errno));
5249 return;
5251 } else {
5252 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5253 DEBUG(3,("call_trans2qfilepathinfo: "
5254 "fileinfo of %s failed "
5255 "(%s)\n",
5256 smb_fname_str_dbg(smb_fname_base),
5257 strerror(errno)));
5258 TALLOC_FREE(smb_fname_base);
5259 reply_nterror(req,
5260 map_nt_error_from_unix(errno));
5261 return;
5265 status = file_name_hash(conn,
5266 smb_fname_str_dbg(smb_fname_base),
5267 &name_hash);
5268 if (!NT_STATUS_IS_OK(status)) {
5269 TALLOC_FREE(smb_fname_base);
5270 reply_nterror(req, status);
5271 return;
5274 fileid = vfs_file_id_from_sbuf(conn,
5275 &smb_fname_base->st);
5276 TALLOC_FREE(smb_fname_base);
5277 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5278 if (delete_pending) {
5279 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5280 return;
5284 if (INFO_LEVEL_IS_UNIX(info_level)) {
5285 /* Always do lstat for UNIX calls. */
5286 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5287 DEBUG(3,("call_trans2qfilepathinfo: "
5288 "SMB_VFS_LSTAT of %s failed (%s)\n",
5289 smb_fname_str_dbg(smb_fname),
5290 strerror(errno)));
5291 reply_nterror(req,
5292 map_nt_error_from_unix(errno));
5293 return;
5296 } else {
5297 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "SMB_VFS_STAT of %s failed (%s)\n",
5300 smb_fname_str_dbg(smb_fname),
5301 strerror(errno)));
5302 reply_nterror(req,
5303 map_nt_error_from_unix(errno));
5304 return;
5308 status = file_name_hash(conn,
5309 smb_fname_str_dbg(smb_fname),
5310 &name_hash);
5311 if (!NT_STATUS_IS_OK(status)) {
5312 reply_nterror(req, status);
5313 return;
5316 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5317 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5318 if (delete_pending) {
5319 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5320 return;
5324 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5325 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5326 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5328 /* Pull out any data sent here before we realloc. */
5329 switch (info_level) {
5330 case SMB_INFO_QUERY_EAS_FROM_LIST:
5332 /* Pull any EA list from the data portion. */
5333 uint32 ea_size;
5335 if (total_data < 4) {
5336 reply_nterror(
5337 req, NT_STATUS_INVALID_PARAMETER);
5338 return;
5340 ea_size = IVAL(pdata,0);
5342 if (total_data > 0 && ea_size != total_data) {
5343 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5344 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5345 reply_nterror(
5346 req, NT_STATUS_INVALID_PARAMETER);
5347 return;
5350 if (!lp_ea_support(SNUM(conn))) {
5351 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5352 return;
5355 /* Pull out the list of names. */
5356 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5357 if (!ea_list) {
5358 reply_nterror(
5359 req, NT_STATUS_INVALID_PARAMETER);
5360 return;
5362 break;
5365 case SMB_QUERY_POSIX_LOCK:
5367 if (fsp == NULL || fsp->fh->fd == -1) {
5368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5369 return;
5372 if (total_data != POSIX_LOCK_DATA_SIZE) {
5373 reply_nterror(
5374 req, NT_STATUS_INVALID_PARAMETER);
5375 return;
5378 /* Copy the lock range data. */
5379 lock_data = (char *)talloc_memdup(
5380 req, pdata, total_data);
5381 if (!lock_data) {
5382 reply_nterror(req, NT_STATUS_NO_MEMORY);
5383 return;
5385 lock_data_count = total_data;
5387 default:
5388 break;
5391 *pparams = (char *)SMB_REALLOC(*pparams,2);
5392 if (*pparams == NULL) {
5393 reply_nterror(req, NT_STATUS_NO_MEMORY);
5394 return;
5396 params = *pparams;
5397 SSVAL(params,0,0);
5400 * draft-leach-cifs-v1-spec-02.txt
5401 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5402 * says:
5404 * The requested information is placed in the Data portion of the
5405 * transaction response. For the information levels greater than 0x100,
5406 * the transaction response has 1 parameter word which should be
5407 * ignored by the client.
5409 * However Windows only follows this rule for the IS_NAME_VALID call.
5411 switch (info_level) {
5412 case SMB_INFO_IS_NAME_VALID:
5413 param_size = 0;
5414 break;
5417 if ((info_level & 0xFF00) == 0xFF00) {
5419 * We use levels that start with 0xFF00
5420 * internally to represent SMB2 specific levels
5422 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5423 return;
5426 status = smbd_do_qfilepathinfo(conn, req, info_level,
5427 fsp, smb_fname,
5428 delete_pending, write_time_ts,
5429 ea_list,
5430 lock_data_count, lock_data,
5431 req->flags2, max_data_bytes,
5432 ppdata, &data_size);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 reply_nterror(req, status);
5435 return;
5438 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5439 max_data_bytes);
5441 return;
5444 /****************************************************************************
5445 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5446 code.
5447 ****************************************************************************/
5449 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5450 connection_struct *conn,
5451 struct smb_request *req,
5452 bool overwrite_if_exists,
5453 const struct smb_filename *smb_fname_old,
5454 struct smb_filename *smb_fname_new)
5456 NTSTATUS status = NT_STATUS_OK;
5458 /* source must already exist. */
5459 if (!VALID_STAT(smb_fname_old->st)) {
5460 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5463 if (VALID_STAT(smb_fname_new->st)) {
5464 if (overwrite_if_exists) {
5465 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5466 return NT_STATUS_FILE_IS_A_DIRECTORY;
5468 status = unlink_internals(conn,
5469 req,
5470 FILE_ATTRIBUTE_NORMAL,
5471 smb_fname_new,
5472 false);
5473 if (!NT_STATUS_IS_OK(status)) {
5474 return status;
5476 } else {
5477 /* Disallow if newname already exists. */
5478 return NT_STATUS_OBJECT_NAME_COLLISION;
5482 /* No links from a directory. */
5483 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5484 return NT_STATUS_FILE_IS_A_DIRECTORY;
5487 /* Setting a hardlink to/from a stream isn't currently supported. */
5488 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5489 is_ntfs_stream_smb_fname(smb_fname_new)) {
5490 return NT_STATUS_INVALID_PARAMETER;
5493 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5494 smb_fname_old->base_name, smb_fname_new->base_name));
5496 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5497 smb_fname_new->base_name) != 0) {
5498 status = map_nt_error_from_unix(errno);
5499 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5500 nt_errstr(status), smb_fname_old->base_name,
5501 smb_fname_new->base_name));
5503 return status;
5506 /****************************************************************************
5507 Deal with setting the time from any of the setfilepathinfo functions.
5508 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5509 calling this function.
5510 ****************************************************************************/
5512 NTSTATUS smb_set_file_time(connection_struct *conn,
5513 files_struct *fsp,
5514 const struct smb_filename *smb_fname,
5515 struct smb_file_time *ft,
5516 bool setting_write_time)
5518 struct smb_filename smb_fname_base;
5519 uint32 action =
5520 FILE_NOTIFY_CHANGE_LAST_ACCESS
5521 |FILE_NOTIFY_CHANGE_LAST_WRITE
5522 |FILE_NOTIFY_CHANGE_CREATION;
5524 if (!VALID_STAT(smb_fname->st)) {
5525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5528 /* get some defaults (no modifications) if any info is zero or -1. */
5529 if (null_timespec(ft->create_time)) {
5530 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5533 if (null_timespec(ft->atime)) {
5534 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5537 if (null_timespec(ft->mtime)) {
5538 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5541 if (!setting_write_time) {
5542 /* ft->mtime comes from change time, not write time. */
5543 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5546 /* Ensure the resolution is the correct for
5547 * what we can store on this filesystem. */
5549 round_timespec(conn->ts_res, &ft->create_time);
5550 round_timespec(conn->ts_res, &ft->ctime);
5551 round_timespec(conn->ts_res, &ft->atime);
5552 round_timespec(conn->ts_res, &ft->mtime);
5554 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5555 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5556 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5557 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5558 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5560 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5561 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5563 if (setting_write_time) {
5565 * This was a Windows setfileinfo on an open file.
5566 * NT does this a lot. We also need to
5567 * set the time here, as it can be read by
5568 * FindFirst/FindNext and with the patch for bug #2045
5569 * in smbd/fileio.c it ensures that this timestamp is
5570 * kept sticky even after a write. We save the request
5571 * away and will set it on file close and after a write. JRA.
5574 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5575 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5577 if (fsp != NULL) {
5578 if (fsp->base_fsp) {
5579 set_sticky_write_time_fsp(fsp->base_fsp,
5580 ft->mtime);
5581 } else {
5582 set_sticky_write_time_fsp(fsp, ft->mtime);
5584 } else {
5585 set_sticky_write_time_path(
5586 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5587 ft->mtime);
5591 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5593 /* Always call ntimes on the base, even if a stream was passed in. */
5594 smb_fname_base = *smb_fname;
5595 smb_fname_base.stream_name = NULL;
5597 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5598 return map_nt_error_from_unix(errno);
5601 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5602 smb_fname->base_name);
5603 return NT_STATUS_OK;
5606 /****************************************************************************
5607 Deal with setting the dosmode from any of the setfilepathinfo functions.
5608 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5609 done before calling this function.
5610 ****************************************************************************/
5612 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5613 const struct smb_filename *smb_fname,
5614 uint32 dosmode)
5616 struct smb_filename *smb_fname_base = NULL;
5617 NTSTATUS status;
5619 if (!VALID_STAT(smb_fname->st)) {
5620 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5623 /* Always operate on the base_name, even if a stream was passed in. */
5624 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5625 NULL, &smb_fname->st,
5626 &smb_fname_base);
5627 if (!NT_STATUS_IS_OK(status)) {
5628 return status;
5631 if (dosmode) {
5632 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5633 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5634 } else {
5635 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5639 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5641 /* check the mode isn't different, before changing it */
5642 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5643 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5644 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5645 (unsigned int)dosmode));
5647 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5648 false)) {
5649 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5650 "%s failed (%s)\n",
5651 smb_fname_str_dbg(smb_fname_base),
5652 strerror(errno)));
5653 status = map_nt_error_from_unix(errno);
5654 goto out;
5657 status = NT_STATUS_OK;
5658 out:
5659 TALLOC_FREE(smb_fname_base);
5660 return status;
5663 /****************************************************************************
5664 Deal with setting the size from any of the setfilepathinfo functions.
5665 ****************************************************************************/
5667 static NTSTATUS smb_set_file_size(connection_struct *conn,
5668 struct smb_request *req,
5669 files_struct *fsp,
5670 const struct smb_filename *smb_fname,
5671 const SMB_STRUCT_STAT *psbuf,
5672 off_t size,
5673 bool fail_after_createfile)
5675 NTSTATUS status = NT_STATUS_OK;
5676 struct smb_filename *smb_fname_tmp = NULL;
5677 files_struct *new_fsp = NULL;
5679 if (!VALID_STAT(*psbuf)) {
5680 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5683 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5685 if (size == get_file_size_stat(psbuf)) {
5686 return NT_STATUS_OK;
5689 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5690 smb_fname_str_dbg(smb_fname), (double)size));
5692 if (fsp && fsp->fh->fd != -1) {
5693 /* Handle based call. */
5694 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5695 return NT_STATUS_ACCESS_DENIED;
5698 if (vfs_set_filelen(fsp, size) == -1) {
5699 return map_nt_error_from_unix(errno);
5701 trigger_write_time_update_immediate(fsp);
5702 return NT_STATUS_OK;
5705 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5706 if (!NT_STATUS_IS_OK(status)) {
5707 return status;
5710 smb_fname_tmp->st = *psbuf;
5712 status = SMB_VFS_CREATE_FILE(
5713 conn, /* conn */
5714 req, /* req */
5715 0, /* root_dir_fid */
5716 smb_fname_tmp, /* fname */
5717 FILE_WRITE_DATA, /* access_mask */
5718 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5719 FILE_SHARE_DELETE),
5720 FILE_OPEN, /* create_disposition*/
5721 0, /* create_options */
5722 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5723 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5724 0, /* allocation_size */
5725 0, /* private_flags */
5726 NULL, /* sd */
5727 NULL, /* ea_list */
5728 &new_fsp, /* result */
5729 NULL); /* pinfo */
5731 TALLOC_FREE(smb_fname_tmp);
5733 if (!NT_STATUS_IS_OK(status)) {
5734 /* NB. We check for open_was_deferred in the caller. */
5735 return status;
5738 /* See RAW-SFILEINFO-END-OF-FILE */
5739 if (fail_after_createfile) {
5740 close_file(req, new_fsp,NORMAL_CLOSE);
5741 return NT_STATUS_INVALID_LEVEL;
5744 if (vfs_set_filelen(new_fsp, size) == -1) {
5745 status = map_nt_error_from_unix(errno);
5746 close_file(req, new_fsp,NORMAL_CLOSE);
5747 return status;
5750 trigger_write_time_update_immediate(new_fsp);
5751 close_file(req, new_fsp,NORMAL_CLOSE);
5752 return NT_STATUS_OK;
5755 /****************************************************************************
5756 Deal with SMB_INFO_SET_EA.
5757 ****************************************************************************/
5759 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5760 const char *pdata,
5761 int total_data,
5762 files_struct *fsp,
5763 const struct smb_filename *smb_fname)
5765 struct ea_list *ea_list = NULL;
5766 TALLOC_CTX *ctx = NULL;
5767 NTSTATUS status = NT_STATUS_OK;
5769 if (total_data < 10) {
5771 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5772 length. They seem to have no effect. Bug #3212. JRA */
5774 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5775 /* We're done. We only get EA info in this call. */
5776 return NT_STATUS_OK;
5779 return NT_STATUS_INVALID_PARAMETER;
5782 if (IVAL(pdata,0) > total_data) {
5783 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5784 IVAL(pdata,0), (unsigned int)total_data));
5785 return NT_STATUS_INVALID_PARAMETER;
5788 ctx = talloc_tos();
5789 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5790 if (!ea_list) {
5791 return NT_STATUS_INVALID_PARAMETER;
5794 status = set_ea(conn, fsp, smb_fname, ea_list);
5796 return status;
5799 /****************************************************************************
5800 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5801 ****************************************************************************/
5803 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5804 const char *pdata,
5805 int total_data,
5806 files_struct *fsp)
5808 struct ea_list *ea_list = NULL;
5809 NTSTATUS status;
5811 if (!fsp) {
5812 return NT_STATUS_INVALID_HANDLE;
5815 if (!lp_ea_support(SNUM(conn))) {
5816 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5817 "EA's not supported.\n",
5818 (unsigned int)total_data));
5819 return NT_STATUS_EAS_NOT_SUPPORTED;
5822 if (total_data < 10) {
5823 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5824 "too small.\n",
5825 (unsigned int)total_data));
5826 return NT_STATUS_INVALID_PARAMETER;
5829 ea_list = read_nttrans_ea_list(talloc_tos(),
5830 pdata,
5831 total_data);
5833 if (!ea_list) {
5834 return NT_STATUS_INVALID_PARAMETER;
5837 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5839 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5840 smb_fname_str_dbg(fsp->fsp_name),
5841 nt_errstr(status) ));
5843 return status;
5847 /****************************************************************************
5848 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5849 ****************************************************************************/
5851 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5852 const char *pdata,
5853 int total_data,
5854 files_struct *fsp,
5855 struct smb_filename *smb_fname)
5857 NTSTATUS status = NT_STATUS_OK;
5858 bool delete_on_close;
5859 uint32 dosmode = 0;
5861 if (total_data < 1) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 if (fsp == NULL) {
5866 return NT_STATUS_INVALID_HANDLE;
5869 delete_on_close = (CVAL(pdata,0) ? True : False);
5870 dosmode = dos_mode(conn, smb_fname);
5872 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5873 "delete_on_close = %u\n",
5874 smb_fname_str_dbg(smb_fname),
5875 (unsigned int)dosmode,
5876 (unsigned int)delete_on_close ));
5878 if (delete_on_close) {
5879 status = can_set_delete_on_close(fsp, dosmode);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 return status;
5885 /* The set is across all open files on this dev/inode pair. */
5886 if (!set_delete_on_close(fsp, delete_on_close,
5887 conn->session_info->security_token,
5888 conn->session_info->unix_token)) {
5889 return NT_STATUS_ACCESS_DENIED;
5891 return NT_STATUS_OK;
5894 /****************************************************************************
5895 Deal with SMB_FILE_POSITION_INFORMATION.
5896 ****************************************************************************/
5898 static NTSTATUS smb_file_position_information(connection_struct *conn,
5899 const char *pdata,
5900 int total_data,
5901 files_struct *fsp)
5903 uint64_t position_information;
5905 if (total_data < 8) {
5906 return NT_STATUS_INVALID_PARAMETER;
5909 if (fsp == NULL) {
5910 /* Ignore on pathname based set. */
5911 return NT_STATUS_OK;
5914 position_information = (uint64_t)IVAL(pdata,0);
5915 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5917 DEBUG(10,("smb_file_position_information: Set file position "
5918 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5919 (double)position_information));
5920 fsp->fh->position_information = position_information;
5921 return NT_STATUS_OK;
5924 /****************************************************************************
5925 Deal with SMB_FILE_MODE_INFORMATION.
5926 ****************************************************************************/
5928 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5929 const char *pdata,
5930 int total_data)
5932 uint32 mode;
5934 if (total_data < 4) {
5935 return NT_STATUS_INVALID_PARAMETER;
5937 mode = IVAL(pdata,0);
5938 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5939 return NT_STATUS_INVALID_PARAMETER;
5941 return NT_STATUS_OK;
5944 /****************************************************************************
5945 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5946 ****************************************************************************/
5948 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5949 struct smb_request *req,
5950 const char *pdata,
5951 int total_data,
5952 const struct smb_filename *smb_fname)
5954 char *link_target = NULL;
5955 const char *newname = smb_fname->base_name;
5956 TALLOC_CTX *ctx = talloc_tos();
5958 /* Set a symbolic link. */
5959 /* Don't allow this if follow links is false. */
5961 if (total_data == 0) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 if (!lp_symlinks(SNUM(conn))) {
5966 return NT_STATUS_ACCESS_DENIED;
5969 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5970 total_data, STR_TERMINATE);
5972 if (!link_target) {
5973 return NT_STATUS_INVALID_PARAMETER;
5976 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5977 newname, link_target ));
5979 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5980 return map_nt_error_from_unix(errno);
5983 return NT_STATUS_OK;
5986 /****************************************************************************
5987 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5988 ****************************************************************************/
5990 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5991 struct smb_request *req,
5992 const char *pdata, int total_data,
5993 struct smb_filename *smb_fname_new)
5995 char *oldname = NULL;
5996 struct smb_filename *smb_fname_old = NULL;
5997 TALLOC_CTX *ctx = talloc_tos();
5998 NTSTATUS status = NT_STATUS_OK;
6000 /* Set a hard link. */
6001 if (total_data == 0) {
6002 return NT_STATUS_INVALID_PARAMETER;
6005 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6006 total_data, STR_TERMINATE, &status);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 return status;
6011 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6012 smb_fname_str_dbg(smb_fname_new), oldname));
6014 status = filename_convert(ctx,
6015 conn,
6016 req->flags2 & FLAGS2_DFS_PATHNAMES,
6017 oldname,
6019 NULL,
6020 &smb_fname_old);
6021 if (!NT_STATUS_IS_OK(status)) {
6022 return status;
6025 return hardlink_internals(ctx, conn, req, false,
6026 smb_fname_old, smb_fname_new);
6029 /****************************************************************************
6030 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6031 ****************************************************************************/
6033 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6034 struct smb_request *req,
6035 const char *pdata,
6036 int total_data,
6037 files_struct *fsp,
6038 struct smb_filename *smb_fname_src)
6040 bool overwrite;
6041 uint32_t len;
6042 char *newname = NULL;
6043 struct smb_filename *smb_fname_dst = NULL;
6044 NTSTATUS status = NT_STATUS_OK;
6045 TALLOC_CTX *ctx = talloc_tos();
6047 if (!fsp) {
6048 return NT_STATUS_INVALID_HANDLE;
6051 if (total_data < 20) {
6052 return NT_STATUS_INVALID_PARAMETER;
6055 overwrite = (CVAL(pdata,0) ? True : False);
6056 len = IVAL(pdata,16);
6058 if (len > (total_data - 20) || (len == 0)) {
6059 return NT_STATUS_INVALID_PARAMETER;
6062 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6063 &pdata[20], len, STR_TERMINATE,
6064 &status);
6065 if (!NT_STATUS_IS_OK(status)) {
6066 return status;
6069 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6070 newname));
6072 status = filename_convert(ctx,
6073 conn,
6074 req->flags2 & FLAGS2_DFS_PATHNAMES,
6075 newname,
6076 UCF_SAVE_LCOMP,
6077 NULL,
6078 &smb_fname_dst);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 return status;
6083 if (fsp->base_fsp) {
6084 /* newname must be a stream name. */
6085 if (newname[0] != ':') {
6086 return NT_STATUS_NOT_SUPPORTED;
6089 /* Create an smb_fname to call rename_internals_fsp() with. */
6090 status = create_synthetic_smb_fname(talloc_tos(),
6091 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6092 &smb_fname_dst);
6093 if (!NT_STATUS_IS_OK(status)) {
6094 goto out;
6098 * Set the original last component, since
6099 * rename_internals_fsp() requires it.
6101 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6102 newname);
6103 if (smb_fname_dst->original_lcomp == NULL) {
6104 status = NT_STATUS_NO_MEMORY;
6105 goto out;
6110 DEBUG(10,("smb2_file_rename_information: "
6111 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6112 fsp->fnum, fsp_str_dbg(fsp),
6113 smb_fname_str_dbg(smb_fname_dst)));
6114 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6115 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6116 overwrite);
6118 out:
6119 TALLOC_FREE(smb_fname_dst);
6120 return status;
6123 static NTSTATUS smb_file_link_information(connection_struct *conn,
6124 struct smb_request *req,
6125 const char *pdata,
6126 int total_data,
6127 files_struct *fsp,
6128 struct smb_filename *smb_fname_src)
6130 bool overwrite;
6131 uint32_t len;
6132 char *newname = NULL;
6133 struct smb_filename *smb_fname_dst = NULL;
6134 NTSTATUS status = NT_STATUS_OK;
6135 TALLOC_CTX *ctx = talloc_tos();
6137 if (!fsp) {
6138 return NT_STATUS_INVALID_HANDLE;
6141 if (total_data < 20) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 overwrite = (CVAL(pdata,0) ? true : false);
6146 len = IVAL(pdata,16);
6148 if (len > (total_data - 20) || (len == 0)) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6153 &pdata[20], len, STR_TERMINATE,
6154 &status);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 return status;
6159 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6160 newname));
6162 status = filename_convert(ctx,
6163 conn,
6164 req->flags2 & FLAGS2_DFS_PATHNAMES,
6165 newname,
6166 UCF_SAVE_LCOMP,
6167 NULL,
6168 &smb_fname_dst);
6169 if (!NT_STATUS_IS_OK(status)) {
6170 return status;
6173 if (fsp->base_fsp) {
6174 /* No stream names. */
6175 return NT_STATUS_NOT_SUPPORTED;
6178 DEBUG(10,("smb_file_link_information: "
6179 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6180 fsp->fnum, fsp_str_dbg(fsp),
6181 smb_fname_str_dbg(smb_fname_dst)));
6182 status = hardlink_internals(ctx,
6183 conn,
6184 req,
6185 overwrite,
6186 fsp->fsp_name,
6187 smb_fname_dst);
6189 TALLOC_FREE(smb_fname_dst);
6190 return status;
6193 /****************************************************************************
6194 Deal with SMB_FILE_RENAME_INFORMATION.
6195 ****************************************************************************/
6197 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6198 struct smb_request *req,
6199 const char *pdata,
6200 int total_data,
6201 files_struct *fsp,
6202 struct smb_filename *smb_fname_src)
6204 bool overwrite;
6205 uint32 root_fid;
6206 uint32 len;
6207 char *newname = NULL;
6208 struct smb_filename *smb_fname_dst = NULL;
6209 bool dest_has_wcard = False;
6210 NTSTATUS status = NT_STATUS_OK;
6211 char *p;
6212 TALLOC_CTX *ctx = talloc_tos();
6214 if (total_data < 13) {
6215 return NT_STATUS_INVALID_PARAMETER;
6218 overwrite = (CVAL(pdata,0) ? True : False);
6219 root_fid = IVAL(pdata,4);
6220 len = IVAL(pdata,8);
6222 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6223 return NT_STATUS_INVALID_PARAMETER;
6226 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6227 len, 0, &status,
6228 &dest_has_wcard);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 return status;
6233 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6234 newname));
6236 status = resolve_dfspath_wcard(ctx, conn,
6237 req->flags2 & FLAGS2_DFS_PATHNAMES,
6238 newname,
6239 true,
6240 !conn->sconn->using_smb2,
6241 &newname,
6242 &dest_has_wcard);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 return status;
6247 /* Check the new name has no '/' characters. */
6248 if (strchr_m(newname, '/')) {
6249 return NT_STATUS_NOT_SUPPORTED;
6252 if (fsp && fsp->base_fsp) {
6253 /* newname must be a stream name. */
6254 if (newname[0] != ':') {
6255 return NT_STATUS_NOT_SUPPORTED;
6258 /* Create an smb_fname to call rename_internals_fsp() with. */
6259 status = create_synthetic_smb_fname(talloc_tos(),
6260 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6261 &smb_fname_dst);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 goto out;
6267 * Set the original last component, since
6268 * rename_internals_fsp() requires it.
6270 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6271 newname);
6272 if (smb_fname_dst->original_lcomp == NULL) {
6273 status = NT_STATUS_NO_MEMORY;
6274 goto out;
6277 } else {
6279 * Build up an smb_fname_dst based on the filename passed in.
6280 * We basically just strip off the last component, and put on
6281 * the newname instead.
6283 char *base_name = NULL;
6285 /* newname must *not* be a stream name. */
6286 if (newname[0] == ':') {
6287 return NT_STATUS_NOT_SUPPORTED;
6291 * Strip off the last component (filename) of the path passed
6292 * in.
6294 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6295 if (!base_name) {
6296 return NT_STATUS_NO_MEMORY;
6298 p = strrchr_m(base_name, '/');
6299 if (p) {
6300 p[1] = '\0';
6301 } else {
6302 base_name = talloc_strdup(ctx, "");
6303 if (!base_name) {
6304 return NT_STATUS_NO_MEMORY;
6307 /* Append the new name. */
6308 base_name = talloc_asprintf_append(base_name,
6309 "%s",
6310 newname);
6311 if (!base_name) {
6312 return NT_STATUS_NO_MEMORY;
6315 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6316 (UCF_SAVE_LCOMP |
6317 (dest_has_wcard ?
6318 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6319 0)));
6321 /* If an error we expect this to be
6322 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6324 if (!NT_STATUS_IS_OK(status)) {
6325 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6326 status)) {
6327 goto out;
6329 /* Create an smb_fname to call rename_internals_fsp() */
6330 status = create_synthetic_smb_fname(ctx,
6331 base_name, NULL,
6332 NULL,
6333 &smb_fname_dst);
6334 if (!NT_STATUS_IS_OK(status)) {
6335 goto out;
6340 if (fsp) {
6341 DEBUG(10,("smb_file_rename_information: "
6342 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6343 fsp->fnum, fsp_str_dbg(fsp),
6344 smb_fname_str_dbg(smb_fname_dst)));
6345 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6346 overwrite);
6347 } else {
6348 DEBUG(10,("smb_file_rename_information: "
6349 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6350 smb_fname_str_dbg(smb_fname_src),
6351 smb_fname_str_dbg(smb_fname_dst)));
6352 status = rename_internals(ctx, conn, req, smb_fname_src,
6353 smb_fname_dst, 0, overwrite, false,
6354 dest_has_wcard,
6355 FILE_WRITE_ATTRIBUTES);
6357 out:
6358 TALLOC_FREE(smb_fname_dst);
6359 return status;
6362 /****************************************************************************
6363 Deal with SMB_SET_POSIX_ACL.
6364 ****************************************************************************/
6366 #if defined(HAVE_POSIX_ACLS)
6367 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6368 const char *pdata,
6369 int total_data,
6370 files_struct *fsp,
6371 const struct smb_filename *smb_fname)
6373 uint16 posix_acl_version;
6374 uint16 num_file_acls;
6375 uint16 num_def_acls;
6376 bool valid_file_acls = True;
6377 bool valid_def_acls = True;
6379 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6380 return NT_STATUS_INVALID_PARAMETER;
6382 posix_acl_version = SVAL(pdata,0);
6383 num_file_acls = SVAL(pdata,2);
6384 num_def_acls = SVAL(pdata,4);
6386 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6387 valid_file_acls = False;
6388 num_file_acls = 0;
6391 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6392 valid_def_acls = False;
6393 num_def_acls = 0;
6396 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6397 return NT_STATUS_INVALID_PARAMETER;
6400 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6401 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6402 return NT_STATUS_INVALID_PARAMETER;
6405 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6406 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6407 (unsigned int)num_file_acls,
6408 (unsigned int)num_def_acls));
6410 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6411 smb_fname->base_name, num_file_acls,
6412 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6413 return map_nt_error_from_unix(errno);
6416 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6417 smb_fname->base_name, &smb_fname->st, num_def_acls,
6418 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6419 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6420 return map_nt_error_from_unix(errno);
6422 return NT_STATUS_OK;
6424 #endif
6426 /****************************************************************************
6427 Deal with SMB_SET_POSIX_LOCK.
6428 ****************************************************************************/
6430 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6431 struct smb_request *req,
6432 const char *pdata,
6433 int total_data,
6434 files_struct *fsp)
6436 uint64_t count;
6437 uint64_t offset;
6438 uint64_t smblctx;
6439 bool blocking_lock = False;
6440 enum brl_type lock_type;
6442 NTSTATUS status = NT_STATUS_OK;
6444 if (fsp == NULL || fsp->fh->fd == -1) {
6445 return NT_STATUS_INVALID_HANDLE;
6448 if (total_data != POSIX_LOCK_DATA_SIZE) {
6449 return NT_STATUS_INVALID_PARAMETER;
6452 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6453 case POSIX_LOCK_TYPE_READ:
6454 lock_type = READ_LOCK;
6455 break;
6456 case POSIX_LOCK_TYPE_WRITE:
6457 /* Return the right POSIX-mappable error code for files opened read-only. */
6458 if (!fsp->can_write) {
6459 return NT_STATUS_INVALID_HANDLE;
6461 lock_type = WRITE_LOCK;
6462 break;
6463 case POSIX_LOCK_TYPE_UNLOCK:
6464 lock_type = UNLOCK_LOCK;
6465 break;
6466 default:
6467 return NT_STATUS_INVALID_PARAMETER;
6470 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6471 blocking_lock = False;
6472 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6473 blocking_lock = True;
6474 } else {
6475 return NT_STATUS_INVALID_PARAMETER;
6478 if (!lp_blocking_locks(SNUM(conn))) {
6479 blocking_lock = False;
6482 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6483 #if defined(HAVE_LONGLONG)
6484 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6485 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6486 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6487 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6488 #else /* HAVE_LONGLONG */
6489 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6490 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6491 #endif /* HAVE_LONGLONG */
6493 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6494 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6495 fsp_str_dbg(fsp),
6496 (unsigned int)lock_type,
6497 (unsigned long long)smblctx,
6498 (double)count,
6499 (double)offset ));
6501 if (lock_type == UNLOCK_LOCK) {
6502 status = do_unlock(req->sconn->msg_ctx,
6503 fsp,
6504 smblctx,
6505 count,
6506 offset,
6507 POSIX_LOCK);
6508 } else {
6509 uint64_t block_smblctx;
6511 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6512 fsp,
6513 smblctx,
6514 count,
6515 offset,
6516 lock_type,
6517 POSIX_LOCK,
6518 blocking_lock,
6519 &status,
6520 &block_smblctx,
6521 NULL);
6523 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6525 * A blocking lock was requested. Package up
6526 * this smb into a queued request and push it
6527 * onto the blocking lock queue.
6529 if(push_blocking_lock_request(br_lck,
6530 req,
6531 fsp,
6532 -1, /* infinite timeout. */
6534 smblctx,
6535 lock_type,
6536 POSIX_LOCK,
6537 offset,
6538 count,
6539 block_smblctx)) {
6540 TALLOC_FREE(br_lck);
6541 return status;
6544 TALLOC_FREE(br_lck);
6547 return status;
6550 /****************************************************************************
6551 Deal with SMB_SET_FILE_BASIC_INFO.
6552 ****************************************************************************/
6554 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6555 const char *pdata,
6556 int total_data,
6557 files_struct *fsp,
6558 const struct smb_filename *smb_fname)
6560 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6561 struct smb_file_time ft;
6562 uint32 dosmode = 0;
6563 NTSTATUS status = NT_STATUS_OK;
6565 ZERO_STRUCT(ft);
6567 if (total_data < 36) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6572 if (!NT_STATUS_IS_OK(status)) {
6573 return status;
6576 /* Set the attributes */
6577 dosmode = IVAL(pdata,32);
6578 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6579 if (!NT_STATUS_IS_OK(status)) {
6580 return status;
6583 /* create time */
6584 ft.create_time = interpret_long_date(pdata);
6586 /* access time */
6587 ft.atime = interpret_long_date(pdata+8);
6589 /* write time. */
6590 ft.mtime = interpret_long_date(pdata+16);
6592 /* change time. */
6593 ft.ctime = interpret_long_date(pdata+24);
6595 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6596 smb_fname_str_dbg(smb_fname)));
6598 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6599 true);
6602 /****************************************************************************
6603 Deal with SMB_INFO_STANDARD.
6604 ****************************************************************************/
6606 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6607 const char *pdata,
6608 int total_data,
6609 files_struct *fsp,
6610 const struct smb_filename *smb_fname)
6612 NTSTATUS status;
6613 struct smb_file_time ft;
6615 ZERO_STRUCT(ft);
6617 if (total_data < 12) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 /* create time */
6622 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6623 /* access time */
6624 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6625 /* write time */
6626 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6628 DEBUG(10,("smb_set_info_standard: file %s\n",
6629 smb_fname_str_dbg(smb_fname)));
6631 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6632 if (!NT_STATUS_IS_OK(status)) {
6633 return status;
6636 return smb_set_file_time(conn,
6637 fsp,
6638 smb_fname,
6639 &ft,
6640 true);
6643 /****************************************************************************
6644 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6645 ****************************************************************************/
6647 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6648 struct smb_request *req,
6649 const char *pdata,
6650 int total_data,
6651 files_struct *fsp,
6652 struct smb_filename *smb_fname)
6654 uint64_t allocation_size = 0;
6655 NTSTATUS status = NT_STATUS_OK;
6656 files_struct *new_fsp = NULL;
6658 if (!VALID_STAT(smb_fname->st)) {
6659 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6662 if (total_data < 8) {
6663 return NT_STATUS_INVALID_PARAMETER;
6666 allocation_size = (uint64_t)IVAL(pdata,0);
6667 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6668 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6669 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6670 (double)allocation_size));
6672 if (allocation_size) {
6673 allocation_size = smb_roundup(conn, allocation_size);
6676 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6677 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6678 (double)allocation_size));
6680 if (fsp && fsp->fh->fd != -1) {
6681 /* Open file handle. */
6682 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6683 return NT_STATUS_ACCESS_DENIED;
6686 /* Only change if needed. */
6687 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6688 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6689 return map_nt_error_from_unix(errno);
6692 /* But always update the time. */
6694 * This is equivalent to a write. Ensure it's seen immediately
6695 * if there are no pending writes.
6697 trigger_write_time_update_immediate(fsp);
6698 return NT_STATUS_OK;
6701 /* Pathname or stat or directory file. */
6702 status = SMB_VFS_CREATE_FILE(
6703 conn, /* conn */
6704 req, /* req */
6705 0, /* root_dir_fid */
6706 smb_fname, /* fname */
6707 FILE_WRITE_DATA, /* access_mask */
6708 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6709 FILE_SHARE_DELETE),
6710 FILE_OPEN, /* create_disposition*/
6711 0, /* create_options */
6712 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6713 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6714 0, /* allocation_size */
6715 0, /* private_flags */
6716 NULL, /* sd */
6717 NULL, /* ea_list */
6718 &new_fsp, /* result */
6719 NULL); /* pinfo */
6721 if (!NT_STATUS_IS_OK(status)) {
6722 /* NB. We check for open_was_deferred in the caller. */
6723 return status;
6726 /* Only change if needed. */
6727 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6728 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6729 status = map_nt_error_from_unix(errno);
6730 close_file(req, new_fsp, NORMAL_CLOSE);
6731 return status;
6735 /* Changing the allocation size should set the last mod time. */
6737 * This is equivalent to a write. Ensure it's seen immediately
6738 * if there are no pending writes.
6740 trigger_write_time_update_immediate(new_fsp);
6742 close_file(req, new_fsp, NORMAL_CLOSE);
6743 return NT_STATUS_OK;
6746 /****************************************************************************
6747 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6748 ****************************************************************************/
6750 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6751 struct smb_request *req,
6752 const char *pdata,
6753 int total_data,
6754 files_struct *fsp,
6755 const struct smb_filename *smb_fname,
6756 bool fail_after_createfile)
6758 off_t size;
6760 if (total_data < 8) {
6761 return NT_STATUS_INVALID_PARAMETER;
6764 size = IVAL(pdata,0);
6765 size |= (((off_t)IVAL(pdata,4)) << 32);
6766 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6767 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6768 (double)size));
6770 return smb_set_file_size(conn, req,
6771 fsp,
6772 smb_fname,
6773 &smb_fname->st,
6774 size,
6775 fail_after_createfile);
6778 /****************************************************************************
6779 Allow a UNIX info mknod.
6780 ****************************************************************************/
6782 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6783 const char *pdata,
6784 int total_data,
6785 const struct smb_filename *smb_fname)
6787 uint32 file_type = IVAL(pdata,56);
6788 #if defined(HAVE_MAKEDEV)
6789 uint32 dev_major = IVAL(pdata,60);
6790 uint32 dev_minor = IVAL(pdata,68);
6791 #endif
6792 SMB_DEV_T dev = (SMB_DEV_T)0;
6793 uint32 raw_unixmode = IVAL(pdata,84);
6794 NTSTATUS status;
6795 mode_t unixmode;
6797 if (total_data < 100) {
6798 return NT_STATUS_INVALID_PARAMETER;
6801 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6802 PERM_NEW_FILE, &unixmode);
6803 if (!NT_STATUS_IS_OK(status)) {
6804 return status;
6807 #if defined(HAVE_MAKEDEV)
6808 dev = makedev(dev_major, dev_minor);
6809 #endif
6811 switch (file_type) {
6812 #if defined(S_IFIFO)
6813 case UNIX_TYPE_FIFO:
6814 unixmode |= S_IFIFO;
6815 break;
6816 #endif
6817 #if defined(S_IFSOCK)
6818 case UNIX_TYPE_SOCKET:
6819 unixmode |= S_IFSOCK;
6820 break;
6821 #endif
6822 #if defined(S_IFCHR)
6823 case UNIX_TYPE_CHARDEV:
6824 unixmode |= S_IFCHR;
6825 break;
6826 #endif
6827 #if defined(S_IFBLK)
6828 case UNIX_TYPE_BLKDEV:
6829 unixmode |= S_IFBLK;
6830 break;
6831 #endif
6832 default:
6833 return NT_STATUS_INVALID_PARAMETER;
6836 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6837 "%.0f mode 0%o for file %s\n", (double)dev,
6838 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6840 /* Ok - do the mknod. */
6841 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6842 return map_nt_error_from_unix(errno);
6845 /* If any of the other "set" calls fail we
6846 * don't want to end up with a half-constructed mknod.
6849 if (lp_inherit_perms(SNUM(conn))) {
6850 char *parent;
6851 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6852 &parent, NULL)) {
6853 return NT_STATUS_NO_MEMORY;
6855 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6856 unixmode);
6857 TALLOC_FREE(parent);
6860 return NT_STATUS_OK;
6863 /****************************************************************************
6864 Deal with SMB_SET_FILE_UNIX_BASIC.
6865 ****************************************************************************/
6867 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6868 struct smb_request *req,
6869 const char *pdata,
6870 int total_data,
6871 files_struct *fsp,
6872 const struct smb_filename *smb_fname)
6874 struct smb_file_time ft;
6875 uint32 raw_unixmode;
6876 mode_t unixmode;
6877 off_t size = 0;
6878 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6879 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6880 NTSTATUS status = NT_STATUS_OK;
6881 bool delete_on_fail = False;
6882 enum perm_type ptype;
6883 files_struct *all_fsps = NULL;
6884 bool modify_mtime = true;
6885 struct file_id id;
6886 struct smb_filename *smb_fname_tmp = NULL;
6887 SMB_STRUCT_STAT sbuf;
6889 ZERO_STRUCT(ft);
6891 if (total_data < 100) {
6892 return NT_STATUS_INVALID_PARAMETER;
6895 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6896 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6897 size=IVAL(pdata,0); /* first 8 Bytes are size */
6898 size |= (((off_t)IVAL(pdata,4)) << 32);
6901 ft.atime = interpret_long_date(pdata+24); /* access_time */
6902 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6903 set_owner = (uid_t)IVAL(pdata,40);
6904 set_grp = (gid_t)IVAL(pdata,48);
6905 raw_unixmode = IVAL(pdata,84);
6907 if (VALID_STAT(smb_fname->st)) {
6908 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6909 ptype = PERM_EXISTING_DIR;
6910 } else {
6911 ptype = PERM_EXISTING_FILE;
6913 } else {
6914 ptype = PERM_NEW_FILE;
6917 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6918 ptype, &unixmode);
6919 if (!NT_STATUS_IS_OK(status)) {
6920 return status;
6923 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6924 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6925 smb_fname_str_dbg(smb_fname), (double)size,
6926 (unsigned int)set_owner, (unsigned int)set_grp,
6927 (int)raw_unixmode));
6929 sbuf = smb_fname->st;
6931 if (!VALID_STAT(sbuf)) {
6933 * The only valid use of this is to create character and block
6934 * devices, and named pipes. This is deprecated (IMHO) and
6935 * a new info level should be used for mknod. JRA.
6938 status = smb_unix_mknod(conn,
6939 pdata,
6940 total_data,
6941 smb_fname);
6942 if (!NT_STATUS_IS_OK(status)) {
6943 return status;
6946 status = copy_smb_filename(talloc_tos(), smb_fname,
6947 &smb_fname_tmp);
6948 if (!NT_STATUS_IS_OK(status)) {
6949 return status;
6952 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6953 status = map_nt_error_from_unix(errno);
6954 TALLOC_FREE(smb_fname_tmp);
6955 SMB_VFS_UNLINK(conn, smb_fname);
6956 return status;
6959 sbuf = smb_fname_tmp->st;
6960 smb_fname = smb_fname_tmp;
6962 /* Ensure we don't try and change anything else. */
6963 raw_unixmode = SMB_MODE_NO_CHANGE;
6964 size = get_file_size_stat(&sbuf);
6965 ft.atime = sbuf.st_ex_atime;
6966 ft.mtime = sbuf.st_ex_mtime;
6968 * We continue here as we might want to change the
6969 * owner uid/gid.
6971 delete_on_fail = True;
6974 #if 1
6975 /* Horrible backwards compatibility hack as an old server bug
6976 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6977 * */
6979 if (!size) {
6980 size = get_file_size_stat(&sbuf);
6982 #endif
6985 * Deal with the UNIX specific mode set.
6988 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6989 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6990 "setting mode 0%o for file %s\n",
6991 (unsigned int)unixmode,
6992 smb_fname_str_dbg(smb_fname)));
6993 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6994 return map_nt_error_from_unix(errno);
6999 * Deal with the UNIX specific uid set.
7002 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7003 (sbuf.st_ex_uid != set_owner)) {
7004 int ret;
7006 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7007 "changing owner %u for path %s\n",
7008 (unsigned int)set_owner,
7009 smb_fname_str_dbg(smb_fname)));
7011 if (S_ISLNK(sbuf.st_ex_mode)) {
7012 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7013 set_owner, (gid_t)-1);
7014 } else {
7015 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7016 set_owner, (gid_t)-1);
7019 if (ret != 0) {
7020 status = map_nt_error_from_unix(errno);
7021 if (delete_on_fail) {
7022 SMB_VFS_UNLINK(conn, smb_fname);
7024 return status;
7029 * Deal with the UNIX specific gid set.
7032 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7033 (sbuf.st_ex_gid != set_grp)) {
7034 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7035 "changing group %u for file %s\n",
7036 (unsigned int)set_owner,
7037 smb_fname_str_dbg(smb_fname)));
7038 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7039 set_grp) != 0) {
7040 status = map_nt_error_from_unix(errno);
7041 if (delete_on_fail) {
7042 SMB_VFS_UNLINK(conn, smb_fname);
7044 return status;
7048 /* Deal with any size changes. */
7050 status = smb_set_file_size(conn, req,
7051 fsp,
7052 smb_fname,
7053 &sbuf,
7054 size,
7055 false);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 return status;
7060 /* Deal with any time changes. */
7061 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7062 /* No change, don't cancel anything. */
7063 return status;
7066 id = vfs_file_id_from_sbuf(conn, &sbuf);
7067 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7068 all_fsps = file_find_di_next(all_fsps)) {
7070 * We're setting the time explicitly for UNIX.
7071 * Cancel any pending changes over all handles.
7073 all_fsps->update_write_time_on_close = false;
7074 TALLOC_FREE(all_fsps->update_write_time_event);
7078 * Override the "setting_write_time"
7079 * parameter here as it almost does what
7080 * we need. Just remember if we modified
7081 * mtime and send the notify ourselves.
7083 if (null_timespec(ft.mtime)) {
7084 modify_mtime = false;
7087 status = smb_set_file_time(conn,
7088 fsp,
7089 smb_fname,
7090 &ft,
7091 false);
7092 if (modify_mtime) {
7093 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7094 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7096 return status;
7099 /****************************************************************************
7100 Deal with SMB_SET_FILE_UNIX_INFO2.
7101 ****************************************************************************/
7103 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7104 struct smb_request *req,
7105 const char *pdata,
7106 int total_data,
7107 files_struct *fsp,
7108 const struct smb_filename *smb_fname)
7110 NTSTATUS status;
7111 uint32 smb_fflags;
7112 uint32 smb_fmask;
7114 if (total_data < 116) {
7115 return NT_STATUS_INVALID_PARAMETER;
7118 /* Start by setting all the fields that are common between UNIX_BASIC
7119 * and UNIX_INFO2.
7121 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7122 fsp, smb_fname);
7123 if (!NT_STATUS_IS_OK(status)) {
7124 return status;
7127 smb_fflags = IVAL(pdata, 108);
7128 smb_fmask = IVAL(pdata, 112);
7130 /* NB: We should only attempt to alter the file flags if the client
7131 * sends a non-zero mask.
7133 if (smb_fmask != 0) {
7134 int stat_fflags = 0;
7136 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7137 smb_fmask, &stat_fflags)) {
7138 /* Client asked to alter a flag we don't understand. */
7139 return NT_STATUS_INVALID_PARAMETER;
7142 if (fsp && fsp->fh->fd != -1) {
7143 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7144 return NT_STATUS_NOT_SUPPORTED;
7145 } else {
7146 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7147 stat_fflags) != 0) {
7148 return map_nt_error_from_unix(errno);
7153 /* XXX: need to add support for changing the create_time here. You
7154 * can do this for paths on Darwin with setattrlist(2). The right way
7155 * to hook this up is probably by extending the VFS utimes interface.
7158 return NT_STATUS_OK;
7161 /****************************************************************************
7162 Create a directory with POSIX semantics.
7163 ****************************************************************************/
7165 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7166 struct smb_request *req,
7167 char **ppdata,
7168 int total_data,
7169 struct smb_filename *smb_fname,
7170 int *pdata_return_size)
7172 NTSTATUS status = NT_STATUS_OK;
7173 uint32 raw_unixmode = 0;
7174 uint32 mod_unixmode = 0;
7175 mode_t unixmode = (mode_t)0;
7176 files_struct *fsp = NULL;
7177 uint16 info_level_return = 0;
7178 int info;
7179 char *pdata = *ppdata;
7181 if (total_data < 18) {
7182 return NT_STATUS_INVALID_PARAMETER;
7185 raw_unixmode = IVAL(pdata,8);
7186 /* Next 4 bytes are not yet defined. */
7188 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7189 PERM_NEW_DIR, &unixmode);
7190 if (!NT_STATUS_IS_OK(status)) {
7191 return status;
7194 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7196 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7197 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7199 status = SMB_VFS_CREATE_FILE(
7200 conn, /* conn */
7201 req, /* req */
7202 0, /* root_dir_fid */
7203 smb_fname, /* fname */
7204 FILE_READ_ATTRIBUTES, /* access_mask */
7205 FILE_SHARE_NONE, /* share_access */
7206 FILE_CREATE, /* create_disposition*/
7207 FILE_DIRECTORY_FILE, /* create_options */
7208 mod_unixmode, /* file_attributes */
7209 0, /* oplock_request */
7210 0, /* allocation_size */
7211 0, /* private_flags */
7212 NULL, /* sd */
7213 NULL, /* ea_list */
7214 &fsp, /* result */
7215 &info); /* pinfo */
7217 if (NT_STATUS_IS_OK(status)) {
7218 close_file(req, fsp, NORMAL_CLOSE);
7221 info_level_return = SVAL(pdata,16);
7223 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7224 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7225 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7226 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7227 } else {
7228 *pdata_return_size = 12;
7231 /* Realloc the data size */
7232 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7233 if (*ppdata == NULL) {
7234 *pdata_return_size = 0;
7235 return NT_STATUS_NO_MEMORY;
7237 pdata = *ppdata;
7239 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7240 SSVAL(pdata,2,0); /* No fnum. */
7241 SIVAL(pdata,4,info); /* Was directory created. */
7243 switch (info_level_return) {
7244 case SMB_QUERY_FILE_UNIX_BASIC:
7245 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7246 SSVAL(pdata,10,0); /* Padding. */
7247 store_file_unix_basic(conn, pdata + 12, fsp,
7248 &smb_fname->st);
7249 break;
7250 case SMB_QUERY_FILE_UNIX_INFO2:
7251 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7252 SSVAL(pdata,10,0); /* Padding. */
7253 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7254 &smb_fname->st);
7255 break;
7256 default:
7257 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7258 SSVAL(pdata,10,0); /* Padding. */
7259 break;
7262 return status;
7265 /****************************************************************************
7266 Open/Create a file with POSIX semantics.
7267 ****************************************************************************/
7269 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7270 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7272 static NTSTATUS smb_posix_open(connection_struct *conn,
7273 struct smb_request *req,
7274 char **ppdata,
7275 int total_data,
7276 struct smb_filename *smb_fname,
7277 int *pdata_return_size)
7279 bool extended_oplock_granted = False;
7280 char *pdata = *ppdata;
7281 uint32 flags = 0;
7282 uint32 wire_open_mode = 0;
7283 uint32 raw_unixmode = 0;
7284 uint32 mod_unixmode = 0;
7285 uint32 create_disp = 0;
7286 uint32 access_mask = 0;
7287 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7288 NTSTATUS status = NT_STATUS_OK;
7289 mode_t unixmode = (mode_t)0;
7290 files_struct *fsp = NULL;
7291 int oplock_request = 0;
7292 int info = 0;
7293 uint16 info_level_return = 0;
7295 if (total_data < 18) {
7296 return NT_STATUS_INVALID_PARAMETER;
7299 flags = IVAL(pdata,0);
7300 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7301 if (oplock_request) {
7302 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7305 wire_open_mode = IVAL(pdata,4);
7307 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7308 return smb_posix_mkdir(conn, req,
7309 ppdata,
7310 total_data,
7311 smb_fname,
7312 pdata_return_size);
7315 switch (wire_open_mode & SMB_ACCMODE) {
7316 case SMB_O_RDONLY:
7317 access_mask = SMB_O_RDONLY_MAPPING;
7318 break;
7319 case SMB_O_WRONLY:
7320 access_mask = SMB_O_WRONLY_MAPPING;
7321 break;
7322 case SMB_O_RDWR:
7323 access_mask = (SMB_O_RDONLY_MAPPING|
7324 SMB_O_WRONLY_MAPPING);
7325 break;
7326 default:
7327 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7328 (unsigned int)wire_open_mode ));
7329 return NT_STATUS_INVALID_PARAMETER;
7332 wire_open_mode &= ~SMB_ACCMODE;
7334 /* First take care of O_CREAT|O_EXCL interactions. */
7335 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7336 case (SMB_O_CREAT | SMB_O_EXCL):
7337 /* File exists fail. File not exist create. */
7338 create_disp = FILE_CREATE;
7339 break;
7340 case SMB_O_CREAT:
7341 /* File exists open. File not exist create. */
7342 create_disp = FILE_OPEN_IF;
7343 break;
7344 case 0:
7345 /* File exists open. File not exist fail. */
7346 create_disp = FILE_OPEN;
7347 break;
7348 case SMB_O_EXCL:
7349 /* O_EXCL on its own without O_CREAT is undefined. */
7350 default:
7351 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7352 (unsigned int)wire_open_mode ));
7353 return NT_STATUS_INVALID_PARAMETER;
7356 /* Next factor in the effects of O_TRUNC. */
7357 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7359 if (wire_open_mode & SMB_O_TRUNC) {
7360 switch (create_disp) {
7361 case FILE_CREATE:
7362 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7363 /* Leave create_disp alone as
7364 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7366 /* File exists fail. File not exist create. */
7367 break;
7368 case FILE_OPEN_IF:
7369 /* SMB_O_CREAT | SMB_O_TRUNC */
7370 /* File exists overwrite. File not exist create. */
7371 create_disp = FILE_OVERWRITE_IF;
7372 break;
7373 case FILE_OPEN:
7374 /* SMB_O_TRUNC */
7375 /* File exists overwrite. File not exist fail. */
7376 create_disp = FILE_OVERWRITE;
7377 break;
7378 default:
7379 /* Cannot get here. */
7380 smb_panic("smb_posix_open: logic error");
7381 return NT_STATUS_INVALID_PARAMETER;
7385 raw_unixmode = IVAL(pdata,8);
7386 /* Next 4 bytes are not yet defined. */
7388 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7389 (VALID_STAT(smb_fname->st) ?
7390 PERM_EXISTING_FILE : PERM_NEW_FILE),
7391 &unixmode);
7393 if (!NT_STATUS_IS_OK(status)) {
7394 return status;
7397 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7399 if (wire_open_mode & SMB_O_SYNC) {
7400 create_options |= FILE_WRITE_THROUGH;
7402 if (wire_open_mode & SMB_O_APPEND) {
7403 access_mask |= FILE_APPEND_DATA;
7405 if (wire_open_mode & SMB_O_DIRECT) {
7406 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7409 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7410 VALID_STAT_OF_DIR(smb_fname->st)) {
7411 if (access_mask != SMB_O_RDONLY_MAPPING) {
7412 return NT_STATUS_FILE_IS_A_DIRECTORY;
7414 create_options &= ~FILE_NON_DIRECTORY_FILE;
7415 create_options |= FILE_DIRECTORY_FILE;
7418 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7419 smb_fname_str_dbg(smb_fname),
7420 (unsigned int)wire_open_mode,
7421 (unsigned int)unixmode ));
7423 status = SMB_VFS_CREATE_FILE(
7424 conn, /* conn */
7425 req, /* req */
7426 0, /* root_dir_fid */
7427 smb_fname, /* fname */
7428 access_mask, /* access_mask */
7429 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7430 FILE_SHARE_DELETE),
7431 create_disp, /* create_disposition*/
7432 create_options, /* create_options */
7433 mod_unixmode, /* file_attributes */
7434 oplock_request, /* oplock_request */
7435 0, /* allocation_size */
7436 0, /* private_flags */
7437 NULL, /* sd */
7438 NULL, /* ea_list */
7439 &fsp, /* result */
7440 &info); /* pinfo */
7442 if (!NT_STATUS_IS_OK(status)) {
7443 return status;
7446 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7447 extended_oplock_granted = True;
7450 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7451 extended_oplock_granted = True;
7454 info_level_return = SVAL(pdata,16);
7456 /* Allocate the correct return size. */
7458 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7459 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7460 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7461 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7462 } else {
7463 *pdata_return_size = 12;
7466 /* Realloc the data size */
7467 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7468 if (*ppdata == NULL) {
7469 close_file(req, fsp, ERROR_CLOSE);
7470 *pdata_return_size = 0;
7471 return NT_STATUS_NO_MEMORY;
7473 pdata = *ppdata;
7475 if (extended_oplock_granted) {
7476 if (flags & REQUEST_BATCH_OPLOCK) {
7477 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7478 } else {
7479 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7481 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7482 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7483 } else {
7484 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7487 SSVAL(pdata,2,fsp->fnum);
7488 SIVAL(pdata,4,info); /* Was file created etc. */
7490 switch (info_level_return) {
7491 case SMB_QUERY_FILE_UNIX_BASIC:
7492 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7493 SSVAL(pdata,10,0); /* padding. */
7494 store_file_unix_basic(conn, pdata + 12, fsp,
7495 &smb_fname->st);
7496 break;
7497 case SMB_QUERY_FILE_UNIX_INFO2:
7498 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7499 SSVAL(pdata,10,0); /* padding. */
7500 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7501 &smb_fname->st);
7502 break;
7503 default:
7504 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7505 SSVAL(pdata,10,0); /* padding. */
7506 break;
7508 return NT_STATUS_OK;
7511 /****************************************************************************
7512 Delete a file with POSIX semantics.
7513 ****************************************************************************/
7515 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7516 struct smb_request *req,
7517 const char *pdata,
7518 int total_data,
7519 struct smb_filename *smb_fname)
7521 NTSTATUS status = NT_STATUS_OK;
7522 files_struct *fsp = NULL;
7523 uint16 flags = 0;
7524 char del = 1;
7525 int info = 0;
7526 int create_options = 0;
7527 int i;
7528 struct share_mode_lock *lck = NULL;
7530 if (total_data < 2) {
7531 return NT_STATUS_INVALID_PARAMETER;
7534 flags = SVAL(pdata,0);
7536 if (!VALID_STAT(smb_fname->st)) {
7537 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7540 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7541 !VALID_STAT_OF_DIR(smb_fname->st)) {
7542 return NT_STATUS_NOT_A_DIRECTORY;
7545 DEBUG(10,("smb_posix_unlink: %s %s\n",
7546 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7547 smb_fname_str_dbg(smb_fname)));
7549 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7550 create_options |= FILE_DIRECTORY_FILE;
7553 status = SMB_VFS_CREATE_FILE(
7554 conn, /* conn */
7555 req, /* req */
7556 0, /* root_dir_fid */
7557 smb_fname, /* fname */
7558 DELETE_ACCESS, /* access_mask */
7559 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7560 FILE_SHARE_DELETE),
7561 FILE_OPEN, /* create_disposition*/
7562 create_options, /* create_options */
7563 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7564 0, /* oplock_request */
7565 0, /* allocation_size */
7566 0, /* private_flags */
7567 NULL, /* sd */
7568 NULL, /* ea_list */
7569 &fsp, /* result */
7570 &info); /* pinfo */
7572 if (!NT_STATUS_IS_OK(status)) {
7573 return status;
7577 * Don't lie to client. If we can't really delete due to
7578 * non-POSIX opens return SHARING_VIOLATION.
7581 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7582 if (lck == NULL) {
7583 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7584 "lock for file %s\n", fsp_str_dbg(fsp)));
7585 close_file(req, fsp, NORMAL_CLOSE);
7586 return NT_STATUS_INVALID_PARAMETER;
7590 * See if others still have the file open. If this is the case, then
7591 * don't delete. If all opens are POSIX delete we can set the delete
7592 * on close disposition.
7594 for (i=0; i<lck->data->num_share_modes; i++) {
7595 struct share_mode_entry *e = &lck->data->share_modes[i];
7596 if (is_valid_share_mode_entry(e)) {
7597 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7598 continue;
7600 if (share_mode_stale_pid(lck->data, i)) {
7601 continue;
7603 /* Fail with sharing violation. */
7604 close_file(req, fsp, NORMAL_CLOSE);
7605 TALLOC_FREE(lck);
7606 return NT_STATUS_SHARING_VIOLATION;
7611 * Set the delete on close.
7613 status = smb_set_file_disposition_info(conn,
7614 &del,
7616 fsp,
7617 smb_fname);
7619 if (!NT_STATUS_IS_OK(status)) {
7620 close_file(req, fsp, NORMAL_CLOSE);
7621 TALLOC_FREE(lck);
7622 return status;
7624 TALLOC_FREE(lck);
7625 return close_file(req, fsp, NORMAL_CLOSE);
7628 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7629 struct smb_request *req,
7630 TALLOC_CTX *mem_ctx,
7631 uint16_t info_level,
7632 files_struct *fsp,
7633 struct smb_filename *smb_fname,
7634 char **ppdata, int total_data,
7635 int *ret_data_size)
7637 char *pdata = *ppdata;
7638 NTSTATUS status = NT_STATUS_OK;
7639 int data_return_size = 0;
7641 *ret_data_size = 0;
7643 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7644 return NT_STATUS_INVALID_LEVEL;
7647 if (!CAN_WRITE(conn)) {
7648 /* Allow POSIX opens. The open path will deny
7649 * any non-readonly opens. */
7650 if (info_level != SMB_POSIX_PATH_OPEN) {
7651 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7655 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7656 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7657 fsp ? fsp->fnum : -1, info_level, total_data));
7659 switch (info_level) {
7661 case SMB_INFO_STANDARD:
7663 status = smb_set_info_standard(conn,
7664 pdata,
7665 total_data,
7666 fsp,
7667 smb_fname);
7668 break;
7671 case SMB_INFO_SET_EA:
7673 status = smb_info_set_ea(conn,
7674 pdata,
7675 total_data,
7676 fsp,
7677 smb_fname);
7678 break;
7681 case SMB_SET_FILE_BASIC_INFO:
7682 case SMB_FILE_BASIC_INFORMATION:
7684 status = smb_set_file_basic_info(conn,
7685 pdata,
7686 total_data,
7687 fsp,
7688 smb_fname);
7689 break;
7692 case SMB_FILE_ALLOCATION_INFORMATION:
7693 case SMB_SET_FILE_ALLOCATION_INFO:
7695 status = smb_set_file_allocation_info(conn, req,
7696 pdata,
7697 total_data,
7698 fsp,
7699 smb_fname);
7700 break;
7703 case SMB_FILE_END_OF_FILE_INFORMATION:
7704 case SMB_SET_FILE_END_OF_FILE_INFO:
7707 * XP/Win7 both fail after the createfile with
7708 * SMB_SET_FILE_END_OF_FILE_INFO but not
7709 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7710 * The level is known here, so pass it down
7711 * appropriately.
7713 bool should_fail =
7714 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7716 status = smb_set_file_end_of_file_info(conn, req,
7717 pdata,
7718 total_data,
7719 fsp,
7720 smb_fname,
7721 should_fail);
7722 break;
7725 case SMB_FILE_DISPOSITION_INFORMATION:
7726 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7728 #if 0
7729 /* JRA - We used to just ignore this on a path ?
7730 * Shouldn't this be invalid level on a pathname
7731 * based call ?
7733 if (tran_call != TRANSACT2_SETFILEINFO) {
7734 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7736 #endif
7737 status = smb_set_file_disposition_info(conn,
7738 pdata,
7739 total_data,
7740 fsp,
7741 smb_fname);
7742 break;
7745 case SMB_FILE_POSITION_INFORMATION:
7747 status = smb_file_position_information(conn,
7748 pdata,
7749 total_data,
7750 fsp);
7751 break;
7754 case SMB_FILE_FULL_EA_INFORMATION:
7756 status = smb_set_file_full_ea_info(conn,
7757 pdata,
7758 total_data,
7759 fsp);
7760 break;
7763 /* From tridge Samba4 :
7764 * MODE_INFORMATION in setfileinfo (I have no
7765 * idea what "mode information" on a file is - it takes a value of 0,
7766 * 2, 4 or 6. What could it be?).
7769 case SMB_FILE_MODE_INFORMATION:
7771 status = smb_file_mode_information(conn,
7772 pdata,
7773 total_data);
7774 break;
7778 * CIFS UNIX extensions.
7781 case SMB_SET_FILE_UNIX_BASIC:
7783 status = smb_set_file_unix_basic(conn, req,
7784 pdata,
7785 total_data,
7786 fsp,
7787 smb_fname);
7788 break;
7791 case SMB_SET_FILE_UNIX_INFO2:
7793 status = smb_set_file_unix_info2(conn, req,
7794 pdata,
7795 total_data,
7796 fsp,
7797 smb_fname);
7798 break;
7801 case SMB_SET_FILE_UNIX_LINK:
7803 if (fsp) {
7804 /* We must have a pathname for this. */
7805 return NT_STATUS_INVALID_LEVEL;
7807 status = smb_set_file_unix_link(conn, req, pdata,
7808 total_data, smb_fname);
7809 break;
7812 case SMB_SET_FILE_UNIX_HLINK:
7814 if (fsp) {
7815 /* We must have a pathname for this. */
7816 return NT_STATUS_INVALID_LEVEL;
7818 status = smb_set_file_unix_hlink(conn, req,
7819 pdata, total_data,
7820 smb_fname);
7821 break;
7824 case SMB_FILE_RENAME_INFORMATION:
7826 status = smb_file_rename_information(conn, req,
7827 pdata, total_data,
7828 fsp, smb_fname);
7829 break;
7832 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7834 /* SMB2 rename information. */
7835 status = smb2_file_rename_information(conn, req,
7836 pdata, total_data,
7837 fsp, smb_fname);
7838 break;
7841 case SMB_FILE_LINK_INFORMATION:
7843 status = smb_file_link_information(conn, req,
7844 pdata, total_data,
7845 fsp, smb_fname);
7846 break;
7849 #if defined(HAVE_POSIX_ACLS)
7850 case SMB_SET_POSIX_ACL:
7852 status = smb_set_posix_acl(conn,
7853 pdata,
7854 total_data,
7855 fsp,
7856 smb_fname);
7857 break;
7859 #endif
7861 case SMB_SET_POSIX_LOCK:
7863 if (!fsp) {
7864 return NT_STATUS_INVALID_LEVEL;
7866 status = smb_set_posix_lock(conn, req,
7867 pdata, total_data, fsp);
7868 break;
7871 case SMB_POSIX_PATH_OPEN:
7873 if (fsp) {
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL;
7878 status = smb_posix_open(conn, req,
7879 ppdata,
7880 total_data,
7881 smb_fname,
7882 &data_return_size);
7883 break;
7886 case SMB_POSIX_PATH_UNLINK:
7888 if (fsp) {
7889 /* We must have a pathname for this. */
7890 return NT_STATUS_INVALID_LEVEL;
7893 status = smb_posix_unlink(conn, req,
7894 pdata,
7895 total_data,
7896 smb_fname);
7897 break;
7900 default:
7901 return NT_STATUS_INVALID_LEVEL;
7904 if (!NT_STATUS_IS_OK(status)) {
7905 return status;
7908 *ret_data_size = data_return_size;
7909 return NT_STATUS_OK;
7912 /****************************************************************************
7913 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7914 ****************************************************************************/
7916 static void call_trans2setfilepathinfo(connection_struct *conn,
7917 struct smb_request *req,
7918 unsigned int tran_call,
7919 char **pparams, int total_params,
7920 char **ppdata, int total_data,
7921 unsigned int max_data_bytes)
7923 char *params = *pparams;
7924 char *pdata = *ppdata;
7925 uint16 info_level;
7926 struct smb_filename *smb_fname = NULL;
7927 files_struct *fsp = NULL;
7928 NTSTATUS status = NT_STATUS_OK;
7929 int data_return_size = 0;
7931 if (!params) {
7932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7933 return;
7936 if (tran_call == TRANSACT2_SETFILEINFO) {
7937 if (total_params < 4) {
7938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7939 return;
7942 fsp = file_fsp(req, SVAL(params,0));
7943 /* Basic check for non-null fsp. */
7944 if (!check_fsp_open(conn, req, fsp)) {
7945 return;
7947 info_level = SVAL(params,2);
7949 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7950 &smb_fname);
7951 if (!NT_STATUS_IS_OK(status)) {
7952 reply_nterror(req, status);
7953 return;
7956 if(fsp->fh->fd == -1) {
7958 * This is actually a SETFILEINFO on a directory
7959 * handle (returned from an NT SMB). NT5.0 seems
7960 * to do this call. JRA.
7962 if (INFO_LEVEL_IS_UNIX(info_level)) {
7963 /* Always do lstat for UNIX calls. */
7964 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7965 DEBUG(3,("call_trans2setfilepathinfo: "
7966 "SMB_VFS_LSTAT of %s failed "
7967 "(%s)\n",
7968 smb_fname_str_dbg(smb_fname),
7969 strerror(errno)));
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7971 return;
7973 } else {
7974 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7975 DEBUG(3,("call_trans2setfilepathinfo: "
7976 "fileinfo of %s failed (%s)\n",
7977 smb_fname_str_dbg(smb_fname),
7978 strerror(errno)));
7979 reply_nterror(req, map_nt_error_from_unix(errno));
7980 return;
7983 } else if (fsp->print_file) {
7985 * Doing a DELETE_ON_CLOSE should cancel a print job.
7987 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7988 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7990 DEBUG(3,("call_trans2setfilepathinfo: "
7991 "Cancelling print job (%s)\n",
7992 fsp_str_dbg(fsp)));
7994 SSVAL(params,0,0);
7995 send_trans2_replies(conn, req, params, 2,
7996 *ppdata, 0,
7997 max_data_bytes);
7998 return;
7999 } else {
8000 reply_nterror(req,
8001 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8002 return;
8004 } else {
8006 * Original code - this is an open file.
8008 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8009 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8010 "of fnum %d failed (%s)\n", fsp->fnum,
8011 strerror(errno)));
8012 reply_nterror(req, map_nt_error_from_unix(errno));
8013 return;
8016 } else {
8017 char *fname = NULL;
8018 uint32_t ucf_flags = 0;
8020 /* set path info */
8021 if (total_params < 7) {
8022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8023 return;
8026 info_level = SVAL(params,0);
8027 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8028 total_params - 6, STR_TERMINATE,
8029 &status);
8030 if (!NT_STATUS_IS_OK(status)) {
8031 reply_nterror(req, status);
8032 return;
8035 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8036 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8037 info_level == SMB_FILE_RENAME_INFORMATION ||
8038 info_level == SMB_POSIX_PATH_UNLINK) {
8039 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8042 status = filename_convert(req, conn,
8043 req->flags2 & FLAGS2_DFS_PATHNAMES,
8044 fname,
8045 ucf_flags,
8046 NULL,
8047 &smb_fname);
8048 if (!NT_STATUS_IS_OK(status)) {
8049 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8050 reply_botherror(req,
8051 NT_STATUS_PATH_NOT_COVERED,
8052 ERRSRV, ERRbadpath);
8053 return;
8055 reply_nterror(req, status);
8056 return;
8059 if (INFO_LEVEL_IS_UNIX(info_level)) {
8061 * For CIFS UNIX extensions the target name may not exist.
8064 /* Always do lstat for UNIX calls. */
8065 SMB_VFS_LSTAT(conn, smb_fname);
8067 } else if (!VALID_STAT(smb_fname->st) &&
8068 SMB_VFS_STAT(conn, smb_fname)) {
8069 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8070 "%s failed (%s)\n",
8071 smb_fname_str_dbg(smb_fname),
8072 strerror(errno)));
8073 reply_nterror(req, map_nt_error_from_unix(errno));
8074 return;
8078 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8079 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8080 fsp ? fsp->fnum : -1, info_level,total_data));
8082 /* Realloc the parameter size */
8083 *pparams = (char *)SMB_REALLOC(*pparams,2);
8084 if (*pparams == NULL) {
8085 reply_nterror(req, NT_STATUS_NO_MEMORY);
8086 return;
8088 params = *pparams;
8090 SSVAL(params,0,0);
8092 status = smbd_do_setfilepathinfo(conn, req, req,
8093 info_level,
8094 fsp,
8095 smb_fname,
8096 ppdata, total_data,
8097 &data_return_size);
8098 if (!NT_STATUS_IS_OK(status)) {
8099 if (open_was_deferred(req->sconn, req->mid)) {
8100 /* We have re-scheduled this call. */
8101 return;
8103 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8104 /* We have re-scheduled this call. */
8105 return;
8107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8108 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8109 ERRSRV, ERRbadpath);
8110 return;
8112 if (info_level == SMB_POSIX_PATH_OPEN) {
8113 reply_openerror(req, status);
8114 return;
8117 reply_nterror(req, status);
8118 return;
8121 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8122 max_data_bytes);
8124 return;
8127 /****************************************************************************
8128 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8129 ****************************************************************************/
8131 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8132 char **pparams, int total_params,
8133 char **ppdata, int total_data,
8134 unsigned int max_data_bytes)
8136 struct smb_filename *smb_dname = NULL;
8137 char *params = *pparams;
8138 char *pdata = *ppdata;
8139 char *directory = NULL;
8140 NTSTATUS status = NT_STATUS_OK;
8141 struct ea_list *ea_list = NULL;
8142 TALLOC_CTX *ctx = talloc_tos();
8144 if (!CAN_WRITE(conn)) {
8145 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8146 return;
8149 if (total_params < 5) {
8150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8151 return;
8154 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8155 total_params - 4, STR_TERMINATE,
8156 &status);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 reply_nterror(req, status);
8159 return;
8162 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8164 status = filename_convert(ctx,
8165 conn,
8166 req->flags2 & FLAGS2_DFS_PATHNAMES,
8167 directory,
8169 NULL,
8170 &smb_dname);
8172 if (!NT_STATUS_IS_OK(status)) {
8173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8174 reply_botherror(req,
8175 NT_STATUS_PATH_NOT_COVERED,
8176 ERRSRV, ERRbadpath);
8177 return;
8179 reply_nterror(req, status);
8180 return;
8184 * OS/2 workplace shell seems to send SET_EA requests of "null"
8185 * length (4 bytes containing IVAL 4).
8186 * They seem to have no effect. Bug #3212. JRA.
8189 if (total_data && (total_data != 4)) {
8190 /* Any data in this call is an EA list. */
8191 if (total_data < 10) {
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 goto out;
8196 if (IVAL(pdata,0) > total_data) {
8197 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8198 IVAL(pdata,0), (unsigned int)total_data));
8199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8200 goto out;
8203 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8204 total_data - 4);
8205 if (!ea_list) {
8206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8207 goto out;
8210 if (!lp_ea_support(SNUM(conn))) {
8211 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8212 goto out;
8215 /* If total_data == 4 Windows doesn't care what values
8216 * are placed in that field, it just ignores them.
8217 * The System i QNTC IBM SMB client puts bad values here,
8218 * so ignore them. */
8220 status = create_directory(conn, req, smb_dname);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 reply_nterror(req, status);
8224 goto out;
8227 /* Try and set any given EA. */
8228 if (ea_list) {
8229 status = set_ea(conn, NULL, smb_dname, ea_list);
8230 if (!NT_STATUS_IS_OK(status)) {
8231 reply_nterror(req, status);
8232 goto out;
8236 /* Realloc the parameter and data sizes */
8237 *pparams = (char *)SMB_REALLOC(*pparams,2);
8238 if(*pparams == NULL) {
8239 reply_nterror(req, NT_STATUS_NO_MEMORY);
8240 goto out;
8242 params = *pparams;
8244 SSVAL(params,0,0);
8246 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8248 out:
8249 TALLOC_FREE(smb_dname);
8250 return;
8253 /****************************************************************************
8254 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8255 We don't actually do this - we just send a null response.
8256 ****************************************************************************/
8258 static void call_trans2findnotifyfirst(connection_struct *conn,
8259 struct smb_request *req,
8260 char **pparams, int total_params,
8261 char **ppdata, int total_data,
8262 unsigned int max_data_bytes)
8264 char *params = *pparams;
8265 uint16 info_level;
8267 if (total_params < 6) {
8268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8269 return;
8272 info_level = SVAL(params,4);
8273 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8275 switch (info_level) {
8276 case 1:
8277 case 2:
8278 break;
8279 default:
8280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8281 return;
8284 /* Realloc the parameter and data sizes */
8285 *pparams = (char *)SMB_REALLOC(*pparams,6);
8286 if (*pparams == NULL) {
8287 reply_nterror(req, NT_STATUS_NO_MEMORY);
8288 return;
8290 params = *pparams;
8292 SSVAL(params,0,fnf_handle);
8293 SSVAL(params,2,0); /* No changes */
8294 SSVAL(params,4,0); /* No EA errors */
8296 fnf_handle++;
8298 if(fnf_handle == 0)
8299 fnf_handle = 257;
8301 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8303 return;
8306 /****************************************************************************
8307 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8308 changes). Currently this does nothing.
8309 ****************************************************************************/
8311 static void call_trans2findnotifynext(connection_struct *conn,
8312 struct smb_request *req,
8313 char **pparams, int total_params,
8314 char **ppdata, int total_data,
8315 unsigned int max_data_bytes)
8317 char *params = *pparams;
8319 DEBUG(3,("call_trans2findnotifynext\n"));
8321 /* Realloc the parameter and data sizes */
8322 *pparams = (char *)SMB_REALLOC(*pparams,4);
8323 if (*pparams == NULL) {
8324 reply_nterror(req, NT_STATUS_NO_MEMORY);
8325 return;
8327 params = *pparams;
8329 SSVAL(params,0,0); /* No changes */
8330 SSVAL(params,2,0); /* No EA errors */
8332 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8334 return;
8337 /****************************************************************************
8338 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8339 ****************************************************************************/
8341 static void call_trans2getdfsreferral(connection_struct *conn,
8342 struct smb_request *req,
8343 char **pparams, int total_params,
8344 char **ppdata, int total_data,
8345 unsigned int max_data_bytes)
8347 char *params = *pparams;
8348 char *pathname = NULL;
8349 int reply_size = 0;
8350 int max_referral_level;
8351 NTSTATUS status = NT_STATUS_OK;
8352 TALLOC_CTX *ctx = talloc_tos();
8354 DEBUG(10,("call_trans2getdfsreferral\n"));
8356 if (total_params < 3) {
8357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 return;
8361 max_referral_level = SVAL(params,0);
8363 if(!lp_host_msdfs()) {
8364 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8365 return;
8368 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8369 total_params - 2, STR_TERMINATE);
8370 if (!pathname) {
8371 reply_nterror(req, NT_STATUS_NOT_FOUND);
8372 return;
8374 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8375 ppdata,&status)) < 0) {
8376 reply_nterror(req, status);
8377 return;
8380 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8381 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8382 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8384 return;
8387 #define LMCAT_SPL 0x53
8388 #define LMFUNC_GETJOBID 0x60
8390 /****************************************************************************
8391 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8392 ****************************************************************************/
8394 static void call_trans2ioctl(connection_struct *conn,
8395 struct smb_request *req,
8396 char **pparams, int total_params,
8397 char **ppdata, int total_data,
8398 unsigned int max_data_bytes)
8400 char *pdata = *ppdata;
8401 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8403 /* check for an invalid fid before proceeding */
8405 if (!fsp) {
8406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8407 return;
8410 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8411 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8412 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8413 if (*ppdata == NULL) {
8414 reply_nterror(req, NT_STATUS_NO_MEMORY);
8415 return;
8417 pdata = *ppdata;
8419 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8420 CAN ACCEPT THIS IN UNICODE. JRA. */
8422 /* Job number */
8423 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8425 srvstr_push(pdata, req->flags2, pdata + 2,
8426 lp_netbios_name(), 15,
8427 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8428 srvstr_push(pdata, req->flags2, pdata+18,
8429 lp_servicename(SNUM(conn)), 13,
8430 STR_ASCII|STR_TERMINATE); /* Service name */
8431 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8432 max_data_bytes);
8433 return;
8436 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8437 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8440 /****************************************************************************
8441 Reply to a SMBfindclose (stop trans2 directory search).
8442 ****************************************************************************/
8444 void reply_findclose(struct smb_request *req)
8446 int dptr_num;
8447 struct smbd_server_connection *sconn = req->sconn;
8449 START_PROFILE(SMBfindclose);
8451 if (req->wct < 1) {
8452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8453 END_PROFILE(SMBfindclose);
8454 return;
8457 dptr_num = SVALS(req->vwv+0, 0);
8459 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8461 dptr_close(sconn, &dptr_num);
8463 reply_outbuf(req, 0, 0);
8465 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8467 END_PROFILE(SMBfindclose);
8468 return;
8471 /****************************************************************************
8472 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8473 ****************************************************************************/
8475 void reply_findnclose(struct smb_request *req)
8477 int dptr_num;
8479 START_PROFILE(SMBfindnclose);
8481 if (req->wct < 1) {
8482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8483 END_PROFILE(SMBfindnclose);
8484 return;
8487 dptr_num = SVAL(req->vwv+0, 0);
8489 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8491 /* We never give out valid handles for a
8492 findnotifyfirst - so any dptr_num is ok here.
8493 Just ignore it. */
8495 reply_outbuf(req, 0, 0);
8497 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8499 END_PROFILE(SMBfindnclose);
8500 return;
8503 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8504 struct trans_state *state)
8506 if (get_Protocol() >= PROTOCOL_NT1) {
8507 req->flags2 |= 0x40; /* IS_LONG_NAME */
8508 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8511 if (conn->encrypt_level == Required && !req->encrypted) {
8512 if (state->call != TRANSACT2_QFSINFO &&
8513 state->call != TRANSACT2_SETFSINFO) {
8514 DEBUG(0,("handle_trans2: encryption required "
8515 "with call 0x%x\n",
8516 (unsigned int)state->call));
8517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8518 return;
8522 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8524 /* Now we must call the relevant TRANS2 function */
8525 switch(state->call) {
8526 case TRANSACT2_OPEN:
8528 START_PROFILE(Trans2_open);
8529 call_trans2open(conn, req,
8530 &state->param, state->total_param,
8531 &state->data, state->total_data,
8532 state->max_data_return);
8533 END_PROFILE(Trans2_open);
8534 break;
8537 case TRANSACT2_FINDFIRST:
8539 START_PROFILE(Trans2_findfirst);
8540 call_trans2findfirst(conn, req,
8541 &state->param, state->total_param,
8542 &state->data, state->total_data,
8543 state->max_data_return);
8544 END_PROFILE(Trans2_findfirst);
8545 break;
8548 case TRANSACT2_FINDNEXT:
8550 START_PROFILE(Trans2_findnext);
8551 call_trans2findnext(conn, req,
8552 &state->param, state->total_param,
8553 &state->data, state->total_data,
8554 state->max_data_return);
8555 END_PROFILE(Trans2_findnext);
8556 break;
8559 case TRANSACT2_QFSINFO:
8561 START_PROFILE(Trans2_qfsinfo);
8562 call_trans2qfsinfo(conn, req,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_qfsinfo);
8567 break;
8570 case TRANSACT2_SETFSINFO:
8572 START_PROFILE(Trans2_setfsinfo);
8573 call_trans2setfsinfo(conn, req,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_setfsinfo);
8578 break;
8581 case TRANSACT2_QPATHINFO:
8582 case TRANSACT2_QFILEINFO:
8584 START_PROFILE(Trans2_qpathinfo);
8585 call_trans2qfilepathinfo(conn, req, state->call,
8586 &state->param, state->total_param,
8587 &state->data, state->total_data,
8588 state->max_data_return);
8589 END_PROFILE(Trans2_qpathinfo);
8590 break;
8593 case TRANSACT2_SETPATHINFO:
8594 case TRANSACT2_SETFILEINFO:
8596 START_PROFILE(Trans2_setpathinfo);
8597 call_trans2setfilepathinfo(conn, req, state->call,
8598 &state->param, state->total_param,
8599 &state->data, state->total_data,
8600 state->max_data_return);
8601 END_PROFILE(Trans2_setpathinfo);
8602 break;
8605 case TRANSACT2_FINDNOTIFYFIRST:
8607 START_PROFILE(Trans2_findnotifyfirst);
8608 call_trans2findnotifyfirst(conn, req,
8609 &state->param, state->total_param,
8610 &state->data, state->total_data,
8611 state->max_data_return);
8612 END_PROFILE(Trans2_findnotifyfirst);
8613 break;
8616 case TRANSACT2_FINDNOTIFYNEXT:
8618 START_PROFILE(Trans2_findnotifynext);
8619 call_trans2findnotifynext(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_findnotifynext);
8624 break;
8627 case TRANSACT2_MKDIR:
8629 START_PROFILE(Trans2_mkdir);
8630 call_trans2mkdir(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_mkdir);
8635 break;
8638 case TRANSACT2_GET_DFS_REFERRAL:
8640 START_PROFILE(Trans2_get_dfs_referral);
8641 call_trans2getdfsreferral(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_get_dfs_referral);
8646 break;
8649 case TRANSACT2_IOCTL:
8651 START_PROFILE(Trans2_ioctl);
8652 call_trans2ioctl(conn, req,
8653 &state->param, state->total_param,
8654 &state->data, state->total_data,
8655 state->max_data_return);
8656 END_PROFILE(Trans2_ioctl);
8657 break;
8660 default:
8661 /* Error in request */
8662 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8663 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8667 /****************************************************************************
8668 Reply to a SMBtrans2.
8669 ****************************************************************************/
8671 void reply_trans2(struct smb_request *req)
8673 connection_struct *conn = req->conn;
8674 unsigned int dsoff;
8675 unsigned int dscnt;
8676 unsigned int psoff;
8677 unsigned int pscnt;
8678 unsigned int tran_call;
8679 struct trans_state *state;
8680 NTSTATUS result;
8682 START_PROFILE(SMBtrans2);
8684 if (req->wct < 14) {
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686 END_PROFILE(SMBtrans2);
8687 return;
8690 dsoff = SVAL(req->vwv+12, 0);
8691 dscnt = SVAL(req->vwv+11, 0);
8692 psoff = SVAL(req->vwv+10, 0);
8693 pscnt = SVAL(req->vwv+9, 0);
8694 tran_call = SVAL(req->vwv+14, 0);
8696 result = allow_new_trans(conn->pending_trans, req->mid);
8697 if (!NT_STATUS_IS_OK(result)) {
8698 DEBUG(2, ("Got invalid trans2 request: %s\n",
8699 nt_errstr(result)));
8700 reply_nterror(req, result);
8701 END_PROFILE(SMBtrans2);
8702 return;
8705 if (IS_IPC(conn)) {
8706 switch (tran_call) {
8707 /* List the allowed trans2 calls on IPC$ */
8708 case TRANSACT2_OPEN:
8709 case TRANSACT2_GET_DFS_REFERRAL:
8710 case TRANSACT2_QFILEINFO:
8711 case TRANSACT2_QFSINFO:
8712 case TRANSACT2_SETFSINFO:
8713 break;
8714 default:
8715 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8716 END_PROFILE(SMBtrans2);
8717 return;
8721 if ((state = talloc(conn, struct trans_state)) == NULL) {
8722 DEBUG(0, ("talloc failed\n"));
8723 reply_nterror(req, NT_STATUS_NO_MEMORY);
8724 END_PROFILE(SMBtrans2);
8725 return;
8728 state->cmd = SMBtrans2;
8730 state->mid = req->mid;
8731 state->vuid = req->vuid;
8732 state->setup_count = SVAL(req->vwv+13, 0);
8733 state->setup = NULL;
8734 state->total_param = SVAL(req->vwv+0, 0);
8735 state->param = NULL;
8736 state->total_data = SVAL(req->vwv+1, 0);
8737 state->data = NULL;
8738 state->max_param_return = SVAL(req->vwv+2, 0);
8739 state->max_data_return = SVAL(req->vwv+3, 0);
8740 state->max_setup_return = SVAL(req->vwv+4, 0);
8741 state->close_on_completion = BITSETW(req->vwv+5, 0);
8742 state->one_way = BITSETW(req->vwv+5, 1);
8744 state->call = tran_call;
8746 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8747 is so as a sanity check */
8748 if (state->setup_count != 1) {
8750 * Need to have rc=0 for ioctl to get job id for OS/2.
8751 * Network printing will fail if function is not successful.
8752 * Similar function in reply.c will be used if protocol
8753 * is LANMAN1.0 instead of LM1.2X002.
8754 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8755 * outbuf doesn't have to be set(only job id is used).
8757 if ( (state->setup_count == 4)
8758 && (tran_call == TRANSACT2_IOCTL)
8759 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8760 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8761 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8762 } else {
8763 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8764 DEBUG(2,("Transaction is %d\n",tran_call));
8765 TALLOC_FREE(state);
8766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8767 END_PROFILE(SMBtrans2);
8768 return;
8772 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8773 goto bad_param;
8775 if (state->total_data) {
8777 if (trans_oob(state->total_data, 0, dscnt)
8778 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8779 goto bad_param;
8782 /* Can't use talloc here, the core routines do realloc on the
8783 * params and data. */
8784 state->data = (char *)SMB_MALLOC(state->total_data);
8785 if (state->data == NULL) {
8786 DEBUG(0,("reply_trans2: data malloc fail for %u "
8787 "bytes !\n", (unsigned int)state->total_data));
8788 TALLOC_FREE(state);
8789 reply_nterror(req, NT_STATUS_NO_MEMORY);
8790 END_PROFILE(SMBtrans2);
8791 return;
8794 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8797 if (state->total_param) {
8799 if (trans_oob(state->total_param, 0, pscnt)
8800 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8801 goto bad_param;
8804 /* Can't use talloc here, the core routines do realloc on the
8805 * params and data. */
8806 state->param = (char *)SMB_MALLOC(state->total_param);
8807 if (state->param == NULL) {
8808 DEBUG(0,("reply_trans: param malloc fail for %u "
8809 "bytes !\n", (unsigned int)state->total_param));
8810 SAFE_FREE(state->data);
8811 TALLOC_FREE(state);
8812 reply_nterror(req, NT_STATUS_NO_MEMORY);
8813 END_PROFILE(SMBtrans2);
8814 return;
8817 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8820 state->received_data = dscnt;
8821 state->received_param = pscnt;
8823 if ((state->received_param == state->total_param) &&
8824 (state->received_data == state->total_data)) {
8826 handle_trans2(conn, req, state);
8828 SAFE_FREE(state->data);
8829 SAFE_FREE(state->param);
8830 TALLOC_FREE(state);
8831 END_PROFILE(SMBtrans2);
8832 return;
8835 DLIST_ADD(conn->pending_trans, state);
8837 /* We need to send an interim response then receive the rest
8838 of the parameter/data bytes */
8839 reply_outbuf(req, 0, 0);
8840 show_msg((char *)req->outbuf);
8841 END_PROFILE(SMBtrans2);
8842 return;
8844 bad_param:
8846 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8847 SAFE_FREE(state->data);
8848 SAFE_FREE(state->param);
8849 TALLOC_FREE(state);
8850 END_PROFILE(SMBtrans2);
8851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8855 /****************************************************************************
8856 Reply to a SMBtranss2
8857 ****************************************************************************/
8859 void reply_transs2(struct smb_request *req)
8861 connection_struct *conn = req->conn;
8862 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8863 struct trans_state *state;
8865 START_PROFILE(SMBtranss2);
8867 show_msg((const char *)req->inbuf);
8869 if (req->wct < 8) {
8870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8871 END_PROFILE(SMBtranss2);
8872 return;
8875 for (state = conn->pending_trans; state != NULL;
8876 state = state->next) {
8877 if (state->mid == req->mid) {
8878 break;
8882 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8884 END_PROFILE(SMBtranss2);
8885 return;
8888 /* Revise state->total_param and state->total_data in case they have
8889 changed downwards */
8891 if (SVAL(req->vwv+0, 0) < state->total_param)
8892 state->total_param = SVAL(req->vwv+0, 0);
8893 if (SVAL(req->vwv+1, 0) < state->total_data)
8894 state->total_data = SVAL(req->vwv+1, 0);
8896 pcnt = SVAL(req->vwv+2, 0);
8897 poff = SVAL(req->vwv+3, 0);
8898 pdisp = SVAL(req->vwv+4, 0);
8900 dcnt = SVAL(req->vwv+5, 0);
8901 doff = SVAL(req->vwv+6, 0);
8902 ddisp = SVAL(req->vwv+7, 0);
8904 state->received_param += pcnt;
8905 state->received_data += dcnt;
8907 if ((state->received_data > state->total_data) ||
8908 (state->received_param > state->total_param))
8909 goto bad_param;
8911 if (pcnt) {
8912 if (trans_oob(state->total_param, pdisp, pcnt)
8913 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8914 goto bad_param;
8916 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8919 if (dcnt) {
8920 if (trans_oob(state->total_data, ddisp, dcnt)
8921 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8922 goto bad_param;
8924 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8927 if ((state->received_param < state->total_param) ||
8928 (state->received_data < state->total_data)) {
8929 END_PROFILE(SMBtranss2);
8930 return;
8933 handle_trans2(conn, req, state);
8935 DLIST_REMOVE(conn->pending_trans, state);
8936 SAFE_FREE(state->data);
8937 SAFE_FREE(state->param);
8938 TALLOC_FREE(state);
8940 END_PROFILE(SMBtranss2);
8941 return;
8943 bad_param:
8945 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8946 DLIST_REMOVE(conn->pending_trans, state);
8947 SAFE_FREE(state->data);
8948 SAFE_FREE(state->param);
8949 TALLOC_FREE(state);
8950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8951 END_PROFILE(SMBtranss2);
8952 return;