Split normal kinit from s4u2 flavored kinit
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob5cfbc3128bd39d4097a8a37dbb2f8175509a3e73
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"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 The canonical "check access" based on object handle or path function.
55 ********************************************************************/
57 NTSTATUS check_access(connection_struct *conn,
58 files_struct *fsp,
59 const struct smb_filename *smb_fname,
60 uint32_t access_mask)
62 if (fsp) {
63 if (!(fsp->access_mask & access_mask)) {
64 return NT_STATUS_ACCESS_DENIED;
66 } else {
67 NTSTATUS status = smbd_check_access_rights(conn,
68 smb_fname,
69 access_mask);
70 if (!NT_STATUS_IS_OK(status)) {
71 return status;
74 return NT_STATUS_OK;
77 /********************************************************************
78 Roundup a value to the nearest allocation roundup size boundary.
79 Only do this for Windows clients.
80 ********************************************************************/
82 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
84 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
86 /* Only roundup for Windows clients. */
87 enum remote_arch_types ra_type = get_remote_arch();
88 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
89 val = SMB_ROUNDUP(val,rval);
91 return val;
94 /********************************************************************
95 Create a 64 bit FileIndex. If the file is on the same device as
96 the root of the share, just return the 64-bit inode. If it isn't,
97 mangle as we used to do.
98 ********************************************************************/
100 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
102 uint64_t file_index;
103 if (conn->base_share_dev == psbuf->st_ex_dev) {
104 return (uint64_t)psbuf->st_ex_ino;
106 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
107 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
108 return file_index;
111 /****************************************************************************
112 Utility functions for dealing with extended attributes.
113 ****************************************************************************/
115 /****************************************************************************
116 Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
119 static bool samba_private_attr_name(const char *unix_ea_name)
121 static const char * const prohibited_ea_names[] = {
122 SAMBA_POSIX_INHERITANCE_EA_NAME,
123 SAMBA_XATTR_DOS_ATTRIB,
124 SAMBA_XATTR_MARKER,
125 XATTR_NTACL_NAME,
126 NULL
129 int i;
131 for (i = 0; prohibited_ea_names[i]; i++) {
132 if (strequal( prohibited_ea_names[i], unix_ea_name))
133 return true;
135 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
136 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
137 return true;
139 return false;
142 /****************************************************************************
143 Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
146 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 const char *ea_name, struct ea_struct *pea)
150 /* Get the value of this xattr. Max size is 64k. */
151 size_t attr_size = 256;
152 char *val = NULL;
153 ssize_t sizeret;
155 again:
157 val = talloc_realloc(mem_ctx, val, char, attr_size);
158 if (!val) {
159 return NT_STATUS_NO_MEMORY;
162 if (fsp && fsp->fh->fd != -1) {
163 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
164 } else {
165 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
168 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
169 attr_size = 65536;
170 goto again;
173 if (sizeret == -1) {
174 return map_nt_error_from_unix(errno);
177 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
178 dump_data(10, (uint8 *)val, sizeret);
180 pea->flags = 0;
181 if (strnequal(ea_name, "user.", 5)) {
182 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
183 } else {
184 pea->name = talloc_strdup(mem_ctx, ea_name);
186 if (pea->name == NULL) {
187 TALLOC_FREE(val);
188 return NT_STATUS_NO_MEMORY;
190 pea->value.data = (unsigned char *)val;
191 pea->value.length = (size_t)sizeret;
192 return NT_STATUS_OK;
195 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
196 files_struct *fsp, const char *fname,
197 char ***pnames, size_t *pnum_names)
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size = 1024;
201 char *ea_namelist = NULL;
203 char *p;
204 char **names, **tmp;
205 size_t num_names;
206 ssize_t sizeret = -1;
208 if (!lp_ea_support(SNUM(conn))) {
209 if (pnames) {
210 *pnames = NULL;
212 *pnum_names = 0;
213 return NT_STATUS_OK;
217 * TALLOC the result early to get the talloc hierarchy right.
220 names = talloc_array(mem_ctx, char *, 1);
221 if (names == NULL) {
222 DEBUG(0, ("talloc failed\n"));
223 return NT_STATUS_NO_MEMORY;
226 while (ea_namelist_size <= 65536) {
228 ea_namelist = talloc_realloc(
229 names, ea_namelist, char, ea_namelist_size);
230 if (ea_namelist == NULL) {
231 DEBUG(0, ("talloc failed\n"));
232 TALLOC_FREE(names);
233 return NT_STATUS_NO_MEMORY;
236 if (fsp && fsp->fh->fd != -1) {
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238 ea_namelist_size);
239 } else {
240 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
241 ea_namelist_size);
244 if ((sizeret == -1) && (errno == ERANGE)) {
245 ea_namelist_size *= 2;
247 else {
248 break;
252 if (sizeret == -1) {
253 TALLOC_FREE(names);
254 return map_nt_error_from_unix(errno);
257 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258 (unsigned int)sizeret));
260 if (sizeret == 0) {
261 TALLOC_FREE(names);
262 if (pnames) {
263 *pnames = NULL;
265 *pnum_names = 0;
266 return NT_STATUS_OK;
270 * Ensure the result is 0-terminated
273 if (ea_namelist[sizeret-1] != '\0') {
274 TALLOC_FREE(names);
275 return NT_STATUS_INTERNAL_ERROR;
279 * count the names
281 num_names = 0;
283 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
284 num_names += 1;
287 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
288 if (tmp == NULL) {
289 DEBUG(0, ("talloc failed\n"));
290 TALLOC_FREE(names);
291 return NT_STATUS_NO_MEMORY;
294 names = tmp;
295 num_names = 0;
297 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298 names[num_names++] = p;
301 if (pnames) {
302 *pnames = names;
303 } else {
304 TALLOC_FREE(names);
306 *pnum_names = num_names;
307 return NT_STATUS_OK;
310 /****************************************************************************
311 Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
314 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
315 const char *fname, size_t *pea_total_len)
317 /* Get a list of all xattrs. Max namesize is 64k. */
318 size_t i, num_names;
319 char **names;
320 struct ea_list *ea_list_head = NULL;
321 NTSTATUS status;
323 *pea_total_len = 0;
325 if (!lp_ea_support(SNUM(conn))) {
326 return NULL;
329 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
330 &names, &num_names);
332 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
333 return NULL;
336 for (i=0; i<num_names; i++) {
337 struct ea_list *listp;
338 fstring dos_ea_name;
340 if (strnequal(names[i], "system.", 7)
341 || samba_private_attr_name(names[i]))
342 continue;
344 listp = talloc(mem_ctx, struct ea_list);
345 if (listp == NULL) {
346 return NULL;
349 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
350 fname, names[i],
351 &listp->ea))) {
352 return NULL;
355 push_ascii_fstring(dos_ea_name, listp->ea.name);
357 *pea_total_len +=
358 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
360 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
362 (unsigned int)listp->ea.value.length));
364 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
368 /* Add on 4 for total length. */
369 if (*pea_total_len) {
370 *pea_total_len += 4;
373 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374 (unsigned int)*pea_total_len));
376 return ea_list_head;
379 /****************************************************************************
380 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
381 that was filled.
382 ****************************************************************************/
384 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
385 connection_struct *conn, struct ea_list *ea_list)
387 unsigned int ret_data_size = 4;
388 char *p = pdata;
390 SMB_ASSERT(total_data_size >= 4);
392 if (!lp_ea_support(SNUM(conn))) {
393 SIVAL(pdata,4,0);
394 return 4;
397 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
398 size_t dos_namelen;
399 fstring dos_ea_name;
400 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
401 dos_namelen = strlen(dos_ea_name);
402 if (dos_namelen > 255 || dos_namelen == 0) {
403 break;
405 if (ea_list->ea.value.length > 65535) {
406 break;
408 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
409 break;
412 /* We know we have room. */
413 SCVAL(p,0,ea_list->ea.flags);
414 SCVAL(p,1,dos_namelen);
415 SSVAL(p,2,ea_list->ea.value.length);
416 strlcpy(p+4, dos_ea_name, dos_namelen+1);
417 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
419 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
420 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
423 ret_data_size = PTR_DIFF(p, pdata);
424 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
425 SIVAL(pdata,0,ret_data_size);
426 return ret_data_size;
429 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
430 char *pdata,
431 unsigned int total_data_size,
432 unsigned int *ret_data_size,
433 connection_struct *conn,
434 struct ea_list *ea_list)
436 uint8_t *p = (uint8_t *)pdata;
437 uint8_t *last_start = NULL;
439 *ret_data_size = 0;
441 if (!lp_ea_support(SNUM(conn))) {
442 return NT_STATUS_NO_EAS_ON_FILE;
445 for (; ea_list; ea_list = ea_list->next) {
446 size_t dos_namelen;
447 fstring dos_ea_name;
448 size_t this_size;
450 if (last_start) {
451 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
453 last_start = p;
455 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
456 dos_namelen = strlen(dos_ea_name);
457 if (dos_namelen > 255 || dos_namelen == 0) {
458 return NT_STATUS_INTERNAL_ERROR;
460 if (ea_list->ea.value.length > 65535) {
461 return NT_STATUS_INTERNAL_ERROR;
464 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
466 if (ea_list->next) {
467 size_t pad = 4 - (this_size % 4);
468 this_size += pad;
471 if (this_size > total_data_size) {
472 return NT_STATUS_INFO_LENGTH_MISMATCH;
475 /* We know we have room. */
476 SIVAL(p, 0x00, 0); /* next offset */
477 SCVAL(p, 0x04, ea_list->ea.flags);
478 SCVAL(p, 0x05, dos_namelen);
479 SSVAL(p, 0x06, ea_list->ea.value.length);
480 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
481 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
483 total_data_size -= this_size;
484 p += this_size;
487 *ret_data_size = PTR_DIFF(p, pdata);
488 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
489 return NT_STATUS_OK;
492 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
494 size_t total_ea_len = 0;
495 TALLOC_CTX *mem_ctx = NULL;
497 if (!lp_ea_support(SNUM(conn))) {
498 return 0;
500 mem_ctx = talloc_tos();
501 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
502 return total_ea_len;
505 /****************************************************************************
506 Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
509 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
511 size_t total_ea_len;
512 TALLOC_CTX *mem_ctx = talloc_tos();
513 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
515 for (; ea_list; ea_list = ea_list->next) {
516 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
517 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518 &unix_ea_name[5], ea_list->ea.name));
519 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
520 break;
525 /****************************************************************************
526 Set or delete an extended attribute.
527 ****************************************************************************/
529 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
530 const struct smb_filename *smb_fname, struct ea_list *ea_list)
532 NTSTATUS status;
533 char *fname = NULL;
535 if (!lp_ea_support(SNUM(conn))) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
540 if (!NT_STATUS_IS_OK(status)) {
541 return status;
544 /* For now setting EAs on streams isn't supported. */
545 fname = smb_fname->base_name;
547 for (;ea_list; ea_list = ea_list->next) {
548 int ret;
549 fstring unix_ea_name;
551 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
552 fstrcat(unix_ea_name, ea_list->ea.name);
554 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
556 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
558 if (samba_private_attr_name(unix_ea_name)) {
559 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
560 return NT_STATUS_ACCESS_DENIED;
563 if (ea_list->ea.value.length == 0) {
564 /* Remove the attribute. */
565 if (fsp && (fsp->fh->fd != -1)) {
566 DEBUG(10,("set_ea: deleting ea name %s on "
567 "file %s by file descriptor.\n",
568 unix_ea_name, fsp_str_dbg(fsp)));
569 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
570 } else {
571 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572 unix_ea_name, fname));
573 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
575 #ifdef ENOATTR
576 /* Removing a non existent attribute always succeeds. */
577 if (ret == -1 && errno == ENOATTR) {
578 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
579 unix_ea_name));
580 ret = 0;
582 #endif
583 } else {
584 if (fsp && (fsp->fh->fd != -1)) {
585 DEBUG(10,("set_ea: setting ea name %s on file "
586 "%s by file descriptor.\n",
587 unix_ea_name, fsp_str_dbg(fsp)));
588 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
589 ea_list->ea.value.data, ea_list->ea.value.length, 0);
590 } else {
591 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592 unix_ea_name, fname));
593 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
594 ea_list->ea.value.data, ea_list->ea.value.length, 0);
598 if (ret == -1) {
599 #ifdef ENOTSUP
600 if (errno == ENOTSUP) {
601 return NT_STATUS_EAS_NOT_SUPPORTED;
603 #endif
604 return map_nt_error_from_unix(errno);
608 return NT_STATUS_OK;
610 /****************************************************************************
611 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
614 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
616 struct ea_list *ea_list_head = NULL;
617 size_t converted_size, offset = 0;
619 while (offset + 2 < data_size) {
620 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
621 unsigned int namelen = CVAL(pdata,offset);
623 offset++; /* Go past the namelen byte. */
625 /* integer wrap paranioa. */
626 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
627 (offset > data_size) || (namelen > data_size) ||
628 (offset + namelen >= data_size)) {
629 break;
631 /* Ensure the name is null terminated. */
632 if (pdata[offset + namelen] != '\0') {
633 return NULL;
635 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
636 &converted_size)) {
637 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638 "failed: %s", strerror(errno)));
640 if (!eal->ea.name) {
641 return NULL;
644 offset += (namelen + 1); /* Go past the name + terminating zero. */
645 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
646 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
649 return ea_list_head;
652 /****************************************************************************
653 Read one EA list entry from the buffer.
654 ****************************************************************************/
656 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
658 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
659 uint16 val_len;
660 unsigned int namelen;
661 size_t converted_size;
663 if (!eal) {
664 return NULL;
667 if (data_size < 6) {
668 return NULL;
671 eal->ea.flags = CVAL(pdata,0);
672 namelen = CVAL(pdata,1);
673 val_len = SVAL(pdata,2);
675 if (4 + namelen + 1 + val_len > data_size) {
676 return NULL;
679 /* Ensure the name is null terminated. */
680 if (pdata[namelen + 4] != '\0') {
681 return NULL;
683 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
684 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
685 strerror(errno)));
687 if (!eal->ea.name) {
688 return NULL;
691 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
692 if (!eal->ea.value.data) {
693 return NULL;
696 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
698 /* Ensure we're null terminated just in case we print the value. */
699 eal->ea.value.data[val_len] = '\0';
700 /* But don't count the null. */
701 eal->ea.value.length--;
703 if (pbytes_used) {
704 *pbytes_used = 4 + namelen + 1 + val_len;
707 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
708 dump_data(10, eal->ea.value.data, eal->ea.value.length);
710 return eal;
713 /****************************************************************************
714 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
717 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
719 struct ea_list *ea_list_head = NULL;
720 size_t offset = 0;
721 size_t bytes_used = 0;
723 while (offset < data_size) {
724 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
726 if (!eal) {
727 return NULL;
730 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
731 offset += bytes_used;
734 return ea_list_head;
737 /****************************************************************************
738 Count the total EA size needed.
739 ****************************************************************************/
741 static size_t ea_list_size(struct ea_list *ealist)
743 fstring dos_ea_name;
744 struct ea_list *listp;
745 size_t ret = 0;
747 for (listp = ealist; listp; listp = listp->next) {
748 push_ascii_fstring(dos_ea_name, listp->ea.name);
749 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
751 /* Add on 4 for total length. */
752 if (ret) {
753 ret += 4;
756 return ret;
759 /****************************************************************************
760 Return a union of EA's from a file list and a list of names.
761 The TALLOC context for the two lists *MUST* be identical as we steal
762 memory from one list to add to another. JRA.
763 ****************************************************************************/
765 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
767 struct ea_list *nlistp, *flistp;
769 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
770 for (flistp = file_list; flistp; flistp = flistp->next) {
771 if (strequal(nlistp->ea.name, flistp->ea.name)) {
772 break;
776 if (flistp) {
777 /* Copy the data from this entry. */
778 nlistp->ea.flags = flistp->ea.flags;
779 nlistp->ea.value = flistp->ea.value;
780 } else {
781 /* Null entry. */
782 nlistp->ea.flags = 0;
783 ZERO_STRUCT(nlistp->ea.value);
787 *total_ea_len = ea_list_size(name_list);
788 return name_list;
791 /****************************************************************************
792 Send the required number of replies back.
793 We assume all fields other than the data fields are
794 set correctly for the type of call.
795 HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
798 void send_trans2_replies(connection_struct *conn,
799 struct smb_request *req,
800 const char *params,
801 int paramsize,
802 const char *pdata,
803 int datasize,
804 int max_data_bytes)
806 /* As we are using a protocol > LANMAN1 then the max_send
807 variable must have been set in the sessetupX call.
808 This takes precedence over the max_xmit field in the
809 global struct. These different max_xmit variables should
810 be merged as this is now too confusing */
812 int data_to_send = datasize;
813 int params_to_send = paramsize;
814 int useable_space;
815 const char *pp = params;
816 const char *pd = pdata;
817 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
818 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819 int data_alignment_offset = 0;
820 bool overflow = False;
821 struct smbd_server_connection *sconn = req->sconn;
822 int max_send = sconn->smb1.sessions.max_send;
824 /* Modify the data_to_send and datasize and set the error if
825 we're trying to send more than max_data_bytes. We still send
826 the part of the packet(s) that fit. Strange, but needed
827 for OS/2. */
829 if (max_data_bytes > 0 && datasize > max_data_bytes) {
830 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831 max_data_bytes, datasize ));
832 datasize = data_to_send = max_data_bytes;
833 overflow = True;
836 /* If there genuinely are no parameters or data to send just send the empty packet */
838 if(params_to_send == 0 && data_to_send == 0) {
839 reply_outbuf(req, 10, 0);
840 show_msg((char *)req->outbuf);
841 if (!srv_send_smb(sconn,
842 (char *)req->outbuf,
843 true, req->seqnum+1,
844 IS_CONN_ENCRYPTED(conn),
845 &req->pcd)) {
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
849 return;
852 /* When sending params and data ensure that both are nicely aligned */
853 /* Only do this alignment when there is also data to send - else
854 can cause NT redirector problems. */
856 if (((params_to_send % 4) != 0) && (data_to_send != 0))
857 data_alignment_offset = 4 - (params_to_send % 4);
859 /* Space is bufsize minus Netbios over TCP header minus SMB header */
860 /* The alignment_offset is to align the param bytes on an even byte
861 boundary. NT 4.0 Beta needs this to work correctly. */
863 useable_space = max_send - (smb_size
864 + 2 * 10 /* wct */
865 + alignment_offset
866 + data_alignment_offset);
868 if (useable_space < 0) {
869 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870 "= %d!!!", useable_space));
871 exit_server_cleanly("send_trans2_replies: Not enough space");
874 while (params_to_send || data_to_send) {
875 /* Calculate whether we will totally or partially fill this packet */
877 total_sent_thistime = params_to_send + data_to_send;
879 /* We can never send more than useable_space */
881 * Note that 'useable_space' does not include the alignment offsets,
882 * but we must include the alignment offsets in the calculation of
883 * the length of the data we send over the wire, as the alignment offsets
884 * are sent here. Fix from Marc_Jacobsen@hp.com.
887 total_sent_thistime = MIN(total_sent_thistime, useable_space);
889 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
890 + data_alignment_offset);
893 * We might have SMBtrans2s in req which was transferred to
894 * the outbuf, fix that.
896 SCVAL(req->outbuf, smb_com, SMBtrans2);
898 /* Set total params and data to be sent */
899 SSVAL(req->outbuf,smb_tprcnt,paramsize);
900 SSVAL(req->outbuf,smb_tdrcnt,datasize);
902 /* Calculate how many parameters and data we can fit into
903 * this packet. Parameters get precedence
906 params_sent_thistime = MIN(params_to_send,useable_space);
907 data_sent_thistime = useable_space - params_sent_thistime;
908 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
910 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
912 /* smb_proff is the offset from the start of the SMB header to the
913 parameter bytes, however the first 4 bytes of outbuf are
914 the Netbios over TCP header. Thus use smb_base() to subtract
915 them from the calculation */
917 SSVAL(req->outbuf,smb_proff,
918 ((smb_buf(req->outbuf)+alignment_offset)
919 - smb_base(req->outbuf)));
921 if(params_sent_thistime == 0)
922 SSVAL(req->outbuf,smb_prdisp,0);
923 else
924 /* Absolute displacement of param bytes sent in this packet */
925 SSVAL(req->outbuf,smb_prdisp,pp - params);
927 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
928 if(data_sent_thistime == 0) {
929 SSVAL(req->outbuf,smb_droff,0);
930 SSVAL(req->outbuf,smb_drdisp, 0);
931 } else {
932 /* The offset of the data bytes is the offset of the
933 parameter bytes plus the number of parameters being sent this time */
934 SSVAL(req->outbuf, smb_droff,
935 ((smb_buf(req->outbuf)+alignment_offset)
936 - smb_base(req->outbuf))
937 + params_sent_thistime + data_alignment_offset);
938 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
941 /* Initialize the padding for alignment */
943 if (alignment_offset != 0) {
944 memset(smb_buf(req->outbuf), 0, alignment_offset);
947 /* Copy the param bytes into the packet */
949 if(params_sent_thistime) {
950 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
951 params_sent_thistime);
954 /* Copy in the data bytes */
955 if(data_sent_thistime) {
956 if (data_alignment_offset != 0) {
957 memset((smb_buf(req->outbuf)+alignment_offset+
958 params_sent_thistime), 0,
959 data_alignment_offset);
961 memcpy(smb_buf(req->outbuf)+alignment_offset
962 +params_sent_thistime+data_alignment_offset,
963 pd,data_sent_thistime);
966 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967 params_sent_thistime, data_sent_thistime, useable_space));
968 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969 params_to_send, data_to_send, paramsize, datasize));
971 if (overflow) {
972 error_packet_set((char *)req->outbuf,
973 ERRDOS,ERRbufferoverflow,
974 STATUS_BUFFER_OVERFLOW,
975 __LINE__,__FILE__);
978 /* Send the packet */
979 show_msg((char *)req->outbuf);
980 if (!srv_send_smb(sconn,
981 (char *)req->outbuf,
982 true, req->seqnum+1,
983 IS_CONN_ENCRYPTED(conn),
984 &req->pcd))
985 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
987 TALLOC_FREE(req->outbuf);
989 pp += params_sent_thistime;
990 pd += data_sent_thistime;
992 params_to_send -= params_sent_thistime;
993 data_to_send -= data_sent_thistime;
995 /* Sanity check */
996 if(params_to_send < 0 || data_to_send < 0) {
997 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998 params_to_send, data_to_send));
999 return;
1003 return;
1006 /****************************************************************************
1007 Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1010 static void call_trans2open(connection_struct *conn,
1011 struct smb_request *req,
1012 char **pparams, int total_params,
1013 char **ppdata, int total_data,
1014 unsigned int max_data_bytes)
1016 struct smb_filename *smb_fname = NULL;
1017 char *params = *pparams;
1018 char *pdata = *ppdata;
1019 int deny_mode;
1020 int32 open_attr;
1021 bool oplock_request;
1022 #if 0
1023 bool return_additional_info;
1024 int16 open_sattr;
1025 time_t open_time;
1026 #endif
1027 int open_ofun;
1028 uint32 open_size;
1029 char *pname;
1030 char *fname = NULL;
1031 off_t size=0;
1032 int fattr=0,mtime=0;
1033 SMB_INO_T inode = 0;
1034 int smb_action = 0;
1035 files_struct *fsp;
1036 struct ea_list *ea_list = NULL;
1037 uint16 flags = 0;
1038 NTSTATUS status;
1039 uint32 access_mask;
1040 uint32 share_mode;
1041 uint32 create_disposition;
1042 uint32 create_options = 0;
1043 uint32_t private_flags = 0;
1044 TALLOC_CTX *ctx = talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params < 29) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 goto out;
1055 flags = SVAL(params, 0);
1056 deny_mode = SVAL(params, 2);
1057 open_attr = SVAL(params,6);
1058 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1059 if (oplock_request) {
1060 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1063 #if 0
1064 return_additional_info = BITSETW(params,0);
1065 open_sattr = SVAL(params, 4);
1066 open_time = make_unix_date3(params+8);
1067 #endif
1068 open_ofun = SVAL(params,12);
1069 open_size = IVAL(params,14);
1070 pname = &params[28];
1072 if (IS_IPC(conn)) {
1073 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1074 goto out;
1077 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1078 total_params - 28, STR_TERMINATE,
1079 &status);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 reply_nterror(req, status);
1082 goto out;
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1087 (unsigned int)open_ofun, open_size));
1089 status = filename_convert(ctx,
1090 conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092 fname,
1094 NULL,
1095 &smb_fname);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req,
1099 NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 goto out;
1103 reply_nterror(req, status);
1104 goto out;
1107 if (open_ofun == 0) {
1108 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1109 goto out;
1112 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1113 open_ofun,
1114 &access_mask, &share_mode,
1115 &create_disposition,
1116 &create_options,
1117 &private_flags)) {
1118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1119 goto out;
1122 /* Any data in this call is an EA list. */
1123 if (total_data && (total_data != 4)) {
1124 if (total_data < 10) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126 goto out;
1129 if (IVAL(pdata,0) > total_data) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata,0), (unsigned int)total_data));
1132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1133 goto out;
1136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1137 total_data - 4);
1138 if (!ea_list) {
1139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1140 goto out;
1143 if (!lp_ea_support(SNUM(conn))) {
1144 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1145 goto out;
1149 status = SMB_VFS_CREATE_FILE(
1150 conn, /* conn */
1151 req, /* req */
1152 0, /* root_dir_fid */
1153 smb_fname, /* fname */
1154 access_mask, /* access_mask */
1155 share_mode, /* share_access */
1156 create_disposition, /* create_disposition*/
1157 create_options, /* create_options */
1158 open_attr, /* file_attributes */
1159 oplock_request, /* oplock_request */
1160 open_size, /* allocation_size */
1161 private_flags,
1162 NULL, /* sd */
1163 ea_list, /* ea_list */
1164 &fsp, /* result */
1165 &smb_action); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (open_was_deferred(req->sconn, req->mid)) {
1169 /* We have re-scheduled this call. */
1170 goto out;
1172 reply_openerror(req, status);
1173 goto out;
1176 size = get_file_size_stat(&smb_fname->st);
1177 fattr = dos_mode(conn, smb_fname);
1178 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1179 inode = smb_fname->st.st_ex_ino;
1180 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1181 close_file(req, fsp, ERROR_CLOSE);
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1183 goto out;
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1188 if(*pparams == NULL ) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1190 goto out;
1192 params = *pparams;
1194 SSVAL(params,0,fsp->fnum);
1195 SSVAL(params,2,fattr);
1196 srv_put_dos_date2(params,4, mtime);
1197 SIVAL(params,8, (uint32)size);
1198 SSVAL(params,12,deny_mode);
1199 SSVAL(params,14,0); /* open_type - file or directory. */
1200 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1206 SSVAL(params,18,smb_action);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params,20,inode);
1212 SSVAL(params,24,0); /* Padding. */
1213 if (flags & 8) {
1214 uint32 ea_size = estimate_ea_size(conn, fsp,
1215 fsp->fsp_name->base_name);
1216 SIVAL(params, 26, ea_size);
1217 } else {
1218 SIVAL(params, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1223 out:
1224 TALLOC_FREE(smb_fname);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild,
1235 bool case_sensitive,
1236 const char *str,
1237 const char *mask)
1239 if (mask[0] == '.' && mask[1] == 0) {
1240 return false;
1243 if (has_wild) {
1244 return false;
1247 if (case_sensitive) {
1248 return strcmp(str,mask)==0;
1249 } else {
1250 return strcasecmp_m(str,mask) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32 unix_filetype(mode_t mode)
1260 if(S_ISREG(mode))
1261 return UNIX_TYPE_FILE;
1262 else if(S_ISDIR(mode))
1263 return UNIX_TYPE_DIR;
1264 #ifdef S_ISLNK
1265 else if(S_ISLNK(mode))
1266 return UNIX_TYPE_SYMLINK;
1267 #endif
1268 #ifdef S_ISCHR
1269 else if(S_ISCHR(mode))
1270 return UNIX_TYPE_CHARDEV;
1271 #endif
1272 #ifdef S_ISBLK
1273 else if(S_ISBLK(mode))
1274 return UNIX_TYPE_BLKDEV;
1275 #endif
1276 #ifdef S_ISFIFO
1277 else if(S_ISFIFO(mode))
1278 return UNIX_TYPE_FIFO;
1279 #endif
1280 #ifdef S_ISSOCK
1281 else if(S_ISSOCK(mode))
1282 return UNIX_TYPE_SOCKET;
1283 #endif
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1286 return UNIX_TYPE_UNKNOWN;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1295 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1296 const SMB_STRUCT_STAT *psbuf,
1297 uint32 perms,
1298 enum perm_type ptype,
1299 mode_t *ret_perms)
1301 mode_t ret = 0;
1303 if (perms == SMB_MODE_NO_CHANGE) {
1304 if (!VALID_STAT(*psbuf)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1306 } else {
1307 *ret_perms = psbuf->st_ex_mode;
1308 return NT_STATUS_OK;
1312 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1313 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1314 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1315 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1316 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1317 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1318 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1319 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1320 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1321 #ifdef S_ISVTX
1322 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1323 #endif
1324 #ifdef S_ISGID
1325 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1326 #endif
1327 #ifdef S_ISUID
1328 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1329 #endif
1331 switch (ptype) {
1332 case PERM_NEW_FILE:
1333 /* Apply mode mask */
1334 ret &= lp_create_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_create_mode(SNUM(conn));
1337 break;
1338 case PERM_NEW_DIR:
1339 ret &= lp_dir_mask(SNUM(conn));
1340 /* Add in force bits */
1341 ret |= lp_force_dir_mode(SNUM(conn));
1342 break;
1343 case PERM_EXISTING_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_security_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_security_mode(SNUM(conn));
1348 break;
1349 case PERM_EXISTING_DIR:
1350 /* Apply mode mask */
1351 ret &= lp_dir_security_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_security_mode(SNUM(conn));
1354 break;
1357 *ret_perms = ret;
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct *conn,
1367 const char *pathname,
1368 SMB_STRUCT_STAT *psbuf)
1370 int saved_errno = errno;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn)) &&
1373 is_msdfs_link(conn, pathname, psbuf)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1376 "as a directory\n",
1377 pathname));
1378 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1379 errno = saved_errno;
1380 return true;
1382 errno = saved_errno;
1383 return false;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state {
1392 connection_struct *conn;
1393 uint32_t info_level;
1394 bool check_mangled_names;
1395 bool has_wild;
1396 bool got_exact_match;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1400 void *private_data,
1401 const char *dname,
1402 const char *mask,
1403 char **_fname)
1405 struct smbd_dirptr_lanman2_state *state =
1406 (struct smbd_dirptr_lanman2_state *)private_data;
1407 bool ok;
1408 char mangled_name[13]; /* mangled 8.3 name. */
1409 bool got_match;
1410 const char *fname;
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname, state->conn->params)) {
1414 ok = name_to_8_3(dname, mangled_name,
1415 true, state->conn->params);
1416 if (!ok) {
1417 return false;
1419 fname = mangled_name;
1420 } else {
1421 fname = dname;
1424 got_match = exact_match(state->has_wild,
1425 state->conn->case_sensitive,
1426 fname, mask);
1427 state->got_exact_match = got_match;
1428 if (!got_match) {
1429 got_match = mask_match(fname, mask,
1430 state->conn->case_sensitive);
1433 if(!got_match && state->check_mangled_names &&
1434 !mangle_is_8_3(fname, false, state->conn->params)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok = name_to_8_3(fname, mangled_name,
1443 false, state->conn->params);
1444 if (!ok) {
1445 return false;
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1450 mangled_name, mask);
1451 state->got_exact_match = got_match;
1452 if (!got_match) {
1453 got_match = mask_match(mangled_name, mask,
1454 state->conn->case_sensitive);
1458 if (!got_match) {
1459 return false;
1462 *_fname = talloc_strdup(ctx, fname);
1463 if (*_fname == NULL) {
1464 return false;
1467 return true;
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1471 void *private_data,
1472 struct smb_filename *smb_fname,
1473 uint32_t *_mode)
1475 struct smbd_dirptr_lanman2_state *state =
1476 (struct smbd_dirptr_lanman2_state *)private_data;
1477 bool ms_dfs_link = false;
1478 uint32_t mode = 0;
1480 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1481 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname),
1485 strerror(errno)));
1486 return false;
1488 } else if (!VALID_STAT(smb_fname->st) &&
1489 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1490 /* Needed to show the msdfs symlinks as
1491 * directories */
1493 ms_dfs_link = check_msdfs_link(state->conn,
1494 smb_fname->base_name,
1495 &smb_fname->st);
1496 if (!ms_dfs_link) {
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname),
1500 strerror(errno)));
1501 return false;
1505 if (ms_dfs_link) {
1506 mode = dos_mode_msdfs(state->conn, smb_fname);
1507 } else {
1508 mode = dos_mode(state->conn, smb_fname);
1511 *_mode = mode;
1512 return true;
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1516 connection_struct *conn,
1517 uint16_t flags2,
1518 uint32_t info_level,
1519 struct ea_list *name_list,
1520 bool check_mangled_names,
1521 bool requires_resume_key,
1522 uint32_t mode,
1523 const char *fname,
1524 const struct smb_filename *smb_fname,
1525 int space_remaining,
1526 uint8_t align,
1527 bool do_pad,
1528 char *base_data,
1529 char **ppdata,
1530 char *end_data,
1531 bool *out_of_space,
1532 uint64_t *last_entry_off)
1534 char *p, *q, *pdata = *ppdata;
1535 uint32_t reskey=0;
1536 uint64_t file_size = 0;
1537 uint64_t allocation_size = 0;
1538 uint64_t file_index = 0;
1539 uint32_t len;
1540 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1541 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1542 char *nameptr;
1543 char *last_entry_ptr;
1544 bool was_8_3;
1545 int off;
1546 int pad = 0;
1548 *out_of_space = false;
1550 ZERO_STRUCT(mdate_ts);
1551 ZERO_STRUCT(adate_ts);
1552 ZERO_STRUCT(create_date_ts);
1553 ZERO_STRUCT(cdate_ts);
1555 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1556 file_size = get_file_size_stat(&smb_fname->st);
1558 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1560 file_index = get_FileIndex(conn, &smb_fname->st);
1562 mdate_ts = smb_fname->st.st_ex_mtime;
1563 adate_ts = smb_fname->st.st_ex_atime;
1564 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1565 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1567 if (lp_dos_filetime_resolution(SNUM(conn))) {
1568 dos_filetime_timespec(&create_date_ts);
1569 dos_filetime_timespec(&mdate_ts);
1570 dos_filetime_timespec(&adate_ts);
1571 dos_filetime_timespec(&cdate_ts);
1574 create_date = convert_timespec_to_time_t(create_date_ts);
1575 mdate = convert_timespec_to_time_t(mdate_ts);
1576 adate = convert_timespec_to_time_t(adate_ts);
1578 /* align the record */
1579 SMB_ASSERT(align >= 1);
1581 off = (int)PTR_DIFF(pdata, base_data);
1582 pad = (off + (align-1)) & ~(align-1);
1583 pad -= off;
1585 if (pad && pad > space_remaining) {
1586 *out_of_space = true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1589 (unsigned int)pad,
1590 space_remaining ));
1591 return false; /* Not finished - just out of space */
1594 off += pad;
1595 /* initialize padding to 0 */
1596 if (pad) {
1597 memset(pdata, 0, pad);
1599 space_remaining -= pad;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1602 space_remaining ));
1604 pdata += pad;
1605 p = pdata;
1606 last_entry_ptr = p;
1608 pad = 0;
1609 off = 0;
1611 switch (info_level) {
1612 case SMB_FIND_INFO_STANDARD:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1614 if(requires_resume_key) {
1615 SIVAL(p,0,reskey);
1616 p += 4;
1618 srv_put_dos_date2(p,0,create_date);
1619 srv_put_dos_date2(p,4,adate);
1620 srv_put_dos_date2(p,8,mdate);
1621 SIVAL(p,12,(uint32)file_size);
1622 SIVAL(p,16,(uint32)allocation_size);
1623 SSVAL(p,20,mode);
1624 p += 23;
1625 nameptr = p;
1626 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 p += ucs2_align(base_data, p, 0);
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE);
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1633 if (len > 2) {
1634 SCVAL(nameptr, -1, len - 2);
1635 } else {
1636 SCVAL(nameptr, -1, 0);
1638 } else {
1639 if (len > 1) {
1640 SCVAL(nameptr, -1, len - 1);
1641 } else {
1642 SCVAL(nameptr, -1, 0);
1645 p += len;
1646 break;
1648 case SMB_FIND_EA_SIZE:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key) {
1651 SIVAL(p,0,reskey);
1652 p += 4;
1654 srv_put_dos_date2(p,0,create_date);
1655 srv_put_dos_date2(p,4,adate);
1656 srv_put_dos_date2(p,8,mdate);
1657 SIVAL(p,12,(uint32)file_size);
1658 SIVAL(p,16,(uint32)allocation_size);
1659 SSVAL(p,20,mode);
1661 unsigned int ea_size = estimate_ea_size(conn, NULL,
1662 smb_fname->base_name);
1663 SIVAL(p,22,ea_size); /* Extended attributes */
1665 p += 27;
1666 nameptr = p - 1;
1667 len = srvstr_push(base_data, flags2,
1668 p, fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE | STR_NOALIGN);
1670 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1671 if (len > 2) {
1672 len -= 2;
1673 } else {
1674 len = 0;
1676 } else {
1677 if (len > 1) {
1678 len -= 1;
1679 } else {
1680 len = 0;
1683 SCVAL(nameptr,0,len);
1684 p += len;
1685 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1686 break;
1688 case SMB_FIND_EA_LIST:
1690 struct ea_list *file_list = NULL;
1691 size_t ea_len = 0;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1694 if (!name_list) {
1695 return false;
1697 if (requires_resume_key) {
1698 SIVAL(p,0,reskey);
1699 p += 4;
1701 srv_put_dos_date2(p,0,create_date);
1702 srv_put_dos_date2(p,4,adate);
1703 srv_put_dos_date2(p,8,mdate);
1704 SIVAL(p,12,(uint32)file_size);
1705 SIVAL(p,16,(uint32)allocation_size);
1706 SSVAL(p,20,mode);
1707 p += 22; /* p now points to the EA area. */
1709 file_list = get_ea_list_from_file(ctx, conn, NULL,
1710 smb_fname->base_name,
1711 &ea_len);
1712 name_list = ea_list_union(name_list, file_list, &ea_len);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1717 *out_of_space = true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1721 space_remaining ));
1722 return False; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1727 nameptr = p;
1728 len = srvstr_push(base_data, flags2,
1729 p + 1, fname, PTR_DIFF(end_data, p+1),
1730 STR_TERMINATE | STR_NOALIGN);
1731 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1732 if (len > 2) {
1733 len -= 2;
1734 } else {
1735 len = 0;
1737 } else {
1738 if (len > 1) {
1739 len -= 1;
1740 } else {
1741 len = 0;
1744 SCVAL(nameptr,0,len);
1745 p += len + 1;
1746 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1747 break;
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1753 p += 4;
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,mode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL,
1765 smb_fname->base_name);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1767 p += 4;
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 char mangled_name[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 memset(p,'\0',26);
1791 p += 2 + 24;
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1795 SIVAL(q,0,len);
1796 p += len;
1798 len = PTR_DIFF(p, pdata);
1799 pad = (len + (align-1)) & ~(align-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1805 SIVAL(pdata,0,pad);
1807 * set padding to zero
1809 if (do_pad) {
1810 memset(p, 0, pad - len);
1811 p = pdata + pad;
1812 } else {
1813 p = pdata + len;
1815 break;
1817 case SMB_FIND_FILE_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1819 p += 4;
1820 SIVAL(p,0,reskey); p += 4;
1821 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1825 SOFF_T(p,0,file_size); p += 8;
1826 SOFF_T(p,0,allocation_size); p += 8;
1827 SIVAL(p,0,mode); p += 4;
1828 len = srvstr_push(base_data, flags2,
1829 p + 4, fname, PTR_DIFF(end_data, p+4),
1830 STR_TERMINATE_ASCII);
1831 SIVAL(p,0,len);
1832 p += 4 + len;
1834 len = PTR_DIFF(p, pdata);
1835 pad = (len + (align-1)) & ~(align-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1841 SIVAL(pdata,0,pad);
1843 * set padding to zero
1845 if (do_pad) {
1846 memset(p, 0, pad - len);
1847 p = pdata + pad;
1848 } else {
1849 p = pdata + len;
1851 break;
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1855 p += 4;
1856 SIVAL(p,0,reskey); p += 4;
1857 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1861 SOFF_T(p,0,file_size); p += 8;
1862 SOFF_T(p,0,allocation_size); p += 8;
1863 SIVAL(p,0,mode); p += 4;
1864 q = p; p += 4; /* q is placeholder for name length. */
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1867 smb_fname->base_name);
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1869 p +=4;
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1874 SIVAL(q, 0, len);
1875 p += len;
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1884 SIVAL(pdata,0,pad);
1886 * set padding to zero
1888 if (do_pad) {
1889 memset(p, 0, pad - len);
1890 p = pdata + pad;
1891 } else {
1892 p = pdata + len;
1894 break;
1896 case SMB_FIND_FILE_NAMES_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1898 p += 4;
1899 SIVAL(p,0,reskey); p += 4;
1900 p += 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1906 SIVAL(p, -4, len);
1907 p += len;
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1916 SIVAL(pdata,0,pad);
1918 * set padding to zero
1920 if (do_pad) {
1921 memset(p, 0, pad - len);
1922 p = pdata + pad;
1923 } else {
1924 p = pdata + len;
1926 break;
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1930 p += 4;
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 q = p; p += 4; /* q is placeholder for name length. */
1941 unsigned int ea_size = estimate_ea_size(conn, NULL,
1942 smb_fname->base_name);
1943 SIVAL(p,0,ea_size); /* Extended attributes */
1944 p +=4;
1946 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1947 SBVAL(p,0,file_index); p += 8;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q, 0, len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1976 p += 4;
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname->base_name);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1990 p +=4;
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3 && check_mangled_names) {
1997 char mangled_name[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname,mangled_name,True,
1999 conn->params)) {
2000 /* Error - mangle failed ! */
2001 memset(mangled_name,'\0',12);
2003 mangled_name[12] = 0;
2004 len = srvstr_push(base_data, flags2,
2005 p+2, mangled_name, 24,
2006 STR_UPPER|STR_UNICODE);
2007 SSVAL(p, 0, len);
2008 if (len < 24) {
2009 memset(p + 2 + len,'\0',24 - len);
2011 SSVAL(p, 0, len);
2012 } else {
2013 memset(p,'\0',26);
2015 p += 26;
2016 SSVAL(p,0,0); p += 2; /* Reserved ? */
2017 SBVAL(p,0,file_index); p += 8;
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE_ASCII);
2021 SIVAL(q,0,len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX:
2046 case SMB_FIND_FILE_UNIX_INFO2:
2047 p+= 4;
2048 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level == SMB_FIND_FILE_UNIX) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p = store_file_unix_basic(conn, p,
2055 NULL, &smb_fname->st);
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2058 STR_TERMINATE);
2059 } else {
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p = store_file_unix_basic_info2(conn, p,
2062 NULL, &smb_fname->st);
2063 nameptr = p;
2064 p += 4;
2065 len = srvstr_push(base_data, flags2, p, fname,
2066 PTR_DIFF(end_data, p), 0);
2067 SIVAL(nameptr, 0, len);
2070 p += len;
2072 len = PTR_DIFF(p, pdata);
2073 pad = (len + (align-1)) & ~(align-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2079 SIVAL(pdata,0,pad);
2081 * set padding to zero
2083 if (do_pad) {
2084 memset(p, 0, pad - len);
2085 p = pdata + pad;
2086 } else {
2087 p = pdata + len;
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2091 break;
2093 default:
2094 return false;
2097 if (PTR_DIFF(p,pdata) > space_remaining) {
2098 *out_of_space = true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p,pdata),
2102 space_remaining ));
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2108 /* Advance the data pointer to the next slot */
2109 *ppdata = p;
2111 return true;
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2115 connection_struct *conn,
2116 struct dptr_struct *dirptr,
2117 uint16 flags2,
2118 const char *path_mask,
2119 uint32 dirtype,
2120 int info_level,
2121 int requires_resume_key,
2122 bool dont_descend,
2123 bool ask_sharemode,
2124 uint8_t align,
2125 bool do_pad,
2126 char **ppdata,
2127 char *base_data,
2128 char *end_data,
2129 int space_remaining,
2130 bool *out_of_space,
2131 bool *got_exact_match,
2132 int *_last_entry_off,
2133 struct ea_list *name_list)
2135 const char *p;
2136 const char *mask = NULL;
2137 long prev_dirpos = 0;
2138 uint32_t mode = 0;
2139 char *fname = NULL;
2140 struct smb_filename *smb_fname = NULL;
2141 struct smbd_dirptr_lanman2_state state;
2142 bool ok;
2143 uint64_t last_entry_off = 0;
2145 ZERO_STRUCT(state);
2146 state.conn = conn;
2147 state.info_level = info_level;
2148 state.check_mangled_names = lp_manglednames(conn->params);
2149 state.has_wild = dptr_has_wild(dirptr);
2150 state.got_exact_match = false;
2152 *out_of_space = false;
2153 *got_exact_match = false;
2155 p = strrchr_m(path_mask,'/');
2156 if(p != NULL) {
2157 if(p[1] == '\0') {
2158 mask = "*.*";
2159 } else {
2160 mask = p+1;
2162 } else {
2163 mask = path_mask;
2166 ok = smbd_dirptr_get_entry(ctx,
2167 dirptr,
2168 mask,
2169 dirtype,
2170 dont_descend,
2171 ask_sharemode,
2172 smbd_dirptr_lanman2_match_fn,
2173 smbd_dirptr_lanman2_mode_fn,
2174 &state,
2175 &fname,
2176 &smb_fname,
2177 &mode,
2178 &prev_dirpos);
2179 if (!ok) {
2180 return false;
2183 *got_exact_match = state.got_exact_match;
2185 ok = smbd_marshall_dir_entry(ctx,
2186 conn,
2187 flags2,
2188 info_level,
2189 name_list,
2190 state.check_mangled_names,
2191 requires_resume_key,
2192 mode,
2193 fname,
2194 smb_fname,
2195 space_remaining,
2196 align,
2197 do_pad,
2198 base_data,
2199 ppdata,
2200 end_data,
2201 out_of_space,
2202 &last_entry_off);
2203 TALLOC_FREE(fname);
2204 TALLOC_FREE(smb_fname);
2205 if (*out_of_space) {
2206 dptr_SeekDir(dirptr, prev_dirpos);
2207 return false;
2209 if (!ok) {
2210 return false;
2213 *_last_entry_off = last_entry_off;
2214 return true;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2218 connection_struct *conn,
2219 struct dptr_struct *dirptr,
2220 uint16 flags2,
2221 const char *path_mask,
2222 uint32 dirtype,
2223 int info_level,
2224 bool requires_resume_key,
2225 bool dont_descend,
2226 bool ask_sharemode,
2227 char **ppdata,
2228 char *base_data,
2229 char *end_data,
2230 int space_remaining,
2231 bool *out_of_space,
2232 bool *got_exact_match,
2233 int *last_entry_off,
2234 struct ea_list *name_list)
2236 uint8_t align = 4;
2237 const bool do_pad = true;
2239 if (info_level >= 1 && info_level <= 3) {
2240 /* No alignment on earlier info levels. */
2241 align = 1;
2244 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2245 path_mask, dirtype, info_level,
2246 requires_resume_key, dont_descend, ask_sharemode,
2247 align, do_pad,
2248 ppdata, base_data, end_data,
2249 space_remaining,
2250 out_of_space, got_exact_match,
2251 last_entry_off, name_list);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct *conn,
2259 struct smb_request *req,
2260 char **pparams, int total_params,
2261 char **ppdata, int total_data,
2262 unsigned int max_data_bytes)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2268 requested. */
2269 struct smb_filename *smb_dname = NULL;
2270 char *params = *pparams;
2271 char *pdata = *ppdata;
2272 char *data_end;
2273 uint32 dirtype;
2274 int maxentries;
2275 uint16 findfirst_flags;
2276 bool close_after_first;
2277 bool close_if_end;
2278 bool requires_resume_key;
2279 int info_level;
2280 char *directory = NULL;
2281 char *mask = NULL;
2282 char *p;
2283 int last_entry_off=0;
2284 int dptr_num = -1;
2285 int numentries = 0;
2286 int i;
2287 bool finished = False;
2288 bool dont_descend = False;
2289 bool out_of_space = False;
2290 int space_remaining;
2291 bool mask_contains_wcard = False;
2292 struct ea_list *ea_list = NULL;
2293 NTSTATUS ntstatus = NT_STATUS_OK;
2294 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX *ctx = talloc_tos();
2296 struct dptr_struct *dirptr = NULL;
2297 struct smbd_server_connection *sconn = req->sconn;
2298 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2299 bool backup_priv = false;
2301 if (total_params < 13) {
2302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2303 goto out;
2306 dirtype = SVAL(params,0);
2307 maxentries = SVAL(params,2);
2308 findfirst_flags = SVAL(params,4);
2309 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2310 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2311 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2312 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2313 security_token_has_privilege(get_current_nttok(conn),
2314 SEC_PRIV_BACKUP));
2316 info_level = SVAL(params,6);
2318 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2319 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2320 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2321 (int)backup_priv,
2322 info_level, max_data_bytes));
2324 if (!maxentries) {
2325 /* W2K3 seems to treat zero as 1. */
2326 maxentries = 1;
2329 switch (info_level) {
2330 case SMB_FIND_INFO_STANDARD:
2331 case SMB_FIND_EA_SIZE:
2332 case SMB_FIND_EA_LIST:
2333 case SMB_FIND_FILE_DIRECTORY_INFO:
2334 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2335 case SMB_FIND_FILE_NAMES_INFO:
2336 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2337 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2338 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2339 break;
2340 case SMB_FIND_FILE_UNIX:
2341 case SMB_FIND_FILE_UNIX_INFO2:
2342 /* Always use filesystem for UNIX mtime query. */
2343 ask_sharemode = false;
2344 if (!lp_unix_extensions()) {
2345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346 goto out;
2348 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2349 break;
2350 default:
2351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2352 goto out;
2355 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2356 params+12, total_params - 12,
2357 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2358 if (!NT_STATUS_IS_OK(ntstatus)) {
2359 reply_nterror(req, ntstatus);
2360 goto out;
2363 if (backup_priv) {
2364 become_root();
2365 ntstatus = filename_convert_with_privilege(ctx,
2366 conn,
2367 req,
2368 directory,
2369 ucf_flags,
2370 &mask_contains_wcard,
2371 &smb_dname);
2372 } else {
2373 ntstatus = filename_convert(ctx, conn,
2374 req->flags2 & FLAGS2_DFS_PATHNAMES,
2375 directory,
2376 ucf_flags,
2377 &mask_contains_wcard,
2378 &smb_dname);
2381 if (!NT_STATUS_IS_OK(ntstatus)) {
2382 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2383 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2384 ERRSRV, ERRbadpath);
2385 goto out;
2387 reply_nterror(req, ntstatus);
2388 goto out;
2391 mask = smb_dname->original_lcomp;
2393 directory = smb_dname->base_name;
2395 p = strrchr_m(directory,'/');
2396 if(p == NULL) {
2397 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2398 if((directory[0] == '.') && (directory[1] == '\0')) {
2399 mask = talloc_strdup(ctx,"*");
2400 if (!mask) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2402 goto out;
2404 mask_contains_wcard = True;
2406 } else {
2407 *p = 0;
2410 if (p == NULL || p == directory) {
2411 /* Ensure we don't have a directory name of "". */
2412 directory = talloc_strdup(talloc_tos(), ".");
2413 if (!directory) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 goto out;
2419 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2421 if (info_level == SMB_FIND_EA_LIST) {
2422 uint32 ea_size;
2424 if (total_data < 4) {
2425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 goto out;
2429 ea_size = IVAL(pdata,0);
2430 if (ea_size != total_data) {
2431 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2432 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2434 goto out;
2437 if (!lp_ea_support(SNUM(conn))) {
2438 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2439 goto out;
2442 /* Pull out the list of names. */
2443 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2444 if (!ea_list) {
2445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2446 goto out;
2450 *ppdata = (char *)SMB_REALLOC(
2451 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2452 if(*ppdata == NULL ) {
2453 reply_nterror(req, NT_STATUS_NO_MEMORY);
2454 goto out;
2456 pdata = *ppdata;
2457 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2459 /* Realloc the params space */
2460 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2461 if (*pparams == NULL) {
2462 reply_nterror(req, NT_STATUS_NO_MEMORY);
2463 goto out;
2465 params = *pparams;
2467 /* Save the wildcard match and attribs we are using on this directory -
2468 needed as lanman2 assumes these are being saved between calls */
2470 ntstatus = dptr_create(conn,
2471 req,
2472 NULL, /* fsp */
2473 directory,
2474 False,
2475 True,
2476 req->smbpid,
2477 mask,
2478 mask_contains_wcard,
2479 dirtype,
2480 &dirptr);
2482 if (!NT_STATUS_IS_OK(ntstatus)) {
2483 reply_nterror(req, ntstatus);
2484 goto out;
2487 if (backup_priv) {
2488 /* Remember this in case we have
2489 to do a findnext. */
2490 dptr_set_priv(dirptr);
2493 dptr_num = dptr_dnum(dirptr);
2494 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2496 /* Initialize per TRANS2_FIND_FIRST operation data */
2497 dptr_init_search_op(dirptr);
2499 /* We don't need to check for VOL here as this is returned by
2500 a different TRANS2 call. */
2502 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2503 directory,lp_dontdescend(SNUM(conn))));
2504 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2505 dont_descend = True;
2507 p = pdata;
2508 space_remaining = max_data_bytes;
2509 out_of_space = False;
2511 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2512 bool got_exact_match = False;
2514 /* this is a heuristic to avoid seeking the dirptr except when
2515 absolutely necessary. It allows for a filename of about 40 chars */
2516 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2517 out_of_space = True;
2518 finished = False;
2519 } else {
2520 finished = !get_lanman2_dir_entry(ctx,
2521 conn,
2522 dirptr,
2523 req->flags2,
2524 mask,dirtype,info_level,
2525 requires_resume_key,dont_descend,
2526 ask_sharemode,
2527 &p,pdata,data_end,
2528 space_remaining, &out_of_space,
2529 &got_exact_match,
2530 &last_entry_off, ea_list);
2533 if (finished && out_of_space)
2534 finished = False;
2536 if (!finished && !out_of_space)
2537 numentries++;
2540 * As an optimisation if we know we aren't looking
2541 * for a wildcard name (ie. the name matches the wildcard exactly)
2542 * then we can finish on any (first) match.
2543 * This speeds up large directory searches. JRA.
2546 if(got_exact_match)
2547 finished = True;
2549 /* Ensure space_remaining never goes -ve. */
2550 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2551 space_remaining = 0;
2552 out_of_space = true;
2553 } else {
2554 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2558 /* Check if we can close the dirptr */
2559 if(close_after_first || (finished && close_if_end)) {
2560 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2561 dptr_close(sconn, &dptr_num);
2565 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2566 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2567 * the protocol level is less than NT1. Tested with smbclient. JRA.
2568 * This should fix the OS/2 client bug #2335.
2571 if(numentries == 0) {
2572 dptr_close(sconn, &dptr_num);
2573 if (get_Protocol() < PROTOCOL_NT1) {
2574 reply_force_doserror(req, ERRDOS, ERRnofiles);
2575 goto out;
2576 } else {
2577 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2578 ERRDOS, ERRbadfile);
2579 goto out;
2583 /* At this point pdata points to numentries directory entries. */
2585 /* Set up the return parameter block */
2586 SSVAL(params,0,dptr_num);
2587 SSVAL(params,2,numentries);
2588 SSVAL(params,4,finished);
2589 SSVAL(params,6,0); /* Never an EA error */
2590 SSVAL(params,8,last_entry_off);
2592 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2593 max_data_bytes);
2595 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2596 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2597 if (!directory) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2602 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2603 smb_fn_name(req->cmd),
2604 mask, directory, dirtype, numentries ) );
2607 * Force a name mangle here to ensure that the
2608 * mask as an 8.3 name is top of the mangled cache.
2609 * The reasons for this are subtle. Don't remove
2610 * this code unless you know what you are doing
2611 * (see PR#13758). JRA.
2614 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2615 char mangled_name[13];
2616 name_to_8_3(mask, mangled_name, True, conn->params);
2618 out:
2620 if (backup_priv) {
2621 unbecome_root();
2624 TALLOC_FREE(smb_dname);
2625 return;
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDNEXT.
2630 ****************************************************************************/
2632 static void call_trans2findnext(connection_struct *conn,
2633 struct smb_request *req,
2634 char **pparams, int total_params,
2635 char **ppdata, int total_data,
2636 unsigned int max_data_bytes)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2642 requested. */
2643 char *params = *pparams;
2644 char *pdata = *ppdata;
2645 char *data_end;
2646 int dptr_num;
2647 int maxentries;
2648 uint16 info_level;
2649 uint32 resume_key;
2650 uint16 findnext_flags;
2651 bool close_after_request;
2652 bool close_if_end;
2653 bool requires_resume_key;
2654 bool continue_bit;
2655 bool mask_contains_wcard = False;
2656 char *resume_name = NULL;
2657 const char *mask = NULL;
2658 const char *directory = NULL;
2659 char *p = NULL;
2660 uint16 dirtype;
2661 int numentries = 0;
2662 int i, last_entry_off=0;
2663 bool finished = False;
2664 bool dont_descend = False;
2665 bool out_of_space = False;
2666 int space_remaining;
2667 struct ea_list *ea_list = NULL;
2668 NTSTATUS ntstatus = NT_STATUS_OK;
2669 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2670 TALLOC_CTX *ctx = talloc_tos();
2671 struct dptr_struct *dirptr;
2672 struct smbd_server_connection *sconn = req->sconn;
2673 bool backup_priv = false;
2675 if (total_params < 13) {
2676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2677 return;
2680 dptr_num = SVAL(params,0);
2681 maxentries = SVAL(params,2);
2682 info_level = SVAL(params,4);
2683 resume_key = IVAL(params,6);
2684 findnext_flags = SVAL(params,10);
2685 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2686 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2687 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2688 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2690 if (!continue_bit) {
2691 /* We only need resume_name if continue_bit is zero. */
2692 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2693 params+12,
2694 total_params - 12, STR_TERMINATE, &ntstatus,
2695 &mask_contains_wcard);
2696 if (!NT_STATUS_IS_OK(ntstatus)) {
2697 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2698 complain (it thinks we're asking for the directory above the shared
2699 path or an invalid name). Catch this as the resume name is only compared, never used in
2700 a file access. JRA. */
2701 srvstr_pull_talloc(ctx, params, req->flags2,
2702 &resume_name, params+12,
2703 total_params - 12,
2704 STR_TERMINATE);
2706 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2707 reply_nterror(req, ntstatus);
2708 return;
2713 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2714 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2715 resume_key = %d resume name = %s continue=%d level = %d\n",
2716 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2717 requires_resume_key, resume_key,
2718 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2720 if (!maxentries) {
2721 /* W2K3 seems to treat zero as 1. */
2722 maxentries = 1;
2725 switch (info_level) {
2726 case SMB_FIND_INFO_STANDARD:
2727 case SMB_FIND_EA_SIZE:
2728 case SMB_FIND_EA_LIST:
2729 case SMB_FIND_FILE_DIRECTORY_INFO:
2730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2731 case SMB_FIND_FILE_NAMES_INFO:
2732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2733 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2735 break;
2736 case SMB_FIND_FILE_UNIX:
2737 case SMB_FIND_FILE_UNIX_INFO2:
2738 /* Always use filesystem for UNIX mtime query. */
2739 ask_sharemode = false;
2740 if (!lp_unix_extensions()) {
2741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2742 return;
2744 break;
2745 default:
2746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2747 return;
2750 if (info_level == SMB_FIND_EA_LIST) {
2751 uint32 ea_size;
2753 if (total_data < 4) {
2754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2755 return;
2758 ea_size = IVAL(pdata,0);
2759 if (ea_size != total_data) {
2760 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2761 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 return;
2766 if (!lp_ea_support(SNUM(conn))) {
2767 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2768 return;
2771 /* Pull out the list of names. */
2772 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2773 if (!ea_list) {
2774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2775 return;
2779 *ppdata = (char *)SMB_REALLOC(
2780 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2781 if(*ppdata == NULL) {
2782 reply_nterror(req, NT_STATUS_NO_MEMORY);
2783 return;
2786 pdata = *ppdata;
2787 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2789 /* Realloc the params space */
2790 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2791 if(*pparams == NULL ) {
2792 reply_nterror(req, NT_STATUS_NO_MEMORY);
2793 return;
2796 params = *pparams;
2798 /* Check that the dptr is valid */
2799 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2800 reply_nterror(req, STATUS_NO_MORE_FILES);
2801 return;
2804 directory = dptr_path(sconn, dptr_num);
2806 /* Get the wildcard mask from the dptr */
2807 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2808 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2809 reply_nterror(req, STATUS_NO_MORE_FILES);
2810 return;
2813 /* Get the attr mask from the dptr */
2814 dirtype = dptr_attr(sconn, dptr_num);
2816 backup_priv = dptr_get_priv(dirptr);
2818 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2819 "backup_priv = %d\n",
2820 dptr_num, mask, dirtype,
2821 (long)dirptr,
2822 dptr_TellDir(dirptr),
2823 (int)backup_priv));
2825 /* Initialize per TRANS2_FIND_NEXT operation data */
2826 dptr_init_search_op(dirptr);
2828 /* We don't need to check for VOL here as this is returned by
2829 a different TRANS2 call. */
2831 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2832 directory,lp_dontdescend(SNUM(conn))));
2833 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2834 dont_descend = True;
2836 p = pdata;
2837 space_remaining = max_data_bytes;
2838 out_of_space = False;
2840 if (backup_priv) {
2841 become_root();
2845 * Seek to the correct position. We no longer use the resume key but
2846 * depend on the last file name instead.
2849 if(!continue_bit && resume_name && *resume_name) {
2850 SMB_STRUCT_STAT st;
2852 long current_pos = 0;
2854 * Remember, name_to_8_3 is called by
2855 * get_lanman2_dir_entry(), so the resume name
2856 * could be mangled. Ensure we check the unmangled name.
2859 if (mangle_is_mangled(resume_name, conn->params)) {
2860 char *new_resume_name = NULL;
2861 mangle_lookup_name_from_8_3(ctx,
2862 resume_name,
2863 &new_resume_name,
2864 conn->params);
2865 if (new_resume_name) {
2866 resume_name = new_resume_name;
2871 * Fix for NT redirector problem triggered by resume key indexes
2872 * changing between directory scans. We now return a resume key of 0
2873 * and instead look for the filename to continue from (also given
2874 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2875 * findfirst/findnext (as is usual) then the directory pointer
2876 * should already be at the correct place.
2879 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2880 } /* end if resume_name && !continue_bit */
2882 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2883 bool got_exact_match = False;
2885 /* this is a heuristic to avoid seeking the dirptr except when
2886 absolutely necessary. It allows for a filename of about 40 chars */
2887 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2888 out_of_space = True;
2889 finished = False;
2890 } else {
2891 finished = !get_lanman2_dir_entry(ctx,
2892 conn,
2893 dirptr,
2894 req->flags2,
2895 mask,dirtype,info_level,
2896 requires_resume_key,dont_descend,
2897 ask_sharemode,
2898 &p,pdata,data_end,
2899 space_remaining, &out_of_space,
2900 &got_exact_match,
2901 &last_entry_off, ea_list);
2904 if (finished && out_of_space)
2905 finished = False;
2907 if (!finished && !out_of_space)
2908 numentries++;
2911 * As an optimisation if we know we aren't looking
2912 * for a wildcard name (ie. the name matches the wildcard exactly)
2913 * then we can finish on any (first) match.
2914 * This speeds up large directory searches. JRA.
2917 if(got_exact_match)
2918 finished = True;
2920 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2923 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2924 smb_fn_name(req->cmd),
2925 mask, directory, dirtype, numentries ) );
2927 /* Check if we can close the dirptr */
2928 if(close_after_request || (finished && close_if_end)) {
2929 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2930 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2933 if (backup_priv) {
2934 unbecome_root();
2937 /* Set up the return parameter block */
2938 SSVAL(params,0,numentries);
2939 SSVAL(params,2,finished);
2940 SSVAL(params,4,0); /* Never an EA error */
2941 SSVAL(params,6,last_entry_off);
2943 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2944 max_data_bytes);
2946 return;
2949 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2951 E_md4hash(lp_servicename(SNUM(conn)),objid);
2952 return objid;
2955 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2957 SMB_ASSERT(extended_info != NULL);
2959 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2960 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2961 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2962 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2963 #ifdef SAMBA_VERSION_REVISION
2964 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2965 #endif
2966 extended_info->samba_subversion = 0;
2967 #ifdef SAMBA_VERSION_RC_RELEASE
2968 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2969 #else
2970 #ifdef SAMBA_VERSION_PRE_RELEASE
2971 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2972 #endif
2973 #endif
2974 #ifdef SAMBA_VERSION_VENDOR_PATCH
2975 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2976 #endif
2977 extended_info->samba_gitcommitdate = 0;
2978 #ifdef SAMBA_VERSION_COMMIT_TIME
2979 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2980 #endif
2982 memset(extended_info->samba_version_string, 0,
2983 sizeof(extended_info->samba_version_string));
2985 snprintf (extended_info->samba_version_string,
2986 sizeof(extended_info->samba_version_string),
2987 "%s", samba_version_string());
2990 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2991 TALLOC_CTX *mem_ctx,
2992 uint16_t info_level,
2993 uint16_t flags2,
2994 unsigned int max_data_bytes,
2995 char **ppdata,
2996 int *ret_data_len)
2998 char *pdata, *end_data;
2999 int data_len = 0, len;
3000 const char *vname = volume_label(SNUM(conn));
3001 int snum = SNUM(conn);
3002 char *fstype = lp_fstype(SNUM(conn));
3003 uint32 additional_flags = 0;
3004 struct smb_filename smb_fname_dot;
3005 SMB_STRUCT_STAT st;
3007 if (IS_IPC(conn)) {
3008 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3009 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3010 "info level (0x%x) on IPC$.\n",
3011 (unsigned int)info_level));
3012 return NT_STATUS_ACCESS_DENIED;
3016 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3018 ZERO_STRUCT(smb_fname_dot);
3019 smb_fname_dot.base_name = discard_const_p(char, ".");
3021 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3022 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3023 return map_nt_error_from_unix(errno);
3026 st = smb_fname_dot.st;
3028 *ppdata = (char *)SMB_REALLOC(
3029 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3030 if (*ppdata == NULL) {
3031 return NT_STATUS_NO_MEMORY;
3034 pdata = *ppdata;
3035 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3036 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3038 switch (info_level) {
3039 case SMB_INFO_ALLOCATION:
3041 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3042 data_len = 18;
3043 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno);
3047 block_size = lp_block_size(snum);
3048 if (bsize < block_size) {
3049 uint64_t factor = block_size/bsize;
3050 bsize = block_size;
3051 dsize /= factor;
3052 dfree /= factor;
3054 if (bsize > block_size) {
3055 uint64_t factor = bsize/block_size;
3056 bsize = block_size;
3057 dsize *= factor;
3058 dfree *= factor;
3060 bytes_per_sector = 512;
3061 sectors_per_unit = bsize/bytes_per_sector;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3065 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3067 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3068 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3069 SIVAL(pdata,l1_cUnit,dsize);
3070 SIVAL(pdata,l1_cUnitAvail,dfree);
3071 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3072 break;
3075 case SMB_INFO_VOLUME:
3076 /* Return volume name */
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3083 * Win2k3 and previous mess this up by sending a name length
3084 * one byte short. I believe only older clients (OS/2 Win9x) use
3085 * this call so try fixing this by adding a terminating null to
3086 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3088 len = srvstr_push(
3089 pdata, flags2,
3090 pdata+l2_vol_szVolLabel, vname,
3091 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3092 STR_NOALIGN|STR_TERMINATE);
3093 SCVAL(pdata,l2_vol_cch,len);
3094 data_len = l2_vol_szVolLabel + len;
3095 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3096 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3097 len, vname));
3098 break;
3100 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3101 case SMB_FS_ATTRIBUTE_INFORMATION:
3103 additional_flags = 0;
3104 #if defined(HAVE_SYS_QUOTAS)
3105 additional_flags |= FILE_VOLUME_QUOTAS;
3106 #endif
3108 if(lp_nt_acl_support(SNUM(conn))) {
3109 additional_flags |= FILE_PERSISTENT_ACLS;
3112 /* Capabilities are filled in at connection time through STATVFS call */
3113 additional_flags |= conn->fs_capabilities;
3114 additional_flags |= lp_parm_int(conn->params->service,
3115 "share", "fake_fscaps",
3118 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3119 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3120 additional_flags); /* FS ATTRIBUTES */
3122 SIVAL(pdata,4,255); /* Max filename component length */
3123 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3124 and will think we can't do long filenames */
3125 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3126 PTR_DIFF(end_data, pdata+12),
3127 STR_UNICODE);
3128 SIVAL(pdata,8,len);
3129 data_len = 12 + len;
3130 break;
3132 case SMB_QUERY_FS_LABEL_INFO:
3133 case SMB_FS_LABEL_INFORMATION:
3134 len = srvstr_push(pdata, flags2, pdata+4, vname,
3135 PTR_DIFF(end_data, pdata+4), 0);
3136 data_len = 4 + len;
3137 SIVAL(pdata,0,len);
3138 break;
3140 case SMB_QUERY_FS_VOLUME_INFO:
3141 case SMB_FS_VOLUME_INFORMATION:
3144 * Add volume serial number - hash of a combination of
3145 * the called hostname and the service name.
3147 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3148 (str_checksum(get_local_machine_name())<<16));
3150 /* Max label len is 32 characters. */
3151 len = srvstr_push(pdata, flags2, pdata+18, vname,
3152 PTR_DIFF(end_data, pdata+18),
3153 STR_UNICODE);
3154 SIVAL(pdata,12,len);
3155 data_len = 18+len;
3157 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3158 (int)strlen(vname),vname, lp_servicename(snum)));
3159 break;
3161 case SMB_QUERY_FS_SIZE_INFO:
3162 case SMB_FS_SIZE_INFORMATION:
3164 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3165 data_len = 24;
3166 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3167 return map_nt_error_from_unix(errno);
3169 block_size = lp_block_size(snum);
3170 if (bsize < block_size) {
3171 uint64_t factor = block_size/bsize;
3172 bsize = block_size;
3173 dsize /= factor;
3174 dfree /= factor;
3176 if (bsize > block_size) {
3177 uint64_t factor = bsize/block_size;
3178 bsize = block_size;
3179 dsize *= factor;
3180 dfree *= factor;
3182 bytes_per_sector = 512;
3183 sectors_per_unit = bsize/bytes_per_sector;
3184 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3185 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3186 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3187 SBIG_UINT(pdata,0,dsize);
3188 SBIG_UINT(pdata,8,dfree);
3189 SIVAL(pdata,16,sectors_per_unit);
3190 SIVAL(pdata,20,bytes_per_sector);
3191 break;
3194 case SMB_FS_FULL_SIZE_INFORMATION:
3196 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3197 data_len = 32;
3198 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3199 return map_nt_error_from_unix(errno);
3201 block_size = lp_block_size(snum);
3202 if (bsize < block_size) {
3203 uint64_t factor = block_size/bsize;
3204 bsize = block_size;
3205 dsize /= factor;
3206 dfree /= factor;
3208 if (bsize > block_size) {
3209 uint64_t factor = bsize/block_size;
3210 bsize = block_size;
3211 dsize *= factor;
3212 dfree *= factor;
3214 bytes_per_sector = 512;
3215 sectors_per_unit = bsize/bytes_per_sector;
3216 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3217 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3218 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3219 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3220 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3221 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3222 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3223 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3224 break;
3227 case SMB_QUERY_FS_DEVICE_INFO:
3228 case SMB_FS_DEVICE_INFORMATION:
3230 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3232 if (!CAN_WRITE(conn)) {
3233 characteristics |= FILE_READ_ONLY_DEVICE;
3235 data_len = 8;
3236 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3237 SIVAL(pdata,4,characteristics);
3238 break;
3241 #ifdef HAVE_SYS_QUOTAS
3242 case SMB_FS_QUOTA_INFORMATION:
3244 * what we have to send --metze:
3246 * Unknown1: 24 NULL bytes
3247 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3248 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3249 * Quota Flags: 2 byte :
3250 * Unknown3: 6 NULL bytes
3252 * 48 bytes total
3254 * details for Quota Flags:
3256 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3257 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3258 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3259 * 0x0001 Enable Quotas: enable quota for this fs
3263 /* we need to fake up a fsp here,
3264 * because its not send in this call
3266 files_struct fsp;
3267 SMB_NTQUOTA_STRUCT quotas;
3269 ZERO_STRUCT(fsp);
3270 ZERO_STRUCT(quotas);
3272 fsp.conn = conn;
3273 fsp.fnum = -1;
3275 /* access check */
3276 if (get_current_uid(conn) != 0) {
3277 DEBUG(0,("set_user_quota: access_denied "
3278 "service [%s] user [%s]\n",
3279 lp_servicename(SNUM(conn)),
3280 conn->session_info->unix_info->unix_name));
3281 return NT_STATUS_ACCESS_DENIED;
3284 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3285 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3286 return map_nt_error_from_unix(errno);
3289 data_len = 48;
3291 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3292 lp_servicename(SNUM(conn))));
3294 /* Unknown1 24 NULL bytes*/
3295 SBIG_UINT(pdata,0,(uint64_t)0);
3296 SBIG_UINT(pdata,8,(uint64_t)0);
3297 SBIG_UINT(pdata,16,(uint64_t)0);
3299 /* Default Soft Quota 8 bytes */
3300 SBIG_UINT(pdata,24,quotas.softlim);
3302 /* Default Hard Quota 8 bytes */
3303 SBIG_UINT(pdata,32,quotas.hardlim);
3305 /* Quota flag 2 bytes */
3306 SSVAL(pdata,40,quotas.qflags);
3308 /* Unknown3 6 NULL bytes */
3309 SSVAL(pdata,42,0);
3310 SIVAL(pdata,44,0);
3312 break;
3314 #endif /* HAVE_SYS_QUOTAS */
3315 case SMB_FS_OBJECTID_INFORMATION:
3317 unsigned char objid[16];
3318 struct smb_extended_info extended_info;
3319 memcpy(pdata,create_volume_objectid(conn, objid),16);
3320 samba_extended_info_version (&extended_info);
3321 SIVAL(pdata,16,extended_info.samba_magic);
3322 SIVAL(pdata,20,extended_info.samba_version);
3323 SIVAL(pdata,24,extended_info.samba_subversion);
3324 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3325 memcpy(pdata+36,extended_info.samba_version_string,28);
3326 data_len = 64;
3327 break;
3331 * Query the version and capabilities of the CIFS UNIX extensions
3332 * in use.
3335 case SMB_QUERY_CIFS_UNIX_INFO:
3337 bool large_write = lp_min_receive_file_size() &&
3338 !srv_is_signing_active(conn->sconn);
3339 bool large_read = !srv_is_signing_active(conn->sconn);
3340 int encrypt_caps = 0;
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL;
3346 switch (conn->encrypt_level) {
3347 case 0:
3348 encrypt_caps = 0;
3349 break;
3350 case 1:
3351 case Auto:
3352 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3353 break;
3354 case Required:
3355 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3356 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3357 large_write = false;
3358 large_read = false;
3359 break;
3362 data_len = 12;
3363 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3364 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3366 /* We have POSIX ACLs, pathname, encryption,
3367 * large read/write, and locking capability. */
3369 SBIG_UINT(pdata,4,((uint64_t)(
3370 CIFS_UNIX_POSIX_ACLS_CAP|
3371 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3372 CIFS_UNIX_FCNTL_LOCKS_CAP|
3373 CIFS_UNIX_EXTATTR_CAP|
3374 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3375 encrypt_caps|
3376 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3377 (large_write ?
3378 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3379 break;
3382 case SMB_QUERY_POSIX_FS_INFO:
3384 int rc;
3385 vfs_statvfs_struct svfs;
3387 if (!lp_unix_extensions()) {
3388 return NT_STATUS_INVALID_LEVEL;
3391 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3393 if (!rc) {
3394 data_len = 56;
3395 SIVAL(pdata,0,svfs.OptimalTransferSize);
3396 SIVAL(pdata,4,svfs.BlockSize);
3397 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3398 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3399 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3400 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3401 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3402 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3403 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3404 #ifdef EOPNOTSUPP
3405 } else if (rc == EOPNOTSUPP) {
3406 return NT_STATUS_INVALID_LEVEL;
3407 #endif /* EOPNOTSUPP */
3408 } else {
3409 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3410 return NT_STATUS_DOS(ERRSRV, ERRerror);
3412 break;
3415 case SMB_QUERY_POSIX_WHOAMI:
3417 uint32_t flags = 0;
3418 uint32_t sid_bytes;
3419 int i;
3421 if (!lp_unix_extensions()) {
3422 return NT_STATUS_INVALID_LEVEL;
3425 if (max_data_bytes < 40) {
3426 return NT_STATUS_BUFFER_TOO_SMALL;
3429 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3430 flags |= SMB_WHOAMI_GUEST;
3433 /* NOTE: 8 bytes for UID/GID, irrespective of native
3434 * platform size. This matches
3435 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3437 data_len = 4 /* flags */
3438 + 4 /* flag mask */
3439 + 8 /* uid */
3440 + 8 /* gid */
3441 + 4 /* ngroups */
3442 + 4 /* num_sids */
3443 + 4 /* SID bytes */
3444 + 4 /* pad/reserved */
3445 + (conn->session_info->unix_token->ngroups * 8)
3446 /* groups list */
3447 + (conn->session_info->security_token->num_sids *
3448 SID_MAX_SIZE)
3449 /* SID list */;
3451 SIVAL(pdata, 0, flags);
3452 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3453 SBIG_UINT(pdata, 8,
3454 (uint64_t)conn->session_info->unix_token->uid);
3455 SBIG_UINT(pdata, 16,
3456 (uint64_t)conn->session_info->unix_token->gid);
3459 if (data_len >= max_data_bytes) {
3460 /* Potential overflow, skip the GIDs and SIDs. */
3462 SIVAL(pdata, 24, 0); /* num_groups */
3463 SIVAL(pdata, 28, 0); /* num_sids */
3464 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3465 SIVAL(pdata, 36, 0); /* reserved */
3467 data_len = 40;
3468 break;
3471 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3472 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3474 /* We walk the SID list twice, but this call is fairly
3475 * infrequent, and I don't expect that it's performance
3476 * sensitive -- jpeach
3478 for (i = 0, sid_bytes = 0;
3479 i < conn->session_info->security_token->num_sids; ++i) {
3480 sid_bytes += ndr_size_dom_sid(
3481 &conn->session_info->security_token->sids[i],
3485 /* SID list byte count */
3486 SIVAL(pdata, 32, sid_bytes);
3488 /* 4 bytes pad/reserved - must be zero */
3489 SIVAL(pdata, 36, 0);
3490 data_len = 40;
3492 /* GID list */
3493 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3494 SBIG_UINT(pdata, data_len,
3495 (uint64_t)conn->session_info->unix_token->groups[i]);
3496 data_len += 8;
3499 /* SID list */
3500 for (i = 0;
3501 i < conn->session_info->security_token->num_sids; ++i) {
3502 int sid_len = ndr_size_dom_sid(
3503 &conn->session_info->security_token->sids[i],
3506 sid_linearize(pdata + data_len, sid_len,
3507 &conn->session_info->security_token->sids[i]);
3508 data_len += sid_len;
3511 break;
3514 case SMB_MAC_QUERY_FS_INFO:
3516 * Thursby MAC extension... ONLY on NTFS filesystems
3517 * once we do streams then we don't need this
3519 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3520 data_len = 88;
3521 SIVAL(pdata,84,0x100); /* Don't support mac... */
3522 break;
3524 /* drop through */
3525 default:
3526 return NT_STATUS_INVALID_LEVEL;
3529 *ret_data_len = data_len;
3530 return NT_STATUS_OK;
3533 /****************************************************************************
3534 Reply to a TRANS2_QFSINFO (query filesystem info).
3535 ****************************************************************************/
3537 static void call_trans2qfsinfo(connection_struct *conn,
3538 struct smb_request *req,
3539 char **pparams, int total_params,
3540 char **ppdata, int total_data,
3541 unsigned int max_data_bytes)
3543 char *params = *pparams;
3544 uint16_t info_level;
3545 int data_len = 0;
3546 NTSTATUS status;
3548 if (total_params < 2) {
3549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550 return;
3553 info_level = SVAL(params,0);
3555 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3556 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3557 DEBUG(0,("call_trans2qfsinfo: encryption required "
3558 "and info level 0x%x sent.\n",
3559 (unsigned int)info_level));
3560 exit_server_cleanly("encryption required "
3561 "on connection");
3562 return;
3566 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3568 status = smbd_do_qfsinfo(conn, req,
3569 info_level,
3570 req->flags2,
3571 max_data_bytes,
3572 ppdata, &data_len);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 reply_nterror(req, status);
3575 return;
3578 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3579 max_data_bytes);
3581 DEBUG( 4, ( "%s info_level = %d\n",
3582 smb_fn_name(req->cmd), info_level) );
3584 return;
3587 /****************************************************************************
3588 Reply to a TRANS2_SETFSINFO (set filesystem info).
3589 ****************************************************************************/
3591 static void call_trans2setfsinfo(connection_struct *conn,
3592 struct smb_request *req,
3593 char **pparams, int total_params,
3594 char **ppdata, int total_data,
3595 unsigned int max_data_bytes)
3597 struct smbd_server_connection *sconn = req->sconn;
3598 char *pdata = *ppdata;
3599 char *params = *pparams;
3600 uint16 info_level;
3602 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3604 /* */
3605 if (total_params < 4) {
3606 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3607 total_params));
3608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3609 return;
3612 info_level = SVAL(params,2);
3614 if (IS_IPC(conn)) {
3615 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3616 info_level != SMB_SET_CIFS_UNIX_INFO) {
3617 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3618 "info level (0x%x) on IPC$.\n",
3619 (unsigned int)info_level));
3620 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3621 return;
3625 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3626 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3627 DEBUG(0,("call_trans2setfsinfo: encryption required "
3628 "and info level 0x%x sent.\n",
3629 (unsigned int)info_level));
3630 exit_server_cleanly("encryption required "
3631 "on connection");
3632 return;
3636 switch(info_level) {
3637 case SMB_SET_CIFS_UNIX_INFO:
3638 if (!lp_unix_extensions()) {
3639 DEBUG(2,("call_trans2setfsinfo: "
3640 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3641 "unix extensions off\n"));
3642 reply_nterror(req,
3643 NT_STATUS_INVALID_LEVEL);
3644 return;
3647 /* There should be 12 bytes of capabilities set. */
3648 if (total_data < 12) {
3649 reply_nterror(
3650 req,
3651 NT_STATUS_INVALID_PARAMETER);
3652 return;
3654 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3655 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3656 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3657 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3658 /* Just print these values for now. */
3659 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3660 "major = %u, minor = %u cap_low = 0x%x, "
3661 "cap_high = 0x%xn",
3662 (unsigned int)sconn->
3663 smb1.unix_info.client_major,
3664 (unsigned int)sconn->
3665 smb1.unix_info.client_minor,
3666 (unsigned int)sconn->
3667 smb1.unix_info.client_cap_low,
3668 (unsigned int)sconn->
3669 smb1.unix_info.client_cap_high));
3671 /* Here is where we must switch to posix pathname processing... */
3672 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3673 lp_set_posix_pathnames();
3674 mangle_change_to_posix();
3677 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3678 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3679 /* Client that knows how to do posix locks,
3680 * but not posix open/mkdir operations. Set a
3681 * default type for read/write checks. */
3683 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3686 break;
3688 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3690 NTSTATUS status;
3691 size_t param_len = 0;
3692 size_t data_len = total_data;
3694 if (!lp_unix_extensions()) {
3695 reply_nterror(
3696 req,
3697 NT_STATUS_INVALID_LEVEL);
3698 return;
3701 if (lp_smb_encrypt(SNUM(conn)) == false) {
3702 reply_nterror(
3703 req,
3704 NT_STATUS_NOT_SUPPORTED);
3705 return;
3708 if (req->sconn->smb1.echo_handler.trusted_fde) {
3709 DEBUG( 2,("call_trans2setfsinfo: "
3710 "request transport encryption disabled"
3711 "with 'fork echo handler = yes'\n"));
3712 reply_nterror(
3713 req,
3714 NT_STATUS_NOT_SUPPORTED);
3715 return;
3718 DEBUG( 4,("call_trans2setfsinfo: "
3719 "request transport encryption.\n"));
3721 status = srv_request_encryption_setup(conn,
3722 (unsigned char **)ppdata,
3723 &data_len,
3724 (unsigned char **)pparams,
3725 &param_len);
3727 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3728 !NT_STATUS_IS_OK(status)) {
3729 reply_nterror(req, status);
3730 return;
3733 send_trans2_replies(conn, req,
3734 *pparams,
3735 param_len,
3736 *ppdata,
3737 data_len,
3738 max_data_bytes);
3740 if (NT_STATUS_IS_OK(status)) {
3741 /* Server-side transport
3742 * encryption is now *on*. */
3743 status = srv_encryption_start(conn);
3744 if (!NT_STATUS_IS_OK(status)) {
3745 char *reason = talloc_asprintf(talloc_tos(),
3746 "Failure in setting "
3747 "up encrypted transport: %s",
3748 nt_errstr(status));
3749 exit_server_cleanly(reason);
3752 return;
3755 case SMB_FS_QUOTA_INFORMATION:
3757 files_struct *fsp = NULL;
3758 SMB_NTQUOTA_STRUCT quotas;
3760 ZERO_STRUCT(quotas);
3762 /* access check */
3763 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3764 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3765 lp_servicename(SNUM(conn)),
3766 conn->session_info->unix_info->unix_name));
3767 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3768 return;
3771 /* note: normaly there're 48 bytes,
3772 * but we didn't use the last 6 bytes for now
3773 * --metze
3775 fsp = file_fsp(req, SVAL(params,0));
3777 if (!check_fsp_ntquota_handle(conn, req,
3778 fsp)) {
3779 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3780 reply_nterror(
3781 req, NT_STATUS_INVALID_HANDLE);
3782 return;
3785 if (total_data < 42) {
3786 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3787 total_data));
3788 reply_nterror(
3789 req,
3790 NT_STATUS_INVALID_PARAMETER);
3791 return;
3794 /* unknown_1 24 NULL bytes in pdata*/
3796 /* the soft quotas 8 bytes (uint64_t)*/
3797 quotas.softlim = BVAL(pdata,24);
3799 /* the hard quotas 8 bytes (uint64_t)*/
3800 quotas.hardlim = BVAL(pdata,32);
3802 /* quota_flags 2 bytes **/
3803 quotas.qflags = SVAL(pdata,40);
3805 /* unknown_2 6 NULL bytes follow*/
3807 /* now set the quotas */
3808 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3809 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3810 reply_nterror(req, map_nt_error_from_unix(errno));
3811 return;
3814 break;
3816 default:
3817 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3818 info_level));
3819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3820 return;
3821 break;
3825 * sending this reply works fine,
3826 * but I'm not sure it's the same
3827 * like windows do...
3828 * --metze
3830 reply_outbuf(req, 10, 0);
3833 #if defined(HAVE_POSIX_ACLS)
3834 /****************************************************************************
3835 Utility function to count the number of entries in a POSIX acl.
3836 ****************************************************************************/
3838 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3840 unsigned int ace_count = 0;
3841 int entry_id = SMB_ACL_FIRST_ENTRY;
3842 SMB_ACL_ENTRY_T entry;
3844 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3845 /* get_next... */
3846 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3847 entry_id = SMB_ACL_NEXT_ENTRY;
3849 ace_count++;
3851 return ace_count;
3854 /****************************************************************************
3855 Utility function to marshall a POSIX acl into wire format.
3856 ****************************************************************************/
3858 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3860 int entry_id = SMB_ACL_FIRST_ENTRY;
3861 SMB_ACL_ENTRY_T entry;
3863 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3864 SMB_ACL_TAG_T tagtype;
3865 SMB_ACL_PERMSET_T permset;
3866 unsigned char perms = 0;
3867 unsigned int own_grp;
3869 /* get_next... */
3870 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3871 entry_id = SMB_ACL_NEXT_ENTRY;
3874 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3875 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3876 return False;
3879 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3880 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3881 return False;
3884 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3885 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3886 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3888 SCVAL(pdata,1,perms);
3890 switch (tagtype) {
3891 case SMB_ACL_USER_OBJ:
3892 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3893 own_grp = (unsigned int)pst->st_ex_uid;
3894 SIVAL(pdata,2,own_grp);
3895 SIVAL(pdata,6,0);
3896 break;
3897 case SMB_ACL_USER:
3899 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3900 if (!puid) {
3901 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3902 return False;
3904 own_grp = (unsigned int)*puid;
3905 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3906 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3907 SIVAL(pdata,2,own_grp);
3908 SIVAL(pdata,6,0);
3909 break;
3911 case SMB_ACL_GROUP_OBJ:
3912 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3913 own_grp = (unsigned int)pst->st_ex_gid;
3914 SIVAL(pdata,2,own_grp);
3915 SIVAL(pdata,6,0);
3916 break;
3917 case SMB_ACL_GROUP:
3919 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3920 if (!pgid) {
3921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3922 return False;
3924 own_grp = (unsigned int)*pgid;
3925 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3926 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3927 SIVAL(pdata,2,own_grp);
3928 SIVAL(pdata,6,0);
3929 break;
3931 case SMB_ACL_MASK:
3932 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3933 SIVAL(pdata,2,0xFFFFFFFF);
3934 SIVAL(pdata,6,0xFFFFFFFF);
3935 break;
3936 case SMB_ACL_OTHER:
3937 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3938 SIVAL(pdata,2,0xFFFFFFFF);
3939 SIVAL(pdata,6,0xFFFFFFFF);
3940 break;
3941 default:
3942 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3943 return False;
3945 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3948 return True;
3950 #endif
3952 /****************************************************************************
3953 Store the FILE_UNIX_BASIC info.
3954 ****************************************************************************/
3956 static char *store_file_unix_basic(connection_struct *conn,
3957 char *pdata,
3958 files_struct *fsp,
3959 const SMB_STRUCT_STAT *psbuf)
3961 uint64_t file_index = get_FileIndex(conn, psbuf);
3963 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3964 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3966 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3967 pdata += 8;
3969 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3970 pdata += 8;
3972 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3973 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3974 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3975 pdata += 24;
3977 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3978 SIVAL(pdata,4,0);
3979 pdata += 8;
3981 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3982 SIVAL(pdata,4,0);
3983 pdata += 8;
3985 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3986 pdata += 4;
3988 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3989 SIVAL(pdata,4,0);
3990 pdata += 8;
3992 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3993 SIVAL(pdata,4,0);
3994 pdata += 8;
3996 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3997 pdata += 8;
3999 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4000 SIVAL(pdata,4,0);
4001 pdata += 8;
4003 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4004 SIVAL(pdata,4,0);
4005 pdata += 8;
4007 return pdata;
4010 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4011 * the chflags(2) (or equivalent) flags.
4013 * XXX: this really should be behind the VFS interface. To do this, we would
4014 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4015 * Each VFS module could then implement its own mapping as appropriate for the
4016 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4018 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4019 info2_flags_map[] =
4021 #ifdef UF_NODUMP
4022 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4023 #endif
4025 #ifdef UF_IMMUTABLE
4026 { UF_IMMUTABLE, EXT_IMMUTABLE },
4027 #endif
4029 #ifdef UF_APPEND
4030 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4031 #endif
4033 #ifdef UF_HIDDEN
4034 { UF_HIDDEN, EXT_HIDDEN },
4035 #endif
4037 /* Do not remove. We need to guarantee that this array has at least one
4038 * entry to build on HP-UX.
4040 { 0, 0 }
4044 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4045 uint32 *smb_fflags, uint32 *smb_fmask)
4047 int i;
4049 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4050 *smb_fmask |= info2_flags_map[i].smb_fflag;
4051 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4052 *smb_fflags |= info2_flags_map[i].smb_fflag;
4057 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4058 const uint32 smb_fflags,
4059 const uint32 smb_fmask,
4060 int *stat_fflags)
4062 uint32 max_fmask = 0;
4063 int i;
4065 *stat_fflags = psbuf->st_ex_flags;
4067 /* For each flags requested in smb_fmask, check the state of the
4068 * corresponding flag in smb_fflags and set or clear the matching
4069 * stat flag.
4072 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4073 max_fmask |= info2_flags_map[i].smb_fflag;
4074 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4075 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4076 *stat_fflags |= info2_flags_map[i].stat_fflag;
4077 } else {
4078 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4083 /* If smb_fmask is asking to set any bits that are not supported by
4084 * our flag mappings, we should fail.
4086 if ((smb_fmask & max_fmask) != smb_fmask) {
4087 return False;
4090 return True;
4094 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4095 * of file flags and birth (create) time.
4097 static char *store_file_unix_basic_info2(connection_struct *conn,
4098 char *pdata,
4099 files_struct *fsp,
4100 const SMB_STRUCT_STAT *psbuf)
4102 uint32 file_flags = 0;
4103 uint32 flags_mask = 0;
4105 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4107 /* Create (birth) time 64 bit */
4108 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4109 pdata += 8;
4111 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4112 SIVAL(pdata, 0, file_flags); /* flags */
4113 SIVAL(pdata, 4, flags_mask); /* mask */
4114 pdata += 8;
4116 return pdata;
4119 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4120 const struct stream_struct *streams,
4121 char *data,
4122 unsigned int max_data_bytes,
4123 unsigned int *data_size)
4125 unsigned int i;
4126 unsigned int ofs = 0;
4128 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4129 unsigned int next_offset;
4130 size_t namelen;
4131 smb_ucs2_t *namebuf;
4133 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4134 streams[i].name, &namelen) ||
4135 namelen <= 2)
4137 return NT_STATUS_INVALID_PARAMETER;
4141 * name_buf is now null-terminated, we need to marshall as not
4142 * terminated
4145 namelen -= 2;
4147 SIVAL(data, ofs+4, namelen);
4148 SOFF_T(data, ofs+8, streams[i].size);
4149 SOFF_T(data, ofs+16, streams[i].alloc_size);
4150 memcpy(data+ofs+24, namebuf, namelen);
4151 TALLOC_FREE(namebuf);
4153 next_offset = ofs + 24 + namelen;
4155 if (i == num_streams-1) {
4156 SIVAL(data, ofs, 0);
4158 else {
4159 unsigned int align = ndr_align_size(next_offset, 8);
4161 memset(data+next_offset, 0, align);
4162 next_offset += align;
4164 SIVAL(data, ofs, next_offset - ofs);
4165 ofs = next_offset;
4168 ofs = next_offset;
4171 *data_size = ofs;
4173 return NT_STATUS_OK;
4176 /****************************************************************************
4177 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4178 ****************************************************************************/
4180 static void call_trans2qpipeinfo(connection_struct *conn,
4181 struct smb_request *req,
4182 unsigned int tran_call,
4183 char **pparams, int total_params,
4184 char **ppdata, int total_data,
4185 unsigned int max_data_bytes)
4187 char *params = *pparams;
4188 char *pdata = *ppdata;
4189 unsigned int data_size = 0;
4190 unsigned int param_size = 2;
4191 uint16 info_level;
4192 files_struct *fsp;
4194 if (!params) {
4195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4196 return;
4199 if (total_params < 4) {
4200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4201 return;
4204 fsp = file_fsp(req, SVAL(params,0));
4205 if (!fsp_is_np(fsp)) {
4206 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4207 return;
4210 info_level = SVAL(params,2);
4212 *pparams = (char *)SMB_REALLOC(*pparams,2);
4213 if (*pparams == NULL) {
4214 reply_nterror(req, NT_STATUS_NO_MEMORY);
4215 return;
4217 params = *pparams;
4218 SSVAL(params,0,0);
4219 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4220 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4221 if (*ppdata == NULL ) {
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4223 return;
4225 pdata = *ppdata;
4227 switch (info_level) {
4228 case SMB_FILE_STANDARD_INFORMATION:
4229 memset(pdata,0,24);
4230 SOFF_T(pdata,0,4096LL);
4231 SIVAL(pdata,16,1);
4232 SIVAL(pdata,20,1);
4233 data_size = 24;
4234 break;
4236 default:
4237 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4238 return;
4241 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4242 max_data_bytes);
4244 return;
4247 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4248 TALLOC_CTX *mem_ctx,
4249 uint16_t info_level,
4250 files_struct *fsp,
4251 struct smb_filename *smb_fname,
4252 bool delete_pending,
4253 struct timespec write_time_ts,
4254 struct ea_list *ea_list,
4255 int lock_data_count,
4256 char *lock_data,
4257 uint16_t flags2,
4258 unsigned int max_data_bytes,
4259 char **ppdata,
4260 unsigned int *pdata_size)
4262 char *pdata = *ppdata;
4263 char *dstart, *dend;
4264 unsigned int data_size;
4265 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4266 time_t create_time, mtime, atime, c_time;
4267 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4268 char *p;
4269 char *base_name;
4270 char *dos_fname;
4271 int mode;
4272 int nlink;
4273 NTSTATUS status;
4274 uint64_t file_size = 0;
4275 uint64_t pos = 0;
4276 uint64_t allocation_size = 0;
4277 uint64_t file_index = 0;
4278 uint32_t access_mask = 0;
4280 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4281 return NT_STATUS_INVALID_LEVEL;
4284 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4285 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4286 info_level, max_data_bytes));
4288 mode = dos_mode(conn, smb_fname);
4289 nlink = psbuf->st_ex_nlink;
4291 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4292 nlink = 1;
4295 if ((nlink > 0) && delete_pending) {
4296 nlink -= 1;
4299 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4300 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4301 if (*ppdata == NULL) {
4302 return NT_STATUS_NO_MEMORY;
4304 pdata = *ppdata;
4305 dstart = pdata;
4306 dend = dstart + data_size - 1;
4308 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4309 update_stat_ex_mtime(psbuf, write_time_ts);
4312 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4313 mtime_ts = psbuf->st_ex_mtime;
4314 atime_ts = psbuf->st_ex_atime;
4315 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4317 if (lp_dos_filetime_resolution(SNUM(conn))) {
4318 dos_filetime_timespec(&create_time_ts);
4319 dos_filetime_timespec(&mtime_ts);
4320 dos_filetime_timespec(&atime_ts);
4321 dos_filetime_timespec(&ctime_ts);
4324 create_time = convert_timespec_to_time_t(create_time_ts);
4325 mtime = convert_timespec_to_time_t(mtime_ts);
4326 atime = convert_timespec_to_time_t(atime_ts);
4327 c_time = convert_timespec_to_time_t(ctime_ts);
4329 p = strrchr_m(smb_fname->base_name,'/');
4330 if (!p)
4331 base_name = smb_fname->base_name;
4332 else
4333 base_name = p+1;
4335 /* NT expects the name to be in an exact form of the *full*
4336 filename. See the trans2 torture test */
4337 if (ISDOT(base_name)) {
4338 dos_fname = talloc_strdup(mem_ctx, "\\");
4339 if (!dos_fname) {
4340 return NT_STATUS_NO_MEMORY;
4342 } else {
4343 dos_fname = talloc_asprintf(mem_ctx,
4344 "\\%s",
4345 smb_fname->base_name);
4346 if (!dos_fname) {
4347 return NT_STATUS_NO_MEMORY;
4349 if (is_ntfs_stream_smb_fname(smb_fname)) {
4350 dos_fname = talloc_asprintf(dos_fname, "%s",
4351 smb_fname->stream_name);
4352 if (!dos_fname) {
4353 return NT_STATUS_NO_MEMORY;
4357 string_replace(dos_fname, '/', '\\');
4360 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4362 if (!fsp) {
4363 /* Do we have this path open ? */
4364 files_struct *fsp1;
4365 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4366 fsp1 = file_find_di_first(conn->sconn, fileid);
4367 if (fsp1 && fsp1->initial_allocation_size) {
4368 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4372 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4373 file_size = get_file_size_stat(psbuf);
4376 if (fsp) {
4377 pos = fsp->fh->position_information;
4380 if (fsp) {
4381 access_mask = fsp->access_mask;
4382 } else {
4383 /* GENERIC_EXECUTE mapping from Windows */
4384 access_mask = 0x12019F;
4387 /* This should be an index number - looks like
4388 dev/ino to me :-)
4390 I think this causes us to fail the IFSKIT
4391 BasicFileInformationTest. -tpot */
4392 file_index = get_FileIndex(conn, psbuf);
4394 switch (info_level) {
4395 case SMB_INFO_STANDARD:
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4397 data_size = 22;
4398 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4399 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4400 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4401 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4402 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4403 SSVAL(pdata,l1_attrFile,mode);
4404 break;
4406 case SMB_INFO_QUERY_EA_SIZE:
4408 unsigned int ea_size =
4409 estimate_ea_size(conn, fsp,
4410 smb_fname->base_name);
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4412 data_size = 26;
4413 srv_put_dos_date2(pdata,0,create_time);
4414 srv_put_dos_date2(pdata,4,atime);
4415 srv_put_dos_date2(pdata,8,mtime); /* write time */
4416 SIVAL(pdata,12,(uint32)file_size);
4417 SIVAL(pdata,16,(uint32)allocation_size);
4418 SSVAL(pdata,20,mode);
4419 SIVAL(pdata,22,ea_size);
4420 break;
4423 case SMB_INFO_IS_NAME_VALID:
4424 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4425 if (fsp) {
4426 /* os/2 needs this ? really ?*/
4427 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4429 /* This is only reached for qpathinfo */
4430 data_size = 0;
4431 break;
4433 case SMB_INFO_QUERY_EAS_FROM_LIST:
4435 size_t total_ea_len = 0;
4436 struct ea_list *ea_file_list = NULL;
4438 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4440 ea_file_list =
4441 get_ea_list_from_file(mem_ctx, conn, fsp,
4442 smb_fname->base_name,
4443 &total_ea_len);
4444 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4446 if (!ea_list || (total_ea_len > data_size)) {
4447 data_size = 4;
4448 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4449 break;
4452 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4453 break;
4456 case SMB_INFO_QUERY_ALL_EAS:
4458 /* We have data_size bytes to put EA's into. */
4459 size_t total_ea_len = 0;
4461 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4463 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4464 smb_fname->base_name,
4465 &total_ea_len);
4466 if (!ea_list || (total_ea_len > data_size)) {
4467 data_size = 4;
4468 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4469 break;
4472 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4473 break;
4476 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4478 /* This is FileFullEaInformation - 0xF which maps to
4479 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4481 /* We have data_size bytes to put EA's into. */
4482 size_t total_ea_len = 0;
4483 struct ea_list *ea_file_list = NULL;
4485 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4487 /*TODO: add filtering and index handling */
4489 ea_file_list =
4490 get_ea_list_from_file(mem_ctx, conn, fsp,
4491 smb_fname->base_name,
4492 &total_ea_len);
4493 if (!ea_file_list) {
4494 return NT_STATUS_NO_EAS_ON_FILE;
4497 status = fill_ea_chained_buffer(mem_ctx,
4498 pdata,
4499 data_size,
4500 &data_size,
4501 conn, ea_file_list);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 return status;
4505 break;
4508 case SMB_FILE_BASIC_INFORMATION:
4509 case SMB_QUERY_FILE_BASIC_INFO:
4511 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4513 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4514 } else {
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4516 data_size = 40;
4517 SIVAL(pdata,36,0);
4519 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4520 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4521 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4522 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4523 SIVAL(pdata,32,mode);
4525 DEBUG(5,("SMB_QFBI - "));
4526 DEBUG(5,("create: %s ", ctime(&create_time)));
4527 DEBUG(5,("access: %s ", ctime(&atime)));
4528 DEBUG(5,("write: %s ", ctime(&mtime)));
4529 DEBUG(5,("change: %s ", ctime(&c_time)));
4530 DEBUG(5,("mode: %x\n", mode));
4531 break;
4533 case SMB_FILE_STANDARD_INFORMATION:
4534 case SMB_QUERY_FILE_STANDARD_INFO:
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4537 data_size = 24;
4538 SOFF_T(pdata,0,allocation_size);
4539 SOFF_T(pdata,8,file_size);
4540 SIVAL(pdata,16,nlink);
4541 SCVAL(pdata,20,delete_pending?1:0);
4542 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4543 SSVAL(pdata,22,0); /* Padding. */
4544 break;
4546 case SMB_FILE_EA_INFORMATION:
4547 case SMB_QUERY_FILE_EA_INFO:
4549 unsigned int ea_size =
4550 estimate_ea_size(conn, fsp, smb_fname->base_name);
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4552 data_size = 4;
4553 SIVAL(pdata,0,ea_size);
4554 break;
4557 /* Get the 8.3 name - used if NT SMB was negotiated. */
4558 case SMB_QUERY_FILE_ALT_NAME_INFO:
4559 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4561 int len;
4562 char mangled_name[13];
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4564 if (!name_to_8_3(base_name,mangled_name,
4565 True,conn->params)) {
4566 return NT_STATUS_NO_MEMORY;
4568 len = srvstr_push(dstart, flags2,
4569 pdata+4, mangled_name,
4570 PTR_DIFF(dend, pdata+4),
4571 STR_UNICODE);
4572 data_size = 4 + len;
4573 SIVAL(pdata,0,len);
4574 break;
4577 case SMB_QUERY_FILE_NAME_INFO:
4579 int len;
4581 this must be *exactly* right for ACLs on mapped drives to work
4583 len = srvstr_push(dstart, flags2,
4584 pdata+4, dos_fname,
4585 PTR_DIFF(dend, pdata+4),
4586 STR_UNICODE);
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4588 data_size = 4 + len;
4589 SIVAL(pdata,0,len);
4590 break;
4593 case SMB_FILE_ALLOCATION_INFORMATION:
4594 case SMB_QUERY_FILE_ALLOCATION_INFO:
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4596 data_size = 8;
4597 SOFF_T(pdata,0,allocation_size);
4598 break;
4600 case SMB_FILE_END_OF_FILE_INFORMATION:
4601 case SMB_QUERY_FILE_END_OF_FILEINFO:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4603 data_size = 8;
4604 SOFF_T(pdata,0,file_size);
4605 break;
4607 case SMB_QUERY_FILE_ALL_INFO:
4608 case SMB_FILE_ALL_INFORMATION:
4610 int len;
4611 unsigned int ea_size =
4612 estimate_ea_size(conn, fsp, smb_fname->base_name);
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4614 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4615 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4616 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4617 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4618 SIVAL(pdata,32,mode);
4619 SIVAL(pdata,36,0); /* padding. */
4620 pdata += 40;
4621 SOFF_T(pdata,0,allocation_size);
4622 SOFF_T(pdata,8,file_size);
4623 SIVAL(pdata,16,nlink);
4624 SCVAL(pdata,20,delete_pending);
4625 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4626 SSVAL(pdata,22,0);
4627 pdata += 24;
4628 SIVAL(pdata,0,ea_size);
4629 pdata += 4; /* EA info */
4630 len = srvstr_push(dstart, flags2,
4631 pdata+4, dos_fname,
4632 PTR_DIFF(dend, pdata+4),
4633 STR_UNICODE);
4634 SIVAL(pdata,0,len);
4635 pdata += 4 + len;
4636 data_size = PTR_DIFF(pdata,(*ppdata));
4637 break;
4640 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4642 int len;
4643 unsigned int ea_size =
4644 estimate_ea_size(conn, fsp, smb_fname->base_name);
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4646 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4647 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4648 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4649 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4650 SIVAL(pdata, 0x20, mode);
4651 SIVAL(pdata, 0x24, 0); /* padding. */
4652 SBVAL(pdata, 0x28, allocation_size);
4653 SBVAL(pdata, 0x30, file_size);
4654 SIVAL(pdata, 0x38, nlink);
4655 SCVAL(pdata, 0x3C, delete_pending);
4656 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4657 SSVAL(pdata, 0x3E, 0); /* padding */
4658 SBVAL(pdata, 0x40, file_index);
4659 SIVAL(pdata, 0x48, ea_size);
4660 SIVAL(pdata, 0x4C, access_mask);
4661 SBVAL(pdata, 0x50, pos);
4662 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4663 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4665 pdata += 0x60;
4667 len = srvstr_push(dstart, flags2,
4668 pdata+4, dos_fname,
4669 PTR_DIFF(dend, pdata+4),
4670 STR_UNICODE);
4671 SIVAL(pdata,0,len);
4672 pdata += 4 + len;
4673 data_size = PTR_DIFF(pdata,(*ppdata));
4674 break;
4676 case SMB_FILE_INTERNAL_INFORMATION:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4679 SBVAL(pdata, 0, file_index);
4680 data_size = 8;
4681 break;
4683 case SMB_FILE_ACCESS_INFORMATION:
4684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4685 SIVAL(pdata, 0, access_mask);
4686 data_size = 4;
4687 break;
4689 case SMB_FILE_NAME_INFORMATION:
4690 /* Pathname with leading '\'. */
4692 size_t byte_len;
4693 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4695 SIVAL(pdata,0,byte_len);
4696 data_size = 4 + byte_len;
4697 break;
4700 case SMB_FILE_DISPOSITION_INFORMATION:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4702 data_size = 1;
4703 SCVAL(pdata,0,delete_pending);
4704 break;
4706 case SMB_FILE_POSITION_INFORMATION:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4708 data_size = 8;
4709 SOFF_T(pdata,0,pos);
4710 break;
4712 case SMB_FILE_MODE_INFORMATION:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4714 SIVAL(pdata,0,mode);
4715 data_size = 4;
4716 break;
4718 case SMB_FILE_ALIGNMENT_INFORMATION:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4720 SIVAL(pdata,0,0); /* No alignment needed. */
4721 data_size = 4;
4722 break;
4725 * NT4 server just returns "invalid query" to this - if we try
4726 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4727 * want this. JRA.
4729 /* The first statement above is false - verified using Thursby
4730 * client against NT4 -- gcolley.
4732 case SMB_QUERY_FILE_STREAM_INFO:
4733 case SMB_FILE_STREAM_INFORMATION: {
4734 unsigned int num_streams = 0;
4735 struct stream_struct *streams = NULL;
4737 DEBUG(10,("smbd_do_qfilepathinfo: "
4738 "SMB_FILE_STREAM_INFORMATION\n"));
4740 if (is_ntfs_stream_smb_fname(smb_fname)) {
4741 return NT_STATUS_INVALID_PARAMETER;
4744 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4745 talloc_tos(), &num_streams, &streams);
4747 if (!NT_STATUS_IS_OK(status)) {
4748 DEBUG(10, ("could not get stream info: %s\n",
4749 nt_errstr(status)));
4750 return status;
4753 status = marshall_stream_info(num_streams, streams,
4754 pdata, max_data_bytes,
4755 &data_size);
4757 if (!NT_STATUS_IS_OK(status)) {
4758 DEBUG(10, ("marshall_stream_info failed: %s\n",
4759 nt_errstr(status)));
4760 return status;
4763 TALLOC_FREE(streams);
4765 break;
4767 case SMB_QUERY_COMPRESSION_INFO:
4768 case SMB_FILE_COMPRESSION_INFORMATION:
4769 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4770 SOFF_T(pdata,0,file_size);
4771 SIVAL(pdata,8,0); /* ??? */
4772 SIVAL(pdata,12,0); /* ??? */
4773 data_size = 16;
4774 break;
4776 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4778 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4779 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4780 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4781 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4782 SOFF_T(pdata,32,allocation_size);
4783 SOFF_T(pdata,40,file_size);
4784 SIVAL(pdata,48,mode);
4785 SIVAL(pdata,52,0); /* ??? */
4786 data_size = 56;
4787 break;
4789 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4791 SIVAL(pdata,0,mode);
4792 SIVAL(pdata,4,0);
4793 data_size = 8;
4794 break;
4797 * CIFS UNIX Extensions.
4800 case SMB_QUERY_FILE_UNIX_BASIC:
4802 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4803 data_size = PTR_DIFF(pdata,(*ppdata));
4805 DEBUG(4,("smbd_do_qfilepathinfo: "
4806 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4807 dump_data(4, (uint8_t *)(*ppdata), data_size);
4809 break;
4811 case SMB_QUERY_FILE_UNIX_INFO2:
4813 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4814 data_size = PTR_DIFF(pdata,(*ppdata));
4817 int i;
4818 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4820 for (i=0; i<100; i++)
4821 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4822 DEBUG(4,("\n"));
4825 break;
4827 case SMB_QUERY_FILE_UNIX_LINK:
4829 int len;
4830 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4832 if (!buffer) {
4833 return NT_STATUS_NO_MEMORY;
4836 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4837 #ifdef S_ISLNK
4838 if(!S_ISLNK(psbuf->st_ex_mode)) {
4839 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4841 #else
4842 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4843 #endif
4844 len = SMB_VFS_READLINK(conn,
4845 smb_fname->base_name,
4846 buffer, PATH_MAX);
4847 if (len == -1) {
4848 return map_nt_error_from_unix(errno);
4850 buffer[len] = 0;
4851 len = srvstr_push(dstart, flags2,
4852 pdata, buffer,
4853 PTR_DIFF(dend, pdata),
4854 STR_TERMINATE);
4855 pdata += len;
4856 data_size = PTR_DIFF(pdata,(*ppdata));
4858 break;
4861 #if defined(HAVE_POSIX_ACLS)
4862 case SMB_QUERY_POSIX_ACL:
4864 SMB_ACL_T file_acl = NULL;
4865 SMB_ACL_T def_acl = NULL;
4866 uint16 num_file_acls = 0;
4867 uint16 num_def_acls = 0;
4869 if (fsp && fsp->fh->fd != -1) {
4870 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4871 } else {
4872 file_acl =
4873 SMB_VFS_SYS_ACL_GET_FILE(conn,
4874 smb_fname->base_name,
4875 SMB_ACL_TYPE_ACCESS);
4878 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4879 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4880 "not implemented on "
4881 "filesystem containing %s\n",
4882 smb_fname->base_name));
4883 return NT_STATUS_NOT_IMPLEMENTED;
4886 if (S_ISDIR(psbuf->st_ex_mode)) {
4887 if (fsp && fsp->is_directory) {
4888 def_acl =
4889 SMB_VFS_SYS_ACL_GET_FILE(
4890 conn,
4891 fsp->fsp_name->base_name,
4892 SMB_ACL_TYPE_DEFAULT);
4893 } else {
4894 def_acl =
4895 SMB_VFS_SYS_ACL_GET_FILE(
4896 conn,
4897 smb_fname->base_name,
4898 SMB_ACL_TYPE_DEFAULT);
4900 def_acl = free_empty_sys_acl(conn, def_acl);
4903 num_file_acls = count_acl_entries(conn, file_acl);
4904 num_def_acls = count_acl_entries(conn, def_acl);
4906 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4907 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4908 data_size,
4909 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4910 SMB_POSIX_ACL_HEADER_SIZE) ));
4911 if (file_acl) {
4912 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4914 if (def_acl) {
4915 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4917 return NT_STATUS_BUFFER_TOO_SMALL;
4920 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4921 SSVAL(pdata,2,num_file_acls);
4922 SSVAL(pdata,4,num_def_acls);
4923 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4924 if (file_acl) {
4925 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4927 if (def_acl) {
4928 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4930 return NT_STATUS_INTERNAL_ERROR;
4932 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4933 if (file_acl) {
4934 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4936 if (def_acl) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4939 return NT_STATUS_INTERNAL_ERROR;
4942 if (file_acl) {
4943 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4945 if (def_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4948 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4949 break;
4951 #endif
4954 case SMB_QUERY_POSIX_LOCK:
4956 uint64_t count;
4957 uint64_t offset;
4958 uint64_t smblctx;
4959 enum brl_type lock_type;
4961 /* We need an open file with a real fd for this. */
4962 if (!fsp || fsp->fh->fd == -1) {
4963 return NT_STATUS_INVALID_LEVEL;
4966 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4967 return NT_STATUS_INVALID_PARAMETER;
4970 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4971 case POSIX_LOCK_TYPE_READ:
4972 lock_type = READ_LOCK;
4973 break;
4974 case POSIX_LOCK_TYPE_WRITE:
4975 lock_type = WRITE_LOCK;
4976 break;
4977 case POSIX_LOCK_TYPE_UNLOCK:
4978 default:
4979 /* There's no point in asking for an unlock... */
4980 return NT_STATUS_INVALID_PARAMETER;
4983 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4984 #if defined(HAVE_LONGLONG)
4985 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4986 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4987 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4988 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4989 #else /* HAVE_LONGLONG */
4990 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4991 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4992 #endif /* HAVE_LONGLONG */
4994 status = query_lock(fsp,
4995 &smblctx,
4996 &count,
4997 &offset,
4998 &lock_type,
4999 POSIX_LOCK);
5001 if (ERROR_WAS_LOCK_DENIED(status)) {
5002 /* Here we need to report who has it locked... */
5003 data_size = POSIX_LOCK_DATA_SIZE;
5005 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5006 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5007 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5008 #if defined(HAVE_LONGLONG)
5009 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5010 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5011 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5012 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5013 #else /* HAVE_LONGLONG */
5014 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5015 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5016 #endif /* HAVE_LONGLONG */
5018 } else if (NT_STATUS_IS_OK(status)) {
5019 /* For success we just return a copy of what we sent
5020 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5021 data_size = POSIX_LOCK_DATA_SIZE;
5022 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5023 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5024 } else {
5025 return status;
5027 break;
5030 default:
5031 return NT_STATUS_INVALID_LEVEL;
5034 *pdata_size = data_size;
5035 return NT_STATUS_OK;
5038 /****************************************************************************
5039 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5040 file name or file id).
5041 ****************************************************************************/
5043 static void call_trans2qfilepathinfo(connection_struct *conn,
5044 struct smb_request *req,
5045 unsigned int tran_call,
5046 char **pparams, int total_params,
5047 char **ppdata, int total_data,
5048 unsigned int max_data_bytes)
5050 char *params = *pparams;
5051 char *pdata = *ppdata;
5052 uint16 info_level;
5053 unsigned int data_size = 0;
5054 unsigned int param_size = 2;
5055 struct smb_filename *smb_fname = NULL;
5056 bool delete_pending = False;
5057 struct timespec write_time_ts;
5058 files_struct *fsp = NULL;
5059 struct file_id fileid;
5060 struct ea_list *ea_list = NULL;
5061 int lock_data_count = 0;
5062 char *lock_data = NULL;
5063 NTSTATUS status = NT_STATUS_OK;
5065 if (!params) {
5066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5067 return;
5070 ZERO_STRUCT(write_time_ts);
5072 if (tran_call == TRANSACT2_QFILEINFO) {
5073 if (total_params < 4) {
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5075 return;
5078 if (IS_IPC(conn)) {
5079 call_trans2qpipeinfo(conn, req, tran_call,
5080 pparams, total_params,
5081 ppdata, total_data,
5082 max_data_bytes);
5083 return;
5086 fsp = file_fsp(req, SVAL(params,0));
5087 info_level = SVAL(params,2);
5089 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5091 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5093 return;
5096 /* Initial check for valid fsp ptr. */
5097 if (!check_fsp_open(conn, req, fsp)) {
5098 return;
5101 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5102 &smb_fname);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 reply_nterror(req, status);
5105 return;
5108 if(fsp->fake_file_handle) {
5110 * This is actually for the QUOTA_FAKE_FILE --metze
5113 /* We know this name is ok, it's already passed the checks. */
5115 } else if(fsp->fh->fd == -1) {
5117 * This is actually a QFILEINFO on a directory
5118 * handle (returned from an NT SMB). NT5.0 seems
5119 * to do this call. JRA.
5122 if (INFO_LEVEL_IS_UNIX(info_level)) {
5123 /* Always do lstat for UNIX calls. */
5124 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5125 DEBUG(3,("call_trans2qfilepathinfo: "
5126 "SMB_VFS_LSTAT of %s failed "
5127 "(%s)\n",
5128 smb_fname_str_dbg(smb_fname),
5129 strerror(errno)));
5130 reply_nterror(req,
5131 map_nt_error_from_unix(errno));
5132 return;
5134 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5135 DEBUG(3,("call_trans2qfilepathinfo: "
5136 "SMB_VFS_STAT of %s failed (%s)\n",
5137 smb_fname_str_dbg(smb_fname),
5138 strerror(errno)));
5139 reply_nterror(req,
5140 map_nt_error_from_unix(errno));
5141 return;
5144 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5145 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5146 } else {
5148 * Original code - this is an open file.
5150 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5151 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5152 fsp->fnum, strerror(errno)));
5153 reply_nterror(req,
5154 map_nt_error_from_unix(errno));
5155 return;
5157 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5158 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5161 } else {
5162 uint32_t name_hash;
5163 char *fname = NULL;
5164 uint32_t ucf_flags = 0;
5166 /* qpathinfo */
5167 if (total_params < 7) {
5168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5169 return;
5172 info_level = SVAL(params,0);
5174 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5176 if (INFO_LEVEL_IS_UNIX(info_level)) {
5177 if (!lp_unix_extensions()) {
5178 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5179 return;
5181 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5182 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5183 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5184 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5188 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5189 total_params - 6,
5190 STR_TERMINATE, &status);
5191 if (!NT_STATUS_IS_OK(status)) {
5192 reply_nterror(req, status);
5193 return;
5196 status = filename_convert(req,
5197 conn,
5198 req->flags2 & FLAGS2_DFS_PATHNAMES,
5199 fname,
5200 ucf_flags,
5201 NULL,
5202 &smb_fname);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5205 reply_botherror(req,
5206 NT_STATUS_PATH_NOT_COVERED,
5207 ERRSRV, ERRbadpath);
5208 return;
5210 reply_nterror(req, status);
5211 return;
5214 /* If this is a stream, check if there is a delete_pending. */
5215 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5216 && is_ntfs_stream_smb_fname(smb_fname)) {
5217 struct smb_filename *smb_fname_base = NULL;
5219 /* Create an smb_filename with stream_name == NULL. */
5220 status =
5221 create_synthetic_smb_fname(talloc_tos(),
5222 smb_fname->base_name,
5223 NULL, NULL,
5224 &smb_fname_base);
5225 if (!NT_STATUS_IS_OK(status)) {
5226 reply_nterror(req, status);
5227 return;
5230 if (INFO_LEVEL_IS_UNIX(info_level)) {
5231 /* Always do lstat for UNIX calls. */
5232 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_LSTAT of %s failed "
5235 "(%s)\n",
5236 smb_fname_str_dbg(smb_fname_base),
5237 strerror(errno)));
5238 TALLOC_FREE(smb_fname_base);
5239 reply_nterror(req,
5240 map_nt_error_from_unix(errno));
5241 return;
5243 } else {
5244 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5245 DEBUG(3,("call_trans2qfilepathinfo: "
5246 "fileinfo of %s failed "
5247 "(%s)\n",
5248 smb_fname_str_dbg(smb_fname_base),
5249 strerror(errno)));
5250 TALLOC_FREE(smb_fname_base);
5251 reply_nterror(req,
5252 map_nt_error_from_unix(errno));
5253 return;
5257 status = file_name_hash(conn,
5258 smb_fname_str_dbg(smb_fname_base),
5259 &name_hash);
5260 if (!NT_STATUS_IS_OK(status)) {
5261 TALLOC_FREE(smb_fname_base);
5262 reply_nterror(req, status);
5263 return;
5266 fileid = vfs_file_id_from_sbuf(conn,
5267 &smb_fname_base->st);
5268 TALLOC_FREE(smb_fname_base);
5269 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5270 if (delete_pending) {
5271 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5272 return;
5276 if (INFO_LEVEL_IS_UNIX(info_level)) {
5277 /* Always do lstat for UNIX calls. */
5278 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5279 DEBUG(3,("call_trans2qfilepathinfo: "
5280 "SMB_VFS_LSTAT of %s failed (%s)\n",
5281 smb_fname_str_dbg(smb_fname),
5282 strerror(errno)));
5283 reply_nterror(req,
5284 map_nt_error_from_unix(errno));
5285 return;
5288 } else {
5289 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5290 DEBUG(3,("call_trans2qfilepathinfo: "
5291 "SMB_VFS_STAT of %s failed (%s)\n",
5292 smb_fname_str_dbg(smb_fname),
5293 strerror(errno)));
5294 reply_nterror(req,
5295 map_nt_error_from_unix(errno));
5296 return;
5300 status = file_name_hash(conn,
5301 smb_fname_str_dbg(smb_fname),
5302 &name_hash);
5303 if (!NT_STATUS_IS_OK(status)) {
5304 reply_nterror(req, status);
5305 return;
5308 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5309 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5310 if (delete_pending) {
5311 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5312 return;
5316 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5317 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5318 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5320 /* Pull out any data sent here before we realloc. */
5321 switch (info_level) {
5322 case SMB_INFO_QUERY_EAS_FROM_LIST:
5324 /* Pull any EA list from the data portion. */
5325 uint32 ea_size;
5327 if (total_data < 4) {
5328 reply_nterror(
5329 req, NT_STATUS_INVALID_PARAMETER);
5330 return;
5332 ea_size = IVAL(pdata,0);
5334 if (total_data > 0 && ea_size != total_data) {
5335 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5336 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5337 reply_nterror(
5338 req, NT_STATUS_INVALID_PARAMETER);
5339 return;
5342 if (!lp_ea_support(SNUM(conn))) {
5343 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5344 return;
5347 /* Pull out the list of names. */
5348 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5349 if (!ea_list) {
5350 reply_nterror(
5351 req, NT_STATUS_INVALID_PARAMETER);
5352 return;
5354 break;
5357 case SMB_QUERY_POSIX_LOCK:
5359 if (fsp == NULL || fsp->fh->fd == -1) {
5360 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5361 return;
5364 if (total_data != POSIX_LOCK_DATA_SIZE) {
5365 reply_nterror(
5366 req, NT_STATUS_INVALID_PARAMETER);
5367 return;
5370 /* Copy the lock range data. */
5371 lock_data = (char *)talloc_memdup(
5372 req, pdata, total_data);
5373 if (!lock_data) {
5374 reply_nterror(req, NT_STATUS_NO_MEMORY);
5375 return;
5377 lock_data_count = total_data;
5379 default:
5380 break;
5383 *pparams = (char *)SMB_REALLOC(*pparams,2);
5384 if (*pparams == NULL) {
5385 reply_nterror(req, NT_STATUS_NO_MEMORY);
5386 return;
5388 params = *pparams;
5389 SSVAL(params,0,0);
5392 * draft-leach-cifs-v1-spec-02.txt
5393 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5394 * says:
5396 * The requested information is placed in the Data portion of the
5397 * transaction response. For the information levels greater than 0x100,
5398 * the transaction response has 1 parameter word which should be
5399 * ignored by the client.
5401 * However Windows only follows this rule for the IS_NAME_VALID call.
5403 switch (info_level) {
5404 case SMB_INFO_IS_NAME_VALID:
5405 param_size = 0;
5406 break;
5409 if ((info_level & 0xFF00) == 0xFF00) {
5411 * We use levels that start with 0xFF00
5412 * internally to represent SMB2 specific levels
5414 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5415 return;
5418 status = smbd_do_qfilepathinfo(conn, req, info_level,
5419 fsp, smb_fname,
5420 delete_pending, write_time_ts,
5421 ea_list,
5422 lock_data_count, lock_data,
5423 req->flags2, max_data_bytes,
5424 ppdata, &data_size);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 reply_nterror(req, status);
5427 return;
5430 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5431 max_data_bytes);
5433 return;
5436 /****************************************************************************
5437 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5438 code.
5439 ****************************************************************************/
5441 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5442 connection_struct *conn,
5443 struct smb_request *req,
5444 bool overwrite_if_exists,
5445 const struct smb_filename *smb_fname_old,
5446 struct smb_filename *smb_fname_new)
5448 NTSTATUS status = NT_STATUS_OK;
5450 /* source must already exist. */
5451 if (!VALID_STAT(smb_fname_old->st)) {
5452 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5455 if (VALID_STAT(smb_fname_new->st)) {
5456 if (overwrite_if_exists) {
5457 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5458 return NT_STATUS_FILE_IS_A_DIRECTORY;
5460 status = unlink_internals(conn,
5461 req,
5462 FILE_ATTRIBUTE_NORMAL,
5463 smb_fname_new,
5464 false);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 return status;
5468 } else {
5469 /* Disallow if newname already exists. */
5470 return NT_STATUS_OBJECT_NAME_COLLISION;
5474 /* No links from a directory. */
5475 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5476 return NT_STATUS_FILE_IS_A_DIRECTORY;
5479 /* Setting a hardlink to/from a stream isn't currently supported. */
5480 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5481 is_ntfs_stream_smb_fname(smb_fname_new)) {
5482 return NT_STATUS_INVALID_PARAMETER;
5485 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5486 smb_fname_old->base_name, smb_fname_new->base_name));
5488 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5489 smb_fname_new->base_name) != 0) {
5490 status = map_nt_error_from_unix(errno);
5491 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5492 nt_errstr(status), smb_fname_old->base_name,
5493 smb_fname_new->base_name));
5495 return status;
5498 /****************************************************************************
5499 Deal with setting the time from any of the setfilepathinfo functions.
5500 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5501 calling this function.
5502 ****************************************************************************/
5504 NTSTATUS smb_set_file_time(connection_struct *conn,
5505 files_struct *fsp,
5506 const struct smb_filename *smb_fname,
5507 struct smb_file_time *ft,
5508 bool setting_write_time)
5510 struct smb_filename smb_fname_base;
5511 uint32 action =
5512 FILE_NOTIFY_CHANGE_LAST_ACCESS
5513 |FILE_NOTIFY_CHANGE_LAST_WRITE
5514 |FILE_NOTIFY_CHANGE_CREATION;
5516 if (!VALID_STAT(smb_fname->st)) {
5517 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5520 /* get some defaults (no modifications) if any info is zero or -1. */
5521 if (null_timespec(ft->create_time)) {
5522 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5525 if (null_timespec(ft->atime)) {
5526 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5529 if (null_timespec(ft->mtime)) {
5530 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5533 if (!setting_write_time) {
5534 /* ft->mtime comes from change time, not write time. */
5535 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5538 /* Ensure the resolution is the correct for
5539 * what we can store on this filesystem. */
5541 round_timespec(conn->ts_res, &ft->create_time);
5542 round_timespec(conn->ts_res, &ft->ctime);
5543 round_timespec(conn->ts_res, &ft->atime);
5544 round_timespec(conn->ts_res, &ft->mtime);
5546 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5547 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5548 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5549 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5550 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5551 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5552 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5553 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5555 if (setting_write_time) {
5557 * This was a Windows setfileinfo on an open file.
5558 * NT does this a lot. We also need to
5559 * set the time here, as it can be read by
5560 * FindFirst/FindNext and with the patch for bug #2045
5561 * in smbd/fileio.c it ensures that this timestamp is
5562 * kept sticky even after a write. We save the request
5563 * away and will set it on file close and after a write. JRA.
5566 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5567 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5569 if (fsp != NULL) {
5570 if (fsp->base_fsp) {
5571 set_sticky_write_time_fsp(fsp->base_fsp,
5572 ft->mtime);
5573 } else {
5574 set_sticky_write_time_fsp(fsp, ft->mtime);
5576 } else {
5577 set_sticky_write_time_path(
5578 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5579 ft->mtime);
5583 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5585 /* Always call ntimes on the base, even if a stream was passed in. */
5586 smb_fname_base = *smb_fname;
5587 smb_fname_base.stream_name = NULL;
5589 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5590 return map_nt_error_from_unix(errno);
5593 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5594 smb_fname->base_name);
5595 return NT_STATUS_OK;
5598 /****************************************************************************
5599 Deal with setting the dosmode from any of the setfilepathinfo functions.
5600 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5601 done before calling this function.
5602 ****************************************************************************/
5604 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5605 const struct smb_filename *smb_fname,
5606 uint32 dosmode)
5608 struct smb_filename *smb_fname_base = NULL;
5609 NTSTATUS status;
5611 if (!VALID_STAT(smb_fname->st)) {
5612 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5615 /* Always operate on the base_name, even if a stream was passed in. */
5616 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5617 NULL, &smb_fname->st,
5618 &smb_fname_base);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 return status;
5623 if (dosmode) {
5624 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5625 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5626 } else {
5627 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5631 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5633 /* check the mode isn't different, before changing it */
5634 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5635 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5636 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5637 (unsigned int)dosmode));
5639 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5640 false)) {
5641 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5642 "%s failed (%s)\n",
5643 smb_fname_str_dbg(smb_fname_base),
5644 strerror(errno)));
5645 status = map_nt_error_from_unix(errno);
5646 goto out;
5649 status = NT_STATUS_OK;
5650 out:
5651 TALLOC_FREE(smb_fname_base);
5652 return status;
5655 /****************************************************************************
5656 Deal with setting the size from any of the setfilepathinfo functions.
5657 ****************************************************************************/
5659 static NTSTATUS smb_set_file_size(connection_struct *conn,
5660 struct smb_request *req,
5661 files_struct *fsp,
5662 const struct smb_filename *smb_fname,
5663 const SMB_STRUCT_STAT *psbuf,
5664 off_t size,
5665 bool fail_after_createfile)
5667 NTSTATUS status = NT_STATUS_OK;
5668 struct smb_filename *smb_fname_tmp = NULL;
5669 files_struct *new_fsp = NULL;
5671 if (!VALID_STAT(*psbuf)) {
5672 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5675 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5677 if (size == get_file_size_stat(psbuf)) {
5678 return NT_STATUS_OK;
5681 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5682 smb_fname_str_dbg(smb_fname), (double)size));
5684 if (fsp && fsp->fh->fd != -1) {
5685 /* Handle based call. */
5686 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5687 return NT_STATUS_ACCESS_DENIED;
5690 if (vfs_set_filelen(fsp, size) == -1) {
5691 return map_nt_error_from_unix(errno);
5693 trigger_write_time_update_immediate(fsp);
5694 return NT_STATUS_OK;
5697 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 return status;
5702 smb_fname_tmp->st = *psbuf;
5704 status = SMB_VFS_CREATE_FILE(
5705 conn, /* conn */
5706 req, /* req */
5707 0, /* root_dir_fid */
5708 smb_fname_tmp, /* fname */
5709 FILE_WRITE_DATA, /* access_mask */
5710 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5711 FILE_SHARE_DELETE),
5712 FILE_OPEN, /* create_disposition*/
5713 0, /* create_options */
5714 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5715 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5716 0, /* allocation_size */
5717 0, /* private_flags */
5718 NULL, /* sd */
5719 NULL, /* ea_list */
5720 &new_fsp, /* result */
5721 NULL); /* pinfo */
5723 TALLOC_FREE(smb_fname_tmp);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 /* NB. We check for open_was_deferred in the caller. */
5727 return status;
5730 /* See RAW-SFILEINFO-END-OF-FILE */
5731 if (fail_after_createfile) {
5732 close_file(req, new_fsp,NORMAL_CLOSE);
5733 return NT_STATUS_INVALID_LEVEL;
5736 if (vfs_set_filelen(new_fsp, size) == -1) {
5737 status = map_nt_error_from_unix(errno);
5738 close_file(req, new_fsp,NORMAL_CLOSE);
5739 return status;
5742 trigger_write_time_update_immediate(new_fsp);
5743 close_file(req, new_fsp,NORMAL_CLOSE);
5744 return NT_STATUS_OK;
5747 /****************************************************************************
5748 Deal with SMB_INFO_SET_EA.
5749 ****************************************************************************/
5751 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5752 const char *pdata,
5753 int total_data,
5754 files_struct *fsp,
5755 const struct smb_filename *smb_fname)
5757 struct ea_list *ea_list = NULL;
5758 TALLOC_CTX *ctx = NULL;
5759 NTSTATUS status = NT_STATUS_OK;
5761 if (total_data < 10) {
5763 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5764 length. They seem to have no effect. Bug #3212. JRA */
5766 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5767 /* We're done. We only get EA info in this call. */
5768 return NT_STATUS_OK;
5771 return NT_STATUS_INVALID_PARAMETER;
5774 if (IVAL(pdata,0) > total_data) {
5775 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5776 IVAL(pdata,0), (unsigned int)total_data));
5777 return NT_STATUS_INVALID_PARAMETER;
5780 ctx = talloc_tos();
5781 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5782 if (!ea_list) {
5783 return NT_STATUS_INVALID_PARAMETER;
5786 status = set_ea(conn, fsp, smb_fname, ea_list);
5788 return status;
5791 /****************************************************************************
5792 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5793 ****************************************************************************/
5795 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5796 const char *pdata,
5797 int total_data,
5798 files_struct *fsp)
5800 struct ea_list *ea_list = NULL;
5801 NTSTATUS status;
5803 if (!fsp) {
5804 return NT_STATUS_INVALID_HANDLE;
5807 if (!lp_ea_support(SNUM(conn))) {
5808 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5809 "EA's not supported.\n",
5810 (unsigned int)total_data));
5811 return NT_STATUS_EAS_NOT_SUPPORTED;
5814 if (total_data < 10) {
5815 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5816 "too small.\n",
5817 (unsigned int)total_data));
5818 return NT_STATUS_INVALID_PARAMETER;
5821 ea_list = read_nttrans_ea_list(talloc_tos(),
5822 pdata,
5823 total_data);
5825 if (!ea_list) {
5826 return NT_STATUS_INVALID_PARAMETER;
5829 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5831 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5832 smb_fname_str_dbg(fsp->fsp_name),
5833 nt_errstr(status) ));
5835 return status;
5839 /****************************************************************************
5840 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5841 ****************************************************************************/
5843 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5844 const char *pdata,
5845 int total_data,
5846 files_struct *fsp,
5847 struct smb_filename *smb_fname)
5849 NTSTATUS status = NT_STATUS_OK;
5850 bool delete_on_close;
5851 uint32 dosmode = 0;
5853 if (total_data < 1) {
5854 return NT_STATUS_INVALID_PARAMETER;
5857 if (fsp == NULL) {
5858 return NT_STATUS_INVALID_HANDLE;
5861 delete_on_close = (CVAL(pdata,0) ? True : False);
5862 dosmode = dos_mode(conn, smb_fname);
5864 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5865 "delete_on_close = %u\n",
5866 smb_fname_str_dbg(smb_fname),
5867 (unsigned int)dosmode,
5868 (unsigned int)delete_on_close ));
5870 if (delete_on_close) {
5871 status = can_set_delete_on_close(fsp, dosmode);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 return status;
5877 /* The set is across all open files on this dev/inode pair. */
5878 if (!set_delete_on_close(fsp, delete_on_close,
5879 conn->session_info->security_token,
5880 conn->session_info->unix_token)) {
5881 return NT_STATUS_ACCESS_DENIED;
5883 return NT_STATUS_OK;
5886 /****************************************************************************
5887 Deal with SMB_FILE_POSITION_INFORMATION.
5888 ****************************************************************************/
5890 static NTSTATUS smb_file_position_information(connection_struct *conn,
5891 const char *pdata,
5892 int total_data,
5893 files_struct *fsp)
5895 uint64_t position_information;
5897 if (total_data < 8) {
5898 return NT_STATUS_INVALID_PARAMETER;
5901 if (fsp == NULL) {
5902 /* Ignore on pathname based set. */
5903 return NT_STATUS_OK;
5906 position_information = (uint64_t)IVAL(pdata,0);
5907 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5909 DEBUG(10,("smb_file_position_information: Set file position "
5910 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5911 (double)position_information));
5912 fsp->fh->position_information = position_information;
5913 return NT_STATUS_OK;
5916 /****************************************************************************
5917 Deal with SMB_FILE_MODE_INFORMATION.
5918 ****************************************************************************/
5920 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5921 const char *pdata,
5922 int total_data)
5924 uint32 mode;
5926 if (total_data < 4) {
5927 return NT_STATUS_INVALID_PARAMETER;
5929 mode = IVAL(pdata,0);
5930 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5931 return NT_STATUS_INVALID_PARAMETER;
5933 return NT_STATUS_OK;
5936 /****************************************************************************
5937 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5938 ****************************************************************************/
5940 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5941 struct smb_request *req,
5942 const char *pdata,
5943 int total_data,
5944 const struct smb_filename *smb_fname)
5946 char *link_target = NULL;
5947 const char *newname = smb_fname->base_name;
5948 TALLOC_CTX *ctx = talloc_tos();
5950 /* Set a symbolic link. */
5951 /* Don't allow this if follow links is false. */
5953 if (total_data == 0) {
5954 return NT_STATUS_INVALID_PARAMETER;
5957 if (!lp_symlinks(SNUM(conn))) {
5958 return NT_STATUS_ACCESS_DENIED;
5961 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5962 total_data, STR_TERMINATE);
5964 if (!link_target) {
5965 return NT_STATUS_INVALID_PARAMETER;
5968 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5969 newname, link_target ));
5971 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5972 return map_nt_error_from_unix(errno);
5975 return NT_STATUS_OK;
5978 /****************************************************************************
5979 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5980 ****************************************************************************/
5982 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5983 struct smb_request *req,
5984 const char *pdata, int total_data,
5985 struct smb_filename *smb_fname_new)
5987 char *oldname = NULL;
5988 struct smb_filename *smb_fname_old = NULL;
5989 TALLOC_CTX *ctx = talloc_tos();
5990 NTSTATUS status = NT_STATUS_OK;
5992 /* Set a hard link. */
5993 if (total_data == 0) {
5994 return NT_STATUS_INVALID_PARAMETER;
5997 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5998 total_data, STR_TERMINATE, &status);
5999 if (!NT_STATUS_IS_OK(status)) {
6000 return status;
6003 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6004 smb_fname_str_dbg(smb_fname_new), oldname));
6006 status = filename_convert(ctx,
6007 conn,
6008 req->flags2 & FLAGS2_DFS_PATHNAMES,
6009 oldname,
6011 NULL,
6012 &smb_fname_old);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 return status;
6017 return hardlink_internals(ctx, conn, req, false,
6018 smb_fname_old, smb_fname_new);
6021 /****************************************************************************
6022 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6023 ****************************************************************************/
6025 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6026 struct smb_request *req,
6027 const char *pdata,
6028 int total_data,
6029 files_struct *fsp,
6030 struct smb_filename *smb_fname_src)
6032 bool overwrite;
6033 uint32_t len;
6034 char *newname = NULL;
6035 struct smb_filename *smb_fname_dst = NULL;
6036 NTSTATUS status = NT_STATUS_OK;
6037 TALLOC_CTX *ctx = talloc_tos();
6039 if (!fsp) {
6040 return NT_STATUS_INVALID_HANDLE;
6043 if (total_data < 20) {
6044 return NT_STATUS_INVALID_PARAMETER;
6047 overwrite = (CVAL(pdata,0) ? True : False);
6048 len = IVAL(pdata,16);
6050 if (len > (total_data - 20) || (len == 0)) {
6051 return NT_STATUS_INVALID_PARAMETER;
6054 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6055 &pdata[20], len, STR_TERMINATE,
6056 &status);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 return status;
6061 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6062 newname));
6064 status = filename_convert(ctx,
6065 conn,
6066 req->flags2 & FLAGS2_DFS_PATHNAMES,
6067 newname,
6068 UCF_SAVE_LCOMP,
6069 NULL,
6070 &smb_fname_dst);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 return status;
6075 if (fsp->base_fsp) {
6076 /* newname must be a stream name. */
6077 if (newname[0] != ':') {
6078 return NT_STATUS_NOT_SUPPORTED;
6081 /* Create an smb_fname to call rename_internals_fsp() with. */
6082 status = create_synthetic_smb_fname(talloc_tos(),
6083 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6084 &smb_fname_dst);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 goto out;
6090 * Set the original last component, since
6091 * rename_internals_fsp() requires it.
6093 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6094 newname);
6095 if (smb_fname_dst->original_lcomp == NULL) {
6096 status = NT_STATUS_NO_MEMORY;
6097 goto out;
6102 DEBUG(10,("smb2_file_rename_information: "
6103 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6104 fsp->fnum, fsp_str_dbg(fsp),
6105 smb_fname_str_dbg(smb_fname_dst)));
6106 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6107 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6108 overwrite);
6110 out:
6111 TALLOC_FREE(smb_fname_dst);
6112 return status;
6115 static NTSTATUS smb_file_link_information(connection_struct *conn,
6116 struct smb_request *req,
6117 const char *pdata,
6118 int total_data,
6119 files_struct *fsp,
6120 struct smb_filename *smb_fname_src)
6122 bool overwrite;
6123 uint32_t len;
6124 char *newname = NULL;
6125 struct smb_filename *smb_fname_dst = NULL;
6126 NTSTATUS status = NT_STATUS_OK;
6127 TALLOC_CTX *ctx = talloc_tos();
6129 if (!fsp) {
6130 return NT_STATUS_INVALID_HANDLE;
6133 if (total_data < 20) {
6134 return NT_STATUS_INVALID_PARAMETER;
6137 overwrite = (CVAL(pdata,0) ? true : false);
6138 len = IVAL(pdata,16);
6140 if (len > (total_data - 20) || (len == 0)) {
6141 return NT_STATUS_INVALID_PARAMETER;
6144 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6145 &pdata[20], len, STR_TERMINATE,
6146 &status);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 return status;
6151 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6152 newname));
6154 status = filename_convert(ctx,
6155 conn,
6156 req->flags2 & FLAGS2_DFS_PATHNAMES,
6157 newname,
6158 UCF_SAVE_LCOMP,
6159 NULL,
6160 &smb_fname_dst);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 return status;
6165 if (fsp->base_fsp) {
6166 /* No stream names. */
6167 return NT_STATUS_NOT_SUPPORTED;
6170 DEBUG(10,("smb_file_link_information: "
6171 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6172 fsp->fnum, fsp_str_dbg(fsp),
6173 smb_fname_str_dbg(smb_fname_dst)));
6174 status = hardlink_internals(ctx,
6175 conn,
6176 req,
6177 overwrite,
6178 fsp->fsp_name,
6179 smb_fname_dst);
6181 TALLOC_FREE(smb_fname_dst);
6182 return status;
6185 /****************************************************************************
6186 Deal with SMB_FILE_RENAME_INFORMATION.
6187 ****************************************************************************/
6189 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6190 struct smb_request *req,
6191 const char *pdata,
6192 int total_data,
6193 files_struct *fsp,
6194 struct smb_filename *smb_fname_src)
6196 bool overwrite;
6197 uint32 root_fid;
6198 uint32 len;
6199 char *newname = NULL;
6200 struct smb_filename *smb_fname_dst = NULL;
6201 bool dest_has_wcard = False;
6202 NTSTATUS status = NT_STATUS_OK;
6203 char *p;
6204 TALLOC_CTX *ctx = talloc_tos();
6206 if (total_data < 13) {
6207 return NT_STATUS_INVALID_PARAMETER;
6210 overwrite = (CVAL(pdata,0) ? True : False);
6211 root_fid = IVAL(pdata,4);
6212 len = IVAL(pdata,8);
6214 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6215 return NT_STATUS_INVALID_PARAMETER;
6218 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6219 len, 0, &status,
6220 &dest_has_wcard);
6221 if (!NT_STATUS_IS_OK(status)) {
6222 return status;
6225 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6226 newname));
6228 status = resolve_dfspath_wcard(ctx, conn,
6229 req->flags2 & FLAGS2_DFS_PATHNAMES,
6230 newname,
6231 true,
6232 &newname,
6233 &dest_has_wcard);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 return status;
6238 /* Check the new name has no '/' characters. */
6239 if (strchr_m(newname, '/')) {
6240 return NT_STATUS_NOT_SUPPORTED;
6243 if (fsp && fsp->base_fsp) {
6244 /* newname must be a stream name. */
6245 if (newname[0] != ':') {
6246 return NT_STATUS_NOT_SUPPORTED;
6249 /* Create an smb_fname to call rename_internals_fsp() with. */
6250 status = create_synthetic_smb_fname(talloc_tos(),
6251 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6252 &smb_fname_dst);
6253 if (!NT_STATUS_IS_OK(status)) {
6254 goto out;
6258 * Set the original last component, since
6259 * rename_internals_fsp() requires it.
6261 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6262 newname);
6263 if (smb_fname_dst->original_lcomp == NULL) {
6264 status = NT_STATUS_NO_MEMORY;
6265 goto out;
6268 } else {
6270 * Build up an smb_fname_dst based on the filename passed in.
6271 * We basically just strip off the last component, and put on
6272 * the newname instead.
6274 char *base_name = NULL;
6276 /* newname must *not* be a stream name. */
6277 if (newname[0] == ':') {
6278 return NT_STATUS_NOT_SUPPORTED;
6282 * Strip off the last component (filename) of the path passed
6283 * in.
6285 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6286 if (!base_name) {
6287 return NT_STATUS_NO_MEMORY;
6289 p = strrchr_m(base_name, '/');
6290 if (p) {
6291 p[1] = '\0';
6292 } else {
6293 base_name = talloc_strdup(ctx, "");
6294 if (!base_name) {
6295 return NT_STATUS_NO_MEMORY;
6298 /* Append the new name. */
6299 base_name = talloc_asprintf_append(base_name,
6300 "%s",
6301 newname);
6302 if (!base_name) {
6303 return NT_STATUS_NO_MEMORY;
6306 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6307 (UCF_SAVE_LCOMP |
6308 (dest_has_wcard ?
6309 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6310 0)));
6312 /* If an error we expect this to be
6313 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6315 if (!NT_STATUS_IS_OK(status)) {
6316 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6317 status)) {
6318 goto out;
6320 /* Create an smb_fname to call rename_internals_fsp() */
6321 status = create_synthetic_smb_fname(ctx,
6322 base_name, NULL,
6323 NULL,
6324 &smb_fname_dst);
6325 if (!NT_STATUS_IS_OK(status)) {
6326 goto out;
6331 if (fsp) {
6332 DEBUG(10,("smb_file_rename_information: "
6333 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6334 fsp->fnum, fsp_str_dbg(fsp),
6335 smb_fname_str_dbg(smb_fname_dst)));
6336 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6337 overwrite);
6338 } else {
6339 DEBUG(10,("smb_file_rename_information: "
6340 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6341 smb_fname_str_dbg(smb_fname_src),
6342 smb_fname_str_dbg(smb_fname_dst)));
6343 status = rename_internals(ctx, conn, req, smb_fname_src,
6344 smb_fname_dst, 0, overwrite, false,
6345 dest_has_wcard,
6346 FILE_WRITE_ATTRIBUTES);
6348 out:
6349 TALLOC_FREE(smb_fname_dst);
6350 return status;
6353 /****************************************************************************
6354 Deal with SMB_SET_POSIX_ACL.
6355 ****************************************************************************/
6357 #if defined(HAVE_POSIX_ACLS)
6358 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6359 const char *pdata,
6360 int total_data,
6361 files_struct *fsp,
6362 const struct smb_filename *smb_fname)
6364 uint16 posix_acl_version;
6365 uint16 num_file_acls;
6366 uint16 num_def_acls;
6367 bool valid_file_acls = True;
6368 bool valid_def_acls = True;
6370 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6371 return NT_STATUS_INVALID_PARAMETER;
6373 posix_acl_version = SVAL(pdata,0);
6374 num_file_acls = SVAL(pdata,2);
6375 num_def_acls = SVAL(pdata,4);
6377 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6378 valid_file_acls = False;
6379 num_file_acls = 0;
6382 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6383 valid_def_acls = False;
6384 num_def_acls = 0;
6387 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6388 return NT_STATUS_INVALID_PARAMETER;
6391 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6392 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6393 return NT_STATUS_INVALID_PARAMETER;
6396 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6397 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6398 (unsigned int)num_file_acls,
6399 (unsigned int)num_def_acls));
6401 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6402 smb_fname->base_name, num_file_acls,
6403 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6404 return map_nt_error_from_unix(errno);
6407 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6408 smb_fname->base_name, &smb_fname->st, num_def_acls,
6409 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6410 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6411 return map_nt_error_from_unix(errno);
6413 return NT_STATUS_OK;
6415 #endif
6417 /****************************************************************************
6418 Deal with SMB_SET_POSIX_LOCK.
6419 ****************************************************************************/
6421 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6422 struct smb_request *req,
6423 const char *pdata,
6424 int total_data,
6425 files_struct *fsp)
6427 uint64_t count;
6428 uint64_t offset;
6429 uint64_t smblctx;
6430 bool blocking_lock = False;
6431 enum brl_type lock_type;
6433 NTSTATUS status = NT_STATUS_OK;
6435 if (fsp == NULL || fsp->fh->fd == -1) {
6436 return NT_STATUS_INVALID_HANDLE;
6439 if (total_data != POSIX_LOCK_DATA_SIZE) {
6440 return NT_STATUS_INVALID_PARAMETER;
6443 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6444 case POSIX_LOCK_TYPE_READ:
6445 lock_type = READ_LOCK;
6446 break;
6447 case POSIX_LOCK_TYPE_WRITE:
6448 /* Return the right POSIX-mappable error code for files opened read-only. */
6449 if (!fsp->can_write) {
6450 return NT_STATUS_INVALID_HANDLE;
6452 lock_type = WRITE_LOCK;
6453 break;
6454 case POSIX_LOCK_TYPE_UNLOCK:
6455 lock_type = UNLOCK_LOCK;
6456 break;
6457 default:
6458 return NT_STATUS_INVALID_PARAMETER;
6461 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6462 blocking_lock = False;
6463 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6464 blocking_lock = True;
6465 } else {
6466 return NT_STATUS_INVALID_PARAMETER;
6469 if (!lp_blocking_locks(SNUM(conn))) {
6470 blocking_lock = False;
6473 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6474 #if defined(HAVE_LONGLONG)
6475 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6476 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6477 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6478 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6479 #else /* HAVE_LONGLONG */
6480 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6481 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6482 #endif /* HAVE_LONGLONG */
6484 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6485 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6486 fsp_str_dbg(fsp),
6487 (unsigned int)lock_type,
6488 (unsigned long long)smblctx,
6489 (double)count,
6490 (double)offset ));
6492 if (lock_type == UNLOCK_LOCK) {
6493 status = do_unlock(req->sconn->msg_ctx,
6494 fsp,
6495 smblctx,
6496 count,
6497 offset,
6498 POSIX_LOCK);
6499 } else {
6500 uint64_t block_smblctx;
6502 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6503 fsp,
6504 smblctx,
6505 count,
6506 offset,
6507 lock_type,
6508 POSIX_LOCK,
6509 blocking_lock,
6510 &status,
6511 &block_smblctx,
6512 NULL);
6514 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6516 * A blocking lock was requested. Package up
6517 * this smb into a queued request and push it
6518 * onto the blocking lock queue.
6520 if(push_blocking_lock_request(br_lck,
6521 req,
6522 fsp,
6523 -1, /* infinite timeout. */
6525 smblctx,
6526 lock_type,
6527 POSIX_LOCK,
6528 offset,
6529 count,
6530 block_smblctx)) {
6531 TALLOC_FREE(br_lck);
6532 return status;
6535 TALLOC_FREE(br_lck);
6538 return status;
6541 /****************************************************************************
6542 Deal with SMB_SET_FILE_BASIC_INFO.
6543 ****************************************************************************/
6545 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6546 const char *pdata,
6547 int total_data,
6548 files_struct *fsp,
6549 const struct smb_filename *smb_fname)
6551 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6552 struct smb_file_time ft;
6553 uint32 dosmode = 0;
6554 NTSTATUS status = NT_STATUS_OK;
6556 ZERO_STRUCT(ft);
6558 if (total_data < 36) {
6559 return NT_STATUS_INVALID_PARAMETER;
6562 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6563 if (!NT_STATUS_IS_OK(status)) {
6564 return status;
6567 /* Set the attributes */
6568 dosmode = IVAL(pdata,32);
6569 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6570 if (!NT_STATUS_IS_OK(status)) {
6571 return status;
6574 /* create time */
6575 ft.create_time = interpret_long_date(pdata);
6577 /* access time */
6578 ft.atime = interpret_long_date(pdata+8);
6580 /* write time. */
6581 ft.mtime = interpret_long_date(pdata+16);
6583 /* change time. */
6584 ft.ctime = interpret_long_date(pdata+24);
6586 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6587 smb_fname_str_dbg(smb_fname)));
6589 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6590 true);
6593 /****************************************************************************
6594 Deal with SMB_INFO_STANDARD.
6595 ****************************************************************************/
6597 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6598 const char *pdata,
6599 int total_data,
6600 files_struct *fsp,
6601 const struct smb_filename *smb_fname)
6603 NTSTATUS status;
6604 struct smb_file_time ft;
6606 ZERO_STRUCT(ft);
6608 if (total_data < 12) {
6609 return NT_STATUS_INVALID_PARAMETER;
6612 /* create time */
6613 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6614 /* access time */
6615 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6616 /* write time */
6617 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6619 DEBUG(10,("smb_set_info_standard: file %s\n",
6620 smb_fname_str_dbg(smb_fname)));
6622 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6623 if (!NT_STATUS_IS_OK(status)) {
6624 return status;
6627 return smb_set_file_time(conn,
6628 fsp,
6629 smb_fname,
6630 &ft,
6631 true);
6634 /****************************************************************************
6635 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6636 ****************************************************************************/
6638 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6639 struct smb_request *req,
6640 const char *pdata,
6641 int total_data,
6642 files_struct *fsp,
6643 struct smb_filename *smb_fname)
6645 uint64_t allocation_size = 0;
6646 NTSTATUS status = NT_STATUS_OK;
6647 files_struct *new_fsp = NULL;
6649 if (!VALID_STAT(smb_fname->st)) {
6650 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6653 if (total_data < 8) {
6654 return NT_STATUS_INVALID_PARAMETER;
6657 allocation_size = (uint64_t)IVAL(pdata,0);
6658 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6659 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6660 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6661 (double)allocation_size));
6663 if (allocation_size) {
6664 allocation_size = smb_roundup(conn, allocation_size);
6667 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6668 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6669 (double)allocation_size));
6671 if (fsp && fsp->fh->fd != -1) {
6672 /* Open file handle. */
6673 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6674 return NT_STATUS_ACCESS_DENIED;
6677 /* Only change if needed. */
6678 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6679 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6680 return map_nt_error_from_unix(errno);
6683 /* But always update the time. */
6685 * This is equivalent to a write. Ensure it's seen immediately
6686 * if there are no pending writes.
6688 trigger_write_time_update_immediate(fsp);
6689 return NT_STATUS_OK;
6692 /* Pathname or stat or directory file. */
6693 status = SMB_VFS_CREATE_FILE(
6694 conn, /* conn */
6695 req, /* req */
6696 0, /* root_dir_fid */
6697 smb_fname, /* fname */
6698 FILE_WRITE_DATA, /* access_mask */
6699 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6700 FILE_SHARE_DELETE),
6701 FILE_OPEN, /* create_disposition*/
6702 0, /* create_options */
6703 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6704 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6705 0, /* allocation_size */
6706 0, /* private_flags */
6707 NULL, /* sd */
6708 NULL, /* ea_list */
6709 &new_fsp, /* result */
6710 NULL); /* pinfo */
6712 if (!NT_STATUS_IS_OK(status)) {
6713 /* NB. We check for open_was_deferred in the caller. */
6714 return status;
6717 /* Only change if needed. */
6718 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6719 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6720 status = map_nt_error_from_unix(errno);
6721 close_file(req, new_fsp, NORMAL_CLOSE);
6722 return status;
6726 /* Changing the allocation size should set the last mod time. */
6728 * This is equivalent to a write. Ensure it's seen immediately
6729 * if there are no pending writes.
6731 trigger_write_time_update_immediate(new_fsp);
6733 close_file(req, new_fsp, NORMAL_CLOSE);
6734 return NT_STATUS_OK;
6737 /****************************************************************************
6738 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6739 ****************************************************************************/
6741 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6742 struct smb_request *req,
6743 const char *pdata,
6744 int total_data,
6745 files_struct *fsp,
6746 const struct smb_filename *smb_fname,
6747 bool fail_after_createfile)
6749 off_t size;
6751 if (total_data < 8) {
6752 return NT_STATUS_INVALID_PARAMETER;
6755 size = IVAL(pdata,0);
6756 size |= (((off_t)IVAL(pdata,4)) << 32);
6757 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6758 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6759 (double)size));
6761 return smb_set_file_size(conn, req,
6762 fsp,
6763 smb_fname,
6764 &smb_fname->st,
6765 size,
6766 fail_after_createfile);
6769 /****************************************************************************
6770 Allow a UNIX info mknod.
6771 ****************************************************************************/
6773 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6774 const char *pdata,
6775 int total_data,
6776 const struct smb_filename *smb_fname)
6778 uint32 file_type = IVAL(pdata,56);
6779 #if defined(HAVE_MAKEDEV)
6780 uint32 dev_major = IVAL(pdata,60);
6781 uint32 dev_minor = IVAL(pdata,68);
6782 #endif
6783 SMB_DEV_T dev = (SMB_DEV_T)0;
6784 uint32 raw_unixmode = IVAL(pdata,84);
6785 NTSTATUS status;
6786 mode_t unixmode;
6788 if (total_data < 100) {
6789 return NT_STATUS_INVALID_PARAMETER;
6792 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6793 PERM_NEW_FILE, &unixmode);
6794 if (!NT_STATUS_IS_OK(status)) {
6795 return status;
6798 #if defined(HAVE_MAKEDEV)
6799 dev = makedev(dev_major, dev_minor);
6800 #endif
6802 switch (file_type) {
6803 #if defined(S_IFIFO)
6804 case UNIX_TYPE_FIFO:
6805 unixmode |= S_IFIFO;
6806 break;
6807 #endif
6808 #if defined(S_IFSOCK)
6809 case UNIX_TYPE_SOCKET:
6810 unixmode |= S_IFSOCK;
6811 break;
6812 #endif
6813 #if defined(S_IFCHR)
6814 case UNIX_TYPE_CHARDEV:
6815 unixmode |= S_IFCHR;
6816 break;
6817 #endif
6818 #if defined(S_IFBLK)
6819 case UNIX_TYPE_BLKDEV:
6820 unixmode |= S_IFBLK;
6821 break;
6822 #endif
6823 default:
6824 return NT_STATUS_INVALID_PARAMETER;
6827 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6828 "%.0f mode 0%o for file %s\n", (double)dev,
6829 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6831 /* Ok - do the mknod. */
6832 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6833 return map_nt_error_from_unix(errno);
6836 /* If any of the other "set" calls fail we
6837 * don't want to end up with a half-constructed mknod.
6840 if (lp_inherit_perms(SNUM(conn))) {
6841 char *parent;
6842 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6843 &parent, NULL)) {
6844 return NT_STATUS_NO_MEMORY;
6846 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6847 unixmode);
6848 TALLOC_FREE(parent);
6851 return NT_STATUS_OK;
6854 /****************************************************************************
6855 Deal with SMB_SET_FILE_UNIX_BASIC.
6856 ****************************************************************************/
6858 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6859 struct smb_request *req,
6860 const char *pdata,
6861 int total_data,
6862 files_struct *fsp,
6863 const struct smb_filename *smb_fname)
6865 struct smb_file_time ft;
6866 uint32 raw_unixmode;
6867 mode_t unixmode;
6868 off_t size = 0;
6869 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6870 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6871 NTSTATUS status = NT_STATUS_OK;
6872 bool delete_on_fail = False;
6873 enum perm_type ptype;
6874 files_struct *all_fsps = NULL;
6875 bool modify_mtime = true;
6876 struct file_id id;
6877 struct smb_filename *smb_fname_tmp = NULL;
6878 SMB_STRUCT_STAT sbuf;
6880 ZERO_STRUCT(ft);
6882 if (total_data < 100) {
6883 return NT_STATUS_INVALID_PARAMETER;
6886 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6887 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6888 size=IVAL(pdata,0); /* first 8 Bytes are size */
6889 size |= (((off_t)IVAL(pdata,4)) << 32);
6892 ft.atime = interpret_long_date(pdata+24); /* access_time */
6893 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6894 set_owner = (uid_t)IVAL(pdata,40);
6895 set_grp = (gid_t)IVAL(pdata,48);
6896 raw_unixmode = IVAL(pdata,84);
6898 if (VALID_STAT(smb_fname->st)) {
6899 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6900 ptype = PERM_EXISTING_DIR;
6901 } else {
6902 ptype = PERM_EXISTING_FILE;
6904 } else {
6905 ptype = PERM_NEW_FILE;
6908 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6909 ptype, &unixmode);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 return status;
6914 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6915 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6916 smb_fname_str_dbg(smb_fname), (double)size,
6917 (unsigned int)set_owner, (unsigned int)set_grp,
6918 (int)raw_unixmode));
6920 sbuf = smb_fname->st;
6922 if (!VALID_STAT(sbuf)) {
6924 * The only valid use of this is to create character and block
6925 * devices, and named pipes. This is deprecated (IMHO) and
6926 * a new info level should be used for mknod. JRA.
6929 status = smb_unix_mknod(conn,
6930 pdata,
6931 total_data,
6932 smb_fname);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 return status;
6937 status = copy_smb_filename(talloc_tos(), smb_fname,
6938 &smb_fname_tmp);
6939 if (!NT_STATUS_IS_OK(status)) {
6940 return status;
6943 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6944 status = map_nt_error_from_unix(errno);
6945 TALLOC_FREE(smb_fname_tmp);
6946 SMB_VFS_UNLINK(conn, smb_fname);
6947 return status;
6950 sbuf = smb_fname_tmp->st;
6951 smb_fname = smb_fname_tmp;
6953 /* Ensure we don't try and change anything else. */
6954 raw_unixmode = SMB_MODE_NO_CHANGE;
6955 size = get_file_size_stat(&sbuf);
6956 ft.atime = sbuf.st_ex_atime;
6957 ft.mtime = sbuf.st_ex_mtime;
6959 * We continue here as we might want to change the
6960 * owner uid/gid.
6962 delete_on_fail = True;
6965 #if 1
6966 /* Horrible backwards compatibility hack as an old server bug
6967 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6968 * */
6970 if (!size) {
6971 size = get_file_size_stat(&sbuf);
6973 #endif
6976 * Deal with the UNIX specific mode set.
6979 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6980 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6981 "setting mode 0%o for file %s\n",
6982 (unsigned int)unixmode,
6983 smb_fname_str_dbg(smb_fname)));
6984 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6985 return map_nt_error_from_unix(errno);
6990 * Deal with the UNIX specific uid set.
6993 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6994 (sbuf.st_ex_uid != set_owner)) {
6995 int ret;
6997 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6998 "changing owner %u for path %s\n",
6999 (unsigned int)set_owner,
7000 smb_fname_str_dbg(smb_fname)));
7002 if (S_ISLNK(sbuf.st_ex_mode)) {
7003 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7004 set_owner, (gid_t)-1);
7005 } else {
7006 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7007 set_owner, (gid_t)-1);
7010 if (ret != 0) {
7011 status = map_nt_error_from_unix(errno);
7012 if (delete_on_fail) {
7013 SMB_VFS_UNLINK(conn, smb_fname);
7015 return status;
7020 * Deal with the UNIX specific gid set.
7023 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7024 (sbuf.st_ex_gid != set_grp)) {
7025 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7026 "changing group %u for file %s\n",
7027 (unsigned int)set_owner,
7028 smb_fname_str_dbg(smb_fname)));
7029 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7030 set_grp) != 0) {
7031 status = map_nt_error_from_unix(errno);
7032 if (delete_on_fail) {
7033 SMB_VFS_UNLINK(conn, smb_fname);
7035 return status;
7039 /* Deal with any size changes. */
7041 status = smb_set_file_size(conn, req,
7042 fsp,
7043 smb_fname,
7044 &sbuf,
7045 size,
7046 false);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 return status;
7051 /* Deal with any time changes. */
7052 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7053 /* No change, don't cancel anything. */
7054 return status;
7057 id = vfs_file_id_from_sbuf(conn, &sbuf);
7058 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7059 all_fsps = file_find_di_next(all_fsps)) {
7061 * We're setting the time explicitly for UNIX.
7062 * Cancel any pending changes over all handles.
7064 all_fsps->update_write_time_on_close = false;
7065 TALLOC_FREE(all_fsps->update_write_time_event);
7069 * Override the "setting_write_time"
7070 * parameter here as it almost does what
7071 * we need. Just remember if we modified
7072 * mtime and send the notify ourselves.
7074 if (null_timespec(ft.mtime)) {
7075 modify_mtime = false;
7078 status = smb_set_file_time(conn,
7079 fsp,
7080 smb_fname,
7081 &ft,
7082 false);
7083 if (modify_mtime) {
7084 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7085 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7087 return status;
7090 /****************************************************************************
7091 Deal with SMB_SET_FILE_UNIX_INFO2.
7092 ****************************************************************************/
7094 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7095 struct smb_request *req,
7096 const char *pdata,
7097 int total_data,
7098 files_struct *fsp,
7099 const struct smb_filename *smb_fname)
7101 NTSTATUS status;
7102 uint32 smb_fflags;
7103 uint32 smb_fmask;
7105 if (total_data < 116) {
7106 return NT_STATUS_INVALID_PARAMETER;
7109 /* Start by setting all the fields that are common between UNIX_BASIC
7110 * and UNIX_INFO2.
7112 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7113 fsp, smb_fname);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 return status;
7118 smb_fflags = IVAL(pdata, 108);
7119 smb_fmask = IVAL(pdata, 112);
7121 /* NB: We should only attempt to alter the file flags if the client
7122 * sends a non-zero mask.
7124 if (smb_fmask != 0) {
7125 int stat_fflags = 0;
7127 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7128 smb_fmask, &stat_fflags)) {
7129 /* Client asked to alter a flag we don't understand. */
7130 return NT_STATUS_INVALID_PARAMETER;
7133 if (fsp && fsp->fh->fd != -1) {
7134 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7135 return NT_STATUS_NOT_SUPPORTED;
7136 } else {
7137 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7138 stat_fflags) != 0) {
7139 return map_nt_error_from_unix(errno);
7144 /* XXX: need to add support for changing the create_time here. You
7145 * can do this for paths on Darwin with setattrlist(2). The right way
7146 * to hook this up is probably by extending the VFS utimes interface.
7149 return NT_STATUS_OK;
7152 /****************************************************************************
7153 Create a directory with POSIX semantics.
7154 ****************************************************************************/
7156 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7157 struct smb_request *req,
7158 char **ppdata,
7159 int total_data,
7160 struct smb_filename *smb_fname,
7161 int *pdata_return_size)
7163 NTSTATUS status = NT_STATUS_OK;
7164 uint32 raw_unixmode = 0;
7165 uint32 mod_unixmode = 0;
7166 mode_t unixmode = (mode_t)0;
7167 files_struct *fsp = NULL;
7168 uint16 info_level_return = 0;
7169 int info;
7170 char *pdata = *ppdata;
7172 if (total_data < 18) {
7173 return NT_STATUS_INVALID_PARAMETER;
7176 raw_unixmode = IVAL(pdata,8);
7177 /* Next 4 bytes are not yet defined. */
7179 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7180 PERM_NEW_DIR, &unixmode);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 return status;
7185 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7187 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7188 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7190 status = SMB_VFS_CREATE_FILE(
7191 conn, /* conn */
7192 req, /* req */
7193 0, /* root_dir_fid */
7194 smb_fname, /* fname */
7195 FILE_READ_ATTRIBUTES, /* access_mask */
7196 FILE_SHARE_NONE, /* share_access */
7197 FILE_CREATE, /* create_disposition*/
7198 FILE_DIRECTORY_FILE, /* create_options */
7199 mod_unixmode, /* file_attributes */
7200 0, /* oplock_request */
7201 0, /* allocation_size */
7202 0, /* private_flags */
7203 NULL, /* sd */
7204 NULL, /* ea_list */
7205 &fsp, /* result */
7206 &info); /* pinfo */
7208 if (NT_STATUS_IS_OK(status)) {
7209 close_file(req, fsp, NORMAL_CLOSE);
7212 info_level_return = SVAL(pdata,16);
7214 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7215 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7216 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7217 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7218 } else {
7219 *pdata_return_size = 12;
7222 /* Realloc the data size */
7223 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7224 if (*ppdata == NULL) {
7225 *pdata_return_size = 0;
7226 return NT_STATUS_NO_MEMORY;
7228 pdata = *ppdata;
7230 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7231 SSVAL(pdata,2,0); /* No fnum. */
7232 SIVAL(pdata,4,info); /* Was directory created. */
7234 switch (info_level_return) {
7235 case SMB_QUERY_FILE_UNIX_BASIC:
7236 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7237 SSVAL(pdata,10,0); /* Padding. */
7238 store_file_unix_basic(conn, pdata + 12, fsp,
7239 &smb_fname->st);
7240 break;
7241 case SMB_QUERY_FILE_UNIX_INFO2:
7242 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7243 SSVAL(pdata,10,0); /* Padding. */
7244 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7245 &smb_fname->st);
7246 break;
7247 default:
7248 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7249 SSVAL(pdata,10,0); /* Padding. */
7250 break;
7253 return status;
7256 /****************************************************************************
7257 Open/Create a file with POSIX semantics.
7258 ****************************************************************************/
7260 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7261 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7263 static NTSTATUS smb_posix_open(connection_struct *conn,
7264 struct smb_request *req,
7265 char **ppdata,
7266 int total_data,
7267 struct smb_filename *smb_fname,
7268 int *pdata_return_size)
7270 bool extended_oplock_granted = False;
7271 char *pdata = *ppdata;
7272 uint32 flags = 0;
7273 uint32 wire_open_mode = 0;
7274 uint32 raw_unixmode = 0;
7275 uint32 mod_unixmode = 0;
7276 uint32 create_disp = 0;
7277 uint32 access_mask = 0;
7278 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7279 NTSTATUS status = NT_STATUS_OK;
7280 mode_t unixmode = (mode_t)0;
7281 files_struct *fsp = NULL;
7282 int oplock_request = 0;
7283 int info = 0;
7284 uint16 info_level_return = 0;
7286 if (total_data < 18) {
7287 return NT_STATUS_INVALID_PARAMETER;
7290 flags = IVAL(pdata,0);
7291 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7292 if (oplock_request) {
7293 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7296 wire_open_mode = IVAL(pdata,4);
7298 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7299 return smb_posix_mkdir(conn, req,
7300 ppdata,
7301 total_data,
7302 smb_fname,
7303 pdata_return_size);
7306 switch (wire_open_mode & SMB_ACCMODE) {
7307 case SMB_O_RDONLY:
7308 access_mask = SMB_O_RDONLY_MAPPING;
7309 break;
7310 case SMB_O_WRONLY:
7311 access_mask = SMB_O_WRONLY_MAPPING;
7312 break;
7313 case SMB_O_RDWR:
7314 access_mask = (SMB_O_RDONLY_MAPPING|
7315 SMB_O_WRONLY_MAPPING);
7316 break;
7317 default:
7318 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7319 (unsigned int)wire_open_mode ));
7320 return NT_STATUS_INVALID_PARAMETER;
7323 wire_open_mode &= ~SMB_ACCMODE;
7325 /* First take care of O_CREAT|O_EXCL interactions. */
7326 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7327 case (SMB_O_CREAT | SMB_O_EXCL):
7328 /* File exists fail. File not exist create. */
7329 create_disp = FILE_CREATE;
7330 break;
7331 case SMB_O_CREAT:
7332 /* File exists open. File not exist create. */
7333 create_disp = FILE_OPEN_IF;
7334 break;
7335 case 0:
7336 /* File exists open. File not exist fail. */
7337 create_disp = FILE_OPEN;
7338 break;
7339 case SMB_O_EXCL:
7340 /* O_EXCL on its own without O_CREAT is undefined. */
7341 default:
7342 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7343 (unsigned int)wire_open_mode ));
7344 return NT_STATUS_INVALID_PARAMETER;
7347 /* Next factor in the effects of O_TRUNC. */
7348 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7350 if (wire_open_mode & SMB_O_TRUNC) {
7351 switch (create_disp) {
7352 case FILE_CREATE:
7353 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7354 /* Leave create_disp alone as
7355 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7357 /* File exists fail. File not exist create. */
7358 break;
7359 case FILE_OPEN_IF:
7360 /* SMB_O_CREAT | SMB_O_TRUNC */
7361 /* File exists overwrite. File not exist create. */
7362 create_disp = FILE_OVERWRITE_IF;
7363 break;
7364 case FILE_OPEN:
7365 /* SMB_O_TRUNC */
7366 /* File exists overwrite. File not exist fail. */
7367 create_disp = FILE_OVERWRITE;
7368 break;
7369 default:
7370 /* Cannot get here. */
7371 smb_panic("smb_posix_open: logic error");
7372 return NT_STATUS_INVALID_PARAMETER;
7376 raw_unixmode = IVAL(pdata,8);
7377 /* Next 4 bytes are not yet defined. */
7379 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7380 (VALID_STAT(smb_fname->st) ?
7381 PERM_EXISTING_FILE : PERM_NEW_FILE),
7382 &unixmode);
7384 if (!NT_STATUS_IS_OK(status)) {
7385 return status;
7388 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7390 if (wire_open_mode & SMB_O_SYNC) {
7391 create_options |= FILE_WRITE_THROUGH;
7393 if (wire_open_mode & SMB_O_APPEND) {
7394 access_mask |= FILE_APPEND_DATA;
7396 if (wire_open_mode & SMB_O_DIRECT) {
7397 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7400 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7401 VALID_STAT_OF_DIR(smb_fname->st)) {
7402 if (access_mask != SMB_O_RDONLY_MAPPING) {
7403 return NT_STATUS_FILE_IS_A_DIRECTORY;
7405 create_options &= ~FILE_NON_DIRECTORY_FILE;
7406 create_options |= FILE_DIRECTORY_FILE;
7409 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7410 smb_fname_str_dbg(smb_fname),
7411 (unsigned int)wire_open_mode,
7412 (unsigned int)unixmode ));
7414 status = SMB_VFS_CREATE_FILE(
7415 conn, /* conn */
7416 req, /* req */
7417 0, /* root_dir_fid */
7418 smb_fname, /* fname */
7419 access_mask, /* access_mask */
7420 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7421 FILE_SHARE_DELETE),
7422 create_disp, /* create_disposition*/
7423 create_options, /* create_options */
7424 mod_unixmode, /* file_attributes */
7425 oplock_request, /* oplock_request */
7426 0, /* allocation_size */
7427 0, /* private_flags */
7428 NULL, /* sd */
7429 NULL, /* ea_list */
7430 &fsp, /* result */
7431 &info); /* pinfo */
7433 if (!NT_STATUS_IS_OK(status)) {
7434 return status;
7437 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7438 extended_oplock_granted = True;
7441 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7442 extended_oplock_granted = True;
7445 info_level_return = SVAL(pdata,16);
7447 /* Allocate the correct return size. */
7449 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7450 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7451 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7452 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7453 } else {
7454 *pdata_return_size = 12;
7457 /* Realloc the data size */
7458 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7459 if (*ppdata == NULL) {
7460 close_file(req, fsp, ERROR_CLOSE);
7461 *pdata_return_size = 0;
7462 return NT_STATUS_NO_MEMORY;
7464 pdata = *ppdata;
7466 if (extended_oplock_granted) {
7467 if (flags & REQUEST_BATCH_OPLOCK) {
7468 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7469 } else {
7470 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7472 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7473 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7474 } else {
7475 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7478 SSVAL(pdata,2,fsp->fnum);
7479 SIVAL(pdata,4,info); /* Was file created etc. */
7481 switch (info_level_return) {
7482 case SMB_QUERY_FILE_UNIX_BASIC:
7483 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7484 SSVAL(pdata,10,0); /* padding. */
7485 store_file_unix_basic(conn, pdata + 12, fsp,
7486 &smb_fname->st);
7487 break;
7488 case SMB_QUERY_FILE_UNIX_INFO2:
7489 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7490 SSVAL(pdata,10,0); /* padding. */
7491 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7492 &smb_fname->st);
7493 break;
7494 default:
7495 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7496 SSVAL(pdata,10,0); /* padding. */
7497 break;
7499 return NT_STATUS_OK;
7502 /****************************************************************************
7503 Delete a file with POSIX semantics.
7504 ****************************************************************************/
7506 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7507 struct smb_request *req,
7508 const char *pdata,
7509 int total_data,
7510 struct smb_filename *smb_fname)
7512 NTSTATUS status = NT_STATUS_OK;
7513 files_struct *fsp = NULL;
7514 uint16 flags = 0;
7515 char del = 1;
7516 int info = 0;
7517 int create_options = 0;
7518 int i;
7519 struct share_mode_lock *lck = NULL;
7521 if (total_data < 2) {
7522 return NT_STATUS_INVALID_PARAMETER;
7525 flags = SVAL(pdata,0);
7527 if (!VALID_STAT(smb_fname->st)) {
7528 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7531 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7532 !VALID_STAT_OF_DIR(smb_fname->st)) {
7533 return NT_STATUS_NOT_A_DIRECTORY;
7536 DEBUG(10,("smb_posix_unlink: %s %s\n",
7537 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7538 smb_fname_str_dbg(smb_fname)));
7540 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7541 create_options |= FILE_DIRECTORY_FILE;
7544 status = SMB_VFS_CREATE_FILE(
7545 conn, /* conn */
7546 req, /* req */
7547 0, /* root_dir_fid */
7548 smb_fname, /* fname */
7549 DELETE_ACCESS, /* access_mask */
7550 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7551 FILE_SHARE_DELETE),
7552 FILE_OPEN, /* create_disposition*/
7553 create_options, /* create_options */
7554 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7555 0, /* oplock_request */
7556 0, /* allocation_size */
7557 0, /* private_flags */
7558 NULL, /* sd */
7559 NULL, /* ea_list */
7560 &fsp, /* result */
7561 &info); /* pinfo */
7563 if (!NT_STATUS_IS_OK(status)) {
7564 return status;
7568 * Don't lie to client. If we can't really delete due to
7569 * non-POSIX opens return SHARING_VIOLATION.
7572 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7573 if (lck == NULL) {
7574 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7575 "lock for file %s\n", fsp_str_dbg(fsp)));
7576 close_file(req, fsp, NORMAL_CLOSE);
7577 return NT_STATUS_INVALID_PARAMETER;
7581 * See if others still have the file open. If this is the case, then
7582 * don't delete. If all opens are POSIX delete we can set the delete
7583 * on close disposition.
7585 for (i=0; i<lck->data->num_share_modes; i++) {
7586 struct share_mode_entry *e = &lck->data->share_modes[i];
7587 if (is_valid_share_mode_entry(e)) {
7588 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7589 continue;
7591 /* Fail with sharing violation. */
7592 close_file(req, fsp, NORMAL_CLOSE);
7593 TALLOC_FREE(lck);
7594 return NT_STATUS_SHARING_VIOLATION;
7599 * Set the delete on close.
7601 status = smb_set_file_disposition_info(conn,
7602 &del,
7604 fsp,
7605 smb_fname);
7607 if (!NT_STATUS_IS_OK(status)) {
7608 close_file(req, fsp, NORMAL_CLOSE);
7609 TALLOC_FREE(lck);
7610 return status;
7612 TALLOC_FREE(lck);
7613 return close_file(req, fsp, NORMAL_CLOSE);
7616 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7617 struct smb_request *req,
7618 TALLOC_CTX *mem_ctx,
7619 uint16_t info_level,
7620 files_struct *fsp,
7621 struct smb_filename *smb_fname,
7622 char **ppdata, int total_data,
7623 int *ret_data_size)
7625 char *pdata = *ppdata;
7626 NTSTATUS status = NT_STATUS_OK;
7627 int data_return_size = 0;
7629 *ret_data_size = 0;
7631 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7632 return NT_STATUS_INVALID_LEVEL;
7635 if (!CAN_WRITE(conn)) {
7636 /* Allow POSIX opens. The open path will deny
7637 * any non-readonly opens. */
7638 if (info_level != SMB_POSIX_PATH_OPEN) {
7639 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7643 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7644 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7645 fsp ? fsp->fnum : -1, info_level, total_data));
7647 switch (info_level) {
7649 case SMB_INFO_STANDARD:
7651 status = smb_set_info_standard(conn,
7652 pdata,
7653 total_data,
7654 fsp,
7655 smb_fname);
7656 break;
7659 case SMB_INFO_SET_EA:
7661 status = smb_info_set_ea(conn,
7662 pdata,
7663 total_data,
7664 fsp,
7665 smb_fname);
7666 break;
7669 case SMB_SET_FILE_BASIC_INFO:
7670 case SMB_FILE_BASIC_INFORMATION:
7672 status = smb_set_file_basic_info(conn,
7673 pdata,
7674 total_data,
7675 fsp,
7676 smb_fname);
7677 break;
7680 case SMB_FILE_ALLOCATION_INFORMATION:
7681 case SMB_SET_FILE_ALLOCATION_INFO:
7683 status = smb_set_file_allocation_info(conn, req,
7684 pdata,
7685 total_data,
7686 fsp,
7687 smb_fname);
7688 break;
7691 case SMB_FILE_END_OF_FILE_INFORMATION:
7692 case SMB_SET_FILE_END_OF_FILE_INFO:
7695 * XP/Win7 both fail after the createfile with
7696 * SMB_SET_FILE_END_OF_FILE_INFO but not
7697 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7698 * The level is known here, so pass it down
7699 * appropriately.
7701 bool should_fail =
7702 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7704 status = smb_set_file_end_of_file_info(conn, req,
7705 pdata,
7706 total_data,
7707 fsp,
7708 smb_fname,
7709 should_fail);
7710 break;
7713 case SMB_FILE_DISPOSITION_INFORMATION:
7714 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7716 #if 0
7717 /* JRA - We used to just ignore this on a path ?
7718 * Shouldn't this be invalid level on a pathname
7719 * based call ?
7721 if (tran_call != TRANSACT2_SETFILEINFO) {
7722 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7724 #endif
7725 status = smb_set_file_disposition_info(conn,
7726 pdata,
7727 total_data,
7728 fsp,
7729 smb_fname);
7730 break;
7733 case SMB_FILE_POSITION_INFORMATION:
7735 status = smb_file_position_information(conn,
7736 pdata,
7737 total_data,
7738 fsp);
7739 break;
7742 case SMB_FILE_FULL_EA_INFORMATION:
7744 status = smb_set_file_full_ea_info(conn,
7745 pdata,
7746 total_data,
7747 fsp);
7748 break;
7751 /* From tridge Samba4 :
7752 * MODE_INFORMATION in setfileinfo (I have no
7753 * idea what "mode information" on a file is - it takes a value of 0,
7754 * 2, 4 or 6. What could it be?).
7757 case SMB_FILE_MODE_INFORMATION:
7759 status = smb_file_mode_information(conn,
7760 pdata,
7761 total_data);
7762 break;
7766 * CIFS UNIX extensions.
7769 case SMB_SET_FILE_UNIX_BASIC:
7771 status = smb_set_file_unix_basic(conn, req,
7772 pdata,
7773 total_data,
7774 fsp,
7775 smb_fname);
7776 break;
7779 case SMB_SET_FILE_UNIX_INFO2:
7781 status = smb_set_file_unix_info2(conn, req,
7782 pdata,
7783 total_data,
7784 fsp,
7785 smb_fname);
7786 break;
7789 case SMB_SET_FILE_UNIX_LINK:
7791 if (fsp) {
7792 /* We must have a pathname for this. */
7793 return NT_STATUS_INVALID_LEVEL;
7795 status = smb_set_file_unix_link(conn, req, pdata,
7796 total_data, smb_fname);
7797 break;
7800 case SMB_SET_FILE_UNIX_HLINK:
7802 if (fsp) {
7803 /* We must have a pathname for this. */
7804 return NT_STATUS_INVALID_LEVEL;
7806 status = smb_set_file_unix_hlink(conn, req,
7807 pdata, total_data,
7808 smb_fname);
7809 break;
7812 case SMB_FILE_RENAME_INFORMATION:
7814 status = smb_file_rename_information(conn, req,
7815 pdata, total_data,
7816 fsp, smb_fname);
7817 break;
7820 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7822 /* SMB2 rename information. */
7823 status = smb2_file_rename_information(conn, req,
7824 pdata, total_data,
7825 fsp, smb_fname);
7826 break;
7829 case SMB_FILE_LINK_INFORMATION:
7831 status = smb_file_link_information(conn, req,
7832 pdata, total_data,
7833 fsp, smb_fname);
7834 break;
7837 #if defined(HAVE_POSIX_ACLS)
7838 case SMB_SET_POSIX_ACL:
7840 status = smb_set_posix_acl(conn,
7841 pdata,
7842 total_data,
7843 fsp,
7844 smb_fname);
7845 break;
7847 #endif
7849 case SMB_SET_POSIX_LOCK:
7851 if (!fsp) {
7852 return NT_STATUS_INVALID_LEVEL;
7854 status = smb_set_posix_lock(conn, req,
7855 pdata, total_data, fsp);
7856 break;
7859 case SMB_POSIX_PATH_OPEN:
7861 if (fsp) {
7862 /* We must have a pathname for this. */
7863 return NT_STATUS_INVALID_LEVEL;
7866 status = smb_posix_open(conn, req,
7867 ppdata,
7868 total_data,
7869 smb_fname,
7870 &data_return_size);
7871 break;
7874 case SMB_POSIX_PATH_UNLINK:
7876 if (fsp) {
7877 /* We must have a pathname for this. */
7878 return NT_STATUS_INVALID_LEVEL;
7881 status = smb_posix_unlink(conn, req,
7882 pdata,
7883 total_data,
7884 smb_fname);
7885 break;
7888 default:
7889 return NT_STATUS_INVALID_LEVEL;
7892 if (!NT_STATUS_IS_OK(status)) {
7893 return status;
7896 *ret_data_size = data_return_size;
7897 return NT_STATUS_OK;
7900 /****************************************************************************
7901 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7902 ****************************************************************************/
7904 static void call_trans2setfilepathinfo(connection_struct *conn,
7905 struct smb_request *req,
7906 unsigned int tran_call,
7907 char **pparams, int total_params,
7908 char **ppdata, int total_data,
7909 unsigned int max_data_bytes)
7911 char *params = *pparams;
7912 char *pdata = *ppdata;
7913 uint16 info_level;
7914 struct smb_filename *smb_fname = NULL;
7915 files_struct *fsp = NULL;
7916 NTSTATUS status = NT_STATUS_OK;
7917 int data_return_size = 0;
7919 if (!params) {
7920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7921 return;
7924 if (tran_call == TRANSACT2_SETFILEINFO) {
7925 if (total_params < 4) {
7926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7927 return;
7930 fsp = file_fsp(req, SVAL(params,0));
7931 /* Basic check for non-null fsp. */
7932 if (!check_fsp_open(conn, req, fsp)) {
7933 return;
7935 info_level = SVAL(params,2);
7937 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7938 &smb_fname);
7939 if (!NT_STATUS_IS_OK(status)) {
7940 reply_nterror(req, status);
7941 return;
7944 if(fsp->fh->fd == -1) {
7946 * This is actually a SETFILEINFO on a directory
7947 * handle (returned from an NT SMB). NT5.0 seems
7948 * to do this call. JRA.
7950 if (INFO_LEVEL_IS_UNIX(info_level)) {
7951 /* Always do lstat for UNIX calls. */
7952 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7953 DEBUG(3,("call_trans2setfilepathinfo: "
7954 "SMB_VFS_LSTAT of %s failed "
7955 "(%s)\n",
7956 smb_fname_str_dbg(smb_fname),
7957 strerror(errno)));
7958 reply_nterror(req, map_nt_error_from_unix(errno));
7959 return;
7961 } else {
7962 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7963 DEBUG(3,("call_trans2setfilepathinfo: "
7964 "fileinfo of %s failed (%s)\n",
7965 smb_fname_str_dbg(smb_fname),
7966 strerror(errno)));
7967 reply_nterror(req, map_nt_error_from_unix(errno));
7968 return;
7971 } else if (fsp->print_file) {
7973 * Doing a DELETE_ON_CLOSE should cancel a print job.
7975 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7976 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7978 DEBUG(3,("call_trans2setfilepathinfo: "
7979 "Cancelling print job (%s)\n",
7980 fsp_str_dbg(fsp)));
7982 SSVAL(params,0,0);
7983 send_trans2_replies(conn, req, params, 2,
7984 *ppdata, 0,
7985 max_data_bytes);
7986 return;
7987 } else {
7988 reply_nterror(req,
7989 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7990 return;
7992 } else {
7994 * Original code - this is an open file.
7996 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7997 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7998 "of fnum %d failed (%s)\n", fsp->fnum,
7999 strerror(errno)));
8000 reply_nterror(req, map_nt_error_from_unix(errno));
8001 return;
8004 } else {
8005 char *fname = NULL;
8006 uint32_t ucf_flags = 0;
8008 /* set path info */
8009 if (total_params < 7) {
8010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8011 return;
8014 info_level = SVAL(params,0);
8015 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8016 total_params - 6, STR_TERMINATE,
8017 &status);
8018 if (!NT_STATUS_IS_OK(status)) {
8019 reply_nterror(req, status);
8020 return;
8023 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8024 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8025 info_level == SMB_FILE_RENAME_INFORMATION ||
8026 info_level == SMB_POSIX_PATH_UNLINK) {
8027 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8030 status = filename_convert(req, conn,
8031 req->flags2 & FLAGS2_DFS_PATHNAMES,
8032 fname,
8033 ucf_flags,
8034 NULL,
8035 &smb_fname);
8036 if (!NT_STATUS_IS_OK(status)) {
8037 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8038 reply_botherror(req,
8039 NT_STATUS_PATH_NOT_COVERED,
8040 ERRSRV, ERRbadpath);
8041 return;
8043 reply_nterror(req, status);
8044 return;
8047 if (INFO_LEVEL_IS_UNIX(info_level)) {
8049 * For CIFS UNIX extensions the target name may not exist.
8052 /* Always do lstat for UNIX calls. */
8053 SMB_VFS_LSTAT(conn, smb_fname);
8055 } else if (!VALID_STAT(smb_fname->st) &&
8056 SMB_VFS_STAT(conn, smb_fname)) {
8057 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8058 "%s failed (%s)\n",
8059 smb_fname_str_dbg(smb_fname),
8060 strerror(errno)));
8061 reply_nterror(req, map_nt_error_from_unix(errno));
8062 return;
8066 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8067 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8068 fsp ? fsp->fnum : -1, info_level,total_data));
8070 /* Realloc the parameter size */
8071 *pparams = (char *)SMB_REALLOC(*pparams,2);
8072 if (*pparams == NULL) {
8073 reply_nterror(req, NT_STATUS_NO_MEMORY);
8074 return;
8076 params = *pparams;
8078 SSVAL(params,0,0);
8080 status = smbd_do_setfilepathinfo(conn, req, req,
8081 info_level,
8082 fsp,
8083 smb_fname,
8084 ppdata, total_data,
8085 &data_return_size);
8086 if (!NT_STATUS_IS_OK(status)) {
8087 if (open_was_deferred(req->sconn, req->mid)) {
8088 /* We have re-scheduled this call. */
8089 return;
8091 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8092 /* We have re-scheduled this call. */
8093 return;
8095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8096 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8097 ERRSRV, ERRbadpath);
8098 return;
8100 if (info_level == SMB_POSIX_PATH_OPEN) {
8101 reply_openerror(req, status);
8102 return;
8105 reply_nterror(req, status);
8106 return;
8109 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8110 max_data_bytes);
8112 return;
8115 /****************************************************************************
8116 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8117 ****************************************************************************/
8119 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8120 char **pparams, int total_params,
8121 char **ppdata, int total_data,
8122 unsigned int max_data_bytes)
8124 struct smb_filename *smb_dname = NULL;
8125 char *params = *pparams;
8126 char *pdata = *ppdata;
8127 char *directory = NULL;
8128 NTSTATUS status = NT_STATUS_OK;
8129 struct ea_list *ea_list = NULL;
8130 TALLOC_CTX *ctx = talloc_tos();
8132 if (!CAN_WRITE(conn)) {
8133 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8134 return;
8137 if (total_params < 5) {
8138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8139 return;
8142 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8143 total_params - 4, STR_TERMINATE,
8144 &status);
8145 if (!NT_STATUS_IS_OK(status)) {
8146 reply_nterror(req, status);
8147 return;
8150 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8152 status = filename_convert(ctx,
8153 conn,
8154 req->flags2 & FLAGS2_DFS_PATHNAMES,
8155 directory,
8157 NULL,
8158 &smb_dname);
8160 if (!NT_STATUS_IS_OK(status)) {
8161 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8162 reply_botherror(req,
8163 NT_STATUS_PATH_NOT_COVERED,
8164 ERRSRV, ERRbadpath);
8165 return;
8167 reply_nterror(req, status);
8168 return;
8172 * OS/2 workplace shell seems to send SET_EA requests of "null"
8173 * length (4 bytes containing IVAL 4).
8174 * They seem to have no effect. Bug #3212. JRA.
8177 if (total_data && (total_data != 4)) {
8178 /* Any data in this call is an EA list. */
8179 if (total_data < 10) {
8180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8181 goto out;
8184 if (IVAL(pdata,0) > total_data) {
8185 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8186 IVAL(pdata,0), (unsigned int)total_data));
8187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8188 goto out;
8191 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8192 total_data - 4);
8193 if (!ea_list) {
8194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 goto out;
8198 if (!lp_ea_support(SNUM(conn))) {
8199 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8200 goto out;
8203 /* If total_data == 4 Windows doesn't care what values
8204 * are placed in that field, it just ignores them.
8205 * The System i QNTC IBM SMB client puts bad values here,
8206 * so ignore them. */
8208 status = create_directory(conn, req, smb_dname);
8210 if (!NT_STATUS_IS_OK(status)) {
8211 reply_nterror(req, status);
8212 goto out;
8215 /* Try and set any given EA. */
8216 if (ea_list) {
8217 status = set_ea(conn, NULL, smb_dname, ea_list);
8218 if (!NT_STATUS_IS_OK(status)) {
8219 reply_nterror(req, status);
8220 goto out;
8224 /* Realloc the parameter and data sizes */
8225 *pparams = (char *)SMB_REALLOC(*pparams,2);
8226 if(*pparams == NULL) {
8227 reply_nterror(req, NT_STATUS_NO_MEMORY);
8228 goto out;
8230 params = *pparams;
8232 SSVAL(params,0,0);
8234 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8236 out:
8237 TALLOC_FREE(smb_dname);
8238 return;
8241 /****************************************************************************
8242 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8243 We don't actually do this - we just send a null response.
8244 ****************************************************************************/
8246 static void call_trans2findnotifyfirst(connection_struct *conn,
8247 struct smb_request *req,
8248 char **pparams, int total_params,
8249 char **ppdata, int total_data,
8250 unsigned int max_data_bytes)
8252 char *params = *pparams;
8253 uint16 info_level;
8255 if (total_params < 6) {
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 return;
8260 info_level = SVAL(params,4);
8261 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8263 switch (info_level) {
8264 case 1:
8265 case 2:
8266 break;
8267 default:
8268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8269 return;
8272 /* Realloc the parameter and data sizes */
8273 *pparams = (char *)SMB_REALLOC(*pparams,6);
8274 if (*pparams == NULL) {
8275 reply_nterror(req, NT_STATUS_NO_MEMORY);
8276 return;
8278 params = *pparams;
8280 SSVAL(params,0,fnf_handle);
8281 SSVAL(params,2,0); /* No changes */
8282 SSVAL(params,4,0); /* No EA errors */
8284 fnf_handle++;
8286 if(fnf_handle == 0)
8287 fnf_handle = 257;
8289 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8291 return;
8294 /****************************************************************************
8295 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8296 changes). Currently this does nothing.
8297 ****************************************************************************/
8299 static void call_trans2findnotifynext(connection_struct *conn,
8300 struct smb_request *req,
8301 char **pparams, int total_params,
8302 char **ppdata, int total_data,
8303 unsigned int max_data_bytes)
8305 char *params = *pparams;
8307 DEBUG(3,("call_trans2findnotifynext\n"));
8309 /* Realloc the parameter and data sizes */
8310 *pparams = (char *)SMB_REALLOC(*pparams,4);
8311 if (*pparams == NULL) {
8312 reply_nterror(req, NT_STATUS_NO_MEMORY);
8313 return;
8315 params = *pparams;
8317 SSVAL(params,0,0); /* No changes */
8318 SSVAL(params,2,0); /* No EA errors */
8320 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8322 return;
8325 /****************************************************************************
8326 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8327 ****************************************************************************/
8329 static void call_trans2getdfsreferral(connection_struct *conn,
8330 struct smb_request *req,
8331 char **pparams, int total_params,
8332 char **ppdata, int total_data,
8333 unsigned int max_data_bytes)
8335 char *params = *pparams;
8336 char *pathname = NULL;
8337 int reply_size = 0;
8338 int max_referral_level;
8339 NTSTATUS status = NT_STATUS_OK;
8340 TALLOC_CTX *ctx = talloc_tos();
8342 DEBUG(10,("call_trans2getdfsreferral\n"));
8344 if (total_params < 3) {
8345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8346 return;
8349 max_referral_level = SVAL(params,0);
8351 if(!lp_host_msdfs()) {
8352 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8353 return;
8356 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8357 total_params - 2, STR_TERMINATE);
8358 if (!pathname) {
8359 reply_nterror(req, NT_STATUS_NOT_FOUND);
8360 return;
8362 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8363 ppdata,&status)) < 0) {
8364 reply_nterror(req, status);
8365 return;
8368 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8369 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8370 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8372 return;
8375 #define LMCAT_SPL 0x53
8376 #define LMFUNC_GETJOBID 0x60
8378 /****************************************************************************
8379 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8380 ****************************************************************************/
8382 static void call_trans2ioctl(connection_struct *conn,
8383 struct smb_request *req,
8384 char **pparams, int total_params,
8385 char **ppdata, int total_data,
8386 unsigned int max_data_bytes)
8388 char *pdata = *ppdata;
8389 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8391 /* check for an invalid fid before proceeding */
8393 if (!fsp) {
8394 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8395 return;
8398 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8399 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8400 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8401 if (*ppdata == NULL) {
8402 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403 return;
8405 pdata = *ppdata;
8407 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8408 CAN ACCEPT THIS IN UNICODE. JRA. */
8410 /* Job number */
8411 if (fsp->print_file) {
8412 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8413 } else {
8414 SSVAL(pdata, 0, 0);
8416 srvstr_push(pdata, req->flags2, pdata + 2,
8417 lp_netbios_name(), 15,
8418 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8419 srvstr_push(pdata, req->flags2, pdata+18,
8420 lp_servicename(SNUM(conn)), 13,
8421 STR_ASCII|STR_TERMINATE); /* Service name */
8422 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8423 max_data_bytes);
8424 return;
8427 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8428 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8431 /****************************************************************************
8432 Reply to a SMBfindclose (stop trans2 directory search).
8433 ****************************************************************************/
8435 void reply_findclose(struct smb_request *req)
8437 int dptr_num;
8438 struct smbd_server_connection *sconn = req->sconn;
8440 START_PROFILE(SMBfindclose);
8442 if (req->wct < 1) {
8443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8444 END_PROFILE(SMBfindclose);
8445 return;
8448 dptr_num = SVALS(req->vwv+0, 0);
8450 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8452 dptr_close(sconn, &dptr_num);
8454 reply_outbuf(req, 0, 0);
8456 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8458 END_PROFILE(SMBfindclose);
8459 return;
8462 /****************************************************************************
8463 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8464 ****************************************************************************/
8466 void reply_findnclose(struct smb_request *req)
8468 int dptr_num;
8470 START_PROFILE(SMBfindnclose);
8472 if (req->wct < 1) {
8473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8474 END_PROFILE(SMBfindnclose);
8475 return;
8478 dptr_num = SVAL(req->vwv+0, 0);
8480 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8482 /* We never give out valid handles for a
8483 findnotifyfirst - so any dptr_num is ok here.
8484 Just ignore it. */
8486 reply_outbuf(req, 0, 0);
8488 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8490 END_PROFILE(SMBfindnclose);
8491 return;
8494 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8495 struct trans_state *state)
8497 if (get_Protocol() >= PROTOCOL_NT1) {
8498 req->flags2 |= 0x40; /* IS_LONG_NAME */
8499 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8502 if (conn->encrypt_level == Required && !req->encrypted) {
8503 if (state->call != TRANSACT2_QFSINFO &&
8504 state->call != TRANSACT2_SETFSINFO) {
8505 DEBUG(0,("handle_trans2: encryption required "
8506 "with call 0x%x\n",
8507 (unsigned int)state->call));
8508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8509 return;
8513 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8515 /* Now we must call the relevant TRANS2 function */
8516 switch(state->call) {
8517 case TRANSACT2_OPEN:
8519 START_PROFILE(Trans2_open);
8520 call_trans2open(conn, req,
8521 &state->param, state->total_param,
8522 &state->data, state->total_data,
8523 state->max_data_return);
8524 END_PROFILE(Trans2_open);
8525 break;
8528 case TRANSACT2_FINDFIRST:
8530 START_PROFILE(Trans2_findfirst);
8531 call_trans2findfirst(conn, req,
8532 &state->param, state->total_param,
8533 &state->data, state->total_data,
8534 state->max_data_return);
8535 END_PROFILE(Trans2_findfirst);
8536 break;
8539 case TRANSACT2_FINDNEXT:
8541 START_PROFILE(Trans2_findnext);
8542 call_trans2findnext(conn, req,
8543 &state->param, state->total_param,
8544 &state->data, state->total_data,
8545 state->max_data_return);
8546 END_PROFILE(Trans2_findnext);
8547 break;
8550 case TRANSACT2_QFSINFO:
8552 START_PROFILE(Trans2_qfsinfo);
8553 call_trans2qfsinfo(conn, req,
8554 &state->param, state->total_param,
8555 &state->data, state->total_data,
8556 state->max_data_return);
8557 END_PROFILE(Trans2_qfsinfo);
8558 break;
8561 case TRANSACT2_SETFSINFO:
8563 START_PROFILE(Trans2_setfsinfo);
8564 call_trans2setfsinfo(conn, req,
8565 &state->param, state->total_param,
8566 &state->data, state->total_data,
8567 state->max_data_return);
8568 END_PROFILE(Trans2_setfsinfo);
8569 break;
8572 case TRANSACT2_QPATHINFO:
8573 case TRANSACT2_QFILEINFO:
8575 START_PROFILE(Trans2_qpathinfo);
8576 call_trans2qfilepathinfo(conn, req, state->call,
8577 &state->param, state->total_param,
8578 &state->data, state->total_data,
8579 state->max_data_return);
8580 END_PROFILE(Trans2_qpathinfo);
8581 break;
8584 case TRANSACT2_SETPATHINFO:
8585 case TRANSACT2_SETFILEINFO:
8587 START_PROFILE(Trans2_setpathinfo);
8588 call_trans2setfilepathinfo(conn, req, state->call,
8589 &state->param, state->total_param,
8590 &state->data, state->total_data,
8591 state->max_data_return);
8592 END_PROFILE(Trans2_setpathinfo);
8593 break;
8596 case TRANSACT2_FINDNOTIFYFIRST:
8598 START_PROFILE(Trans2_findnotifyfirst);
8599 call_trans2findnotifyfirst(conn, req,
8600 &state->param, state->total_param,
8601 &state->data, state->total_data,
8602 state->max_data_return);
8603 END_PROFILE(Trans2_findnotifyfirst);
8604 break;
8607 case TRANSACT2_FINDNOTIFYNEXT:
8609 START_PROFILE(Trans2_findnotifynext);
8610 call_trans2findnotifynext(conn, req,
8611 &state->param, state->total_param,
8612 &state->data, state->total_data,
8613 state->max_data_return);
8614 END_PROFILE(Trans2_findnotifynext);
8615 break;
8618 case TRANSACT2_MKDIR:
8620 START_PROFILE(Trans2_mkdir);
8621 call_trans2mkdir(conn, req,
8622 &state->param, state->total_param,
8623 &state->data, state->total_data,
8624 state->max_data_return);
8625 END_PROFILE(Trans2_mkdir);
8626 break;
8629 case TRANSACT2_GET_DFS_REFERRAL:
8631 START_PROFILE(Trans2_get_dfs_referral);
8632 call_trans2getdfsreferral(conn, req,
8633 &state->param, state->total_param,
8634 &state->data, state->total_data,
8635 state->max_data_return);
8636 END_PROFILE(Trans2_get_dfs_referral);
8637 break;
8640 case TRANSACT2_IOCTL:
8642 START_PROFILE(Trans2_ioctl);
8643 call_trans2ioctl(conn, req,
8644 &state->param, state->total_param,
8645 &state->data, state->total_data,
8646 state->max_data_return);
8647 END_PROFILE(Trans2_ioctl);
8648 break;
8651 default:
8652 /* Error in request */
8653 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8654 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8658 /****************************************************************************
8659 Reply to a SMBtrans2.
8660 ****************************************************************************/
8662 void reply_trans2(struct smb_request *req)
8664 connection_struct *conn = req->conn;
8665 unsigned int dsoff;
8666 unsigned int dscnt;
8667 unsigned int psoff;
8668 unsigned int pscnt;
8669 unsigned int tran_call;
8670 struct trans_state *state;
8671 NTSTATUS result;
8673 START_PROFILE(SMBtrans2);
8675 if (req->wct < 14) {
8676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8677 END_PROFILE(SMBtrans2);
8678 return;
8681 dsoff = SVAL(req->vwv+12, 0);
8682 dscnt = SVAL(req->vwv+11, 0);
8683 psoff = SVAL(req->vwv+10, 0);
8684 pscnt = SVAL(req->vwv+9, 0);
8685 tran_call = SVAL(req->vwv+14, 0);
8687 result = allow_new_trans(conn->pending_trans, req->mid);
8688 if (!NT_STATUS_IS_OK(result)) {
8689 DEBUG(2, ("Got invalid trans2 request: %s\n",
8690 nt_errstr(result)));
8691 reply_nterror(req, result);
8692 END_PROFILE(SMBtrans2);
8693 return;
8696 if (IS_IPC(conn)) {
8697 switch (tran_call) {
8698 /* List the allowed trans2 calls on IPC$ */
8699 case TRANSACT2_OPEN:
8700 case TRANSACT2_GET_DFS_REFERRAL:
8701 case TRANSACT2_QFILEINFO:
8702 case TRANSACT2_QFSINFO:
8703 case TRANSACT2_SETFSINFO:
8704 break;
8705 default:
8706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8707 END_PROFILE(SMBtrans2);
8708 return;
8712 if ((state = talloc(conn, struct trans_state)) == NULL) {
8713 DEBUG(0, ("talloc failed\n"));
8714 reply_nterror(req, NT_STATUS_NO_MEMORY);
8715 END_PROFILE(SMBtrans2);
8716 return;
8719 state->cmd = SMBtrans2;
8721 state->mid = req->mid;
8722 state->vuid = req->vuid;
8723 state->setup_count = SVAL(req->vwv+13, 0);
8724 state->setup = NULL;
8725 state->total_param = SVAL(req->vwv+0, 0);
8726 state->param = NULL;
8727 state->total_data = SVAL(req->vwv+1, 0);
8728 state->data = NULL;
8729 state->max_param_return = SVAL(req->vwv+2, 0);
8730 state->max_data_return = SVAL(req->vwv+3, 0);
8731 state->max_setup_return = SVAL(req->vwv+4, 0);
8732 state->close_on_completion = BITSETW(req->vwv+5, 0);
8733 state->one_way = BITSETW(req->vwv+5, 1);
8735 state->call = tran_call;
8737 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8738 is so as a sanity check */
8739 if (state->setup_count != 1) {
8741 * Need to have rc=0 for ioctl to get job id for OS/2.
8742 * Network printing will fail if function is not successful.
8743 * Similar function in reply.c will be used if protocol
8744 * is LANMAN1.0 instead of LM1.2X002.
8745 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8746 * outbuf doesn't have to be set(only job id is used).
8748 if ( (state->setup_count == 4)
8749 && (tran_call == TRANSACT2_IOCTL)
8750 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8751 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8752 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8753 } else {
8754 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8755 DEBUG(2,("Transaction is %d\n",tran_call));
8756 TALLOC_FREE(state);
8757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8758 END_PROFILE(SMBtrans2);
8759 return;
8763 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8764 goto bad_param;
8766 if (state->total_data) {
8768 if (trans_oob(state->total_data, 0, dscnt)
8769 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8770 goto bad_param;
8773 /* Can't use talloc here, the core routines do realloc on the
8774 * params and data. */
8775 state->data = (char *)SMB_MALLOC(state->total_data);
8776 if (state->data == NULL) {
8777 DEBUG(0,("reply_trans2: data malloc fail for %u "
8778 "bytes !\n", (unsigned int)state->total_data));
8779 TALLOC_FREE(state);
8780 reply_nterror(req, NT_STATUS_NO_MEMORY);
8781 END_PROFILE(SMBtrans2);
8782 return;
8785 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8788 if (state->total_param) {
8790 if (trans_oob(state->total_param, 0, pscnt)
8791 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8792 goto bad_param;
8795 /* Can't use talloc here, the core routines do realloc on the
8796 * params and data. */
8797 state->param = (char *)SMB_MALLOC(state->total_param);
8798 if (state->param == NULL) {
8799 DEBUG(0,("reply_trans: param malloc fail for %u "
8800 "bytes !\n", (unsigned int)state->total_param));
8801 SAFE_FREE(state->data);
8802 TALLOC_FREE(state);
8803 reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 END_PROFILE(SMBtrans2);
8805 return;
8808 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8811 state->received_data = dscnt;
8812 state->received_param = pscnt;
8814 if ((state->received_param == state->total_param) &&
8815 (state->received_data == state->total_data)) {
8817 handle_trans2(conn, req, state);
8819 SAFE_FREE(state->data);
8820 SAFE_FREE(state->param);
8821 TALLOC_FREE(state);
8822 END_PROFILE(SMBtrans2);
8823 return;
8826 DLIST_ADD(conn->pending_trans, state);
8828 /* We need to send an interim response then receive the rest
8829 of the parameter/data bytes */
8830 reply_outbuf(req, 0, 0);
8831 show_msg((char *)req->outbuf);
8832 END_PROFILE(SMBtrans2);
8833 return;
8835 bad_param:
8837 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8838 SAFE_FREE(state->data);
8839 SAFE_FREE(state->param);
8840 TALLOC_FREE(state);
8841 END_PROFILE(SMBtrans2);
8842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8846 /****************************************************************************
8847 Reply to a SMBtranss2
8848 ****************************************************************************/
8850 void reply_transs2(struct smb_request *req)
8852 connection_struct *conn = req->conn;
8853 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8854 struct trans_state *state;
8856 START_PROFILE(SMBtranss2);
8858 show_msg((const char *)req->inbuf);
8860 if (req->wct < 8) {
8861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8862 END_PROFILE(SMBtranss2);
8863 return;
8866 for (state = conn->pending_trans; state != NULL;
8867 state = state->next) {
8868 if (state->mid == req->mid) {
8869 break;
8873 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8875 END_PROFILE(SMBtranss2);
8876 return;
8879 /* Revise state->total_param and state->total_data in case they have
8880 changed downwards */
8882 if (SVAL(req->vwv+0, 0) < state->total_param)
8883 state->total_param = SVAL(req->vwv+0, 0);
8884 if (SVAL(req->vwv+1, 0) < state->total_data)
8885 state->total_data = SVAL(req->vwv+1, 0);
8887 pcnt = SVAL(req->vwv+2, 0);
8888 poff = SVAL(req->vwv+3, 0);
8889 pdisp = SVAL(req->vwv+4, 0);
8891 dcnt = SVAL(req->vwv+5, 0);
8892 doff = SVAL(req->vwv+6, 0);
8893 ddisp = SVAL(req->vwv+7, 0);
8895 state->received_param += pcnt;
8896 state->received_data += dcnt;
8898 if ((state->received_data > state->total_data) ||
8899 (state->received_param > state->total_param))
8900 goto bad_param;
8902 if (pcnt) {
8903 if (trans_oob(state->total_param, pdisp, pcnt)
8904 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8905 goto bad_param;
8907 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8910 if (dcnt) {
8911 if (trans_oob(state->total_data, ddisp, dcnt)
8912 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8913 goto bad_param;
8915 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8918 if ((state->received_param < state->total_param) ||
8919 (state->received_data < state->total_data)) {
8920 END_PROFILE(SMBtranss2);
8921 return;
8924 handle_trans2(conn, req, state);
8926 DLIST_REMOVE(conn->pending_trans, state);
8927 SAFE_FREE(state->data);
8928 SAFE_FREE(state->param);
8929 TALLOC_FREE(state);
8931 END_PROFILE(SMBtranss2);
8932 return;
8934 bad_param:
8936 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8937 DLIST_REMOVE(conn->pending_trans, state);
8938 SAFE_FREE(state->data);
8939 SAFE_FREE(state->param);
8940 TALLOC_FREE(state);
8941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8942 END_PROFILE(SMBtranss2);
8943 return;