s4-lsaprc: Don't call lsa_OpenPolicy2 in lsa_LookupNames4.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob682b3c4e4ff4a25e95bef914d020e67357cc693b
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);
893 /* Set total params and data to be sent */
894 SSVAL(req->outbuf,smb_tprcnt,paramsize);
895 SSVAL(req->outbuf,smb_tdrcnt,datasize);
897 /* Calculate how many parameters and data we can fit into
898 * this packet. Parameters get precedence
901 params_sent_thistime = MIN(params_to_send,useable_space);
902 data_sent_thistime = useable_space - params_sent_thistime;
903 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
905 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
907 /* smb_proff is the offset from the start of the SMB header to the
908 parameter bytes, however the first 4 bytes of outbuf are
909 the Netbios over TCP header. Thus use smb_base() to subtract
910 them from the calculation */
912 SSVAL(req->outbuf,smb_proff,
913 ((smb_buf(req->outbuf)+alignment_offset)
914 - smb_base(req->outbuf)));
916 if(params_sent_thistime == 0)
917 SSVAL(req->outbuf,smb_prdisp,0);
918 else
919 /* Absolute displacement of param bytes sent in this packet */
920 SSVAL(req->outbuf,smb_prdisp,pp - params);
922 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
923 if(data_sent_thistime == 0) {
924 SSVAL(req->outbuf,smb_droff,0);
925 SSVAL(req->outbuf,smb_drdisp, 0);
926 } else {
927 /* The offset of the data bytes is the offset of the
928 parameter bytes plus the number of parameters being sent this time */
929 SSVAL(req->outbuf, smb_droff,
930 ((smb_buf(req->outbuf)+alignment_offset)
931 - smb_base(req->outbuf))
932 + params_sent_thistime + data_alignment_offset);
933 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
936 /* Initialize the padding for alignment */
938 if (alignment_offset != 0) {
939 memset(smb_buf(req->outbuf), 0, alignment_offset);
942 /* Copy the param bytes into the packet */
944 if(params_sent_thistime) {
945 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
946 params_sent_thistime);
949 /* Copy in the data bytes */
950 if(data_sent_thistime) {
951 if (data_alignment_offset != 0) {
952 memset((smb_buf(req->outbuf)+alignment_offset+
953 params_sent_thistime), 0,
954 data_alignment_offset);
956 memcpy(smb_buf(req->outbuf)+alignment_offset
957 +params_sent_thistime+data_alignment_offset,
958 pd,data_sent_thistime);
961 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
962 params_sent_thistime, data_sent_thistime, useable_space));
963 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
964 params_to_send, data_to_send, paramsize, datasize));
966 if (overflow) {
967 error_packet_set((char *)req->outbuf,
968 ERRDOS,ERRbufferoverflow,
969 STATUS_BUFFER_OVERFLOW,
970 __LINE__,__FILE__);
973 /* Send the packet */
974 show_msg((char *)req->outbuf);
975 if (!srv_send_smb(sconn,
976 (char *)req->outbuf,
977 true, req->seqnum+1,
978 IS_CONN_ENCRYPTED(conn),
979 &req->pcd))
980 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
982 TALLOC_FREE(req->outbuf);
984 pp += params_sent_thistime;
985 pd += data_sent_thistime;
987 params_to_send -= params_sent_thistime;
988 data_to_send -= data_sent_thistime;
990 /* Sanity check */
991 if(params_to_send < 0 || data_to_send < 0) {
992 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
993 params_to_send, data_to_send));
994 return;
998 return;
1001 /****************************************************************************
1002 Reply to a TRANSACT2_OPEN.
1003 ****************************************************************************/
1005 static void call_trans2open(connection_struct *conn,
1006 struct smb_request *req,
1007 char **pparams, int total_params,
1008 char **ppdata, int total_data,
1009 unsigned int max_data_bytes)
1011 struct smb_filename *smb_fname = NULL;
1012 char *params = *pparams;
1013 char *pdata = *ppdata;
1014 int deny_mode;
1015 int32 open_attr;
1016 bool oplock_request;
1017 #if 0
1018 bool return_additional_info;
1019 int16 open_sattr;
1020 time_t open_time;
1021 #endif
1022 int open_ofun;
1023 uint32 open_size;
1024 char *pname;
1025 char *fname = NULL;
1026 off_t size=0;
1027 int fattr=0,mtime=0;
1028 SMB_INO_T inode = 0;
1029 int smb_action = 0;
1030 files_struct *fsp;
1031 struct ea_list *ea_list = NULL;
1032 uint16 flags = 0;
1033 NTSTATUS status;
1034 uint32 access_mask;
1035 uint32 share_mode;
1036 uint32 create_disposition;
1037 uint32 create_options = 0;
1038 uint32_t private_flags = 0;
1039 TALLOC_CTX *ctx = talloc_tos();
1042 * Ensure we have enough parameters to perform the operation.
1045 if (total_params < 29) {
1046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1047 goto out;
1050 flags = SVAL(params, 0);
1051 deny_mode = SVAL(params, 2);
1052 open_attr = SVAL(params,6);
1053 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1054 if (oplock_request) {
1055 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1058 #if 0
1059 return_additional_info = BITSETW(params,0);
1060 open_sattr = SVAL(params, 4);
1061 open_time = make_unix_date3(params+8);
1062 #endif
1063 open_ofun = SVAL(params,12);
1064 open_size = IVAL(params,14);
1065 pname = &params[28];
1067 if (IS_IPC(conn)) {
1068 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1069 goto out;
1072 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1073 total_params - 28, STR_TERMINATE,
1074 &status);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 reply_nterror(req, status);
1077 goto out;
1080 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1081 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1082 (unsigned int)open_ofun, open_size));
1084 status = filename_convert(ctx,
1085 conn,
1086 req->flags2 & FLAGS2_DFS_PATHNAMES,
1087 fname,
1089 NULL,
1090 &smb_fname);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1093 reply_botherror(req,
1094 NT_STATUS_PATH_NOT_COVERED,
1095 ERRSRV, ERRbadpath);
1096 goto out;
1098 reply_nterror(req, status);
1099 goto out;
1102 if (open_ofun == 0) {
1103 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1104 goto out;
1107 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1108 open_ofun,
1109 &access_mask, &share_mode,
1110 &create_disposition,
1111 &create_options,
1112 &private_flags)) {
1113 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1114 goto out;
1117 /* Any data in this call is an EA list. */
1118 if (total_data && (total_data != 4)) {
1119 if (total_data < 10) {
1120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1121 goto out;
1124 if (IVAL(pdata,0) > total_data) {
1125 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1126 IVAL(pdata,0), (unsigned int)total_data));
1127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1128 goto out;
1131 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1132 total_data - 4);
1133 if (!ea_list) {
1134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1135 goto out;
1138 if (!lp_ea_support(SNUM(conn))) {
1139 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1140 goto out;
1144 status = SMB_VFS_CREATE_FILE(
1145 conn, /* conn */
1146 req, /* req */
1147 0, /* root_dir_fid */
1148 smb_fname, /* fname */
1149 access_mask, /* access_mask */
1150 share_mode, /* share_access */
1151 create_disposition, /* create_disposition*/
1152 create_options, /* create_options */
1153 open_attr, /* file_attributes */
1154 oplock_request, /* oplock_request */
1155 open_size, /* allocation_size */
1156 private_flags,
1157 NULL, /* sd */
1158 ea_list, /* ea_list */
1159 &fsp, /* result */
1160 &smb_action); /* psbuf */
1162 if (!NT_STATUS_IS_OK(status)) {
1163 if (open_was_deferred(req->sconn, req->mid)) {
1164 /* We have re-scheduled this call. */
1165 goto out;
1167 reply_openerror(req, status);
1168 goto out;
1171 size = get_file_size_stat(&smb_fname->st);
1172 fattr = dos_mode(conn, smb_fname);
1173 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1174 inode = smb_fname->st.st_ex_ino;
1175 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1176 close_file(req, fsp, ERROR_CLOSE);
1177 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1178 goto out;
1181 /* Realloc the size of parameters and data we will return */
1182 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1183 if(*pparams == NULL ) {
1184 reply_nterror(req, NT_STATUS_NO_MEMORY);
1185 goto out;
1187 params = *pparams;
1189 SSVAL(params,0,fsp->fnum);
1190 SSVAL(params,2,fattr);
1191 srv_put_dos_date2(params,4, mtime);
1192 SIVAL(params,8, (uint32)size);
1193 SSVAL(params,12,deny_mode);
1194 SSVAL(params,14,0); /* open_type - file or directory. */
1195 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1197 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1198 smb_action |= EXTENDED_OPLOCK_GRANTED;
1201 SSVAL(params,18,smb_action);
1204 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1206 SIVAL(params,20,inode);
1207 SSVAL(params,24,0); /* Padding. */
1208 if (flags & 8) {
1209 uint32 ea_size = estimate_ea_size(conn, fsp,
1210 fsp->fsp_name->base_name);
1211 SIVAL(params, 26, ea_size);
1212 } else {
1213 SIVAL(params, 26, 0);
1216 /* Send the required number of replies */
1217 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1218 out:
1219 TALLOC_FREE(smb_fname);
1222 /*********************************************************
1223 Routine to check if a given string matches exactly.
1224 as a special case a mask of "." does NOT match. That
1225 is required for correct wildcard semantics
1226 Case can be significant or not.
1227 **********************************************************/
1229 static bool exact_match(bool has_wild,
1230 bool case_sensitive,
1231 const char *str,
1232 const char *mask)
1234 if (mask[0] == '.' && mask[1] == 0) {
1235 return false;
1238 if (has_wild) {
1239 return false;
1242 if (case_sensitive) {
1243 return strcmp(str,mask)==0;
1244 } else {
1245 return strcasecmp_m(str,mask) == 0;
1249 /****************************************************************************
1250 Return the filetype for UNIX extensions.
1251 ****************************************************************************/
1253 static uint32 unix_filetype(mode_t mode)
1255 if(S_ISREG(mode))
1256 return UNIX_TYPE_FILE;
1257 else if(S_ISDIR(mode))
1258 return UNIX_TYPE_DIR;
1259 #ifdef S_ISLNK
1260 else if(S_ISLNK(mode))
1261 return UNIX_TYPE_SYMLINK;
1262 #endif
1263 #ifdef S_ISCHR
1264 else if(S_ISCHR(mode))
1265 return UNIX_TYPE_CHARDEV;
1266 #endif
1267 #ifdef S_ISBLK
1268 else if(S_ISBLK(mode))
1269 return UNIX_TYPE_BLKDEV;
1270 #endif
1271 #ifdef S_ISFIFO
1272 else if(S_ISFIFO(mode))
1273 return UNIX_TYPE_FIFO;
1274 #endif
1275 #ifdef S_ISSOCK
1276 else if(S_ISSOCK(mode))
1277 return UNIX_TYPE_SOCKET;
1278 #endif
1280 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1281 return UNIX_TYPE_UNKNOWN;
1284 /****************************************************************************
1285 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1286 ****************************************************************************/
1288 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1290 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1291 const SMB_STRUCT_STAT *psbuf,
1292 uint32 perms,
1293 enum perm_type ptype,
1294 mode_t *ret_perms)
1296 mode_t ret = 0;
1298 if (perms == SMB_MODE_NO_CHANGE) {
1299 if (!VALID_STAT(*psbuf)) {
1300 return NT_STATUS_INVALID_PARAMETER;
1301 } else {
1302 *ret_perms = psbuf->st_ex_mode;
1303 return NT_STATUS_OK;
1307 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1308 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1309 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1310 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1311 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1312 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1313 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1314 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1315 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1316 #ifdef S_ISVTX
1317 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1318 #endif
1319 #ifdef S_ISGID
1320 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1321 #endif
1322 #ifdef S_ISUID
1323 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1324 #endif
1326 switch (ptype) {
1327 case PERM_NEW_FILE:
1328 /* Apply mode mask */
1329 ret &= lp_create_mask(SNUM(conn));
1330 /* Add in force bits */
1331 ret |= lp_force_create_mode(SNUM(conn));
1332 break;
1333 case PERM_NEW_DIR:
1334 ret &= lp_dir_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_dir_mode(SNUM(conn));
1337 break;
1338 case PERM_EXISTING_FILE:
1339 /* Apply mode mask */
1340 ret &= lp_security_mask(SNUM(conn));
1341 /* Add in force bits */
1342 ret |= lp_force_security_mode(SNUM(conn));
1343 break;
1344 case PERM_EXISTING_DIR:
1345 /* Apply mode mask */
1346 ret &= lp_dir_security_mask(SNUM(conn));
1347 /* Add in force bits */
1348 ret |= lp_force_dir_security_mode(SNUM(conn));
1349 break;
1352 *ret_perms = ret;
1353 return NT_STATUS_OK;
1356 /****************************************************************************
1357 Needed to show the msdfs symlinks as directories. Modifies psbuf
1358 to be a directory if it's a msdfs link.
1359 ****************************************************************************/
1361 static bool check_msdfs_link(connection_struct *conn,
1362 const char *pathname,
1363 SMB_STRUCT_STAT *psbuf)
1365 int saved_errno = errno;
1366 if(lp_host_msdfs() &&
1367 lp_msdfs_root(SNUM(conn)) &&
1368 is_msdfs_link(conn, pathname, psbuf)) {
1370 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1371 "as a directory\n",
1372 pathname));
1373 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1374 errno = saved_errno;
1375 return true;
1377 errno = saved_errno;
1378 return false;
1382 /****************************************************************************
1383 Get a level dependent lanman2 dir entry.
1384 ****************************************************************************/
1386 struct smbd_dirptr_lanman2_state {
1387 connection_struct *conn;
1388 uint32_t info_level;
1389 bool check_mangled_names;
1390 bool has_wild;
1391 bool got_exact_match;
1394 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1395 void *private_data,
1396 const char *dname,
1397 const char *mask,
1398 char **_fname)
1400 struct smbd_dirptr_lanman2_state *state =
1401 (struct smbd_dirptr_lanman2_state *)private_data;
1402 bool ok;
1403 char mangled_name[13]; /* mangled 8.3 name. */
1404 bool got_match;
1405 const char *fname;
1407 /* Mangle fname if it's an illegal name. */
1408 if (mangle_must_mangle(dname, state->conn->params)) {
1409 ok = name_to_8_3(dname, mangled_name,
1410 true, state->conn->params);
1411 if (!ok) {
1412 return false;
1414 fname = mangled_name;
1415 } else {
1416 fname = dname;
1419 got_match = exact_match(state->has_wild,
1420 state->conn->case_sensitive,
1421 fname, mask);
1422 state->got_exact_match = got_match;
1423 if (!got_match) {
1424 got_match = mask_match(fname, mask,
1425 state->conn->case_sensitive);
1428 if(!got_match && state->check_mangled_names &&
1429 !mangle_is_8_3(fname, false, state->conn->params)) {
1431 * It turns out that NT matches wildcards against
1432 * both long *and* short names. This may explain some
1433 * of the wildcard wierdness from old DOS clients
1434 * that some people have been seeing.... JRA.
1436 /* Force the mangling into 8.3. */
1437 ok = name_to_8_3(fname, mangled_name,
1438 false, state->conn->params);
1439 if (!ok) {
1440 return false;
1443 got_match = exact_match(state->has_wild,
1444 state->conn->case_sensitive,
1445 mangled_name, mask);
1446 state->got_exact_match = got_match;
1447 if (!got_match) {
1448 got_match = mask_match(mangled_name, mask,
1449 state->conn->case_sensitive);
1453 if (!got_match) {
1454 return false;
1457 *_fname = talloc_strdup(ctx, fname);
1458 if (*_fname == NULL) {
1459 return false;
1462 return true;
1465 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1466 void *private_data,
1467 struct smb_filename *smb_fname,
1468 uint32_t *_mode)
1470 struct smbd_dirptr_lanman2_state *state =
1471 (struct smbd_dirptr_lanman2_state *)private_data;
1472 bool ms_dfs_link = false;
1473 uint32_t mode = 0;
1475 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1476 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1477 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1478 "Couldn't lstat [%s] (%s)\n",
1479 smb_fname_str_dbg(smb_fname),
1480 strerror(errno)));
1481 return false;
1483 } else if (!VALID_STAT(smb_fname->st) &&
1484 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1485 /* Needed to show the msdfs symlinks as
1486 * directories */
1488 ms_dfs_link = check_msdfs_link(state->conn,
1489 smb_fname->base_name,
1490 &smb_fname->st);
1491 if (!ms_dfs_link) {
1492 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1493 "Couldn't stat [%s] (%s)\n",
1494 smb_fname_str_dbg(smb_fname),
1495 strerror(errno)));
1496 return false;
1500 if (ms_dfs_link) {
1501 mode = dos_mode_msdfs(state->conn, smb_fname);
1502 } else {
1503 mode = dos_mode(state->conn, smb_fname);
1506 *_mode = mode;
1507 return true;
1510 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1511 connection_struct *conn,
1512 uint16_t flags2,
1513 uint32_t info_level,
1514 struct ea_list *name_list,
1515 bool check_mangled_names,
1516 bool requires_resume_key,
1517 uint32_t mode,
1518 const char *fname,
1519 const struct smb_filename *smb_fname,
1520 int space_remaining,
1521 uint8_t align,
1522 bool do_pad,
1523 char *base_data,
1524 char **ppdata,
1525 char *end_data,
1526 bool *out_of_space,
1527 uint64_t *last_entry_off)
1529 char *p, *q, *pdata = *ppdata;
1530 uint32_t reskey=0;
1531 uint64_t file_size = 0;
1532 uint64_t allocation_size = 0;
1533 uint64_t file_index = 0;
1534 uint32_t len;
1535 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1536 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1537 char *nameptr;
1538 char *last_entry_ptr;
1539 bool was_8_3;
1540 int off;
1541 int pad = 0;
1543 *out_of_space = false;
1545 ZERO_STRUCT(mdate_ts);
1546 ZERO_STRUCT(adate_ts);
1547 ZERO_STRUCT(create_date_ts);
1548 ZERO_STRUCT(cdate_ts);
1550 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1551 file_size = get_file_size_stat(&smb_fname->st);
1553 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1555 file_index = get_FileIndex(conn, &smb_fname->st);
1557 mdate_ts = smb_fname->st.st_ex_mtime;
1558 adate_ts = smb_fname->st.st_ex_atime;
1559 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1560 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1562 if (lp_dos_filetime_resolution(SNUM(conn))) {
1563 dos_filetime_timespec(&create_date_ts);
1564 dos_filetime_timespec(&mdate_ts);
1565 dos_filetime_timespec(&adate_ts);
1566 dos_filetime_timespec(&cdate_ts);
1569 create_date = convert_timespec_to_time_t(create_date_ts);
1570 mdate = convert_timespec_to_time_t(mdate_ts);
1571 adate = convert_timespec_to_time_t(adate_ts);
1573 /* align the record */
1574 SMB_ASSERT(align >= 1);
1576 off = (int)PTR_DIFF(pdata, base_data);
1577 pad = (off + (align-1)) & ~(align-1);
1578 pad -= off;
1580 if (pad && pad > space_remaining) {
1581 *out_of_space = true;
1582 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1583 "for padding (wanted %u, had %d)\n",
1584 (unsigned int)pad,
1585 space_remaining ));
1586 return false; /* Not finished - just out of space */
1589 off += pad;
1590 /* initialize padding to 0 */
1591 if (pad) {
1592 memset(pdata, 0, pad);
1594 space_remaining -= pad;
1596 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1597 space_remaining ));
1599 pdata += pad;
1600 p = pdata;
1601 last_entry_ptr = p;
1603 pad = 0;
1604 off = 0;
1606 switch (info_level) {
1607 case SMB_FIND_INFO_STANDARD:
1608 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1609 if(requires_resume_key) {
1610 SIVAL(p,0,reskey);
1611 p += 4;
1613 srv_put_dos_date2(p,0,create_date);
1614 srv_put_dos_date2(p,4,adate);
1615 srv_put_dos_date2(p,8,mdate);
1616 SIVAL(p,12,(uint32)file_size);
1617 SIVAL(p,16,(uint32)allocation_size);
1618 SSVAL(p,20,mode);
1619 p += 23;
1620 nameptr = p;
1621 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1622 p += ucs2_align(base_data, p, 0);
1624 len = srvstr_push(base_data, flags2, p,
1625 fname, PTR_DIFF(end_data, p),
1626 STR_TERMINATE);
1627 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1628 if (len > 2) {
1629 SCVAL(nameptr, -1, len - 2);
1630 } else {
1631 SCVAL(nameptr, -1, 0);
1633 } else {
1634 if (len > 1) {
1635 SCVAL(nameptr, -1, len - 1);
1636 } else {
1637 SCVAL(nameptr, -1, 0);
1640 p += len;
1641 break;
1643 case SMB_FIND_EA_SIZE:
1644 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1645 if (requires_resume_key) {
1646 SIVAL(p,0,reskey);
1647 p += 4;
1649 srv_put_dos_date2(p,0,create_date);
1650 srv_put_dos_date2(p,4,adate);
1651 srv_put_dos_date2(p,8,mdate);
1652 SIVAL(p,12,(uint32)file_size);
1653 SIVAL(p,16,(uint32)allocation_size);
1654 SSVAL(p,20,mode);
1656 unsigned int ea_size = estimate_ea_size(conn, NULL,
1657 smb_fname->base_name);
1658 SIVAL(p,22,ea_size); /* Extended attributes */
1660 p += 27;
1661 nameptr = p - 1;
1662 len = srvstr_push(base_data, flags2,
1663 p, fname, PTR_DIFF(end_data, p),
1664 STR_TERMINATE | STR_NOALIGN);
1665 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1666 if (len > 2) {
1667 len -= 2;
1668 } else {
1669 len = 0;
1671 } else {
1672 if (len > 1) {
1673 len -= 1;
1674 } else {
1675 len = 0;
1678 SCVAL(nameptr,0,len);
1679 p += len;
1680 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1681 break;
1683 case SMB_FIND_EA_LIST:
1685 struct ea_list *file_list = NULL;
1686 size_t ea_len = 0;
1688 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1689 if (!name_list) {
1690 return false;
1692 if (requires_resume_key) {
1693 SIVAL(p,0,reskey);
1694 p += 4;
1696 srv_put_dos_date2(p,0,create_date);
1697 srv_put_dos_date2(p,4,adate);
1698 srv_put_dos_date2(p,8,mdate);
1699 SIVAL(p,12,(uint32)file_size);
1700 SIVAL(p,16,(uint32)allocation_size);
1701 SSVAL(p,20,mode);
1702 p += 22; /* p now points to the EA area. */
1704 file_list = get_ea_list_from_file(ctx, conn, NULL,
1705 smb_fname->base_name,
1706 &ea_len);
1707 name_list = ea_list_union(name_list, file_list, &ea_len);
1709 /* We need to determine if this entry will fit in the space available. */
1710 /* Max string size is 255 bytes. */
1711 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1712 *out_of_space = true;
1713 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1714 "(wanted %u, had %d)\n",
1715 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1716 space_remaining ));
1717 return False; /* Not finished - just out of space */
1720 /* Push the ea_data followed by the name. */
1721 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1722 nameptr = p;
1723 len = srvstr_push(base_data, flags2,
1724 p + 1, fname, PTR_DIFF(end_data, p+1),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len + 1;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1745 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1746 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1747 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1748 p += 4;
1749 SIVAL(p,0,reskey); p += 4;
1750 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1751 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1752 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1753 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1754 SOFF_T(p,0,file_size); p += 8;
1755 SOFF_T(p,0,allocation_size); p += 8;
1756 SIVAL(p,0,mode); p += 4;
1757 q = p; p += 4; /* q is placeholder for name length. */
1759 unsigned int ea_size = estimate_ea_size(conn, NULL,
1760 smb_fname->base_name);
1761 SIVAL(p,0,ea_size); /* Extended attributes */
1762 p += 4;
1764 /* Clear the short name buffer. This is
1765 * IMPORTANT as not doing so will trigger
1766 * a Win2k client bug. JRA.
1768 if (!was_8_3 && check_mangled_names) {
1769 char mangled_name[13]; /* mangled 8.3 name. */
1770 if (!name_to_8_3(fname,mangled_name,True,
1771 conn->params)) {
1772 /* Error - mangle failed ! */
1773 memset(mangled_name,'\0',12);
1775 mangled_name[12] = 0;
1776 len = srvstr_push(base_data, flags2,
1777 p+2, mangled_name, 24,
1778 STR_UPPER|STR_UNICODE);
1779 if (len < 24) {
1780 memset(p + 2 + len,'\0',24 - len);
1782 SSVAL(p, 0, len);
1783 } else {
1784 memset(p,'\0',26);
1786 p += 2 + 24;
1787 len = srvstr_push(base_data, flags2, p,
1788 fname, PTR_DIFF(end_data, p),
1789 STR_TERMINATE_ASCII);
1790 SIVAL(q,0,len);
1791 p += len;
1793 len = PTR_DIFF(p, pdata);
1794 pad = (len + (align-1)) & ~(align-1);
1796 * offset to the next entry, the caller
1797 * will overwrite it for the last entry
1798 * that's why we always include the padding
1800 SIVAL(pdata,0,pad);
1802 * set padding to zero
1804 if (do_pad) {
1805 memset(p, 0, pad - len);
1806 p = pdata + pad;
1807 } else {
1808 p = pdata + len;
1810 break;
1812 case SMB_FIND_FILE_DIRECTORY_INFO:
1813 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1814 p += 4;
1815 SIVAL(p,0,reskey); p += 4;
1816 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1819 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1820 SOFF_T(p,0,file_size); p += 8;
1821 SOFF_T(p,0,allocation_size); p += 8;
1822 SIVAL(p,0,mode); p += 4;
1823 len = srvstr_push(base_data, flags2,
1824 p + 4, fname, PTR_DIFF(end_data, p+4),
1825 STR_TERMINATE_ASCII);
1826 SIVAL(p,0,len);
1827 p += 4 + len;
1829 len = PTR_DIFF(p, pdata);
1830 pad = (len + (align-1)) & ~(align-1);
1832 * offset to the next entry, the caller
1833 * will overwrite it for the last entry
1834 * that's why we always include the padding
1836 SIVAL(pdata,0,pad);
1838 * set padding to zero
1840 if (do_pad) {
1841 memset(p, 0, pad - len);
1842 p = pdata + pad;
1843 } else {
1844 p = pdata + len;
1846 break;
1848 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1850 p += 4;
1851 SIVAL(p,0,reskey); p += 4;
1852 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1853 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1854 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1856 SOFF_T(p,0,file_size); p += 8;
1857 SOFF_T(p,0,allocation_size); p += 8;
1858 SIVAL(p,0,mode); p += 4;
1859 q = p; p += 4; /* q is placeholder for name length. */
1861 unsigned int ea_size = estimate_ea_size(conn, NULL,
1862 smb_fname->base_name);
1863 SIVAL(p,0,ea_size); /* Extended attributes */
1864 p +=4;
1866 len = srvstr_push(base_data, flags2, p,
1867 fname, PTR_DIFF(end_data, p),
1868 STR_TERMINATE_ASCII);
1869 SIVAL(q, 0, len);
1870 p += len;
1872 len = PTR_DIFF(p, pdata);
1873 pad = (len + (align-1)) & ~(align-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1879 SIVAL(pdata,0,pad);
1881 * set padding to zero
1883 if (do_pad) {
1884 memset(p, 0, pad - len);
1885 p = pdata + pad;
1886 } else {
1887 p = pdata + len;
1889 break;
1891 case SMB_FIND_FILE_NAMES_INFO:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1893 p += 4;
1894 SIVAL(p,0,reskey); p += 4;
1895 p += 4;
1896 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1897 acl on a dir (tridge) */
1898 len = srvstr_push(base_data, flags2, p,
1899 fname, PTR_DIFF(end_data, p),
1900 STR_TERMINATE_ASCII);
1901 SIVAL(p, -4, len);
1902 p += len;
1904 len = PTR_DIFF(p, pdata);
1905 pad = (len + (align-1)) & ~(align-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1911 SIVAL(pdata,0,pad);
1913 * set padding to zero
1915 if (do_pad) {
1916 memset(p, 0, pad - len);
1917 p = pdata + pad;
1918 } else {
1919 p = pdata + len;
1921 break;
1923 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1925 p += 4;
1926 SIVAL(p,0,reskey); p += 4;
1927 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1930 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1931 SOFF_T(p,0,file_size); p += 8;
1932 SOFF_T(p,0,allocation_size); p += 8;
1933 SIVAL(p,0,mode); p += 4;
1934 q = p; p += 4; /* q is placeholder for name length. */
1936 unsigned int ea_size = estimate_ea_size(conn, NULL,
1937 smb_fname->base_name);
1938 SIVAL(p,0,ea_size); /* Extended attributes */
1939 p +=4;
1941 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1942 SBVAL(p,0,file_index); p += 8;
1943 len = srvstr_push(base_data, flags2, p,
1944 fname, PTR_DIFF(end_data, p),
1945 STR_TERMINATE_ASCII);
1946 SIVAL(q, 0, len);
1947 p += len;
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1956 SIVAL(pdata,0,pad);
1958 * set padding to zero
1960 if (do_pad) {
1961 memset(p, 0, pad - len);
1962 p = pdata + pad;
1963 } else {
1964 p = pdata + len;
1966 break;
1968 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1969 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1970 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1971 p += 4;
1972 SIVAL(p,0,reskey); p += 4;
1973 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1974 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1975 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1976 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1977 SOFF_T(p,0,file_size); p += 8;
1978 SOFF_T(p,0,allocation_size); p += 8;
1979 SIVAL(p,0,mode); p += 4;
1980 q = p; p += 4; /* q is placeholder for name length */
1982 unsigned int ea_size = estimate_ea_size(conn, NULL,
1983 smb_fname->base_name);
1984 SIVAL(p,0,ea_size); /* Extended attributes */
1985 p +=4;
1987 /* Clear the short name buffer. This is
1988 * IMPORTANT as not doing so will trigger
1989 * a Win2k client bug. JRA.
1991 if (!was_8_3 && check_mangled_names) {
1992 char mangled_name[13]; /* mangled 8.3 name. */
1993 if (!name_to_8_3(fname,mangled_name,True,
1994 conn->params)) {
1995 /* Error - mangle failed ! */
1996 memset(mangled_name,'\0',12);
1998 mangled_name[12] = 0;
1999 len = srvstr_push(base_data, flags2,
2000 p+2, mangled_name, 24,
2001 STR_UPPER|STR_UNICODE);
2002 SSVAL(p, 0, len);
2003 if (len < 24) {
2004 memset(p + 2 + len,'\0',24 - len);
2006 SSVAL(p, 0, len);
2007 } else {
2008 memset(p,'\0',26);
2010 p += 26;
2011 SSVAL(p,0,0); p += 2; /* Reserved ? */
2012 SBVAL(p,0,file_index); p += 8;
2013 len = srvstr_push(base_data, flags2, p,
2014 fname, PTR_DIFF(end_data, p),
2015 STR_TERMINATE_ASCII);
2016 SIVAL(q,0,len);
2017 p += len;
2019 len = PTR_DIFF(p, pdata);
2020 pad = (len + (align-1)) & ~(align-1);
2022 * offset to the next entry, the caller
2023 * will overwrite it for the last entry
2024 * that's why we always include the padding
2026 SIVAL(pdata,0,pad);
2028 * set padding to zero
2030 if (do_pad) {
2031 memset(p, 0, pad - len);
2032 p = pdata + pad;
2033 } else {
2034 p = pdata + len;
2036 break;
2038 /* CIFS UNIX Extension. */
2040 case SMB_FIND_FILE_UNIX:
2041 case SMB_FIND_FILE_UNIX_INFO2:
2042 p+= 4;
2043 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2045 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2047 if (info_level == SMB_FIND_FILE_UNIX) {
2048 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2049 p = store_file_unix_basic(conn, p,
2050 NULL, &smb_fname->st);
2051 len = srvstr_push(base_data, flags2, p,
2052 fname, PTR_DIFF(end_data, p),
2053 STR_TERMINATE);
2054 } else {
2055 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2056 p = store_file_unix_basic_info2(conn, p,
2057 NULL, &smb_fname->st);
2058 nameptr = p;
2059 p += 4;
2060 len = srvstr_push(base_data, flags2, p, fname,
2061 PTR_DIFF(end_data, p), 0);
2062 SIVAL(nameptr, 0, len);
2065 p += len;
2067 len = PTR_DIFF(p, pdata);
2068 pad = (len + (align-1)) & ~(align-1);
2070 * offset to the next entry, the caller
2071 * will overwrite it for the last entry
2072 * that's why we always include the padding
2074 SIVAL(pdata,0,pad);
2076 * set padding to zero
2078 if (do_pad) {
2079 memset(p, 0, pad - len);
2080 p = pdata + pad;
2081 } else {
2082 p = pdata + len;
2084 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2086 break;
2088 default:
2089 return false;
2092 if (PTR_DIFF(p,pdata) > space_remaining) {
2093 *out_of_space = true;
2094 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2095 "(wanted %u, had %d)\n",
2096 (unsigned int)PTR_DIFF(p,pdata),
2097 space_remaining ));
2098 return false; /* Not finished - just out of space */
2101 /* Setup the last entry pointer, as an offset from base_data */
2102 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2103 /* Advance the data pointer to the next slot */
2104 *ppdata = p;
2106 return true;
2109 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2110 connection_struct *conn,
2111 struct dptr_struct *dirptr,
2112 uint16 flags2,
2113 const char *path_mask,
2114 uint32 dirtype,
2115 int info_level,
2116 int requires_resume_key,
2117 bool dont_descend,
2118 bool ask_sharemode,
2119 uint8_t align,
2120 bool do_pad,
2121 char **ppdata,
2122 char *base_data,
2123 char *end_data,
2124 int space_remaining,
2125 bool *out_of_space,
2126 bool *got_exact_match,
2127 int *_last_entry_off,
2128 struct ea_list *name_list)
2130 const char *p;
2131 const char *mask = NULL;
2132 long prev_dirpos = 0;
2133 uint32_t mode = 0;
2134 char *fname = NULL;
2135 struct smb_filename *smb_fname = NULL;
2136 struct smbd_dirptr_lanman2_state state;
2137 bool ok;
2138 uint64_t last_entry_off = 0;
2140 ZERO_STRUCT(state);
2141 state.conn = conn;
2142 state.info_level = info_level;
2143 state.check_mangled_names = lp_manglednames(conn->params);
2144 state.has_wild = dptr_has_wild(dirptr);
2145 state.got_exact_match = false;
2147 *out_of_space = false;
2148 *got_exact_match = false;
2150 p = strrchr_m(path_mask,'/');
2151 if(p != NULL) {
2152 if(p[1] == '\0') {
2153 mask = "*.*";
2154 } else {
2155 mask = p+1;
2157 } else {
2158 mask = path_mask;
2161 ok = smbd_dirptr_get_entry(ctx,
2162 dirptr,
2163 mask,
2164 dirtype,
2165 dont_descend,
2166 ask_sharemode,
2167 smbd_dirptr_lanman2_match_fn,
2168 smbd_dirptr_lanman2_mode_fn,
2169 &state,
2170 &fname,
2171 &smb_fname,
2172 &mode,
2173 &prev_dirpos);
2174 if (!ok) {
2175 return false;
2178 *got_exact_match = state.got_exact_match;
2180 ok = smbd_marshall_dir_entry(ctx,
2181 conn,
2182 flags2,
2183 info_level,
2184 name_list,
2185 state.check_mangled_names,
2186 requires_resume_key,
2187 mode,
2188 fname,
2189 smb_fname,
2190 space_remaining,
2191 align,
2192 do_pad,
2193 base_data,
2194 ppdata,
2195 end_data,
2196 out_of_space,
2197 &last_entry_off);
2198 TALLOC_FREE(fname);
2199 TALLOC_FREE(smb_fname);
2200 if (*out_of_space) {
2201 dptr_SeekDir(dirptr, prev_dirpos);
2202 return false;
2204 if (!ok) {
2205 return false;
2208 *_last_entry_off = last_entry_off;
2209 return true;
2212 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2213 connection_struct *conn,
2214 struct dptr_struct *dirptr,
2215 uint16 flags2,
2216 const char *path_mask,
2217 uint32 dirtype,
2218 int info_level,
2219 bool requires_resume_key,
2220 bool dont_descend,
2221 bool ask_sharemode,
2222 char **ppdata,
2223 char *base_data,
2224 char *end_data,
2225 int space_remaining,
2226 bool *out_of_space,
2227 bool *got_exact_match,
2228 int *last_entry_off,
2229 struct ea_list *name_list)
2231 uint8_t align = 4;
2232 const bool do_pad = true;
2234 if (info_level >= 1 && info_level <= 3) {
2235 /* No alignment on earlier info levels. */
2236 align = 1;
2239 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2240 path_mask, dirtype, info_level,
2241 requires_resume_key, dont_descend, ask_sharemode,
2242 align, do_pad,
2243 ppdata, base_data, end_data,
2244 space_remaining,
2245 out_of_space, got_exact_match,
2246 last_entry_off, name_list);
2249 /****************************************************************************
2250 Reply to a TRANS2_FINDFIRST.
2251 ****************************************************************************/
2253 static void call_trans2findfirst(connection_struct *conn,
2254 struct smb_request *req,
2255 char **pparams, int total_params,
2256 char **ppdata, int total_data,
2257 unsigned int max_data_bytes)
2259 /* We must be careful here that we don't return more than the
2260 allowed number of data bytes. If this means returning fewer than
2261 maxentries then so be it. We assume that the redirector has
2262 enough room for the fixed number of parameter bytes it has
2263 requested. */
2264 struct smb_filename *smb_dname = NULL;
2265 char *params = *pparams;
2266 char *pdata = *ppdata;
2267 char *data_end;
2268 uint32 dirtype;
2269 int maxentries;
2270 uint16 findfirst_flags;
2271 bool close_after_first;
2272 bool close_if_end;
2273 bool requires_resume_key;
2274 int info_level;
2275 char *directory = NULL;
2276 char *mask = NULL;
2277 char *p;
2278 int last_entry_off=0;
2279 int dptr_num = -1;
2280 int numentries = 0;
2281 int i;
2282 bool finished = False;
2283 bool dont_descend = False;
2284 bool out_of_space = False;
2285 int space_remaining;
2286 bool mask_contains_wcard = False;
2287 struct ea_list *ea_list = NULL;
2288 NTSTATUS ntstatus = NT_STATUS_OK;
2289 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2290 TALLOC_CTX *ctx = talloc_tos();
2291 struct dptr_struct *dirptr = NULL;
2292 struct smbd_server_connection *sconn = req->sconn;
2293 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2294 bool backup_priv = false;
2296 if (total_params < 13) {
2297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2298 goto out;
2301 dirtype = SVAL(params,0);
2302 maxentries = SVAL(params,2);
2303 findfirst_flags = SVAL(params,4);
2304 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2305 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2306 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2307 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2308 security_token_has_privilege(get_current_nttok(conn),
2309 SEC_PRIV_BACKUP));
2311 info_level = SVAL(params,6);
2313 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2314 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2315 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2316 (int)backup_priv,
2317 info_level, max_data_bytes));
2319 if (!maxentries) {
2320 /* W2K3 seems to treat zero as 1. */
2321 maxentries = 1;
2324 switch (info_level) {
2325 case SMB_FIND_INFO_STANDARD:
2326 case SMB_FIND_EA_SIZE:
2327 case SMB_FIND_EA_LIST:
2328 case SMB_FIND_FILE_DIRECTORY_INFO:
2329 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2330 case SMB_FIND_FILE_NAMES_INFO:
2331 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2332 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2333 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2334 break;
2335 case SMB_FIND_FILE_UNIX:
2336 case SMB_FIND_FILE_UNIX_INFO2:
2337 /* Always use filesystem for UNIX mtime query. */
2338 ask_sharemode = false;
2339 if (!lp_unix_extensions()) {
2340 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2341 goto out;
2343 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2344 break;
2345 default:
2346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2347 goto out;
2350 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2351 params+12, total_params - 12,
2352 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2353 if (!NT_STATUS_IS_OK(ntstatus)) {
2354 reply_nterror(req, ntstatus);
2355 goto out;
2358 if (backup_priv) {
2359 become_root();
2360 ntstatus = filename_convert_with_privilege(ctx,
2361 conn,
2362 req,
2363 directory,
2364 ucf_flags,
2365 &mask_contains_wcard,
2366 &smb_dname);
2367 } else {
2368 ntstatus = filename_convert(ctx, conn,
2369 req->flags2 & FLAGS2_DFS_PATHNAMES,
2370 directory,
2371 ucf_flags,
2372 &mask_contains_wcard,
2373 &smb_dname);
2376 if (!NT_STATUS_IS_OK(ntstatus)) {
2377 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2378 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2379 ERRSRV, ERRbadpath);
2380 goto out;
2382 reply_nterror(req, ntstatus);
2383 goto out;
2386 mask = smb_dname->original_lcomp;
2388 directory = smb_dname->base_name;
2390 p = strrchr_m(directory,'/');
2391 if(p == NULL) {
2392 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2393 if((directory[0] == '.') && (directory[1] == '\0')) {
2394 mask = talloc_strdup(ctx,"*");
2395 if (!mask) {
2396 reply_nterror(req, NT_STATUS_NO_MEMORY);
2397 goto out;
2399 mask_contains_wcard = True;
2401 } else {
2402 *p = 0;
2405 if (p == NULL || p == directory) {
2406 /* Ensure we don't have a directory name of "". */
2407 directory = talloc_strdup(talloc_tos(), ".");
2408 if (!directory) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2410 goto out;
2414 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2416 if (info_level == SMB_FIND_EA_LIST) {
2417 uint32 ea_size;
2419 if (total_data < 4) {
2420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2421 goto out;
2424 ea_size = IVAL(pdata,0);
2425 if (ea_size != total_data) {
2426 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2427 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2429 goto out;
2432 if (!lp_ea_support(SNUM(conn))) {
2433 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2434 goto out;
2437 /* Pull out the list of names. */
2438 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2439 if (!ea_list) {
2440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2441 goto out;
2445 *ppdata = (char *)SMB_REALLOC(
2446 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2447 if(*ppdata == NULL ) {
2448 reply_nterror(req, NT_STATUS_NO_MEMORY);
2449 goto out;
2451 pdata = *ppdata;
2452 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2454 /* Realloc the params space */
2455 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2456 if (*pparams == NULL) {
2457 reply_nterror(req, NT_STATUS_NO_MEMORY);
2458 goto out;
2460 params = *pparams;
2462 /* Save the wildcard match and attribs we are using on this directory -
2463 needed as lanman2 assumes these are being saved between calls */
2465 ntstatus = dptr_create(conn,
2466 req,
2467 NULL, /* fsp */
2468 directory,
2469 False,
2470 True,
2471 req->smbpid,
2472 mask,
2473 mask_contains_wcard,
2474 dirtype,
2475 &dirptr);
2477 if (!NT_STATUS_IS_OK(ntstatus)) {
2478 reply_nterror(req, ntstatus);
2479 goto out;
2482 if (backup_priv) {
2483 /* Remember this in case we have
2484 to do a findnext. */
2485 dptr_set_priv(dirptr);
2488 dptr_num = dptr_dnum(dirptr);
2489 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2491 /* Initialize per TRANS2_FIND_FIRST operation data */
2492 dptr_init_search_op(dirptr);
2494 /* We don't need to check for VOL here as this is returned by
2495 a different TRANS2 call. */
2497 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2498 directory,lp_dontdescend(SNUM(conn))));
2499 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2500 dont_descend = True;
2502 p = pdata;
2503 space_remaining = max_data_bytes;
2504 out_of_space = False;
2506 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2507 bool got_exact_match = False;
2509 /* this is a heuristic to avoid seeking the dirptr except when
2510 absolutely necessary. It allows for a filename of about 40 chars */
2511 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2512 out_of_space = True;
2513 finished = False;
2514 } else {
2515 finished = !get_lanman2_dir_entry(ctx,
2516 conn,
2517 dirptr,
2518 req->flags2,
2519 mask,dirtype,info_level,
2520 requires_resume_key,dont_descend,
2521 ask_sharemode,
2522 &p,pdata,data_end,
2523 space_remaining, &out_of_space,
2524 &got_exact_match,
2525 &last_entry_off, ea_list);
2528 if (finished && out_of_space)
2529 finished = False;
2531 if (!finished && !out_of_space)
2532 numentries++;
2535 * As an optimisation if we know we aren't looking
2536 * for a wildcard name (ie. the name matches the wildcard exactly)
2537 * then we can finish on any (first) match.
2538 * This speeds up large directory searches. JRA.
2541 if(got_exact_match)
2542 finished = True;
2544 /* Ensure space_remaining never goes -ve. */
2545 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2546 space_remaining = 0;
2547 out_of_space = true;
2548 } else {
2549 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2553 /* Check if we can close the dirptr */
2554 if(close_after_first || (finished && close_if_end)) {
2555 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2556 dptr_close(sconn, &dptr_num);
2560 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2561 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2562 * the protocol level is less than NT1. Tested with smbclient. JRA.
2563 * This should fix the OS/2 client bug #2335.
2566 if(numentries == 0) {
2567 dptr_close(sconn, &dptr_num);
2568 if (get_Protocol() < PROTOCOL_NT1) {
2569 reply_force_doserror(req, ERRDOS, ERRnofiles);
2570 goto out;
2571 } else {
2572 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2573 ERRDOS, ERRbadfile);
2574 goto out;
2578 /* At this point pdata points to numentries directory entries. */
2580 /* Set up the return parameter block */
2581 SSVAL(params,0,dptr_num);
2582 SSVAL(params,2,numentries);
2583 SSVAL(params,4,finished);
2584 SSVAL(params,6,0); /* Never an EA error */
2585 SSVAL(params,8,last_entry_off);
2587 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2588 max_data_bytes);
2590 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2591 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2592 if (!directory) {
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2597 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2598 smb_fn_name(req->cmd),
2599 mask, directory, dirtype, numentries ) );
2602 * Force a name mangle here to ensure that the
2603 * mask as an 8.3 name is top of the mangled cache.
2604 * The reasons for this are subtle. Don't remove
2605 * this code unless you know what you are doing
2606 * (see PR#13758). JRA.
2609 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2610 char mangled_name[13];
2611 name_to_8_3(mask, mangled_name, True, conn->params);
2613 out:
2615 if (backup_priv) {
2616 unbecome_root();
2619 TALLOC_FREE(smb_dname);
2620 return;
2623 /****************************************************************************
2624 Reply to a TRANS2_FINDNEXT.
2625 ****************************************************************************/
2627 static void call_trans2findnext(connection_struct *conn,
2628 struct smb_request *req,
2629 char **pparams, int total_params,
2630 char **ppdata, int total_data,
2631 unsigned int max_data_bytes)
2633 /* We must be careful here that we don't return more than the
2634 allowed number of data bytes. If this means returning fewer than
2635 maxentries then so be it. We assume that the redirector has
2636 enough room for the fixed number of parameter bytes it has
2637 requested. */
2638 char *params = *pparams;
2639 char *pdata = *ppdata;
2640 char *data_end;
2641 int dptr_num;
2642 int maxentries;
2643 uint16 info_level;
2644 uint32 resume_key;
2645 uint16 findnext_flags;
2646 bool close_after_request;
2647 bool close_if_end;
2648 bool requires_resume_key;
2649 bool continue_bit;
2650 bool mask_contains_wcard = False;
2651 char *resume_name = NULL;
2652 const char *mask = NULL;
2653 const char *directory = NULL;
2654 char *p = NULL;
2655 uint16 dirtype;
2656 int numentries = 0;
2657 int i, last_entry_off=0;
2658 bool finished = False;
2659 bool dont_descend = False;
2660 bool out_of_space = False;
2661 int space_remaining;
2662 struct ea_list *ea_list = NULL;
2663 NTSTATUS ntstatus = NT_STATUS_OK;
2664 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2665 TALLOC_CTX *ctx = talloc_tos();
2666 struct dptr_struct *dirptr;
2667 struct smbd_server_connection *sconn = req->sconn;
2668 bool backup_priv = false;
2670 if (total_params < 13) {
2671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2672 return;
2675 dptr_num = SVAL(params,0);
2676 maxentries = SVAL(params,2);
2677 info_level = SVAL(params,4);
2678 resume_key = IVAL(params,6);
2679 findnext_flags = SVAL(params,10);
2680 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2681 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2682 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2683 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2685 if (!continue_bit) {
2686 /* We only need resume_name if continue_bit is zero. */
2687 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2688 params+12,
2689 total_params - 12, STR_TERMINATE, &ntstatus,
2690 &mask_contains_wcard);
2691 if (!NT_STATUS_IS_OK(ntstatus)) {
2692 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2693 complain (it thinks we're asking for the directory above the shared
2694 path or an invalid name). Catch this as the resume name is only compared, never used in
2695 a file access. JRA. */
2696 srvstr_pull_talloc(ctx, params, req->flags2,
2697 &resume_name, params+12,
2698 total_params - 12,
2699 STR_TERMINATE);
2701 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2702 reply_nterror(req, ntstatus);
2703 return;
2708 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2709 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2710 resume_key = %d resume name = %s continue=%d level = %d\n",
2711 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2712 requires_resume_key, resume_key,
2713 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2715 if (!maxentries) {
2716 /* W2K3 seems to treat zero as 1. */
2717 maxentries = 1;
2720 switch (info_level) {
2721 case SMB_FIND_INFO_STANDARD:
2722 case SMB_FIND_EA_SIZE:
2723 case SMB_FIND_EA_LIST:
2724 case SMB_FIND_FILE_DIRECTORY_INFO:
2725 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2726 case SMB_FIND_FILE_NAMES_INFO:
2727 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2728 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2729 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2730 break;
2731 case SMB_FIND_FILE_UNIX:
2732 case SMB_FIND_FILE_UNIX_INFO2:
2733 /* Always use filesystem for UNIX mtime query. */
2734 ask_sharemode = false;
2735 if (!lp_unix_extensions()) {
2736 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2737 return;
2739 break;
2740 default:
2741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2742 return;
2745 if (info_level == SMB_FIND_EA_LIST) {
2746 uint32 ea_size;
2748 if (total_data < 4) {
2749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2750 return;
2753 ea_size = IVAL(pdata,0);
2754 if (ea_size != total_data) {
2755 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2756 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2758 return;
2761 if (!lp_ea_support(SNUM(conn))) {
2762 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2763 return;
2766 /* Pull out the list of names. */
2767 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2768 if (!ea_list) {
2769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2770 return;
2774 *ppdata = (char *)SMB_REALLOC(
2775 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2776 if(*ppdata == NULL) {
2777 reply_nterror(req, NT_STATUS_NO_MEMORY);
2778 return;
2781 pdata = *ppdata;
2782 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2784 /* Realloc the params space */
2785 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2786 if(*pparams == NULL ) {
2787 reply_nterror(req, NT_STATUS_NO_MEMORY);
2788 return;
2791 params = *pparams;
2793 /* Check that the dptr is valid */
2794 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2795 reply_nterror(req, STATUS_NO_MORE_FILES);
2796 return;
2799 directory = dptr_path(sconn, dptr_num);
2801 /* Get the wildcard mask from the dptr */
2802 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2803 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2804 reply_nterror(req, STATUS_NO_MORE_FILES);
2805 return;
2808 /* Get the attr mask from the dptr */
2809 dirtype = dptr_attr(sconn, dptr_num);
2811 backup_priv = dptr_get_priv(dirptr);
2813 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2814 "backup_priv = %d\n",
2815 dptr_num, mask, dirtype,
2816 (long)dirptr,
2817 dptr_TellDir(dirptr),
2818 (int)backup_priv));
2820 /* Initialize per TRANS2_FIND_NEXT operation data */
2821 dptr_init_search_op(dirptr);
2823 /* We don't need to check for VOL here as this is returned by
2824 a different TRANS2 call. */
2826 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2827 directory,lp_dontdescend(SNUM(conn))));
2828 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2829 dont_descend = True;
2831 p = pdata;
2832 space_remaining = max_data_bytes;
2833 out_of_space = False;
2835 if (backup_priv) {
2836 become_root();
2840 * Seek to the correct position. We no longer use the resume key but
2841 * depend on the last file name instead.
2844 if(!continue_bit && resume_name && *resume_name) {
2845 SMB_STRUCT_STAT st;
2847 long current_pos = 0;
2849 * Remember, name_to_8_3 is called by
2850 * get_lanman2_dir_entry(), so the resume name
2851 * could be mangled. Ensure we check the unmangled name.
2854 if (mangle_is_mangled(resume_name, conn->params)) {
2855 char *new_resume_name = NULL;
2856 mangle_lookup_name_from_8_3(ctx,
2857 resume_name,
2858 &new_resume_name,
2859 conn->params);
2860 if (new_resume_name) {
2861 resume_name = new_resume_name;
2866 * Fix for NT redirector problem triggered by resume key indexes
2867 * changing between directory scans. We now return a resume key of 0
2868 * and instead look for the filename to continue from (also given
2869 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2870 * findfirst/findnext (as is usual) then the directory pointer
2871 * should already be at the correct place.
2874 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2875 } /* end if resume_name && !continue_bit */
2877 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2878 bool got_exact_match = False;
2880 /* this is a heuristic to avoid seeking the dirptr except when
2881 absolutely necessary. It allows for a filename of about 40 chars */
2882 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2883 out_of_space = True;
2884 finished = False;
2885 } else {
2886 finished = !get_lanman2_dir_entry(ctx,
2887 conn,
2888 dirptr,
2889 req->flags2,
2890 mask,dirtype,info_level,
2891 requires_resume_key,dont_descend,
2892 ask_sharemode,
2893 &p,pdata,data_end,
2894 space_remaining, &out_of_space,
2895 &got_exact_match,
2896 &last_entry_off, ea_list);
2899 if (finished && out_of_space)
2900 finished = False;
2902 if (!finished && !out_of_space)
2903 numentries++;
2906 * As an optimisation if we know we aren't looking
2907 * for a wildcard name (ie. the name matches the wildcard exactly)
2908 * then we can finish on any (first) match.
2909 * This speeds up large directory searches. JRA.
2912 if(got_exact_match)
2913 finished = True;
2915 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2918 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2919 smb_fn_name(req->cmd),
2920 mask, directory, dirtype, numentries ) );
2922 /* Check if we can close the dirptr */
2923 if(close_after_request || (finished && close_if_end)) {
2924 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2925 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2928 if (backup_priv) {
2929 unbecome_root();
2932 /* Set up the return parameter block */
2933 SSVAL(params,0,numentries);
2934 SSVAL(params,2,finished);
2935 SSVAL(params,4,0); /* Never an EA error */
2936 SSVAL(params,6,last_entry_off);
2938 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2939 max_data_bytes);
2941 return;
2944 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2946 E_md4hash(lp_servicename(SNUM(conn)),objid);
2947 return objid;
2950 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2952 SMB_ASSERT(extended_info != NULL);
2954 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2955 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2956 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2957 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2958 #ifdef SAMBA_VERSION_REVISION
2959 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2960 #endif
2961 extended_info->samba_subversion = 0;
2962 #ifdef SAMBA_VERSION_RC_RELEASE
2963 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2964 #else
2965 #ifdef SAMBA_VERSION_PRE_RELEASE
2966 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2967 #endif
2968 #endif
2969 #ifdef SAMBA_VERSION_VENDOR_PATCH
2970 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2971 #endif
2972 extended_info->samba_gitcommitdate = 0;
2973 #ifdef SAMBA_VERSION_COMMIT_TIME
2974 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2975 #endif
2977 memset(extended_info->samba_version_string, 0,
2978 sizeof(extended_info->samba_version_string));
2980 snprintf (extended_info->samba_version_string,
2981 sizeof(extended_info->samba_version_string),
2982 "%s", samba_version_string());
2985 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2986 TALLOC_CTX *mem_ctx,
2987 uint16_t info_level,
2988 uint16_t flags2,
2989 unsigned int max_data_bytes,
2990 char **ppdata,
2991 int *ret_data_len)
2993 char *pdata, *end_data;
2994 int data_len = 0, len;
2995 const char *vname = volume_label(SNUM(conn));
2996 int snum = SNUM(conn);
2997 char *fstype = lp_fstype(SNUM(conn));
2998 uint32 additional_flags = 0;
2999 struct smb_filename smb_fname_dot;
3000 SMB_STRUCT_STAT st;
3002 if (IS_IPC(conn)) {
3003 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3004 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3005 "info level (0x%x) on IPC$.\n",
3006 (unsigned int)info_level));
3007 return NT_STATUS_ACCESS_DENIED;
3011 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3013 ZERO_STRUCT(smb_fname_dot);
3014 smb_fname_dot.base_name = discard_const_p(char, ".");
3016 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3017 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3018 return map_nt_error_from_unix(errno);
3021 st = smb_fname_dot.st;
3023 *ppdata = (char *)SMB_REALLOC(
3024 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3025 if (*ppdata == NULL) {
3026 return NT_STATUS_NO_MEMORY;
3029 pdata = *ppdata;
3030 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3031 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3033 switch (info_level) {
3034 case SMB_INFO_ALLOCATION:
3036 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3037 data_len = 18;
3038 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3039 return map_nt_error_from_unix(errno);
3042 block_size = lp_block_size(snum);
3043 if (bsize < block_size) {
3044 uint64_t factor = block_size/bsize;
3045 bsize = block_size;
3046 dsize /= factor;
3047 dfree /= factor;
3049 if (bsize > block_size) {
3050 uint64_t factor = bsize/block_size;
3051 bsize = block_size;
3052 dsize *= factor;
3053 dfree *= factor;
3055 bytes_per_sector = 512;
3056 sectors_per_unit = bsize/bytes_per_sector;
3058 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3059 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3060 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3062 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3063 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3064 SIVAL(pdata,l1_cUnit,dsize);
3065 SIVAL(pdata,l1_cUnitAvail,dfree);
3066 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3067 break;
3070 case SMB_INFO_VOLUME:
3071 /* Return volume name */
3073 * Add volume serial number - hash of a combination of
3074 * the called hostname and the service name.
3076 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3078 * Win2k3 and previous mess this up by sending a name length
3079 * one byte short. I believe only older clients (OS/2 Win9x) use
3080 * this call so try fixing this by adding a terminating null to
3081 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3083 len = srvstr_push(
3084 pdata, flags2,
3085 pdata+l2_vol_szVolLabel, vname,
3086 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3087 STR_NOALIGN|STR_TERMINATE);
3088 SCVAL(pdata,l2_vol_cch,len);
3089 data_len = l2_vol_szVolLabel + len;
3090 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3091 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3092 len, vname));
3093 break;
3095 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3096 case SMB_FS_ATTRIBUTE_INFORMATION:
3098 additional_flags = 0;
3099 #if defined(HAVE_SYS_QUOTAS)
3100 additional_flags |= FILE_VOLUME_QUOTAS;
3101 #endif
3103 if(lp_nt_acl_support(SNUM(conn))) {
3104 additional_flags |= FILE_PERSISTENT_ACLS;
3107 /* Capabilities are filled in at connection time through STATVFS call */
3108 additional_flags |= conn->fs_capabilities;
3109 additional_flags |= lp_parm_int(conn->params->service,
3110 "share", "fake_fscaps",
3113 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3114 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3115 additional_flags); /* FS ATTRIBUTES */
3117 SIVAL(pdata,4,255); /* Max filename component length */
3118 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3119 and will think we can't do long filenames */
3120 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3121 PTR_DIFF(end_data, pdata+12),
3122 STR_UNICODE);
3123 SIVAL(pdata,8,len);
3124 data_len = 12 + len;
3125 break;
3127 case SMB_QUERY_FS_LABEL_INFO:
3128 case SMB_FS_LABEL_INFORMATION:
3129 len = srvstr_push(pdata, flags2, pdata+4, vname,
3130 PTR_DIFF(end_data, pdata+4), 0);
3131 data_len = 4 + len;
3132 SIVAL(pdata,0,len);
3133 break;
3135 case SMB_QUERY_FS_VOLUME_INFO:
3136 case SMB_FS_VOLUME_INFORMATION:
3139 * Add volume serial number - hash of a combination of
3140 * the called hostname and the service name.
3142 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3143 (str_checksum(get_local_machine_name())<<16));
3145 /* Max label len is 32 characters. */
3146 len = srvstr_push(pdata, flags2, pdata+18, vname,
3147 PTR_DIFF(end_data, pdata+18),
3148 STR_UNICODE);
3149 SIVAL(pdata,12,len);
3150 data_len = 18+len;
3152 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3153 (int)strlen(vname),vname, lp_servicename(snum)));
3154 break;
3156 case SMB_QUERY_FS_SIZE_INFO:
3157 case SMB_FS_SIZE_INFORMATION:
3159 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3160 data_len = 24;
3161 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3162 return map_nt_error_from_unix(errno);
3164 block_size = lp_block_size(snum);
3165 if (bsize < block_size) {
3166 uint64_t factor = block_size/bsize;
3167 bsize = block_size;
3168 dsize /= factor;
3169 dfree /= factor;
3171 if (bsize > block_size) {
3172 uint64_t factor = bsize/block_size;
3173 bsize = block_size;
3174 dsize *= factor;
3175 dfree *= factor;
3177 bytes_per_sector = 512;
3178 sectors_per_unit = bsize/bytes_per_sector;
3179 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3180 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3181 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3182 SBIG_UINT(pdata,0,dsize);
3183 SBIG_UINT(pdata,8,dfree);
3184 SIVAL(pdata,16,sectors_per_unit);
3185 SIVAL(pdata,20,bytes_per_sector);
3186 break;
3189 case SMB_FS_FULL_SIZE_INFORMATION:
3191 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3192 data_len = 32;
3193 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3194 return map_nt_error_from_unix(errno);
3196 block_size = lp_block_size(snum);
3197 if (bsize < block_size) {
3198 uint64_t factor = block_size/bsize;
3199 bsize = block_size;
3200 dsize /= factor;
3201 dfree /= factor;
3203 if (bsize > block_size) {
3204 uint64_t factor = bsize/block_size;
3205 bsize = block_size;
3206 dsize *= factor;
3207 dfree *= factor;
3209 bytes_per_sector = 512;
3210 sectors_per_unit = bsize/bytes_per_sector;
3211 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3212 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3213 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3214 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3215 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3216 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3217 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3218 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3219 break;
3222 case SMB_QUERY_FS_DEVICE_INFO:
3223 case SMB_FS_DEVICE_INFORMATION:
3225 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3227 if (!CAN_WRITE(conn)) {
3228 characteristics |= FILE_READ_ONLY_DEVICE;
3230 data_len = 8;
3231 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3232 SIVAL(pdata,4,characteristics);
3233 break;
3236 #ifdef HAVE_SYS_QUOTAS
3237 case SMB_FS_QUOTA_INFORMATION:
3239 * what we have to send --metze:
3241 * Unknown1: 24 NULL bytes
3242 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3243 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3244 * Quota Flags: 2 byte :
3245 * Unknown3: 6 NULL bytes
3247 * 48 bytes total
3249 * details for Quota Flags:
3251 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3252 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3253 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3254 * 0x0001 Enable Quotas: enable quota for this fs
3258 /* we need to fake up a fsp here,
3259 * because its not send in this call
3261 files_struct fsp;
3262 SMB_NTQUOTA_STRUCT quotas;
3264 ZERO_STRUCT(fsp);
3265 ZERO_STRUCT(quotas);
3267 fsp.conn = conn;
3268 fsp.fnum = FNUM_FIELD_INVALID;
3270 /* access check */
3271 if (get_current_uid(conn) != 0) {
3272 DEBUG(0,("set_user_quota: access_denied "
3273 "service [%s] user [%s]\n",
3274 lp_servicename(SNUM(conn)),
3275 conn->session_info->unix_info->unix_name));
3276 return NT_STATUS_ACCESS_DENIED;
3279 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3280 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3281 return map_nt_error_from_unix(errno);
3284 data_len = 48;
3286 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3287 lp_servicename(SNUM(conn))));
3289 /* Unknown1 24 NULL bytes*/
3290 SBIG_UINT(pdata,0,(uint64_t)0);
3291 SBIG_UINT(pdata,8,(uint64_t)0);
3292 SBIG_UINT(pdata,16,(uint64_t)0);
3294 /* Default Soft Quota 8 bytes */
3295 SBIG_UINT(pdata,24,quotas.softlim);
3297 /* Default Hard Quota 8 bytes */
3298 SBIG_UINT(pdata,32,quotas.hardlim);
3300 /* Quota flag 2 bytes */
3301 SSVAL(pdata,40,quotas.qflags);
3303 /* Unknown3 6 NULL bytes */
3304 SSVAL(pdata,42,0);
3305 SIVAL(pdata,44,0);
3307 break;
3309 #endif /* HAVE_SYS_QUOTAS */
3310 case SMB_FS_OBJECTID_INFORMATION:
3312 unsigned char objid[16];
3313 struct smb_extended_info extended_info;
3314 memcpy(pdata,create_volume_objectid(conn, objid),16);
3315 samba_extended_info_version (&extended_info);
3316 SIVAL(pdata,16,extended_info.samba_magic);
3317 SIVAL(pdata,20,extended_info.samba_version);
3318 SIVAL(pdata,24,extended_info.samba_subversion);
3319 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3320 memcpy(pdata+36,extended_info.samba_version_string,28);
3321 data_len = 64;
3322 break;
3326 * Query the version and capabilities of the CIFS UNIX extensions
3327 * in use.
3330 case SMB_QUERY_CIFS_UNIX_INFO:
3332 bool large_write = lp_min_receive_file_size() &&
3333 !srv_is_signing_active(conn->sconn);
3334 bool large_read = !srv_is_signing_active(conn->sconn);
3335 int encrypt_caps = 0;
3337 if (!lp_unix_extensions()) {
3338 return NT_STATUS_INVALID_LEVEL;
3341 switch (conn->encrypt_level) {
3342 case 0:
3343 encrypt_caps = 0;
3344 break;
3345 case 1:
3346 case Auto:
3347 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3348 break;
3349 case Required:
3350 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3351 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3352 large_write = false;
3353 large_read = false;
3354 break;
3357 data_len = 12;
3358 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3359 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3361 /* We have POSIX ACLs, pathname, encryption,
3362 * large read/write, and locking capability. */
3364 SBIG_UINT(pdata,4,((uint64_t)(
3365 CIFS_UNIX_POSIX_ACLS_CAP|
3366 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3367 CIFS_UNIX_FCNTL_LOCKS_CAP|
3368 CIFS_UNIX_EXTATTR_CAP|
3369 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3370 encrypt_caps|
3371 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3372 (large_write ?
3373 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3374 break;
3377 case SMB_QUERY_POSIX_FS_INFO:
3379 int rc;
3380 vfs_statvfs_struct svfs;
3382 if (!lp_unix_extensions()) {
3383 return NT_STATUS_INVALID_LEVEL;
3386 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3388 if (!rc) {
3389 data_len = 56;
3390 SIVAL(pdata,0,svfs.OptimalTransferSize);
3391 SIVAL(pdata,4,svfs.BlockSize);
3392 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3393 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3394 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3395 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3396 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3397 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3398 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3399 #ifdef EOPNOTSUPP
3400 } else if (rc == EOPNOTSUPP) {
3401 return NT_STATUS_INVALID_LEVEL;
3402 #endif /* EOPNOTSUPP */
3403 } else {
3404 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3405 return NT_STATUS_DOS(ERRSRV, ERRerror);
3407 break;
3410 case SMB_QUERY_POSIX_WHOAMI:
3412 uint32_t flags = 0;
3413 uint32_t sid_bytes;
3414 int i;
3416 if (!lp_unix_extensions()) {
3417 return NT_STATUS_INVALID_LEVEL;
3420 if (max_data_bytes < 40) {
3421 return NT_STATUS_BUFFER_TOO_SMALL;
3424 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3425 flags |= SMB_WHOAMI_GUEST;
3428 /* NOTE: 8 bytes for UID/GID, irrespective of native
3429 * platform size. This matches
3430 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3432 data_len = 4 /* flags */
3433 + 4 /* flag mask */
3434 + 8 /* uid */
3435 + 8 /* gid */
3436 + 4 /* ngroups */
3437 + 4 /* num_sids */
3438 + 4 /* SID bytes */
3439 + 4 /* pad/reserved */
3440 + (conn->session_info->unix_token->ngroups * 8)
3441 /* groups list */
3442 + (conn->session_info->security_token->num_sids *
3443 SID_MAX_SIZE)
3444 /* SID list */;
3446 SIVAL(pdata, 0, flags);
3447 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3448 SBIG_UINT(pdata, 8,
3449 (uint64_t)conn->session_info->unix_token->uid);
3450 SBIG_UINT(pdata, 16,
3451 (uint64_t)conn->session_info->unix_token->gid);
3454 if (data_len >= max_data_bytes) {
3455 /* Potential overflow, skip the GIDs and SIDs. */
3457 SIVAL(pdata, 24, 0); /* num_groups */
3458 SIVAL(pdata, 28, 0); /* num_sids */
3459 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3460 SIVAL(pdata, 36, 0); /* reserved */
3462 data_len = 40;
3463 break;
3466 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3467 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3469 /* We walk the SID list twice, but this call is fairly
3470 * infrequent, and I don't expect that it's performance
3471 * sensitive -- jpeach
3473 for (i = 0, sid_bytes = 0;
3474 i < conn->session_info->security_token->num_sids; ++i) {
3475 sid_bytes += ndr_size_dom_sid(
3476 &conn->session_info->security_token->sids[i],
3480 /* SID list byte count */
3481 SIVAL(pdata, 32, sid_bytes);
3483 /* 4 bytes pad/reserved - must be zero */
3484 SIVAL(pdata, 36, 0);
3485 data_len = 40;
3487 /* GID list */
3488 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3489 SBIG_UINT(pdata, data_len,
3490 (uint64_t)conn->session_info->unix_token->groups[i]);
3491 data_len += 8;
3494 /* SID list */
3495 for (i = 0;
3496 i < conn->session_info->security_token->num_sids; ++i) {
3497 int sid_len = ndr_size_dom_sid(
3498 &conn->session_info->security_token->sids[i],
3501 sid_linearize(pdata + data_len, sid_len,
3502 &conn->session_info->security_token->sids[i]);
3503 data_len += sid_len;
3506 break;
3509 case SMB_MAC_QUERY_FS_INFO:
3511 * Thursby MAC extension... ONLY on NTFS filesystems
3512 * once we do streams then we don't need this
3514 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3515 data_len = 88;
3516 SIVAL(pdata,84,0x100); /* Don't support mac... */
3517 break;
3519 /* drop through */
3520 default:
3521 return NT_STATUS_INVALID_LEVEL;
3524 *ret_data_len = data_len;
3525 return NT_STATUS_OK;
3528 /****************************************************************************
3529 Reply to a TRANS2_QFSINFO (query filesystem info).
3530 ****************************************************************************/
3532 static void call_trans2qfsinfo(connection_struct *conn,
3533 struct smb_request *req,
3534 char **pparams, int total_params,
3535 char **ppdata, int total_data,
3536 unsigned int max_data_bytes)
3538 char *params = *pparams;
3539 uint16_t info_level;
3540 int data_len = 0;
3541 NTSTATUS status;
3543 if (total_params < 2) {
3544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3545 return;
3548 info_level = SVAL(params,0);
3550 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3551 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3552 DEBUG(0,("call_trans2qfsinfo: encryption required "
3553 "and info level 0x%x sent.\n",
3554 (unsigned int)info_level));
3555 exit_server_cleanly("encryption required "
3556 "on connection");
3557 return;
3561 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3563 status = smbd_do_qfsinfo(conn, req,
3564 info_level,
3565 req->flags2,
3566 max_data_bytes,
3567 ppdata, &data_len);
3568 if (!NT_STATUS_IS_OK(status)) {
3569 reply_nterror(req, status);
3570 return;
3573 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3574 max_data_bytes);
3576 DEBUG( 4, ( "%s info_level = %d\n",
3577 smb_fn_name(req->cmd), info_level) );
3579 return;
3582 /****************************************************************************
3583 Reply to a TRANS2_SETFSINFO (set filesystem info).
3584 ****************************************************************************/
3586 static void call_trans2setfsinfo(connection_struct *conn,
3587 struct smb_request *req,
3588 char **pparams, int total_params,
3589 char **ppdata, int total_data,
3590 unsigned int max_data_bytes)
3592 struct smbd_server_connection *sconn = req->sconn;
3593 char *pdata = *ppdata;
3594 char *params = *pparams;
3595 uint16 info_level;
3597 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3599 /* */
3600 if (total_params < 4) {
3601 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3602 total_params));
3603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3604 return;
3607 info_level = SVAL(params,2);
3609 if (IS_IPC(conn)) {
3610 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3611 info_level != SMB_SET_CIFS_UNIX_INFO) {
3612 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3613 "info level (0x%x) on IPC$.\n",
3614 (unsigned int)info_level));
3615 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3616 return;
3620 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3621 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3622 DEBUG(0,("call_trans2setfsinfo: encryption required "
3623 "and info level 0x%x sent.\n",
3624 (unsigned int)info_level));
3625 exit_server_cleanly("encryption required "
3626 "on connection");
3627 return;
3631 switch(info_level) {
3632 case SMB_SET_CIFS_UNIX_INFO:
3633 if (!lp_unix_extensions()) {
3634 DEBUG(2,("call_trans2setfsinfo: "
3635 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3636 "unix extensions off\n"));
3637 reply_nterror(req,
3638 NT_STATUS_INVALID_LEVEL);
3639 return;
3642 /* There should be 12 bytes of capabilities set. */
3643 if (total_data < 12) {
3644 reply_nterror(
3645 req,
3646 NT_STATUS_INVALID_PARAMETER);
3647 return;
3649 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3650 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3651 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3652 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3653 /* Just print these values for now. */
3654 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3655 "major = %u, minor = %u cap_low = 0x%x, "
3656 "cap_high = 0x%xn",
3657 (unsigned int)sconn->
3658 smb1.unix_info.client_major,
3659 (unsigned int)sconn->
3660 smb1.unix_info.client_minor,
3661 (unsigned int)sconn->
3662 smb1.unix_info.client_cap_low,
3663 (unsigned int)sconn->
3664 smb1.unix_info.client_cap_high));
3666 /* Here is where we must switch to posix pathname processing... */
3667 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3668 lp_set_posix_pathnames();
3669 mangle_change_to_posix();
3672 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3673 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3674 /* Client that knows how to do posix locks,
3675 * but not posix open/mkdir operations. Set a
3676 * default type for read/write checks. */
3678 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3681 break;
3683 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3685 NTSTATUS status;
3686 size_t param_len = 0;
3687 size_t data_len = total_data;
3689 if (!lp_unix_extensions()) {
3690 reply_nterror(
3691 req,
3692 NT_STATUS_INVALID_LEVEL);
3693 return;
3696 if (lp_smb_encrypt(SNUM(conn)) == false) {
3697 reply_nterror(
3698 req,
3699 NT_STATUS_NOT_SUPPORTED);
3700 return;
3703 if (req->sconn->smb1.echo_handler.trusted_fde) {
3704 DEBUG( 2,("call_trans2setfsinfo: "
3705 "request transport encryption disabled"
3706 "with 'fork echo handler = yes'\n"));
3707 reply_nterror(
3708 req,
3709 NT_STATUS_NOT_SUPPORTED);
3710 return;
3713 DEBUG( 4,("call_trans2setfsinfo: "
3714 "request transport encryption.\n"));
3716 status = srv_request_encryption_setup(conn,
3717 (unsigned char **)ppdata,
3718 &data_len,
3719 (unsigned char **)pparams,
3720 &param_len);
3722 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3723 !NT_STATUS_IS_OK(status)) {
3724 reply_nterror(req, status);
3725 return;
3728 send_trans2_replies(conn, req,
3729 *pparams,
3730 param_len,
3731 *ppdata,
3732 data_len,
3733 max_data_bytes);
3735 if (NT_STATUS_IS_OK(status)) {
3736 /* Server-side transport
3737 * encryption is now *on*. */
3738 status = srv_encryption_start(conn);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 char *reason = talloc_asprintf(talloc_tos(),
3741 "Failure in setting "
3742 "up encrypted transport: %s",
3743 nt_errstr(status));
3744 exit_server_cleanly(reason);
3747 return;
3750 case SMB_FS_QUOTA_INFORMATION:
3752 files_struct *fsp = NULL;
3753 SMB_NTQUOTA_STRUCT quotas;
3755 ZERO_STRUCT(quotas);
3757 /* access check */
3758 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3759 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3760 lp_servicename(SNUM(conn)),
3761 conn->session_info->unix_info->unix_name));
3762 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3763 return;
3766 /* note: normaly there're 48 bytes,
3767 * but we didn't use the last 6 bytes for now
3768 * --metze
3770 fsp = file_fsp(req, SVAL(params,0));
3772 if (!check_fsp_ntquota_handle(conn, req,
3773 fsp)) {
3774 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3775 reply_nterror(
3776 req, NT_STATUS_INVALID_HANDLE);
3777 return;
3780 if (total_data < 42) {
3781 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3782 total_data));
3783 reply_nterror(
3784 req,
3785 NT_STATUS_INVALID_PARAMETER);
3786 return;
3789 /* unknown_1 24 NULL bytes in pdata*/
3791 /* the soft quotas 8 bytes (uint64_t)*/
3792 quotas.softlim = BVAL(pdata,24);
3794 /* the hard quotas 8 bytes (uint64_t)*/
3795 quotas.hardlim = BVAL(pdata,32);
3797 /* quota_flags 2 bytes **/
3798 quotas.qflags = SVAL(pdata,40);
3800 /* unknown_2 6 NULL bytes follow*/
3802 /* now set the quotas */
3803 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3804 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3805 reply_nterror(req, map_nt_error_from_unix(errno));
3806 return;
3809 break;
3811 default:
3812 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3813 info_level));
3814 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3815 return;
3816 break;
3820 * sending this reply works fine,
3821 * but I'm not sure it's the same
3822 * like windows do...
3823 * --metze
3825 reply_outbuf(req, 10, 0);
3828 #if defined(HAVE_POSIX_ACLS)
3829 /****************************************************************************
3830 Utility function to count the number of entries in a POSIX acl.
3831 ****************************************************************************/
3833 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3835 unsigned int ace_count = 0;
3836 int entry_id = SMB_ACL_FIRST_ENTRY;
3837 SMB_ACL_ENTRY_T entry;
3839 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3840 /* get_next... */
3841 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3842 entry_id = SMB_ACL_NEXT_ENTRY;
3844 ace_count++;
3846 return ace_count;
3849 /****************************************************************************
3850 Utility function to marshall a POSIX acl into wire format.
3851 ****************************************************************************/
3853 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3855 int entry_id = SMB_ACL_FIRST_ENTRY;
3856 SMB_ACL_ENTRY_T entry;
3858 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3859 SMB_ACL_TAG_T tagtype;
3860 SMB_ACL_PERMSET_T permset;
3861 unsigned char perms = 0;
3862 unsigned int own_grp;
3864 /* get_next... */
3865 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3866 entry_id = SMB_ACL_NEXT_ENTRY;
3869 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3870 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3871 return False;
3874 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3875 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3876 return False;
3879 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3880 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3881 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3883 SCVAL(pdata,1,perms);
3885 switch (tagtype) {
3886 case SMB_ACL_USER_OBJ:
3887 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3888 own_grp = (unsigned int)pst->st_ex_uid;
3889 SIVAL(pdata,2,own_grp);
3890 SIVAL(pdata,6,0);
3891 break;
3892 case SMB_ACL_USER:
3894 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3895 if (!puid) {
3896 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3897 return False;
3899 own_grp = (unsigned int)*puid;
3900 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3901 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3902 SIVAL(pdata,2,own_grp);
3903 SIVAL(pdata,6,0);
3904 break;
3906 case SMB_ACL_GROUP_OBJ:
3907 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3908 own_grp = (unsigned int)pst->st_ex_gid;
3909 SIVAL(pdata,2,own_grp);
3910 SIVAL(pdata,6,0);
3911 break;
3912 case SMB_ACL_GROUP:
3914 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3915 if (!pgid) {
3916 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3917 return False;
3919 own_grp = (unsigned int)*pgid;
3920 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3921 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3922 SIVAL(pdata,2,own_grp);
3923 SIVAL(pdata,6,0);
3924 break;
3926 case SMB_ACL_MASK:
3927 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3928 SIVAL(pdata,2,0xFFFFFFFF);
3929 SIVAL(pdata,6,0xFFFFFFFF);
3930 break;
3931 case SMB_ACL_OTHER:
3932 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3933 SIVAL(pdata,2,0xFFFFFFFF);
3934 SIVAL(pdata,6,0xFFFFFFFF);
3935 break;
3936 default:
3937 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3938 return False;
3940 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3943 return True;
3945 #endif
3947 /****************************************************************************
3948 Store the FILE_UNIX_BASIC info.
3949 ****************************************************************************/
3951 static char *store_file_unix_basic(connection_struct *conn,
3952 char *pdata,
3953 files_struct *fsp,
3954 const SMB_STRUCT_STAT *psbuf)
3956 uint64_t file_index = get_FileIndex(conn, psbuf);
3957 dev_t devno;
3959 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3960 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3962 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3963 pdata += 8;
3965 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3966 pdata += 8;
3968 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3969 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3970 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3971 pdata += 24;
3973 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3974 SIVAL(pdata,4,0);
3975 pdata += 8;
3977 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3978 SIVAL(pdata,4,0);
3979 pdata += 8;
3981 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3982 pdata += 4;
3984 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3985 devno = psbuf->st_ex_rdev;
3986 } else {
3987 devno = psbuf->st_ex_dev;
3990 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
3991 SIVAL(pdata,4,0);
3992 pdata += 8;
3994 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
3995 SIVAL(pdata,4,0);
3996 pdata += 8;
3998 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3999 pdata += 8;
4001 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4002 SIVAL(pdata,4,0);
4003 pdata += 8;
4005 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4006 SIVAL(pdata,4,0);
4007 pdata += 8;
4009 return pdata;
4012 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4013 * the chflags(2) (or equivalent) flags.
4015 * XXX: this really should be behind the VFS interface. To do this, we would
4016 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4017 * Each VFS module could then implement its own mapping as appropriate for the
4018 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4020 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4021 info2_flags_map[] =
4023 #ifdef UF_NODUMP
4024 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4025 #endif
4027 #ifdef UF_IMMUTABLE
4028 { UF_IMMUTABLE, EXT_IMMUTABLE },
4029 #endif
4031 #ifdef UF_APPEND
4032 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4033 #endif
4035 #ifdef UF_HIDDEN
4036 { UF_HIDDEN, EXT_HIDDEN },
4037 #endif
4039 /* Do not remove. We need to guarantee that this array has at least one
4040 * entry to build on HP-UX.
4042 { 0, 0 }
4046 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4047 uint32 *smb_fflags, uint32 *smb_fmask)
4049 int i;
4051 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4052 *smb_fmask |= info2_flags_map[i].smb_fflag;
4053 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4054 *smb_fflags |= info2_flags_map[i].smb_fflag;
4059 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4060 const uint32 smb_fflags,
4061 const uint32 smb_fmask,
4062 int *stat_fflags)
4064 uint32 max_fmask = 0;
4065 int i;
4067 *stat_fflags = psbuf->st_ex_flags;
4069 /* For each flags requested in smb_fmask, check the state of the
4070 * corresponding flag in smb_fflags and set or clear the matching
4071 * stat flag.
4074 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4075 max_fmask |= info2_flags_map[i].smb_fflag;
4076 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4077 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4078 *stat_fflags |= info2_flags_map[i].stat_fflag;
4079 } else {
4080 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4085 /* If smb_fmask is asking to set any bits that are not supported by
4086 * our flag mappings, we should fail.
4088 if ((smb_fmask & max_fmask) != smb_fmask) {
4089 return False;
4092 return True;
4096 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4097 * of file flags and birth (create) time.
4099 static char *store_file_unix_basic_info2(connection_struct *conn,
4100 char *pdata,
4101 files_struct *fsp,
4102 const SMB_STRUCT_STAT *psbuf)
4104 uint32 file_flags = 0;
4105 uint32 flags_mask = 0;
4107 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4109 /* Create (birth) time 64 bit */
4110 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4111 pdata += 8;
4113 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4114 SIVAL(pdata, 0, file_flags); /* flags */
4115 SIVAL(pdata, 4, flags_mask); /* mask */
4116 pdata += 8;
4118 return pdata;
4121 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4122 const struct stream_struct *streams,
4123 char *data,
4124 unsigned int max_data_bytes,
4125 unsigned int *data_size)
4127 unsigned int i;
4128 unsigned int ofs = 0;
4130 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4131 unsigned int next_offset;
4132 size_t namelen;
4133 smb_ucs2_t *namebuf;
4135 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4136 streams[i].name, &namelen) ||
4137 namelen <= 2)
4139 return NT_STATUS_INVALID_PARAMETER;
4143 * name_buf is now null-terminated, we need to marshall as not
4144 * terminated
4147 namelen -= 2;
4149 SIVAL(data, ofs+4, namelen);
4150 SOFF_T(data, ofs+8, streams[i].size);
4151 SOFF_T(data, ofs+16, streams[i].alloc_size);
4152 memcpy(data+ofs+24, namebuf, namelen);
4153 TALLOC_FREE(namebuf);
4155 next_offset = ofs + 24 + namelen;
4157 if (i == num_streams-1) {
4158 SIVAL(data, ofs, 0);
4160 else {
4161 unsigned int align = ndr_align_size(next_offset, 8);
4163 memset(data+next_offset, 0, align);
4164 next_offset += align;
4166 SIVAL(data, ofs, next_offset - ofs);
4167 ofs = next_offset;
4170 ofs = next_offset;
4173 *data_size = ofs;
4175 return NT_STATUS_OK;
4178 /****************************************************************************
4179 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4180 ****************************************************************************/
4182 static void call_trans2qpipeinfo(connection_struct *conn,
4183 struct smb_request *req,
4184 unsigned int tran_call,
4185 char **pparams, int total_params,
4186 char **ppdata, int total_data,
4187 unsigned int max_data_bytes)
4189 char *params = *pparams;
4190 char *pdata = *ppdata;
4191 unsigned int data_size = 0;
4192 unsigned int param_size = 2;
4193 uint16 info_level;
4194 files_struct *fsp;
4196 if (!params) {
4197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4198 return;
4201 if (total_params < 4) {
4202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4203 return;
4206 fsp = file_fsp(req, SVAL(params,0));
4207 if (!fsp_is_np(fsp)) {
4208 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4209 return;
4212 info_level = SVAL(params,2);
4214 *pparams = (char *)SMB_REALLOC(*pparams,2);
4215 if (*pparams == NULL) {
4216 reply_nterror(req, NT_STATUS_NO_MEMORY);
4217 return;
4219 params = *pparams;
4220 SSVAL(params,0,0);
4221 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4222 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4223 if (*ppdata == NULL ) {
4224 reply_nterror(req, NT_STATUS_NO_MEMORY);
4225 return;
4227 pdata = *ppdata;
4229 switch (info_level) {
4230 case SMB_FILE_STANDARD_INFORMATION:
4231 memset(pdata,0,24);
4232 SOFF_T(pdata,0,4096LL);
4233 SIVAL(pdata,16,1);
4234 SIVAL(pdata,20,1);
4235 data_size = 24;
4236 break;
4238 default:
4239 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4240 return;
4243 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4244 max_data_bytes);
4246 return;
4249 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4250 TALLOC_CTX *mem_ctx,
4251 uint16_t info_level,
4252 files_struct *fsp,
4253 struct smb_filename *smb_fname,
4254 bool delete_pending,
4255 struct timespec write_time_ts,
4256 struct ea_list *ea_list,
4257 int lock_data_count,
4258 char *lock_data,
4259 uint16_t flags2,
4260 unsigned int max_data_bytes,
4261 char **ppdata,
4262 unsigned int *pdata_size)
4264 char *pdata = *ppdata;
4265 char *dstart, *dend;
4266 unsigned int data_size;
4267 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4268 time_t create_time, mtime, atime, c_time;
4269 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4270 char *p;
4271 char *base_name;
4272 char *dos_fname;
4273 int mode;
4274 int nlink;
4275 NTSTATUS status;
4276 uint64_t file_size = 0;
4277 uint64_t pos = 0;
4278 uint64_t allocation_size = 0;
4279 uint64_t file_index = 0;
4280 uint32_t access_mask = 0;
4282 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4283 return NT_STATUS_INVALID_LEVEL;
4286 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4287 smb_fname_str_dbg(smb_fname),
4288 fsp_fnum_dbg(fsp),
4289 info_level, max_data_bytes));
4291 mode = dos_mode(conn, smb_fname);
4292 nlink = psbuf->st_ex_nlink;
4294 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4295 nlink = 1;
4298 if ((nlink > 0) && delete_pending) {
4299 nlink -= 1;
4302 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4303 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4304 if (*ppdata == NULL) {
4305 return NT_STATUS_NO_MEMORY;
4307 pdata = *ppdata;
4308 dstart = pdata;
4309 dend = dstart + data_size - 1;
4311 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4312 update_stat_ex_mtime(psbuf, write_time_ts);
4315 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4316 mtime_ts = psbuf->st_ex_mtime;
4317 atime_ts = psbuf->st_ex_atime;
4318 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4320 if (lp_dos_filetime_resolution(SNUM(conn))) {
4321 dos_filetime_timespec(&create_time_ts);
4322 dos_filetime_timespec(&mtime_ts);
4323 dos_filetime_timespec(&atime_ts);
4324 dos_filetime_timespec(&ctime_ts);
4327 create_time = convert_timespec_to_time_t(create_time_ts);
4328 mtime = convert_timespec_to_time_t(mtime_ts);
4329 atime = convert_timespec_to_time_t(atime_ts);
4330 c_time = convert_timespec_to_time_t(ctime_ts);
4332 p = strrchr_m(smb_fname->base_name,'/');
4333 if (!p)
4334 base_name = smb_fname->base_name;
4335 else
4336 base_name = p+1;
4338 /* NT expects the name to be in an exact form of the *full*
4339 filename. See the trans2 torture test */
4340 if (ISDOT(base_name)) {
4341 dos_fname = talloc_strdup(mem_ctx, "\\");
4342 if (!dos_fname) {
4343 return NT_STATUS_NO_MEMORY;
4345 } else {
4346 dos_fname = talloc_asprintf(mem_ctx,
4347 "\\%s",
4348 smb_fname->base_name);
4349 if (!dos_fname) {
4350 return NT_STATUS_NO_MEMORY;
4352 if (is_ntfs_stream_smb_fname(smb_fname)) {
4353 dos_fname = talloc_asprintf(dos_fname, "%s",
4354 smb_fname->stream_name);
4355 if (!dos_fname) {
4356 return NT_STATUS_NO_MEMORY;
4360 string_replace(dos_fname, '/', '\\');
4363 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4365 if (!fsp) {
4366 /* Do we have this path open ? */
4367 files_struct *fsp1;
4368 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4369 fsp1 = file_find_di_first(conn->sconn, fileid);
4370 if (fsp1 && fsp1->initial_allocation_size) {
4371 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4375 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4376 file_size = get_file_size_stat(psbuf);
4379 if (fsp) {
4380 pos = fsp->fh->position_information;
4383 if (fsp) {
4384 access_mask = fsp->access_mask;
4385 } else {
4386 /* GENERIC_EXECUTE mapping from Windows */
4387 access_mask = 0x12019F;
4390 /* This should be an index number - looks like
4391 dev/ino to me :-)
4393 I think this causes us to fail the IFSKIT
4394 BasicFileInformationTest. -tpot */
4395 file_index = get_FileIndex(conn, psbuf);
4397 switch (info_level) {
4398 case SMB_INFO_STANDARD:
4399 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4400 data_size = 22;
4401 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4402 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4403 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4404 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4405 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4406 SSVAL(pdata,l1_attrFile,mode);
4407 break;
4409 case SMB_INFO_QUERY_EA_SIZE:
4411 unsigned int ea_size =
4412 estimate_ea_size(conn, fsp,
4413 smb_fname->base_name);
4414 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4415 data_size = 26;
4416 srv_put_dos_date2(pdata,0,create_time);
4417 srv_put_dos_date2(pdata,4,atime);
4418 srv_put_dos_date2(pdata,8,mtime); /* write time */
4419 SIVAL(pdata,12,(uint32)file_size);
4420 SIVAL(pdata,16,(uint32)allocation_size);
4421 SSVAL(pdata,20,mode);
4422 SIVAL(pdata,22,ea_size);
4423 break;
4426 case SMB_INFO_IS_NAME_VALID:
4427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4428 if (fsp) {
4429 /* os/2 needs this ? really ?*/
4430 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4432 /* This is only reached for qpathinfo */
4433 data_size = 0;
4434 break;
4436 case SMB_INFO_QUERY_EAS_FROM_LIST:
4438 size_t total_ea_len = 0;
4439 struct ea_list *ea_file_list = NULL;
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4443 ea_file_list =
4444 get_ea_list_from_file(mem_ctx, conn, fsp,
4445 smb_fname->base_name,
4446 &total_ea_len);
4447 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4449 if (!ea_list || (total_ea_len > data_size)) {
4450 data_size = 4;
4451 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4452 break;
4455 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4456 break;
4459 case SMB_INFO_QUERY_ALL_EAS:
4461 /* We have data_size bytes to put EA's into. */
4462 size_t total_ea_len = 0;
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4466 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4467 smb_fname->base_name,
4468 &total_ea_len);
4469 if (!ea_list || (total_ea_len > data_size)) {
4470 data_size = 4;
4471 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4472 break;
4475 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4476 break;
4479 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4481 /* This is FileFullEaInformation - 0xF which maps to
4482 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4484 /* We have data_size bytes to put EA's into. */
4485 size_t total_ea_len = 0;
4486 struct ea_list *ea_file_list = NULL;
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4490 /*TODO: add filtering and index handling */
4492 ea_file_list =
4493 get_ea_list_from_file(mem_ctx, conn, fsp,
4494 smb_fname->base_name,
4495 &total_ea_len);
4496 if (!ea_file_list) {
4497 return NT_STATUS_NO_EAS_ON_FILE;
4500 status = fill_ea_chained_buffer(mem_ctx,
4501 pdata,
4502 data_size,
4503 &data_size,
4504 conn, ea_file_list);
4505 if (!NT_STATUS_IS_OK(status)) {
4506 return status;
4508 break;
4511 case SMB_FILE_BASIC_INFORMATION:
4512 case SMB_QUERY_FILE_BASIC_INFO:
4514 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4516 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4517 } else {
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4519 data_size = 40;
4520 SIVAL(pdata,36,0);
4522 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4523 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4524 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4525 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4526 SIVAL(pdata,32,mode);
4528 DEBUG(5,("SMB_QFBI - "));
4529 DEBUG(5,("create: %s ", ctime(&create_time)));
4530 DEBUG(5,("access: %s ", ctime(&atime)));
4531 DEBUG(5,("write: %s ", ctime(&mtime)));
4532 DEBUG(5,("change: %s ", ctime(&c_time)));
4533 DEBUG(5,("mode: %x\n", mode));
4534 break;
4536 case SMB_FILE_STANDARD_INFORMATION:
4537 case SMB_QUERY_FILE_STANDARD_INFO:
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4540 data_size = 24;
4541 SOFF_T(pdata,0,allocation_size);
4542 SOFF_T(pdata,8,file_size);
4543 SIVAL(pdata,16,nlink);
4544 SCVAL(pdata,20,delete_pending?1:0);
4545 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4546 SSVAL(pdata,22,0); /* Padding. */
4547 break;
4549 case SMB_FILE_EA_INFORMATION:
4550 case SMB_QUERY_FILE_EA_INFO:
4552 unsigned int ea_size =
4553 estimate_ea_size(conn, fsp, smb_fname->base_name);
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4555 data_size = 4;
4556 SIVAL(pdata,0,ea_size);
4557 break;
4560 /* Get the 8.3 name - used if NT SMB was negotiated. */
4561 case SMB_QUERY_FILE_ALT_NAME_INFO:
4562 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4564 int len;
4565 char mangled_name[13];
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4567 if (!name_to_8_3(base_name,mangled_name,
4568 True,conn->params)) {
4569 return NT_STATUS_NO_MEMORY;
4571 len = srvstr_push(dstart, flags2,
4572 pdata+4, mangled_name,
4573 PTR_DIFF(dend, pdata+4),
4574 STR_UNICODE);
4575 data_size = 4 + len;
4576 SIVAL(pdata,0,len);
4577 break;
4580 case SMB_QUERY_FILE_NAME_INFO:
4582 int len;
4584 this must be *exactly* right for ACLs on mapped drives to work
4586 len = srvstr_push(dstart, flags2,
4587 pdata+4, dos_fname,
4588 PTR_DIFF(dend, pdata+4),
4589 STR_UNICODE);
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4591 data_size = 4 + len;
4592 SIVAL(pdata,0,len);
4593 break;
4596 case SMB_FILE_ALLOCATION_INFORMATION:
4597 case SMB_QUERY_FILE_ALLOCATION_INFO:
4598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4599 data_size = 8;
4600 SOFF_T(pdata,0,allocation_size);
4601 break;
4603 case SMB_FILE_END_OF_FILE_INFORMATION:
4604 case SMB_QUERY_FILE_END_OF_FILEINFO:
4605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4606 data_size = 8;
4607 SOFF_T(pdata,0,file_size);
4608 break;
4610 case SMB_QUERY_FILE_ALL_INFO:
4611 case SMB_FILE_ALL_INFORMATION:
4613 int len;
4614 unsigned int ea_size =
4615 estimate_ea_size(conn, fsp, smb_fname->base_name);
4616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4617 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4618 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4619 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4620 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4621 SIVAL(pdata,32,mode);
4622 SIVAL(pdata,36,0); /* padding. */
4623 pdata += 40;
4624 SOFF_T(pdata,0,allocation_size);
4625 SOFF_T(pdata,8,file_size);
4626 SIVAL(pdata,16,nlink);
4627 SCVAL(pdata,20,delete_pending);
4628 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4629 SSVAL(pdata,22,0);
4630 pdata += 24;
4631 SIVAL(pdata,0,ea_size);
4632 pdata += 4; /* EA info */
4633 len = srvstr_push(dstart, flags2,
4634 pdata+4, dos_fname,
4635 PTR_DIFF(dend, pdata+4),
4636 STR_UNICODE);
4637 SIVAL(pdata,0,len);
4638 pdata += 4 + len;
4639 data_size = PTR_DIFF(pdata,(*ppdata));
4640 break;
4643 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4645 int len;
4646 unsigned int ea_size =
4647 estimate_ea_size(conn, fsp, smb_fname->base_name);
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4649 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4650 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4651 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4652 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4653 SIVAL(pdata, 0x20, mode);
4654 SIVAL(pdata, 0x24, 0); /* padding. */
4655 SBVAL(pdata, 0x28, allocation_size);
4656 SBVAL(pdata, 0x30, file_size);
4657 SIVAL(pdata, 0x38, nlink);
4658 SCVAL(pdata, 0x3C, delete_pending);
4659 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4660 SSVAL(pdata, 0x3E, 0); /* padding */
4661 SBVAL(pdata, 0x40, file_index);
4662 SIVAL(pdata, 0x48, ea_size);
4663 SIVAL(pdata, 0x4C, access_mask);
4664 SBVAL(pdata, 0x50, pos);
4665 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4666 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4668 pdata += 0x60;
4670 len = srvstr_push(dstart, flags2,
4671 pdata+4, dos_fname,
4672 PTR_DIFF(dend, pdata+4),
4673 STR_UNICODE);
4674 SIVAL(pdata,0,len);
4675 pdata += 4 + len;
4676 data_size = PTR_DIFF(pdata,(*ppdata));
4677 break;
4679 case SMB_FILE_INTERNAL_INFORMATION:
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4682 SBVAL(pdata, 0, file_index);
4683 data_size = 8;
4684 break;
4686 case SMB_FILE_ACCESS_INFORMATION:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4688 SIVAL(pdata, 0, access_mask);
4689 data_size = 4;
4690 break;
4692 case SMB_FILE_NAME_INFORMATION:
4693 /* Pathname with leading '\'. */
4695 size_t byte_len;
4696 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4698 SIVAL(pdata,0,byte_len);
4699 data_size = 4 + byte_len;
4700 break;
4703 case SMB_FILE_DISPOSITION_INFORMATION:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4705 data_size = 1;
4706 SCVAL(pdata,0,delete_pending);
4707 break;
4709 case SMB_FILE_POSITION_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4711 data_size = 8;
4712 SOFF_T(pdata,0,pos);
4713 break;
4715 case SMB_FILE_MODE_INFORMATION:
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4717 SIVAL(pdata,0,mode);
4718 data_size = 4;
4719 break;
4721 case SMB_FILE_ALIGNMENT_INFORMATION:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4723 SIVAL(pdata,0,0); /* No alignment needed. */
4724 data_size = 4;
4725 break;
4728 * NT4 server just returns "invalid query" to this - if we try
4729 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4730 * want this. JRA.
4732 /* The first statement above is false - verified using Thursby
4733 * client against NT4 -- gcolley.
4735 case SMB_QUERY_FILE_STREAM_INFO:
4736 case SMB_FILE_STREAM_INFORMATION: {
4737 unsigned int num_streams = 0;
4738 struct stream_struct *streams = NULL;
4740 DEBUG(10,("smbd_do_qfilepathinfo: "
4741 "SMB_FILE_STREAM_INFORMATION\n"));
4743 if (is_ntfs_stream_smb_fname(smb_fname)) {
4744 return NT_STATUS_INVALID_PARAMETER;
4747 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4748 talloc_tos(), &num_streams, &streams);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 DEBUG(10, ("could not get stream info: %s\n",
4752 nt_errstr(status)));
4753 return status;
4756 status = marshall_stream_info(num_streams, streams,
4757 pdata, max_data_bytes,
4758 &data_size);
4760 if (!NT_STATUS_IS_OK(status)) {
4761 DEBUG(10, ("marshall_stream_info failed: %s\n",
4762 nt_errstr(status)));
4763 return status;
4766 TALLOC_FREE(streams);
4768 break;
4770 case SMB_QUERY_COMPRESSION_INFO:
4771 case SMB_FILE_COMPRESSION_INFORMATION:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4773 SOFF_T(pdata,0,file_size);
4774 SIVAL(pdata,8,0); /* ??? */
4775 SIVAL(pdata,12,0); /* ??? */
4776 data_size = 16;
4777 break;
4779 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4781 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4782 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4783 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4784 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4785 SOFF_T(pdata,32,allocation_size);
4786 SOFF_T(pdata,40,file_size);
4787 SIVAL(pdata,48,mode);
4788 SIVAL(pdata,52,0); /* ??? */
4789 data_size = 56;
4790 break;
4792 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4794 SIVAL(pdata,0,mode);
4795 SIVAL(pdata,4,0);
4796 data_size = 8;
4797 break;
4800 * CIFS UNIX Extensions.
4803 case SMB_QUERY_FILE_UNIX_BASIC:
4805 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4806 data_size = PTR_DIFF(pdata,(*ppdata));
4808 DEBUG(4,("smbd_do_qfilepathinfo: "
4809 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4810 dump_data(4, (uint8_t *)(*ppdata), data_size);
4812 break;
4814 case SMB_QUERY_FILE_UNIX_INFO2:
4816 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4817 data_size = PTR_DIFF(pdata,(*ppdata));
4820 int i;
4821 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4823 for (i=0; i<100; i++)
4824 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4825 DEBUG(4,("\n"));
4828 break;
4830 case SMB_QUERY_FILE_UNIX_LINK:
4832 int len;
4833 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4835 if (!buffer) {
4836 return NT_STATUS_NO_MEMORY;
4839 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4840 #ifdef S_ISLNK
4841 if(!S_ISLNK(psbuf->st_ex_mode)) {
4842 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4844 #else
4845 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4846 #endif
4847 len = SMB_VFS_READLINK(conn,
4848 smb_fname->base_name,
4849 buffer, PATH_MAX);
4850 if (len == -1) {
4851 return map_nt_error_from_unix(errno);
4853 buffer[len] = 0;
4854 len = srvstr_push(dstart, flags2,
4855 pdata, buffer,
4856 PTR_DIFF(dend, pdata),
4857 STR_TERMINATE);
4858 pdata += len;
4859 data_size = PTR_DIFF(pdata,(*ppdata));
4861 break;
4864 #if defined(HAVE_POSIX_ACLS)
4865 case SMB_QUERY_POSIX_ACL:
4867 SMB_ACL_T file_acl = NULL;
4868 SMB_ACL_T def_acl = NULL;
4869 uint16 num_file_acls = 0;
4870 uint16 num_def_acls = 0;
4872 if (fsp && fsp->fh->fd != -1) {
4873 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4874 } else {
4875 file_acl =
4876 SMB_VFS_SYS_ACL_GET_FILE(conn,
4877 smb_fname->base_name,
4878 SMB_ACL_TYPE_ACCESS);
4881 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4882 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4883 "not implemented on "
4884 "filesystem containing %s\n",
4885 smb_fname->base_name));
4886 return NT_STATUS_NOT_IMPLEMENTED;
4889 if (S_ISDIR(psbuf->st_ex_mode)) {
4890 if (fsp && fsp->is_directory) {
4891 def_acl =
4892 SMB_VFS_SYS_ACL_GET_FILE(
4893 conn,
4894 fsp->fsp_name->base_name,
4895 SMB_ACL_TYPE_DEFAULT);
4896 } else {
4897 def_acl =
4898 SMB_VFS_SYS_ACL_GET_FILE(
4899 conn,
4900 smb_fname->base_name,
4901 SMB_ACL_TYPE_DEFAULT);
4903 def_acl = free_empty_sys_acl(conn, def_acl);
4906 num_file_acls = count_acl_entries(conn, file_acl);
4907 num_def_acls = count_acl_entries(conn, def_acl);
4909 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4910 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4911 data_size,
4912 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4913 SMB_POSIX_ACL_HEADER_SIZE) ));
4914 if (file_acl) {
4915 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4917 if (def_acl) {
4918 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4920 return NT_STATUS_BUFFER_TOO_SMALL;
4923 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4924 SSVAL(pdata,2,num_file_acls);
4925 SSVAL(pdata,4,num_def_acls);
4926 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4927 if (file_acl) {
4928 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4930 if (def_acl) {
4931 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4933 return NT_STATUS_INTERNAL_ERROR;
4935 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4936 if (file_acl) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4939 if (def_acl) {
4940 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4942 return NT_STATUS_INTERNAL_ERROR;
4945 if (file_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4948 if (def_acl) {
4949 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4951 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4952 break;
4954 #endif
4957 case SMB_QUERY_POSIX_LOCK:
4959 uint64_t count;
4960 uint64_t offset;
4961 uint64_t smblctx;
4962 enum brl_type lock_type;
4964 /* We need an open file with a real fd for this. */
4965 if (!fsp || fsp->fh->fd == -1) {
4966 return NT_STATUS_INVALID_LEVEL;
4969 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4970 return NT_STATUS_INVALID_PARAMETER;
4973 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4974 case POSIX_LOCK_TYPE_READ:
4975 lock_type = READ_LOCK;
4976 break;
4977 case POSIX_LOCK_TYPE_WRITE:
4978 lock_type = WRITE_LOCK;
4979 break;
4980 case POSIX_LOCK_TYPE_UNLOCK:
4981 default:
4982 /* There's no point in asking for an unlock... */
4983 return NT_STATUS_INVALID_PARAMETER;
4986 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4987 #if defined(HAVE_LONGLONG)
4988 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4989 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4990 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4991 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4992 #else /* HAVE_LONGLONG */
4993 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4994 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4995 #endif /* HAVE_LONGLONG */
4997 status = query_lock(fsp,
4998 &smblctx,
4999 &count,
5000 &offset,
5001 &lock_type,
5002 POSIX_LOCK);
5004 if (ERROR_WAS_LOCK_DENIED(status)) {
5005 /* Here we need to report who has it locked... */
5006 data_size = POSIX_LOCK_DATA_SIZE;
5008 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5009 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5010 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5011 #if defined(HAVE_LONGLONG)
5012 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5013 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5014 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5015 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5016 #else /* HAVE_LONGLONG */
5017 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5018 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5019 #endif /* HAVE_LONGLONG */
5021 } else if (NT_STATUS_IS_OK(status)) {
5022 /* For success we just return a copy of what we sent
5023 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5024 data_size = POSIX_LOCK_DATA_SIZE;
5025 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5026 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5027 } else {
5028 return status;
5030 break;
5033 default:
5034 return NT_STATUS_INVALID_LEVEL;
5037 *pdata_size = data_size;
5038 return NT_STATUS_OK;
5041 /****************************************************************************
5042 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5043 file name or file id).
5044 ****************************************************************************/
5046 static void call_trans2qfilepathinfo(connection_struct *conn,
5047 struct smb_request *req,
5048 unsigned int tran_call,
5049 char **pparams, int total_params,
5050 char **ppdata, int total_data,
5051 unsigned int max_data_bytes)
5053 char *params = *pparams;
5054 char *pdata = *ppdata;
5055 uint16 info_level;
5056 unsigned int data_size = 0;
5057 unsigned int param_size = 2;
5058 struct smb_filename *smb_fname = NULL;
5059 bool delete_pending = False;
5060 struct timespec write_time_ts;
5061 files_struct *fsp = NULL;
5062 struct file_id fileid;
5063 struct ea_list *ea_list = NULL;
5064 int lock_data_count = 0;
5065 char *lock_data = NULL;
5066 NTSTATUS status = NT_STATUS_OK;
5068 if (!params) {
5069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5070 return;
5073 ZERO_STRUCT(write_time_ts);
5075 if (tran_call == TRANSACT2_QFILEINFO) {
5076 if (total_params < 4) {
5077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5078 return;
5081 if (IS_IPC(conn)) {
5082 call_trans2qpipeinfo(conn, req, tran_call,
5083 pparams, total_params,
5084 ppdata, total_data,
5085 max_data_bytes);
5086 return;
5089 fsp = file_fsp(req, SVAL(params,0));
5090 info_level = SVAL(params,2);
5092 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5094 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5095 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5096 return;
5099 /* Initial check for valid fsp ptr. */
5100 if (!check_fsp_open(conn, req, fsp)) {
5101 return;
5104 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5105 &smb_fname);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 reply_nterror(req, status);
5108 return;
5111 if(fsp->fake_file_handle) {
5113 * This is actually for the QUOTA_FAKE_FILE --metze
5116 /* We know this name is ok, it's already passed the checks. */
5118 } else if(fsp->fh->fd == -1) {
5120 * This is actually a QFILEINFO on a directory
5121 * handle (returned from an NT SMB). NT5.0 seems
5122 * to do this call. JRA.
5125 if (INFO_LEVEL_IS_UNIX(info_level)) {
5126 /* Always do lstat for UNIX calls. */
5127 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5128 DEBUG(3,("call_trans2qfilepathinfo: "
5129 "SMB_VFS_LSTAT of %s failed "
5130 "(%s)\n",
5131 smb_fname_str_dbg(smb_fname),
5132 strerror(errno)));
5133 reply_nterror(req,
5134 map_nt_error_from_unix(errno));
5135 return;
5137 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5138 DEBUG(3,("call_trans2qfilepathinfo: "
5139 "SMB_VFS_STAT of %s failed (%s)\n",
5140 smb_fname_str_dbg(smb_fname),
5141 strerror(errno)));
5142 reply_nterror(req,
5143 map_nt_error_from_unix(errno));
5144 return;
5147 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5148 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5149 } else {
5151 * Original code - this is an open file.
5153 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5154 DEBUG(3, ("fstat of %s failed (%s)\n",
5155 fsp_fnum_dbg(fsp), strerror(errno)));
5156 reply_nterror(req,
5157 map_nt_error_from_unix(errno));
5158 return;
5160 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5161 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5164 } else {
5165 uint32_t name_hash;
5166 char *fname = NULL;
5167 uint32_t ucf_flags = 0;
5169 /* qpathinfo */
5170 if (total_params < 7) {
5171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5172 return;
5175 info_level = SVAL(params,0);
5177 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5179 if (INFO_LEVEL_IS_UNIX(info_level)) {
5180 if (!lp_unix_extensions()) {
5181 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5182 return;
5184 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5185 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5186 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5187 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5191 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5192 total_params - 6,
5193 STR_TERMINATE, &status);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 reply_nterror(req, status);
5196 return;
5199 status = filename_convert(req,
5200 conn,
5201 req->flags2 & FLAGS2_DFS_PATHNAMES,
5202 fname,
5203 ucf_flags,
5204 NULL,
5205 &smb_fname);
5206 if (!NT_STATUS_IS_OK(status)) {
5207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5208 reply_botherror(req,
5209 NT_STATUS_PATH_NOT_COVERED,
5210 ERRSRV, ERRbadpath);
5211 return;
5213 reply_nterror(req, status);
5214 return;
5217 /* If this is a stream, check if there is a delete_pending. */
5218 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5219 && is_ntfs_stream_smb_fname(smb_fname)) {
5220 struct smb_filename *smb_fname_base = NULL;
5222 /* Create an smb_filename with stream_name == NULL. */
5223 status =
5224 create_synthetic_smb_fname(talloc_tos(),
5225 smb_fname->base_name,
5226 NULL, NULL,
5227 &smb_fname_base);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 reply_nterror(req, status);
5230 return;
5233 if (INFO_LEVEL_IS_UNIX(info_level)) {
5234 /* Always do lstat for UNIX calls. */
5235 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5236 DEBUG(3,("call_trans2qfilepathinfo: "
5237 "SMB_VFS_LSTAT of %s failed "
5238 "(%s)\n",
5239 smb_fname_str_dbg(smb_fname_base),
5240 strerror(errno)));
5241 TALLOC_FREE(smb_fname_base);
5242 reply_nterror(req,
5243 map_nt_error_from_unix(errno));
5244 return;
5246 } else {
5247 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "fileinfo of %s failed "
5250 "(%s)\n",
5251 smb_fname_str_dbg(smb_fname_base),
5252 strerror(errno)));
5253 TALLOC_FREE(smb_fname_base);
5254 reply_nterror(req,
5255 map_nt_error_from_unix(errno));
5256 return;
5260 status = file_name_hash(conn,
5261 smb_fname_str_dbg(smb_fname_base),
5262 &name_hash);
5263 if (!NT_STATUS_IS_OK(status)) {
5264 TALLOC_FREE(smb_fname_base);
5265 reply_nterror(req, status);
5266 return;
5269 fileid = vfs_file_id_from_sbuf(conn,
5270 &smb_fname_base->st);
5271 TALLOC_FREE(smb_fname_base);
5272 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5273 if (delete_pending) {
5274 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5275 return;
5279 if (INFO_LEVEL_IS_UNIX(info_level)) {
5280 /* Always do lstat for UNIX calls. */
5281 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5282 DEBUG(3,("call_trans2qfilepathinfo: "
5283 "SMB_VFS_LSTAT of %s failed (%s)\n",
5284 smb_fname_str_dbg(smb_fname),
5285 strerror(errno)));
5286 reply_nterror(req,
5287 map_nt_error_from_unix(errno));
5288 return;
5291 } else {
5292 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5293 DEBUG(3,("call_trans2qfilepathinfo: "
5294 "SMB_VFS_STAT of %s failed (%s)\n",
5295 smb_fname_str_dbg(smb_fname),
5296 strerror(errno)));
5297 reply_nterror(req,
5298 map_nt_error_from_unix(errno));
5299 return;
5303 status = file_name_hash(conn,
5304 smb_fname_str_dbg(smb_fname),
5305 &name_hash);
5306 if (!NT_STATUS_IS_OK(status)) {
5307 reply_nterror(req, status);
5308 return;
5311 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5312 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5313 if (delete_pending) {
5314 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5315 return;
5319 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5320 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5321 fsp_fnum_dbg(fsp),
5322 info_level,tran_call,total_data));
5324 /* Pull out any data sent here before we realloc. */
5325 switch (info_level) {
5326 case SMB_INFO_QUERY_EAS_FROM_LIST:
5328 /* Pull any EA list from the data portion. */
5329 uint32 ea_size;
5331 if (total_data < 4) {
5332 reply_nterror(
5333 req, NT_STATUS_INVALID_PARAMETER);
5334 return;
5336 ea_size = IVAL(pdata,0);
5338 if (total_data > 0 && ea_size != total_data) {
5339 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5340 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5341 reply_nterror(
5342 req, NT_STATUS_INVALID_PARAMETER);
5343 return;
5346 if (!lp_ea_support(SNUM(conn))) {
5347 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5348 return;
5351 /* Pull out the list of names. */
5352 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5353 if (!ea_list) {
5354 reply_nterror(
5355 req, NT_STATUS_INVALID_PARAMETER);
5356 return;
5358 break;
5361 case SMB_QUERY_POSIX_LOCK:
5363 if (fsp == NULL || fsp->fh->fd == -1) {
5364 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5365 return;
5368 if (total_data != POSIX_LOCK_DATA_SIZE) {
5369 reply_nterror(
5370 req, NT_STATUS_INVALID_PARAMETER);
5371 return;
5374 /* Copy the lock range data. */
5375 lock_data = (char *)talloc_memdup(
5376 req, pdata, total_data);
5377 if (!lock_data) {
5378 reply_nterror(req, NT_STATUS_NO_MEMORY);
5379 return;
5381 lock_data_count = total_data;
5383 default:
5384 break;
5387 *pparams = (char *)SMB_REALLOC(*pparams,2);
5388 if (*pparams == NULL) {
5389 reply_nterror(req, NT_STATUS_NO_MEMORY);
5390 return;
5392 params = *pparams;
5393 SSVAL(params,0,0);
5396 * draft-leach-cifs-v1-spec-02.txt
5397 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5398 * says:
5400 * The requested information is placed in the Data portion of the
5401 * transaction response. For the information levels greater than 0x100,
5402 * the transaction response has 1 parameter word which should be
5403 * ignored by the client.
5405 * However Windows only follows this rule for the IS_NAME_VALID call.
5407 switch (info_level) {
5408 case SMB_INFO_IS_NAME_VALID:
5409 param_size = 0;
5410 break;
5413 if ((info_level & 0xFF00) == 0xFF00) {
5415 * We use levels that start with 0xFF00
5416 * internally to represent SMB2 specific levels
5418 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5419 return;
5422 status = smbd_do_qfilepathinfo(conn, req, info_level,
5423 fsp, smb_fname,
5424 delete_pending, write_time_ts,
5425 ea_list,
5426 lock_data_count, lock_data,
5427 req->flags2, max_data_bytes,
5428 ppdata, &data_size);
5429 if (!NT_STATUS_IS_OK(status)) {
5430 reply_nterror(req, status);
5431 return;
5434 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5435 max_data_bytes);
5437 return;
5440 /****************************************************************************
5441 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5442 code.
5443 ****************************************************************************/
5445 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5446 connection_struct *conn,
5447 struct smb_request *req,
5448 bool overwrite_if_exists,
5449 const struct smb_filename *smb_fname_old,
5450 struct smb_filename *smb_fname_new)
5452 NTSTATUS status = NT_STATUS_OK;
5454 /* source must already exist. */
5455 if (!VALID_STAT(smb_fname_old->st)) {
5456 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5459 if (VALID_STAT(smb_fname_new->st)) {
5460 if (overwrite_if_exists) {
5461 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5462 return NT_STATUS_FILE_IS_A_DIRECTORY;
5464 status = unlink_internals(conn,
5465 req,
5466 FILE_ATTRIBUTE_NORMAL,
5467 smb_fname_new,
5468 false);
5469 if (!NT_STATUS_IS_OK(status)) {
5470 return status;
5472 } else {
5473 /* Disallow if newname already exists. */
5474 return NT_STATUS_OBJECT_NAME_COLLISION;
5478 /* No links from a directory. */
5479 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5480 return NT_STATUS_FILE_IS_A_DIRECTORY;
5483 /* Setting a hardlink to/from a stream isn't currently supported. */
5484 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5485 is_ntfs_stream_smb_fname(smb_fname_new)) {
5486 return NT_STATUS_INVALID_PARAMETER;
5489 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5490 smb_fname_old->base_name, smb_fname_new->base_name));
5492 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5493 smb_fname_new->base_name) != 0) {
5494 status = map_nt_error_from_unix(errno);
5495 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5496 nt_errstr(status), smb_fname_old->base_name,
5497 smb_fname_new->base_name));
5499 return status;
5502 /****************************************************************************
5503 Deal with setting the time from any of the setfilepathinfo functions.
5504 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5505 calling this function.
5506 ****************************************************************************/
5508 NTSTATUS smb_set_file_time(connection_struct *conn,
5509 files_struct *fsp,
5510 const struct smb_filename *smb_fname,
5511 struct smb_file_time *ft,
5512 bool setting_write_time)
5514 struct smb_filename smb_fname_base;
5515 uint32 action =
5516 FILE_NOTIFY_CHANGE_LAST_ACCESS
5517 |FILE_NOTIFY_CHANGE_LAST_WRITE
5518 |FILE_NOTIFY_CHANGE_CREATION;
5520 if (!VALID_STAT(smb_fname->st)) {
5521 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5524 /* get some defaults (no modifications) if any info is zero or -1. */
5525 if (null_timespec(ft->create_time)) {
5526 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5529 if (null_timespec(ft->atime)) {
5530 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5533 if (null_timespec(ft->mtime)) {
5534 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5537 if (!setting_write_time) {
5538 /* ft->mtime comes from change time, not write time. */
5539 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5542 /* Ensure the resolution is the correct for
5543 * what we can store on this filesystem. */
5545 round_timespec(conn->ts_res, &ft->create_time);
5546 round_timespec(conn->ts_res, &ft->ctime);
5547 round_timespec(conn->ts_res, &ft->atime);
5548 round_timespec(conn->ts_res, &ft->mtime);
5550 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5551 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5552 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5553 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5554 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5555 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5556 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5557 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5559 if (setting_write_time) {
5561 * This was a Windows setfileinfo on an open file.
5562 * NT does this a lot. We also need to
5563 * set the time here, as it can be read by
5564 * FindFirst/FindNext and with the patch for bug #2045
5565 * in smbd/fileio.c it ensures that this timestamp is
5566 * kept sticky even after a write. We save the request
5567 * away and will set it on file close and after a write. JRA.
5570 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5571 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5573 if (fsp != NULL) {
5574 if (fsp->base_fsp) {
5575 set_sticky_write_time_fsp(fsp->base_fsp,
5576 ft->mtime);
5577 } else {
5578 set_sticky_write_time_fsp(fsp, ft->mtime);
5580 } else {
5581 set_sticky_write_time_path(
5582 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5583 ft->mtime);
5587 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5589 /* Always call ntimes on the base, even if a stream was passed in. */
5590 smb_fname_base = *smb_fname;
5591 smb_fname_base.stream_name = NULL;
5593 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5594 return map_nt_error_from_unix(errno);
5597 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5598 smb_fname->base_name);
5599 return NT_STATUS_OK;
5602 /****************************************************************************
5603 Deal with setting the dosmode from any of the setfilepathinfo functions.
5604 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5605 done before calling this function.
5606 ****************************************************************************/
5608 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5609 const struct smb_filename *smb_fname,
5610 uint32 dosmode)
5612 struct smb_filename *smb_fname_base = NULL;
5613 NTSTATUS status;
5615 if (!VALID_STAT(smb_fname->st)) {
5616 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5619 /* Always operate on the base_name, even if a stream was passed in. */
5620 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5621 NULL, &smb_fname->st,
5622 &smb_fname_base);
5623 if (!NT_STATUS_IS_OK(status)) {
5624 return status;
5627 if (dosmode) {
5628 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5629 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5630 } else {
5631 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5635 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5637 /* check the mode isn't different, before changing it */
5638 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5639 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5640 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5641 (unsigned int)dosmode));
5643 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5644 false)) {
5645 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5646 "%s failed (%s)\n",
5647 smb_fname_str_dbg(smb_fname_base),
5648 strerror(errno)));
5649 status = map_nt_error_from_unix(errno);
5650 goto out;
5653 status = NT_STATUS_OK;
5654 out:
5655 TALLOC_FREE(smb_fname_base);
5656 return status;
5659 /****************************************************************************
5660 Deal with setting the size from any of the setfilepathinfo functions.
5661 ****************************************************************************/
5663 static NTSTATUS smb_set_file_size(connection_struct *conn,
5664 struct smb_request *req,
5665 files_struct *fsp,
5666 const struct smb_filename *smb_fname,
5667 const SMB_STRUCT_STAT *psbuf,
5668 off_t size,
5669 bool fail_after_createfile)
5671 NTSTATUS status = NT_STATUS_OK;
5672 struct smb_filename *smb_fname_tmp = NULL;
5673 files_struct *new_fsp = NULL;
5675 if (!VALID_STAT(*psbuf)) {
5676 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5679 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5681 if (size == get_file_size_stat(psbuf)) {
5682 return NT_STATUS_OK;
5685 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5686 smb_fname_str_dbg(smb_fname), (double)size));
5688 if (fsp && fsp->fh->fd != -1) {
5689 /* Handle based call. */
5690 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5691 return NT_STATUS_ACCESS_DENIED;
5694 if (vfs_set_filelen(fsp, size) == -1) {
5695 return map_nt_error_from_unix(errno);
5697 trigger_write_time_update_immediate(fsp);
5698 return NT_STATUS_OK;
5701 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5702 if (!NT_STATUS_IS_OK(status)) {
5703 return status;
5706 smb_fname_tmp->st = *psbuf;
5708 status = SMB_VFS_CREATE_FILE(
5709 conn, /* conn */
5710 req, /* req */
5711 0, /* root_dir_fid */
5712 smb_fname_tmp, /* fname */
5713 FILE_WRITE_DATA, /* access_mask */
5714 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5715 FILE_SHARE_DELETE),
5716 FILE_OPEN, /* create_disposition*/
5717 0, /* create_options */
5718 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5719 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5720 0, /* allocation_size */
5721 0, /* private_flags */
5722 NULL, /* sd */
5723 NULL, /* ea_list */
5724 &new_fsp, /* result */
5725 NULL); /* pinfo */
5727 TALLOC_FREE(smb_fname_tmp);
5729 if (!NT_STATUS_IS_OK(status)) {
5730 /* NB. We check for open_was_deferred in the caller. */
5731 return status;
5734 /* See RAW-SFILEINFO-END-OF-FILE */
5735 if (fail_after_createfile) {
5736 close_file(req, new_fsp,NORMAL_CLOSE);
5737 return NT_STATUS_INVALID_LEVEL;
5740 if (vfs_set_filelen(new_fsp, size) == -1) {
5741 status = map_nt_error_from_unix(errno);
5742 close_file(req, new_fsp,NORMAL_CLOSE);
5743 return status;
5746 trigger_write_time_update_immediate(new_fsp);
5747 close_file(req, new_fsp,NORMAL_CLOSE);
5748 return NT_STATUS_OK;
5751 /****************************************************************************
5752 Deal with SMB_INFO_SET_EA.
5753 ****************************************************************************/
5755 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5756 const char *pdata,
5757 int total_data,
5758 files_struct *fsp,
5759 const struct smb_filename *smb_fname)
5761 struct ea_list *ea_list = NULL;
5762 TALLOC_CTX *ctx = NULL;
5763 NTSTATUS status = NT_STATUS_OK;
5765 if (total_data < 10) {
5767 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5768 length. They seem to have no effect. Bug #3212. JRA */
5770 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5771 /* We're done. We only get EA info in this call. */
5772 return NT_STATUS_OK;
5775 return NT_STATUS_INVALID_PARAMETER;
5778 if (IVAL(pdata,0) > total_data) {
5779 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5780 IVAL(pdata,0), (unsigned int)total_data));
5781 return NT_STATUS_INVALID_PARAMETER;
5784 ctx = talloc_tos();
5785 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5786 if (!ea_list) {
5787 return NT_STATUS_INVALID_PARAMETER;
5790 status = set_ea(conn, fsp, smb_fname, ea_list);
5792 return status;
5795 /****************************************************************************
5796 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5797 ****************************************************************************/
5799 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5800 const char *pdata,
5801 int total_data,
5802 files_struct *fsp)
5804 struct ea_list *ea_list = NULL;
5805 NTSTATUS status;
5807 if (!fsp) {
5808 return NT_STATUS_INVALID_HANDLE;
5811 if (!lp_ea_support(SNUM(conn))) {
5812 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5813 "EA's not supported.\n",
5814 (unsigned int)total_data));
5815 return NT_STATUS_EAS_NOT_SUPPORTED;
5818 if (total_data < 10) {
5819 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5820 "too small.\n",
5821 (unsigned int)total_data));
5822 return NT_STATUS_INVALID_PARAMETER;
5825 ea_list = read_nttrans_ea_list(talloc_tos(),
5826 pdata,
5827 total_data);
5829 if (!ea_list) {
5830 return NT_STATUS_INVALID_PARAMETER;
5833 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5835 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5836 smb_fname_str_dbg(fsp->fsp_name),
5837 nt_errstr(status) ));
5839 return status;
5843 /****************************************************************************
5844 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5845 ****************************************************************************/
5847 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5848 const char *pdata,
5849 int total_data,
5850 files_struct *fsp,
5851 struct smb_filename *smb_fname)
5853 NTSTATUS status = NT_STATUS_OK;
5854 bool delete_on_close;
5855 uint32 dosmode = 0;
5857 if (total_data < 1) {
5858 return NT_STATUS_INVALID_PARAMETER;
5861 if (fsp == NULL) {
5862 return NT_STATUS_INVALID_HANDLE;
5865 delete_on_close = (CVAL(pdata,0) ? True : False);
5866 dosmode = dos_mode(conn, smb_fname);
5868 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5869 "delete_on_close = %u\n",
5870 smb_fname_str_dbg(smb_fname),
5871 (unsigned int)dosmode,
5872 (unsigned int)delete_on_close ));
5874 if (delete_on_close) {
5875 status = can_set_delete_on_close(fsp, dosmode);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 return status;
5881 /* The set is across all open files on this dev/inode pair. */
5882 if (!set_delete_on_close(fsp, delete_on_close,
5883 conn->session_info->security_token,
5884 conn->session_info->unix_token)) {
5885 return NT_STATUS_ACCESS_DENIED;
5887 return NT_STATUS_OK;
5890 /****************************************************************************
5891 Deal with SMB_FILE_POSITION_INFORMATION.
5892 ****************************************************************************/
5894 static NTSTATUS smb_file_position_information(connection_struct *conn,
5895 const char *pdata,
5896 int total_data,
5897 files_struct *fsp)
5899 uint64_t position_information;
5901 if (total_data < 8) {
5902 return NT_STATUS_INVALID_PARAMETER;
5905 if (fsp == NULL) {
5906 /* Ignore on pathname based set. */
5907 return NT_STATUS_OK;
5910 position_information = (uint64_t)IVAL(pdata,0);
5911 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5913 DEBUG(10,("smb_file_position_information: Set file position "
5914 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5915 (double)position_information));
5916 fsp->fh->position_information = position_information;
5917 return NT_STATUS_OK;
5920 /****************************************************************************
5921 Deal with SMB_FILE_MODE_INFORMATION.
5922 ****************************************************************************/
5924 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5925 const char *pdata,
5926 int total_data)
5928 uint32 mode;
5930 if (total_data < 4) {
5931 return NT_STATUS_INVALID_PARAMETER;
5933 mode = IVAL(pdata,0);
5934 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5935 return NT_STATUS_INVALID_PARAMETER;
5937 return NT_STATUS_OK;
5940 /****************************************************************************
5941 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5942 ****************************************************************************/
5944 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5945 struct smb_request *req,
5946 const char *pdata,
5947 int total_data,
5948 const struct smb_filename *smb_fname)
5950 char *link_target = NULL;
5951 const char *newname = smb_fname->base_name;
5952 TALLOC_CTX *ctx = talloc_tos();
5954 /* Set a symbolic link. */
5955 /* Don't allow this if follow links is false. */
5957 if (total_data == 0) {
5958 return NT_STATUS_INVALID_PARAMETER;
5961 if (!lp_symlinks(SNUM(conn))) {
5962 return NT_STATUS_ACCESS_DENIED;
5965 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5966 total_data, STR_TERMINATE);
5968 if (!link_target) {
5969 return NT_STATUS_INVALID_PARAMETER;
5972 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5973 newname, link_target ));
5975 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5976 return map_nt_error_from_unix(errno);
5979 return NT_STATUS_OK;
5982 /****************************************************************************
5983 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5984 ****************************************************************************/
5986 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5987 struct smb_request *req,
5988 const char *pdata, int total_data,
5989 struct smb_filename *smb_fname_new)
5991 char *oldname = NULL;
5992 struct smb_filename *smb_fname_old = NULL;
5993 TALLOC_CTX *ctx = talloc_tos();
5994 NTSTATUS status = NT_STATUS_OK;
5996 /* Set a hard link. */
5997 if (total_data == 0) {
5998 return NT_STATUS_INVALID_PARAMETER;
6001 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6002 total_data, STR_TERMINATE, &status);
6003 if (!NT_STATUS_IS_OK(status)) {
6004 return status;
6007 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6008 smb_fname_str_dbg(smb_fname_new), oldname));
6010 status = filename_convert(ctx,
6011 conn,
6012 req->flags2 & FLAGS2_DFS_PATHNAMES,
6013 oldname,
6015 NULL,
6016 &smb_fname_old);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 return status;
6021 return hardlink_internals(ctx, conn, req, false,
6022 smb_fname_old, smb_fname_new);
6025 /****************************************************************************
6026 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6027 ****************************************************************************/
6029 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6030 struct smb_request *req,
6031 const char *pdata,
6032 int total_data,
6033 files_struct *fsp,
6034 struct smb_filename *smb_fname_src)
6036 bool overwrite;
6037 uint32_t len;
6038 char *newname = NULL;
6039 struct smb_filename *smb_fname_dst = NULL;
6040 NTSTATUS status = NT_STATUS_OK;
6041 TALLOC_CTX *ctx = talloc_tos();
6043 if (!fsp) {
6044 return NT_STATUS_INVALID_HANDLE;
6047 if (total_data < 20) {
6048 return NT_STATUS_INVALID_PARAMETER;
6051 overwrite = (CVAL(pdata,0) ? True : False);
6052 len = IVAL(pdata,16);
6054 if (len > (total_data - 20) || (len == 0)) {
6055 return NT_STATUS_INVALID_PARAMETER;
6058 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6059 &pdata[20], len, STR_TERMINATE,
6060 &status);
6061 if (!NT_STATUS_IS_OK(status)) {
6062 return status;
6065 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6066 newname));
6068 status = filename_convert(ctx,
6069 conn,
6070 req->flags2 & FLAGS2_DFS_PATHNAMES,
6071 newname,
6072 UCF_SAVE_LCOMP,
6073 NULL,
6074 &smb_fname_dst);
6075 if (!NT_STATUS_IS_OK(status)) {
6076 return status;
6079 if (fsp->base_fsp) {
6080 /* newname must be a stream name. */
6081 if (newname[0] != ':') {
6082 return NT_STATUS_NOT_SUPPORTED;
6085 /* Create an smb_fname to call rename_internals_fsp() with. */
6086 status = create_synthetic_smb_fname(talloc_tos(),
6087 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6088 &smb_fname_dst);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 goto out;
6094 * Set the original last component, since
6095 * rename_internals_fsp() requires it.
6097 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6098 newname);
6099 if (smb_fname_dst->original_lcomp == NULL) {
6100 status = NT_STATUS_NO_MEMORY;
6101 goto out;
6106 DEBUG(10,("smb2_file_rename_information: "
6107 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6108 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6109 smb_fname_str_dbg(smb_fname_dst)));
6110 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6111 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6112 overwrite);
6114 out:
6115 TALLOC_FREE(smb_fname_dst);
6116 return status;
6119 static NTSTATUS smb_file_link_information(connection_struct *conn,
6120 struct smb_request *req,
6121 const char *pdata,
6122 int total_data,
6123 files_struct *fsp,
6124 struct smb_filename *smb_fname_src)
6126 bool overwrite;
6127 uint32_t len;
6128 char *newname = NULL;
6129 struct smb_filename *smb_fname_dst = NULL;
6130 NTSTATUS status = NT_STATUS_OK;
6131 TALLOC_CTX *ctx = talloc_tos();
6133 if (!fsp) {
6134 return NT_STATUS_INVALID_HANDLE;
6137 if (total_data < 20) {
6138 return NT_STATUS_INVALID_PARAMETER;
6141 overwrite = (CVAL(pdata,0) ? true : false);
6142 len = IVAL(pdata,16);
6144 if (len > (total_data - 20) || (len == 0)) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6149 &pdata[20], len, STR_TERMINATE,
6150 &status);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 return status;
6155 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6156 newname));
6158 status = filename_convert(ctx,
6159 conn,
6160 req->flags2 & FLAGS2_DFS_PATHNAMES,
6161 newname,
6162 UCF_SAVE_LCOMP,
6163 NULL,
6164 &smb_fname_dst);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 return status;
6169 if (fsp->base_fsp) {
6170 /* No stream names. */
6171 return NT_STATUS_NOT_SUPPORTED;
6174 DEBUG(10,("smb_file_link_information: "
6175 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6176 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6177 smb_fname_str_dbg(smb_fname_dst)));
6178 status = hardlink_internals(ctx,
6179 conn,
6180 req,
6181 overwrite,
6182 fsp->fsp_name,
6183 smb_fname_dst);
6185 TALLOC_FREE(smb_fname_dst);
6186 return status;
6189 /****************************************************************************
6190 Deal with SMB_FILE_RENAME_INFORMATION.
6191 ****************************************************************************/
6193 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6194 struct smb_request *req,
6195 const char *pdata,
6196 int total_data,
6197 files_struct *fsp,
6198 struct smb_filename *smb_fname_src)
6200 bool overwrite;
6201 uint32 root_fid;
6202 uint32 len;
6203 char *newname = NULL;
6204 struct smb_filename *smb_fname_dst = NULL;
6205 bool dest_has_wcard = False;
6206 NTSTATUS status = NT_STATUS_OK;
6207 char *p;
6208 TALLOC_CTX *ctx = talloc_tos();
6210 if (total_data < 13) {
6211 return NT_STATUS_INVALID_PARAMETER;
6214 overwrite = (CVAL(pdata,0) ? True : False);
6215 root_fid = IVAL(pdata,4);
6216 len = IVAL(pdata,8);
6218 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6219 return NT_STATUS_INVALID_PARAMETER;
6222 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6223 len, 0, &status,
6224 &dest_has_wcard);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 return status;
6229 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6230 newname));
6232 status = resolve_dfspath_wcard(ctx, conn,
6233 req->flags2 & FLAGS2_DFS_PATHNAMES,
6234 newname,
6235 true,
6236 !conn->sconn->using_smb2,
6237 &newname,
6238 &dest_has_wcard);
6239 if (!NT_STATUS_IS_OK(status)) {
6240 return status;
6243 /* Check the new name has no '/' characters. */
6244 if (strchr_m(newname, '/')) {
6245 return NT_STATUS_NOT_SUPPORTED;
6248 if (fsp && fsp->base_fsp) {
6249 /* newname must be a stream name. */
6250 if (newname[0] != ':') {
6251 return NT_STATUS_NOT_SUPPORTED;
6254 /* Create an smb_fname to call rename_internals_fsp() with. */
6255 status = create_synthetic_smb_fname(talloc_tos(),
6256 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6257 &smb_fname_dst);
6258 if (!NT_STATUS_IS_OK(status)) {
6259 goto out;
6263 * Set the original last component, since
6264 * rename_internals_fsp() requires it.
6266 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6267 newname);
6268 if (smb_fname_dst->original_lcomp == NULL) {
6269 status = NT_STATUS_NO_MEMORY;
6270 goto out;
6273 } else {
6275 * Build up an smb_fname_dst based on the filename passed in.
6276 * We basically just strip off the last component, and put on
6277 * the newname instead.
6279 char *base_name = NULL;
6281 /* newname must *not* be a stream name. */
6282 if (newname[0] == ':') {
6283 return NT_STATUS_NOT_SUPPORTED;
6287 * Strip off the last component (filename) of the path passed
6288 * in.
6290 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6291 if (!base_name) {
6292 return NT_STATUS_NO_MEMORY;
6294 p = strrchr_m(base_name, '/');
6295 if (p) {
6296 p[1] = '\0';
6297 } else {
6298 base_name = talloc_strdup(ctx, "");
6299 if (!base_name) {
6300 return NT_STATUS_NO_MEMORY;
6303 /* Append the new name. */
6304 base_name = talloc_asprintf_append(base_name,
6305 "%s",
6306 newname);
6307 if (!base_name) {
6308 return NT_STATUS_NO_MEMORY;
6311 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6312 (UCF_SAVE_LCOMP |
6313 (dest_has_wcard ?
6314 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6315 0)));
6317 /* If an error we expect this to be
6318 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6320 if (!NT_STATUS_IS_OK(status)) {
6321 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6322 status)) {
6323 goto out;
6325 /* Create an smb_fname to call rename_internals_fsp() */
6326 status = create_synthetic_smb_fname(ctx,
6327 base_name, NULL,
6328 NULL,
6329 &smb_fname_dst);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 goto out;
6336 if (fsp) {
6337 DEBUG(10,("smb_file_rename_information: "
6338 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6339 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6340 smb_fname_str_dbg(smb_fname_dst)));
6341 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6342 overwrite);
6343 } else {
6344 DEBUG(10,("smb_file_rename_information: "
6345 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6346 smb_fname_str_dbg(smb_fname_src),
6347 smb_fname_str_dbg(smb_fname_dst)));
6348 status = rename_internals(ctx, conn, req, smb_fname_src,
6349 smb_fname_dst, 0, overwrite, false,
6350 dest_has_wcard,
6351 FILE_WRITE_ATTRIBUTES);
6353 out:
6354 TALLOC_FREE(smb_fname_dst);
6355 return status;
6358 /****************************************************************************
6359 Deal with SMB_SET_POSIX_ACL.
6360 ****************************************************************************/
6362 #if defined(HAVE_POSIX_ACLS)
6363 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6364 const char *pdata,
6365 int total_data,
6366 files_struct *fsp,
6367 const struct smb_filename *smb_fname)
6369 uint16 posix_acl_version;
6370 uint16 num_file_acls;
6371 uint16 num_def_acls;
6372 bool valid_file_acls = True;
6373 bool valid_def_acls = True;
6375 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6376 return NT_STATUS_INVALID_PARAMETER;
6378 posix_acl_version = SVAL(pdata,0);
6379 num_file_acls = SVAL(pdata,2);
6380 num_def_acls = SVAL(pdata,4);
6382 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6383 valid_file_acls = False;
6384 num_file_acls = 0;
6387 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6388 valid_def_acls = False;
6389 num_def_acls = 0;
6392 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6393 return NT_STATUS_INVALID_PARAMETER;
6396 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6397 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6398 return NT_STATUS_INVALID_PARAMETER;
6401 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6402 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6403 (unsigned int)num_file_acls,
6404 (unsigned int)num_def_acls));
6406 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6407 smb_fname->base_name, num_file_acls,
6408 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6409 return map_nt_error_from_unix(errno);
6412 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6413 smb_fname->base_name, &smb_fname->st, num_def_acls,
6414 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6415 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6416 return map_nt_error_from_unix(errno);
6418 return NT_STATUS_OK;
6420 #endif
6422 /****************************************************************************
6423 Deal with SMB_SET_POSIX_LOCK.
6424 ****************************************************************************/
6426 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6427 struct smb_request *req,
6428 const char *pdata,
6429 int total_data,
6430 files_struct *fsp)
6432 uint64_t count;
6433 uint64_t offset;
6434 uint64_t smblctx;
6435 bool blocking_lock = False;
6436 enum brl_type lock_type;
6438 NTSTATUS status = NT_STATUS_OK;
6440 if (fsp == NULL || fsp->fh->fd == -1) {
6441 return NT_STATUS_INVALID_HANDLE;
6444 if (total_data != POSIX_LOCK_DATA_SIZE) {
6445 return NT_STATUS_INVALID_PARAMETER;
6448 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6449 case POSIX_LOCK_TYPE_READ:
6450 lock_type = READ_LOCK;
6451 break;
6452 case POSIX_LOCK_TYPE_WRITE:
6453 /* Return the right POSIX-mappable error code for files opened read-only. */
6454 if (!fsp->can_write) {
6455 return NT_STATUS_INVALID_HANDLE;
6457 lock_type = WRITE_LOCK;
6458 break;
6459 case POSIX_LOCK_TYPE_UNLOCK:
6460 lock_type = UNLOCK_LOCK;
6461 break;
6462 default:
6463 return NT_STATUS_INVALID_PARAMETER;
6466 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6467 blocking_lock = False;
6468 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6469 blocking_lock = True;
6470 } else {
6471 return NT_STATUS_INVALID_PARAMETER;
6474 if (!lp_blocking_locks(SNUM(conn))) {
6475 blocking_lock = False;
6478 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6479 #if defined(HAVE_LONGLONG)
6480 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6481 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6482 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6483 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6484 #else /* HAVE_LONGLONG */
6485 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6486 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6487 #endif /* HAVE_LONGLONG */
6489 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6490 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6491 fsp_str_dbg(fsp),
6492 (unsigned int)lock_type,
6493 (unsigned long long)smblctx,
6494 (double)count,
6495 (double)offset ));
6497 if (lock_type == UNLOCK_LOCK) {
6498 status = do_unlock(req->sconn->msg_ctx,
6499 fsp,
6500 smblctx,
6501 count,
6502 offset,
6503 POSIX_LOCK);
6504 } else {
6505 uint64_t block_smblctx;
6507 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6508 fsp,
6509 smblctx,
6510 count,
6511 offset,
6512 lock_type,
6513 POSIX_LOCK,
6514 blocking_lock,
6515 &status,
6516 &block_smblctx,
6517 NULL);
6519 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6521 * A blocking lock was requested. Package up
6522 * this smb into a queued request and push it
6523 * onto the blocking lock queue.
6525 if(push_blocking_lock_request(br_lck,
6526 req,
6527 fsp,
6528 -1, /* infinite timeout. */
6530 smblctx,
6531 lock_type,
6532 POSIX_LOCK,
6533 offset,
6534 count,
6535 block_smblctx)) {
6536 TALLOC_FREE(br_lck);
6537 return status;
6540 TALLOC_FREE(br_lck);
6543 return status;
6546 /****************************************************************************
6547 Deal with SMB_SET_FILE_BASIC_INFO.
6548 ****************************************************************************/
6550 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6551 const char *pdata,
6552 int total_data,
6553 files_struct *fsp,
6554 const struct smb_filename *smb_fname)
6556 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6557 struct smb_file_time ft;
6558 uint32 dosmode = 0;
6559 NTSTATUS status = NT_STATUS_OK;
6561 ZERO_STRUCT(ft);
6563 if (total_data < 36) {
6564 return NT_STATUS_INVALID_PARAMETER;
6567 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 return status;
6572 /* Set the attributes */
6573 dosmode = IVAL(pdata,32);
6574 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6575 if (!NT_STATUS_IS_OK(status)) {
6576 return status;
6579 /* create time */
6580 ft.create_time = interpret_long_date(pdata);
6582 /* access time */
6583 ft.atime = interpret_long_date(pdata+8);
6585 /* write time. */
6586 ft.mtime = interpret_long_date(pdata+16);
6588 /* change time. */
6589 ft.ctime = interpret_long_date(pdata+24);
6591 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6592 smb_fname_str_dbg(smb_fname)));
6594 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6595 true);
6598 /****************************************************************************
6599 Deal with SMB_INFO_STANDARD.
6600 ****************************************************************************/
6602 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6603 const char *pdata,
6604 int total_data,
6605 files_struct *fsp,
6606 const struct smb_filename *smb_fname)
6608 NTSTATUS status;
6609 struct smb_file_time ft;
6611 ZERO_STRUCT(ft);
6613 if (total_data < 12) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 /* create time */
6618 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6619 /* access time */
6620 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6621 /* write time */
6622 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6624 DEBUG(10,("smb_set_info_standard: file %s\n",
6625 smb_fname_str_dbg(smb_fname)));
6627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 return status;
6632 return smb_set_file_time(conn,
6633 fsp,
6634 smb_fname,
6635 &ft,
6636 true);
6639 /****************************************************************************
6640 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6641 ****************************************************************************/
6643 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6644 struct smb_request *req,
6645 const char *pdata,
6646 int total_data,
6647 files_struct *fsp,
6648 struct smb_filename *smb_fname)
6650 uint64_t allocation_size = 0;
6651 NTSTATUS status = NT_STATUS_OK;
6652 files_struct *new_fsp = NULL;
6654 if (!VALID_STAT(smb_fname->st)) {
6655 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6658 if (total_data < 8) {
6659 return NT_STATUS_INVALID_PARAMETER;
6662 allocation_size = (uint64_t)IVAL(pdata,0);
6663 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6664 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6665 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6666 (double)allocation_size));
6668 if (allocation_size) {
6669 allocation_size = smb_roundup(conn, allocation_size);
6672 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6673 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6674 (double)allocation_size));
6676 if (fsp && fsp->fh->fd != -1) {
6677 /* Open file handle. */
6678 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6679 return NT_STATUS_ACCESS_DENIED;
6682 /* Only change if needed. */
6683 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6684 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6685 return map_nt_error_from_unix(errno);
6688 /* But always update the time. */
6690 * This is equivalent to a write. Ensure it's seen immediately
6691 * if there are no pending writes.
6693 trigger_write_time_update_immediate(fsp);
6694 return NT_STATUS_OK;
6697 /* Pathname or stat or directory file. */
6698 status = SMB_VFS_CREATE_FILE(
6699 conn, /* conn */
6700 req, /* req */
6701 0, /* root_dir_fid */
6702 smb_fname, /* fname */
6703 FILE_WRITE_DATA, /* access_mask */
6704 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6705 FILE_SHARE_DELETE),
6706 FILE_OPEN, /* create_disposition*/
6707 0, /* create_options */
6708 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6709 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6710 0, /* allocation_size */
6711 0, /* private_flags */
6712 NULL, /* sd */
6713 NULL, /* ea_list */
6714 &new_fsp, /* result */
6715 NULL); /* pinfo */
6717 if (!NT_STATUS_IS_OK(status)) {
6718 /* NB. We check for open_was_deferred in the caller. */
6719 return status;
6722 /* Only change if needed. */
6723 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6724 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6725 status = map_nt_error_from_unix(errno);
6726 close_file(req, new_fsp, NORMAL_CLOSE);
6727 return status;
6731 /* Changing the allocation size should set the last mod time. */
6733 * This is equivalent to a write. Ensure it's seen immediately
6734 * if there are no pending writes.
6736 trigger_write_time_update_immediate(new_fsp);
6738 close_file(req, new_fsp, NORMAL_CLOSE);
6739 return NT_STATUS_OK;
6742 /****************************************************************************
6743 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6744 ****************************************************************************/
6746 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6747 struct smb_request *req,
6748 const char *pdata,
6749 int total_data,
6750 files_struct *fsp,
6751 const struct smb_filename *smb_fname,
6752 bool fail_after_createfile)
6754 off_t size;
6756 if (total_data < 8) {
6757 return NT_STATUS_INVALID_PARAMETER;
6760 size = IVAL(pdata,0);
6761 size |= (((off_t)IVAL(pdata,4)) << 32);
6762 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6763 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6764 (double)size));
6766 return smb_set_file_size(conn, req,
6767 fsp,
6768 smb_fname,
6769 &smb_fname->st,
6770 size,
6771 fail_after_createfile);
6774 /****************************************************************************
6775 Allow a UNIX info mknod.
6776 ****************************************************************************/
6778 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6779 const char *pdata,
6780 int total_data,
6781 const struct smb_filename *smb_fname)
6783 uint32 file_type = IVAL(pdata,56);
6784 #if defined(HAVE_MAKEDEV)
6785 uint32 dev_major = IVAL(pdata,60);
6786 uint32 dev_minor = IVAL(pdata,68);
6787 #endif
6788 SMB_DEV_T dev = (SMB_DEV_T)0;
6789 uint32 raw_unixmode = IVAL(pdata,84);
6790 NTSTATUS status;
6791 mode_t unixmode;
6793 if (total_data < 100) {
6794 return NT_STATUS_INVALID_PARAMETER;
6797 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6798 PERM_NEW_FILE, &unixmode);
6799 if (!NT_STATUS_IS_OK(status)) {
6800 return status;
6803 #if defined(HAVE_MAKEDEV)
6804 dev = makedev(dev_major, dev_minor);
6805 #endif
6807 switch (file_type) {
6808 #if defined(S_IFIFO)
6809 case UNIX_TYPE_FIFO:
6810 unixmode |= S_IFIFO;
6811 break;
6812 #endif
6813 #if defined(S_IFSOCK)
6814 case UNIX_TYPE_SOCKET:
6815 unixmode |= S_IFSOCK;
6816 break;
6817 #endif
6818 #if defined(S_IFCHR)
6819 case UNIX_TYPE_CHARDEV:
6820 unixmode |= S_IFCHR;
6821 break;
6822 #endif
6823 #if defined(S_IFBLK)
6824 case UNIX_TYPE_BLKDEV:
6825 unixmode |= S_IFBLK;
6826 break;
6827 #endif
6828 default:
6829 return NT_STATUS_INVALID_PARAMETER;
6832 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6833 "%.0f mode 0%o for file %s\n", (double)dev,
6834 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6836 /* Ok - do the mknod. */
6837 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6838 return map_nt_error_from_unix(errno);
6841 /* If any of the other "set" calls fail we
6842 * don't want to end up with a half-constructed mknod.
6845 if (lp_inherit_perms(SNUM(conn))) {
6846 char *parent;
6847 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6848 &parent, NULL)) {
6849 return NT_STATUS_NO_MEMORY;
6851 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6852 unixmode);
6853 TALLOC_FREE(parent);
6856 return NT_STATUS_OK;
6859 /****************************************************************************
6860 Deal with SMB_SET_FILE_UNIX_BASIC.
6861 ****************************************************************************/
6863 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6864 struct smb_request *req,
6865 const char *pdata,
6866 int total_data,
6867 files_struct *fsp,
6868 const struct smb_filename *smb_fname)
6870 struct smb_file_time ft;
6871 uint32 raw_unixmode;
6872 mode_t unixmode;
6873 off_t size = 0;
6874 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6875 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6876 NTSTATUS status = NT_STATUS_OK;
6877 bool delete_on_fail = False;
6878 enum perm_type ptype;
6879 files_struct *all_fsps = NULL;
6880 bool modify_mtime = true;
6881 struct file_id id;
6882 struct smb_filename *smb_fname_tmp = NULL;
6883 SMB_STRUCT_STAT sbuf;
6885 ZERO_STRUCT(ft);
6887 if (total_data < 100) {
6888 return NT_STATUS_INVALID_PARAMETER;
6891 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6892 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6893 size=IVAL(pdata,0); /* first 8 Bytes are size */
6894 size |= (((off_t)IVAL(pdata,4)) << 32);
6897 ft.atime = interpret_long_date(pdata+24); /* access_time */
6898 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6899 set_owner = (uid_t)IVAL(pdata,40);
6900 set_grp = (gid_t)IVAL(pdata,48);
6901 raw_unixmode = IVAL(pdata,84);
6903 if (VALID_STAT(smb_fname->st)) {
6904 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6905 ptype = PERM_EXISTING_DIR;
6906 } else {
6907 ptype = PERM_EXISTING_FILE;
6909 } else {
6910 ptype = PERM_NEW_FILE;
6913 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6914 ptype, &unixmode);
6915 if (!NT_STATUS_IS_OK(status)) {
6916 return status;
6919 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6920 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6921 smb_fname_str_dbg(smb_fname), (double)size,
6922 (unsigned int)set_owner, (unsigned int)set_grp,
6923 (int)raw_unixmode));
6925 sbuf = smb_fname->st;
6927 if (!VALID_STAT(sbuf)) {
6929 * The only valid use of this is to create character and block
6930 * devices, and named pipes. This is deprecated (IMHO) and
6931 * a new info level should be used for mknod. JRA.
6934 status = smb_unix_mknod(conn,
6935 pdata,
6936 total_data,
6937 smb_fname);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 return status;
6942 status = copy_smb_filename(talloc_tos(), smb_fname,
6943 &smb_fname_tmp);
6944 if (!NT_STATUS_IS_OK(status)) {
6945 return status;
6948 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6949 status = map_nt_error_from_unix(errno);
6950 TALLOC_FREE(smb_fname_tmp);
6951 SMB_VFS_UNLINK(conn, smb_fname);
6952 return status;
6955 sbuf = smb_fname_tmp->st;
6956 smb_fname = smb_fname_tmp;
6958 /* Ensure we don't try and change anything else. */
6959 raw_unixmode = SMB_MODE_NO_CHANGE;
6960 size = get_file_size_stat(&sbuf);
6961 ft.atime = sbuf.st_ex_atime;
6962 ft.mtime = sbuf.st_ex_mtime;
6964 * We continue here as we might want to change the
6965 * owner uid/gid.
6967 delete_on_fail = True;
6970 #if 1
6971 /* Horrible backwards compatibility hack as an old server bug
6972 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6973 * */
6975 if (!size) {
6976 size = get_file_size_stat(&sbuf);
6978 #endif
6981 * Deal with the UNIX specific mode set.
6984 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6985 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6986 "setting mode 0%o for file %s\n",
6987 (unsigned int)unixmode,
6988 smb_fname_str_dbg(smb_fname)));
6989 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6990 return map_nt_error_from_unix(errno);
6995 * Deal with the UNIX specific uid set.
6998 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6999 (sbuf.st_ex_uid != set_owner)) {
7000 int ret;
7002 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7003 "changing owner %u for path %s\n",
7004 (unsigned int)set_owner,
7005 smb_fname_str_dbg(smb_fname)));
7007 if (S_ISLNK(sbuf.st_ex_mode)) {
7008 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7009 set_owner, (gid_t)-1);
7010 } else {
7011 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7012 set_owner, (gid_t)-1);
7015 if (ret != 0) {
7016 status = map_nt_error_from_unix(errno);
7017 if (delete_on_fail) {
7018 SMB_VFS_UNLINK(conn, smb_fname);
7020 return status;
7025 * Deal with the UNIX specific gid set.
7028 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7029 (sbuf.st_ex_gid != set_grp)) {
7030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7031 "changing group %u for file %s\n",
7032 (unsigned int)set_owner,
7033 smb_fname_str_dbg(smb_fname)));
7034 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7035 set_grp) != 0) {
7036 status = map_nt_error_from_unix(errno);
7037 if (delete_on_fail) {
7038 SMB_VFS_UNLINK(conn, smb_fname);
7040 return status;
7044 /* Deal with any size changes. */
7046 status = smb_set_file_size(conn, req,
7047 fsp,
7048 smb_fname,
7049 &sbuf,
7050 size,
7051 false);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return status;
7056 /* Deal with any time changes. */
7057 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7058 /* No change, don't cancel anything. */
7059 return status;
7062 id = vfs_file_id_from_sbuf(conn, &sbuf);
7063 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7064 all_fsps = file_find_di_next(all_fsps)) {
7066 * We're setting the time explicitly for UNIX.
7067 * Cancel any pending changes over all handles.
7069 all_fsps->update_write_time_on_close = false;
7070 TALLOC_FREE(all_fsps->update_write_time_event);
7074 * Override the "setting_write_time"
7075 * parameter here as it almost does what
7076 * we need. Just remember if we modified
7077 * mtime and send the notify ourselves.
7079 if (null_timespec(ft.mtime)) {
7080 modify_mtime = false;
7083 status = smb_set_file_time(conn,
7084 fsp,
7085 smb_fname,
7086 &ft,
7087 false);
7088 if (modify_mtime) {
7089 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7090 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7092 return status;
7095 /****************************************************************************
7096 Deal with SMB_SET_FILE_UNIX_INFO2.
7097 ****************************************************************************/
7099 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7100 struct smb_request *req,
7101 const char *pdata,
7102 int total_data,
7103 files_struct *fsp,
7104 const struct smb_filename *smb_fname)
7106 NTSTATUS status;
7107 uint32 smb_fflags;
7108 uint32 smb_fmask;
7110 if (total_data < 116) {
7111 return NT_STATUS_INVALID_PARAMETER;
7114 /* Start by setting all the fields that are common between UNIX_BASIC
7115 * and UNIX_INFO2.
7117 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7118 fsp, smb_fname);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 return status;
7123 smb_fflags = IVAL(pdata, 108);
7124 smb_fmask = IVAL(pdata, 112);
7126 /* NB: We should only attempt to alter the file flags if the client
7127 * sends a non-zero mask.
7129 if (smb_fmask != 0) {
7130 int stat_fflags = 0;
7132 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7133 smb_fmask, &stat_fflags)) {
7134 /* Client asked to alter a flag we don't understand. */
7135 return NT_STATUS_INVALID_PARAMETER;
7138 if (fsp && fsp->fh->fd != -1) {
7139 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7140 return NT_STATUS_NOT_SUPPORTED;
7141 } else {
7142 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7143 stat_fflags) != 0) {
7144 return map_nt_error_from_unix(errno);
7149 /* XXX: need to add support for changing the create_time here. You
7150 * can do this for paths on Darwin with setattrlist(2). The right way
7151 * to hook this up is probably by extending the VFS utimes interface.
7154 return NT_STATUS_OK;
7157 /****************************************************************************
7158 Create a directory with POSIX semantics.
7159 ****************************************************************************/
7161 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7162 struct smb_request *req,
7163 char **ppdata,
7164 int total_data,
7165 struct smb_filename *smb_fname,
7166 int *pdata_return_size)
7168 NTSTATUS status = NT_STATUS_OK;
7169 uint32 raw_unixmode = 0;
7170 uint32 mod_unixmode = 0;
7171 mode_t unixmode = (mode_t)0;
7172 files_struct *fsp = NULL;
7173 uint16 info_level_return = 0;
7174 int info;
7175 char *pdata = *ppdata;
7177 if (total_data < 18) {
7178 return NT_STATUS_INVALID_PARAMETER;
7181 raw_unixmode = IVAL(pdata,8);
7182 /* Next 4 bytes are not yet defined. */
7184 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7185 PERM_NEW_DIR, &unixmode);
7186 if (!NT_STATUS_IS_OK(status)) {
7187 return status;
7190 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7192 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7193 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7195 status = SMB_VFS_CREATE_FILE(
7196 conn, /* conn */
7197 req, /* req */
7198 0, /* root_dir_fid */
7199 smb_fname, /* fname */
7200 FILE_READ_ATTRIBUTES, /* access_mask */
7201 FILE_SHARE_NONE, /* share_access */
7202 FILE_CREATE, /* create_disposition*/
7203 FILE_DIRECTORY_FILE, /* create_options */
7204 mod_unixmode, /* file_attributes */
7205 0, /* oplock_request */
7206 0, /* allocation_size */
7207 0, /* private_flags */
7208 NULL, /* sd */
7209 NULL, /* ea_list */
7210 &fsp, /* result */
7211 &info); /* pinfo */
7213 if (NT_STATUS_IS_OK(status)) {
7214 close_file(req, fsp, NORMAL_CLOSE);
7217 info_level_return = SVAL(pdata,16);
7219 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7220 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7221 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7222 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7223 } else {
7224 *pdata_return_size = 12;
7227 /* Realloc the data size */
7228 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7229 if (*ppdata == NULL) {
7230 *pdata_return_size = 0;
7231 return NT_STATUS_NO_MEMORY;
7233 pdata = *ppdata;
7235 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7236 SSVAL(pdata,2,0); /* No fnum. */
7237 SIVAL(pdata,4,info); /* Was directory created. */
7239 switch (info_level_return) {
7240 case SMB_QUERY_FILE_UNIX_BASIC:
7241 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7242 SSVAL(pdata,10,0); /* Padding. */
7243 store_file_unix_basic(conn, pdata + 12, fsp,
7244 &smb_fname->st);
7245 break;
7246 case SMB_QUERY_FILE_UNIX_INFO2:
7247 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7248 SSVAL(pdata,10,0); /* Padding. */
7249 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7250 &smb_fname->st);
7251 break;
7252 default:
7253 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7254 SSVAL(pdata,10,0); /* Padding. */
7255 break;
7258 return status;
7261 /****************************************************************************
7262 Open/Create a file with POSIX semantics.
7263 ****************************************************************************/
7265 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7266 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7268 static NTSTATUS smb_posix_open(connection_struct *conn,
7269 struct smb_request *req,
7270 char **ppdata,
7271 int total_data,
7272 struct smb_filename *smb_fname,
7273 int *pdata_return_size)
7275 bool extended_oplock_granted = False;
7276 char *pdata = *ppdata;
7277 uint32 flags = 0;
7278 uint32 wire_open_mode = 0;
7279 uint32 raw_unixmode = 0;
7280 uint32 mod_unixmode = 0;
7281 uint32 create_disp = 0;
7282 uint32 access_mask = 0;
7283 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7284 NTSTATUS status = NT_STATUS_OK;
7285 mode_t unixmode = (mode_t)0;
7286 files_struct *fsp = NULL;
7287 int oplock_request = 0;
7288 int info = 0;
7289 uint16 info_level_return = 0;
7291 if (total_data < 18) {
7292 return NT_STATUS_INVALID_PARAMETER;
7295 flags = IVAL(pdata,0);
7296 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7297 if (oplock_request) {
7298 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7301 wire_open_mode = IVAL(pdata,4);
7303 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7304 return smb_posix_mkdir(conn, req,
7305 ppdata,
7306 total_data,
7307 smb_fname,
7308 pdata_return_size);
7311 switch (wire_open_mode & SMB_ACCMODE) {
7312 case SMB_O_RDONLY:
7313 access_mask = SMB_O_RDONLY_MAPPING;
7314 break;
7315 case SMB_O_WRONLY:
7316 access_mask = SMB_O_WRONLY_MAPPING;
7317 break;
7318 case SMB_O_RDWR:
7319 access_mask = (SMB_O_RDONLY_MAPPING|
7320 SMB_O_WRONLY_MAPPING);
7321 break;
7322 default:
7323 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7324 (unsigned int)wire_open_mode ));
7325 return NT_STATUS_INVALID_PARAMETER;
7328 wire_open_mode &= ~SMB_ACCMODE;
7330 /* First take care of O_CREAT|O_EXCL interactions. */
7331 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7332 case (SMB_O_CREAT | SMB_O_EXCL):
7333 /* File exists fail. File not exist create. */
7334 create_disp = FILE_CREATE;
7335 break;
7336 case SMB_O_CREAT:
7337 /* File exists open. File not exist create. */
7338 create_disp = FILE_OPEN_IF;
7339 break;
7340 case 0:
7341 /* File exists open. File not exist fail. */
7342 create_disp = FILE_OPEN;
7343 break;
7344 case SMB_O_EXCL:
7345 /* O_EXCL on its own without O_CREAT is undefined. */
7346 default:
7347 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7348 (unsigned int)wire_open_mode ));
7349 return NT_STATUS_INVALID_PARAMETER;
7352 /* Next factor in the effects of O_TRUNC. */
7353 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7355 if (wire_open_mode & SMB_O_TRUNC) {
7356 switch (create_disp) {
7357 case FILE_CREATE:
7358 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7359 /* Leave create_disp alone as
7360 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7362 /* File exists fail. File not exist create. */
7363 break;
7364 case FILE_OPEN_IF:
7365 /* SMB_O_CREAT | SMB_O_TRUNC */
7366 /* File exists overwrite. File not exist create. */
7367 create_disp = FILE_OVERWRITE_IF;
7368 break;
7369 case FILE_OPEN:
7370 /* SMB_O_TRUNC */
7371 /* File exists overwrite. File not exist fail. */
7372 create_disp = FILE_OVERWRITE;
7373 break;
7374 default:
7375 /* Cannot get here. */
7376 smb_panic("smb_posix_open: logic error");
7377 return NT_STATUS_INVALID_PARAMETER;
7381 raw_unixmode = IVAL(pdata,8);
7382 /* Next 4 bytes are not yet defined. */
7384 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7385 (VALID_STAT(smb_fname->st) ?
7386 PERM_EXISTING_FILE : PERM_NEW_FILE),
7387 &unixmode);
7389 if (!NT_STATUS_IS_OK(status)) {
7390 return status;
7393 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7395 if (wire_open_mode & SMB_O_SYNC) {
7396 create_options |= FILE_WRITE_THROUGH;
7398 if (wire_open_mode & SMB_O_APPEND) {
7399 access_mask |= FILE_APPEND_DATA;
7401 if (wire_open_mode & SMB_O_DIRECT) {
7402 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7405 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7406 VALID_STAT_OF_DIR(smb_fname->st)) {
7407 if (access_mask != SMB_O_RDONLY_MAPPING) {
7408 return NT_STATUS_FILE_IS_A_DIRECTORY;
7410 create_options &= ~FILE_NON_DIRECTORY_FILE;
7411 create_options |= FILE_DIRECTORY_FILE;
7414 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7415 smb_fname_str_dbg(smb_fname),
7416 (unsigned int)wire_open_mode,
7417 (unsigned int)unixmode ));
7419 status = SMB_VFS_CREATE_FILE(
7420 conn, /* conn */
7421 req, /* req */
7422 0, /* root_dir_fid */
7423 smb_fname, /* fname */
7424 access_mask, /* access_mask */
7425 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7426 FILE_SHARE_DELETE),
7427 create_disp, /* create_disposition*/
7428 create_options, /* create_options */
7429 mod_unixmode, /* file_attributes */
7430 oplock_request, /* oplock_request */
7431 0, /* allocation_size */
7432 0, /* private_flags */
7433 NULL, /* sd */
7434 NULL, /* ea_list */
7435 &fsp, /* result */
7436 &info); /* pinfo */
7438 if (!NT_STATUS_IS_OK(status)) {
7439 return status;
7442 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7443 extended_oplock_granted = True;
7446 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7447 extended_oplock_granted = True;
7450 info_level_return = SVAL(pdata,16);
7452 /* Allocate the correct return size. */
7454 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7455 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7456 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7457 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7458 } else {
7459 *pdata_return_size = 12;
7462 /* Realloc the data size */
7463 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7464 if (*ppdata == NULL) {
7465 close_file(req, fsp, ERROR_CLOSE);
7466 *pdata_return_size = 0;
7467 return NT_STATUS_NO_MEMORY;
7469 pdata = *ppdata;
7471 if (extended_oplock_granted) {
7472 if (flags & REQUEST_BATCH_OPLOCK) {
7473 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7474 } else {
7475 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7477 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7478 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7479 } else {
7480 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7483 SSVAL(pdata,2,fsp->fnum);
7484 SIVAL(pdata,4,info); /* Was file created etc. */
7486 switch (info_level_return) {
7487 case SMB_QUERY_FILE_UNIX_BASIC:
7488 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7489 SSVAL(pdata,10,0); /* padding. */
7490 store_file_unix_basic(conn, pdata + 12, fsp,
7491 &smb_fname->st);
7492 break;
7493 case SMB_QUERY_FILE_UNIX_INFO2:
7494 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7495 SSVAL(pdata,10,0); /* padding. */
7496 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7497 &smb_fname->st);
7498 break;
7499 default:
7500 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7501 SSVAL(pdata,10,0); /* padding. */
7502 break;
7504 return NT_STATUS_OK;
7507 /****************************************************************************
7508 Delete a file with POSIX semantics.
7509 ****************************************************************************/
7511 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7512 struct smb_request *req,
7513 const char *pdata,
7514 int total_data,
7515 struct smb_filename *smb_fname)
7517 NTSTATUS status = NT_STATUS_OK;
7518 files_struct *fsp = NULL;
7519 uint16 flags = 0;
7520 char del = 1;
7521 int info = 0;
7522 int create_options = 0;
7523 int i;
7524 struct share_mode_lock *lck = NULL;
7526 if (total_data < 2) {
7527 return NT_STATUS_INVALID_PARAMETER;
7530 flags = SVAL(pdata,0);
7532 if (!VALID_STAT(smb_fname->st)) {
7533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7536 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7537 !VALID_STAT_OF_DIR(smb_fname->st)) {
7538 return NT_STATUS_NOT_A_DIRECTORY;
7541 DEBUG(10,("smb_posix_unlink: %s %s\n",
7542 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7543 smb_fname_str_dbg(smb_fname)));
7545 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7546 create_options |= FILE_DIRECTORY_FILE;
7549 status = SMB_VFS_CREATE_FILE(
7550 conn, /* conn */
7551 req, /* req */
7552 0, /* root_dir_fid */
7553 smb_fname, /* fname */
7554 DELETE_ACCESS, /* access_mask */
7555 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7556 FILE_SHARE_DELETE),
7557 FILE_OPEN, /* create_disposition*/
7558 create_options, /* create_options */
7559 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7560 0, /* oplock_request */
7561 0, /* allocation_size */
7562 0, /* private_flags */
7563 NULL, /* sd */
7564 NULL, /* ea_list */
7565 &fsp, /* result */
7566 &info); /* pinfo */
7568 if (!NT_STATUS_IS_OK(status)) {
7569 return status;
7573 * Don't lie to client. If we can't really delete due to
7574 * non-POSIX opens return SHARING_VIOLATION.
7577 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7578 if (lck == NULL) {
7579 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7580 "lock for file %s\n", fsp_str_dbg(fsp)));
7581 close_file(req, fsp, NORMAL_CLOSE);
7582 return NT_STATUS_INVALID_PARAMETER;
7586 * See if others still have the file open. If this is the case, then
7587 * don't delete. If all opens are POSIX delete we can set the delete
7588 * on close disposition.
7590 for (i=0; i<lck->data->num_share_modes; i++) {
7591 struct share_mode_entry *e = &lck->data->share_modes[i];
7592 if (is_valid_share_mode_entry(e)) {
7593 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7594 continue;
7596 if (share_mode_stale_pid(lck->data, i)) {
7597 continue;
7599 /* Fail with sharing violation. */
7600 close_file(req, fsp, NORMAL_CLOSE);
7601 TALLOC_FREE(lck);
7602 return NT_STATUS_SHARING_VIOLATION;
7607 * Set the delete on close.
7609 status = smb_set_file_disposition_info(conn,
7610 &del,
7612 fsp,
7613 smb_fname);
7615 if (!NT_STATUS_IS_OK(status)) {
7616 close_file(req, fsp, NORMAL_CLOSE);
7617 TALLOC_FREE(lck);
7618 return status;
7620 TALLOC_FREE(lck);
7621 return close_file(req, fsp, NORMAL_CLOSE);
7624 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7625 struct smb_request *req,
7626 TALLOC_CTX *mem_ctx,
7627 uint16_t info_level,
7628 files_struct *fsp,
7629 struct smb_filename *smb_fname,
7630 char **ppdata, int total_data,
7631 int *ret_data_size)
7633 char *pdata = *ppdata;
7634 NTSTATUS status = NT_STATUS_OK;
7635 int data_return_size = 0;
7637 *ret_data_size = 0;
7639 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7640 return NT_STATUS_INVALID_LEVEL;
7643 if (!CAN_WRITE(conn)) {
7644 /* Allow POSIX opens. The open path will deny
7645 * any non-readonly opens. */
7646 if (info_level != SMB_POSIX_PATH_OPEN) {
7647 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7651 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7652 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7653 fsp_fnum_dbg(fsp),
7654 info_level, total_data));
7656 switch (info_level) {
7658 case SMB_INFO_STANDARD:
7660 status = smb_set_info_standard(conn,
7661 pdata,
7662 total_data,
7663 fsp,
7664 smb_fname);
7665 break;
7668 case SMB_INFO_SET_EA:
7670 status = smb_info_set_ea(conn,
7671 pdata,
7672 total_data,
7673 fsp,
7674 smb_fname);
7675 break;
7678 case SMB_SET_FILE_BASIC_INFO:
7679 case SMB_FILE_BASIC_INFORMATION:
7681 status = smb_set_file_basic_info(conn,
7682 pdata,
7683 total_data,
7684 fsp,
7685 smb_fname);
7686 break;
7689 case SMB_FILE_ALLOCATION_INFORMATION:
7690 case SMB_SET_FILE_ALLOCATION_INFO:
7692 status = smb_set_file_allocation_info(conn, req,
7693 pdata,
7694 total_data,
7695 fsp,
7696 smb_fname);
7697 break;
7700 case SMB_FILE_END_OF_FILE_INFORMATION:
7701 case SMB_SET_FILE_END_OF_FILE_INFO:
7704 * XP/Win7 both fail after the createfile with
7705 * SMB_SET_FILE_END_OF_FILE_INFO but not
7706 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7707 * The level is known here, so pass it down
7708 * appropriately.
7710 bool should_fail =
7711 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7713 status = smb_set_file_end_of_file_info(conn, req,
7714 pdata,
7715 total_data,
7716 fsp,
7717 smb_fname,
7718 should_fail);
7719 break;
7722 case SMB_FILE_DISPOSITION_INFORMATION:
7723 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7725 #if 0
7726 /* JRA - We used to just ignore this on a path ?
7727 * Shouldn't this be invalid level on a pathname
7728 * based call ?
7730 if (tran_call != TRANSACT2_SETFILEINFO) {
7731 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7733 #endif
7734 status = smb_set_file_disposition_info(conn,
7735 pdata,
7736 total_data,
7737 fsp,
7738 smb_fname);
7739 break;
7742 case SMB_FILE_POSITION_INFORMATION:
7744 status = smb_file_position_information(conn,
7745 pdata,
7746 total_data,
7747 fsp);
7748 break;
7751 case SMB_FILE_FULL_EA_INFORMATION:
7753 status = smb_set_file_full_ea_info(conn,
7754 pdata,
7755 total_data,
7756 fsp);
7757 break;
7760 /* From tridge Samba4 :
7761 * MODE_INFORMATION in setfileinfo (I have no
7762 * idea what "mode information" on a file is - it takes a value of 0,
7763 * 2, 4 or 6. What could it be?).
7766 case SMB_FILE_MODE_INFORMATION:
7768 status = smb_file_mode_information(conn,
7769 pdata,
7770 total_data);
7771 break;
7775 * CIFS UNIX extensions.
7778 case SMB_SET_FILE_UNIX_BASIC:
7780 status = smb_set_file_unix_basic(conn, req,
7781 pdata,
7782 total_data,
7783 fsp,
7784 smb_fname);
7785 break;
7788 case SMB_SET_FILE_UNIX_INFO2:
7790 status = smb_set_file_unix_info2(conn, req,
7791 pdata,
7792 total_data,
7793 fsp,
7794 smb_fname);
7795 break;
7798 case SMB_SET_FILE_UNIX_LINK:
7800 if (fsp) {
7801 /* We must have a pathname for this. */
7802 return NT_STATUS_INVALID_LEVEL;
7804 status = smb_set_file_unix_link(conn, req, pdata,
7805 total_data, smb_fname);
7806 break;
7809 case SMB_SET_FILE_UNIX_HLINK:
7811 if (fsp) {
7812 /* We must have a pathname for this. */
7813 return NT_STATUS_INVALID_LEVEL;
7815 status = smb_set_file_unix_hlink(conn, req,
7816 pdata, total_data,
7817 smb_fname);
7818 break;
7821 case SMB_FILE_RENAME_INFORMATION:
7823 status = smb_file_rename_information(conn, req,
7824 pdata, total_data,
7825 fsp, smb_fname);
7826 break;
7829 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7831 /* SMB2 rename information. */
7832 status = smb2_file_rename_information(conn, req,
7833 pdata, total_data,
7834 fsp, smb_fname);
7835 break;
7838 case SMB_FILE_LINK_INFORMATION:
7840 status = smb_file_link_information(conn, req,
7841 pdata, total_data,
7842 fsp, smb_fname);
7843 break;
7846 #if defined(HAVE_POSIX_ACLS)
7847 case SMB_SET_POSIX_ACL:
7849 status = smb_set_posix_acl(conn,
7850 pdata,
7851 total_data,
7852 fsp,
7853 smb_fname);
7854 break;
7856 #endif
7858 case SMB_SET_POSIX_LOCK:
7860 if (!fsp) {
7861 return NT_STATUS_INVALID_LEVEL;
7863 status = smb_set_posix_lock(conn, req,
7864 pdata, total_data, fsp);
7865 break;
7868 case SMB_POSIX_PATH_OPEN:
7870 if (fsp) {
7871 /* We must have a pathname for this. */
7872 return NT_STATUS_INVALID_LEVEL;
7875 status = smb_posix_open(conn, req,
7876 ppdata,
7877 total_data,
7878 smb_fname,
7879 &data_return_size);
7880 break;
7883 case SMB_POSIX_PATH_UNLINK:
7885 if (fsp) {
7886 /* We must have a pathname for this. */
7887 return NT_STATUS_INVALID_LEVEL;
7890 status = smb_posix_unlink(conn, req,
7891 pdata,
7892 total_data,
7893 smb_fname);
7894 break;
7897 default:
7898 return NT_STATUS_INVALID_LEVEL;
7901 if (!NT_STATUS_IS_OK(status)) {
7902 return status;
7905 *ret_data_size = data_return_size;
7906 return NT_STATUS_OK;
7909 /****************************************************************************
7910 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7911 ****************************************************************************/
7913 static void call_trans2setfilepathinfo(connection_struct *conn,
7914 struct smb_request *req,
7915 unsigned int tran_call,
7916 char **pparams, int total_params,
7917 char **ppdata, int total_data,
7918 unsigned int max_data_bytes)
7920 char *params = *pparams;
7921 char *pdata = *ppdata;
7922 uint16 info_level;
7923 struct smb_filename *smb_fname = NULL;
7924 files_struct *fsp = NULL;
7925 NTSTATUS status = NT_STATUS_OK;
7926 int data_return_size = 0;
7928 if (!params) {
7929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930 return;
7933 if (tran_call == TRANSACT2_SETFILEINFO) {
7934 if (total_params < 4) {
7935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936 return;
7939 fsp = file_fsp(req, SVAL(params,0));
7940 /* Basic check for non-null fsp. */
7941 if (!check_fsp_open(conn, req, fsp)) {
7942 return;
7944 info_level = SVAL(params,2);
7946 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7947 &smb_fname);
7948 if (!NT_STATUS_IS_OK(status)) {
7949 reply_nterror(req, status);
7950 return;
7953 if(fsp->fh->fd == -1) {
7955 * This is actually a SETFILEINFO on a directory
7956 * handle (returned from an NT SMB). NT5.0 seems
7957 * to do this call. JRA.
7959 if (INFO_LEVEL_IS_UNIX(info_level)) {
7960 /* Always do lstat for UNIX calls. */
7961 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7962 DEBUG(3,("call_trans2setfilepathinfo: "
7963 "SMB_VFS_LSTAT of %s failed "
7964 "(%s)\n",
7965 smb_fname_str_dbg(smb_fname),
7966 strerror(errno)));
7967 reply_nterror(req, map_nt_error_from_unix(errno));
7968 return;
7970 } else {
7971 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7972 DEBUG(3,("call_trans2setfilepathinfo: "
7973 "fileinfo of %s failed (%s)\n",
7974 smb_fname_str_dbg(smb_fname),
7975 strerror(errno)));
7976 reply_nterror(req, map_nt_error_from_unix(errno));
7977 return;
7980 } else if (fsp->print_file) {
7982 * Doing a DELETE_ON_CLOSE should cancel a print job.
7984 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7985 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7987 DEBUG(3,("call_trans2setfilepathinfo: "
7988 "Cancelling print job (%s)\n",
7989 fsp_str_dbg(fsp)));
7991 SSVAL(params,0,0);
7992 send_trans2_replies(conn, req, params, 2,
7993 *ppdata, 0,
7994 max_data_bytes);
7995 return;
7996 } else {
7997 reply_nterror(req,
7998 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7999 return;
8001 } else {
8003 * Original code - this is an open file.
8005 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8006 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8007 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8008 strerror(errno)));
8009 reply_nterror(req, map_nt_error_from_unix(errno));
8010 return;
8013 } else {
8014 char *fname = NULL;
8015 uint32_t ucf_flags = 0;
8017 /* set path info */
8018 if (total_params < 7) {
8019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8020 return;
8023 info_level = SVAL(params,0);
8024 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8025 total_params - 6, STR_TERMINATE,
8026 &status);
8027 if (!NT_STATUS_IS_OK(status)) {
8028 reply_nterror(req, status);
8029 return;
8032 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8033 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8034 info_level == SMB_FILE_RENAME_INFORMATION ||
8035 info_level == SMB_POSIX_PATH_UNLINK) {
8036 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8039 status = filename_convert(req, conn,
8040 req->flags2 & FLAGS2_DFS_PATHNAMES,
8041 fname,
8042 ucf_flags,
8043 NULL,
8044 &smb_fname);
8045 if (!NT_STATUS_IS_OK(status)) {
8046 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8047 reply_botherror(req,
8048 NT_STATUS_PATH_NOT_COVERED,
8049 ERRSRV, ERRbadpath);
8050 return;
8052 reply_nterror(req, status);
8053 return;
8056 if (INFO_LEVEL_IS_UNIX(info_level)) {
8058 * For CIFS UNIX extensions the target name may not exist.
8061 /* Always do lstat for UNIX calls. */
8062 SMB_VFS_LSTAT(conn, smb_fname);
8064 } else if (!VALID_STAT(smb_fname->st) &&
8065 SMB_VFS_STAT(conn, smb_fname)) {
8066 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8067 "%s failed (%s)\n",
8068 smb_fname_str_dbg(smb_fname),
8069 strerror(errno)));
8070 reply_nterror(req, map_nt_error_from_unix(errno));
8071 return;
8075 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8076 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8077 fsp_fnum_dbg(fsp),
8078 info_level,total_data));
8080 /* Realloc the parameter size */
8081 *pparams = (char *)SMB_REALLOC(*pparams,2);
8082 if (*pparams == NULL) {
8083 reply_nterror(req, NT_STATUS_NO_MEMORY);
8084 return;
8086 params = *pparams;
8088 SSVAL(params,0,0);
8090 status = smbd_do_setfilepathinfo(conn, req, req,
8091 info_level,
8092 fsp,
8093 smb_fname,
8094 ppdata, total_data,
8095 &data_return_size);
8096 if (!NT_STATUS_IS_OK(status)) {
8097 if (open_was_deferred(req->sconn, req->mid)) {
8098 /* We have re-scheduled this call. */
8099 return;
8101 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8102 /* We have re-scheduled this call. */
8103 return;
8105 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8106 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8107 ERRSRV, ERRbadpath);
8108 return;
8110 if (info_level == SMB_POSIX_PATH_OPEN) {
8111 reply_openerror(req, status);
8112 return;
8115 reply_nterror(req, status);
8116 return;
8119 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8120 max_data_bytes);
8122 return;
8125 /****************************************************************************
8126 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8127 ****************************************************************************/
8129 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8130 char **pparams, int total_params,
8131 char **ppdata, int total_data,
8132 unsigned int max_data_bytes)
8134 struct smb_filename *smb_dname = NULL;
8135 char *params = *pparams;
8136 char *pdata = *ppdata;
8137 char *directory = NULL;
8138 NTSTATUS status = NT_STATUS_OK;
8139 struct ea_list *ea_list = NULL;
8140 TALLOC_CTX *ctx = talloc_tos();
8142 if (!CAN_WRITE(conn)) {
8143 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8144 return;
8147 if (total_params < 5) {
8148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8149 return;
8152 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8153 total_params - 4, STR_TERMINATE,
8154 &status);
8155 if (!NT_STATUS_IS_OK(status)) {
8156 reply_nterror(req, status);
8157 return;
8160 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8162 status = filename_convert(ctx,
8163 conn,
8164 req->flags2 & FLAGS2_DFS_PATHNAMES,
8165 directory,
8167 NULL,
8168 &smb_dname);
8170 if (!NT_STATUS_IS_OK(status)) {
8171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8172 reply_botherror(req,
8173 NT_STATUS_PATH_NOT_COVERED,
8174 ERRSRV, ERRbadpath);
8175 return;
8177 reply_nterror(req, status);
8178 return;
8182 * OS/2 workplace shell seems to send SET_EA requests of "null"
8183 * length (4 bytes containing IVAL 4).
8184 * They seem to have no effect. Bug #3212. JRA.
8187 if (total_data && (total_data != 4)) {
8188 /* Any data in this call is an EA list. */
8189 if (total_data < 10) {
8190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8191 goto out;
8194 if (IVAL(pdata,0) > total_data) {
8195 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8196 IVAL(pdata,0), (unsigned int)total_data));
8197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8198 goto out;
8201 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8202 total_data - 4);
8203 if (!ea_list) {
8204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8205 goto out;
8208 if (!lp_ea_support(SNUM(conn))) {
8209 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8210 goto out;
8213 /* If total_data == 4 Windows doesn't care what values
8214 * are placed in that field, it just ignores them.
8215 * The System i QNTC IBM SMB client puts bad values here,
8216 * so ignore them. */
8218 status = create_directory(conn, req, smb_dname);
8220 if (!NT_STATUS_IS_OK(status)) {
8221 reply_nterror(req, status);
8222 goto out;
8225 /* Try and set any given EA. */
8226 if (ea_list) {
8227 status = set_ea(conn, NULL, smb_dname, ea_list);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 reply_nterror(req, status);
8230 goto out;
8234 /* Realloc the parameter and data sizes */
8235 *pparams = (char *)SMB_REALLOC(*pparams,2);
8236 if(*pparams == NULL) {
8237 reply_nterror(req, NT_STATUS_NO_MEMORY);
8238 goto out;
8240 params = *pparams;
8242 SSVAL(params,0,0);
8244 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8246 out:
8247 TALLOC_FREE(smb_dname);
8248 return;
8251 /****************************************************************************
8252 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8253 We don't actually do this - we just send a null response.
8254 ****************************************************************************/
8256 static void call_trans2findnotifyfirst(connection_struct *conn,
8257 struct smb_request *req,
8258 char **pparams, int total_params,
8259 char **ppdata, int total_data,
8260 unsigned int max_data_bytes)
8262 char *params = *pparams;
8263 uint16 info_level;
8265 if (total_params < 6) {
8266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8267 return;
8270 info_level = SVAL(params,4);
8271 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8273 switch (info_level) {
8274 case 1:
8275 case 2:
8276 break;
8277 default:
8278 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8279 return;
8282 /* Realloc the parameter and data sizes */
8283 *pparams = (char *)SMB_REALLOC(*pparams,6);
8284 if (*pparams == NULL) {
8285 reply_nterror(req, NT_STATUS_NO_MEMORY);
8286 return;
8288 params = *pparams;
8290 SSVAL(params,0,fnf_handle);
8291 SSVAL(params,2,0); /* No changes */
8292 SSVAL(params,4,0); /* No EA errors */
8294 fnf_handle++;
8296 if(fnf_handle == 0)
8297 fnf_handle = 257;
8299 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8301 return;
8304 /****************************************************************************
8305 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8306 changes). Currently this does nothing.
8307 ****************************************************************************/
8309 static void call_trans2findnotifynext(connection_struct *conn,
8310 struct smb_request *req,
8311 char **pparams, int total_params,
8312 char **ppdata, int total_data,
8313 unsigned int max_data_bytes)
8315 char *params = *pparams;
8317 DEBUG(3,("call_trans2findnotifynext\n"));
8319 /* Realloc the parameter and data sizes */
8320 *pparams = (char *)SMB_REALLOC(*pparams,4);
8321 if (*pparams == NULL) {
8322 reply_nterror(req, NT_STATUS_NO_MEMORY);
8323 return;
8325 params = *pparams;
8327 SSVAL(params,0,0); /* No changes */
8328 SSVAL(params,2,0); /* No EA errors */
8330 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8332 return;
8335 /****************************************************************************
8336 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8337 ****************************************************************************/
8339 static void call_trans2getdfsreferral(connection_struct *conn,
8340 struct smb_request *req,
8341 char **pparams, int total_params,
8342 char **ppdata, int total_data,
8343 unsigned int max_data_bytes)
8345 char *params = *pparams;
8346 char *pathname = NULL;
8347 int reply_size = 0;
8348 int max_referral_level;
8349 NTSTATUS status = NT_STATUS_OK;
8350 TALLOC_CTX *ctx = talloc_tos();
8352 DEBUG(10,("call_trans2getdfsreferral\n"));
8354 if (total_params < 3) {
8355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8356 return;
8359 max_referral_level = SVAL(params,0);
8361 if(!lp_host_msdfs()) {
8362 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8363 return;
8366 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8367 total_params - 2, STR_TERMINATE);
8368 if (!pathname) {
8369 reply_nterror(req, NT_STATUS_NOT_FOUND);
8370 return;
8372 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8373 ppdata,&status)) < 0) {
8374 reply_nterror(req, status);
8375 return;
8378 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8379 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8380 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8382 return;
8385 #define LMCAT_SPL 0x53
8386 #define LMFUNC_GETJOBID 0x60
8388 /****************************************************************************
8389 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8390 ****************************************************************************/
8392 static void call_trans2ioctl(connection_struct *conn,
8393 struct smb_request *req,
8394 char **pparams, int total_params,
8395 char **ppdata, int total_data,
8396 unsigned int max_data_bytes)
8398 char *pdata = *ppdata;
8399 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8401 /* check for an invalid fid before proceeding */
8403 if (!fsp) {
8404 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8405 return;
8408 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8409 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8410 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8411 if (*ppdata == NULL) {
8412 reply_nterror(req, NT_STATUS_NO_MEMORY);
8413 return;
8415 pdata = *ppdata;
8417 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8418 CAN ACCEPT THIS IN UNICODE. JRA. */
8420 /* Job number */
8421 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8423 srvstr_push(pdata, req->flags2, pdata + 2,
8424 lp_netbios_name(), 15,
8425 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8426 srvstr_push(pdata, req->flags2, pdata+18,
8427 lp_servicename(SNUM(conn)), 13,
8428 STR_ASCII|STR_TERMINATE); /* Service name */
8429 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8430 max_data_bytes);
8431 return;
8434 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8435 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8438 /****************************************************************************
8439 Reply to a SMBfindclose (stop trans2 directory search).
8440 ****************************************************************************/
8442 void reply_findclose(struct smb_request *req)
8444 int dptr_num;
8445 struct smbd_server_connection *sconn = req->sconn;
8447 START_PROFILE(SMBfindclose);
8449 if (req->wct < 1) {
8450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8451 END_PROFILE(SMBfindclose);
8452 return;
8455 dptr_num = SVALS(req->vwv+0, 0);
8457 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8459 dptr_close(sconn, &dptr_num);
8461 reply_outbuf(req, 0, 0);
8463 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8465 END_PROFILE(SMBfindclose);
8466 return;
8469 /****************************************************************************
8470 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8471 ****************************************************************************/
8473 void reply_findnclose(struct smb_request *req)
8475 int dptr_num;
8477 START_PROFILE(SMBfindnclose);
8479 if (req->wct < 1) {
8480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8481 END_PROFILE(SMBfindnclose);
8482 return;
8485 dptr_num = SVAL(req->vwv+0, 0);
8487 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8489 /* We never give out valid handles for a
8490 findnotifyfirst - so any dptr_num is ok here.
8491 Just ignore it. */
8493 reply_outbuf(req, 0, 0);
8495 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8497 END_PROFILE(SMBfindnclose);
8498 return;
8501 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8502 struct trans_state *state)
8504 if (get_Protocol() >= PROTOCOL_NT1) {
8505 req->flags2 |= 0x40; /* IS_LONG_NAME */
8506 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8509 if (conn->encrypt_level == Required && !req->encrypted) {
8510 if (state->call != TRANSACT2_QFSINFO &&
8511 state->call != TRANSACT2_SETFSINFO) {
8512 DEBUG(0,("handle_trans2: encryption required "
8513 "with call 0x%x\n",
8514 (unsigned int)state->call));
8515 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8516 return;
8520 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8522 /* Now we must call the relevant TRANS2 function */
8523 switch(state->call) {
8524 case TRANSACT2_OPEN:
8526 START_PROFILE(Trans2_open);
8527 call_trans2open(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_open);
8532 break;
8535 case TRANSACT2_FINDFIRST:
8537 START_PROFILE(Trans2_findfirst);
8538 call_trans2findfirst(conn, req,
8539 &state->param, state->total_param,
8540 &state->data, state->total_data,
8541 state->max_data_return);
8542 END_PROFILE(Trans2_findfirst);
8543 break;
8546 case TRANSACT2_FINDNEXT:
8548 START_PROFILE(Trans2_findnext);
8549 call_trans2findnext(conn, req,
8550 &state->param, state->total_param,
8551 &state->data, state->total_data,
8552 state->max_data_return);
8553 END_PROFILE(Trans2_findnext);
8554 break;
8557 case TRANSACT2_QFSINFO:
8559 START_PROFILE(Trans2_qfsinfo);
8560 call_trans2qfsinfo(conn, req,
8561 &state->param, state->total_param,
8562 &state->data, state->total_data,
8563 state->max_data_return);
8564 END_PROFILE(Trans2_qfsinfo);
8565 break;
8568 case TRANSACT2_SETFSINFO:
8570 START_PROFILE(Trans2_setfsinfo);
8571 call_trans2setfsinfo(conn, req,
8572 &state->param, state->total_param,
8573 &state->data, state->total_data,
8574 state->max_data_return);
8575 END_PROFILE(Trans2_setfsinfo);
8576 break;
8579 case TRANSACT2_QPATHINFO:
8580 case TRANSACT2_QFILEINFO:
8582 START_PROFILE(Trans2_qpathinfo);
8583 call_trans2qfilepathinfo(conn, req, state->call,
8584 &state->param, state->total_param,
8585 &state->data, state->total_data,
8586 state->max_data_return);
8587 END_PROFILE(Trans2_qpathinfo);
8588 break;
8591 case TRANSACT2_SETPATHINFO:
8592 case TRANSACT2_SETFILEINFO:
8594 START_PROFILE(Trans2_setpathinfo);
8595 call_trans2setfilepathinfo(conn, req, state->call,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_setpathinfo);
8600 break;
8603 case TRANSACT2_FINDNOTIFYFIRST:
8605 START_PROFILE(Trans2_findnotifyfirst);
8606 call_trans2findnotifyfirst(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_findnotifyfirst);
8611 break;
8614 case TRANSACT2_FINDNOTIFYNEXT:
8616 START_PROFILE(Trans2_findnotifynext);
8617 call_trans2findnotifynext(conn, req,
8618 &state->param, state->total_param,
8619 &state->data, state->total_data,
8620 state->max_data_return);
8621 END_PROFILE(Trans2_findnotifynext);
8622 break;
8625 case TRANSACT2_MKDIR:
8627 START_PROFILE(Trans2_mkdir);
8628 call_trans2mkdir(conn, req,
8629 &state->param, state->total_param,
8630 &state->data, state->total_data,
8631 state->max_data_return);
8632 END_PROFILE(Trans2_mkdir);
8633 break;
8636 case TRANSACT2_GET_DFS_REFERRAL:
8638 START_PROFILE(Trans2_get_dfs_referral);
8639 call_trans2getdfsreferral(conn, req,
8640 &state->param, state->total_param,
8641 &state->data, state->total_data,
8642 state->max_data_return);
8643 END_PROFILE(Trans2_get_dfs_referral);
8644 break;
8647 case TRANSACT2_IOCTL:
8649 START_PROFILE(Trans2_ioctl);
8650 call_trans2ioctl(conn, req,
8651 &state->param, state->total_param,
8652 &state->data, state->total_data,
8653 state->max_data_return);
8654 END_PROFILE(Trans2_ioctl);
8655 break;
8658 default:
8659 /* Error in request */
8660 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8661 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8665 /****************************************************************************
8666 Reply to a SMBtrans2.
8667 ****************************************************************************/
8669 void reply_trans2(struct smb_request *req)
8671 connection_struct *conn = req->conn;
8672 unsigned int dsoff;
8673 unsigned int dscnt;
8674 unsigned int psoff;
8675 unsigned int pscnt;
8676 unsigned int tran_call;
8677 struct trans_state *state;
8678 NTSTATUS result;
8680 START_PROFILE(SMBtrans2);
8682 if (req->wct < 14) {
8683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8684 END_PROFILE(SMBtrans2);
8685 return;
8688 dsoff = SVAL(req->vwv+12, 0);
8689 dscnt = SVAL(req->vwv+11, 0);
8690 psoff = SVAL(req->vwv+10, 0);
8691 pscnt = SVAL(req->vwv+9, 0);
8692 tran_call = SVAL(req->vwv+14, 0);
8694 result = allow_new_trans(conn->pending_trans, req->mid);
8695 if (!NT_STATUS_IS_OK(result)) {
8696 DEBUG(2, ("Got invalid trans2 request: %s\n",
8697 nt_errstr(result)));
8698 reply_nterror(req, result);
8699 END_PROFILE(SMBtrans2);
8700 return;
8703 if (IS_IPC(conn)) {
8704 switch (tran_call) {
8705 /* List the allowed trans2 calls on IPC$ */
8706 case TRANSACT2_OPEN:
8707 case TRANSACT2_GET_DFS_REFERRAL:
8708 case TRANSACT2_QFILEINFO:
8709 case TRANSACT2_QFSINFO:
8710 case TRANSACT2_SETFSINFO:
8711 break;
8712 default:
8713 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8714 END_PROFILE(SMBtrans2);
8715 return;
8719 if ((state = talloc(conn, struct trans_state)) == NULL) {
8720 DEBUG(0, ("talloc failed\n"));
8721 reply_nterror(req, NT_STATUS_NO_MEMORY);
8722 END_PROFILE(SMBtrans2);
8723 return;
8726 state->cmd = SMBtrans2;
8728 state->mid = req->mid;
8729 state->vuid = req->vuid;
8730 state->setup_count = SVAL(req->vwv+13, 0);
8731 state->setup = NULL;
8732 state->total_param = SVAL(req->vwv+0, 0);
8733 state->param = NULL;
8734 state->total_data = SVAL(req->vwv+1, 0);
8735 state->data = NULL;
8736 state->max_param_return = SVAL(req->vwv+2, 0);
8737 state->max_data_return = SVAL(req->vwv+3, 0);
8738 state->max_setup_return = SVAL(req->vwv+4, 0);
8739 state->close_on_completion = BITSETW(req->vwv+5, 0);
8740 state->one_way = BITSETW(req->vwv+5, 1);
8742 state->call = tran_call;
8744 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8745 is so as a sanity check */
8746 if (state->setup_count != 1) {
8748 * Need to have rc=0 for ioctl to get job id for OS/2.
8749 * Network printing will fail if function is not successful.
8750 * Similar function in reply.c will be used if protocol
8751 * is LANMAN1.0 instead of LM1.2X002.
8752 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8753 * outbuf doesn't have to be set(only job id is used).
8755 if ( (state->setup_count == 4)
8756 && (tran_call == TRANSACT2_IOCTL)
8757 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8758 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8759 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8760 } else {
8761 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8762 DEBUG(2,("Transaction is %d\n",tran_call));
8763 TALLOC_FREE(state);
8764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8765 END_PROFILE(SMBtrans2);
8766 return;
8770 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8771 goto bad_param;
8773 if (state->total_data) {
8775 if (trans_oob(state->total_data, 0, dscnt)
8776 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8777 goto bad_param;
8780 /* Can't use talloc here, the core routines do realloc on the
8781 * params and data. */
8782 state->data = (char *)SMB_MALLOC(state->total_data);
8783 if (state->data == NULL) {
8784 DEBUG(0,("reply_trans2: data malloc fail for %u "
8785 "bytes !\n", (unsigned int)state->total_data));
8786 TALLOC_FREE(state);
8787 reply_nterror(req, NT_STATUS_NO_MEMORY);
8788 END_PROFILE(SMBtrans2);
8789 return;
8792 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8795 if (state->total_param) {
8797 if (trans_oob(state->total_param, 0, pscnt)
8798 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8799 goto bad_param;
8802 /* Can't use talloc here, the core routines do realloc on the
8803 * params and data. */
8804 state->param = (char *)SMB_MALLOC(state->total_param);
8805 if (state->param == NULL) {
8806 DEBUG(0,("reply_trans: param malloc fail for %u "
8807 "bytes !\n", (unsigned int)state->total_param));
8808 SAFE_FREE(state->data);
8809 TALLOC_FREE(state);
8810 reply_nterror(req, NT_STATUS_NO_MEMORY);
8811 END_PROFILE(SMBtrans2);
8812 return;
8815 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8818 state->received_data = dscnt;
8819 state->received_param = pscnt;
8821 if ((state->received_param == state->total_param) &&
8822 (state->received_data == state->total_data)) {
8824 handle_trans2(conn, req, state);
8826 SAFE_FREE(state->data);
8827 SAFE_FREE(state->param);
8828 TALLOC_FREE(state);
8829 END_PROFILE(SMBtrans2);
8830 return;
8833 DLIST_ADD(conn->pending_trans, state);
8835 /* We need to send an interim response then receive the rest
8836 of the parameter/data bytes */
8837 reply_outbuf(req, 0, 0);
8838 show_msg((char *)req->outbuf);
8839 END_PROFILE(SMBtrans2);
8840 return;
8842 bad_param:
8844 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8845 SAFE_FREE(state->data);
8846 SAFE_FREE(state->param);
8847 TALLOC_FREE(state);
8848 END_PROFILE(SMBtrans2);
8849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8853 /****************************************************************************
8854 Reply to a SMBtranss2
8855 ****************************************************************************/
8857 void reply_transs2(struct smb_request *req)
8859 connection_struct *conn = req->conn;
8860 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8861 struct trans_state *state;
8863 START_PROFILE(SMBtranss2);
8865 show_msg((const char *)req->inbuf);
8867 /* Windows clients expect all replies to
8868 a transact secondary (SMBtranss2 0x33)
8869 to have a command code of transact
8870 (SMBtrans2 0x32). See bug #8989
8871 and also [MS-CIFS] section 2.2.4.47.2
8872 for details.
8874 req->cmd = SMBtrans2;
8876 if (req->wct < 8) {
8877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8878 END_PROFILE(SMBtranss2);
8879 return;
8882 for (state = conn->pending_trans; state != NULL;
8883 state = state->next) {
8884 if (state->mid == req->mid) {
8885 break;
8889 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8891 END_PROFILE(SMBtranss2);
8892 return;
8895 /* Revise state->total_param and state->total_data in case they have
8896 changed downwards */
8898 if (SVAL(req->vwv+0, 0) < state->total_param)
8899 state->total_param = SVAL(req->vwv+0, 0);
8900 if (SVAL(req->vwv+1, 0) < state->total_data)
8901 state->total_data = SVAL(req->vwv+1, 0);
8903 pcnt = SVAL(req->vwv+2, 0);
8904 poff = SVAL(req->vwv+3, 0);
8905 pdisp = SVAL(req->vwv+4, 0);
8907 dcnt = SVAL(req->vwv+5, 0);
8908 doff = SVAL(req->vwv+6, 0);
8909 ddisp = SVAL(req->vwv+7, 0);
8911 state->received_param += pcnt;
8912 state->received_data += dcnt;
8914 if ((state->received_data > state->total_data) ||
8915 (state->received_param > state->total_param))
8916 goto bad_param;
8918 if (pcnt) {
8919 if (trans_oob(state->total_param, pdisp, pcnt)
8920 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8921 goto bad_param;
8923 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8926 if (dcnt) {
8927 if (trans_oob(state->total_data, ddisp, dcnt)
8928 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8929 goto bad_param;
8931 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8934 if ((state->received_param < state->total_param) ||
8935 (state->received_data < state->total_data)) {
8936 END_PROFILE(SMBtranss2);
8937 return;
8940 handle_trans2(conn, req, state);
8942 DLIST_REMOVE(conn->pending_trans, state);
8943 SAFE_FREE(state->data);
8944 SAFE_FREE(state->param);
8945 TALLOC_FREE(state);
8947 END_PROFILE(SMBtranss2);
8948 return;
8950 bad_param:
8952 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8953 DLIST_REMOVE(conn->pending_trans, state);
8954 SAFE_FREE(state->data);
8955 SAFE_FREE(state->param);
8956 TALLOC_FREE(state);
8957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8958 END_PROFILE(SMBtranss2);
8959 return;