libcli/smb: add basic session->smb2.channel_sequence handling
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob73feaf879846cc9bd9b6fef2efa42b082e176956
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(ctx, SNUM(conn))));
2499 if (in_list(directory,lp_dontdescend(ctx, 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(ctx, SNUM(conn))));
2828 if (in_list(directory,lp_dontdescend(ctx, 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(talloc_tos(), 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(talloc_tos(), SNUM(conn));
2996 int snum = SNUM(conn);
2997 char *fstype = lp_fstype(talloc_tos(), 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(talloc_tos(), 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(talloc_tos(), 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,
3154 lp_servicename(talloc_tos(), snum)));
3155 break;
3157 case SMB_QUERY_FS_SIZE_INFO:
3158 case SMB_FS_SIZE_INFORMATION:
3160 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3161 data_len = 24;
3162 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3163 return map_nt_error_from_unix(errno);
3165 block_size = lp_block_size(snum);
3166 if (bsize < block_size) {
3167 uint64_t factor = block_size/bsize;
3168 bsize = block_size;
3169 dsize /= factor;
3170 dfree /= factor;
3172 if (bsize > block_size) {
3173 uint64_t factor = bsize/block_size;
3174 bsize = block_size;
3175 dsize *= factor;
3176 dfree *= factor;
3178 bytes_per_sector = 512;
3179 sectors_per_unit = bsize/bytes_per_sector;
3180 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3181 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3182 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3183 SBIG_UINT(pdata,0,dsize);
3184 SBIG_UINT(pdata,8,dfree);
3185 SIVAL(pdata,16,sectors_per_unit);
3186 SIVAL(pdata,20,bytes_per_sector);
3187 break;
3190 case SMB_FS_FULL_SIZE_INFORMATION:
3192 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3193 data_len = 32;
3194 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3195 return map_nt_error_from_unix(errno);
3197 block_size = lp_block_size(snum);
3198 if (bsize < block_size) {
3199 uint64_t factor = block_size/bsize;
3200 bsize = block_size;
3201 dsize /= factor;
3202 dfree /= factor;
3204 if (bsize > block_size) {
3205 uint64_t factor = bsize/block_size;
3206 bsize = block_size;
3207 dsize *= factor;
3208 dfree *= factor;
3210 bytes_per_sector = 512;
3211 sectors_per_unit = bsize/bytes_per_sector;
3212 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3213 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3214 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3215 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3216 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3217 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3218 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3219 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3220 break;
3223 case SMB_QUERY_FS_DEVICE_INFO:
3224 case SMB_FS_DEVICE_INFORMATION:
3226 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3228 if (!CAN_WRITE(conn)) {
3229 characteristics |= FILE_READ_ONLY_DEVICE;
3231 data_len = 8;
3232 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3233 SIVAL(pdata,4,characteristics);
3234 break;
3237 #ifdef HAVE_SYS_QUOTAS
3238 case SMB_FS_QUOTA_INFORMATION:
3240 * what we have to send --metze:
3242 * Unknown1: 24 NULL bytes
3243 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3244 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3245 * Quota Flags: 2 byte :
3246 * Unknown3: 6 NULL bytes
3248 * 48 bytes total
3250 * details for Quota Flags:
3252 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3253 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3254 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3255 * 0x0001 Enable Quotas: enable quota for this fs
3259 /* we need to fake up a fsp here,
3260 * because its not send in this call
3262 files_struct fsp;
3263 SMB_NTQUOTA_STRUCT quotas;
3265 ZERO_STRUCT(fsp);
3266 ZERO_STRUCT(quotas);
3268 fsp.conn = conn;
3269 fsp.fnum = FNUM_FIELD_INVALID;
3271 /* access check */
3272 if (get_current_uid(conn) != 0) {
3273 DEBUG(0,("set_user_quota: access_denied "
3274 "service [%s] user [%s]\n",
3275 lp_servicename(talloc_tos(), SNUM(conn)),
3276 conn->session_info->unix_info->unix_name));
3277 return NT_STATUS_ACCESS_DENIED;
3280 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3281 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3282 return map_nt_error_from_unix(errno);
3285 data_len = 48;
3287 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3288 lp_servicename(talloc_tos(), SNUM(conn))));
3290 /* Unknown1 24 NULL bytes*/
3291 SBIG_UINT(pdata,0,(uint64_t)0);
3292 SBIG_UINT(pdata,8,(uint64_t)0);
3293 SBIG_UINT(pdata,16,(uint64_t)0);
3295 /* Default Soft Quota 8 bytes */
3296 SBIG_UINT(pdata,24,quotas.softlim);
3298 /* Default Hard Quota 8 bytes */
3299 SBIG_UINT(pdata,32,quotas.hardlim);
3301 /* Quota flag 2 bytes */
3302 SSVAL(pdata,40,quotas.qflags);
3304 /* Unknown3 6 NULL bytes */
3305 SSVAL(pdata,42,0);
3306 SIVAL(pdata,44,0);
3308 break;
3310 #endif /* HAVE_SYS_QUOTAS */
3311 case SMB_FS_OBJECTID_INFORMATION:
3313 unsigned char objid[16];
3314 struct smb_extended_info extended_info;
3315 memcpy(pdata,create_volume_objectid(conn, objid),16);
3316 samba_extended_info_version (&extended_info);
3317 SIVAL(pdata,16,extended_info.samba_magic);
3318 SIVAL(pdata,20,extended_info.samba_version);
3319 SIVAL(pdata,24,extended_info.samba_subversion);
3320 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3321 memcpy(pdata+36,extended_info.samba_version_string,28);
3322 data_len = 64;
3323 break;
3327 * Query the version and capabilities of the CIFS UNIX extensions
3328 * in use.
3331 case SMB_QUERY_CIFS_UNIX_INFO:
3333 bool large_write = lp_min_receive_file_size() &&
3334 !srv_is_signing_active(conn->sconn);
3335 bool large_read = !srv_is_signing_active(conn->sconn);
3336 int encrypt_caps = 0;
3338 if (!lp_unix_extensions()) {
3339 return NT_STATUS_INVALID_LEVEL;
3342 switch (conn->encrypt_level) {
3343 case 0:
3344 encrypt_caps = 0;
3345 break;
3346 case 1:
3347 case Auto:
3348 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3349 break;
3350 case Required:
3351 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3352 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3353 large_write = false;
3354 large_read = false;
3355 break;
3358 data_len = 12;
3359 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3360 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3362 /* We have POSIX ACLs, pathname, encryption,
3363 * large read/write, and locking capability. */
3365 SBIG_UINT(pdata,4,((uint64_t)(
3366 CIFS_UNIX_POSIX_ACLS_CAP|
3367 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3368 CIFS_UNIX_FCNTL_LOCKS_CAP|
3369 CIFS_UNIX_EXTATTR_CAP|
3370 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3371 encrypt_caps|
3372 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3373 (large_write ?
3374 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3375 break;
3378 case SMB_QUERY_POSIX_FS_INFO:
3380 int rc;
3381 vfs_statvfs_struct svfs;
3383 if (!lp_unix_extensions()) {
3384 return NT_STATUS_INVALID_LEVEL;
3387 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3389 if (!rc) {
3390 data_len = 56;
3391 SIVAL(pdata,0,svfs.OptimalTransferSize);
3392 SIVAL(pdata,4,svfs.BlockSize);
3393 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3394 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3395 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3396 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3397 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3398 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3399 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3400 #ifdef EOPNOTSUPP
3401 } else if (rc == EOPNOTSUPP) {
3402 return NT_STATUS_INVALID_LEVEL;
3403 #endif /* EOPNOTSUPP */
3404 } else {
3405 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3406 return NT_STATUS_DOS(ERRSRV, ERRerror);
3408 break;
3411 case SMB_QUERY_POSIX_WHOAMI:
3413 uint32_t flags = 0;
3414 uint32_t sid_bytes;
3415 int i;
3417 if (!lp_unix_extensions()) {
3418 return NT_STATUS_INVALID_LEVEL;
3421 if (max_data_bytes < 40) {
3422 return NT_STATUS_BUFFER_TOO_SMALL;
3425 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3426 flags |= SMB_WHOAMI_GUEST;
3429 /* NOTE: 8 bytes for UID/GID, irrespective of native
3430 * platform size. This matches
3431 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3433 data_len = 4 /* flags */
3434 + 4 /* flag mask */
3435 + 8 /* uid */
3436 + 8 /* gid */
3437 + 4 /* ngroups */
3438 + 4 /* num_sids */
3439 + 4 /* SID bytes */
3440 + 4 /* pad/reserved */
3441 + (conn->session_info->unix_token->ngroups * 8)
3442 /* groups list */
3443 + (conn->session_info->security_token->num_sids *
3444 SID_MAX_SIZE)
3445 /* SID list */;
3447 SIVAL(pdata, 0, flags);
3448 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3449 SBIG_UINT(pdata, 8,
3450 (uint64_t)conn->session_info->unix_token->uid);
3451 SBIG_UINT(pdata, 16,
3452 (uint64_t)conn->session_info->unix_token->gid);
3455 if (data_len >= max_data_bytes) {
3456 /* Potential overflow, skip the GIDs and SIDs. */
3458 SIVAL(pdata, 24, 0); /* num_groups */
3459 SIVAL(pdata, 28, 0); /* num_sids */
3460 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3461 SIVAL(pdata, 36, 0); /* reserved */
3463 data_len = 40;
3464 break;
3467 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3468 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3470 /* We walk the SID list twice, but this call is fairly
3471 * infrequent, and I don't expect that it's performance
3472 * sensitive -- jpeach
3474 for (i = 0, sid_bytes = 0;
3475 i < conn->session_info->security_token->num_sids; ++i) {
3476 sid_bytes += ndr_size_dom_sid(
3477 &conn->session_info->security_token->sids[i],
3481 /* SID list byte count */
3482 SIVAL(pdata, 32, sid_bytes);
3484 /* 4 bytes pad/reserved - must be zero */
3485 SIVAL(pdata, 36, 0);
3486 data_len = 40;
3488 /* GID list */
3489 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3490 SBIG_UINT(pdata, data_len,
3491 (uint64_t)conn->session_info->unix_token->groups[i]);
3492 data_len += 8;
3495 /* SID list */
3496 for (i = 0;
3497 i < conn->session_info->security_token->num_sids; ++i) {
3498 int sid_len = ndr_size_dom_sid(
3499 &conn->session_info->security_token->sids[i],
3502 sid_linearize(pdata + data_len, sid_len,
3503 &conn->session_info->security_token->sids[i]);
3504 data_len += sid_len;
3507 break;
3510 case SMB_MAC_QUERY_FS_INFO:
3512 * Thursby MAC extension... ONLY on NTFS filesystems
3513 * once we do streams then we don't need this
3515 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3516 data_len = 88;
3517 SIVAL(pdata,84,0x100); /* Don't support mac... */
3518 break;
3520 /* drop through */
3521 default:
3522 return NT_STATUS_INVALID_LEVEL;
3525 *ret_data_len = data_len;
3526 return NT_STATUS_OK;
3529 /****************************************************************************
3530 Reply to a TRANS2_QFSINFO (query filesystem info).
3531 ****************************************************************************/
3533 static void call_trans2qfsinfo(connection_struct *conn,
3534 struct smb_request *req,
3535 char **pparams, int total_params,
3536 char **ppdata, int total_data,
3537 unsigned int max_data_bytes)
3539 char *params = *pparams;
3540 uint16_t info_level;
3541 int data_len = 0;
3542 NTSTATUS status;
3544 if (total_params < 2) {
3545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546 return;
3549 info_level = SVAL(params,0);
3551 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3552 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3553 DEBUG(0,("call_trans2qfsinfo: encryption required "
3554 "and info level 0x%x sent.\n",
3555 (unsigned int)info_level));
3556 exit_server_cleanly("encryption required "
3557 "on connection");
3558 return;
3562 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3564 status = smbd_do_qfsinfo(conn, req,
3565 info_level,
3566 req->flags2,
3567 max_data_bytes,
3568 ppdata, &data_len);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 reply_nterror(req, status);
3571 return;
3574 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3575 max_data_bytes);
3577 DEBUG( 4, ( "%s info_level = %d\n",
3578 smb_fn_name(req->cmd), info_level) );
3580 return;
3583 /****************************************************************************
3584 Reply to a TRANS2_SETFSINFO (set filesystem info).
3585 ****************************************************************************/
3587 static void call_trans2setfsinfo(connection_struct *conn,
3588 struct smb_request *req,
3589 char **pparams, int total_params,
3590 char **ppdata, int total_data,
3591 unsigned int max_data_bytes)
3593 struct smbd_server_connection *sconn = req->sconn;
3594 char *pdata = *ppdata;
3595 char *params = *pparams;
3596 uint16 info_level;
3598 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3599 lp_servicename(talloc_tos(), SNUM(conn))));
3601 /* */
3602 if (total_params < 4) {
3603 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3604 total_params));
3605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3606 return;
3609 info_level = SVAL(params,2);
3611 if (IS_IPC(conn)) {
3612 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3613 info_level != SMB_SET_CIFS_UNIX_INFO) {
3614 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3615 "info level (0x%x) on IPC$.\n",
3616 (unsigned int)info_level));
3617 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3618 return;
3622 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3623 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3624 DEBUG(0,("call_trans2setfsinfo: encryption required "
3625 "and info level 0x%x sent.\n",
3626 (unsigned int)info_level));
3627 exit_server_cleanly("encryption required "
3628 "on connection");
3629 return;
3633 switch(info_level) {
3634 case SMB_SET_CIFS_UNIX_INFO:
3635 if (!lp_unix_extensions()) {
3636 DEBUG(2,("call_trans2setfsinfo: "
3637 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3638 "unix extensions off\n"));
3639 reply_nterror(req,
3640 NT_STATUS_INVALID_LEVEL);
3641 return;
3644 /* There should be 12 bytes of capabilities set. */
3645 if (total_data < 12) {
3646 reply_nterror(
3647 req,
3648 NT_STATUS_INVALID_PARAMETER);
3649 return;
3651 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3652 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3653 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3654 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3655 /* Just print these values for now. */
3656 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3657 "major = %u, minor = %u cap_low = 0x%x, "
3658 "cap_high = 0x%xn",
3659 (unsigned int)sconn->
3660 smb1.unix_info.client_major,
3661 (unsigned int)sconn->
3662 smb1.unix_info.client_minor,
3663 (unsigned int)sconn->
3664 smb1.unix_info.client_cap_low,
3665 (unsigned int)sconn->
3666 smb1.unix_info.client_cap_high));
3668 /* Here is where we must switch to posix pathname processing... */
3669 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3670 lp_set_posix_pathnames();
3671 mangle_change_to_posix();
3674 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3675 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3676 /* Client that knows how to do posix locks,
3677 * but not posix open/mkdir operations. Set a
3678 * default type for read/write checks. */
3680 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3683 break;
3685 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3687 NTSTATUS status;
3688 size_t param_len = 0;
3689 size_t data_len = total_data;
3691 if (!lp_unix_extensions()) {
3692 reply_nterror(
3693 req,
3694 NT_STATUS_INVALID_LEVEL);
3695 return;
3698 if (lp_smb_encrypt(SNUM(conn)) == false) {
3699 reply_nterror(
3700 req,
3701 NT_STATUS_NOT_SUPPORTED);
3702 return;
3705 if (req->sconn->smb1.echo_handler.trusted_fde) {
3706 DEBUG( 2,("call_trans2setfsinfo: "
3707 "request transport encryption disabled"
3708 "with 'fork echo handler = yes'\n"));
3709 reply_nterror(
3710 req,
3711 NT_STATUS_NOT_SUPPORTED);
3712 return;
3715 DEBUG( 4,("call_trans2setfsinfo: "
3716 "request transport encryption.\n"));
3718 status = srv_request_encryption_setup(conn,
3719 (unsigned char **)ppdata,
3720 &data_len,
3721 (unsigned char **)pparams,
3722 &param_len);
3724 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3725 !NT_STATUS_IS_OK(status)) {
3726 reply_nterror(req, status);
3727 return;
3730 send_trans2_replies(conn, req,
3731 *pparams,
3732 param_len,
3733 *ppdata,
3734 data_len,
3735 max_data_bytes);
3737 if (NT_STATUS_IS_OK(status)) {
3738 /* Server-side transport
3739 * encryption is now *on*. */
3740 status = srv_encryption_start(conn);
3741 if (!NT_STATUS_IS_OK(status)) {
3742 char *reason = talloc_asprintf(talloc_tos(),
3743 "Failure in setting "
3744 "up encrypted transport: %s",
3745 nt_errstr(status));
3746 exit_server_cleanly(reason);
3749 return;
3752 case SMB_FS_QUOTA_INFORMATION:
3754 files_struct *fsp = NULL;
3755 SMB_NTQUOTA_STRUCT quotas;
3757 ZERO_STRUCT(quotas);
3759 /* access check */
3760 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3761 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3762 lp_servicename(talloc_tos(), SNUM(conn)),
3763 conn->session_info->unix_info->unix_name));
3764 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3765 return;
3768 /* note: normaly there're 48 bytes,
3769 * but we didn't use the last 6 bytes for now
3770 * --metze
3772 fsp = file_fsp(req, SVAL(params,0));
3774 if (!check_fsp_ntquota_handle(conn, req,
3775 fsp)) {
3776 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3777 reply_nterror(
3778 req, NT_STATUS_INVALID_HANDLE);
3779 return;
3782 if (total_data < 42) {
3783 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3784 total_data));
3785 reply_nterror(
3786 req,
3787 NT_STATUS_INVALID_PARAMETER);
3788 return;
3791 /* unknown_1 24 NULL bytes in pdata*/
3793 /* the soft quotas 8 bytes (uint64_t)*/
3794 quotas.softlim = BVAL(pdata,24);
3796 /* the hard quotas 8 bytes (uint64_t)*/
3797 quotas.hardlim = BVAL(pdata,32);
3799 /* quota_flags 2 bytes **/
3800 quotas.qflags = SVAL(pdata,40);
3802 /* unknown_2 6 NULL bytes follow*/
3804 /* now set the quotas */
3805 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3806 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3807 reply_nterror(req, map_nt_error_from_unix(errno));
3808 return;
3811 break;
3813 default:
3814 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3815 info_level));
3816 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3817 return;
3818 break;
3822 * sending this reply works fine,
3823 * but I'm not sure it's the same
3824 * like windows do...
3825 * --metze
3827 reply_outbuf(req, 10, 0);
3830 #if defined(HAVE_POSIX_ACLS)
3831 /****************************************************************************
3832 Utility function to count the number of entries in a POSIX acl.
3833 ****************************************************************************/
3835 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3837 unsigned int ace_count = 0;
3838 int entry_id = SMB_ACL_FIRST_ENTRY;
3839 SMB_ACL_ENTRY_T entry;
3841 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3842 /* get_next... */
3843 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3844 entry_id = SMB_ACL_NEXT_ENTRY;
3846 ace_count++;
3848 return ace_count;
3851 /****************************************************************************
3852 Utility function to marshall a POSIX acl into wire format.
3853 ****************************************************************************/
3855 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3857 int entry_id = SMB_ACL_FIRST_ENTRY;
3858 SMB_ACL_ENTRY_T entry;
3860 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3861 SMB_ACL_TAG_T tagtype;
3862 SMB_ACL_PERMSET_T permset;
3863 unsigned char perms = 0;
3864 unsigned int own_grp;
3866 /* get_next... */
3867 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3868 entry_id = SMB_ACL_NEXT_ENTRY;
3871 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3873 return False;
3876 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3877 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3878 return False;
3881 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3882 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3883 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3885 SCVAL(pdata,1,perms);
3887 switch (tagtype) {
3888 case SMB_ACL_USER_OBJ:
3889 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3890 own_grp = (unsigned int)pst->st_ex_uid;
3891 SIVAL(pdata,2,own_grp);
3892 SIVAL(pdata,6,0);
3893 break;
3894 case SMB_ACL_USER:
3896 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3897 if (!puid) {
3898 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3899 return False;
3901 own_grp = (unsigned int)*puid;
3902 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3903 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3904 SIVAL(pdata,2,own_grp);
3905 SIVAL(pdata,6,0);
3906 break;
3908 case SMB_ACL_GROUP_OBJ:
3909 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3910 own_grp = (unsigned int)pst->st_ex_gid;
3911 SIVAL(pdata,2,own_grp);
3912 SIVAL(pdata,6,0);
3913 break;
3914 case SMB_ACL_GROUP:
3916 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3917 if (!pgid) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3919 return False;
3921 own_grp = (unsigned int)*pgid;
3922 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3923 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3924 SIVAL(pdata,2,own_grp);
3925 SIVAL(pdata,6,0);
3926 break;
3928 case SMB_ACL_MASK:
3929 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3930 SIVAL(pdata,2,0xFFFFFFFF);
3931 SIVAL(pdata,6,0xFFFFFFFF);
3932 break;
3933 case SMB_ACL_OTHER:
3934 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3935 SIVAL(pdata,2,0xFFFFFFFF);
3936 SIVAL(pdata,6,0xFFFFFFFF);
3937 break;
3938 default:
3939 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3940 return False;
3942 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3945 return True;
3947 #endif
3949 /****************************************************************************
3950 Store the FILE_UNIX_BASIC info.
3951 ****************************************************************************/
3953 static char *store_file_unix_basic(connection_struct *conn,
3954 char *pdata,
3955 files_struct *fsp,
3956 const SMB_STRUCT_STAT *psbuf)
3958 uint64_t file_index = get_FileIndex(conn, psbuf);
3959 dev_t devno;
3961 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3962 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3964 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3965 pdata += 8;
3967 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3968 pdata += 8;
3970 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3971 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3972 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3973 pdata += 24;
3975 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3976 SIVAL(pdata,4,0);
3977 pdata += 8;
3979 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3980 SIVAL(pdata,4,0);
3981 pdata += 8;
3983 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3984 pdata += 4;
3986 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3987 devno = psbuf->st_ex_rdev;
3988 } else {
3989 devno = psbuf->st_ex_dev;
3992 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
3993 SIVAL(pdata,4,0);
3994 pdata += 8;
3996 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
3997 SIVAL(pdata,4,0);
3998 pdata += 8;
4000 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4001 pdata += 8;
4003 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4004 SIVAL(pdata,4,0);
4005 pdata += 8;
4007 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4008 SIVAL(pdata,4,0);
4009 pdata += 8;
4011 return pdata;
4014 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4015 * the chflags(2) (or equivalent) flags.
4017 * XXX: this really should be behind the VFS interface. To do this, we would
4018 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4019 * Each VFS module could then implement its own mapping as appropriate for the
4020 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4022 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4023 info2_flags_map[] =
4025 #ifdef UF_NODUMP
4026 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4027 #endif
4029 #ifdef UF_IMMUTABLE
4030 { UF_IMMUTABLE, EXT_IMMUTABLE },
4031 #endif
4033 #ifdef UF_APPEND
4034 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4035 #endif
4037 #ifdef UF_HIDDEN
4038 { UF_HIDDEN, EXT_HIDDEN },
4039 #endif
4041 /* Do not remove. We need to guarantee that this array has at least one
4042 * entry to build on HP-UX.
4044 { 0, 0 }
4048 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4049 uint32 *smb_fflags, uint32 *smb_fmask)
4051 int i;
4053 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4054 *smb_fmask |= info2_flags_map[i].smb_fflag;
4055 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4056 *smb_fflags |= info2_flags_map[i].smb_fflag;
4061 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4062 const uint32 smb_fflags,
4063 const uint32 smb_fmask,
4064 int *stat_fflags)
4066 uint32 max_fmask = 0;
4067 int i;
4069 *stat_fflags = psbuf->st_ex_flags;
4071 /* For each flags requested in smb_fmask, check the state of the
4072 * corresponding flag in smb_fflags and set or clear the matching
4073 * stat flag.
4076 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4077 max_fmask |= info2_flags_map[i].smb_fflag;
4078 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4079 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4080 *stat_fflags |= info2_flags_map[i].stat_fflag;
4081 } else {
4082 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4087 /* If smb_fmask is asking to set any bits that are not supported by
4088 * our flag mappings, we should fail.
4090 if ((smb_fmask & max_fmask) != smb_fmask) {
4091 return False;
4094 return True;
4098 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4099 * of file flags and birth (create) time.
4101 static char *store_file_unix_basic_info2(connection_struct *conn,
4102 char *pdata,
4103 files_struct *fsp,
4104 const SMB_STRUCT_STAT *psbuf)
4106 uint32 file_flags = 0;
4107 uint32 flags_mask = 0;
4109 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4111 /* Create (birth) time 64 bit */
4112 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4113 pdata += 8;
4115 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4116 SIVAL(pdata, 0, file_flags); /* flags */
4117 SIVAL(pdata, 4, flags_mask); /* mask */
4118 pdata += 8;
4120 return pdata;
4123 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4124 const struct stream_struct *streams,
4125 char *data,
4126 unsigned int max_data_bytes,
4127 unsigned int *data_size)
4129 unsigned int i;
4130 unsigned int ofs = 0;
4132 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4133 unsigned int next_offset;
4134 size_t namelen;
4135 smb_ucs2_t *namebuf;
4137 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4138 streams[i].name, &namelen) ||
4139 namelen <= 2)
4141 return NT_STATUS_INVALID_PARAMETER;
4145 * name_buf is now null-terminated, we need to marshall as not
4146 * terminated
4149 namelen -= 2;
4151 SIVAL(data, ofs+4, namelen);
4152 SOFF_T(data, ofs+8, streams[i].size);
4153 SOFF_T(data, ofs+16, streams[i].alloc_size);
4154 memcpy(data+ofs+24, namebuf, namelen);
4155 TALLOC_FREE(namebuf);
4157 next_offset = ofs + 24 + namelen;
4159 if (i == num_streams-1) {
4160 SIVAL(data, ofs, 0);
4162 else {
4163 unsigned int align = ndr_align_size(next_offset, 8);
4165 memset(data+next_offset, 0, align);
4166 next_offset += align;
4168 SIVAL(data, ofs, next_offset - ofs);
4169 ofs = next_offset;
4172 ofs = next_offset;
4175 *data_size = ofs;
4177 return NT_STATUS_OK;
4180 /****************************************************************************
4181 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4182 ****************************************************************************/
4184 static void call_trans2qpipeinfo(connection_struct *conn,
4185 struct smb_request *req,
4186 unsigned int tran_call,
4187 char **pparams, int total_params,
4188 char **ppdata, int total_data,
4189 unsigned int max_data_bytes)
4191 char *params = *pparams;
4192 char *pdata = *ppdata;
4193 unsigned int data_size = 0;
4194 unsigned int param_size = 2;
4195 uint16 info_level;
4196 files_struct *fsp;
4198 if (!params) {
4199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4200 return;
4203 if (total_params < 4) {
4204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4205 return;
4208 fsp = file_fsp(req, SVAL(params,0));
4209 if (!fsp_is_np(fsp)) {
4210 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4211 return;
4214 info_level = SVAL(params,2);
4216 *pparams = (char *)SMB_REALLOC(*pparams,2);
4217 if (*pparams == NULL) {
4218 reply_nterror(req, NT_STATUS_NO_MEMORY);
4219 return;
4221 params = *pparams;
4222 SSVAL(params,0,0);
4223 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4224 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4225 if (*ppdata == NULL ) {
4226 reply_nterror(req, NT_STATUS_NO_MEMORY);
4227 return;
4229 pdata = *ppdata;
4231 switch (info_level) {
4232 case SMB_FILE_STANDARD_INFORMATION:
4233 memset(pdata,0,24);
4234 SOFF_T(pdata,0,4096LL);
4235 SIVAL(pdata,16,1);
4236 SIVAL(pdata,20,1);
4237 data_size = 24;
4238 break;
4240 default:
4241 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4242 return;
4245 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4246 max_data_bytes);
4248 return;
4251 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4252 TALLOC_CTX *mem_ctx,
4253 uint16_t info_level,
4254 files_struct *fsp,
4255 struct smb_filename *smb_fname,
4256 bool delete_pending,
4257 struct timespec write_time_ts,
4258 struct ea_list *ea_list,
4259 int lock_data_count,
4260 char *lock_data,
4261 uint16_t flags2,
4262 unsigned int max_data_bytes,
4263 char **ppdata,
4264 unsigned int *pdata_size)
4266 char *pdata = *ppdata;
4267 char *dstart, *dend;
4268 unsigned int data_size;
4269 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4270 time_t create_time, mtime, atime, c_time;
4271 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4272 char *p;
4273 char *base_name;
4274 char *dos_fname;
4275 int mode;
4276 int nlink;
4277 NTSTATUS status;
4278 uint64_t file_size = 0;
4279 uint64_t pos = 0;
4280 uint64_t allocation_size = 0;
4281 uint64_t file_index = 0;
4282 uint32_t access_mask = 0;
4284 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4285 return NT_STATUS_INVALID_LEVEL;
4288 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4289 smb_fname_str_dbg(smb_fname),
4290 fsp_fnum_dbg(fsp),
4291 info_level, max_data_bytes));
4293 mode = dos_mode(conn, smb_fname);
4294 nlink = psbuf->st_ex_nlink;
4296 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4297 nlink = 1;
4300 if ((nlink > 0) && delete_pending) {
4301 nlink -= 1;
4304 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4305 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4306 if (*ppdata == NULL) {
4307 return NT_STATUS_NO_MEMORY;
4309 pdata = *ppdata;
4310 dstart = pdata;
4311 dend = dstart + data_size - 1;
4313 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4314 update_stat_ex_mtime(psbuf, write_time_ts);
4317 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4318 mtime_ts = psbuf->st_ex_mtime;
4319 atime_ts = psbuf->st_ex_atime;
4320 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4322 if (lp_dos_filetime_resolution(SNUM(conn))) {
4323 dos_filetime_timespec(&create_time_ts);
4324 dos_filetime_timespec(&mtime_ts);
4325 dos_filetime_timespec(&atime_ts);
4326 dos_filetime_timespec(&ctime_ts);
4329 create_time = convert_timespec_to_time_t(create_time_ts);
4330 mtime = convert_timespec_to_time_t(mtime_ts);
4331 atime = convert_timespec_to_time_t(atime_ts);
4332 c_time = convert_timespec_to_time_t(ctime_ts);
4334 p = strrchr_m(smb_fname->base_name,'/');
4335 if (!p)
4336 base_name = smb_fname->base_name;
4337 else
4338 base_name = p+1;
4340 /* NT expects the name to be in an exact form of the *full*
4341 filename. See the trans2 torture test */
4342 if (ISDOT(base_name)) {
4343 dos_fname = talloc_strdup(mem_ctx, "\\");
4344 if (!dos_fname) {
4345 return NT_STATUS_NO_MEMORY;
4347 } else {
4348 dos_fname = talloc_asprintf(mem_ctx,
4349 "\\%s",
4350 smb_fname->base_name);
4351 if (!dos_fname) {
4352 return NT_STATUS_NO_MEMORY;
4354 if (is_ntfs_stream_smb_fname(smb_fname)) {
4355 dos_fname = talloc_asprintf(dos_fname, "%s",
4356 smb_fname->stream_name);
4357 if (!dos_fname) {
4358 return NT_STATUS_NO_MEMORY;
4362 string_replace(dos_fname, '/', '\\');
4365 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4367 if (!fsp) {
4368 /* Do we have this path open ? */
4369 files_struct *fsp1;
4370 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4371 fsp1 = file_find_di_first(conn->sconn, fileid);
4372 if (fsp1 && fsp1->initial_allocation_size) {
4373 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4377 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4378 file_size = get_file_size_stat(psbuf);
4381 if (fsp) {
4382 pos = fsp->fh->position_information;
4385 if (fsp) {
4386 access_mask = fsp->access_mask;
4387 } else {
4388 /* GENERIC_EXECUTE mapping from Windows */
4389 access_mask = 0x12019F;
4392 /* This should be an index number - looks like
4393 dev/ino to me :-)
4395 I think this causes us to fail the IFSKIT
4396 BasicFileInformationTest. -tpot */
4397 file_index = get_FileIndex(conn, psbuf);
4399 switch (info_level) {
4400 case SMB_INFO_STANDARD:
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4402 data_size = 22;
4403 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4404 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4405 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4406 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4407 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4408 SSVAL(pdata,l1_attrFile,mode);
4409 break;
4411 case SMB_INFO_QUERY_EA_SIZE:
4413 unsigned int ea_size =
4414 estimate_ea_size(conn, fsp,
4415 smb_fname->base_name);
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4417 data_size = 26;
4418 srv_put_dos_date2(pdata,0,create_time);
4419 srv_put_dos_date2(pdata,4,atime);
4420 srv_put_dos_date2(pdata,8,mtime); /* write time */
4421 SIVAL(pdata,12,(uint32)file_size);
4422 SIVAL(pdata,16,(uint32)allocation_size);
4423 SSVAL(pdata,20,mode);
4424 SIVAL(pdata,22,ea_size);
4425 break;
4428 case SMB_INFO_IS_NAME_VALID:
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4430 if (fsp) {
4431 /* os/2 needs this ? really ?*/
4432 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4434 /* This is only reached for qpathinfo */
4435 data_size = 0;
4436 break;
4438 case SMB_INFO_QUERY_EAS_FROM_LIST:
4440 size_t total_ea_len = 0;
4441 struct ea_list *ea_file_list = NULL;
4443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4445 ea_file_list =
4446 get_ea_list_from_file(mem_ctx, conn, fsp,
4447 smb_fname->base_name,
4448 &total_ea_len);
4449 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4451 if (!ea_list || (total_ea_len > data_size)) {
4452 data_size = 4;
4453 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4454 break;
4457 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4458 break;
4461 case SMB_INFO_QUERY_ALL_EAS:
4463 /* We have data_size bytes to put EA's into. */
4464 size_t total_ea_len = 0;
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4468 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4469 smb_fname->base_name,
4470 &total_ea_len);
4471 if (!ea_list || (total_ea_len > data_size)) {
4472 data_size = 4;
4473 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4474 break;
4477 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4478 break;
4481 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4483 /* This is FileFullEaInformation - 0xF which maps to
4484 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4486 /* We have data_size bytes to put EA's into. */
4487 size_t total_ea_len = 0;
4488 struct ea_list *ea_file_list = NULL;
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4492 /*TODO: add filtering and index handling */
4494 ea_file_list =
4495 get_ea_list_from_file(mem_ctx, conn, fsp,
4496 smb_fname->base_name,
4497 &total_ea_len);
4498 if (!ea_file_list) {
4499 return NT_STATUS_NO_EAS_ON_FILE;
4502 status = fill_ea_chained_buffer(mem_ctx,
4503 pdata,
4504 data_size,
4505 &data_size,
4506 conn, ea_file_list);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 return status;
4510 break;
4513 case SMB_FILE_BASIC_INFORMATION:
4514 case SMB_QUERY_FILE_BASIC_INFO:
4516 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4518 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4519 } else {
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4521 data_size = 40;
4522 SIVAL(pdata,36,0);
4524 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4525 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4526 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4527 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4528 SIVAL(pdata,32,mode);
4530 DEBUG(5,("SMB_QFBI - "));
4531 DEBUG(5,("create: %s ", ctime(&create_time)));
4532 DEBUG(5,("access: %s ", ctime(&atime)));
4533 DEBUG(5,("write: %s ", ctime(&mtime)));
4534 DEBUG(5,("change: %s ", ctime(&c_time)));
4535 DEBUG(5,("mode: %x\n", mode));
4536 break;
4538 case SMB_FILE_STANDARD_INFORMATION:
4539 case SMB_QUERY_FILE_STANDARD_INFO:
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4542 data_size = 24;
4543 SOFF_T(pdata,0,allocation_size);
4544 SOFF_T(pdata,8,file_size);
4545 SIVAL(pdata,16,nlink);
4546 SCVAL(pdata,20,delete_pending?1:0);
4547 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4548 SSVAL(pdata,22,0); /* Padding. */
4549 break;
4551 case SMB_FILE_EA_INFORMATION:
4552 case SMB_QUERY_FILE_EA_INFO:
4554 unsigned int ea_size =
4555 estimate_ea_size(conn, fsp, smb_fname->base_name);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4557 data_size = 4;
4558 SIVAL(pdata,0,ea_size);
4559 break;
4562 /* Get the 8.3 name - used if NT SMB was negotiated. */
4563 case SMB_QUERY_FILE_ALT_NAME_INFO:
4564 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4566 int len;
4567 char mangled_name[13];
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4569 if (!name_to_8_3(base_name,mangled_name,
4570 True,conn->params)) {
4571 return NT_STATUS_NO_MEMORY;
4573 len = srvstr_push(dstart, flags2,
4574 pdata+4, mangled_name,
4575 PTR_DIFF(dend, pdata+4),
4576 STR_UNICODE);
4577 data_size = 4 + len;
4578 SIVAL(pdata,0,len);
4579 break;
4582 case SMB_QUERY_FILE_NAME_INFO:
4584 int len;
4586 this must be *exactly* right for ACLs on mapped drives to work
4588 len = srvstr_push(dstart, flags2,
4589 pdata+4, dos_fname,
4590 PTR_DIFF(dend, pdata+4),
4591 STR_UNICODE);
4592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4593 data_size = 4 + len;
4594 SIVAL(pdata,0,len);
4595 break;
4598 case SMB_FILE_ALLOCATION_INFORMATION:
4599 case SMB_QUERY_FILE_ALLOCATION_INFO:
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4601 data_size = 8;
4602 SOFF_T(pdata,0,allocation_size);
4603 break;
4605 case SMB_FILE_END_OF_FILE_INFORMATION:
4606 case SMB_QUERY_FILE_END_OF_FILEINFO:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4608 data_size = 8;
4609 SOFF_T(pdata,0,file_size);
4610 break;
4612 case SMB_QUERY_FILE_ALL_INFO:
4613 case SMB_FILE_ALL_INFORMATION:
4615 int len;
4616 unsigned int ea_size =
4617 estimate_ea_size(conn, fsp, smb_fname->base_name);
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4619 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4620 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4621 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4622 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4623 SIVAL(pdata,32,mode);
4624 SIVAL(pdata,36,0); /* padding. */
4625 pdata += 40;
4626 SOFF_T(pdata,0,allocation_size);
4627 SOFF_T(pdata,8,file_size);
4628 SIVAL(pdata,16,nlink);
4629 SCVAL(pdata,20,delete_pending);
4630 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4631 SSVAL(pdata,22,0);
4632 pdata += 24;
4633 SIVAL(pdata,0,ea_size);
4634 pdata += 4; /* EA info */
4635 len = srvstr_push(dstart, flags2,
4636 pdata+4, dos_fname,
4637 PTR_DIFF(dend, pdata+4),
4638 STR_UNICODE);
4639 SIVAL(pdata,0,len);
4640 pdata += 4 + len;
4641 data_size = PTR_DIFF(pdata,(*ppdata));
4642 break;
4645 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4647 int len;
4648 unsigned int ea_size =
4649 estimate_ea_size(conn, fsp, smb_fname->base_name);
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4651 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4652 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4653 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4654 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4655 SIVAL(pdata, 0x20, mode);
4656 SIVAL(pdata, 0x24, 0); /* padding. */
4657 SBVAL(pdata, 0x28, allocation_size);
4658 SBVAL(pdata, 0x30, file_size);
4659 SIVAL(pdata, 0x38, nlink);
4660 SCVAL(pdata, 0x3C, delete_pending);
4661 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4662 SSVAL(pdata, 0x3E, 0); /* padding */
4663 SBVAL(pdata, 0x40, file_index);
4664 SIVAL(pdata, 0x48, ea_size);
4665 SIVAL(pdata, 0x4C, access_mask);
4666 SBVAL(pdata, 0x50, pos);
4667 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4668 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4670 pdata += 0x60;
4672 len = srvstr_push(dstart, flags2,
4673 pdata+4, dos_fname,
4674 PTR_DIFF(dend, pdata+4),
4675 STR_UNICODE);
4676 SIVAL(pdata,0,len);
4677 pdata += 4 + len;
4678 data_size = PTR_DIFF(pdata,(*ppdata));
4679 break;
4681 case SMB_FILE_INTERNAL_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4684 SBVAL(pdata, 0, file_index);
4685 data_size = 8;
4686 break;
4688 case SMB_FILE_ACCESS_INFORMATION:
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4690 SIVAL(pdata, 0, access_mask);
4691 data_size = 4;
4692 break;
4694 case SMB_FILE_NAME_INFORMATION:
4695 /* Pathname with leading '\'. */
4697 size_t byte_len;
4698 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4700 SIVAL(pdata,0,byte_len);
4701 data_size = 4 + byte_len;
4702 break;
4705 case SMB_FILE_DISPOSITION_INFORMATION:
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4707 data_size = 1;
4708 SCVAL(pdata,0,delete_pending);
4709 break;
4711 case SMB_FILE_POSITION_INFORMATION:
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4713 data_size = 8;
4714 SOFF_T(pdata,0,pos);
4715 break;
4717 case SMB_FILE_MODE_INFORMATION:
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4719 SIVAL(pdata,0,mode);
4720 data_size = 4;
4721 break;
4723 case SMB_FILE_ALIGNMENT_INFORMATION:
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4725 SIVAL(pdata,0,0); /* No alignment needed. */
4726 data_size = 4;
4727 break;
4730 * NT4 server just returns "invalid query" to this - if we try
4731 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4732 * want this. JRA.
4734 /* The first statement above is false - verified using Thursby
4735 * client against NT4 -- gcolley.
4737 case SMB_QUERY_FILE_STREAM_INFO:
4738 case SMB_FILE_STREAM_INFORMATION: {
4739 unsigned int num_streams = 0;
4740 struct stream_struct *streams = NULL;
4742 DEBUG(10,("smbd_do_qfilepathinfo: "
4743 "SMB_FILE_STREAM_INFORMATION\n"));
4745 if (is_ntfs_stream_smb_fname(smb_fname)) {
4746 return NT_STATUS_INVALID_PARAMETER;
4749 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4750 talloc_tos(), &num_streams, &streams);
4752 if (!NT_STATUS_IS_OK(status)) {
4753 DEBUG(10, ("could not get stream info: %s\n",
4754 nt_errstr(status)));
4755 return status;
4758 status = marshall_stream_info(num_streams, streams,
4759 pdata, max_data_bytes,
4760 &data_size);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 DEBUG(10, ("marshall_stream_info failed: %s\n",
4764 nt_errstr(status)));
4765 return status;
4768 TALLOC_FREE(streams);
4770 break;
4772 case SMB_QUERY_COMPRESSION_INFO:
4773 case SMB_FILE_COMPRESSION_INFORMATION:
4774 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4775 SOFF_T(pdata,0,file_size);
4776 SIVAL(pdata,8,0); /* ??? */
4777 SIVAL(pdata,12,0); /* ??? */
4778 data_size = 16;
4779 break;
4781 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4782 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4783 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4784 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4785 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4786 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4787 SOFF_T(pdata,32,allocation_size);
4788 SOFF_T(pdata,40,file_size);
4789 SIVAL(pdata,48,mode);
4790 SIVAL(pdata,52,0); /* ??? */
4791 data_size = 56;
4792 break;
4794 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4795 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4796 SIVAL(pdata,0,mode);
4797 SIVAL(pdata,4,0);
4798 data_size = 8;
4799 break;
4802 * CIFS UNIX Extensions.
4805 case SMB_QUERY_FILE_UNIX_BASIC:
4807 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4808 data_size = PTR_DIFF(pdata,(*ppdata));
4810 DEBUG(4,("smbd_do_qfilepathinfo: "
4811 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4812 dump_data(4, (uint8_t *)(*ppdata), data_size);
4814 break;
4816 case SMB_QUERY_FILE_UNIX_INFO2:
4818 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4819 data_size = PTR_DIFF(pdata,(*ppdata));
4822 int i;
4823 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4825 for (i=0; i<100; i++)
4826 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4827 DEBUG(4,("\n"));
4830 break;
4832 case SMB_QUERY_FILE_UNIX_LINK:
4834 int len;
4835 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4837 if (!buffer) {
4838 return NT_STATUS_NO_MEMORY;
4841 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4842 #ifdef S_ISLNK
4843 if(!S_ISLNK(psbuf->st_ex_mode)) {
4844 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4846 #else
4847 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4848 #endif
4849 len = SMB_VFS_READLINK(conn,
4850 smb_fname->base_name,
4851 buffer, PATH_MAX);
4852 if (len == -1) {
4853 return map_nt_error_from_unix(errno);
4855 buffer[len] = 0;
4856 len = srvstr_push(dstart, flags2,
4857 pdata, buffer,
4858 PTR_DIFF(dend, pdata),
4859 STR_TERMINATE);
4860 pdata += len;
4861 data_size = PTR_DIFF(pdata,(*ppdata));
4863 break;
4866 #if defined(HAVE_POSIX_ACLS)
4867 case SMB_QUERY_POSIX_ACL:
4869 SMB_ACL_T file_acl = NULL;
4870 SMB_ACL_T def_acl = NULL;
4871 uint16 num_file_acls = 0;
4872 uint16 num_def_acls = 0;
4874 if (fsp && fsp->fh->fd != -1) {
4875 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4876 } else {
4877 file_acl =
4878 SMB_VFS_SYS_ACL_GET_FILE(conn,
4879 smb_fname->base_name,
4880 SMB_ACL_TYPE_ACCESS);
4883 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4884 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4885 "not implemented on "
4886 "filesystem containing %s\n",
4887 smb_fname->base_name));
4888 return NT_STATUS_NOT_IMPLEMENTED;
4891 if (S_ISDIR(psbuf->st_ex_mode)) {
4892 if (fsp && fsp->is_directory) {
4893 def_acl =
4894 SMB_VFS_SYS_ACL_GET_FILE(
4895 conn,
4896 fsp->fsp_name->base_name,
4897 SMB_ACL_TYPE_DEFAULT);
4898 } else {
4899 def_acl =
4900 SMB_VFS_SYS_ACL_GET_FILE(
4901 conn,
4902 smb_fname->base_name,
4903 SMB_ACL_TYPE_DEFAULT);
4905 def_acl = free_empty_sys_acl(conn, def_acl);
4908 num_file_acls = count_acl_entries(conn, file_acl);
4909 num_def_acls = count_acl_entries(conn, def_acl);
4911 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4912 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4913 data_size,
4914 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4915 SMB_POSIX_ACL_HEADER_SIZE) ));
4916 if (file_acl) {
4917 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4919 if (def_acl) {
4920 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4922 return NT_STATUS_BUFFER_TOO_SMALL;
4925 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4926 SSVAL(pdata,2,num_file_acls);
4927 SSVAL(pdata,4,num_def_acls);
4928 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4929 if (file_acl) {
4930 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4932 if (def_acl) {
4933 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4935 return NT_STATUS_INTERNAL_ERROR;
4937 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4938 if (file_acl) {
4939 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4941 if (def_acl) {
4942 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4944 return NT_STATUS_INTERNAL_ERROR;
4947 if (file_acl) {
4948 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4950 if (def_acl) {
4951 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4953 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4954 break;
4956 #endif
4959 case SMB_QUERY_POSIX_LOCK:
4961 uint64_t count;
4962 uint64_t offset;
4963 uint64_t smblctx;
4964 enum brl_type lock_type;
4966 /* We need an open file with a real fd for this. */
4967 if (!fsp || fsp->fh->fd == -1) {
4968 return NT_STATUS_INVALID_LEVEL;
4971 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4972 return NT_STATUS_INVALID_PARAMETER;
4975 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4976 case POSIX_LOCK_TYPE_READ:
4977 lock_type = READ_LOCK;
4978 break;
4979 case POSIX_LOCK_TYPE_WRITE:
4980 lock_type = WRITE_LOCK;
4981 break;
4982 case POSIX_LOCK_TYPE_UNLOCK:
4983 default:
4984 /* There's no point in asking for an unlock... */
4985 return NT_STATUS_INVALID_PARAMETER;
4988 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4989 #if defined(HAVE_LONGLONG)
4990 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4991 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4992 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4993 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4994 #else /* HAVE_LONGLONG */
4995 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4996 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4997 #endif /* HAVE_LONGLONG */
4999 status = query_lock(fsp,
5000 &smblctx,
5001 &count,
5002 &offset,
5003 &lock_type,
5004 POSIX_LOCK);
5006 if (ERROR_WAS_LOCK_DENIED(status)) {
5007 /* Here we need to report who has it locked... */
5008 data_size = POSIX_LOCK_DATA_SIZE;
5010 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5011 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5012 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5013 #if defined(HAVE_LONGLONG)
5014 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5015 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5016 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5017 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5018 #else /* HAVE_LONGLONG */
5019 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5020 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5021 #endif /* HAVE_LONGLONG */
5023 } else if (NT_STATUS_IS_OK(status)) {
5024 /* For success we just return a copy of what we sent
5025 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5026 data_size = POSIX_LOCK_DATA_SIZE;
5027 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5028 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5029 } else {
5030 return status;
5032 break;
5035 default:
5036 return NT_STATUS_INVALID_LEVEL;
5039 *pdata_size = data_size;
5040 return NT_STATUS_OK;
5043 /****************************************************************************
5044 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5045 file name or file id).
5046 ****************************************************************************/
5048 static void call_trans2qfilepathinfo(connection_struct *conn,
5049 struct smb_request *req,
5050 unsigned int tran_call,
5051 char **pparams, int total_params,
5052 char **ppdata, int total_data,
5053 unsigned int max_data_bytes)
5055 char *params = *pparams;
5056 char *pdata = *ppdata;
5057 uint16 info_level;
5058 unsigned int data_size = 0;
5059 unsigned int param_size = 2;
5060 struct smb_filename *smb_fname = NULL;
5061 bool delete_pending = False;
5062 struct timespec write_time_ts;
5063 files_struct *fsp = NULL;
5064 struct file_id fileid;
5065 struct ea_list *ea_list = NULL;
5066 int lock_data_count = 0;
5067 char *lock_data = NULL;
5068 NTSTATUS status = NT_STATUS_OK;
5070 if (!params) {
5071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5072 return;
5075 ZERO_STRUCT(write_time_ts);
5077 if (tran_call == TRANSACT2_QFILEINFO) {
5078 if (total_params < 4) {
5079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5080 return;
5083 if (IS_IPC(conn)) {
5084 call_trans2qpipeinfo(conn, req, tran_call,
5085 pparams, total_params,
5086 ppdata, total_data,
5087 max_data_bytes);
5088 return;
5091 fsp = file_fsp(req, SVAL(params,0));
5092 info_level = SVAL(params,2);
5094 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5096 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5097 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5098 return;
5101 /* Initial check for valid fsp ptr. */
5102 if (!check_fsp_open(conn, req, fsp)) {
5103 return;
5106 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5107 &smb_fname);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 reply_nterror(req, status);
5110 return;
5113 if(fsp->fake_file_handle) {
5115 * This is actually for the QUOTA_FAKE_FILE --metze
5118 /* We know this name is ok, it's already passed the checks. */
5120 } else if(fsp->fh->fd == -1) {
5122 * This is actually a QFILEINFO on a directory
5123 * handle (returned from an NT SMB). NT5.0 seems
5124 * to do this call. JRA.
5127 if (INFO_LEVEL_IS_UNIX(info_level)) {
5128 /* Always do lstat for UNIX calls. */
5129 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5130 DEBUG(3,("call_trans2qfilepathinfo: "
5131 "SMB_VFS_LSTAT of %s failed "
5132 "(%s)\n",
5133 smb_fname_str_dbg(smb_fname),
5134 strerror(errno)));
5135 reply_nterror(req,
5136 map_nt_error_from_unix(errno));
5137 return;
5139 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5140 DEBUG(3,("call_trans2qfilepathinfo: "
5141 "SMB_VFS_STAT of %s failed (%s)\n",
5142 smb_fname_str_dbg(smb_fname),
5143 strerror(errno)));
5144 reply_nterror(req,
5145 map_nt_error_from_unix(errno));
5146 return;
5149 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5150 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5151 } else {
5153 * Original code - this is an open file.
5155 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5156 DEBUG(3, ("fstat of %s failed (%s)\n",
5157 fsp_fnum_dbg(fsp), strerror(errno)));
5158 reply_nterror(req,
5159 map_nt_error_from_unix(errno));
5160 return;
5162 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5163 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5166 } else {
5167 uint32_t name_hash;
5168 char *fname = NULL;
5169 uint32_t ucf_flags = 0;
5171 /* qpathinfo */
5172 if (total_params < 7) {
5173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5174 return;
5177 info_level = SVAL(params,0);
5179 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5181 if (INFO_LEVEL_IS_UNIX(info_level)) {
5182 if (!lp_unix_extensions()) {
5183 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5184 return;
5186 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5187 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5188 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5189 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5193 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5194 total_params - 6,
5195 STR_TERMINATE, &status);
5196 if (!NT_STATUS_IS_OK(status)) {
5197 reply_nterror(req, status);
5198 return;
5201 status = filename_convert(req,
5202 conn,
5203 req->flags2 & FLAGS2_DFS_PATHNAMES,
5204 fname,
5205 ucf_flags,
5206 NULL,
5207 &smb_fname);
5208 if (!NT_STATUS_IS_OK(status)) {
5209 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5210 reply_botherror(req,
5211 NT_STATUS_PATH_NOT_COVERED,
5212 ERRSRV, ERRbadpath);
5213 return;
5215 reply_nterror(req, status);
5216 return;
5219 /* If this is a stream, check if there is a delete_pending. */
5220 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5221 && is_ntfs_stream_smb_fname(smb_fname)) {
5222 struct smb_filename *smb_fname_base = NULL;
5224 /* Create an smb_filename with stream_name == NULL. */
5225 status =
5226 create_synthetic_smb_fname(talloc_tos(),
5227 smb_fname->base_name,
5228 NULL, NULL,
5229 &smb_fname_base);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 reply_nterror(req, status);
5232 return;
5235 if (INFO_LEVEL_IS_UNIX(info_level)) {
5236 /* Always do lstat for UNIX calls. */
5237 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5238 DEBUG(3,("call_trans2qfilepathinfo: "
5239 "SMB_VFS_LSTAT of %s failed "
5240 "(%s)\n",
5241 smb_fname_str_dbg(smb_fname_base),
5242 strerror(errno)));
5243 TALLOC_FREE(smb_fname_base);
5244 reply_nterror(req,
5245 map_nt_error_from_unix(errno));
5246 return;
5248 } else {
5249 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5250 DEBUG(3,("call_trans2qfilepathinfo: "
5251 "fileinfo of %s failed "
5252 "(%s)\n",
5253 smb_fname_str_dbg(smb_fname_base),
5254 strerror(errno)));
5255 TALLOC_FREE(smb_fname_base);
5256 reply_nterror(req,
5257 map_nt_error_from_unix(errno));
5258 return;
5262 status = file_name_hash(conn,
5263 smb_fname_str_dbg(smb_fname_base),
5264 &name_hash);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 TALLOC_FREE(smb_fname_base);
5267 reply_nterror(req, status);
5268 return;
5271 fileid = vfs_file_id_from_sbuf(conn,
5272 &smb_fname_base->st);
5273 TALLOC_FREE(smb_fname_base);
5274 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5275 if (delete_pending) {
5276 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5277 return;
5281 if (INFO_LEVEL_IS_UNIX(info_level)) {
5282 /* Always do lstat for UNIX calls. */
5283 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5284 DEBUG(3,("call_trans2qfilepathinfo: "
5285 "SMB_VFS_LSTAT of %s failed (%s)\n",
5286 smb_fname_str_dbg(smb_fname),
5287 strerror(errno)));
5288 reply_nterror(req,
5289 map_nt_error_from_unix(errno));
5290 return;
5293 } else {
5294 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5295 DEBUG(3,("call_trans2qfilepathinfo: "
5296 "SMB_VFS_STAT of %s failed (%s)\n",
5297 smb_fname_str_dbg(smb_fname),
5298 strerror(errno)));
5299 reply_nterror(req,
5300 map_nt_error_from_unix(errno));
5301 return;
5305 status = file_name_hash(conn,
5306 smb_fname_str_dbg(smb_fname),
5307 &name_hash);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 reply_nterror(req, status);
5310 return;
5313 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5314 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5315 if (delete_pending) {
5316 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5317 return;
5321 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5322 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5323 fsp_fnum_dbg(fsp),
5324 info_level,tran_call,total_data));
5326 /* Pull out any data sent here before we realloc. */
5327 switch (info_level) {
5328 case SMB_INFO_QUERY_EAS_FROM_LIST:
5330 /* Pull any EA list from the data portion. */
5331 uint32 ea_size;
5333 if (total_data < 4) {
5334 reply_nterror(
5335 req, NT_STATUS_INVALID_PARAMETER);
5336 return;
5338 ea_size = IVAL(pdata,0);
5340 if (total_data > 0 && ea_size != total_data) {
5341 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5342 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5343 reply_nterror(
5344 req, NT_STATUS_INVALID_PARAMETER);
5345 return;
5348 if (!lp_ea_support(SNUM(conn))) {
5349 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5350 return;
5353 /* Pull out the list of names. */
5354 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5355 if (!ea_list) {
5356 reply_nterror(
5357 req, NT_STATUS_INVALID_PARAMETER);
5358 return;
5360 break;
5363 case SMB_QUERY_POSIX_LOCK:
5365 if (fsp == NULL || fsp->fh->fd == -1) {
5366 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5367 return;
5370 if (total_data != POSIX_LOCK_DATA_SIZE) {
5371 reply_nterror(
5372 req, NT_STATUS_INVALID_PARAMETER);
5373 return;
5376 /* Copy the lock range data. */
5377 lock_data = (char *)talloc_memdup(
5378 req, pdata, total_data);
5379 if (!lock_data) {
5380 reply_nterror(req, NT_STATUS_NO_MEMORY);
5381 return;
5383 lock_data_count = total_data;
5385 default:
5386 break;
5389 *pparams = (char *)SMB_REALLOC(*pparams,2);
5390 if (*pparams == NULL) {
5391 reply_nterror(req, NT_STATUS_NO_MEMORY);
5392 return;
5394 params = *pparams;
5395 SSVAL(params,0,0);
5398 * draft-leach-cifs-v1-spec-02.txt
5399 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5400 * says:
5402 * The requested information is placed in the Data portion of the
5403 * transaction response. For the information levels greater than 0x100,
5404 * the transaction response has 1 parameter word which should be
5405 * ignored by the client.
5407 * However Windows only follows this rule for the IS_NAME_VALID call.
5409 switch (info_level) {
5410 case SMB_INFO_IS_NAME_VALID:
5411 param_size = 0;
5412 break;
5415 if ((info_level & 0xFF00) == 0xFF00) {
5417 * We use levels that start with 0xFF00
5418 * internally to represent SMB2 specific levels
5420 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5421 return;
5424 status = smbd_do_qfilepathinfo(conn, req, info_level,
5425 fsp, smb_fname,
5426 delete_pending, write_time_ts,
5427 ea_list,
5428 lock_data_count, lock_data,
5429 req->flags2, max_data_bytes,
5430 ppdata, &data_size);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 reply_nterror(req, status);
5433 return;
5436 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5437 max_data_bytes);
5439 return;
5442 /****************************************************************************
5443 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5444 code.
5445 ****************************************************************************/
5447 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5448 connection_struct *conn,
5449 struct smb_request *req,
5450 bool overwrite_if_exists,
5451 const struct smb_filename *smb_fname_old,
5452 struct smb_filename *smb_fname_new)
5454 NTSTATUS status = NT_STATUS_OK;
5456 /* source must already exist. */
5457 if (!VALID_STAT(smb_fname_old->st)) {
5458 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5461 if (VALID_STAT(smb_fname_new->st)) {
5462 if (overwrite_if_exists) {
5463 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5464 return NT_STATUS_FILE_IS_A_DIRECTORY;
5466 status = unlink_internals(conn,
5467 req,
5468 FILE_ATTRIBUTE_NORMAL,
5469 smb_fname_new,
5470 false);
5471 if (!NT_STATUS_IS_OK(status)) {
5472 return status;
5474 } else {
5475 /* Disallow if newname already exists. */
5476 return NT_STATUS_OBJECT_NAME_COLLISION;
5480 /* No links from a directory. */
5481 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5482 return NT_STATUS_FILE_IS_A_DIRECTORY;
5485 /* Setting a hardlink to/from a stream isn't currently supported. */
5486 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5487 is_ntfs_stream_smb_fname(smb_fname_new)) {
5488 return NT_STATUS_INVALID_PARAMETER;
5491 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5492 smb_fname_old->base_name, smb_fname_new->base_name));
5494 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5495 smb_fname_new->base_name) != 0) {
5496 status = map_nt_error_from_unix(errno);
5497 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5498 nt_errstr(status), smb_fname_old->base_name,
5499 smb_fname_new->base_name));
5501 return status;
5504 /****************************************************************************
5505 Deal with setting the time from any of the setfilepathinfo functions.
5506 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5507 calling this function.
5508 ****************************************************************************/
5510 NTSTATUS smb_set_file_time(connection_struct *conn,
5511 files_struct *fsp,
5512 const struct smb_filename *smb_fname,
5513 struct smb_file_time *ft,
5514 bool setting_write_time)
5516 struct smb_filename smb_fname_base;
5517 uint32 action =
5518 FILE_NOTIFY_CHANGE_LAST_ACCESS
5519 |FILE_NOTIFY_CHANGE_LAST_WRITE
5520 |FILE_NOTIFY_CHANGE_CREATION;
5522 if (!VALID_STAT(smb_fname->st)) {
5523 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5526 /* get some defaults (no modifications) if any info is zero or -1. */
5527 if (null_timespec(ft->create_time)) {
5528 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5531 if (null_timespec(ft->atime)) {
5532 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5535 if (null_timespec(ft->mtime)) {
5536 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5539 if (!setting_write_time) {
5540 /* ft->mtime comes from change time, not write time. */
5541 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5544 /* Ensure the resolution is the correct for
5545 * what we can store on this filesystem. */
5547 round_timespec(conn->ts_res, &ft->create_time);
5548 round_timespec(conn->ts_res, &ft->ctime);
5549 round_timespec(conn->ts_res, &ft->atime);
5550 round_timespec(conn->ts_res, &ft->mtime);
5552 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5553 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5554 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5555 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5556 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5557 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5558 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5561 if (setting_write_time) {
5563 * This was a Windows setfileinfo on an open file.
5564 * NT does this a lot. We also need to
5565 * set the time here, as it can be read by
5566 * FindFirst/FindNext and with the patch for bug #2045
5567 * in smbd/fileio.c it ensures that this timestamp is
5568 * kept sticky even after a write. We save the request
5569 * away and will set it on file close and after a write. JRA.
5572 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5573 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5575 if (fsp != NULL) {
5576 if (fsp->base_fsp) {
5577 set_sticky_write_time_fsp(fsp->base_fsp,
5578 ft->mtime);
5579 } else {
5580 set_sticky_write_time_fsp(fsp, ft->mtime);
5582 } else {
5583 set_sticky_write_time_path(
5584 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5585 ft->mtime);
5589 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5591 /* Always call ntimes on the base, even if a stream was passed in. */
5592 smb_fname_base = *smb_fname;
5593 smb_fname_base.stream_name = NULL;
5595 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5596 return map_nt_error_from_unix(errno);
5599 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5600 smb_fname->base_name);
5601 return NT_STATUS_OK;
5604 /****************************************************************************
5605 Deal with setting the dosmode from any of the setfilepathinfo functions.
5606 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5607 done before calling this function.
5608 ****************************************************************************/
5610 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5611 const struct smb_filename *smb_fname,
5612 uint32 dosmode)
5614 struct smb_filename *smb_fname_base = NULL;
5615 NTSTATUS status;
5617 if (!VALID_STAT(smb_fname->st)) {
5618 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5621 /* Always operate on the base_name, even if a stream was passed in. */
5622 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5623 NULL, &smb_fname->st,
5624 &smb_fname_base);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 return status;
5629 if (dosmode) {
5630 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5631 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5632 } else {
5633 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5637 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5639 /* check the mode isn't different, before changing it */
5640 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5641 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5642 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5643 (unsigned int)dosmode));
5645 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5646 false)) {
5647 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5648 "%s failed (%s)\n",
5649 smb_fname_str_dbg(smb_fname_base),
5650 strerror(errno)));
5651 status = map_nt_error_from_unix(errno);
5652 goto out;
5655 status = NT_STATUS_OK;
5656 out:
5657 TALLOC_FREE(smb_fname_base);
5658 return status;
5661 /****************************************************************************
5662 Deal with setting the size from any of the setfilepathinfo functions.
5663 ****************************************************************************/
5665 static NTSTATUS smb_set_file_size(connection_struct *conn,
5666 struct smb_request *req,
5667 files_struct *fsp,
5668 const struct smb_filename *smb_fname,
5669 const SMB_STRUCT_STAT *psbuf,
5670 off_t size,
5671 bool fail_after_createfile)
5673 NTSTATUS status = NT_STATUS_OK;
5674 struct smb_filename *smb_fname_tmp = NULL;
5675 files_struct *new_fsp = NULL;
5677 if (!VALID_STAT(*psbuf)) {
5678 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5681 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5683 if (size == get_file_size_stat(psbuf)) {
5684 return NT_STATUS_OK;
5687 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5688 smb_fname_str_dbg(smb_fname), (double)size));
5690 if (fsp && fsp->fh->fd != -1) {
5691 /* Handle based call. */
5692 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5693 return NT_STATUS_ACCESS_DENIED;
5696 if (vfs_set_filelen(fsp, size) == -1) {
5697 return map_nt_error_from_unix(errno);
5699 trigger_write_time_update_immediate(fsp);
5700 return NT_STATUS_OK;
5703 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5704 if (!NT_STATUS_IS_OK(status)) {
5705 return status;
5708 smb_fname_tmp->st = *psbuf;
5710 status = SMB_VFS_CREATE_FILE(
5711 conn, /* conn */
5712 req, /* req */
5713 0, /* root_dir_fid */
5714 smb_fname_tmp, /* fname */
5715 FILE_WRITE_DATA, /* access_mask */
5716 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5717 FILE_SHARE_DELETE),
5718 FILE_OPEN, /* create_disposition*/
5719 0, /* create_options */
5720 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5721 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5722 0, /* allocation_size */
5723 0, /* private_flags */
5724 NULL, /* sd */
5725 NULL, /* ea_list */
5726 &new_fsp, /* result */
5727 NULL); /* pinfo */
5729 TALLOC_FREE(smb_fname_tmp);
5731 if (!NT_STATUS_IS_OK(status)) {
5732 /* NB. We check for open_was_deferred in the caller. */
5733 return status;
5736 /* See RAW-SFILEINFO-END-OF-FILE */
5737 if (fail_after_createfile) {
5738 close_file(req, new_fsp,NORMAL_CLOSE);
5739 return NT_STATUS_INVALID_LEVEL;
5742 if (vfs_set_filelen(new_fsp, size) == -1) {
5743 status = map_nt_error_from_unix(errno);
5744 close_file(req, new_fsp,NORMAL_CLOSE);
5745 return status;
5748 trigger_write_time_update_immediate(new_fsp);
5749 close_file(req, new_fsp,NORMAL_CLOSE);
5750 return NT_STATUS_OK;
5753 /****************************************************************************
5754 Deal with SMB_INFO_SET_EA.
5755 ****************************************************************************/
5757 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5758 const char *pdata,
5759 int total_data,
5760 files_struct *fsp,
5761 const struct smb_filename *smb_fname)
5763 struct ea_list *ea_list = NULL;
5764 TALLOC_CTX *ctx = NULL;
5765 NTSTATUS status = NT_STATUS_OK;
5767 if (total_data < 10) {
5769 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5770 length. They seem to have no effect. Bug #3212. JRA */
5772 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5773 /* We're done. We only get EA info in this call. */
5774 return NT_STATUS_OK;
5777 return NT_STATUS_INVALID_PARAMETER;
5780 if (IVAL(pdata,0) > total_data) {
5781 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5782 IVAL(pdata,0), (unsigned int)total_data));
5783 return NT_STATUS_INVALID_PARAMETER;
5786 ctx = talloc_tos();
5787 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5788 if (!ea_list) {
5789 return NT_STATUS_INVALID_PARAMETER;
5792 status = set_ea(conn, fsp, smb_fname, ea_list);
5794 return status;
5797 /****************************************************************************
5798 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5799 ****************************************************************************/
5801 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5802 const char *pdata,
5803 int total_data,
5804 files_struct *fsp)
5806 struct ea_list *ea_list = NULL;
5807 NTSTATUS status;
5809 if (!fsp) {
5810 return NT_STATUS_INVALID_HANDLE;
5813 if (!lp_ea_support(SNUM(conn))) {
5814 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5815 "EA's not supported.\n",
5816 (unsigned int)total_data));
5817 return NT_STATUS_EAS_NOT_SUPPORTED;
5820 if (total_data < 10) {
5821 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5822 "too small.\n",
5823 (unsigned int)total_data));
5824 return NT_STATUS_INVALID_PARAMETER;
5827 ea_list = read_nttrans_ea_list(talloc_tos(),
5828 pdata,
5829 total_data);
5831 if (!ea_list) {
5832 return NT_STATUS_INVALID_PARAMETER;
5835 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5837 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5838 smb_fname_str_dbg(fsp->fsp_name),
5839 nt_errstr(status) ));
5841 return status;
5845 /****************************************************************************
5846 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5847 ****************************************************************************/
5849 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5850 const char *pdata,
5851 int total_data,
5852 files_struct *fsp,
5853 struct smb_filename *smb_fname)
5855 NTSTATUS status = NT_STATUS_OK;
5856 bool delete_on_close;
5857 uint32 dosmode = 0;
5859 if (total_data < 1) {
5860 return NT_STATUS_INVALID_PARAMETER;
5863 if (fsp == NULL) {
5864 return NT_STATUS_INVALID_HANDLE;
5867 delete_on_close = (CVAL(pdata,0) ? True : False);
5868 dosmode = dos_mode(conn, smb_fname);
5870 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5871 "delete_on_close = %u\n",
5872 smb_fname_str_dbg(smb_fname),
5873 (unsigned int)dosmode,
5874 (unsigned int)delete_on_close ));
5876 if (delete_on_close) {
5877 status = can_set_delete_on_close(fsp, dosmode);
5878 if (!NT_STATUS_IS_OK(status)) {
5879 return status;
5883 /* The set is across all open files on this dev/inode pair. */
5884 if (!set_delete_on_close(fsp, delete_on_close,
5885 conn->session_info->security_token,
5886 conn->session_info->unix_token)) {
5887 return NT_STATUS_ACCESS_DENIED;
5889 return NT_STATUS_OK;
5892 /****************************************************************************
5893 Deal with SMB_FILE_POSITION_INFORMATION.
5894 ****************************************************************************/
5896 static NTSTATUS smb_file_position_information(connection_struct *conn,
5897 const char *pdata,
5898 int total_data,
5899 files_struct *fsp)
5901 uint64_t position_information;
5903 if (total_data < 8) {
5904 return NT_STATUS_INVALID_PARAMETER;
5907 if (fsp == NULL) {
5908 /* Ignore on pathname based set. */
5909 return NT_STATUS_OK;
5912 position_information = (uint64_t)IVAL(pdata,0);
5913 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5915 DEBUG(10,("smb_file_position_information: Set file position "
5916 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5917 (double)position_information));
5918 fsp->fh->position_information = position_information;
5919 return NT_STATUS_OK;
5922 /****************************************************************************
5923 Deal with SMB_FILE_MODE_INFORMATION.
5924 ****************************************************************************/
5926 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5927 const char *pdata,
5928 int total_data)
5930 uint32 mode;
5932 if (total_data < 4) {
5933 return NT_STATUS_INVALID_PARAMETER;
5935 mode = IVAL(pdata,0);
5936 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5937 return NT_STATUS_INVALID_PARAMETER;
5939 return NT_STATUS_OK;
5942 /****************************************************************************
5943 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5944 ****************************************************************************/
5946 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5947 struct smb_request *req,
5948 const char *pdata,
5949 int total_data,
5950 const struct smb_filename *smb_fname)
5952 char *link_target = NULL;
5953 const char *newname = smb_fname->base_name;
5954 TALLOC_CTX *ctx = talloc_tos();
5956 /* Set a symbolic link. */
5957 /* Don't allow this if follow links is false. */
5959 if (total_data == 0) {
5960 return NT_STATUS_INVALID_PARAMETER;
5963 if (!lp_symlinks(SNUM(conn))) {
5964 return NT_STATUS_ACCESS_DENIED;
5967 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5968 total_data, STR_TERMINATE);
5970 if (!link_target) {
5971 return NT_STATUS_INVALID_PARAMETER;
5974 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5975 newname, link_target ));
5977 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5978 return map_nt_error_from_unix(errno);
5981 return NT_STATUS_OK;
5984 /****************************************************************************
5985 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5986 ****************************************************************************/
5988 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5989 struct smb_request *req,
5990 const char *pdata, int total_data,
5991 struct smb_filename *smb_fname_new)
5993 char *oldname = NULL;
5994 struct smb_filename *smb_fname_old = NULL;
5995 TALLOC_CTX *ctx = talloc_tos();
5996 NTSTATUS status = NT_STATUS_OK;
5998 /* Set a hard link. */
5999 if (total_data == 0) {
6000 return NT_STATUS_INVALID_PARAMETER;
6003 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6004 total_data, STR_TERMINATE, &status);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 return status;
6009 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6010 smb_fname_str_dbg(smb_fname_new), oldname));
6012 status = filename_convert(ctx,
6013 conn,
6014 req->flags2 & FLAGS2_DFS_PATHNAMES,
6015 oldname,
6017 NULL,
6018 &smb_fname_old);
6019 if (!NT_STATUS_IS_OK(status)) {
6020 return status;
6023 return hardlink_internals(ctx, conn, req, false,
6024 smb_fname_old, smb_fname_new);
6027 /****************************************************************************
6028 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6029 ****************************************************************************/
6031 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6032 struct smb_request *req,
6033 const char *pdata,
6034 int total_data,
6035 files_struct *fsp,
6036 struct smb_filename *smb_fname_src)
6038 bool overwrite;
6039 uint32_t len;
6040 char *newname = NULL;
6041 struct smb_filename *smb_fname_dst = NULL;
6042 NTSTATUS status = NT_STATUS_OK;
6043 TALLOC_CTX *ctx = talloc_tos();
6045 if (!fsp) {
6046 return NT_STATUS_INVALID_HANDLE;
6049 if (total_data < 20) {
6050 return NT_STATUS_INVALID_PARAMETER;
6053 overwrite = (CVAL(pdata,0) ? True : False);
6054 len = IVAL(pdata,16);
6056 if (len > (total_data - 20) || (len == 0)) {
6057 return NT_STATUS_INVALID_PARAMETER;
6060 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6061 &pdata[20], len, STR_TERMINATE,
6062 &status);
6063 if (!NT_STATUS_IS_OK(status)) {
6064 return status;
6067 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6068 newname));
6070 status = filename_convert(ctx,
6071 conn,
6072 req->flags2 & FLAGS2_DFS_PATHNAMES,
6073 newname,
6074 UCF_SAVE_LCOMP,
6075 NULL,
6076 &smb_fname_dst);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 return status;
6081 if (fsp->base_fsp) {
6082 /* newname must be a stream name. */
6083 if (newname[0] != ':') {
6084 return NT_STATUS_NOT_SUPPORTED;
6087 /* Create an smb_fname to call rename_internals_fsp() with. */
6088 status = create_synthetic_smb_fname(talloc_tos(),
6089 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6090 &smb_fname_dst);
6091 if (!NT_STATUS_IS_OK(status)) {
6092 goto out;
6096 * Set the original last component, since
6097 * rename_internals_fsp() requires it.
6099 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6100 newname);
6101 if (smb_fname_dst->original_lcomp == NULL) {
6102 status = NT_STATUS_NO_MEMORY;
6103 goto out;
6108 DEBUG(10,("smb2_file_rename_information: "
6109 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6110 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6111 smb_fname_str_dbg(smb_fname_dst)));
6112 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6113 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6114 overwrite);
6116 out:
6117 TALLOC_FREE(smb_fname_dst);
6118 return status;
6121 static NTSTATUS smb_file_link_information(connection_struct *conn,
6122 struct smb_request *req,
6123 const char *pdata,
6124 int total_data,
6125 files_struct *fsp,
6126 struct smb_filename *smb_fname_src)
6128 bool overwrite;
6129 uint32_t len;
6130 char *newname = NULL;
6131 struct smb_filename *smb_fname_dst = NULL;
6132 NTSTATUS status = NT_STATUS_OK;
6133 TALLOC_CTX *ctx = talloc_tos();
6135 if (!fsp) {
6136 return NT_STATUS_INVALID_HANDLE;
6139 if (total_data < 20) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 overwrite = (CVAL(pdata,0) ? true : false);
6144 len = IVAL(pdata,16);
6146 if (len > (total_data - 20) || (len == 0)) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6151 &pdata[20], len, STR_TERMINATE,
6152 &status);
6153 if (!NT_STATUS_IS_OK(status)) {
6154 return status;
6157 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6158 newname));
6160 status = filename_convert(ctx,
6161 conn,
6162 req->flags2 & FLAGS2_DFS_PATHNAMES,
6163 newname,
6164 UCF_SAVE_LCOMP,
6165 NULL,
6166 &smb_fname_dst);
6167 if (!NT_STATUS_IS_OK(status)) {
6168 return status;
6171 if (fsp->base_fsp) {
6172 /* No stream names. */
6173 return NT_STATUS_NOT_SUPPORTED;
6176 DEBUG(10,("smb_file_link_information: "
6177 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6178 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6179 smb_fname_str_dbg(smb_fname_dst)));
6180 status = hardlink_internals(ctx,
6181 conn,
6182 req,
6183 overwrite,
6184 fsp->fsp_name,
6185 smb_fname_dst);
6187 TALLOC_FREE(smb_fname_dst);
6188 return status;
6191 /****************************************************************************
6192 Deal with SMB_FILE_RENAME_INFORMATION.
6193 ****************************************************************************/
6195 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6196 struct smb_request *req,
6197 const char *pdata,
6198 int total_data,
6199 files_struct *fsp,
6200 struct smb_filename *smb_fname_src)
6202 bool overwrite;
6203 uint32 root_fid;
6204 uint32 len;
6205 char *newname = NULL;
6206 struct smb_filename *smb_fname_dst = NULL;
6207 bool dest_has_wcard = False;
6208 NTSTATUS status = NT_STATUS_OK;
6209 char *p;
6210 TALLOC_CTX *ctx = talloc_tos();
6212 if (total_data < 13) {
6213 return NT_STATUS_INVALID_PARAMETER;
6216 overwrite = (CVAL(pdata,0) ? True : False);
6217 root_fid = IVAL(pdata,4);
6218 len = IVAL(pdata,8);
6220 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6221 return NT_STATUS_INVALID_PARAMETER;
6224 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6225 len, 0, &status,
6226 &dest_has_wcard);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 return status;
6231 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6232 newname));
6234 status = resolve_dfspath_wcard(ctx, conn,
6235 req->flags2 & FLAGS2_DFS_PATHNAMES,
6236 newname,
6237 true,
6238 !conn->sconn->using_smb2,
6239 &newname,
6240 &dest_has_wcard);
6241 if (!NT_STATUS_IS_OK(status)) {
6242 return status;
6245 /* Check the new name has no '/' characters. */
6246 if (strchr_m(newname, '/')) {
6247 return NT_STATUS_NOT_SUPPORTED;
6250 if (fsp && fsp->base_fsp) {
6251 /* newname must be a stream name. */
6252 if (newname[0] != ':') {
6253 return NT_STATUS_NOT_SUPPORTED;
6256 /* Create an smb_fname to call rename_internals_fsp() with. */
6257 status = create_synthetic_smb_fname(talloc_tos(),
6258 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6259 &smb_fname_dst);
6260 if (!NT_STATUS_IS_OK(status)) {
6261 goto out;
6265 * Set the original last component, since
6266 * rename_internals_fsp() requires it.
6268 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6269 newname);
6270 if (smb_fname_dst->original_lcomp == NULL) {
6271 status = NT_STATUS_NO_MEMORY;
6272 goto out;
6275 } else {
6277 * Build up an smb_fname_dst based on the filename passed in.
6278 * We basically just strip off the last component, and put on
6279 * the newname instead.
6281 char *base_name = NULL;
6283 /* newname must *not* be a stream name. */
6284 if (newname[0] == ':') {
6285 return NT_STATUS_NOT_SUPPORTED;
6289 * Strip off the last component (filename) of the path passed
6290 * in.
6292 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6293 if (!base_name) {
6294 return NT_STATUS_NO_MEMORY;
6296 p = strrchr_m(base_name, '/');
6297 if (p) {
6298 p[1] = '\0';
6299 } else {
6300 base_name = talloc_strdup(ctx, "");
6301 if (!base_name) {
6302 return NT_STATUS_NO_MEMORY;
6305 /* Append the new name. */
6306 base_name = talloc_asprintf_append(base_name,
6307 "%s",
6308 newname);
6309 if (!base_name) {
6310 return NT_STATUS_NO_MEMORY;
6313 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6314 (UCF_SAVE_LCOMP |
6315 (dest_has_wcard ?
6316 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6317 0)));
6319 /* If an error we expect this to be
6320 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6322 if (!NT_STATUS_IS_OK(status)) {
6323 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6324 status)) {
6325 goto out;
6327 /* Create an smb_fname to call rename_internals_fsp() */
6328 status = create_synthetic_smb_fname(ctx,
6329 base_name, NULL,
6330 NULL,
6331 &smb_fname_dst);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 goto out;
6338 if (fsp) {
6339 DEBUG(10,("smb_file_rename_information: "
6340 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6341 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6342 smb_fname_str_dbg(smb_fname_dst)));
6343 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6344 overwrite);
6345 } else {
6346 DEBUG(10,("smb_file_rename_information: "
6347 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6348 smb_fname_str_dbg(smb_fname_src),
6349 smb_fname_str_dbg(smb_fname_dst)));
6350 status = rename_internals(ctx, conn, req, smb_fname_src,
6351 smb_fname_dst, 0, overwrite, false,
6352 dest_has_wcard,
6353 FILE_WRITE_ATTRIBUTES);
6355 out:
6356 TALLOC_FREE(smb_fname_dst);
6357 return status;
6360 /****************************************************************************
6361 Deal with SMB_SET_POSIX_ACL.
6362 ****************************************************************************/
6364 #if defined(HAVE_POSIX_ACLS)
6365 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6366 const char *pdata,
6367 int total_data,
6368 files_struct *fsp,
6369 const struct smb_filename *smb_fname)
6371 uint16 posix_acl_version;
6372 uint16 num_file_acls;
6373 uint16 num_def_acls;
6374 bool valid_file_acls = True;
6375 bool valid_def_acls = True;
6377 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6378 return NT_STATUS_INVALID_PARAMETER;
6380 posix_acl_version = SVAL(pdata,0);
6381 num_file_acls = SVAL(pdata,2);
6382 num_def_acls = SVAL(pdata,4);
6384 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6385 valid_file_acls = False;
6386 num_file_acls = 0;
6389 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6390 valid_def_acls = False;
6391 num_def_acls = 0;
6394 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6395 return NT_STATUS_INVALID_PARAMETER;
6398 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6399 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6400 return NT_STATUS_INVALID_PARAMETER;
6403 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6404 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6405 (unsigned int)num_file_acls,
6406 (unsigned int)num_def_acls));
6408 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6409 smb_fname->base_name, num_file_acls,
6410 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6411 return map_nt_error_from_unix(errno);
6414 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6415 smb_fname->base_name, &smb_fname->st, num_def_acls,
6416 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6417 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6418 return map_nt_error_from_unix(errno);
6420 return NT_STATUS_OK;
6422 #endif
6424 /****************************************************************************
6425 Deal with SMB_SET_POSIX_LOCK.
6426 ****************************************************************************/
6428 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6429 struct smb_request *req,
6430 const char *pdata,
6431 int total_data,
6432 files_struct *fsp)
6434 uint64_t count;
6435 uint64_t offset;
6436 uint64_t smblctx;
6437 bool blocking_lock = False;
6438 enum brl_type lock_type;
6440 NTSTATUS status = NT_STATUS_OK;
6442 if (fsp == NULL || fsp->fh->fd == -1) {
6443 return NT_STATUS_INVALID_HANDLE;
6446 if (total_data != POSIX_LOCK_DATA_SIZE) {
6447 return NT_STATUS_INVALID_PARAMETER;
6450 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6451 case POSIX_LOCK_TYPE_READ:
6452 lock_type = READ_LOCK;
6453 break;
6454 case POSIX_LOCK_TYPE_WRITE:
6455 /* Return the right POSIX-mappable error code for files opened read-only. */
6456 if (!fsp->can_write) {
6457 return NT_STATUS_INVALID_HANDLE;
6459 lock_type = WRITE_LOCK;
6460 break;
6461 case POSIX_LOCK_TYPE_UNLOCK:
6462 lock_type = UNLOCK_LOCK;
6463 break;
6464 default:
6465 return NT_STATUS_INVALID_PARAMETER;
6468 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6469 blocking_lock = False;
6470 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6471 blocking_lock = True;
6472 } else {
6473 return NT_STATUS_INVALID_PARAMETER;
6476 if (!lp_blocking_locks(SNUM(conn))) {
6477 blocking_lock = False;
6480 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6481 #if defined(HAVE_LONGLONG)
6482 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6483 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6484 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6485 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6486 #else /* HAVE_LONGLONG */
6487 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6488 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6489 #endif /* HAVE_LONGLONG */
6491 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6492 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6493 fsp_str_dbg(fsp),
6494 (unsigned int)lock_type,
6495 (unsigned long long)smblctx,
6496 (double)count,
6497 (double)offset ));
6499 if (lock_type == UNLOCK_LOCK) {
6500 status = do_unlock(req->sconn->msg_ctx,
6501 fsp,
6502 smblctx,
6503 count,
6504 offset,
6505 POSIX_LOCK);
6506 } else {
6507 uint64_t block_smblctx;
6509 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6510 fsp,
6511 smblctx,
6512 count,
6513 offset,
6514 lock_type,
6515 POSIX_LOCK,
6516 blocking_lock,
6517 &status,
6518 &block_smblctx,
6519 NULL);
6521 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6523 * A blocking lock was requested. Package up
6524 * this smb into a queued request and push it
6525 * onto the blocking lock queue.
6527 if(push_blocking_lock_request(br_lck,
6528 req,
6529 fsp,
6530 -1, /* infinite timeout. */
6532 smblctx,
6533 lock_type,
6534 POSIX_LOCK,
6535 offset,
6536 count,
6537 block_smblctx)) {
6538 TALLOC_FREE(br_lck);
6539 return status;
6542 TALLOC_FREE(br_lck);
6545 return status;
6548 /****************************************************************************
6549 Deal with SMB_SET_FILE_BASIC_INFO.
6550 ****************************************************************************/
6552 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6553 const char *pdata,
6554 int total_data,
6555 files_struct *fsp,
6556 const struct smb_filename *smb_fname)
6558 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6559 struct smb_file_time ft;
6560 uint32 dosmode = 0;
6561 NTSTATUS status = NT_STATUS_OK;
6563 ZERO_STRUCT(ft);
6565 if (total_data < 36) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6570 if (!NT_STATUS_IS_OK(status)) {
6571 return status;
6574 /* Set the attributes */
6575 dosmode = IVAL(pdata,32);
6576 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 return status;
6581 /* create time */
6582 ft.create_time = interpret_long_date(pdata);
6584 /* access time */
6585 ft.atime = interpret_long_date(pdata+8);
6587 /* write time. */
6588 ft.mtime = interpret_long_date(pdata+16);
6590 /* change time. */
6591 ft.ctime = interpret_long_date(pdata+24);
6593 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6594 smb_fname_str_dbg(smb_fname)));
6596 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6597 true);
6600 /****************************************************************************
6601 Deal with SMB_INFO_STANDARD.
6602 ****************************************************************************/
6604 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6605 const char *pdata,
6606 int total_data,
6607 files_struct *fsp,
6608 const struct smb_filename *smb_fname)
6610 NTSTATUS status;
6611 struct smb_file_time ft;
6613 ZERO_STRUCT(ft);
6615 if (total_data < 12) {
6616 return NT_STATUS_INVALID_PARAMETER;
6619 /* create time */
6620 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6621 /* access time */
6622 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6623 /* write time */
6624 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6626 DEBUG(10,("smb_set_info_standard: file %s\n",
6627 smb_fname_str_dbg(smb_fname)));
6629 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 return status;
6634 return smb_set_file_time(conn,
6635 fsp,
6636 smb_fname,
6637 &ft,
6638 true);
6641 /****************************************************************************
6642 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6643 ****************************************************************************/
6645 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6646 struct smb_request *req,
6647 const char *pdata,
6648 int total_data,
6649 files_struct *fsp,
6650 struct smb_filename *smb_fname)
6652 uint64_t allocation_size = 0;
6653 NTSTATUS status = NT_STATUS_OK;
6654 files_struct *new_fsp = NULL;
6656 if (!VALID_STAT(smb_fname->st)) {
6657 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6660 if (total_data < 8) {
6661 return NT_STATUS_INVALID_PARAMETER;
6664 allocation_size = (uint64_t)IVAL(pdata,0);
6665 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6666 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6667 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6668 (double)allocation_size));
6670 if (allocation_size) {
6671 allocation_size = smb_roundup(conn, allocation_size);
6674 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6675 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6676 (double)allocation_size));
6678 if (fsp && fsp->fh->fd != -1) {
6679 /* Open file handle. */
6680 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6681 return NT_STATUS_ACCESS_DENIED;
6684 /* Only change if needed. */
6685 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6686 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6687 return map_nt_error_from_unix(errno);
6690 /* But always update the time. */
6692 * This is equivalent to a write. Ensure it's seen immediately
6693 * if there are no pending writes.
6695 trigger_write_time_update_immediate(fsp);
6696 return NT_STATUS_OK;
6699 /* Pathname or stat or directory file. */
6700 status = SMB_VFS_CREATE_FILE(
6701 conn, /* conn */
6702 req, /* req */
6703 0, /* root_dir_fid */
6704 smb_fname, /* fname */
6705 FILE_WRITE_DATA, /* access_mask */
6706 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6707 FILE_SHARE_DELETE),
6708 FILE_OPEN, /* create_disposition*/
6709 0, /* create_options */
6710 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6711 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6712 0, /* allocation_size */
6713 0, /* private_flags */
6714 NULL, /* sd */
6715 NULL, /* ea_list */
6716 &new_fsp, /* result */
6717 NULL); /* pinfo */
6719 if (!NT_STATUS_IS_OK(status)) {
6720 /* NB. We check for open_was_deferred in the caller. */
6721 return status;
6724 /* Only change if needed. */
6725 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6726 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6727 status = map_nt_error_from_unix(errno);
6728 close_file(req, new_fsp, NORMAL_CLOSE);
6729 return status;
6733 /* Changing the allocation size should set the last mod time. */
6735 * This is equivalent to a write. Ensure it's seen immediately
6736 * if there are no pending writes.
6738 trigger_write_time_update_immediate(new_fsp);
6740 close_file(req, new_fsp, NORMAL_CLOSE);
6741 return NT_STATUS_OK;
6744 /****************************************************************************
6745 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6746 ****************************************************************************/
6748 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6749 struct smb_request *req,
6750 const char *pdata,
6751 int total_data,
6752 files_struct *fsp,
6753 const struct smb_filename *smb_fname,
6754 bool fail_after_createfile)
6756 off_t size;
6758 if (total_data < 8) {
6759 return NT_STATUS_INVALID_PARAMETER;
6762 size = IVAL(pdata,0);
6763 size |= (((off_t)IVAL(pdata,4)) << 32);
6764 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6765 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6766 (double)size));
6768 return smb_set_file_size(conn, req,
6769 fsp,
6770 smb_fname,
6771 &smb_fname->st,
6772 size,
6773 fail_after_createfile);
6776 /****************************************************************************
6777 Allow a UNIX info mknod.
6778 ****************************************************************************/
6780 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6781 const char *pdata,
6782 int total_data,
6783 const struct smb_filename *smb_fname)
6785 uint32 file_type = IVAL(pdata,56);
6786 #if defined(HAVE_MAKEDEV)
6787 uint32 dev_major = IVAL(pdata,60);
6788 uint32 dev_minor = IVAL(pdata,68);
6789 #endif
6790 SMB_DEV_T dev = (SMB_DEV_T)0;
6791 uint32 raw_unixmode = IVAL(pdata,84);
6792 NTSTATUS status;
6793 mode_t unixmode;
6795 if (total_data < 100) {
6796 return NT_STATUS_INVALID_PARAMETER;
6799 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6800 PERM_NEW_FILE, &unixmode);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 return status;
6805 #if defined(HAVE_MAKEDEV)
6806 dev = makedev(dev_major, dev_minor);
6807 #endif
6809 switch (file_type) {
6810 #if defined(S_IFIFO)
6811 case UNIX_TYPE_FIFO:
6812 unixmode |= S_IFIFO;
6813 break;
6814 #endif
6815 #if defined(S_IFSOCK)
6816 case UNIX_TYPE_SOCKET:
6817 unixmode |= S_IFSOCK;
6818 break;
6819 #endif
6820 #if defined(S_IFCHR)
6821 case UNIX_TYPE_CHARDEV:
6822 unixmode |= S_IFCHR;
6823 break;
6824 #endif
6825 #if defined(S_IFBLK)
6826 case UNIX_TYPE_BLKDEV:
6827 unixmode |= S_IFBLK;
6828 break;
6829 #endif
6830 default:
6831 return NT_STATUS_INVALID_PARAMETER;
6834 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6835 "%.0f mode 0%o for file %s\n", (double)dev,
6836 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6838 /* Ok - do the mknod. */
6839 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6840 return map_nt_error_from_unix(errno);
6843 /* If any of the other "set" calls fail we
6844 * don't want to end up with a half-constructed mknod.
6847 if (lp_inherit_perms(SNUM(conn))) {
6848 char *parent;
6849 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6850 &parent, NULL)) {
6851 return NT_STATUS_NO_MEMORY;
6853 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6854 unixmode);
6855 TALLOC_FREE(parent);
6858 return NT_STATUS_OK;
6861 /****************************************************************************
6862 Deal with SMB_SET_FILE_UNIX_BASIC.
6863 ****************************************************************************/
6865 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6866 struct smb_request *req,
6867 const char *pdata,
6868 int total_data,
6869 files_struct *fsp,
6870 const struct smb_filename *smb_fname)
6872 struct smb_file_time ft;
6873 uint32 raw_unixmode;
6874 mode_t unixmode;
6875 off_t size = 0;
6876 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6877 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6878 NTSTATUS status = NT_STATUS_OK;
6879 bool delete_on_fail = False;
6880 enum perm_type ptype;
6881 files_struct *all_fsps = NULL;
6882 bool modify_mtime = true;
6883 struct file_id id;
6884 struct smb_filename *smb_fname_tmp = NULL;
6885 SMB_STRUCT_STAT sbuf;
6887 ZERO_STRUCT(ft);
6889 if (total_data < 100) {
6890 return NT_STATUS_INVALID_PARAMETER;
6893 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6894 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6895 size=IVAL(pdata,0); /* first 8 Bytes are size */
6896 size |= (((off_t)IVAL(pdata,4)) << 32);
6899 ft.atime = interpret_long_date(pdata+24); /* access_time */
6900 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6901 set_owner = (uid_t)IVAL(pdata,40);
6902 set_grp = (gid_t)IVAL(pdata,48);
6903 raw_unixmode = IVAL(pdata,84);
6905 if (VALID_STAT(smb_fname->st)) {
6906 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6907 ptype = PERM_EXISTING_DIR;
6908 } else {
6909 ptype = PERM_EXISTING_FILE;
6911 } else {
6912 ptype = PERM_NEW_FILE;
6915 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6916 ptype, &unixmode);
6917 if (!NT_STATUS_IS_OK(status)) {
6918 return status;
6921 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6922 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6923 smb_fname_str_dbg(smb_fname), (double)size,
6924 (unsigned int)set_owner, (unsigned int)set_grp,
6925 (int)raw_unixmode));
6927 sbuf = smb_fname->st;
6929 if (!VALID_STAT(sbuf)) {
6931 * The only valid use of this is to create character and block
6932 * devices, and named pipes. This is deprecated (IMHO) and
6933 * a new info level should be used for mknod. JRA.
6936 status = smb_unix_mknod(conn,
6937 pdata,
6938 total_data,
6939 smb_fname);
6940 if (!NT_STATUS_IS_OK(status)) {
6941 return status;
6944 status = copy_smb_filename(talloc_tos(), smb_fname,
6945 &smb_fname_tmp);
6946 if (!NT_STATUS_IS_OK(status)) {
6947 return status;
6950 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6951 status = map_nt_error_from_unix(errno);
6952 TALLOC_FREE(smb_fname_tmp);
6953 SMB_VFS_UNLINK(conn, smb_fname);
6954 return status;
6957 sbuf = smb_fname_tmp->st;
6958 smb_fname = smb_fname_tmp;
6960 /* Ensure we don't try and change anything else. */
6961 raw_unixmode = SMB_MODE_NO_CHANGE;
6962 size = get_file_size_stat(&sbuf);
6963 ft.atime = sbuf.st_ex_atime;
6964 ft.mtime = sbuf.st_ex_mtime;
6966 * We continue here as we might want to change the
6967 * owner uid/gid.
6969 delete_on_fail = True;
6972 #if 1
6973 /* Horrible backwards compatibility hack as an old server bug
6974 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6975 * */
6977 if (!size) {
6978 size = get_file_size_stat(&sbuf);
6980 #endif
6983 * Deal with the UNIX specific mode set.
6986 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6987 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6988 "setting mode 0%o for file %s\n",
6989 (unsigned int)unixmode,
6990 smb_fname_str_dbg(smb_fname)));
6991 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6992 return map_nt_error_from_unix(errno);
6997 * Deal with the UNIX specific uid set.
7000 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7001 (sbuf.st_ex_uid != set_owner)) {
7002 int ret;
7004 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7005 "changing owner %u for path %s\n",
7006 (unsigned int)set_owner,
7007 smb_fname_str_dbg(smb_fname)));
7009 if (S_ISLNK(sbuf.st_ex_mode)) {
7010 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7011 set_owner, (gid_t)-1);
7012 } else {
7013 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7014 set_owner, (gid_t)-1);
7017 if (ret != 0) {
7018 status = map_nt_error_from_unix(errno);
7019 if (delete_on_fail) {
7020 SMB_VFS_UNLINK(conn, smb_fname);
7022 return status;
7027 * Deal with the UNIX specific gid set.
7030 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7031 (sbuf.st_ex_gid != set_grp)) {
7032 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7033 "changing group %u for file %s\n",
7034 (unsigned int)set_owner,
7035 smb_fname_str_dbg(smb_fname)));
7036 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7037 set_grp) != 0) {
7038 status = map_nt_error_from_unix(errno);
7039 if (delete_on_fail) {
7040 SMB_VFS_UNLINK(conn, smb_fname);
7042 return status;
7046 /* Deal with any size changes. */
7048 status = smb_set_file_size(conn, req,
7049 fsp,
7050 smb_fname,
7051 &sbuf,
7052 size,
7053 false);
7054 if (!NT_STATUS_IS_OK(status)) {
7055 return status;
7058 /* Deal with any time changes. */
7059 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7060 /* No change, don't cancel anything. */
7061 return status;
7064 id = vfs_file_id_from_sbuf(conn, &sbuf);
7065 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7066 all_fsps = file_find_di_next(all_fsps)) {
7068 * We're setting the time explicitly for UNIX.
7069 * Cancel any pending changes over all handles.
7071 all_fsps->update_write_time_on_close = false;
7072 TALLOC_FREE(all_fsps->update_write_time_event);
7076 * Override the "setting_write_time"
7077 * parameter here as it almost does what
7078 * we need. Just remember if we modified
7079 * mtime and send the notify ourselves.
7081 if (null_timespec(ft.mtime)) {
7082 modify_mtime = false;
7085 status = smb_set_file_time(conn,
7086 fsp,
7087 smb_fname,
7088 &ft,
7089 false);
7090 if (modify_mtime) {
7091 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7092 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7094 return status;
7097 /****************************************************************************
7098 Deal with SMB_SET_FILE_UNIX_INFO2.
7099 ****************************************************************************/
7101 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7102 struct smb_request *req,
7103 const char *pdata,
7104 int total_data,
7105 files_struct *fsp,
7106 const struct smb_filename *smb_fname)
7108 NTSTATUS status;
7109 uint32 smb_fflags;
7110 uint32 smb_fmask;
7112 if (total_data < 116) {
7113 return NT_STATUS_INVALID_PARAMETER;
7116 /* Start by setting all the fields that are common between UNIX_BASIC
7117 * and UNIX_INFO2.
7119 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7120 fsp, smb_fname);
7121 if (!NT_STATUS_IS_OK(status)) {
7122 return status;
7125 smb_fflags = IVAL(pdata, 108);
7126 smb_fmask = IVAL(pdata, 112);
7128 /* NB: We should only attempt to alter the file flags if the client
7129 * sends a non-zero mask.
7131 if (smb_fmask != 0) {
7132 int stat_fflags = 0;
7134 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7135 smb_fmask, &stat_fflags)) {
7136 /* Client asked to alter a flag we don't understand. */
7137 return NT_STATUS_INVALID_PARAMETER;
7140 if (fsp && fsp->fh->fd != -1) {
7141 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7142 return NT_STATUS_NOT_SUPPORTED;
7143 } else {
7144 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7145 stat_fflags) != 0) {
7146 return map_nt_error_from_unix(errno);
7151 /* XXX: need to add support for changing the create_time here. You
7152 * can do this for paths on Darwin with setattrlist(2). The right way
7153 * to hook this up is probably by extending the VFS utimes interface.
7156 return NT_STATUS_OK;
7159 /****************************************************************************
7160 Create a directory with POSIX semantics.
7161 ****************************************************************************/
7163 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7164 struct smb_request *req,
7165 char **ppdata,
7166 int total_data,
7167 struct smb_filename *smb_fname,
7168 int *pdata_return_size)
7170 NTSTATUS status = NT_STATUS_OK;
7171 uint32 raw_unixmode = 0;
7172 uint32 mod_unixmode = 0;
7173 mode_t unixmode = (mode_t)0;
7174 files_struct *fsp = NULL;
7175 uint16 info_level_return = 0;
7176 int info;
7177 char *pdata = *ppdata;
7179 if (total_data < 18) {
7180 return NT_STATUS_INVALID_PARAMETER;
7183 raw_unixmode = IVAL(pdata,8);
7184 /* Next 4 bytes are not yet defined. */
7186 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7187 PERM_NEW_DIR, &unixmode);
7188 if (!NT_STATUS_IS_OK(status)) {
7189 return status;
7192 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7194 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7195 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7197 status = SMB_VFS_CREATE_FILE(
7198 conn, /* conn */
7199 req, /* req */
7200 0, /* root_dir_fid */
7201 smb_fname, /* fname */
7202 FILE_READ_ATTRIBUTES, /* access_mask */
7203 FILE_SHARE_NONE, /* share_access */
7204 FILE_CREATE, /* create_disposition*/
7205 FILE_DIRECTORY_FILE, /* create_options */
7206 mod_unixmode, /* file_attributes */
7207 0, /* oplock_request */
7208 0, /* allocation_size */
7209 0, /* private_flags */
7210 NULL, /* sd */
7211 NULL, /* ea_list */
7212 &fsp, /* result */
7213 &info); /* pinfo */
7215 if (NT_STATUS_IS_OK(status)) {
7216 close_file(req, fsp, NORMAL_CLOSE);
7219 info_level_return = SVAL(pdata,16);
7221 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7222 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7223 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7224 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7225 } else {
7226 *pdata_return_size = 12;
7229 /* Realloc the data size */
7230 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7231 if (*ppdata == NULL) {
7232 *pdata_return_size = 0;
7233 return NT_STATUS_NO_MEMORY;
7235 pdata = *ppdata;
7237 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7238 SSVAL(pdata,2,0); /* No fnum. */
7239 SIVAL(pdata,4,info); /* Was directory created. */
7241 switch (info_level_return) {
7242 case SMB_QUERY_FILE_UNIX_BASIC:
7243 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7244 SSVAL(pdata,10,0); /* Padding. */
7245 store_file_unix_basic(conn, pdata + 12, fsp,
7246 &smb_fname->st);
7247 break;
7248 case SMB_QUERY_FILE_UNIX_INFO2:
7249 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7250 SSVAL(pdata,10,0); /* Padding. */
7251 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7252 &smb_fname->st);
7253 break;
7254 default:
7255 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7256 SSVAL(pdata,10,0); /* Padding. */
7257 break;
7260 return status;
7263 /****************************************************************************
7264 Open/Create a file with POSIX semantics.
7265 ****************************************************************************/
7267 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7268 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7270 static NTSTATUS smb_posix_open(connection_struct *conn,
7271 struct smb_request *req,
7272 char **ppdata,
7273 int total_data,
7274 struct smb_filename *smb_fname,
7275 int *pdata_return_size)
7277 bool extended_oplock_granted = False;
7278 char *pdata = *ppdata;
7279 uint32 flags = 0;
7280 uint32 wire_open_mode = 0;
7281 uint32 raw_unixmode = 0;
7282 uint32 mod_unixmode = 0;
7283 uint32 create_disp = 0;
7284 uint32 access_mask = 0;
7285 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7286 NTSTATUS status = NT_STATUS_OK;
7287 mode_t unixmode = (mode_t)0;
7288 files_struct *fsp = NULL;
7289 int oplock_request = 0;
7290 int info = 0;
7291 uint16 info_level_return = 0;
7293 if (total_data < 18) {
7294 return NT_STATUS_INVALID_PARAMETER;
7297 flags = IVAL(pdata,0);
7298 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7299 if (oplock_request) {
7300 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7303 wire_open_mode = IVAL(pdata,4);
7305 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7306 return smb_posix_mkdir(conn, req,
7307 ppdata,
7308 total_data,
7309 smb_fname,
7310 pdata_return_size);
7313 switch (wire_open_mode & SMB_ACCMODE) {
7314 case SMB_O_RDONLY:
7315 access_mask = SMB_O_RDONLY_MAPPING;
7316 break;
7317 case SMB_O_WRONLY:
7318 access_mask = SMB_O_WRONLY_MAPPING;
7319 break;
7320 case SMB_O_RDWR:
7321 access_mask = (SMB_O_RDONLY_MAPPING|
7322 SMB_O_WRONLY_MAPPING);
7323 break;
7324 default:
7325 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7326 (unsigned int)wire_open_mode ));
7327 return NT_STATUS_INVALID_PARAMETER;
7330 wire_open_mode &= ~SMB_ACCMODE;
7332 /* First take care of O_CREAT|O_EXCL interactions. */
7333 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7334 case (SMB_O_CREAT | SMB_O_EXCL):
7335 /* File exists fail. File not exist create. */
7336 create_disp = FILE_CREATE;
7337 break;
7338 case SMB_O_CREAT:
7339 /* File exists open. File not exist create. */
7340 create_disp = FILE_OPEN_IF;
7341 break;
7342 case 0:
7343 /* File exists open. File not exist fail. */
7344 create_disp = FILE_OPEN;
7345 break;
7346 case SMB_O_EXCL:
7347 /* O_EXCL on its own without O_CREAT is undefined. */
7348 default:
7349 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7350 (unsigned int)wire_open_mode ));
7351 return NT_STATUS_INVALID_PARAMETER;
7354 /* Next factor in the effects of O_TRUNC. */
7355 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7357 if (wire_open_mode & SMB_O_TRUNC) {
7358 switch (create_disp) {
7359 case FILE_CREATE:
7360 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7361 /* Leave create_disp alone as
7362 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7364 /* File exists fail. File not exist create. */
7365 break;
7366 case FILE_OPEN_IF:
7367 /* SMB_O_CREAT | SMB_O_TRUNC */
7368 /* File exists overwrite. File not exist create. */
7369 create_disp = FILE_OVERWRITE_IF;
7370 break;
7371 case FILE_OPEN:
7372 /* SMB_O_TRUNC */
7373 /* File exists overwrite. File not exist fail. */
7374 create_disp = FILE_OVERWRITE;
7375 break;
7376 default:
7377 /* Cannot get here. */
7378 smb_panic("smb_posix_open: logic error");
7379 return NT_STATUS_INVALID_PARAMETER;
7383 raw_unixmode = IVAL(pdata,8);
7384 /* Next 4 bytes are not yet defined. */
7386 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7387 (VALID_STAT(smb_fname->st) ?
7388 PERM_EXISTING_FILE : PERM_NEW_FILE),
7389 &unixmode);
7391 if (!NT_STATUS_IS_OK(status)) {
7392 return status;
7395 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7397 if (wire_open_mode & SMB_O_SYNC) {
7398 create_options |= FILE_WRITE_THROUGH;
7400 if (wire_open_mode & SMB_O_APPEND) {
7401 access_mask |= FILE_APPEND_DATA;
7403 if (wire_open_mode & SMB_O_DIRECT) {
7404 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7407 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7408 VALID_STAT_OF_DIR(smb_fname->st)) {
7409 if (access_mask != SMB_O_RDONLY_MAPPING) {
7410 return NT_STATUS_FILE_IS_A_DIRECTORY;
7412 create_options &= ~FILE_NON_DIRECTORY_FILE;
7413 create_options |= FILE_DIRECTORY_FILE;
7416 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7417 smb_fname_str_dbg(smb_fname),
7418 (unsigned int)wire_open_mode,
7419 (unsigned int)unixmode ));
7421 status = SMB_VFS_CREATE_FILE(
7422 conn, /* conn */
7423 req, /* req */
7424 0, /* root_dir_fid */
7425 smb_fname, /* fname */
7426 access_mask, /* access_mask */
7427 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7428 FILE_SHARE_DELETE),
7429 create_disp, /* create_disposition*/
7430 create_options, /* create_options */
7431 mod_unixmode, /* file_attributes */
7432 oplock_request, /* oplock_request */
7433 0, /* allocation_size */
7434 0, /* private_flags */
7435 NULL, /* sd */
7436 NULL, /* ea_list */
7437 &fsp, /* result */
7438 &info); /* pinfo */
7440 if (!NT_STATUS_IS_OK(status)) {
7441 return status;
7444 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7445 extended_oplock_granted = True;
7448 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7449 extended_oplock_granted = True;
7452 info_level_return = SVAL(pdata,16);
7454 /* Allocate the correct return size. */
7456 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7457 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7458 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7459 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7460 } else {
7461 *pdata_return_size = 12;
7464 /* Realloc the data size */
7465 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7466 if (*ppdata == NULL) {
7467 close_file(req, fsp, ERROR_CLOSE);
7468 *pdata_return_size = 0;
7469 return NT_STATUS_NO_MEMORY;
7471 pdata = *ppdata;
7473 if (extended_oplock_granted) {
7474 if (flags & REQUEST_BATCH_OPLOCK) {
7475 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7476 } else {
7477 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7479 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7480 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7481 } else {
7482 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7485 SSVAL(pdata,2,fsp->fnum);
7486 SIVAL(pdata,4,info); /* Was file created etc. */
7488 switch (info_level_return) {
7489 case SMB_QUERY_FILE_UNIX_BASIC:
7490 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7491 SSVAL(pdata,10,0); /* padding. */
7492 store_file_unix_basic(conn, pdata + 12, fsp,
7493 &smb_fname->st);
7494 break;
7495 case SMB_QUERY_FILE_UNIX_INFO2:
7496 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7497 SSVAL(pdata,10,0); /* padding. */
7498 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7499 &smb_fname->st);
7500 break;
7501 default:
7502 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7503 SSVAL(pdata,10,0); /* padding. */
7504 break;
7506 return NT_STATUS_OK;
7509 /****************************************************************************
7510 Delete a file with POSIX semantics.
7511 ****************************************************************************/
7513 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7514 struct smb_request *req,
7515 const char *pdata,
7516 int total_data,
7517 struct smb_filename *smb_fname)
7519 NTSTATUS status = NT_STATUS_OK;
7520 files_struct *fsp = NULL;
7521 uint16 flags = 0;
7522 char del = 1;
7523 int info = 0;
7524 int create_options = 0;
7525 int i;
7526 struct share_mode_lock *lck = NULL;
7528 if (total_data < 2) {
7529 return NT_STATUS_INVALID_PARAMETER;
7532 flags = SVAL(pdata,0);
7534 if (!VALID_STAT(smb_fname->st)) {
7535 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7538 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7539 !VALID_STAT_OF_DIR(smb_fname->st)) {
7540 return NT_STATUS_NOT_A_DIRECTORY;
7543 DEBUG(10,("smb_posix_unlink: %s %s\n",
7544 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7545 smb_fname_str_dbg(smb_fname)));
7547 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7548 create_options |= FILE_DIRECTORY_FILE;
7551 status = SMB_VFS_CREATE_FILE(
7552 conn, /* conn */
7553 req, /* req */
7554 0, /* root_dir_fid */
7555 smb_fname, /* fname */
7556 DELETE_ACCESS, /* access_mask */
7557 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7558 FILE_SHARE_DELETE),
7559 FILE_OPEN, /* create_disposition*/
7560 create_options, /* create_options */
7561 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7562 0, /* oplock_request */
7563 0, /* allocation_size */
7564 0, /* private_flags */
7565 NULL, /* sd */
7566 NULL, /* ea_list */
7567 &fsp, /* result */
7568 &info); /* pinfo */
7570 if (!NT_STATUS_IS_OK(status)) {
7571 return status;
7575 * Don't lie to client. If we can't really delete due to
7576 * non-POSIX opens return SHARING_VIOLATION.
7579 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7580 if (lck == NULL) {
7581 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7582 "lock for file %s\n", fsp_str_dbg(fsp)));
7583 close_file(req, fsp, NORMAL_CLOSE);
7584 return NT_STATUS_INVALID_PARAMETER;
7588 * See if others still have the file open. If this is the case, then
7589 * don't delete. If all opens are POSIX delete we can set the delete
7590 * on close disposition.
7592 for (i=0; i<lck->data->num_share_modes; i++) {
7593 struct share_mode_entry *e = &lck->data->share_modes[i];
7594 if (is_valid_share_mode_entry(e)) {
7595 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7596 continue;
7598 if (share_mode_stale_pid(lck->data, i)) {
7599 continue;
7601 /* Fail with sharing violation. */
7602 close_file(req, fsp, NORMAL_CLOSE);
7603 TALLOC_FREE(lck);
7604 return NT_STATUS_SHARING_VIOLATION;
7609 * Set the delete on close.
7611 status = smb_set_file_disposition_info(conn,
7612 &del,
7614 fsp,
7615 smb_fname);
7617 if (!NT_STATUS_IS_OK(status)) {
7618 close_file(req, fsp, NORMAL_CLOSE);
7619 TALLOC_FREE(lck);
7620 return status;
7622 TALLOC_FREE(lck);
7623 return close_file(req, fsp, NORMAL_CLOSE);
7626 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7627 struct smb_request *req,
7628 TALLOC_CTX *mem_ctx,
7629 uint16_t info_level,
7630 files_struct *fsp,
7631 struct smb_filename *smb_fname,
7632 char **ppdata, int total_data,
7633 int *ret_data_size)
7635 char *pdata = *ppdata;
7636 NTSTATUS status = NT_STATUS_OK;
7637 int data_return_size = 0;
7639 *ret_data_size = 0;
7641 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7642 return NT_STATUS_INVALID_LEVEL;
7645 if (!CAN_WRITE(conn)) {
7646 /* Allow POSIX opens. The open path will deny
7647 * any non-readonly opens. */
7648 if (info_level != SMB_POSIX_PATH_OPEN) {
7649 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7653 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7654 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7655 fsp_fnum_dbg(fsp),
7656 info_level, total_data));
7658 switch (info_level) {
7660 case SMB_INFO_STANDARD:
7662 status = smb_set_info_standard(conn,
7663 pdata,
7664 total_data,
7665 fsp,
7666 smb_fname);
7667 break;
7670 case SMB_INFO_SET_EA:
7672 status = smb_info_set_ea(conn,
7673 pdata,
7674 total_data,
7675 fsp,
7676 smb_fname);
7677 break;
7680 case SMB_SET_FILE_BASIC_INFO:
7681 case SMB_FILE_BASIC_INFORMATION:
7683 status = smb_set_file_basic_info(conn,
7684 pdata,
7685 total_data,
7686 fsp,
7687 smb_fname);
7688 break;
7691 case SMB_FILE_ALLOCATION_INFORMATION:
7692 case SMB_SET_FILE_ALLOCATION_INFO:
7694 status = smb_set_file_allocation_info(conn, req,
7695 pdata,
7696 total_data,
7697 fsp,
7698 smb_fname);
7699 break;
7702 case SMB_FILE_END_OF_FILE_INFORMATION:
7703 case SMB_SET_FILE_END_OF_FILE_INFO:
7706 * XP/Win7 both fail after the createfile with
7707 * SMB_SET_FILE_END_OF_FILE_INFO but not
7708 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7709 * The level is known here, so pass it down
7710 * appropriately.
7712 bool should_fail =
7713 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7715 status = smb_set_file_end_of_file_info(conn, req,
7716 pdata,
7717 total_data,
7718 fsp,
7719 smb_fname,
7720 should_fail);
7721 break;
7724 case SMB_FILE_DISPOSITION_INFORMATION:
7725 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7727 #if 0
7728 /* JRA - We used to just ignore this on a path ?
7729 * Shouldn't this be invalid level on a pathname
7730 * based call ?
7732 if (tran_call != TRANSACT2_SETFILEINFO) {
7733 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7735 #endif
7736 status = smb_set_file_disposition_info(conn,
7737 pdata,
7738 total_data,
7739 fsp,
7740 smb_fname);
7741 break;
7744 case SMB_FILE_POSITION_INFORMATION:
7746 status = smb_file_position_information(conn,
7747 pdata,
7748 total_data,
7749 fsp);
7750 break;
7753 case SMB_FILE_FULL_EA_INFORMATION:
7755 status = smb_set_file_full_ea_info(conn,
7756 pdata,
7757 total_data,
7758 fsp);
7759 break;
7762 /* From tridge Samba4 :
7763 * MODE_INFORMATION in setfileinfo (I have no
7764 * idea what "mode information" on a file is - it takes a value of 0,
7765 * 2, 4 or 6. What could it be?).
7768 case SMB_FILE_MODE_INFORMATION:
7770 status = smb_file_mode_information(conn,
7771 pdata,
7772 total_data);
7773 break;
7777 * CIFS UNIX extensions.
7780 case SMB_SET_FILE_UNIX_BASIC:
7782 status = smb_set_file_unix_basic(conn, req,
7783 pdata,
7784 total_data,
7785 fsp,
7786 smb_fname);
7787 break;
7790 case SMB_SET_FILE_UNIX_INFO2:
7792 status = smb_set_file_unix_info2(conn, req,
7793 pdata,
7794 total_data,
7795 fsp,
7796 smb_fname);
7797 break;
7800 case SMB_SET_FILE_UNIX_LINK:
7802 if (fsp) {
7803 /* We must have a pathname for this. */
7804 return NT_STATUS_INVALID_LEVEL;
7806 status = smb_set_file_unix_link(conn, req, pdata,
7807 total_data, smb_fname);
7808 break;
7811 case SMB_SET_FILE_UNIX_HLINK:
7813 if (fsp) {
7814 /* We must have a pathname for this. */
7815 return NT_STATUS_INVALID_LEVEL;
7817 status = smb_set_file_unix_hlink(conn, req,
7818 pdata, total_data,
7819 smb_fname);
7820 break;
7823 case SMB_FILE_RENAME_INFORMATION:
7825 status = smb_file_rename_information(conn, req,
7826 pdata, total_data,
7827 fsp, smb_fname);
7828 break;
7831 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7833 /* SMB2 rename information. */
7834 status = smb2_file_rename_information(conn, req,
7835 pdata, total_data,
7836 fsp, smb_fname);
7837 break;
7840 case SMB_FILE_LINK_INFORMATION:
7842 status = smb_file_link_information(conn, req,
7843 pdata, total_data,
7844 fsp, smb_fname);
7845 break;
7848 #if defined(HAVE_POSIX_ACLS)
7849 case SMB_SET_POSIX_ACL:
7851 status = smb_set_posix_acl(conn,
7852 pdata,
7853 total_data,
7854 fsp,
7855 smb_fname);
7856 break;
7858 #endif
7860 case SMB_SET_POSIX_LOCK:
7862 if (!fsp) {
7863 return NT_STATUS_INVALID_LEVEL;
7865 status = smb_set_posix_lock(conn, req,
7866 pdata, total_data, fsp);
7867 break;
7870 case SMB_POSIX_PATH_OPEN:
7872 if (fsp) {
7873 /* We must have a pathname for this. */
7874 return NT_STATUS_INVALID_LEVEL;
7877 status = smb_posix_open(conn, req,
7878 ppdata,
7879 total_data,
7880 smb_fname,
7881 &data_return_size);
7882 break;
7885 case SMB_POSIX_PATH_UNLINK:
7887 if (fsp) {
7888 /* We must have a pathname for this. */
7889 return NT_STATUS_INVALID_LEVEL;
7892 status = smb_posix_unlink(conn, req,
7893 pdata,
7894 total_data,
7895 smb_fname);
7896 break;
7899 default:
7900 return NT_STATUS_INVALID_LEVEL;
7903 if (!NT_STATUS_IS_OK(status)) {
7904 return status;
7907 *ret_data_size = data_return_size;
7908 return NT_STATUS_OK;
7911 /****************************************************************************
7912 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7913 ****************************************************************************/
7915 static void call_trans2setfilepathinfo(connection_struct *conn,
7916 struct smb_request *req,
7917 unsigned int tran_call,
7918 char **pparams, int total_params,
7919 char **ppdata, int total_data,
7920 unsigned int max_data_bytes)
7922 char *params = *pparams;
7923 char *pdata = *ppdata;
7924 uint16 info_level;
7925 struct smb_filename *smb_fname = NULL;
7926 files_struct *fsp = NULL;
7927 NTSTATUS status = NT_STATUS_OK;
7928 int data_return_size = 0;
7930 if (!params) {
7931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7932 return;
7935 if (tran_call == TRANSACT2_SETFILEINFO) {
7936 if (total_params < 4) {
7937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7938 return;
7941 fsp = file_fsp(req, SVAL(params,0));
7942 /* Basic check for non-null fsp. */
7943 if (!check_fsp_open(conn, req, fsp)) {
7944 return;
7946 info_level = SVAL(params,2);
7948 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7949 &smb_fname);
7950 if (!NT_STATUS_IS_OK(status)) {
7951 reply_nterror(req, status);
7952 return;
7955 if(fsp->fh->fd == -1) {
7957 * This is actually a SETFILEINFO on a directory
7958 * handle (returned from an NT SMB). NT5.0 seems
7959 * to do this call. JRA.
7961 if (INFO_LEVEL_IS_UNIX(info_level)) {
7962 /* Always do lstat for UNIX calls. */
7963 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7964 DEBUG(3,("call_trans2setfilepathinfo: "
7965 "SMB_VFS_LSTAT of %s failed "
7966 "(%s)\n",
7967 smb_fname_str_dbg(smb_fname),
7968 strerror(errno)));
7969 reply_nterror(req, map_nt_error_from_unix(errno));
7970 return;
7972 } else {
7973 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7974 DEBUG(3,("call_trans2setfilepathinfo: "
7975 "fileinfo of %s failed (%s)\n",
7976 smb_fname_str_dbg(smb_fname),
7977 strerror(errno)));
7978 reply_nterror(req, map_nt_error_from_unix(errno));
7979 return;
7982 } else if (fsp->print_file) {
7984 * Doing a DELETE_ON_CLOSE should cancel a print job.
7986 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7987 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7989 DEBUG(3,("call_trans2setfilepathinfo: "
7990 "Cancelling print job (%s)\n",
7991 fsp_str_dbg(fsp)));
7993 SSVAL(params,0,0);
7994 send_trans2_replies(conn, req, params, 2,
7995 *ppdata, 0,
7996 max_data_bytes);
7997 return;
7998 } else {
7999 reply_nterror(req,
8000 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8001 return;
8003 } else {
8005 * Original code - this is an open file.
8007 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8008 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8009 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8010 strerror(errno)));
8011 reply_nterror(req, map_nt_error_from_unix(errno));
8012 return;
8015 } else {
8016 char *fname = NULL;
8017 uint32_t ucf_flags = 0;
8019 /* set path info */
8020 if (total_params < 7) {
8021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8022 return;
8025 info_level = SVAL(params,0);
8026 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8027 total_params - 6, STR_TERMINATE,
8028 &status);
8029 if (!NT_STATUS_IS_OK(status)) {
8030 reply_nterror(req, status);
8031 return;
8034 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8035 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8036 info_level == SMB_FILE_RENAME_INFORMATION ||
8037 info_level == SMB_POSIX_PATH_UNLINK) {
8038 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8041 status = filename_convert(req, conn,
8042 req->flags2 & FLAGS2_DFS_PATHNAMES,
8043 fname,
8044 ucf_flags,
8045 NULL,
8046 &smb_fname);
8047 if (!NT_STATUS_IS_OK(status)) {
8048 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8049 reply_botherror(req,
8050 NT_STATUS_PATH_NOT_COVERED,
8051 ERRSRV, ERRbadpath);
8052 return;
8054 reply_nterror(req, status);
8055 return;
8058 if (INFO_LEVEL_IS_UNIX(info_level)) {
8060 * For CIFS UNIX extensions the target name may not exist.
8063 /* Always do lstat for UNIX calls. */
8064 SMB_VFS_LSTAT(conn, smb_fname);
8066 } else if (!VALID_STAT(smb_fname->st) &&
8067 SMB_VFS_STAT(conn, smb_fname)) {
8068 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8069 "%s failed (%s)\n",
8070 smb_fname_str_dbg(smb_fname),
8071 strerror(errno)));
8072 reply_nterror(req, map_nt_error_from_unix(errno));
8073 return;
8077 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8078 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8079 fsp_fnum_dbg(fsp),
8080 info_level,total_data));
8082 /* Realloc the parameter size */
8083 *pparams = (char *)SMB_REALLOC(*pparams,2);
8084 if (*pparams == NULL) {
8085 reply_nterror(req, NT_STATUS_NO_MEMORY);
8086 return;
8088 params = *pparams;
8090 SSVAL(params,0,0);
8092 status = smbd_do_setfilepathinfo(conn, req, req,
8093 info_level,
8094 fsp,
8095 smb_fname,
8096 ppdata, total_data,
8097 &data_return_size);
8098 if (!NT_STATUS_IS_OK(status)) {
8099 if (open_was_deferred(req->sconn, req->mid)) {
8100 /* We have re-scheduled this call. */
8101 return;
8103 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8104 /* We have re-scheduled this call. */
8105 return;
8107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8108 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8109 ERRSRV, ERRbadpath);
8110 return;
8112 if (info_level == SMB_POSIX_PATH_OPEN) {
8113 reply_openerror(req, status);
8114 return;
8117 reply_nterror(req, status);
8118 return;
8121 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8122 max_data_bytes);
8124 return;
8127 /****************************************************************************
8128 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8129 ****************************************************************************/
8131 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8132 char **pparams, int total_params,
8133 char **ppdata, int total_data,
8134 unsigned int max_data_bytes)
8136 struct smb_filename *smb_dname = NULL;
8137 char *params = *pparams;
8138 char *pdata = *ppdata;
8139 char *directory = NULL;
8140 NTSTATUS status = NT_STATUS_OK;
8141 struct ea_list *ea_list = NULL;
8142 TALLOC_CTX *ctx = talloc_tos();
8144 if (!CAN_WRITE(conn)) {
8145 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8146 return;
8149 if (total_params < 5) {
8150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8151 return;
8154 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8155 total_params - 4, STR_TERMINATE,
8156 &status);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 reply_nterror(req, status);
8159 return;
8162 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8164 status = filename_convert(ctx,
8165 conn,
8166 req->flags2 & FLAGS2_DFS_PATHNAMES,
8167 directory,
8169 NULL,
8170 &smb_dname);
8172 if (!NT_STATUS_IS_OK(status)) {
8173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8174 reply_botherror(req,
8175 NT_STATUS_PATH_NOT_COVERED,
8176 ERRSRV, ERRbadpath);
8177 return;
8179 reply_nterror(req, status);
8180 return;
8184 * OS/2 workplace shell seems to send SET_EA requests of "null"
8185 * length (4 bytes containing IVAL 4).
8186 * They seem to have no effect. Bug #3212. JRA.
8189 if (total_data && (total_data != 4)) {
8190 /* Any data in this call is an EA list. */
8191 if (total_data < 10) {
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 goto out;
8196 if (IVAL(pdata,0) > total_data) {
8197 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8198 IVAL(pdata,0), (unsigned int)total_data));
8199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8200 goto out;
8203 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8204 total_data - 4);
8205 if (!ea_list) {
8206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8207 goto out;
8210 if (!lp_ea_support(SNUM(conn))) {
8211 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8212 goto out;
8215 /* If total_data == 4 Windows doesn't care what values
8216 * are placed in that field, it just ignores them.
8217 * The System i QNTC IBM SMB client puts bad values here,
8218 * so ignore them. */
8220 status = create_directory(conn, req, smb_dname);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 reply_nterror(req, status);
8224 goto out;
8227 /* Try and set any given EA. */
8228 if (ea_list) {
8229 status = set_ea(conn, NULL, smb_dname, ea_list);
8230 if (!NT_STATUS_IS_OK(status)) {
8231 reply_nterror(req, status);
8232 goto out;
8236 /* Realloc the parameter and data sizes */
8237 *pparams = (char *)SMB_REALLOC(*pparams,2);
8238 if(*pparams == NULL) {
8239 reply_nterror(req, NT_STATUS_NO_MEMORY);
8240 goto out;
8242 params = *pparams;
8244 SSVAL(params,0,0);
8246 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8248 out:
8249 TALLOC_FREE(smb_dname);
8250 return;
8253 /****************************************************************************
8254 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8255 We don't actually do this - we just send a null response.
8256 ****************************************************************************/
8258 static void call_trans2findnotifyfirst(connection_struct *conn,
8259 struct smb_request *req,
8260 char **pparams, int total_params,
8261 char **ppdata, int total_data,
8262 unsigned int max_data_bytes)
8264 char *params = *pparams;
8265 uint16 info_level;
8267 if (total_params < 6) {
8268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8269 return;
8272 info_level = SVAL(params,4);
8273 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8275 switch (info_level) {
8276 case 1:
8277 case 2:
8278 break;
8279 default:
8280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8281 return;
8284 /* Realloc the parameter and data sizes */
8285 *pparams = (char *)SMB_REALLOC(*pparams,6);
8286 if (*pparams == NULL) {
8287 reply_nterror(req, NT_STATUS_NO_MEMORY);
8288 return;
8290 params = *pparams;
8292 SSVAL(params,0,fnf_handle);
8293 SSVAL(params,2,0); /* No changes */
8294 SSVAL(params,4,0); /* No EA errors */
8296 fnf_handle++;
8298 if(fnf_handle == 0)
8299 fnf_handle = 257;
8301 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8303 return;
8306 /****************************************************************************
8307 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8308 changes). Currently this does nothing.
8309 ****************************************************************************/
8311 static void call_trans2findnotifynext(connection_struct *conn,
8312 struct smb_request *req,
8313 char **pparams, int total_params,
8314 char **ppdata, int total_data,
8315 unsigned int max_data_bytes)
8317 char *params = *pparams;
8319 DEBUG(3,("call_trans2findnotifynext\n"));
8321 /* Realloc the parameter and data sizes */
8322 *pparams = (char *)SMB_REALLOC(*pparams,4);
8323 if (*pparams == NULL) {
8324 reply_nterror(req, NT_STATUS_NO_MEMORY);
8325 return;
8327 params = *pparams;
8329 SSVAL(params,0,0); /* No changes */
8330 SSVAL(params,2,0); /* No EA errors */
8332 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8334 return;
8337 /****************************************************************************
8338 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8339 ****************************************************************************/
8341 static void call_trans2getdfsreferral(connection_struct *conn,
8342 struct smb_request *req,
8343 char **pparams, int total_params,
8344 char **ppdata, int total_data,
8345 unsigned int max_data_bytes)
8347 char *params = *pparams;
8348 char *pathname = NULL;
8349 int reply_size = 0;
8350 int max_referral_level;
8351 NTSTATUS status = NT_STATUS_OK;
8352 TALLOC_CTX *ctx = talloc_tos();
8354 DEBUG(10,("call_trans2getdfsreferral\n"));
8356 if (total_params < 3) {
8357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 return;
8361 max_referral_level = SVAL(params,0);
8363 if(!lp_host_msdfs()) {
8364 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8365 return;
8368 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8369 total_params - 2, STR_TERMINATE);
8370 if (!pathname) {
8371 reply_nterror(req, NT_STATUS_NOT_FOUND);
8372 return;
8374 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8375 ppdata,&status)) < 0) {
8376 reply_nterror(req, status);
8377 return;
8380 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8381 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8382 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8384 return;
8387 #define LMCAT_SPL 0x53
8388 #define LMFUNC_GETJOBID 0x60
8390 /****************************************************************************
8391 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8392 ****************************************************************************/
8394 static void call_trans2ioctl(connection_struct *conn,
8395 struct smb_request *req,
8396 char **pparams, int total_params,
8397 char **ppdata, int total_data,
8398 unsigned int max_data_bytes)
8400 char *pdata = *ppdata;
8401 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8403 /* check for an invalid fid before proceeding */
8405 if (!fsp) {
8406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8407 return;
8410 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8411 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8412 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8413 if (*ppdata == NULL) {
8414 reply_nterror(req, NT_STATUS_NO_MEMORY);
8415 return;
8417 pdata = *ppdata;
8419 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8420 CAN ACCEPT THIS IN UNICODE. JRA. */
8422 /* Job number */
8423 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8425 srvstr_push(pdata, req->flags2, pdata + 2,
8426 lp_netbios_name(), 15,
8427 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8428 srvstr_push(pdata, req->flags2, pdata+18,
8429 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8430 STR_ASCII|STR_TERMINATE); /* Service name */
8431 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8432 max_data_bytes);
8433 return;
8436 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8437 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8440 /****************************************************************************
8441 Reply to a SMBfindclose (stop trans2 directory search).
8442 ****************************************************************************/
8444 void reply_findclose(struct smb_request *req)
8446 int dptr_num;
8447 struct smbd_server_connection *sconn = req->sconn;
8449 START_PROFILE(SMBfindclose);
8451 if (req->wct < 1) {
8452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8453 END_PROFILE(SMBfindclose);
8454 return;
8457 dptr_num = SVALS(req->vwv+0, 0);
8459 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8461 dptr_close(sconn, &dptr_num);
8463 reply_outbuf(req, 0, 0);
8465 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8467 END_PROFILE(SMBfindclose);
8468 return;
8471 /****************************************************************************
8472 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8473 ****************************************************************************/
8475 void reply_findnclose(struct smb_request *req)
8477 int dptr_num;
8479 START_PROFILE(SMBfindnclose);
8481 if (req->wct < 1) {
8482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8483 END_PROFILE(SMBfindnclose);
8484 return;
8487 dptr_num = SVAL(req->vwv+0, 0);
8489 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8491 /* We never give out valid handles for a
8492 findnotifyfirst - so any dptr_num is ok here.
8493 Just ignore it. */
8495 reply_outbuf(req, 0, 0);
8497 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8499 END_PROFILE(SMBfindnclose);
8500 return;
8503 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8504 struct trans_state *state)
8506 if (get_Protocol() >= PROTOCOL_NT1) {
8507 req->flags2 |= 0x40; /* IS_LONG_NAME */
8508 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8511 if (conn->encrypt_level == Required && !req->encrypted) {
8512 if (state->call != TRANSACT2_QFSINFO &&
8513 state->call != TRANSACT2_SETFSINFO) {
8514 DEBUG(0,("handle_trans2: encryption required "
8515 "with call 0x%x\n",
8516 (unsigned int)state->call));
8517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8518 return;
8522 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8524 /* Now we must call the relevant TRANS2 function */
8525 switch(state->call) {
8526 case TRANSACT2_OPEN:
8528 START_PROFILE(Trans2_open);
8529 call_trans2open(conn, req,
8530 &state->param, state->total_param,
8531 &state->data, state->total_data,
8532 state->max_data_return);
8533 END_PROFILE(Trans2_open);
8534 break;
8537 case TRANSACT2_FINDFIRST:
8539 START_PROFILE(Trans2_findfirst);
8540 call_trans2findfirst(conn, req,
8541 &state->param, state->total_param,
8542 &state->data, state->total_data,
8543 state->max_data_return);
8544 END_PROFILE(Trans2_findfirst);
8545 break;
8548 case TRANSACT2_FINDNEXT:
8550 START_PROFILE(Trans2_findnext);
8551 call_trans2findnext(conn, req,
8552 &state->param, state->total_param,
8553 &state->data, state->total_data,
8554 state->max_data_return);
8555 END_PROFILE(Trans2_findnext);
8556 break;
8559 case TRANSACT2_QFSINFO:
8561 START_PROFILE(Trans2_qfsinfo);
8562 call_trans2qfsinfo(conn, req,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_qfsinfo);
8567 break;
8570 case TRANSACT2_SETFSINFO:
8572 START_PROFILE(Trans2_setfsinfo);
8573 call_trans2setfsinfo(conn, req,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_setfsinfo);
8578 break;
8581 case TRANSACT2_QPATHINFO:
8582 case TRANSACT2_QFILEINFO:
8584 START_PROFILE(Trans2_qpathinfo);
8585 call_trans2qfilepathinfo(conn, req, state->call,
8586 &state->param, state->total_param,
8587 &state->data, state->total_data,
8588 state->max_data_return);
8589 END_PROFILE(Trans2_qpathinfo);
8590 break;
8593 case TRANSACT2_SETPATHINFO:
8594 case TRANSACT2_SETFILEINFO:
8596 START_PROFILE(Trans2_setpathinfo);
8597 call_trans2setfilepathinfo(conn, req, state->call,
8598 &state->param, state->total_param,
8599 &state->data, state->total_data,
8600 state->max_data_return);
8601 END_PROFILE(Trans2_setpathinfo);
8602 break;
8605 case TRANSACT2_FINDNOTIFYFIRST:
8607 START_PROFILE(Trans2_findnotifyfirst);
8608 call_trans2findnotifyfirst(conn, req,
8609 &state->param, state->total_param,
8610 &state->data, state->total_data,
8611 state->max_data_return);
8612 END_PROFILE(Trans2_findnotifyfirst);
8613 break;
8616 case TRANSACT2_FINDNOTIFYNEXT:
8618 START_PROFILE(Trans2_findnotifynext);
8619 call_trans2findnotifynext(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_findnotifynext);
8624 break;
8627 case TRANSACT2_MKDIR:
8629 START_PROFILE(Trans2_mkdir);
8630 call_trans2mkdir(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_mkdir);
8635 break;
8638 case TRANSACT2_GET_DFS_REFERRAL:
8640 START_PROFILE(Trans2_get_dfs_referral);
8641 call_trans2getdfsreferral(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_get_dfs_referral);
8646 break;
8649 case TRANSACT2_IOCTL:
8651 START_PROFILE(Trans2_ioctl);
8652 call_trans2ioctl(conn, req,
8653 &state->param, state->total_param,
8654 &state->data, state->total_data,
8655 state->max_data_return);
8656 END_PROFILE(Trans2_ioctl);
8657 break;
8660 default:
8661 /* Error in request */
8662 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8663 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8667 /****************************************************************************
8668 Reply to a SMBtrans2.
8669 ****************************************************************************/
8671 void reply_trans2(struct smb_request *req)
8673 connection_struct *conn = req->conn;
8674 unsigned int dsoff;
8675 unsigned int dscnt;
8676 unsigned int psoff;
8677 unsigned int pscnt;
8678 unsigned int tran_call;
8679 struct trans_state *state;
8680 NTSTATUS result;
8682 START_PROFILE(SMBtrans2);
8684 if (req->wct < 14) {
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686 END_PROFILE(SMBtrans2);
8687 return;
8690 dsoff = SVAL(req->vwv+12, 0);
8691 dscnt = SVAL(req->vwv+11, 0);
8692 psoff = SVAL(req->vwv+10, 0);
8693 pscnt = SVAL(req->vwv+9, 0);
8694 tran_call = SVAL(req->vwv+14, 0);
8696 result = allow_new_trans(conn->pending_trans, req->mid);
8697 if (!NT_STATUS_IS_OK(result)) {
8698 DEBUG(2, ("Got invalid trans2 request: %s\n",
8699 nt_errstr(result)));
8700 reply_nterror(req, result);
8701 END_PROFILE(SMBtrans2);
8702 return;
8705 if (IS_IPC(conn)) {
8706 switch (tran_call) {
8707 /* List the allowed trans2 calls on IPC$ */
8708 case TRANSACT2_OPEN:
8709 case TRANSACT2_GET_DFS_REFERRAL:
8710 case TRANSACT2_QFILEINFO:
8711 case TRANSACT2_QFSINFO:
8712 case TRANSACT2_SETFSINFO:
8713 break;
8714 default:
8715 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8716 END_PROFILE(SMBtrans2);
8717 return;
8721 if ((state = talloc(conn, struct trans_state)) == NULL) {
8722 DEBUG(0, ("talloc failed\n"));
8723 reply_nterror(req, NT_STATUS_NO_MEMORY);
8724 END_PROFILE(SMBtrans2);
8725 return;
8728 state->cmd = SMBtrans2;
8730 state->mid = req->mid;
8731 state->vuid = req->vuid;
8732 state->setup_count = SVAL(req->vwv+13, 0);
8733 state->setup = NULL;
8734 state->total_param = SVAL(req->vwv+0, 0);
8735 state->param = NULL;
8736 state->total_data = SVAL(req->vwv+1, 0);
8737 state->data = NULL;
8738 state->max_param_return = SVAL(req->vwv+2, 0);
8739 state->max_data_return = SVAL(req->vwv+3, 0);
8740 state->max_setup_return = SVAL(req->vwv+4, 0);
8741 state->close_on_completion = BITSETW(req->vwv+5, 0);
8742 state->one_way = BITSETW(req->vwv+5, 1);
8744 state->call = tran_call;
8746 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8747 is so as a sanity check */
8748 if (state->setup_count != 1) {
8750 * Need to have rc=0 for ioctl to get job id for OS/2.
8751 * Network printing will fail if function is not successful.
8752 * Similar function in reply.c will be used if protocol
8753 * is LANMAN1.0 instead of LM1.2X002.
8754 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8755 * outbuf doesn't have to be set(only job id is used).
8757 if ( (state->setup_count == 4)
8758 && (tran_call == TRANSACT2_IOCTL)
8759 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8760 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8761 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8762 } else {
8763 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8764 DEBUG(2,("Transaction is %d\n",tran_call));
8765 TALLOC_FREE(state);
8766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8767 END_PROFILE(SMBtrans2);
8768 return;
8772 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8773 goto bad_param;
8775 if (state->total_data) {
8777 if (trans_oob(state->total_data, 0, dscnt)
8778 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8779 goto bad_param;
8782 /* Can't use talloc here, the core routines do realloc on the
8783 * params and data. */
8784 state->data = (char *)SMB_MALLOC(state->total_data);
8785 if (state->data == NULL) {
8786 DEBUG(0,("reply_trans2: data malloc fail for %u "
8787 "bytes !\n", (unsigned int)state->total_data));
8788 TALLOC_FREE(state);
8789 reply_nterror(req, NT_STATUS_NO_MEMORY);
8790 END_PROFILE(SMBtrans2);
8791 return;
8794 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8797 if (state->total_param) {
8799 if (trans_oob(state->total_param, 0, pscnt)
8800 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8801 goto bad_param;
8804 /* Can't use talloc here, the core routines do realloc on the
8805 * params and data. */
8806 state->param = (char *)SMB_MALLOC(state->total_param);
8807 if (state->param == NULL) {
8808 DEBUG(0,("reply_trans: param malloc fail for %u "
8809 "bytes !\n", (unsigned int)state->total_param));
8810 SAFE_FREE(state->data);
8811 TALLOC_FREE(state);
8812 reply_nterror(req, NT_STATUS_NO_MEMORY);
8813 END_PROFILE(SMBtrans2);
8814 return;
8817 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8820 state->received_data = dscnt;
8821 state->received_param = pscnt;
8823 if ((state->received_param == state->total_param) &&
8824 (state->received_data == state->total_data)) {
8826 handle_trans2(conn, req, state);
8828 SAFE_FREE(state->data);
8829 SAFE_FREE(state->param);
8830 TALLOC_FREE(state);
8831 END_PROFILE(SMBtrans2);
8832 return;
8835 DLIST_ADD(conn->pending_trans, state);
8837 /* We need to send an interim response then receive the rest
8838 of the parameter/data bytes */
8839 reply_outbuf(req, 0, 0);
8840 show_msg((char *)req->outbuf);
8841 END_PROFILE(SMBtrans2);
8842 return;
8844 bad_param:
8846 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8847 SAFE_FREE(state->data);
8848 SAFE_FREE(state->param);
8849 TALLOC_FREE(state);
8850 END_PROFILE(SMBtrans2);
8851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8855 /****************************************************************************
8856 Reply to a SMBtranss2
8857 ****************************************************************************/
8859 void reply_transs2(struct smb_request *req)
8861 connection_struct *conn = req->conn;
8862 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8863 struct trans_state *state;
8865 START_PROFILE(SMBtranss2);
8867 show_msg((const char *)req->inbuf);
8869 /* Windows clients expect all replies to
8870 a transact secondary (SMBtranss2 0x33)
8871 to have a command code of transact
8872 (SMBtrans2 0x32). See bug #8989
8873 and also [MS-CIFS] section 2.2.4.47.2
8874 for details.
8876 req->cmd = SMBtrans2;
8878 if (req->wct < 8) {
8879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8880 END_PROFILE(SMBtranss2);
8881 return;
8884 for (state = conn->pending_trans; state != NULL;
8885 state = state->next) {
8886 if (state->mid == req->mid) {
8887 break;
8891 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8893 END_PROFILE(SMBtranss2);
8894 return;
8897 /* Revise state->total_param and state->total_data in case they have
8898 changed downwards */
8900 if (SVAL(req->vwv+0, 0) < state->total_param)
8901 state->total_param = SVAL(req->vwv+0, 0);
8902 if (SVAL(req->vwv+1, 0) < state->total_data)
8903 state->total_data = SVAL(req->vwv+1, 0);
8905 pcnt = SVAL(req->vwv+2, 0);
8906 poff = SVAL(req->vwv+3, 0);
8907 pdisp = SVAL(req->vwv+4, 0);
8909 dcnt = SVAL(req->vwv+5, 0);
8910 doff = SVAL(req->vwv+6, 0);
8911 ddisp = SVAL(req->vwv+7, 0);
8913 state->received_param += pcnt;
8914 state->received_data += dcnt;
8916 if ((state->received_data > state->total_data) ||
8917 (state->received_param > state->total_param))
8918 goto bad_param;
8920 if (pcnt) {
8921 if (trans_oob(state->total_param, pdisp, pcnt)
8922 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8923 goto bad_param;
8925 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8928 if (dcnt) {
8929 if (trans_oob(state->total_data, ddisp, dcnt)
8930 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8931 goto bad_param;
8933 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8936 if ((state->received_param < state->total_param) ||
8937 (state->received_data < state->total_data)) {
8938 END_PROFILE(SMBtranss2);
8939 return;
8942 handle_trans2(conn, req, state);
8944 DLIST_REMOVE(conn->pending_trans, state);
8945 SAFE_FREE(state->data);
8946 SAFE_FREE(state->param);
8947 TALLOC_FREE(state);
8949 END_PROFILE(SMBtranss2);
8950 return;
8952 bad_param:
8954 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8955 DLIST_REMOVE(conn->pending_trans, state);
8956 SAFE_FREE(state->data);
8957 SAFE_FREE(state->param);
8958 TALLOC_FREE(state);
8959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8960 END_PROFILE(SMBtranss2);
8961 return;