Remove the check for FILE_WRITE_ATTRIBUTES from smb_set_file_time(). It
[Samba/id10ts.git] / source3 / smbd / trans2.c
blob0e831ecff9cabee2e649897b3034f934b891c964
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 "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
43 char *pdata,
44 files_struct *fsp,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 Roundup a value to the nearest allocation roundup size boundary.
54 Only do this for Windows clients.
55 ********************************************************************/
57 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
59 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
61 /* Only roundup for Windows clients. */
62 enum remote_arch_types ra_type = get_remote_arch();
63 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
64 val = SMB_ROUNDUP(val,rval);
66 return val;
69 /********************************************************************
70 Create a 64 bit FileIndex. If the file is on the same device as
71 the root of the share, just return the 64-bit inode. If it isn't,
72 mangle as we used to do.
73 ********************************************************************/
75 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
77 uint64_t file_index;
78 if (conn->base_share_dev == psbuf->st_ex_dev) {
79 return (uint64_t)psbuf->st_ex_ino;
81 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
82 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
83 return file_index;
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
99 SAMBA_XATTR_MARKER,
100 XATTR_NTACL_NAME,
101 NULL
104 int i;
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 return true;
110 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
112 return true;
114 return false;
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
127 char *val = NULL;
128 ssize_t sizeret;
130 again:
132 val = talloc_realloc(mem_ctx, val, char, attr_size);
133 if (!val) {
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 } else {
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
144 attr_size = 65536;
145 goto again;
148 if (sizeret == -1) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
155 pea->flags = 0;
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 } else {
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
162 TALLOC_FREE(val);
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
167 return NT_STATUS_OK;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
178 char *p;
179 char **names, **tmp;
180 size_t num_names;
181 ssize_t sizeret = -1;
183 if (!lp_ea_support(SNUM(conn))) {
184 if (pnames) {
185 *pnames = NULL;
187 *pnum_names = 0;
188 return NT_STATUS_OK;
192 * TALLOC the result early to get the talloc hierarchy right.
195 names = talloc_array(mem_ctx, char *, 1);
196 if (names == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 return NT_STATUS_NO_MEMORY;
201 while (ea_namelist_size <= 65536) {
203 ea_namelist = talloc_realloc(
204 names, ea_namelist, char, ea_namelist_size);
205 if (ea_namelist == NULL) {
206 DEBUG(0, ("talloc failed\n"));
207 TALLOC_FREE(names);
208 return NT_STATUS_NO_MEMORY;
211 if (fsp && fsp->fh->fd != -1) {
212 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 ea_namelist_size);
214 } else {
215 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
216 ea_namelist_size);
219 if ((sizeret == -1) && (errno == ERANGE)) {
220 ea_namelist_size *= 2;
222 else {
223 break;
227 if (sizeret == -1) {
228 TALLOC_FREE(names);
229 return map_nt_error_from_unix(errno);
232 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
233 (unsigned int)sizeret));
235 if (sizeret == 0) {
236 TALLOC_FREE(names);
237 if (pnames) {
238 *pnames = NULL;
240 *pnum_names = 0;
241 return NT_STATUS_OK;
245 * Ensure the result is 0-terminated
248 if (ea_namelist[sizeret-1] != '\0') {
249 TALLOC_FREE(names);
250 return NT_STATUS_INTERNAL_ERROR;
254 * count the names
256 num_names = 0;
258 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
259 num_names += 1;
262 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
263 if (tmp == NULL) {
264 DEBUG(0, ("talloc failed\n"));
265 TALLOC_FREE(names);
266 return NT_STATUS_NO_MEMORY;
269 names = tmp;
270 num_names = 0;
272 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
273 names[num_names++] = p;
276 if (pnames) {
277 *pnames = names;
278 } else {
279 TALLOC_FREE(names);
281 *pnum_names = num_names;
282 return NT_STATUS_OK;
285 /****************************************************************************
286 Return a linked list of the total EA's. Plus the total size
287 ****************************************************************************/
289 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
290 const char *fname, size_t *pea_total_len)
292 /* Get a list of all xattrs. Max namesize is 64k. */
293 size_t i, num_names;
294 char **names;
295 struct ea_list *ea_list_head = NULL;
296 NTSTATUS status;
298 *pea_total_len = 0;
300 if (!lp_ea_support(SNUM(conn))) {
301 return NULL;
304 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
305 &names, &num_names);
307 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
308 return NULL;
311 for (i=0; i<num_names; i++) {
312 struct ea_list *listp;
313 fstring dos_ea_name;
315 if (strnequal(names[i], "system.", 7)
316 || samba_private_attr_name(names[i]))
317 continue;
319 listp = talloc(mem_ctx, struct ea_list);
320 if (listp == NULL) {
321 return NULL;
324 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
325 fname, names[i],
326 &listp->ea))) {
327 return NULL;
330 push_ascii_fstring(dos_ea_name, listp->ea.name);
332 *pea_total_len +=
333 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
335 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
336 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
337 (unsigned int)listp->ea.value.length));
339 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
343 /* Add on 4 for total length. */
344 if (*pea_total_len) {
345 *pea_total_len += 4;
348 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
349 (unsigned int)*pea_total_len));
351 return ea_list_head;
354 /****************************************************************************
355 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
356 that was filled.
357 ****************************************************************************/
359 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
360 connection_struct *conn, struct ea_list *ea_list)
362 unsigned int ret_data_size = 4;
363 char *p = pdata;
365 SMB_ASSERT(total_data_size >= 4);
367 if (!lp_ea_support(SNUM(conn))) {
368 SIVAL(pdata,4,0);
369 return 4;
372 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
373 size_t dos_namelen;
374 fstring dos_ea_name;
375 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
376 dos_namelen = strlen(dos_ea_name);
377 if (dos_namelen > 255 || dos_namelen == 0) {
378 break;
380 if (ea_list->ea.value.length > 65535) {
381 break;
383 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
384 break;
387 /* We know we have room. */
388 SCVAL(p,0,ea_list->ea.flags);
389 SCVAL(p,1,dos_namelen);
390 SSVAL(p,2,ea_list->ea.value.length);
391 strlcpy(p+4, dos_ea_name, dos_namelen+1);
392 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
394 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
398 ret_data_size = PTR_DIFF(p, pdata);
399 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
400 SIVAL(pdata,0,ret_data_size);
401 return ret_data_size;
404 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
405 char *pdata,
406 unsigned int total_data_size,
407 unsigned int *ret_data_size,
408 connection_struct *conn,
409 struct ea_list *ea_list)
411 uint8_t *p = (uint8_t *)pdata;
412 uint8_t *last_start = NULL;
414 *ret_data_size = 0;
416 if (!lp_ea_support(SNUM(conn))) {
417 return NT_STATUS_NO_EAS_ON_FILE;
420 for (; ea_list; ea_list = ea_list->next) {
421 size_t dos_namelen;
422 fstring dos_ea_name;
423 size_t this_size;
425 if (last_start) {
426 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
428 last_start = p;
430 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
431 dos_namelen = strlen(dos_ea_name);
432 if (dos_namelen > 255 || dos_namelen == 0) {
433 return NT_STATUS_INTERNAL_ERROR;
435 if (ea_list->ea.value.length > 65535) {
436 return NT_STATUS_INTERNAL_ERROR;
439 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
441 if (ea_list->next) {
442 size_t pad = 4 - (this_size % 4);
443 this_size += pad;
446 if (this_size > total_data_size) {
447 return NT_STATUS_INFO_LENGTH_MISMATCH;
450 /* We know we have room. */
451 SIVAL(p, 0x00, 0); /* next offset */
452 SCVAL(p, 0x04, ea_list->ea.flags);
453 SCVAL(p, 0x05, dos_namelen);
454 SSVAL(p, 0x06, ea_list->ea.value.length);
455 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
456 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
458 total_data_size -= this_size;
459 p += this_size;
462 *ret_data_size = PTR_DIFF(p, pdata);
463 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
464 return NT_STATUS_OK;
467 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
469 size_t total_ea_len = 0;
470 TALLOC_CTX *mem_ctx = NULL;
472 if (!lp_ea_support(SNUM(conn))) {
473 return 0;
475 mem_ctx = talloc_tos();
476 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
477 return total_ea_len;
480 /****************************************************************************
481 Ensure the EA name is case insensitive by matching any existing EA name.
482 ****************************************************************************/
484 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
486 size_t total_ea_len;
487 TALLOC_CTX *mem_ctx = talloc_tos();
488 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
490 for (; ea_list; ea_list = ea_list->next) {
491 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
492 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
493 &unix_ea_name[5], ea_list->ea.name));
494 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
495 break;
500 /****************************************************************************
501 Set or delete an extended attribute.
502 ****************************************************************************/
504 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, struct ea_list *ea_list)
507 char *fname = NULL;
509 if (!lp_ea_support(SNUM(conn))) {
510 return NT_STATUS_EAS_NOT_SUPPORTED;
513 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
514 return NT_STATUS_ACCESS_DENIED;
517 /* For now setting EAs on streams isn't supported. */
518 fname = smb_fname->base_name;
520 for (;ea_list; ea_list = ea_list->next) {
521 int ret;
522 fstring unix_ea_name;
524 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
525 fstrcat(unix_ea_name, ea_list->ea.name);
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
543 } else {
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
548 #ifdef ENOATTR
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
552 unix_ea_name));
553 ret = 0;
555 #endif
556 } else {
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
563 } else {
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
571 if (ret == -1) {
572 #ifdef ENOTSUP
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
576 #endif
577 return map_nt_error_from_unix(errno);
581 return NT_STATUS_OK;
583 /****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585 ****************************************************************************/
587 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
596 offset++; /* Go past the namelen byte. */
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
602 break;
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
606 return NULL;
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
609 &converted_size)) {
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
613 if (!eal->ea.name) {
614 return NULL;
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
622 return ea_list_head;
625 /****************************************************************************
626 Read one EA list entry from the buffer.
627 ****************************************************************************/
629 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
631 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
632 uint16 val_len;
633 unsigned int namelen;
634 size_t converted_size;
636 if (!eal) {
637 return NULL;
640 if (data_size < 6) {
641 return NULL;
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
648 if (4 + namelen + 1 + val_len > data_size) {
649 return NULL;
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
654 return NULL;
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
658 strerror(errno)));
660 if (!eal->ea.name) {
661 return NULL;
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
666 return NULL;
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
676 if (pbytes_used) {
677 *pbytes_used = 4 + namelen + 1 + val_len;
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
683 return eal;
686 /****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688 ****************************************************************************/
690 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
692 struct ea_list *ea_list_head = NULL;
693 size_t offset = 0;
694 size_t bytes_used = 0;
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
699 if (!eal) {
700 return NULL;
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
707 return ea_list_head;
710 /****************************************************************************
711 Count the total EA size needed.
712 ****************************************************************************/
714 static size_t ea_list_size(struct ea_list *ealist)
716 fstring dos_ea_name;
717 struct ea_list *listp;
718 size_t ret = 0;
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
724 /* Add on 4 for total length. */
725 if (ret) {
726 ret += 4;
729 return ret;
732 /****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736 ****************************************************************************/
738 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
740 struct ea_list *nlistp, *flistp;
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
745 break;
749 if (flistp) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
753 } else {
754 /* Null entry. */
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
760 *total_ea_len = ea_list_size(name_list);
761 return name_list;
764 /****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769 ****************************************************************************/
771 void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
773 const char *params,
774 int paramsize,
775 const char *pdata,
776 int datasize,
777 int max_data_bytes)
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
787 int useable_space;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = req->sconn;
795 int max_send = sconn->smb1.sessions.max_send;
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
800 for OS/2. */
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
806 overflow = True;
809 /* If there genuinely are no parameters or data to send just send the empty packet */
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(sconn,
815 (char *)req->outbuf,
816 true, req->seqnum+1,
817 IS_CONN_ENCRYPTED(conn),
818 &req->pcd)) {
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
821 TALLOC_FREE(req->outbuf);
822 return;
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
836 useable_space = max_send - (smb_size
837 + 2 * 10 /* wct */
838 + alignment_offset
839 + data_alignment_offset);
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
850 total_sent_thistime = params_to_send + data_to_send;
852 /* We can never send more than useable_space */
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
866 * We might have SMBtrans2s in req which was transferred to
867 * the outbuf, fix that.
869 SCVAL(req->outbuf, smb_com, SMBtrans2);
871 /* Set total params and data to be sent */
872 SSVAL(req->outbuf,smb_tprcnt,paramsize);
873 SSVAL(req->outbuf,smb_tdrcnt,datasize);
875 /* Calculate how many parameters and data we can fit into
876 * this packet. Parameters get precedence
879 params_sent_thistime = MIN(params_to_send,useable_space);
880 data_sent_thistime = useable_space - params_sent_thistime;
881 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
883 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
885 /* smb_proff is the offset from the start of the SMB header to the
886 parameter bytes, however the first 4 bytes of outbuf are
887 the Netbios over TCP header. Thus use smb_base() to subtract
888 them from the calculation */
890 SSVAL(req->outbuf,smb_proff,
891 ((smb_buf(req->outbuf)+alignment_offset)
892 - smb_base(req->outbuf)));
894 if(params_sent_thistime == 0)
895 SSVAL(req->outbuf,smb_prdisp,0);
896 else
897 /* Absolute displacement of param bytes sent in this packet */
898 SSVAL(req->outbuf,smb_prdisp,pp - params);
900 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
901 if(data_sent_thistime == 0) {
902 SSVAL(req->outbuf,smb_droff,0);
903 SSVAL(req->outbuf,smb_drdisp, 0);
904 } else {
905 /* The offset of the data bytes is the offset of the
906 parameter bytes plus the number of parameters being sent this time */
907 SSVAL(req->outbuf, smb_droff,
908 ((smb_buf(req->outbuf)+alignment_offset)
909 - smb_base(req->outbuf))
910 + params_sent_thistime + data_alignment_offset);
911 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
914 /* Initialize the padding for alignment */
916 if (alignment_offset != 0) {
917 memset(smb_buf(req->outbuf), 0, alignment_offset);
920 /* Copy the param bytes into the packet */
922 if(params_sent_thistime) {
923 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
924 params_sent_thistime);
927 /* Copy in the data bytes */
928 if(data_sent_thistime) {
929 if (data_alignment_offset != 0) {
930 memset((smb_buf(req->outbuf)+alignment_offset+
931 params_sent_thistime), 0,
932 data_alignment_offset);
934 memcpy(smb_buf(req->outbuf)+alignment_offset
935 +params_sent_thistime+data_alignment_offset,
936 pd,data_sent_thistime);
939 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
940 params_sent_thistime, data_sent_thistime, useable_space));
941 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
942 params_to_send, data_to_send, paramsize, datasize));
944 if (overflow) {
945 error_packet_set((char *)req->outbuf,
946 ERRDOS,ERRbufferoverflow,
947 STATUS_BUFFER_OVERFLOW,
948 __LINE__,__FILE__);
951 /* Send the packet */
952 show_msg((char *)req->outbuf);
953 if (!srv_send_smb(sconn,
954 (char *)req->outbuf,
955 true, req->seqnum+1,
956 IS_CONN_ENCRYPTED(conn),
957 &req->pcd))
958 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
960 TALLOC_FREE(req->outbuf);
962 pp += params_sent_thistime;
963 pd += data_sent_thistime;
965 params_to_send -= params_sent_thistime;
966 data_to_send -= data_sent_thistime;
968 /* Sanity check */
969 if(params_to_send < 0 || data_to_send < 0) {
970 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
971 params_to_send, data_to_send));
972 return;
976 return;
979 /****************************************************************************
980 Reply to a TRANSACT2_OPEN.
981 ****************************************************************************/
983 static void call_trans2open(connection_struct *conn,
984 struct smb_request *req,
985 char **pparams, int total_params,
986 char **ppdata, int total_data,
987 unsigned int max_data_bytes)
989 struct smb_filename *smb_fname = NULL;
990 char *params = *pparams;
991 char *pdata = *ppdata;
992 int deny_mode;
993 int32 open_attr;
994 bool oplock_request;
995 #if 0
996 bool return_additional_info;
997 int16 open_sattr;
998 time_t open_time;
999 #endif
1000 int open_ofun;
1001 uint32 open_size;
1002 char *pname;
1003 char *fname = NULL;
1004 SMB_OFF_T size=0;
1005 int fattr=0,mtime=0;
1006 SMB_INO_T inode = 0;
1007 int smb_action = 0;
1008 files_struct *fsp;
1009 struct ea_list *ea_list = NULL;
1010 uint16 flags = 0;
1011 NTSTATUS status;
1012 uint32 access_mask;
1013 uint32 share_mode;
1014 uint32 create_disposition;
1015 uint32 create_options = 0;
1016 uint32_t private_flags = 0;
1017 TALLOC_CTX *ctx = talloc_tos();
1020 * Ensure we have enough parameters to perform the operation.
1023 if (total_params < 29) {
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1025 goto out;
1028 flags = SVAL(params, 0);
1029 deny_mode = SVAL(params, 2);
1030 open_attr = SVAL(params,6);
1031 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1032 if (oplock_request) {
1033 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1036 #if 0
1037 return_additional_info = BITSETW(params,0);
1038 open_sattr = SVAL(params, 4);
1039 open_time = make_unix_date3(params+8);
1040 #endif
1041 open_ofun = SVAL(params,12);
1042 open_size = IVAL(params,14);
1043 pname = &params[28];
1045 if (IS_IPC(conn)) {
1046 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1047 goto out;
1050 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1051 total_params - 28, STR_TERMINATE,
1052 &status);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 reply_nterror(req, status);
1055 goto out;
1058 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1059 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1060 (unsigned int)open_ofun, open_size));
1062 status = filename_convert(ctx,
1063 conn,
1064 req->flags2 & FLAGS2_DFS_PATHNAMES,
1065 fname,
1067 NULL,
1068 &smb_fname);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1071 reply_botherror(req,
1072 NT_STATUS_PATH_NOT_COVERED,
1073 ERRSRV, ERRbadpath);
1074 goto out;
1076 reply_nterror(req, status);
1077 goto out;
1080 if (open_ofun == 0) {
1081 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1082 goto out;
1085 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1086 open_ofun,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1089 &create_options,
1090 &private_flags)) {
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1092 goto out;
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1099 goto out;
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 goto out;
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1110 total_data - 4);
1111 if (!ea_list) {
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1113 goto out;
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1118 goto out;
1122 status = SMB_VFS_CREATE_FILE(
1123 conn, /* conn */
1124 req, /* req */
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1134 private_flags,
1135 NULL, /* sd */
1136 ea_list, /* ea_list */
1137 &fsp, /* result */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->sconn, req->mid)) {
1142 /* We have re-scheduled this call. */
1143 goto out;
1145 reply_openerror(req, status);
1146 goto out;
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1156 goto out;
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1163 goto out;
1165 params = *pparams;
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1186 if (flags & 8) {
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1190 } else {
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1196 out:
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1209 const char *str,
1210 const char *mask)
1212 if (mask[0] == '.' && mask[1] == 0) {
1213 return false;
1216 if (has_wild) {
1217 return false;
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1222 } else {
1223 return strcasecmp_m(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1233 if(S_ISREG(mode))
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1237 #ifdef S_ISLNK
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1240 #endif
1241 #ifdef S_ISCHR
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1244 #endif
1245 #ifdef S_ISBLK
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1248 #endif
1249 #ifdef S_ISFIFO
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1252 #endif
1253 #ifdef S_ISSOCK
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1256 #endif
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1270 uint32 perms,
1271 enum perm_type ptype,
1272 mode_t *ret_perms)
1274 mode_t ret = 0;
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1279 } else {
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1294 #ifdef S_ISVTX
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1296 #endif
1297 #ifdef S_ISGID
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1299 #endif
1300 #ifdef S_ISUID
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1302 #endif
1304 switch (ptype) {
1305 case PERM_NEW_FILE:
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1310 break;
1311 case PERM_NEW_DIR:
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1315 break;
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1321 break;
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1327 break;
1330 *ret_perms = ret;
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1349 "as a directory\n",
1350 pathname));
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1353 return true;
1355 errno = saved_errno;
1356 return false;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1368 bool has_wild;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1373 void *private_data,
1374 const char *dname,
1375 const char *mask,
1376 char **_fname)
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1380 bool ok;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1382 bool got_match;
1383 const char *fname;
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1389 if (!ok) {
1390 return false;
1392 fname = mangled_name;
1393 } else {
1394 fname = dname;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1399 fname, mask);
1400 state->got_exact_match = got_match;
1401 if (!got_match) {
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1417 if (!ok) {
1418 return false;
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1425 if (!got_match) {
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1431 if (!got_match) {
1432 return false;
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1437 return false;
1440 return true;
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1444 void *private_data,
1445 struct smb_filename *smb_fname,
1446 uint32_t *_mode)
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1451 uint32_t mode = 0;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1458 strerror(errno)));
1459 return false;
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1464 * directories */
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1468 &smb_fname->st);
1469 if (!ms_dfs_link) {
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1473 strerror(errno)));
1474 return false;
1478 if (ms_dfs_link) {
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1480 } else {
1481 mode = dos_mode(state->conn, smb_fname);
1484 *_mode = mode;
1485 return true;
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1490 uint16_t flags2,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1495 uint32_t mode,
1496 const char *fname,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1499 uint8_t align,
1500 bool do_pad,
1501 char *base_data,
1502 char **ppdata,
1503 char *end_data,
1504 bool *out_of_space,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1508 uint32_t reskey=0;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1512 uint32_t len;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1516 char *nameptr;
1517 char *last_entry_ptr;
1518 bool was_8_3;
1519 int off;
1520 int pad = 0;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1558 pad -= off;
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1564 (unsigned int)pad,
1565 space_remaining ));
1566 return false; /* Not finished - just out of space */
1569 off += pad;
1570 /* initialize padding to 0 */
1571 if (pad) {
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1577 space_remaining ));
1579 pdata += pad;
1580 p = pdata;
1581 last_entry_ptr = p;
1583 pad = 0;
1584 off = 0;
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1590 SIVAL(p,0,reskey);
1591 p += 4;
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1598 SSVAL(p,20,mode);
1599 p += 23;
1600 nameptr = p;
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE);
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1608 if (len > 2) {
1609 SCVAL(nameptr, -1, len - 2);
1610 } else {
1611 SCVAL(nameptr, -1, 0);
1613 } else {
1614 if (len > 1) {
1615 SCVAL(nameptr, -1, len - 1);
1616 } else {
1617 SCVAL(nameptr, -1, 0);
1620 p += len;
1621 break;
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1626 SIVAL(p,0,reskey);
1627 p += 4;
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1634 SSVAL(p,20,mode);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1640 p += 27;
1641 nameptr = p - 1;
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1646 if (len > 2) {
1647 len -= 2;
1648 } else {
1649 len = 0;
1651 } else {
1652 if (len > 1) {
1653 len -= 1;
1654 } else {
1655 len = 0;
1658 SCVAL(nameptr,0,len);
1659 p += len;
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1661 break;
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1666 size_t ea_len = 0;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1669 if (!name_list) {
1670 return false;
1672 if (requires_resume_key) {
1673 SIVAL(p,0,reskey);
1674 p += 4;
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1681 SSVAL(p,20,mode);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1686 &ea_len);
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1696 space_remaining ));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702 nameptr = p;
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707 if (len > 2) {
1708 len -= 2;
1709 } else {
1710 len = 0;
1712 } else {
1713 if (len > 1) {
1714 len -= 1;
1715 } else {
1716 len = 0;
1719 SCVAL(nameptr,0,len);
1720 p += len + 1;
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722 break;
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728 p += 4;
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1742 p += 4;
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1751 conn->params)) {
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1759 if (len < 24) {
1760 memset(p + 2 + len,'\0',24 - len);
1762 SSVAL(p, 0, len);
1763 } else {
1764 memset(p,'\0',26);
1766 p += 2 + 24;
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1770 SIVAL(q,0,len);
1771 p += len;
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1780 SIVAL(pdata,0,pad);
1782 * set padding to zero
1784 if (do_pad) {
1785 memset(p, 0, pad - len);
1786 p = pdata + pad;
1787 } else {
1788 p = pdata + len;
1790 break;
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1794 p += 4;
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1806 SIVAL(p,0,len);
1807 p += 4 + len;
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1816 SIVAL(pdata,0,pad);
1818 * set padding to zero
1820 if (do_pad) {
1821 memset(p, 0, pad - len);
1822 p = pdata + pad;
1823 } else {
1824 p = pdata + len;
1826 break;
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1830 p += 4;
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1844 p +=4;
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1849 SIVAL(q, 0, len);
1850 p += len;
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1859 SIVAL(pdata,0,pad);
1861 * set padding to zero
1863 if (do_pad) {
1864 memset(p, 0, pad - len);
1865 p = pdata + pad;
1866 } else {
1867 p = pdata + len;
1869 break;
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1873 p += 4;
1874 SIVAL(p,0,reskey); p += 4;
1875 p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1881 SIVAL(p, -4, len);
1882 p += len;
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1891 SIVAL(pdata,0,pad);
1893 * set padding to zero
1895 if (do_pad) {
1896 memset(p, 0, pad - len);
1897 p = pdata + pad;
1898 } else {
1899 p = pdata + len;
1901 break;
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1905 p += 4;
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1919 p +=4;
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1926 SIVAL(q, 0, len);
1927 p += len;
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1936 SIVAL(pdata,0,pad);
1938 * set padding to zero
1940 if (do_pad) {
1941 memset(p, 0, pad - len);
1942 p = pdata + pad;
1943 } else {
1944 p = pdata + len;
1946 break;
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1951 p += 4;
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1965 p +=4;
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1974 conn->params)) {
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1982 SSVAL(p, 0, len);
1983 if (len < 24) {
1984 memset(p + 2 + len,'\0',24 - len);
1986 SSVAL(p, 0, len);
1987 } else {
1988 memset(p,'\0',26);
1990 p += 26;
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1996 SIVAL(q,0,len);
1997 p += len;
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2006 SIVAL(pdata,0,pad);
2008 * set padding to zero
2010 if (do_pad) {
2011 memset(p, 0, pad - len);
2012 p = pdata + pad;
2013 } else {
2014 p = pdata + len;
2016 break;
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2022 p+= 4;
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2033 STR_TERMINATE);
2034 } else {
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2038 nameptr = p;
2039 p += 4;
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2045 p += len;
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2054 SIVAL(pdata,0,pad);
2056 * set padding to zero
2058 if (do_pad) {
2059 memset(p, 0, pad - len);
2060 p = pdata + pad;
2061 } else {
2062 p = pdata + len;
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2066 break;
2068 default:
2069 return false;
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2077 space_remaining ));
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2084 *ppdata = p;
2086 return true;
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2092 uint16 flags2,
2093 const char *path_mask,
2094 uint32 dirtype,
2095 int info_level,
2096 int requires_resume_key,
2097 bool dont_descend,
2098 bool ask_sharemode,
2099 uint8_t align,
2100 bool do_pad,
2101 char **ppdata,
2102 char *base_data,
2103 char *end_data,
2104 int space_remaining,
2105 bool *out_of_space,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2110 const char *p;
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2113 uint32_t mode = 0;
2114 char *fname = NULL;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2117 bool ok;
2118 uint64_t last_entry_off = 0;
2120 ZERO_STRUCT(state);
2121 state.conn = conn;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2131 if(p != NULL) {
2132 if(p[1] == '\0') {
2133 mask = "*.*";
2134 } else {
2135 mask = p+1;
2137 } else {
2138 mask = path_mask;
2141 ok = smbd_dirptr_get_entry(ctx,
2142 dirptr,
2143 mask,
2144 dirtype,
2145 dont_descend,
2146 ask_sharemode,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2149 &state,
2150 &fname,
2151 &smb_fname,
2152 &mode,
2153 &prev_dirpos);
2154 if (!ok) {
2155 return false;
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2161 conn,
2162 flags2,
2163 info_level,
2164 name_list,
2165 state.check_mangled_names,
2166 requires_resume_key,
2167 mode,
2168 fname,
2169 smb_fname,
2170 space_remaining,
2171 align,
2172 do_pad,
2173 base_data,
2174 ppdata,
2175 end_data,
2176 out_of_space,
2177 &last_entry_off);
2178 TALLOC_FREE(fname);
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2182 return false;
2184 if (!ok) {
2185 return false;
2188 *_last_entry_off = last_entry_off;
2189 return true;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2195 uint16 flags2,
2196 const char *path_mask,
2197 uint32 dirtype,
2198 int info_level,
2199 bool requires_resume_key,
2200 bool dont_descend,
2201 bool ask_sharemode,
2202 char **ppdata,
2203 char *base_data,
2204 char *end_data,
2205 int space_remaining,
2206 bool *out_of_space,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2211 uint8_t align = 4;
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2216 align = 1;
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2222 align, do_pad,
2223 ppdata, base_data, end_data,
2224 space_remaining,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2243 requested. */
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2247 char *data_end;
2248 uint32 dirtype;
2249 int maxentries;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2252 bool close_if_end;
2253 bool requires_resume_key;
2254 int info_level;
2255 char *directory = NULL;
2256 char *mask = NULL;
2257 char *p;
2258 int last_entry_off=0;
2259 int dptr_num = -1;
2260 int numentries = 0;
2261 int i;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2273 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2275 if (total_params < 13) {
2276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2277 goto out;
2280 dirtype = SVAL(params,0);
2281 maxentries = SVAL(params,2);
2282 findfirst_flags = SVAL(params,4);
2283 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2284 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2285 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2286 info_level = SVAL(params,6);
2288 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2289 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2290 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2291 info_level, max_data_bytes));
2293 if (!maxentries) {
2294 /* W2K3 seems to treat zero as 1. */
2295 maxentries = 1;
2298 switch (info_level) {
2299 case SMB_FIND_INFO_STANDARD:
2300 case SMB_FIND_EA_SIZE:
2301 case SMB_FIND_EA_LIST:
2302 case SMB_FIND_FILE_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2304 case SMB_FIND_FILE_NAMES_INFO:
2305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2306 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2308 break;
2309 case SMB_FIND_FILE_UNIX:
2310 case SMB_FIND_FILE_UNIX_INFO2:
2311 /* Always use filesystem for UNIX mtime query. */
2312 ask_sharemode = false;
2313 if (!lp_unix_extensions()) {
2314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 goto out;
2317 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2318 break;
2319 default:
2320 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2321 goto out;
2324 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2325 params+12, total_params - 12,
2326 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2327 if (!NT_STATUS_IS_OK(ntstatus)) {
2328 reply_nterror(req, ntstatus);
2329 goto out;
2332 ntstatus = filename_convert(ctx, conn,
2333 req->flags2 & FLAGS2_DFS_PATHNAMES,
2334 directory,
2335 ucf_flags,
2336 &mask_contains_wcard,
2337 &smb_dname);
2338 if (!NT_STATUS_IS_OK(ntstatus)) {
2339 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2340 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2341 ERRSRV, ERRbadpath);
2342 goto out;
2344 reply_nterror(req, ntstatus);
2345 goto out;
2348 mask = smb_dname->original_lcomp;
2350 directory = smb_dname->base_name;
2352 p = strrchr_m(directory,'/');
2353 if(p == NULL) {
2354 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2355 if((directory[0] == '.') && (directory[1] == '\0')) {
2356 mask = talloc_strdup(ctx,"*");
2357 if (!mask) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 goto out;
2361 mask_contains_wcard = True;
2363 } else {
2364 *p = 0;
2367 if (p == NULL || p == directory) {
2368 /* Ensure we don't have a directory name of "". */
2369 directory = talloc_strdup(talloc_tos(), ".");
2370 if (!directory) {
2371 reply_nterror(req, NT_STATUS_NO_MEMORY);
2372 goto out;
2376 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2378 if (info_level == SMB_FIND_EA_LIST) {
2379 uint32 ea_size;
2381 if (total_data < 4) {
2382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2383 goto out;
2386 ea_size = IVAL(pdata,0);
2387 if (ea_size != total_data) {
2388 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2389 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2391 goto out;
2394 if (!lp_ea_support(SNUM(conn))) {
2395 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2396 goto out;
2399 /* Pull out the list of names. */
2400 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2401 if (!ea_list) {
2402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2403 goto out;
2407 *ppdata = (char *)SMB_REALLOC(
2408 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2409 if(*ppdata == NULL ) {
2410 reply_nterror(req, NT_STATUS_NO_MEMORY);
2411 goto out;
2413 pdata = *ppdata;
2414 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2416 /* Realloc the params space */
2417 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2418 if (*pparams == NULL) {
2419 reply_nterror(req, NT_STATUS_NO_MEMORY);
2420 goto out;
2422 params = *pparams;
2424 /* Save the wildcard match and attribs we are using on this directory -
2425 needed as lanman2 assumes these are being saved between calls */
2427 ntstatus = dptr_create(conn,
2428 NULL, /* fsp */
2429 directory,
2430 False,
2431 True,
2432 req->smbpid,
2433 mask,
2434 mask_contains_wcard,
2435 dirtype,
2436 &dirptr);
2438 if (!NT_STATUS_IS_OK(ntstatus)) {
2439 reply_nterror(req, ntstatus);
2440 goto out;
2443 dptr_num = dptr_dnum(dirptr);
2444 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2446 /* Initialize per TRANS2_FIND_FIRST operation data */
2447 dptr_init_search_op(dirptr);
2449 /* We don't need to check for VOL here as this is returned by
2450 a different TRANS2 call. */
2452 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2453 directory,lp_dontdescend(SNUM(conn))));
2454 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2455 dont_descend = True;
2457 p = pdata;
2458 space_remaining = max_data_bytes;
2459 out_of_space = False;
2461 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2462 bool got_exact_match = False;
2464 /* this is a heuristic to avoid seeking the dirptr except when
2465 absolutely necessary. It allows for a filename of about 40 chars */
2466 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2467 out_of_space = True;
2468 finished = False;
2469 } else {
2470 finished = !get_lanman2_dir_entry(ctx,
2471 conn,
2472 dirptr,
2473 req->flags2,
2474 mask,dirtype,info_level,
2475 requires_resume_key,dont_descend,
2476 ask_sharemode,
2477 &p,pdata,data_end,
2478 space_remaining, &out_of_space,
2479 &got_exact_match,
2480 &last_entry_off, ea_list);
2483 if (finished && out_of_space)
2484 finished = False;
2486 if (!finished && !out_of_space)
2487 numentries++;
2490 * As an optimisation if we know we aren't looking
2491 * for a wildcard name (ie. the name matches the wildcard exactly)
2492 * then we can finish on any (first) match.
2493 * This speeds up large directory searches. JRA.
2496 if(got_exact_match)
2497 finished = True;
2499 /* Ensure space_remaining never goes -ve. */
2500 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2501 space_remaining = 0;
2502 out_of_space = true;
2503 } else {
2504 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2508 /* Check if we can close the dirptr */
2509 if(close_after_first || (finished && close_if_end)) {
2510 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2511 dptr_close(sconn, &dptr_num);
2515 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2516 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2517 * the protocol level is less than NT1. Tested with smbclient. JRA.
2518 * This should fix the OS/2 client bug #2335.
2521 if(numentries == 0) {
2522 dptr_close(sconn, &dptr_num);
2523 if (get_Protocol() < PROTOCOL_NT1) {
2524 reply_force_doserror(req, ERRDOS, ERRnofiles);
2525 goto out;
2526 } else {
2527 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2528 ERRDOS, ERRbadfile);
2529 goto out;
2533 /* At this point pdata points to numentries directory entries. */
2535 /* Set up the return parameter block */
2536 SSVAL(params,0,dptr_num);
2537 SSVAL(params,2,numentries);
2538 SSVAL(params,4,finished);
2539 SSVAL(params,6,0); /* Never an EA error */
2540 SSVAL(params,8,last_entry_off);
2542 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2543 max_data_bytes);
2545 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2546 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2547 if (!directory) {
2548 reply_nterror(req, NT_STATUS_NO_MEMORY);
2552 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2553 smb_fn_name(req->cmd),
2554 mask, directory, dirtype, numentries ) );
2557 * Force a name mangle here to ensure that the
2558 * mask as an 8.3 name is top of the mangled cache.
2559 * The reasons for this are subtle. Don't remove
2560 * this code unless you know what you are doing
2561 * (see PR#13758). JRA.
2564 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2565 char mangled_name[13];
2566 name_to_8_3(mask, mangled_name, True, conn->params);
2568 out:
2569 TALLOC_FREE(smb_dname);
2570 return;
2573 /****************************************************************************
2574 Reply to a TRANS2_FINDNEXT.
2575 ****************************************************************************/
2577 static void call_trans2findnext(connection_struct *conn,
2578 struct smb_request *req,
2579 char **pparams, int total_params,
2580 char **ppdata, int total_data,
2581 unsigned int max_data_bytes)
2583 /* We must be careful here that we don't return more than the
2584 allowed number of data bytes. If this means returning fewer than
2585 maxentries then so be it. We assume that the redirector has
2586 enough room for the fixed number of parameter bytes it has
2587 requested. */
2588 char *params = *pparams;
2589 char *pdata = *ppdata;
2590 char *data_end;
2591 int dptr_num;
2592 int maxentries;
2593 uint16 info_level;
2594 uint32 resume_key;
2595 uint16 findnext_flags;
2596 bool close_after_request;
2597 bool close_if_end;
2598 bool requires_resume_key;
2599 bool continue_bit;
2600 bool mask_contains_wcard = False;
2601 char *resume_name = NULL;
2602 const char *mask = NULL;
2603 const char *directory = NULL;
2604 char *p = NULL;
2605 uint16 dirtype;
2606 int numentries = 0;
2607 int i, last_entry_off=0;
2608 bool finished = False;
2609 bool dont_descend = False;
2610 bool out_of_space = False;
2611 int space_remaining;
2612 struct ea_list *ea_list = NULL;
2613 NTSTATUS ntstatus = NT_STATUS_OK;
2614 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2615 TALLOC_CTX *ctx = talloc_tos();
2616 struct dptr_struct *dirptr;
2617 struct smbd_server_connection *sconn = req->sconn;
2619 if (total_params < 13) {
2620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2621 return;
2624 dptr_num = SVAL(params,0);
2625 maxentries = SVAL(params,2);
2626 info_level = SVAL(params,4);
2627 resume_key = IVAL(params,6);
2628 findnext_flags = SVAL(params,10);
2629 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2630 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2631 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2632 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2634 if (!continue_bit) {
2635 /* We only need resume_name if continue_bit is zero. */
2636 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2637 params+12,
2638 total_params - 12, STR_TERMINATE, &ntstatus,
2639 &mask_contains_wcard);
2640 if (!NT_STATUS_IS_OK(ntstatus)) {
2641 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2642 complain (it thinks we're asking for the directory above the shared
2643 path or an invalid name). Catch this as the resume name is only compared, never used in
2644 a file access. JRA. */
2645 srvstr_pull_talloc(ctx, params, req->flags2,
2646 &resume_name, params+12,
2647 total_params - 12,
2648 STR_TERMINATE);
2650 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2651 reply_nterror(req, ntstatus);
2652 return;
2657 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2658 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2659 resume_key = %d resume name = %s continue=%d level = %d\n",
2660 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2661 requires_resume_key, resume_key,
2662 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2664 if (!maxentries) {
2665 /* W2K3 seems to treat zero as 1. */
2666 maxentries = 1;
2669 switch (info_level) {
2670 case SMB_FIND_INFO_STANDARD:
2671 case SMB_FIND_EA_SIZE:
2672 case SMB_FIND_EA_LIST:
2673 case SMB_FIND_FILE_DIRECTORY_INFO:
2674 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2675 case SMB_FIND_FILE_NAMES_INFO:
2676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2677 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2678 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2679 break;
2680 case SMB_FIND_FILE_UNIX:
2681 case SMB_FIND_FILE_UNIX_INFO2:
2682 /* Always use filesystem for UNIX mtime query. */
2683 ask_sharemode = false;
2684 if (!lp_unix_extensions()) {
2685 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2686 return;
2688 break;
2689 default:
2690 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 return;
2694 if (info_level == SMB_FIND_EA_LIST) {
2695 uint32 ea_size;
2697 if (total_data < 4) {
2698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2699 return;
2702 ea_size = IVAL(pdata,0);
2703 if (ea_size != total_data) {
2704 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2705 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2707 return;
2710 if (!lp_ea_support(SNUM(conn))) {
2711 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2712 return;
2715 /* Pull out the list of names. */
2716 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2717 if (!ea_list) {
2718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2719 return;
2723 *ppdata = (char *)SMB_REALLOC(
2724 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725 if(*ppdata == NULL) {
2726 reply_nterror(req, NT_STATUS_NO_MEMORY);
2727 return;
2730 pdata = *ppdata;
2731 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2733 /* Realloc the params space */
2734 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2735 if(*pparams == NULL ) {
2736 reply_nterror(req, NT_STATUS_NO_MEMORY);
2737 return;
2740 params = *pparams;
2742 /* Check that the dptr is valid */
2743 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2744 reply_nterror(req, STATUS_NO_MORE_FILES);
2745 return;
2748 directory = dptr_path(sconn, dptr_num);
2750 /* Get the wildcard mask from the dptr */
2751 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2752 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2753 reply_nterror(req, STATUS_NO_MORE_FILES);
2754 return;
2757 mask = p;
2759 /* Get the attr mask from the dptr */
2760 dirtype = dptr_attr(sconn, dptr_num);
2762 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2763 dptr_num, mask, dirtype,
2764 (long)dirptr,
2765 dptr_TellDir(dirptr)));
2767 /* Initialize per TRANS2_FIND_NEXT operation data */
2768 dptr_init_search_op(dirptr);
2770 /* We don't need to check for VOL here as this is returned by
2771 a different TRANS2 call. */
2773 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2774 directory,lp_dontdescend(SNUM(conn))));
2775 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2776 dont_descend = True;
2778 p = pdata;
2779 space_remaining = max_data_bytes;
2780 out_of_space = False;
2783 * Seek to the correct position. We no longer use the resume key but
2784 * depend on the last file name instead.
2787 if(!continue_bit && resume_name && *resume_name) {
2788 SMB_STRUCT_STAT st;
2790 long current_pos = 0;
2792 * Remember, name_to_8_3 is called by
2793 * get_lanman2_dir_entry(), so the resume name
2794 * could be mangled. Ensure we check the unmangled name.
2797 if (mangle_is_mangled(resume_name, conn->params)) {
2798 char *new_resume_name = NULL;
2799 mangle_lookup_name_from_8_3(ctx,
2800 resume_name,
2801 &new_resume_name,
2802 conn->params);
2803 if (new_resume_name) {
2804 resume_name = new_resume_name;
2809 * Fix for NT redirector problem triggered by resume key indexes
2810 * changing between directory scans. We now return a resume key of 0
2811 * and instead look for the filename to continue from (also given
2812 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2813 * findfirst/findnext (as is usual) then the directory pointer
2814 * should already be at the correct place.
2817 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2818 } /* end if resume_name && !continue_bit */
2820 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2821 bool got_exact_match = False;
2823 /* this is a heuristic to avoid seeking the dirptr except when
2824 absolutely necessary. It allows for a filename of about 40 chars */
2825 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2826 out_of_space = True;
2827 finished = False;
2828 } else {
2829 finished = !get_lanman2_dir_entry(ctx,
2830 conn,
2831 dirptr,
2832 req->flags2,
2833 mask,dirtype,info_level,
2834 requires_resume_key,dont_descend,
2835 ask_sharemode,
2836 &p,pdata,data_end,
2837 space_remaining, &out_of_space,
2838 &got_exact_match,
2839 &last_entry_off, ea_list);
2842 if (finished && out_of_space)
2843 finished = False;
2845 if (!finished && !out_of_space)
2846 numentries++;
2849 * As an optimisation if we know we aren't looking
2850 * for a wildcard name (ie. the name matches the wildcard exactly)
2851 * then we can finish on any (first) match.
2852 * This speeds up large directory searches. JRA.
2855 if(got_exact_match)
2856 finished = True;
2858 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2861 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2862 smb_fn_name(req->cmd),
2863 mask, directory, dirtype, numentries ) );
2865 /* Check if we can close the dirptr */
2866 if(close_after_request || (finished && close_if_end)) {
2867 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2868 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2871 /* Set up the return parameter block */
2872 SSVAL(params,0,numentries);
2873 SSVAL(params,2,finished);
2874 SSVAL(params,4,0); /* Never an EA error */
2875 SSVAL(params,6,last_entry_off);
2877 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2878 max_data_bytes);
2880 return;
2883 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2885 E_md4hash(lp_servicename(SNUM(conn)),objid);
2886 return objid;
2889 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2891 SMB_ASSERT(extended_info != NULL);
2893 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2894 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2895 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2896 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2897 #ifdef SAMBA_VERSION_REVISION
2898 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2899 #endif
2900 extended_info->samba_subversion = 0;
2901 #ifdef SAMBA_VERSION_RC_RELEASE
2902 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2903 #else
2904 #ifdef SAMBA_VERSION_PRE_RELEASE
2905 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2906 #endif
2907 #endif
2908 #ifdef SAMBA_VERSION_VENDOR_PATCH
2909 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2910 #endif
2911 extended_info->samba_gitcommitdate = 0;
2912 #ifdef SAMBA_VERSION_COMMIT_TIME
2913 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2914 #endif
2916 memset(extended_info->samba_version_string, 0,
2917 sizeof(extended_info->samba_version_string));
2919 snprintf (extended_info->samba_version_string,
2920 sizeof(extended_info->samba_version_string),
2921 "%s", samba_version_string());
2924 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2925 TALLOC_CTX *mem_ctx,
2926 uint16_t info_level,
2927 uint16_t flags2,
2928 unsigned int max_data_bytes,
2929 char **ppdata,
2930 int *ret_data_len)
2932 char *pdata, *end_data;
2933 int data_len = 0, len;
2934 const char *vname = volume_label(SNUM(conn));
2935 int snum = SNUM(conn);
2936 char *fstype = lp_fstype(SNUM(conn));
2937 uint32 additional_flags = 0;
2938 struct smb_filename smb_fname_dot;
2939 SMB_STRUCT_STAT st;
2941 if (IS_IPC(conn)) {
2942 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2943 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2944 "info level (0x%x) on IPC$.\n",
2945 (unsigned int)info_level));
2946 return NT_STATUS_ACCESS_DENIED;
2950 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2952 ZERO_STRUCT(smb_fname_dot);
2953 smb_fname_dot.base_name = discard_const_p(char, ".");
2955 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2956 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2957 return map_nt_error_from_unix(errno);
2960 st = smb_fname_dot.st;
2962 *ppdata = (char *)SMB_REALLOC(
2963 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2964 if (*ppdata == NULL) {
2965 return NT_STATUS_NO_MEMORY;
2968 pdata = *ppdata;
2969 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2970 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2972 switch (info_level) {
2973 case SMB_INFO_ALLOCATION:
2975 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2976 data_len = 18;
2977 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2978 return map_nt_error_from_unix(errno);
2981 block_size = lp_block_size(snum);
2982 if (bsize < block_size) {
2983 uint64_t factor = block_size/bsize;
2984 bsize = block_size;
2985 dsize /= factor;
2986 dfree /= factor;
2988 if (bsize > block_size) {
2989 uint64_t factor = bsize/block_size;
2990 bsize = block_size;
2991 dsize *= factor;
2992 dfree *= factor;
2994 bytes_per_sector = 512;
2995 sectors_per_unit = bsize/bytes_per_sector;
2997 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2998 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2999 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3001 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3002 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3003 SIVAL(pdata,l1_cUnit,dsize);
3004 SIVAL(pdata,l1_cUnitAvail,dfree);
3005 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3006 break;
3009 case SMB_INFO_VOLUME:
3010 /* Return volume name */
3012 * Add volume serial number - hash of a combination of
3013 * the called hostname and the service name.
3015 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3017 * Win2k3 and previous mess this up by sending a name length
3018 * one byte short. I believe only older clients (OS/2 Win9x) use
3019 * this call so try fixing this by adding a terminating null to
3020 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3022 len = srvstr_push(
3023 pdata, flags2,
3024 pdata+l2_vol_szVolLabel, vname,
3025 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3026 STR_NOALIGN|STR_TERMINATE);
3027 SCVAL(pdata,l2_vol_cch,len);
3028 data_len = l2_vol_szVolLabel + len;
3029 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3030 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3031 len, vname));
3032 break;
3034 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3035 case SMB_FS_ATTRIBUTE_INFORMATION:
3037 additional_flags = 0;
3038 #if defined(HAVE_SYS_QUOTAS)
3039 additional_flags |= FILE_VOLUME_QUOTAS;
3040 #endif
3042 if(lp_nt_acl_support(SNUM(conn))) {
3043 additional_flags |= FILE_PERSISTENT_ACLS;
3046 /* Capabilities are filled in at connection time through STATVFS call */
3047 additional_flags |= conn->fs_capabilities;
3048 additional_flags |= lp_parm_int(conn->params->service,
3049 "share", "fake_fscaps",
3052 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3053 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3054 additional_flags); /* FS ATTRIBUTES */
3056 SIVAL(pdata,4,255); /* Max filename component length */
3057 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3058 and will think we can't do long filenames */
3059 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3060 PTR_DIFF(end_data, pdata+12),
3061 STR_UNICODE);
3062 SIVAL(pdata,8,len);
3063 data_len = 12 + len;
3064 break;
3066 case SMB_QUERY_FS_LABEL_INFO:
3067 case SMB_FS_LABEL_INFORMATION:
3068 len = srvstr_push(pdata, flags2, pdata+4, vname,
3069 PTR_DIFF(end_data, pdata+4), 0);
3070 data_len = 4 + len;
3071 SIVAL(pdata,0,len);
3072 break;
3074 case SMB_QUERY_FS_VOLUME_INFO:
3075 case SMB_FS_VOLUME_INFORMATION:
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3082 (str_checksum(get_local_machine_name())<<16));
3084 /* Max label len is 32 characters. */
3085 len = srvstr_push(pdata, flags2, pdata+18, vname,
3086 PTR_DIFF(end_data, pdata+18),
3087 STR_UNICODE);
3088 SIVAL(pdata,12,len);
3089 data_len = 18+len;
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3092 (int)strlen(vname),vname, lp_servicename(snum)));
3093 break;
3095 case SMB_QUERY_FS_SIZE_INFO:
3096 case SMB_FS_SIZE_INFORMATION:
3098 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3099 data_len = 24;
3100 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3101 return map_nt_error_from_unix(errno);
3103 block_size = lp_block_size(snum);
3104 if (bsize < block_size) {
3105 uint64_t factor = block_size/bsize;
3106 bsize = block_size;
3107 dsize /= factor;
3108 dfree /= factor;
3110 if (bsize > block_size) {
3111 uint64_t factor = bsize/block_size;
3112 bsize = block_size;
3113 dsize *= factor;
3114 dfree *= factor;
3116 bytes_per_sector = 512;
3117 sectors_per_unit = bsize/bytes_per_sector;
3118 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3119 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3120 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3121 SBIG_UINT(pdata,0,dsize);
3122 SBIG_UINT(pdata,8,dfree);
3123 SIVAL(pdata,16,sectors_per_unit);
3124 SIVAL(pdata,20,bytes_per_sector);
3125 break;
3128 case SMB_FS_FULL_SIZE_INFORMATION:
3130 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3131 data_len = 32;
3132 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3133 return map_nt_error_from_unix(errno);
3135 block_size = lp_block_size(snum);
3136 if (bsize < block_size) {
3137 uint64_t factor = block_size/bsize;
3138 bsize = block_size;
3139 dsize /= factor;
3140 dfree /= factor;
3142 if (bsize > block_size) {
3143 uint64_t factor = bsize/block_size;
3144 bsize = block_size;
3145 dsize *= factor;
3146 dfree *= factor;
3148 bytes_per_sector = 512;
3149 sectors_per_unit = bsize/bytes_per_sector;
3150 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3151 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3152 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3153 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3154 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3155 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3156 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3157 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3158 break;
3161 case SMB_QUERY_FS_DEVICE_INFO:
3162 case SMB_FS_DEVICE_INFORMATION:
3164 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3166 if (!CAN_WRITE(conn)) {
3167 characteristics |= FILE_READ_ONLY_DEVICE;
3169 data_len = 8;
3170 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3171 SIVAL(pdata,4,characteristics);
3172 break;
3175 #ifdef HAVE_SYS_QUOTAS
3176 case SMB_FS_QUOTA_INFORMATION:
3178 * what we have to send --metze:
3180 * Unknown1: 24 NULL bytes
3181 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3182 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3183 * Quota Flags: 2 byte :
3184 * Unknown3: 6 NULL bytes
3186 * 48 bytes total
3188 * details for Quota Flags:
3190 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3191 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3192 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3193 * 0x0001 Enable Quotas: enable quota for this fs
3197 /* we need to fake up a fsp here,
3198 * because its not send in this call
3200 files_struct fsp;
3201 SMB_NTQUOTA_STRUCT quotas;
3203 ZERO_STRUCT(fsp);
3204 ZERO_STRUCT(quotas);
3206 fsp.conn = conn;
3207 fsp.fnum = -1;
3209 /* access check */
3210 if (get_current_uid(conn) != 0) {
3211 DEBUG(0,("set_user_quota: access_denied "
3212 "service [%s] user [%s]\n",
3213 lp_servicename(SNUM(conn)),
3214 conn->session_info->unix_info->unix_name));
3215 return NT_STATUS_ACCESS_DENIED;
3218 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3219 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3220 return map_nt_error_from_unix(errno);
3223 data_len = 48;
3225 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3226 lp_servicename(SNUM(conn))));
3228 /* Unknown1 24 NULL bytes*/
3229 SBIG_UINT(pdata,0,(uint64_t)0);
3230 SBIG_UINT(pdata,8,(uint64_t)0);
3231 SBIG_UINT(pdata,16,(uint64_t)0);
3233 /* Default Soft Quota 8 bytes */
3234 SBIG_UINT(pdata,24,quotas.softlim);
3236 /* Default Hard Quota 8 bytes */
3237 SBIG_UINT(pdata,32,quotas.hardlim);
3239 /* Quota flag 2 bytes */
3240 SSVAL(pdata,40,quotas.qflags);
3242 /* Unknown3 6 NULL bytes */
3243 SSVAL(pdata,42,0);
3244 SIVAL(pdata,44,0);
3246 break;
3248 #endif /* HAVE_SYS_QUOTAS */
3249 case SMB_FS_OBJECTID_INFORMATION:
3251 unsigned char objid[16];
3252 struct smb_extended_info extended_info;
3253 memcpy(pdata,create_volume_objectid(conn, objid),16);
3254 samba_extended_info_version (&extended_info);
3255 SIVAL(pdata,16,extended_info.samba_magic);
3256 SIVAL(pdata,20,extended_info.samba_version);
3257 SIVAL(pdata,24,extended_info.samba_subversion);
3258 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3259 memcpy(pdata+36,extended_info.samba_version_string,28);
3260 data_len = 64;
3261 break;
3265 * Query the version and capabilities of the CIFS UNIX extensions
3266 * in use.
3269 case SMB_QUERY_CIFS_UNIX_INFO:
3271 bool large_write = lp_min_receive_file_size() &&
3272 !srv_is_signing_active(conn->sconn);
3273 bool large_read = !srv_is_signing_active(conn->sconn);
3274 int encrypt_caps = 0;
3276 if (!lp_unix_extensions()) {
3277 return NT_STATUS_INVALID_LEVEL;
3280 switch (conn->encrypt_level) {
3281 case 0:
3282 encrypt_caps = 0;
3283 break;
3284 case 1:
3285 case Auto:
3286 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3287 break;
3288 case Required:
3289 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3290 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3291 large_write = false;
3292 large_read = false;
3293 break;
3296 data_len = 12;
3297 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3298 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3300 /* We have POSIX ACLs, pathname, encryption,
3301 * large read/write, and locking capability. */
3303 SBIG_UINT(pdata,4,((uint64_t)(
3304 CIFS_UNIX_POSIX_ACLS_CAP|
3305 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3306 CIFS_UNIX_FCNTL_LOCKS_CAP|
3307 CIFS_UNIX_EXTATTR_CAP|
3308 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3309 encrypt_caps|
3310 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3311 (large_write ?
3312 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3313 break;
3316 case SMB_QUERY_POSIX_FS_INFO:
3318 int rc;
3319 vfs_statvfs_struct svfs;
3321 if (!lp_unix_extensions()) {
3322 return NT_STATUS_INVALID_LEVEL;
3325 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3327 if (!rc) {
3328 data_len = 56;
3329 SIVAL(pdata,0,svfs.OptimalTransferSize);
3330 SIVAL(pdata,4,svfs.BlockSize);
3331 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3332 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3333 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3334 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3335 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3336 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3337 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3338 #ifdef EOPNOTSUPP
3339 } else if (rc == EOPNOTSUPP) {
3340 return NT_STATUS_INVALID_LEVEL;
3341 #endif /* EOPNOTSUPP */
3342 } else {
3343 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3344 return NT_STATUS_DOS(ERRSRV, ERRerror);
3346 break;
3349 case SMB_QUERY_POSIX_WHOAMI:
3351 uint32_t flags = 0;
3352 uint32_t sid_bytes;
3353 int i;
3355 if (!lp_unix_extensions()) {
3356 return NT_STATUS_INVALID_LEVEL;
3359 if (max_data_bytes < 40) {
3360 return NT_STATUS_BUFFER_TOO_SMALL;
3363 /* We ARE guest if global_sid_Builtin_Guests is
3364 * in our list of SIDs.
3366 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3367 conn->session_info->security_token)) {
3368 flags |= SMB_WHOAMI_GUEST;
3371 /* We are NOT guest if global_sid_Authenticated_Users
3372 * is in our list of SIDs.
3374 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3375 conn->session_info->security_token)) {
3376 flags &= ~SMB_WHOAMI_GUEST;
3379 /* NOTE: 8 bytes for UID/GID, irrespective of native
3380 * platform size. This matches
3381 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3383 data_len = 4 /* flags */
3384 + 4 /* flag mask */
3385 + 8 /* uid */
3386 + 8 /* gid */
3387 + 4 /* ngroups */
3388 + 4 /* num_sids */
3389 + 4 /* SID bytes */
3390 + 4 /* pad/reserved */
3391 + (conn->session_info->unix_token->ngroups * 8)
3392 /* groups list */
3393 + (conn->session_info->security_token->num_sids *
3394 SID_MAX_SIZE)
3395 /* SID list */;
3397 SIVAL(pdata, 0, flags);
3398 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3399 SBIG_UINT(pdata, 8,
3400 (uint64_t)conn->session_info->unix_token->uid);
3401 SBIG_UINT(pdata, 16,
3402 (uint64_t)conn->session_info->unix_token->gid);
3405 if (data_len >= max_data_bytes) {
3406 /* Potential overflow, skip the GIDs and SIDs. */
3408 SIVAL(pdata, 24, 0); /* num_groups */
3409 SIVAL(pdata, 28, 0); /* num_sids */
3410 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3411 SIVAL(pdata, 36, 0); /* reserved */
3413 data_len = 40;
3414 break;
3417 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3418 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3420 /* We walk the SID list twice, but this call is fairly
3421 * infrequent, and I don't expect that it's performance
3422 * sensitive -- jpeach
3424 for (i = 0, sid_bytes = 0;
3425 i < conn->session_info->security_token->num_sids; ++i) {
3426 sid_bytes += ndr_size_dom_sid(
3427 &conn->session_info->security_token->sids[i],
3431 /* SID list byte count */
3432 SIVAL(pdata, 32, sid_bytes);
3434 /* 4 bytes pad/reserved - must be zero */
3435 SIVAL(pdata, 36, 0);
3436 data_len = 40;
3438 /* GID list */
3439 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3440 SBIG_UINT(pdata, data_len,
3441 (uint64_t)conn->session_info->unix_token->groups[i]);
3442 data_len += 8;
3445 /* SID list */
3446 for (i = 0;
3447 i < conn->session_info->security_token->num_sids; ++i) {
3448 int sid_len = ndr_size_dom_sid(
3449 &conn->session_info->security_token->sids[i],
3452 sid_linearize(pdata + data_len, sid_len,
3453 &conn->session_info->security_token->sids[i]);
3454 data_len += sid_len;
3457 break;
3460 case SMB_MAC_QUERY_FS_INFO:
3462 * Thursby MAC extension... ONLY on NTFS filesystems
3463 * once we do streams then we don't need this
3465 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3466 data_len = 88;
3467 SIVAL(pdata,84,0x100); /* Don't support mac... */
3468 break;
3470 /* drop through */
3471 default:
3472 return NT_STATUS_INVALID_LEVEL;
3475 *ret_data_len = data_len;
3476 return NT_STATUS_OK;
3479 /****************************************************************************
3480 Reply to a TRANS2_QFSINFO (query filesystem info).
3481 ****************************************************************************/
3483 static void call_trans2qfsinfo(connection_struct *conn,
3484 struct smb_request *req,
3485 char **pparams, int total_params,
3486 char **ppdata, int total_data,
3487 unsigned int max_data_bytes)
3489 char *params = *pparams;
3490 uint16_t info_level;
3491 int data_len = 0;
3492 NTSTATUS status;
3494 if (total_params < 2) {
3495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3496 return;
3499 info_level = SVAL(params,0);
3501 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3502 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3503 DEBUG(0,("call_trans2qfsinfo: encryption required "
3504 "and info level 0x%x sent.\n",
3505 (unsigned int)info_level));
3506 exit_server_cleanly("encryption required "
3507 "on connection");
3508 return;
3512 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3514 status = smbd_do_qfsinfo(conn, req,
3515 info_level,
3516 req->flags2,
3517 max_data_bytes,
3518 ppdata, &data_len);
3519 if (!NT_STATUS_IS_OK(status)) {
3520 reply_nterror(req, status);
3521 return;
3524 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3525 max_data_bytes);
3527 DEBUG( 4, ( "%s info_level = %d\n",
3528 smb_fn_name(req->cmd), info_level) );
3530 return;
3533 /****************************************************************************
3534 Reply to a TRANS2_SETFSINFO (set filesystem info).
3535 ****************************************************************************/
3537 static void call_trans2setfsinfo(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 struct smbd_server_connection *sconn = req->sconn;
3544 char *pdata = *ppdata;
3545 char *params = *pparams;
3546 uint16 info_level;
3548 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3550 /* */
3551 if (total_params < 4) {
3552 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3553 total_params));
3554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3555 return;
3558 info_level = SVAL(params,2);
3560 if (IS_IPC(conn)) {
3561 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3562 info_level != SMB_SET_CIFS_UNIX_INFO) {
3563 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3564 "info level (0x%x) on IPC$.\n",
3565 (unsigned int)info_level));
3566 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3567 return;
3571 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3572 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3573 DEBUG(0,("call_trans2setfsinfo: encryption required "
3574 "and info level 0x%x sent.\n",
3575 (unsigned int)info_level));
3576 exit_server_cleanly("encryption required "
3577 "on connection");
3578 return;
3582 switch(info_level) {
3583 case SMB_SET_CIFS_UNIX_INFO:
3584 if (!lp_unix_extensions()) {
3585 reply_nterror(req,
3586 NT_STATUS_INVALID_LEVEL);
3587 return;
3590 /* There should be 12 bytes of capabilities set. */
3591 if (total_data < 8) {
3592 reply_nterror(
3593 req,
3594 NT_STATUS_INVALID_PARAMETER);
3595 return;
3597 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3598 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3599 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3600 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3601 /* Just print these values for now. */
3602 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3603 "major = %u, minor = %u cap_low = 0x%x, "
3604 "cap_high = 0x%xn",
3605 (unsigned int)sconn->
3606 smb1.unix_info.client_major,
3607 (unsigned int)sconn->
3608 smb1.unix_info.client_minor,
3609 (unsigned int)sconn->
3610 smb1.unix_info.client_cap_low,
3611 (unsigned int)sconn->
3612 smb1.unix_info.client_cap_high));
3614 /* Here is where we must switch to posix pathname processing... */
3615 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3616 lp_set_posix_pathnames();
3617 mangle_change_to_posix();
3620 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3621 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3622 /* Client that knows how to do posix locks,
3623 * but not posix open/mkdir operations. Set a
3624 * default type for read/write checks. */
3626 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3629 break;
3631 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3633 NTSTATUS status;
3634 size_t param_len = 0;
3635 size_t data_len = total_data;
3637 if (!lp_unix_extensions()) {
3638 reply_nterror(
3639 req,
3640 NT_STATUS_INVALID_LEVEL);
3641 return;
3644 if (lp_smb_encrypt(SNUM(conn)) == false) {
3645 reply_nterror(
3646 req,
3647 NT_STATUS_NOT_SUPPORTED);
3648 return;
3651 if (req->sconn->smb1.echo_handler.trusted_fde) {
3652 DEBUG( 2,("call_trans2setfsinfo: "
3653 "request transport encryption disabled"
3654 "with 'fork echo handler = yes'\n"));
3655 reply_nterror(
3656 req,
3657 NT_STATUS_NOT_SUPPORTED);
3658 return;
3661 DEBUG( 4,("call_trans2setfsinfo: "
3662 "request transport encryption.\n"));
3664 status = srv_request_encryption_setup(conn,
3665 (unsigned char **)ppdata,
3666 &data_len,
3667 (unsigned char **)pparams,
3668 &param_len);
3670 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3671 !NT_STATUS_IS_OK(status)) {
3672 reply_nterror(req, status);
3673 return;
3676 send_trans2_replies(conn, req,
3677 *pparams,
3678 param_len,
3679 *ppdata,
3680 data_len,
3681 max_data_bytes);
3683 if (NT_STATUS_IS_OK(status)) {
3684 /* Server-side transport
3685 * encryption is now *on*. */
3686 status = srv_encryption_start(conn);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 char *reason = talloc_asprintf(talloc_tos(),
3689 "Failure in setting "
3690 "up encrypted transport: %s",
3691 nt_errstr(status));
3692 exit_server_cleanly(reason);
3695 return;
3698 case SMB_FS_QUOTA_INFORMATION:
3700 files_struct *fsp = NULL;
3701 SMB_NTQUOTA_STRUCT quotas;
3703 ZERO_STRUCT(quotas);
3705 /* access check */
3706 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3707 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3708 lp_servicename(SNUM(conn)),
3709 conn->session_info->unix_info->unix_name));
3710 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3711 return;
3714 /* note: normaly there're 48 bytes,
3715 * but we didn't use the last 6 bytes for now
3716 * --metze
3718 fsp = file_fsp(req, SVAL(params,0));
3720 if (!check_fsp_ntquota_handle(conn, req,
3721 fsp)) {
3722 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3723 reply_nterror(
3724 req, NT_STATUS_INVALID_HANDLE);
3725 return;
3728 if (total_data < 42) {
3729 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3730 total_data));
3731 reply_nterror(
3732 req,
3733 NT_STATUS_INVALID_PARAMETER);
3734 return;
3737 /* unknown_1 24 NULL bytes in pdata*/
3739 /* the soft quotas 8 bytes (uint64_t)*/
3740 quotas.softlim = BVAL(pdata,24);
3742 /* the hard quotas 8 bytes (uint64_t)*/
3743 quotas.hardlim = BVAL(pdata,32);
3745 /* quota_flags 2 bytes **/
3746 quotas.qflags = SVAL(pdata,40);
3748 /* unknown_2 6 NULL bytes follow*/
3750 /* now set the quotas */
3751 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3752 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3753 reply_nterror(req, map_nt_error_from_unix(errno));
3754 return;
3757 break;
3759 default:
3760 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3761 info_level));
3762 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3763 return;
3764 break;
3768 * sending this reply works fine,
3769 * but I'm not sure it's the same
3770 * like windows do...
3771 * --metze
3773 reply_outbuf(req, 10, 0);
3776 #if defined(HAVE_POSIX_ACLS)
3777 /****************************************************************************
3778 Utility function to count the number of entries in a POSIX acl.
3779 ****************************************************************************/
3781 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3783 unsigned int ace_count = 0;
3784 int entry_id = SMB_ACL_FIRST_ENTRY;
3785 SMB_ACL_ENTRY_T entry;
3787 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3788 /* get_next... */
3789 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3790 entry_id = SMB_ACL_NEXT_ENTRY;
3792 ace_count++;
3794 return ace_count;
3797 /****************************************************************************
3798 Utility function to marshall a POSIX acl into wire format.
3799 ****************************************************************************/
3801 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3803 int entry_id = SMB_ACL_FIRST_ENTRY;
3804 SMB_ACL_ENTRY_T entry;
3806 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3807 SMB_ACL_TAG_T tagtype;
3808 SMB_ACL_PERMSET_T permset;
3809 unsigned char perms = 0;
3810 unsigned int own_grp;
3812 /* get_next... */
3813 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3814 entry_id = SMB_ACL_NEXT_ENTRY;
3817 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3819 return False;
3822 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3823 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3824 return False;
3827 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3828 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3829 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3831 SCVAL(pdata,1,perms);
3833 switch (tagtype) {
3834 case SMB_ACL_USER_OBJ:
3835 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3836 own_grp = (unsigned int)pst->st_ex_uid;
3837 SIVAL(pdata,2,own_grp);
3838 SIVAL(pdata,6,0);
3839 break;
3840 case SMB_ACL_USER:
3842 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3843 if (!puid) {
3844 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3845 return False;
3847 own_grp = (unsigned int)*puid;
3848 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3849 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3850 SIVAL(pdata,2,own_grp);
3851 SIVAL(pdata,6,0);
3852 break;
3854 case SMB_ACL_GROUP_OBJ:
3855 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3856 own_grp = (unsigned int)pst->st_ex_gid;
3857 SIVAL(pdata,2,own_grp);
3858 SIVAL(pdata,6,0);
3859 break;
3860 case SMB_ACL_GROUP:
3862 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3863 if (!pgid) {
3864 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3865 return False;
3867 own_grp = (unsigned int)*pgid;
3868 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3869 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3870 SIVAL(pdata,2,own_grp);
3871 SIVAL(pdata,6,0);
3872 break;
3874 case SMB_ACL_MASK:
3875 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3876 SIVAL(pdata,2,0xFFFFFFFF);
3877 SIVAL(pdata,6,0xFFFFFFFF);
3878 break;
3879 case SMB_ACL_OTHER:
3880 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3881 SIVAL(pdata,2,0xFFFFFFFF);
3882 SIVAL(pdata,6,0xFFFFFFFF);
3883 break;
3884 default:
3885 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3886 return False;
3888 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3891 return True;
3893 #endif
3895 /****************************************************************************
3896 Store the FILE_UNIX_BASIC info.
3897 ****************************************************************************/
3899 static char *store_file_unix_basic(connection_struct *conn,
3900 char *pdata,
3901 files_struct *fsp,
3902 const SMB_STRUCT_STAT *psbuf)
3904 uint64_t file_index = get_FileIndex(conn, psbuf);
3906 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3907 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3909 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3910 pdata += 8;
3912 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3913 pdata += 8;
3915 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3916 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3917 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3918 pdata += 24;
3920 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3921 SIVAL(pdata,4,0);
3922 pdata += 8;
3924 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3925 SIVAL(pdata,4,0);
3926 pdata += 8;
3928 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3929 pdata += 4;
3931 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3932 SIVAL(pdata,4,0);
3933 pdata += 8;
3935 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3936 SIVAL(pdata,4,0);
3937 pdata += 8;
3939 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3940 pdata += 8;
3942 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3943 SIVAL(pdata,4,0);
3944 pdata += 8;
3946 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3947 SIVAL(pdata,4,0);
3948 pdata += 8;
3950 return pdata;
3953 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3954 * the chflags(2) (or equivalent) flags.
3956 * XXX: this really should be behind the VFS interface. To do this, we would
3957 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3958 * Each VFS module could then implement its own mapping as appropriate for the
3959 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3961 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3962 info2_flags_map[] =
3964 #ifdef UF_NODUMP
3965 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3966 #endif
3968 #ifdef UF_IMMUTABLE
3969 { UF_IMMUTABLE, EXT_IMMUTABLE },
3970 #endif
3972 #ifdef UF_APPEND
3973 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3974 #endif
3976 #ifdef UF_HIDDEN
3977 { UF_HIDDEN, EXT_HIDDEN },
3978 #endif
3980 /* Do not remove. We need to guarantee that this array has at least one
3981 * entry to build on HP-UX.
3983 { 0, 0 }
3987 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3988 uint32 *smb_fflags, uint32 *smb_fmask)
3990 int i;
3992 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3993 *smb_fmask |= info2_flags_map[i].smb_fflag;
3994 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3995 *smb_fflags |= info2_flags_map[i].smb_fflag;
4000 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4001 const uint32 smb_fflags,
4002 const uint32 smb_fmask,
4003 int *stat_fflags)
4005 uint32 max_fmask = 0;
4006 int i;
4008 *stat_fflags = psbuf->st_ex_flags;
4010 /* For each flags requested in smb_fmask, check the state of the
4011 * corresponding flag in smb_fflags and set or clear the matching
4012 * stat flag.
4015 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4016 max_fmask |= info2_flags_map[i].smb_fflag;
4017 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4018 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4019 *stat_fflags |= info2_flags_map[i].stat_fflag;
4020 } else {
4021 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4026 /* If smb_fmask is asking to set any bits that are not supported by
4027 * our flag mappings, we should fail.
4029 if ((smb_fmask & max_fmask) != smb_fmask) {
4030 return False;
4033 return True;
4037 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4038 * of file flags and birth (create) time.
4040 static char *store_file_unix_basic_info2(connection_struct *conn,
4041 char *pdata,
4042 files_struct *fsp,
4043 const SMB_STRUCT_STAT *psbuf)
4045 uint32 file_flags = 0;
4046 uint32 flags_mask = 0;
4048 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4050 /* Create (birth) time 64 bit */
4051 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4052 pdata += 8;
4054 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4055 SIVAL(pdata, 0, file_flags); /* flags */
4056 SIVAL(pdata, 4, flags_mask); /* mask */
4057 pdata += 8;
4059 return pdata;
4062 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4063 const struct stream_struct *streams,
4064 char *data,
4065 unsigned int max_data_bytes,
4066 unsigned int *data_size)
4068 unsigned int i;
4069 unsigned int ofs = 0;
4071 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4072 unsigned int next_offset;
4073 size_t namelen;
4074 smb_ucs2_t *namebuf;
4076 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4077 streams[i].name, &namelen) ||
4078 namelen <= 2)
4080 return NT_STATUS_INVALID_PARAMETER;
4084 * name_buf is now null-terminated, we need to marshall as not
4085 * terminated
4088 namelen -= 2;
4090 SIVAL(data, ofs+4, namelen);
4091 SOFF_T(data, ofs+8, streams[i].size);
4092 SOFF_T(data, ofs+16, streams[i].alloc_size);
4093 memcpy(data+ofs+24, namebuf, namelen);
4094 TALLOC_FREE(namebuf);
4096 next_offset = ofs + 24 + namelen;
4098 if (i == num_streams-1) {
4099 SIVAL(data, ofs, 0);
4101 else {
4102 unsigned int align = ndr_align_size(next_offset, 8);
4104 memset(data+next_offset, 0, align);
4105 next_offset += align;
4107 SIVAL(data, ofs, next_offset - ofs);
4108 ofs = next_offset;
4111 ofs = next_offset;
4114 *data_size = ofs;
4116 return NT_STATUS_OK;
4119 /****************************************************************************
4120 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4121 ****************************************************************************/
4123 static void call_trans2qpipeinfo(connection_struct *conn,
4124 struct smb_request *req,
4125 unsigned int tran_call,
4126 char **pparams, int total_params,
4127 char **ppdata, int total_data,
4128 unsigned int max_data_bytes)
4130 char *params = *pparams;
4131 char *pdata = *ppdata;
4132 unsigned int data_size = 0;
4133 unsigned int param_size = 2;
4134 uint16 info_level;
4135 files_struct *fsp;
4137 if (!params) {
4138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 return;
4142 if (total_params < 4) {
4143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4144 return;
4147 fsp = file_fsp(req, SVAL(params,0));
4148 if (!fsp_is_np(fsp)) {
4149 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4150 return;
4153 info_level = SVAL(params,2);
4155 *pparams = (char *)SMB_REALLOC(*pparams,2);
4156 if (*pparams == NULL) {
4157 reply_nterror(req, NT_STATUS_NO_MEMORY);
4158 return;
4160 params = *pparams;
4161 SSVAL(params,0,0);
4162 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4163 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4164 if (*ppdata == NULL ) {
4165 reply_nterror(req, NT_STATUS_NO_MEMORY);
4166 return;
4168 pdata = *ppdata;
4170 switch (info_level) {
4171 case SMB_FILE_STANDARD_INFORMATION:
4172 memset(pdata,0,24);
4173 SOFF_T(pdata,0,4096LL);
4174 SIVAL(pdata,16,1);
4175 SIVAL(pdata,20,1);
4176 data_size = 24;
4177 break;
4179 default:
4180 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4181 return;
4184 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4185 max_data_bytes);
4187 return;
4190 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4191 TALLOC_CTX *mem_ctx,
4192 uint16_t info_level,
4193 files_struct *fsp,
4194 struct smb_filename *smb_fname,
4195 bool delete_pending,
4196 struct timespec write_time_ts,
4197 struct ea_list *ea_list,
4198 int lock_data_count,
4199 char *lock_data,
4200 uint16_t flags2,
4201 unsigned int max_data_bytes,
4202 char **ppdata,
4203 unsigned int *pdata_size)
4205 char *pdata = *ppdata;
4206 char *dstart, *dend;
4207 unsigned int data_size;
4208 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4209 time_t create_time, mtime, atime, c_time;
4210 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4211 char *p;
4212 char *base_name;
4213 char *dos_fname;
4214 int mode;
4215 int nlink;
4216 NTSTATUS status;
4217 uint64_t file_size = 0;
4218 uint64_t pos = 0;
4219 uint64_t allocation_size = 0;
4220 uint64_t file_index = 0;
4221 uint32_t access_mask = 0;
4223 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4224 return NT_STATUS_INVALID_LEVEL;
4227 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4228 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4229 info_level, max_data_bytes));
4231 mode = dos_mode(conn, smb_fname);
4232 nlink = psbuf->st_ex_nlink;
4234 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4235 nlink = 1;
4238 if ((nlink > 0) && delete_pending) {
4239 nlink -= 1;
4242 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4243 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4244 if (*ppdata == NULL) {
4245 return NT_STATUS_NO_MEMORY;
4247 pdata = *ppdata;
4248 dstart = pdata;
4249 dend = dstart + data_size - 1;
4251 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4252 update_stat_ex_mtime(psbuf, write_time_ts);
4255 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4256 mtime_ts = psbuf->st_ex_mtime;
4257 atime_ts = psbuf->st_ex_atime;
4258 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4260 if (lp_dos_filetime_resolution(SNUM(conn))) {
4261 dos_filetime_timespec(&create_time_ts);
4262 dos_filetime_timespec(&mtime_ts);
4263 dos_filetime_timespec(&atime_ts);
4264 dos_filetime_timespec(&ctime_ts);
4267 create_time = convert_timespec_to_time_t(create_time_ts);
4268 mtime = convert_timespec_to_time_t(mtime_ts);
4269 atime = convert_timespec_to_time_t(atime_ts);
4270 c_time = convert_timespec_to_time_t(ctime_ts);
4272 p = strrchr_m(smb_fname->base_name,'/');
4273 if (!p)
4274 base_name = smb_fname->base_name;
4275 else
4276 base_name = p+1;
4278 /* NT expects the name to be in an exact form of the *full*
4279 filename. See the trans2 torture test */
4280 if (ISDOT(base_name)) {
4281 dos_fname = talloc_strdup(mem_ctx, "\\");
4282 if (!dos_fname) {
4283 return NT_STATUS_NO_MEMORY;
4285 } else {
4286 dos_fname = talloc_asprintf(mem_ctx,
4287 "\\%s",
4288 smb_fname->base_name);
4289 if (!dos_fname) {
4290 return NT_STATUS_NO_MEMORY;
4292 if (is_ntfs_stream_smb_fname(smb_fname)) {
4293 dos_fname = talloc_asprintf(dos_fname, "%s",
4294 smb_fname->stream_name);
4295 if (!dos_fname) {
4296 return NT_STATUS_NO_MEMORY;
4300 string_replace(dos_fname, '/', '\\');
4303 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4305 if (!fsp) {
4306 /* Do we have this path open ? */
4307 files_struct *fsp1;
4308 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4309 fsp1 = file_find_di_first(conn->sconn, fileid);
4310 if (fsp1 && fsp1->initial_allocation_size) {
4311 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4315 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4316 file_size = get_file_size_stat(psbuf);
4319 if (fsp) {
4320 pos = fsp->fh->position_information;
4323 if (fsp) {
4324 access_mask = fsp->access_mask;
4325 } else {
4326 /* GENERIC_EXECUTE mapping from Windows */
4327 access_mask = 0x12019F;
4330 /* This should be an index number - looks like
4331 dev/ino to me :-)
4333 I think this causes us to fail the IFSKIT
4334 BasicFileInformationTest. -tpot */
4335 file_index = get_FileIndex(conn, psbuf);
4337 switch (info_level) {
4338 case SMB_INFO_STANDARD:
4339 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4340 data_size = 22;
4341 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4342 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4343 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4344 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4345 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4346 SSVAL(pdata,l1_attrFile,mode);
4347 break;
4349 case SMB_INFO_QUERY_EA_SIZE:
4351 unsigned int ea_size =
4352 estimate_ea_size(conn, fsp,
4353 smb_fname->base_name);
4354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4355 data_size = 26;
4356 srv_put_dos_date2(pdata,0,create_time);
4357 srv_put_dos_date2(pdata,4,atime);
4358 srv_put_dos_date2(pdata,8,mtime); /* write time */
4359 SIVAL(pdata,12,(uint32)file_size);
4360 SIVAL(pdata,16,(uint32)allocation_size);
4361 SSVAL(pdata,20,mode);
4362 SIVAL(pdata,22,ea_size);
4363 break;
4366 case SMB_INFO_IS_NAME_VALID:
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4368 if (fsp) {
4369 /* os/2 needs this ? really ?*/
4370 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4372 /* This is only reached for qpathinfo */
4373 data_size = 0;
4374 break;
4376 case SMB_INFO_QUERY_EAS_FROM_LIST:
4378 size_t total_ea_len = 0;
4379 struct ea_list *ea_file_list = NULL;
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4383 ea_file_list =
4384 get_ea_list_from_file(mem_ctx, conn, fsp,
4385 smb_fname->base_name,
4386 &total_ea_len);
4387 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4389 if (!ea_list || (total_ea_len > data_size)) {
4390 data_size = 4;
4391 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4392 break;
4395 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4396 break;
4399 case SMB_INFO_QUERY_ALL_EAS:
4401 /* We have data_size bytes to put EA's into. */
4402 size_t total_ea_len = 0;
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4406 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4407 smb_fname->base_name,
4408 &total_ea_len);
4409 if (!ea_list || (total_ea_len > data_size)) {
4410 data_size = 4;
4411 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4412 break;
4415 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4416 break;
4419 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4421 /* This is FileFullEaInformation - 0xF which maps to
4422 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4424 /* We have data_size bytes to put EA's into. */
4425 size_t total_ea_len = 0;
4426 struct ea_list *ea_file_list = NULL;
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4430 /*TODO: add filtering and index handling */
4432 ea_file_list =
4433 get_ea_list_from_file(mem_ctx, conn, fsp,
4434 smb_fname->base_name,
4435 &total_ea_len);
4436 if (!ea_file_list) {
4437 return NT_STATUS_NO_EAS_ON_FILE;
4440 status = fill_ea_chained_buffer(mem_ctx,
4441 pdata,
4442 data_size,
4443 &data_size,
4444 conn, ea_file_list);
4445 if (!NT_STATUS_IS_OK(status)) {
4446 return status;
4448 break;
4451 case SMB_FILE_BASIC_INFORMATION:
4452 case SMB_QUERY_FILE_BASIC_INFO:
4454 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4456 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4457 } else {
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4459 data_size = 40;
4460 SIVAL(pdata,36,0);
4462 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4463 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4464 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4465 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4466 SIVAL(pdata,32,mode);
4468 DEBUG(5,("SMB_QFBI - "));
4469 DEBUG(5,("create: %s ", ctime(&create_time)));
4470 DEBUG(5,("access: %s ", ctime(&atime)));
4471 DEBUG(5,("write: %s ", ctime(&mtime)));
4472 DEBUG(5,("change: %s ", ctime(&c_time)));
4473 DEBUG(5,("mode: %x\n", mode));
4474 break;
4476 case SMB_FILE_STANDARD_INFORMATION:
4477 case SMB_QUERY_FILE_STANDARD_INFO:
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4480 data_size = 24;
4481 SOFF_T(pdata,0,allocation_size);
4482 SOFF_T(pdata,8,file_size);
4483 SIVAL(pdata,16,nlink);
4484 SCVAL(pdata,20,delete_pending?1:0);
4485 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4486 SSVAL(pdata,22,0); /* Padding. */
4487 break;
4489 case SMB_FILE_EA_INFORMATION:
4490 case SMB_QUERY_FILE_EA_INFO:
4492 unsigned int ea_size =
4493 estimate_ea_size(conn, fsp, smb_fname->base_name);
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4495 data_size = 4;
4496 SIVAL(pdata,0,ea_size);
4497 break;
4500 /* Get the 8.3 name - used if NT SMB was negotiated. */
4501 case SMB_QUERY_FILE_ALT_NAME_INFO:
4502 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4504 int len;
4505 char mangled_name[13];
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4507 if (!name_to_8_3(base_name,mangled_name,
4508 True,conn->params)) {
4509 return NT_STATUS_NO_MEMORY;
4511 len = srvstr_push(dstart, flags2,
4512 pdata+4, mangled_name,
4513 PTR_DIFF(dend, pdata+4),
4514 STR_UNICODE);
4515 data_size = 4 + len;
4516 SIVAL(pdata,0,len);
4517 break;
4520 case SMB_QUERY_FILE_NAME_INFO:
4522 int len;
4524 this must be *exactly* right for ACLs on mapped drives to work
4526 len = srvstr_push(dstart, flags2,
4527 pdata+4, dos_fname,
4528 PTR_DIFF(dend, pdata+4),
4529 STR_UNICODE);
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4531 data_size = 4 + len;
4532 SIVAL(pdata,0,len);
4533 break;
4536 case SMB_FILE_ALLOCATION_INFORMATION:
4537 case SMB_QUERY_FILE_ALLOCATION_INFO:
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4539 data_size = 8;
4540 SOFF_T(pdata,0,allocation_size);
4541 break;
4543 case SMB_FILE_END_OF_FILE_INFORMATION:
4544 case SMB_QUERY_FILE_END_OF_FILEINFO:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4546 data_size = 8;
4547 SOFF_T(pdata,0,file_size);
4548 break;
4550 case SMB_QUERY_FILE_ALL_INFO:
4551 case SMB_FILE_ALL_INFORMATION:
4553 int len;
4554 unsigned int ea_size =
4555 estimate_ea_size(conn, fsp, smb_fname->base_name);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4557 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4558 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4559 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4560 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4561 SIVAL(pdata,32,mode);
4562 SIVAL(pdata,36,0); /* padding. */
4563 pdata += 40;
4564 SOFF_T(pdata,0,allocation_size);
4565 SOFF_T(pdata,8,file_size);
4566 SIVAL(pdata,16,nlink);
4567 SCVAL(pdata,20,delete_pending);
4568 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4569 SSVAL(pdata,22,0);
4570 pdata += 24;
4571 SIVAL(pdata,0,ea_size);
4572 pdata += 4; /* EA info */
4573 len = srvstr_push(dstart, flags2,
4574 pdata+4, dos_fname,
4575 PTR_DIFF(dend, pdata+4),
4576 STR_UNICODE);
4577 SIVAL(pdata,0,len);
4578 pdata += 4 + len;
4579 data_size = PTR_DIFF(pdata,(*ppdata));
4580 break;
4583 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4585 int len;
4586 unsigned int ea_size =
4587 estimate_ea_size(conn, fsp, smb_fname->base_name);
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4589 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4590 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4591 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4592 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4593 SIVAL(pdata, 0x20, mode);
4594 SIVAL(pdata, 0x24, 0); /* padding. */
4595 SBVAL(pdata, 0x28, allocation_size);
4596 SBVAL(pdata, 0x30, file_size);
4597 SIVAL(pdata, 0x38, nlink);
4598 SCVAL(pdata, 0x3C, delete_pending);
4599 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4600 SSVAL(pdata, 0x3E, 0); /* padding */
4601 SBVAL(pdata, 0x40, file_index);
4602 SIVAL(pdata, 0x48, ea_size);
4603 SIVAL(pdata, 0x4C, access_mask);
4604 SBVAL(pdata, 0x50, pos);
4605 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4606 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4608 pdata += 0x60;
4610 len = srvstr_push(dstart, flags2,
4611 pdata+4, dos_fname,
4612 PTR_DIFF(dend, pdata+4),
4613 STR_UNICODE);
4614 SIVAL(pdata,0,len);
4615 pdata += 4 + len;
4616 data_size = PTR_DIFF(pdata,(*ppdata));
4617 break;
4619 case SMB_FILE_INTERNAL_INFORMATION:
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4622 SBVAL(pdata, 0, file_index);
4623 data_size = 8;
4624 break;
4626 case SMB_FILE_ACCESS_INFORMATION:
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4628 SIVAL(pdata, 0, access_mask);
4629 data_size = 4;
4630 break;
4632 case SMB_FILE_NAME_INFORMATION:
4633 /* Pathname with leading '\'. */
4635 size_t byte_len;
4636 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4638 SIVAL(pdata,0,byte_len);
4639 data_size = 4 + byte_len;
4640 break;
4643 case SMB_FILE_DISPOSITION_INFORMATION:
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4645 data_size = 1;
4646 SCVAL(pdata,0,delete_pending);
4647 break;
4649 case SMB_FILE_POSITION_INFORMATION:
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4651 data_size = 8;
4652 SOFF_T(pdata,0,pos);
4653 break;
4655 case SMB_FILE_MODE_INFORMATION:
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4657 SIVAL(pdata,0,mode);
4658 data_size = 4;
4659 break;
4661 case SMB_FILE_ALIGNMENT_INFORMATION:
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4663 SIVAL(pdata,0,0); /* No alignment needed. */
4664 data_size = 4;
4665 break;
4668 * NT4 server just returns "invalid query" to this - if we try
4669 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4670 * want this. JRA.
4672 /* The first statement above is false - verified using Thursby
4673 * client against NT4 -- gcolley.
4675 case SMB_QUERY_FILE_STREAM_INFO:
4676 case SMB_FILE_STREAM_INFORMATION: {
4677 unsigned int num_streams = 0;
4678 struct stream_struct *streams = NULL;
4680 DEBUG(10,("smbd_do_qfilepathinfo: "
4681 "SMB_FILE_STREAM_INFORMATION\n"));
4683 if (is_ntfs_stream_smb_fname(smb_fname)) {
4684 return NT_STATUS_INVALID_PARAMETER;
4687 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4688 talloc_tos(), &num_streams, &streams);
4690 if (!NT_STATUS_IS_OK(status)) {
4691 DEBUG(10, ("could not get stream info: %s\n",
4692 nt_errstr(status)));
4693 return status;
4696 status = marshall_stream_info(num_streams, streams,
4697 pdata, max_data_bytes,
4698 &data_size);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 DEBUG(10, ("marshall_stream_info failed: %s\n",
4702 nt_errstr(status)));
4703 return status;
4706 TALLOC_FREE(streams);
4708 break;
4710 case SMB_QUERY_COMPRESSION_INFO:
4711 case SMB_FILE_COMPRESSION_INFORMATION:
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4713 SOFF_T(pdata,0,file_size);
4714 SIVAL(pdata,8,0); /* ??? */
4715 SIVAL(pdata,12,0); /* ??? */
4716 data_size = 16;
4717 break;
4719 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4721 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4722 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4723 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4724 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4725 SOFF_T(pdata,32,allocation_size);
4726 SOFF_T(pdata,40,file_size);
4727 SIVAL(pdata,48,mode);
4728 SIVAL(pdata,52,0); /* ??? */
4729 data_size = 56;
4730 break;
4732 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4734 SIVAL(pdata,0,mode);
4735 SIVAL(pdata,4,0);
4736 data_size = 8;
4737 break;
4740 * CIFS UNIX Extensions.
4743 case SMB_QUERY_FILE_UNIX_BASIC:
4745 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4746 data_size = PTR_DIFF(pdata,(*ppdata));
4748 DEBUG(4,("smbd_do_qfilepathinfo: "
4749 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4750 dump_data(4, (uint8_t *)(*ppdata), data_size);
4752 break;
4754 case SMB_QUERY_FILE_UNIX_INFO2:
4756 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4757 data_size = PTR_DIFF(pdata,(*ppdata));
4760 int i;
4761 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4763 for (i=0; i<100; i++)
4764 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4765 DEBUG(4,("\n"));
4768 break;
4770 case SMB_QUERY_FILE_UNIX_LINK:
4772 int len;
4773 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4775 if (!buffer) {
4776 return NT_STATUS_NO_MEMORY;
4779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4780 #ifdef S_ISLNK
4781 if(!S_ISLNK(psbuf->st_ex_mode)) {
4782 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4784 #else
4785 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4786 #endif
4787 len = SMB_VFS_READLINK(conn,
4788 smb_fname->base_name,
4789 buffer, PATH_MAX);
4790 if (len == -1) {
4791 return map_nt_error_from_unix(errno);
4793 buffer[len] = 0;
4794 len = srvstr_push(dstart, flags2,
4795 pdata, buffer,
4796 PTR_DIFF(dend, pdata),
4797 STR_TERMINATE);
4798 pdata += len;
4799 data_size = PTR_DIFF(pdata,(*ppdata));
4801 break;
4804 #if defined(HAVE_POSIX_ACLS)
4805 case SMB_QUERY_POSIX_ACL:
4807 SMB_ACL_T file_acl = NULL;
4808 SMB_ACL_T def_acl = NULL;
4809 uint16 num_file_acls = 0;
4810 uint16 num_def_acls = 0;
4812 if (fsp && fsp->fh->fd != -1) {
4813 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4814 } else {
4815 file_acl =
4816 SMB_VFS_SYS_ACL_GET_FILE(conn,
4817 smb_fname->base_name,
4818 SMB_ACL_TYPE_ACCESS);
4821 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4822 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4823 "not implemented on "
4824 "filesystem containing %s\n",
4825 smb_fname->base_name));
4826 return NT_STATUS_NOT_IMPLEMENTED;
4829 if (S_ISDIR(psbuf->st_ex_mode)) {
4830 if (fsp && fsp->is_directory) {
4831 def_acl =
4832 SMB_VFS_SYS_ACL_GET_FILE(
4833 conn,
4834 fsp->fsp_name->base_name,
4835 SMB_ACL_TYPE_DEFAULT);
4836 } else {
4837 def_acl =
4838 SMB_VFS_SYS_ACL_GET_FILE(
4839 conn,
4840 smb_fname->base_name,
4841 SMB_ACL_TYPE_DEFAULT);
4843 def_acl = free_empty_sys_acl(conn, def_acl);
4846 num_file_acls = count_acl_entries(conn, file_acl);
4847 num_def_acls = count_acl_entries(conn, def_acl);
4849 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4850 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4851 data_size,
4852 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4853 SMB_POSIX_ACL_HEADER_SIZE) ));
4854 if (file_acl) {
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4857 if (def_acl) {
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4860 return NT_STATUS_BUFFER_TOO_SMALL;
4863 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4864 SSVAL(pdata,2,num_file_acls);
4865 SSVAL(pdata,4,num_def_acls);
4866 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4867 if (file_acl) {
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4870 if (def_acl) {
4871 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4873 return NT_STATUS_INTERNAL_ERROR;
4875 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4876 if (file_acl) {
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4879 if (def_acl) {
4880 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4882 return NT_STATUS_INTERNAL_ERROR;
4885 if (file_acl) {
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4888 if (def_acl) {
4889 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4891 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4892 break;
4894 #endif
4897 case SMB_QUERY_POSIX_LOCK:
4899 uint64_t count;
4900 uint64_t offset;
4901 uint64_t smblctx;
4902 enum brl_type lock_type;
4904 /* We need an open file with a real fd for this. */
4905 if (!fsp || fsp->fh->fd == -1) {
4906 return NT_STATUS_INVALID_LEVEL;
4909 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4910 return NT_STATUS_INVALID_PARAMETER;
4913 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4914 case POSIX_LOCK_TYPE_READ:
4915 lock_type = READ_LOCK;
4916 break;
4917 case POSIX_LOCK_TYPE_WRITE:
4918 lock_type = WRITE_LOCK;
4919 break;
4920 case POSIX_LOCK_TYPE_UNLOCK:
4921 default:
4922 /* There's no point in asking for an unlock... */
4923 return NT_STATUS_INVALID_PARAMETER;
4926 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4927 #if defined(HAVE_LONGLONG)
4928 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4929 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4930 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4931 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4932 #else /* HAVE_LONGLONG */
4933 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4934 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4935 #endif /* HAVE_LONGLONG */
4937 status = query_lock(fsp,
4938 &smblctx,
4939 &count,
4940 &offset,
4941 &lock_type,
4942 POSIX_LOCK);
4944 if (ERROR_WAS_LOCK_DENIED(status)) {
4945 /* Here we need to report who has it locked... */
4946 data_size = POSIX_LOCK_DATA_SIZE;
4948 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4949 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4950 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4951 #if defined(HAVE_LONGLONG)
4952 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4953 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4954 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4955 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4956 #else /* HAVE_LONGLONG */
4957 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4958 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4959 #endif /* HAVE_LONGLONG */
4961 } else if (NT_STATUS_IS_OK(status)) {
4962 /* For success we just return a copy of what we sent
4963 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4964 data_size = POSIX_LOCK_DATA_SIZE;
4965 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4966 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4967 } else {
4968 return status;
4970 break;
4973 default:
4974 return NT_STATUS_INVALID_LEVEL;
4977 *pdata_size = data_size;
4978 return NT_STATUS_OK;
4981 /****************************************************************************
4982 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4983 file name or file id).
4984 ****************************************************************************/
4986 static void call_trans2qfilepathinfo(connection_struct *conn,
4987 struct smb_request *req,
4988 unsigned int tran_call,
4989 char **pparams, int total_params,
4990 char **ppdata, int total_data,
4991 unsigned int max_data_bytes)
4993 char *params = *pparams;
4994 char *pdata = *ppdata;
4995 uint16 info_level;
4996 unsigned int data_size = 0;
4997 unsigned int param_size = 2;
4998 struct smb_filename *smb_fname = NULL;
4999 bool delete_pending = False;
5000 struct timespec write_time_ts;
5001 files_struct *fsp = NULL;
5002 struct file_id fileid;
5003 struct ea_list *ea_list = NULL;
5004 int lock_data_count = 0;
5005 char *lock_data = NULL;
5006 NTSTATUS status = NT_STATUS_OK;
5008 if (!params) {
5009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5010 return;
5013 ZERO_STRUCT(write_time_ts);
5015 if (tran_call == TRANSACT2_QFILEINFO) {
5016 if (total_params < 4) {
5017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5018 return;
5021 if (IS_IPC(conn)) {
5022 call_trans2qpipeinfo(conn, req, tran_call,
5023 pparams, total_params,
5024 ppdata, total_data,
5025 max_data_bytes);
5026 return;
5029 fsp = file_fsp(req, SVAL(params,0));
5030 info_level = SVAL(params,2);
5032 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5034 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5035 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5036 return;
5039 /* Initial check for valid fsp ptr. */
5040 if (!check_fsp_open(conn, req, fsp)) {
5041 return;
5044 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5045 &smb_fname);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 reply_nterror(req, status);
5048 return;
5051 if(fsp->fake_file_handle) {
5053 * This is actually for the QUOTA_FAKE_FILE --metze
5056 /* We know this name is ok, it's already passed the checks. */
5058 } else if(fsp->fh->fd == -1) {
5060 * This is actually a QFILEINFO on a directory
5061 * handle (returned from an NT SMB). NT5.0 seems
5062 * to do this call. JRA.
5065 if (INFO_LEVEL_IS_UNIX(info_level)) {
5066 /* Always do lstat for UNIX calls. */
5067 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5068 DEBUG(3,("call_trans2qfilepathinfo: "
5069 "SMB_VFS_LSTAT of %s failed "
5070 "(%s)\n",
5071 smb_fname_str_dbg(smb_fname),
5072 strerror(errno)));
5073 reply_nterror(req,
5074 map_nt_error_from_unix(errno));
5075 return;
5077 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5078 DEBUG(3,("call_trans2qfilepathinfo: "
5079 "SMB_VFS_STAT of %s failed (%s)\n",
5080 smb_fname_str_dbg(smb_fname),
5081 strerror(errno)));
5082 reply_nterror(req,
5083 map_nt_error_from_unix(errno));
5084 return;
5087 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5088 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5089 } else {
5091 * Original code - this is an open file.
5093 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5094 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5095 fsp->fnum, strerror(errno)));
5096 reply_nterror(req,
5097 map_nt_error_from_unix(errno));
5098 return;
5100 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5101 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5104 } else {
5105 uint32_t name_hash;
5106 char *fname = NULL;
5107 uint32_t ucf_flags = 0;
5109 /* qpathinfo */
5110 if (total_params < 7) {
5111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5112 return;
5115 info_level = SVAL(params,0);
5117 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5119 if (INFO_LEVEL_IS_UNIX(info_level)) {
5120 if (!lp_unix_extensions()) {
5121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5122 return;
5124 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5125 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5126 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5127 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5131 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5132 total_params - 6,
5133 STR_TERMINATE, &status);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 reply_nterror(req, status);
5136 return;
5139 status = filename_convert(req,
5140 conn,
5141 req->flags2 & FLAGS2_DFS_PATHNAMES,
5142 fname,
5143 ucf_flags,
5144 NULL,
5145 &smb_fname);
5146 if (!NT_STATUS_IS_OK(status)) {
5147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5148 reply_botherror(req,
5149 NT_STATUS_PATH_NOT_COVERED,
5150 ERRSRV, ERRbadpath);
5151 return;
5153 reply_nterror(req, status);
5154 return;
5157 /* If this is a stream, check if there is a delete_pending. */
5158 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5159 && is_ntfs_stream_smb_fname(smb_fname)) {
5160 struct smb_filename *smb_fname_base = NULL;
5162 /* Create an smb_filename with stream_name == NULL. */
5163 status =
5164 create_synthetic_smb_fname(talloc_tos(),
5165 smb_fname->base_name,
5166 NULL, NULL,
5167 &smb_fname_base);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 reply_nterror(req, status);
5170 return;
5173 if (INFO_LEVEL_IS_UNIX(info_level)) {
5174 /* Always do lstat for UNIX calls. */
5175 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5176 DEBUG(3,("call_trans2qfilepathinfo: "
5177 "SMB_VFS_LSTAT of %s failed "
5178 "(%s)\n",
5179 smb_fname_str_dbg(smb_fname_base),
5180 strerror(errno)));
5181 TALLOC_FREE(smb_fname_base);
5182 reply_nterror(req,
5183 map_nt_error_from_unix(errno));
5184 return;
5186 } else {
5187 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "fileinfo of %s failed "
5190 "(%s)\n",
5191 smb_fname_str_dbg(smb_fname_base),
5192 strerror(errno)));
5193 TALLOC_FREE(smb_fname_base);
5194 reply_nterror(req,
5195 map_nt_error_from_unix(errno));
5196 return;
5200 status = file_name_hash(conn,
5201 smb_fname_str_dbg(smb_fname_base),
5202 &name_hash);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 TALLOC_FREE(smb_fname_base);
5205 reply_nterror(req, status);
5206 return;
5209 fileid = vfs_file_id_from_sbuf(conn,
5210 &smb_fname_base->st);
5211 TALLOC_FREE(smb_fname_base);
5212 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5213 if (delete_pending) {
5214 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5215 return;
5219 if (INFO_LEVEL_IS_UNIX(info_level)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname),
5225 strerror(errno)));
5226 reply_nterror(req,
5227 map_nt_error_from_unix(errno));
5228 return;
5231 } else {
5232 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname),
5236 strerror(errno)));
5237 reply_nterror(req,
5238 map_nt_error_from_unix(errno));
5239 return;
5243 status = file_name_hash(conn,
5244 smb_fname_str_dbg(smb_fname),
5245 &name_hash);
5246 if (!NT_STATUS_IS_OK(status)) {
5247 reply_nterror(req, status);
5248 return;
5251 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5252 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5253 if (delete_pending) {
5254 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5255 return;
5259 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5260 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5261 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5263 /* Pull out any data sent here before we realloc. */
5264 switch (info_level) {
5265 case SMB_INFO_QUERY_EAS_FROM_LIST:
5267 /* Pull any EA list from the data portion. */
5268 uint32 ea_size;
5270 if (total_data < 4) {
5271 reply_nterror(
5272 req, NT_STATUS_INVALID_PARAMETER);
5273 return;
5275 ea_size = IVAL(pdata,0);
5277 if (total_data > 0 && ea_size != total_data) {
5278 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5279 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5280 reply_nterror(
5281 req, NT_STATUS_INVALID_PARAMETER);
5282 return;
5285 if (!lp_ea_support(SNUM(conn))) {
5286 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5287 return;
5290 /* Pull out the list of names. */
5291 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5292 if (!ea_list) {
5293 reply_nterror(
5294 req, NT_STATUS_INVALID_PARAMETER);
5295 return;
5297 break;
5300 case SMB_QUERY_POSIX_LOCK:
5302 if (fsp == NULL || fsp->fh->fd == -1) {
5303 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5304 return;
5307 if (total_data != POSIX_LOCK_DATA_SIZE) {
5308 reply_nterror(
5309 req, NT_STATUS_INVALID_PARAMETER);
5310 return;
5313 /* Copy the lock range data. */
5314 lock_data = (char *)talloc_memdup(
5315 req, pdata, total_data);
5316 if (!lock_data) {
5317 reply_nterror(req, NT_STATUS_NO_MEMORY);
5318 return;
5320 lock_data_count = total_data;
5322 default:
5323 break;
5326 *pparams = (char *)SMB_REALLOC(*pparams,2);
5327 if (*pparams == NULL) {
5328 reply_nterror(req, NT_STATUS_NO_MEMORY);
5329 return;
5331 params = *pparams;
5332 SSVAL(params,0,0);
5335 * draft-leach-cifs-v1-spec-02.txt
5336 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5337 * says:
5339 * The requested information is placed in the Data portion of the
5340 * transaction response. For the information levels greater than 0x100,
5341 * the transaction response has 1 parameter word which should be
5342 * ignored by the client.
5344 * However Windows only follows this rule for the IS_NAME_VALID call.
5346 switch (info_level) {
5347 case SMB_INFO_IS_NAME_VALID:
5348 param_size = 0;
5349 break;
5352 if ((info_level & 0xFF00) == 0xFF00) {
5354 * We use levels that start with 0xFF00
5355 * internally to represent SMB2 specific levels
5357 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5358 return;
5361 status = smbd_do_qfilepathinfo(conn, req, info_level,
5362 fsp, smb_fname,
5363 delete_pending, write_time_ts,
5364 ea_list,
5365 lock_data_count, lock_data,
5366 req->flags2, max_data_bytes,
5367 ppdata, &data_size);
5368 if (!NT_STATUS_IS_OK(status)) {
5369 reply_nterror(req, status);
5370 return;
5373 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5374 max_data_bytes);
5376 return;
5379 /****************************************************************************
5380 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5381 code.
5382 ****************************************************************************/
5384 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5385 connection_struct *conn,
5386 struct smb_request *req,
5387 bool overwrite_if_exists,
5388 const struct smb_filename *smb_fname_old,
5389 struct smb_filename *smb_fname_new)
5391 NTSTATUS status = NT_STATUS_OK;
5393 /* source must already exist. */
5394 if (!VALID_STAT(smb_fname_old->st)) {
5395 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5398 if (VALID_STAT(smb_fname_new->st)) {
5399 if (overwrite_if_exists) {
5400 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5401 return NT_STATUS_FILE_IS_A_DIRECTORY;
5403 status = unlink_internals(conn,
5404 req,
5405 FILE_ATTRIBUTE_NORMAL,
5406 smb_fname_new,
5407 false);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 return status;
5411 } else {
5412 /* Disallow if newname already exists. */
5413 return NT_STATUS_OBJECT_NAME_COLLISION;
5417 /* No links from a directory. */
5418 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5419 return NT_STATUS_FILE_IS_A_DIRECTORY;
5422 /* Setting a hardlink to/from a stream isn't currently supported. */
5423 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5424 is_ntfs_stream_smb_fname(smb_fname_new)) {
5425 return NT_STATUS_INVALID_PARAMETER;
5428 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5429 smb_fname_old->base_name, smb_fname_new->base_name));
5431 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5432 smb_fname_new->base_name) != 0) {
5433 status = map_nt_error_from_unix(errno);
5434 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5435 nt_errstr(status), smb_fname_old->base_name,
5436 smb_fname_new->base_name));
5438 return status;
5441 /****************************************************************************
5442 Deal with setting the time from any of the setfilepathinfo functions.
5443 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5444 calling this function.
5445 ****************************************************************************/
5447 NTSTATUS smb_set_file_time(connection_struct *conn,
5448 files_struct *fsp,
5449 const struct smb_filename *smb_fname,
5450 struct smb_file_time *ft,
5451 bool setting_write_time)
5453 struct smb_filename smb_fname_base;
5454 uint32 action =
5455 FILE_NOTIFY_CHANGE_LAST_ACCESS
5456 |FILE_NOTIFY_CHANGE_LAST_WRITE
5457 |FILE_NOTIFY_CHANGE_CREATION;
5459 if (!VALID_STAT(smb_fname->st)) {
5460 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5463 /* get some defaults (no modifications) if any info is zero or -1. */
5464 if (null_timespec(ft->create_time)) {
5465 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5468 if (null_timespec(ft->atime)) {
5469 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5472 if (null_timespec(ft->mtime)) {
5473 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5476 if (!setting_write_time) {
5477 /* ft->mtime comes from change time, not write time. */
5478 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5481 /* Ensure the resolution is the correct for
5482 * what we can store on this filesystem. */
5484 round_timespec(conn->ts_res, &ft->create_time);
5485 round_timespec(conn->ts_res, &ft->ctime);
5486 round_timespec(conn->ts_res, &ft->atime);
5487 round_timespec(conn->ts_res, &ft->mtime);
5489 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5490 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5491 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5492 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5493 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5494 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5495 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5496 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5498 if (setting_write_time) {
5500 * This was a Windows setfileinfo on an open file.
5501 * NT does this a lot. We also need to
5502 * set the time here, as it can be read by
5503 * FindFirst/FindNext and with the patch for bug #2045
5504 * in smbd/fileio.c it ensures that this timestamp is
5505 * kept sticky even after a write. We save the request
5506 * away and will set it on file close and after a write. JRA.
5509 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5510 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5512 if (fsp != NULL) {
5513 if (fsp->base_fsp) {
5514 set_sticky_write_time_fsp(fsp->base_fsp,
5515 ft->mtime);
5516 } else {
5517 set_sticky_write_time_fsp(fsp, ft->mtime);
5519 } else {
5520 set_sticky_write_time_path(
5521 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5522 ft->mtime);
5526 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5528 /* Always call ntimes on the base, even if a stream was passed in. */
5529 smb_fname_base = *smb_fname;
5530 smb_fname_base.stream_name = NULL;
5532 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5533 return map_nt_error_from_unix(errno);
5536 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5537 smb_fname->base_name);
5538 return NT_STATUS_OK;
5541 /****************************************************************************
5542 Deal with setting the dosmode from any of the setfilepathinfo functions.
5543 ****************************************************************************/
5545 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5546 const struct smb_filename *smb_fname,
5547 uint32 dosmode)
5549 struct smb_filename *smb_fname_base = NULL;
5550 NTSTATUS status;
5552 if (!VALID_STAT(smb_fname->st)) {
5553 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5556 /* Always operate on the base_name, even if a stream was passed in. */
5557 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5558 NULL, &smb_fname->st,
5559 &smb_fname_base);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 return status;
5564 if (dosmode) {
5565 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5566 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5567 } else {
5568 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5572 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5574 /* check the mode isn't different, before changing it */
5575 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5576 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5577 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5578 (unsigned int)dosmode));
5580 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5581 false)) {
5582 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5583 "%s failed (%s)\n",
5584 smb_fname_str_dbg(smb_fname_base),
5585 strerror(errno)));
5586 status = map_nt_error_from_unix(errno);
5587 goto out;
5590 status = NT_STATUS_OK;
5591 out:
5592 TALLOC_FREE(smb_fname_base);
5593 return status;
5596 /****************************************************************************
5597 Deal with setting the size from any of the setfilepathinfo functions.
5598 ****************************************************************************/
5600 static NTSTATUS smb_set_file_size(connection_struct *conn,
5601 struct smb_request *req,
5602 files_struct *fsp,
5603 const struct smb_filename *smb_fname,
5604 const SMB_STRUCT_STAT *psbuf,
5605 SMB_OFF_T size,
5606 bool fail_after_createfile)
5608 NTSTATUS status = NT_STATUS_OK;
5609 struct smb_filename *smb_fname_tmp = NULL;
5610 files_struct *new_fsp = NULL;
5612 if (!VALID_STAT(*psbuf)) {
5613 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5616 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5618 if (size == get_file_size_stat(psbuf)) {
5619 return NT_STATUS_OK;
5622 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5623 smb_fname_str_dbg(smb_fname), (double)size));
5625 if (fsp && fsp->fh->fd != -1) {
5626 /* Handle based call. */
5627 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5628 return NT_STATUS_ACCESS_DENIED;
5631 if (vfs_set_filelen(fsp, size) == -1) {
5632 return map_nt_error_from_unix(errno);
5634 trigger_write_time_update_immediate(fsp);
5635 return NT_STATUS_OK;
5638 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 return status;
5643 smb_fname_tmp->st = *psbuf;
5645 status = SMB_VFS_CREATE_FILE(
5646 conn, /* conn */
5647 req, /* req */
5648 0, /* root_dir_fid */
5649 smb_fname_tmp, /* fname */
5650 FILE_WRITE_DATA, /* access_mask */
5651 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5652 FILE_SHARE_DELETE),
5653 FILE_OPEN, /* create_disposition*/
5654 0, /* create_options */
5655 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5656 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5657 0, /* allocation_size */
5658 0, /* private_flags */
5659 NULL, /* sd */
5660 NULL, /* ea_list */
5661 &new_fsp, /* result */
5662 NULL); /* pinfo */
5664 TALLOC_FREE(smb_fname_tmp);
5666 if (!NT_STATUS_IS_OK(status)) {
5667 /* NB. We check for open_was_deferred in the caller. */
5668 return status;
5671 /* See RAW-SFILEINFO-END-OF-FILE */
5672 if (fail_after_createfile) {
5673 close_file(req, new_fsp,NORMAL_CLOSE);
5674 return NT_STATUS_INVALID_LEVEL;
5677 if (vfs_set_filelen(new_fsp, size) == -1) {
5678 status = map_nt_error_from_unix(errno);
5679 close_file(req, new_fsp,NORMAL_CLOSE);
5680 return status;
5683 trigger_write_time_update_immediate(new_fsp);
5684 close_file(req, new_fsp,NORMAL_CLOSE);
5685 return NT_STATUS_OK;
5688 /****************************************************************************
5689 Deal with SMB_INFO_SET_EA.
5690 ****************************************************************************/
5692 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5693 const char *pdata,
5694 int total_data,
5695 files_struct *fsp,
5696 const struct smb_filename *smb_fname)
5698 struct ea_list *ea_list = NULL;
5699 TALLOC_CTX *ctx = NULL;
5700 NTSTATUS status = NT_STATUS_OK;
5702 if (total_data < 10) {
5704 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5705 length. They seem to have no effect. Bug #3212. JRA */
5707 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5708 /* We're done. We only get EA info in this call. */
5709 return NT_STATUS_OK;
5712 return NT_STATUS_INVALID_PARAMETER;
5715 if (IVAL(pdata,0) > total_data) {
5716 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5717 IVAL(pdata,0), (unsigned int)total_data));
5718 return NT_STATUS_INVALID_PARAMETER;
5721 ctx = talloc_tos();
5722 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5723 if (!ea_list) {
5724 return NT_STATUS_INVALID_PARAMETER;
5727 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5728 return NT_STATUS_ACCESS_DENIED;
5731 status = set_ea(conn, fsp, smb_fname, ea_list);
5733 return status;
5736 /****************************************************************************
5737 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5738 ****************************************************************************/
5740 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5741 const char *pdata,
5742 int total_data,
5743 files_struct *fsp)
5745 struct ea_list *ea_list = NULL;
5746 NTSTATUS status;
5748 if (!fsp) {
5749 return NT_STATUS_INVALID_HANDLE;
5752 if (!lp_ea_support(SNUM(conn))) {
5753 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5754 "EA's not supported.\n",
5755 (unsigned int)total_data));
5756 return NT_STATUS_EAS_NOT_SUPPORTED;
5759 if (total_data < 10) {
5760 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5761 "too small.\n",
5762 (unsigned int)total_data));
5763 return NT_STATUS_INVALID_PARAMETER;
5766 ea_list = read_nttrans_ea_list(talloc_tos(),
5767 pdata,
5768 total_data);
5770 if (!ea_list) {
5771 return NT_STATUS_INVALID_PARAMETER;
5774 if (!(fsp->access_mask & FILE_WRITE_EA)) {
5775 return NT_STATUS_ACCESS_DENIED;
5778 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5780 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5781 smb_fname_str_dbg(fsp->fsp_name),
5782 nt_errstr(status) ));
5784 return status;
5788 /****************************************************************************
5789 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5790 ****************************************************************************/
5792 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5793 const char *pdata,
5794 int total_data,
5795 files_struct *fsp,
5796 struct smb_filename *smb_fname)
5798 NTSTATUS status = NT_STATUS_OK;
5799 bool delete_on_close;
5800 uint32 dosmode = 0;
5802 if (total_data < 1) {
5803 return NT_STATUS_INVALID_PARAMETER;
5806 if (fsp == NULL) {
5807 return NT_STATUS_INVALID_HANDLE;
5810 delete_on_close = (CVAL(pdata,0) ? True : False);
5811 dosmode = dos_mode(conn, smb_fname);
5813 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5814 "delete_on_close = %u\n",
5815 smb_fname_str_dbg(smb_fname),
5816 (unsigned int)dosmode,
5817 (unsigned int)delete_on_close ));
5819 if (delete_on_close) {
5820 status = can_set_delete_on_close(fsp, dosmode);
5821 if (!NT_STATUS_IS_OK(status)) {
5822 return status;
5826 /* The set is across all open files on this dev/inode pair. */
5827 if (!set_delete_on_close(fsp, delete_on_close,
5828 conn->session_info->unix_token)) {
5829 return NT_STATUS_ACCESS_DENIED;
5831 return NT_STATUS_OK;
5834 /****************************************************************************
5835 Deal with SMB_FILE_POSITION_INFORMATION.
5836 ****************************************************************************/
5838 static NTSTATUS smb_file_position_information(connection_struct *conn,
5839 const char *pdata,
5840 int total_data,
5841 files_struct *fsp)
5843 uint64_t position_information;
5845 if (total_data < 8) {
5846 return NT_STATUS_INVALID_PARAMETER;
5849 if (fsp == NULL) {
5850 /* Ignore on pathname based set. */
5851 return NT_STATUS_OK;
5854 position_information = (uint64_t)IVAL(pdata,0);
5855 #ifdef LARGE_SMB_OFF_T
5856 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5857 #else /* LARGE_SMB_OFF_T */
5858 if (IVAL(pdata,4) != 0) {
5859 /* more than 32 bits? */
5860 return NT_STATUS_INVALID_PARAMETER;
5862 #endif /* LARGE_SMB_OFF_T */
5864 DEBUG(10,("smb_file_position_information: Set file position "
5865 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5866 (double)position_information));
5867 fsp->fh->position_information = position_information;
5868 return NT_STATUS_OK;
5871 /****************************************************************************
5872 Deal with SMB_FILE_MODE_INFORMATION.
5873 ****************************************************************************/
5875 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5876 const char *pdata,
5877 int total_data)
5879 uint32 mode;
5881 if (total_data < 4) {
5882 return NT_STATUS_INVALID_PARAMETER;
5884 mode = IVAL(pdata,0);
5885 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5886 return NT_STATUS_INVALID_PARAMETER;
5888 return NT_STATUS_OK;
5891 /****************************************************************************
5892 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5893 ****************************************************************************/
5895 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5896 struct smb_request *req,
5897 const char *pdata,
5898 int total_data,
5899 const struct smb_filename *smb_fname)
5901 char *link_target = NULL;
5902 const char *newname = smb_fname->base_name;
5903 TALLOC_CTX *ctx = talloc_tos();
5905 /* Set a symbolic link. */
5906 /* Don't allow this if follow links is false. */
5908 if (total_data == 0) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 if (!lp_symlinks(SNUM(conn))) {
5913 return NT_STATUS_ACCESS_DENIED;
5916 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5917 total_data, STR_TERMINATE);
5919 if (!link_target) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5924 newname, link_target ));
5926 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5927 return map_nt_error_from_unix(errno);
5930 return NT_STATUS_OK;
5933 /****************************************************************************
5934 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5935 ****************************************************************************/
5937 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5938 struct smb_request *req,
5939 const char *pdata, int total_data,
5940 struct smb_filename *smb_fname_new)
5942 char *oldname = NULL;
5943 struct smb_filename *smb_fname_old = NULL;
5944 TALLOC_CTX *ctx = talloc_tos();
5945 NTSTATUS status = NT_STATUS_OK;
5947 /* Set a hard link. */
5948 if (total_data == 0) {
5949 return NT_STATUS_INVALID_PARAMETER;
5952 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5953 total_data, STR_TERMINATE, &status);
5954 if (!NT_STATUS_IS_OK(status)) {
5955 return status;
5958 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5959 smb_fname_str_dbg(smb_fname_new), oldname));
5961 status = filename_convert(ctx,
5962 conn,
5963 req->flags2 & FLAGS2_DFS_PATHNAMES,
5964 oldname,
5966 NULL,
5967 &smb_fname_old);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 return status;
5972 return hardlink_internals(ctx, conn, req, false,
5973 smb_fname_old, smb_fname_new);
5976 /****************************************************************************
5977 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5978 ****************************************************************************/
5980 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5981 struct smb_request *req,
5982 const char *pdata,
5983 int total_data,
5984 files_struct *fsp,
5985 struct smb_filename *smb_fname_src)
5987 bool overwrite;
5988 uint32_t len;
5989 char *newname = NULL;
5990 struct smb_filename *smb_fname_dst = NULL;
5991 NTSTATUS status = NT_STATUS_OK;
5992 TALLOC_CTX *ctx = talloc_tos();
5994 if (!fsp) {
5995 return NT_STATUS_INVALID_HANDLE;
5998 if (total_data < 20) {
5999 return NT_STATUS_INVALID_PARAMETER;
6002 overwrite = (CVAL(pdata,0) ? True : False);
6003 len = IVAL(pdata,16);
6005 if (len > (total_data - 20) || (len == 0)) {
6006 return NT_STATUS_INVALID_PARAMETER;
6009 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6010 &pdata[20], len, STR_TERMINATE,
6011 &status);
6012 if (!NT_STATUS_IS_OK(status)) {
6013 return status;
6016 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6017 newname));
6019 status = filename_convert(ctx,
6020 conn,
6021 req->flags2 & FLAGS2_DFS_PATHNAMES,
6022 newname,
6023 UCF_SAVE_LCOMP,
6024 NULL,
6025 &smb_fname_dst);
6026 if (!NT_STATUS_IS_OK(status)) {
6027 return status;
6030 if (fsp->base_fsp) {
6031 /* newname must be a stream name. */
6032 if (newname[0] != ':') {
6033 return NT_STATUS_NOT_SUPPORTED;
6036 /* Create an smb_fname to call rename_internals_fsp() with. */
6037 status = create_synthetic_smb_fname(talloc_tos(),
6038 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6039 &smb_fname_dst);
6040 if (!NT_STATUS_IS_OK(status)) {
6041 goto out;
6045 * Set the original last component, since
6046 * rename_internals_fsp() requires it.
6048 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6049 newname);
6050 if (smb_fname_dst->original_lcomp == NULL) {
6051 status = NT_STATUS_NO_MEMORY;
6052 goto out;
6057 DEBUG(10,("smb2_file_rename_information: "
6058 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6059 fsp->fnum, fsp_str_dbg(fsp),
6060 smb_fname_str_dbg(smb_fname_dst)));
6061 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6062 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6063 overwrite);
6065 out:
6066 TALLOC_FREE(smb_fname_dst);
6067 return status;
6070 static NTSTATUS smb_file_link_information(connection_struct *conn,
6071 struct smb_request *req,
6072 const char *pdata,
6073 int total_data,
6074 files_struct *fsp,
6075 struct smb_filename *smb_fname_src)
6077 bool overwrite;
6078 uint32_t len;
6079 char *newname = NULL;
6080 struct smb_filename *smb_fname_dst = NULL;
6081 NTSTATUS status = NT_STATUS_OK;
6082 TALLOC_CTX *ctx = talloc_tos();
6084 if (!fsp) {
6085 return NT_STATUS_INVALID_HANDLE;
6088 if (total_data < 20) {
6089 return NT_STATUS_INVALID_PARAMETER;
6092 overwrite = (CVAL(pdata,0) ? true : false);
6093 len = IVAL(pdata,16);
6095 if (len > (total_data - 20) || (len == 0)) {
6096 return NT_STATUS_INVALID_PARAMETER;
6099 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6100 &pdata[20], len, STR_TERMINATE,
6101 &status);
6102 if (!NT_STATUS_IS_OK(status)) {
6103 return status;
6106 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6107 newname));
6109 status = filename_convert(ctx,
6110 conn,
6111 req->flags2 & FLAGS2_DFS_PATHNAMES,
6112 newname,
6113 UCF_SAVE_LCOMP,
6114 NULL,
6115 &smb_fname_dst);
6116 if (!NT_STATUS_IS_OK(status)) {
6117 return status;
6120 if (fsp->base_fsp) {
6121 /* No stream names. */
6122 return NT_STATUS_NOT_SUPPORTED;
6125 DEBUG(10,("smb_file_link_information: "
6126 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6127 fsp->fnum, fsp_str_dbg(fsp),
6128 smb_fname_str_dbg(smb_fname_dst)));
6129 status = hardlink_internals(ctx,
6130 conn,
6131 req,
6132 overwrite,
6133 fsp->fsp_name,
6134 smb_fname_dst);
6136 TALLOC_FREE(smb_fname_dst);
6137 return status;
6140 /****************************************************************************
6141 Deal with SMB_FILE_RENAME_INFORMATION.
6142 ****************************************************************************/
6144 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6145 struct smb_request *req,
6146 const char *pdata,
6147 int total_data,
6148 files_struct *fsp,
6149 struct smb_filename *smb_fname_src)
6151 bool overwrite;
6152 uint32 root_fid;
6153 uint32 len;
6154 char *newname = NULL;
6155 struct smb_filename *smb_fname_dst = NULL;
6156 bool dest_has_wcard = False;
6157 NTSTATUS status = NT_STATUS_OK;
6158 char *p;
6159 TALLOC_CTX *ctx = talloc_tos();
6161 if (total_data < 13) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 overwrite = (CVAL(pdata,0) ? True : False);
6166 root_fid = IVAL(pdata,4);
6167 len = IVAL(pdata,8);
6169 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6170 return NT_STATUS_INVALID_PARAMETER;
6173 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6174 len, 0, &status,
6175 &dest_has_wcard);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 return status;
6180 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6181 newname));
6183 status = resolve_dfspath_wcard(ctx, conn,
6184 req->flags2 & FLAGS2_DFS_PATHNAMES,
6185 newname,
6186 true,
6187 &newname,
6188 &dest_has_wcard);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 return status;
6193 /* Check the new name has no '/' characters. */
6194 if (strchr_m(newname, '/')) {
6195 return NT_STATUS_NOT_SUPPORTED;
6198 if (fsp && fsp->base_fsp) {
6199 /* newname must be a stream name. */
6200 if (newname[0] != ':') {
6201 return NT_STATUS_NOT_SUPPORTED;
6204 /* Create an smb_fname to call rename_internals_fsp() with. */
6205 status = create_synthetic_smb_fname(talloc_tos(),
6206 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6207 &smb_fname_dst);
6208 if (!NT_STATUS_IS_OK(status)) {
6209 goto out;
6213 * Set the original last component, since
6214 * rename_internals_fsp() requires it.
6216 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6217 newname);
6218 if (smb_fname_dst->original_lcomp == NULL) {
6219 status = NT_STATUS_NO_MEMORY;
6220 goto out;
6223 } else {
6225 * Build up an smb_fname_dst based on the filename passed in.
6226 * We basically just strip off the last component, and put on
6227 * the newname instead.
6229 char *base_name = NULL;
6231 /* newname must *not* be a stream name. */
6232 if (newname[0] == ':') {
6233 return NT_STATUS_NOT_SUPPORTED;
6237 * Strip off the last component (filename) of the path passed
6238 * in.
6240 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6241 if (!base_name) {
6242 return NT_STATUS_NO_MEMORY;
6244 p = strrchr_m(base_name, '/');
6245 if (p) {
6246 p[1] = '\0';
6247 } else {
6248 base_name = talloc_strdup(ctx, "");
6249 if (!base_name) {
6250 return NT_STATUS_NO_MEMORY;
6253 /* Append the new name. */
6254 base_name = talloc_asprintf_append(base_name,
6255 "%s",
6256 newname);
6257 if (!base_name) {
6258 return NT_STATUS_NO_MEMORY;
6261 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6262 (UCF_SAVE_LCOMP |
6263 (dest_has_wcard ?
6264 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6265 0)));
6267 /* If an error we expect this to be
6268 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6270 if (!NT_STATUS_IS_OK(status)) {
6271 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6272 status)) {
6273 goto out;
6275 /* Create an smb_fname to call rename_internals_fsp() */
6276 status = create_synthetic_smb_fname(ctx,
6277 base_name, NULL,
6278 NULL,
6279 &smb_fname_dst);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 goto out;
6286 if (fsp) {
6287 DEBUG(10,("smb_file_rename_information: "
6288 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6289 fsp->fnum, fsp_str_dbg(fsp),
6290 smb_fname_str_dbg(smb_fname_dst)));
6291 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6292 overwrite);
6293 } else {
6294 DEBUG(10,("smb_file_rename_information: "
6295 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6296 smb_fname_str_dbg(smb_fname_src),
6297 smb_fname_str_dbg(smb_fname_dst)));
6298 status = rename_internals(ctx, conn, req, smb_fname_src,
6299 smb_fname_dst, 0, overwrite, false,
6300 dest_has_wcard,
6301 FILE_WRITE_ATTRIBUTES);
6303 out:
6304 TALLOC_FREE(smb_fname_dst);
6305 return status;
6308 /****************************************************************************
6309 Deal with SMB_SET_POSIX_ACL.
6310 ****************************************************************************/
6312 #if defined(HAVE_POSIX_ACLS)
6313 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6314 const char *pdata,
6315 int total_data,
6316 files_struct *fsp,
6317 const struct smb_filename *smb_fname)
6319 uint16 posix_acl_version;
6320 uint16 num_file_acls;
6321 uint16 num_def_acls;
6322 bool valid_file_acls = True;
6323 bool valid_def_acls = True;
6325 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6326 return NT_STATUS_INVALID_PARAMETER;
6328 posix_acl_version = SVAL(pdata,0);
6329 num_file_acls = SVAL(pdata,2);
6330 num_def_acls = SVAL(pdata,4);
6332 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6333 valid_file_acls = False;
6334 num_file_acls = 0;
6337 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6338 valid_def_acls = False;
6339 num_def_acls = 0;
6342 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6343 return NT_STATUS_INVALID_PARAMETER;
6346 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6347 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6348 return NT_STATUS_INVALID_PARAMETER;
6351 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6352 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6353 (unsigned int)num_file_acls,
6354 (unsigned int)num_def_acls));
6356 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6357 smb_fname->base_name, num_file_acls,
6358 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6359 return map_nt_error_from_unix(errno);
6362 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6363 smb_fname->base_name, &smb_fname->st, num_def_acls,
6364 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6365 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6366 return map_nt_error_from_unix(errno);
6368 return NT_STATUS_OK;
6370 #endif
6372 /****************************************************************************
6373 Deal with SMB_SET_POSIX_LOCK.
6374 ****************************************************************************/
6376 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6377 struct smb_request *req,
6378 const char *pdata,
6379 int total_data,
6380 files_struct *fsp)
6382 uint64_t count;
6383 uint64_t offset;
6384 uint64_t smblctx;
6385 bool blocking_lock = False;
6386 enum brl_type lock_type;
6388 NTSTATUS status = NT_STATUS_OK;
6390 if (fsp == NULL || fsp->fh->fd == -1) {
6391 return NT_STATUS_INVALID_HANDLE;
6394 if (total_data != POSIX_LOCK_DATA_SIZE) {
6395 return NT_STATUS_INVALID_PARAMETER;
6398 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6399 case POSIX_LOCK_TYPE_READ:
6400 lock_type = READ_LOCK;
6401 break;
6402 case POSIX_LOCK_TYPE_WRITE:
6403 /* Return the right POSIX-mappable error code for files opened read-only. */
6404 if (!fsp->can_write) {
6405 return NT_STATUS_INVALID_HANDLE;
6407 lock_type = WRITE_LOCK;
6408 break;
6409 case POSIX_LOCK_TYPE_UNLOCK:
6410 lock_type = UNLOCK_LOCK;
6411 break;
6412 default:
6413 return NT_STATUS_INVALID_PARAMETER;
6416 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6417 blocking_lock = False;
6418 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6419 blocking_lock = True;
6420 } else {
6421 return NT_STATUS_INVALID_PARAMETER;
6424 if (!lp_blocking_locks(SNUM(conn))) {
6425 blocking_lock = False;
6428 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6429 #if defined(HAVE_LONGLONG)
6430 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6431 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6432 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6433 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6434 #else /* HAVE_LONGLONG */
6435 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6436 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6437 #endif /* HAVE_LONGLONG */
6439 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6440 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6441 fsp_str_dbg(fsp),
6442 (unsigned int)lock_type,
6443 (unsigned long long)smblctx,
6444 (double)count,
6445 (double)offset ));
6447 if (lock_type == UNLOCK_LOCK) {
6448 status = do_unlock(req->sconn->msg_ctx,
6449 fsp,
6450 smblctx,
6451 count,
6452 offset,
6453 POSIX_LOCK);
6454 } else {
6455 uint64_t block_smblctx;
6457 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6458 fsp,
6459 smblctx,
6460 count,
6461 offset,
6462 lock_type,
6463 POSIX_LOCK,
6464 blocking_lock,
6465 &status,
6466 &block_smblctx,
6467 NULL);
6469 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6471 * A blocking lock was requested. Package up
6472 * this smb into a queued request and push it
6473 * onto the blocking lock queue.
6475 if(push_blocking_lock_request(br_lck,
6476 req,
6477 fsp,
6478 -1, /* infinite timeout. */
6480 smblctx,
6481 lock_type,
6482 POSIX_LOCK,
6483 offset,
6484 count,
6485 block_smblctx)) {
6486 TALLOC_FREE(br_lck);
6487 return status;
6490 TALLOC_FREE(br_lck);
6493 return status;
6496 /****************************************************************************
6497 Deal with SMB_SET_FILE_BASIC_INFO.
6498 ****************************************************************************/
6500 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6501 const char *pdata,
6502 int total_data,
6503 files_struct *fsp,
6504 const struct smb_filename *smb_fname)
6506 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6507 struct smb_file_time ft;
6508 uint32 dosmode = 0;
6509 NTSTATUS status = NT_STATUS_OK;
6511 ZERO_STRUCT(ft);
6513 if (total_data < 36) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6518 return NT_STATUS_ACCESS_DENIED;
6521 /* Set the attributes */
6522 dosmode = IVAL(pdata,32);
6523 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6524 if (!NT_STATUS_IS_OK(status)) {
6525 return status;
6528 /* create time */
6529 ft.create_time = interpret_long_date(pdata);
6531 /* access time */
6532 ft.atime = interpret_long_date(pdata+8);
6534 /* write time. */
6535 ft.mtime = interpret_long_date(pdata+16);
6537 /* change time. */
6538 ft.ctime = interpret_long_date(pdata+24);
6540 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6541 smb_fname_str_dbg(smb_fname)));
6543 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6544 true);
6547 /****************************************************************************
6548 Deal with SMB_INFO_STANDARD.
6549 ****************************************************************************/
6551 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6552 const char *pdata,
6553 int total_data,
6554 files_struct *fsp,
6555 const struct smb_filename *smb_fname)
6557 struct smb_file_time ft;
6559 ZERO_STRUCT(ft);
6561 if (total_data < 12) {
6562 return NT_STATUS_INVALID_PARAMETER;
6565 /* create time */
6566 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6567 /* access time */
6568 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6569 /* write time */
6570 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6572 DEBUG(10,("smb_set_info_standard: file %s\n",
6573 smb_fname_str_dbg(smb_fname)));
6575 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6576 return NT_STATUS_ACCESS_DENIED;
6579 return smb_set_file_time(conn,
6580 fsp,
6581 smb_fname,
6582 &ft,
6583 true);
6586 /****************************************************************************
6587 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6588 ****************************************************************************/
6590 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6591 struct smb_request *req,
6592 const char *pdata,
6593 int total_data,
6594 files_struct *fsp,
6595 struct smb_filename *smb_fname)
6597 uint64_t allocation_size = 0;
6598 NTSTATUS status = NT_STATUS_OK;
6599 files_struct *new_fsp = NULL;
6601 if (!VALID_STAT(smb_fname->st)) {
6602 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6605 if (total_data < 8) {
6606 return NT_STATUS_INVALID_PARAMETER;
6609 allocation_size = (uint64_t)IVAL(pdata,0);
6610 #ifdef LARGE_SMB_OFF_T
6611 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6612 #else /* LARGE_SMB_OFF_T */
6613 if (IVAL(pdata,4) != 0) {
6614 /* more than 32 bits? */
6615 return NT_STATUS_INVALID_PARAMETER;
6617 #endif /* LARGE_SMB_OFF_T */
6619 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6620 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6621 (double)allocation_size));
6623 if (allocation_size) {
6624 allocation_size = smb_roundup(conn, allocation_size);
6627 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6628 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6629 (double)allocation_size));
6631 if (fsp && fsp->fh->fd != -1) {
6632 /* Open file handle. */
6633 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6634 return NT_STATUS_ACCESS_DENIED;
6637 /* Only change if needed. */
6638 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6639 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6640 return map_nt_error_from_unix(errno);
6643 /* But always update the time. */
6645 * This is equivalent to a write. Ensure it's seen immediately
6646 * if there are no pending writes.
6648 trigger_write_time_update_immediate(fsp);
6649 return NT_STATUS_OK;
6652 /* Pathname or stat or directory file. */
6653 status = SMB_VFS_CREATE_FILE(
6654 conn, /* conn */
6655 req, /* req */
6656 0, /* root_dir_fid */
6657 smb_fname, /* fname */
6658 FILE_WRITE_DATA, /* access_mask */
6659 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6660 FILE_SHARE_DELETE),
6661 FILE_OPEN, /* create_disposition*/
6662 0, /* create_options */
6663 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6664 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6665 0, /* allocation_size */
6666 0, /* private_flags */
6667 NULL, /* sd */
6668 NULL, /* ea_list */
6669 &new_fsp, /* result */
6670 NULL); /* pinfo */
6672 if (!NT_STATUS_IS_OK(status)) {
6673 /* NB. We check for open_was_deferred in the caller. */
6674 return status;
6677 /* Only change if needed. */
6678 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6679 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6680 status = map_nt_error_from_unix(errno);
6681 close_file(req, new_fsp, NORMAL_CLOSE);
6682 return status;
6686 /* Changing the allocation size should set the last mod time. */
6688 * This is equivalent to a write. Ensure it's seen immediately
6689 * if there are no pending writes.
6691 trigger_write_time_update_immediate(new_fsp);
6693 close_file(req, new_fsp, NORMAL_CLOSE);
6694 return NT_STATUS_OK;
6697 /****************************************************************************
6698 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6699 ****************************************************************************/
6701 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6702 struct smb_request *req,
6703 const char *pdata,
6704 int total_data,
6705 files_struct *fsp,
6706 const struct smb_filename *smb_fname,
6707 bool fail_after_createfile)
6709 SMB_OFF_T size;
6711 if (total_data < 8) {
6712 return NT_STATUS_INVALID_PARAMETER;
6715 size = IVAL(pdata,0);
6716 #ifdef LARGE_SMB_OFF_T
6717 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6718 #else /* LARGE_SMB_OFF_T */
6719 if (IVAL(pdata,4) != 0) {
6720 /* more than 32 bits? */
6721 return NT_STATUS_INVALID_PARAMETER;
6723 #endif /* LARGE_SMB_OFF_T */
6724 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6725 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6726 (double)size));
6728 return smb_set_file_size(conn, req,
6729 fsp,
6730 smb_fname,
6731 &smb_fname->st,
6732 size,
6733 fail_after_createfile);
6736 /****************************************************************************
6737 Allow a UNIX info mknod.
6738 ****************************************************************************/
6740 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6741 const char *pdata,
6742 int total_data,
6743 const struct smb_filename *smb_fname)
6745 uint32 file_type = IVAL(pdata,56);
6746 #if defined(HAVE_MAKEDEV)
6747 uint32 dev_major = IVAL(pdata,60);
6748 uint32 dev_minor = IVAL(pdata,68);
6749 #endif
6750 SMB_DEV_T dev = (SMB_DEV_T)0;
6751 uint32 raw_unixmode = IVAL(pdata,84);
6752 NTSTATUS status;
6753 mode_t unixmode;
6755 if (total_data < 100) {
6756 return NT_STATUS_INVALID_PARAMETER;
6759 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6760 PERM_NEW_FILE, &unixmode);
6761 if (!NT_STATUS_IS_OK(status)) {
6762 return status;
6765 #if defined(HAVE_MAKEDEV)
6766 dev = makedev(dev_major, dev_minor);
6767 #endif
6769 switch (file_type) {
6770 #if defined(S_IFIFO)
6771 case UNIX_TYPE_FIFO:
6772 unixmode |= S_IFIFO;
6773 break;
6774 #endif
6775 #if defined(S_IFSOCK)
6776 case UNIX_TYPE_SOCKET:
6777 unixmode |= S_IFSOCK;
6778 break;
6779 #endif
6780 #if defined(S_IFCHR)
6781 case UNIX_TYPE_CHARDEV:
6782 unixmode |= S_IFCHR;
6783 break;
6784 #endif
6785 #if defined(S_IFBLK)
6786 case UNIX_TYPE_BLKDEV:
6787 unixmode |= S_IFBLK;
6788 break;
6789 #endif
6790 default:
6791 return NT_STATUS_INVALID_PARAMETER;
6794 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6795 "%.0f mode 0%o for file %s\n", (double)dev,
6796 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6798 /* Ok - do the mknod. */
6799 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6800 return map_nt_error_from_unix(errno);
6803 /* If any of the other "set" calls fail we
6804 * don't want to end up with a half-constructed mknod.
6807 if (lp_inherit_perms(SNUM(conn))) {
6808 char *parent;
6809 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6810 &parent, NULL)) {
6811 return NT_STATUS_NO_MEMORY;
6813 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6814 unixmode);
6815 TALLOC_FREE(parent);
6818 return NT_STATUS_OK;
6821 /****************************************************************************
6822 Deal with SMB_SET_FILE_UNIX_BASIC.
6823 ****************************************************************************/
6825 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6826 struct smb_request *req,
6827 const char *pdata,
6828 int total_data,
6829 files_struct *fsp,
6830 const struct smb_filename *smb_fname)
6832 struct smb_file_time ft;
6833 uint32 raw_unixmode;
6834 mode_t unixmode;
6835 SMB_OFF_T size = 0;
6836 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6837 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6838 NTSTATUS status = NT_STATUS_OK;
6839 bool delete_on_fail = False;
6840 enum perm_type ptype;
6841 files_struct *all_fsps = NULL;
6842 bool modify_mtime = true;
6843 struct file_id id;
6844 struct smb_filename *smb_fname_tmp = NULL;
6845 SMB_STRUCT_STAT sbuf;
6847 ZERO_STRUCT(ft);
6849 if (total_data < 100) {
6850 return NT_STATUS_INVALID_PARAMETER;
6853 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6854 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6855 size=IVAL(pdata,0); /* first 8 Bytes are size */
6856 #ifdef LARGE_SMB_OFF_T
6857 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6858 #else /* LARGE_SMB_OFF_T */
6859 if (IVAL(pdata,4) != 0) {
6860 /* more than 32 bits? */
6861 return NT_STATUS_INVALID_PARAMETER;
6863 #endif /* LARGE_SMB_OFF_T */
6866 ft.atime = interpret_long_date(pdata+24); /* access_time */
6867 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6868 set_owner = (uid_t)IVAL(pdata,40);
6869 set_grp = (gid_t)IVAL(pdata,48);
6870 raw_unixmode = IVAL(pdata,84);
6872 if (VALID_STAT(smb_fname->st)) {
6873 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6874 ptype = PERM_EXISTING_DIR;
6875 } else {
6876 ptype = PERM_EXISTING_FILE;
6878 } else {
6879 ptype = PERM_NEW_FILE;
6882 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6883 ptype, &unixmode);
6884 if (!NT_STATUS_IS_OK(status)) {
6885 return status;
6888 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6889 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6890 smb_fname_str_dbg(smb_fname), (double)size,
6891 (unsigned int)set_owner, (unsigned int)set_grp,
6892 (int)raw_unixmode));
6894 sbuf = smb_fname->st;
6896 if (!VALID_STAT(sbuf)) {
6898 * The only valid use of this is to create character and block
6899 * devices, and named pipes. This is deprecated (IMHO) and
6900 * a new info level should be used for mknod. JRA.
6903 status = smb_unix_mknod(conn,
6904 pdata,
6905 total_data,
6906 smb_fname);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 return status;
6911 status = copy_smb_filename(talloc_tos(), smb_fname,
6912 &smb_fname_tmp);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 return status;
6917 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6918 status = map_nt_error_from_unix(errno);
6919 TALLOC_FREE(smb_fname_tmp);
6920 SMB_VFS_UNLINK(conn, smb_fname);
6921 return status;
6924 sbuf = smb_fname_tmp->st;
6925 smb_fname = smb_fname_tmp;
6927 /* Ensure we don't try and change anything else. */
6928 raw_unixmode = SMB_MODE_NO_CHANGE;
6929 size = get_file_size_stat(&sbuf);
6930 ft.atime = sbuf.st_ex_atime;
6931 ft.mtime = sbuf.st_ex_mtime;
6933 * We continue here as we might want to change the
6934 * owner uid/gid.
6936 delete_on_fail = True;
6939 #if 1
6940 /* Horrible backwards compatibility hack as an old server bug
6941 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6942 * */
6944 if (!size) {
6945 size = get_file_size_stat(&sbuf);
6947 #endif
6949 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6950 return NT_STATUS_ACCESS_DENIED;
6954 * Deal with the UNIX specific mode set.
6957 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6958 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6959 "setting mode 0%o for file %s\n",
6960 (unsigned int)unixmode,
6961 smb_fname_str_dbg(smb_fname)));
6962 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6963 return map_nt_error_from_unix(errno);
6968 * Deal with the UNIX specific uid set.
6971 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6972 (sbuf.st_ex_uid != set_owner)) {
6973 int ret;
6975 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6976 "changing owner %u for path %s\n",
6977 (unsigned int)set_owner,
6978 smb_fname_str_dbg(smb_fname)));
6980 if (S_ISLNK(sbuf.st_ex_mode)) {
6981 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6982 set_owner, (gid_t)-1);
6983 } else {
6984 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6985 set_owner, (gid_t)-1);
6988 if (ret != 0) {
6989 status = map_nt_error_from_unix(errno);
6990 if (delete_on_fail) {
6991 SMB_VFS_UNLINK(conn, smb_fname);
6993 return status;
6998 * Deal with the UNIX specific gid set.
7001 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7002 (sbuf.st_ex_gid != set_grp)) {
7003 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7004 "changing group %u for file %s\n",
7005 (unsigned int)set_owner,
7006 smb_fname_str_dbg(smb_fname)));
7007 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7008 set_grp) != 0) {
7009 status = map_nt_error_from_unix(errno);
7010 if (delete_on_fail) {
7011 SMB_VFS_UNLINK(conn, smb_fname);
7013 return status;
7017 /* Deal with any size changes. */
7019 status = smb_set_file_size(conn, req,
7020 fsp,
7021 smb_fname,
7022 &sbuf,
7023 size,
7024 false);
7025 if (!NT_STATUS_IS_OK(status)) {
7026 return status;
7029 /* Deal with any time changes. */
7030 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7031 /* No change, don't cancel anything. */
7032 return status;
7035 id = vfs_file_id_from_sbuf(conn, &sbuf);
7036 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7037 all_fsps = file_find_di_next(all_fsps)) {
7039 * We're setting the time explicitly for UNIX.
7040 * Cancel any pending changes over all handles.
7042 all_fsps->update_write_time_on_close = false;
7043 TALLOC_FREE(all_fsps->update_write_time_event);
7047 * Override the "setting_write_time"
7048 * parameter here as it almost does what
7049 * we need. Just remember if we modified
7050 * mtime and send the notify ourselves.
7052 if (null_timespec(ft.mtime)) {
7053 modify_mtime = false;
7056 status = smb_set_file_time(conn,
7057 fsp,
7058 smb_fname,
7059 &ft,
7060 false);
7061 if (modify_mtime) {
7062 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7063 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7065 return status;
7068 /****************************************************************************
7069 Deal with SMB_SET_FILE_UNIX_INFO2.
7070 ****************************************************************************/
7072 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7073 struct smb_request *req,
7074 const char *pdata,
7075 int total_data,
7076 files_struct *fsp,
7077 const struct smb_filename *smb_fname)
7079 NTSTATUS status;
7080 uint32 smb_fflags;
7081 uint32 smb_fmask;
7083 if (total_data < 116) {
7084 return NT_STATUS_INVALID_PARAMETER;
7087 /* Start by setting all the fields that are common between UNIX_BASIC
7088 * and UNIX_INFO2.
7090 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7091 fsp, smb_fname);
7092 if (!NT_STATUS_IS_OK(status)) {
7093 return status;
7096 smb_fflags = IVAL(pdata, 108);
7097 smb_fmask = IVAL(pdata, 112);
7099 /* NB: We should only attempt to alter the file flags if the client
7100 * sends a non-zero mask.
7102 if (smb_fmask != 0) {
7103 int stat_fflags = 0;
7105 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7106 smb_fmask, &stat_fflags)) {
7107 /* Client asked to alter a flag we don't understand. */
7108 return NT_STATUS_INVALID_PARAMETER;
7111 if (fsp && fsp->fh->fd != -1) {
7112 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7113 return NT_STATUS_NOT_SUPPORTED;
7114 } else {
7115 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7116 stat_fflags) != 0) {
7117 return map_nt_error_from_unix(errno);
7122 /* XXX: need to add support for changing the create_time here. You
7123 * can do this for paths on Darwin with setattrlist(2). The right way
7124 * to hook this up is probably by extending the VFS utimes interface.
7127 return NT_STATUS_OK;
7130 /****************************************************************************
7131 Create a directory with POSIX semantics.
7132 ****************************************************************************/
7134 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7135 struct smb_request *req,
7136 char **ppdata,
7137 int total_data,
7138 struct smb_filename *smb_fname,
7139 int *pdata_return_size)
7141 NTSTATUS status = NT_STATUS_OK;
7142 uint32 raw_unixmode = 0;
7143 uint32 mod_unixmode = 0;
7144 mode_t unixmode = (mode_t)0;
7145 files_struct *fsp = NULL;
7146 uint16 info_level_return = 0;
7147 int info;
7148 char *pdata = *ppdata;
7150 if (total_data < 18) {
7151 return NT_STATUS_INVALID_PARAMETER;
7154 raw_unixmode = IVAL(pdata,8);
7155 /* Next 4 bytes are not yet defined. */
7157 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7158 PERM_NEW_DIR, &unixmode);
7159 if (!NT_STATUS_IS_OK(status)) {
7160 return status;
7163 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7165 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7166 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7168 status = SMB_VFS_CREATE_FILE(
7169 conn, /* conn */
7170 req, /* req */
7171 0, /* root_dir_fid */
7172 smb_fname, /* fname */
7173 FILE_READ_ATTRIBUTES, /* access_mask */
7174 FILE_SHARE_NONE, /* share_access */
7175 FILE_CREATE, /* create_disposition*/
7176 FILE_DIRECTORY_FILE, /* create_options */
7177 mod_unixmode, /* file_attributes */
7178 0, /* oplock_request */
7179 0, /* allocation_size */
7180 0, /* private_flags */
7181 NULL, /* sd */
7182 NULL, /* ea_list */
7183 &fsp, /* result */
7184 &info); /* pinfo */
7186 if (NT_STATUS_IS_OK(status)) {
7187 close_file(req, fsp, NORMAL_CLOSE);
7190 info_level_return = SVAL(pdata,16);
7192 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7193 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7194 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7195 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7196 } else {
7197 *pdata_return_size = 12;
7200 /* Realloc the data size */
7201 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7202 if (*ppdata == NULL) {
7203 *pdata_return_size = 0;
7204 return NT_STATUS_NO_MEMORY;
7206 pdata = *ppdata;
7208 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7209 SSVAL(pdata,2,0); /* No fnum. */
7210 SIVAL(pdata,4,info); /* Was directory created. */
7212 switch (info_level_return) {
7213 case SMB_QUERY_FILE_UNIX_BASIC:
7214 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7215 SSVAL(pdata,10,0); /* Padding. */
7216 store_file_unix_basic(conn, pdata + 12, fsp,
7217 &smb_fname->st);
7218 break;
7219 case SMB_QUERY_FILE_UNIX_INFO2:
7220 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7221 SSVAL(pdata,10,0); /* Padding. */
7222 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7223 &smb_fname->st);
7224 break;
7225 default:
7226 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7227 SSVAL(pdata,10,0); /* Padding. */
7228 break;
7231 return status;
7234 /****************************************************************************
7235 Open/Create a file with POSIX semantics.
7236 ****************************************************************************/
7238 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7239 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7241 static NTSTATUS smb_posix_open(connection_struct *conn,
7242 struct smb_request *req,
7243 char **ppdata,
7244 int total_data,
7245 struct smb_filename *smb_fname,
7246 int *pdata_return_size)
7248 bool extended_oplock_granted = False;
7249 char *pdata = *ppdata;
7250 uint32 flags = 0;
7251 uint32 wire_open_mode = 0;
7252 uint32 raw_unixmode = 0;
7253 uint32 mod_unixmode = 0;
7254 uint32 create_disp = 0;
7255 uint32 access_mask = 0;
7256 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7257 NTSTATUS status = NT_STATUS_OK;
7258 mode_t unixmode = (mode_t)0;
7259 files_struct *fsp = NULL;
7260 int oplock_request = 0;
7261 int info = 0;
7262 uint16 info_level_return = 0;
7264 if (total_data < 18) {
7265 return NT_STATUS_INVALID_PARAMETER;
7268 flags = IVAL(pdata,0);
7269 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7270 if (oplock_request) {
7271 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7274 wire_open_mode = IVAL(pdata,4);
7276 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7277 return smb_posix_mkdir(conn, req,
7278 ppdata,
7279 total_data,
7280 smb_fname,
7281 pdata_return_size);
7284 switch (wire_open_mode & SMB_ACCMODE) {
7285 case SMB_O_RDONLY:
7286 access_mask = SMB_O_RDONLY_MAPPING;
7287 break;
7288 case SMB_O_WRONLY:
7289 access_mask = SMB_O_WRONLY_MAPPING;
7290 break;
7291 case SMB_O_RDWR:
7292 access_mask = (SMB_O_RDONLY_MAPPING|
7293 SMB_O_WRONLY_MAPPING);
7294 break;
7295 default:
7296 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7297 (unsigned int)wire_open_mode ));
7298 return NT_STATUS_INVALID_PARAMETER;
7301 wire_open_mode &= ~SMB_ACCMODE;
7303 /* First take care of O_CREAT|O_EXCL interactions. */
7304 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7305 case (SMB_O_CREAT | SMB_O_EXCL):
7306 /* File exists fail. File not exist create. */
7307 create_disp = FILE_CREATE;
7308 break;
7309 case SMB_O_CREAT:
7310 /* File exists open. File not exist create. */
7311 create_disp = FILE_OPEN_IF;
7312 break;
7313 case 0:
7314 /* File exists open. File not exist fail. */
7315 create_disp = FILE_OPEN;
7316 break;
7317 case SMB_O_EXCL:
7318 /* O_EXCL on its own without O_CREAT is undefined. */
7319 default:
7320 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7321 (unsigned int)wire_open_mode ));
7322 return NT_STATUS_INVALID_PARAMETER;
7325 /* Next factor in the effects of O_TRUNC. */
7326 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7328 if (wire_open_mode & SMB_O_TRUNC) {
7329 switch (create_disp) {
7330 case FILE_CREATE:
7331 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7332 /* Leave create_disp alone as
7333 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7335 /* File exists fail. File not exist create. */
7336 break;
7337 case FILE_OPEN_IF:
7338 /* SMB_O_CREAT | SMB_O_TRUNC */
7339 /* File exists overwrite. File not exist create. */
7340 create_disp = FILE_OVERWRITE_IF;
7341 break;
7342 case FILE_OPEN:
7343 /* SMB_O_TRUNC */
7344 /* File exists overwrite. File not exist fail. */
7345 create_disp = FILE_OVERWRITE;
7346 break;
7347 default:
7348 /* Cannot get here. */
7349 smb_panic("smb_posix_open: logic error");
7350 return NT_STATUS_INVALID_PARAMETER;
7354 raw_unixmode = IVAL(pdata,8);
7355 /* Next 4 bytes are not yet defined. */
7357 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7358 (VALID_STAT(smb_fname->st) ?
7359 PERM_EXISTING_FILE : PERM_NEW_FILE),
7360 &unixmode);
7362 if (!NT_STATUS_IS_OK(status)) {
7363 return status;
7366 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7368 if (wire_open_mode & SMB_O_SYNC) {
7369 create_options |= FILE_WRITE_THROUGH;
7371 if (wire_open_mode & SMB_O_APPEND) {
7372 access_mask |= FILE_APPEND_DATA;
7374 if (wire_open_mode & SMB_O_DIRECT) {
7375 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7378 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7379 VALID_STAT_OF_DIR(smb_fname->st)) {
7380 if (access_mask != SMB_O_RDONLY_MAPPING) {
7381 return NT_STATUS_FILE_IS_A_DIRECTORY;
7383 create_options &= ~FILE_NON_DIRECTORY_FILE;
7384 create_options |= FILE_DIRECTORY_FILE;
7387 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7388 smb_fname_str_dbg(smb_fname),
7389 (unsigned int)wire_open_mode,
7390 (unsigned int)unixmode ));
7392 status = SMB_VFS_CREATE_FILE(
7393 conn, /* conn */
7394 req, /* req */
7395 0, /* root_dir_fid */
7396 smb_fname, /* fname */
7397 access_mask, /* access_mask */
7398 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7399 FILE_SHARE_DELETE),
7400 create_disp, /* create_disposition*/
7401 create_options, /* create_options */
7402 mod_unixmode, /* file_attributes */
7403 oplock_request, /* oplock_request */
7404 0, /* allocation_size */
7405 0, /* private_flags */
7406 NULL, /* sd */
7407 NULL, /* ea_list */
7408 &fsp, /* result */
7409 &info); /* pinfo */
7411 if (!NT_STATUS_IS_OK(status)) {
7412 return status;
7415 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7416 extended_oplock_granted = True;
7419 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7420 extended_oplock_granted = True;
7423 info_level_return = SVAL(pdata,16);
7425 /* Allocate the correct return size. */
7427 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7428 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7429 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7430 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7431 } else {
7432 *pdata_return_size = 12;
7435 /* Realloc the data size */
7436 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7437 if (*ppdata == NULL) {
7438 close_file(req, fsp, ERROR_CLOSE);
7439 *pdata_return_size = 0;
7440 return NT_STATUS_NO_MEMORY;
7442 pdata = *ppdata;
7444 if (extended_oplock_granted) {
7445 if (flags & REQUEST_BATCH_OPLOCK) {
7446 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7447 } else {
7448 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7450 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7451 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7452 } else {
7453 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7456 SSVAL(pdata,2,fsp->fnum);
7457 SIVAL(pdata,4,info); /* Was file created etc. */
7459 switch (info_level_return) {
7460 case SMB_QUERY_FILE_UNIX_BASIC:
7461 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7462 SSVAL(pdata,10,0); /* padding. */
7463 store_file_unix_basic(conn, pdata + 12, fsp,
7464 &smb_fname->st);
7465 break;
7466 case SMB_QUERY_FILE_UNIX_INFO2:
7467 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7468 SSVAL(pdata,10,0); /* padding. */
7469 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7470 &smb_fname->st);
7471 break;
7472 default:
7473 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7474 SSVAL(pdata,10,0); /* padding. */
7475 break;
7477 return NT_STATUS_OK;
7480 /****************************************************************************
7481 Delete a file with POSIX semantics.
7482 ****************************************************************************/
7484 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7485 struct smb_request *req,
7486 const char *pdata,
7487 int total_data,
7488 struct smb_filename *smb_fname)
7490 NTSTATUS status = NT_STATUS_OK;
7491 files_struct *fsp = NULL;
7492 uint16 flags = 0;
7493 char del = 1;
7494 int info = 0;
7495 int create_options = 0;
7496 int i;
7497 struct share_mode_lock *lck = NULL;
7499 if (total_data < 2) {
7500 return NT_STATUS_INVALID_PARAMETER;
7503 flags = SVAL(pdata,0);
7505 if (!VALID_STAT(smb_fname->st)) {
7506 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7509 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7510 !VALID_STAT_OF_DIR(smb_fname->st)) {
7511 return NT_STATUS_NOT_A_DIRECTORY;
7514 DEBUG(10,("smb_posix_unlink: %s %s\n",
7515 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7516 smb_fname_str_dbg(smb_fname)));
7518 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7519 create_options |= FILE_DIRECTORY_FILE;
7522 status = SMB_VFS_CREATE_FILE(
7523 conn, /* conn */
7524 req, /* req */
7525 0, /* root_dir_fid */
7526 smb_fname, /* fname */
7527 DELETE_ACCESS, /* access_mask */
7528 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7529 FILE_SHARE_DELETE),
7530 FILE_OPEN, /* create_disposition*/
7531 create_options, /* create_options */
7532 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7533 0, /* oplock_request */
7534 0, /* allocation_size */
7535 0, /* private_flags */
7536 NULL, /* sd */
7537 NULL, /* ea_list */
7538 &fsp, /* result */
7539 &info); /* pinfo */
7541 if (!NT_STATUS_IS_OK(status)) {
7542 return status;
7546 * Don't lie to client. If we can't really delete due to
7547 * non-POSIX opens return SHARING_VIOLATION.
7550 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7551 NULL);
7552 if (lck == NULL) {
7553 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7554 "lock for file %s\n", fsp_str_dbg(fsp)));
7555 close_file(req, fsp, NORMAL_CLOSE);
7556 return NT_STATUS_INVALID_PARAMETER;
7560 * See if others still have the file open. If this is the case, then
7561 * don't delete. If all opens are POSIX delete we can set the delete
7562 * on close disposition.
7564 for (i=0; i<lck->num_share_modes; i++) {
7565 struct share_mode_entry *e = &lck->share_modes[i];
7566 if (is_valid_share_mode_entry(e)) {
7567 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7568 continue;
7570 /* Fail with sharing violation. */
7571 close_file(req, fsp, NORMAL_CLOSE);
7572 TALLOC_FREE(lck);
7573 return NT_STATUS_SHARING_VIOLATION;
7578 * Set the delete on close.
7580 status = smb_set_file_disposition_info(conn,
7581 &del,
7583 fsp,
7584 smb_fname);
7586 if (!NT_STATUS_IS_OK(status)) {
7587 close_file(req, fsp, NORMAL_CLOSE);
7588 TALLOC_FREE(lck);
7589 return status;
7591 TALLOC_FREE(lck);
7592 return close_file(req, fsp, NORMAL_CLOSE);
7595 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7596 struct smb_request *req,
7597 TALLOC_CTX *mem_ctx,
7598 uint16_t info_level,
7599 files_struct *fsp,
7600 struct smb_filename *smb_fname,
7601 char **ppdata, int total_data,
7602 int *ret_data_size)
7604 char *pdata = *ppdata;
7605 NTSTATUS status = NT_STATUS_OK;
7606 int data_return_size = 0;
7608 *ret_data_size = 0;
7610 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7611 return NT_STATUS_INVALID_LEVEL;
7614 if (!CAN_WRITE(conn)) {
7615 /* Allow POSIX opens. The open path will deny
7616 * any non-readonly opens. */
7617 if (info_level != SMB_POSIX_PATH_OPEN) {
7618 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7622 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7623 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7624 fsp ? fsp->fnum : -1, info_level, total_data));
7626 switch (info_level) {
7628 case SMB_INFO_STANDARD:
7630 status = smb_set_info_standard(conn,
7631 pdata,
7632 total_data,
7633 fsp,
7634 smb_fname);
7635 break;
7638 case SMB_INFO_SET_EA:
7640 status = smb_info_set_ea(conn,
7641 pdata,
7642 total_data,
7643 fsp,
7644 smb_fname);
7645 break;
7648 case SMB_SET_FILE_BASIC_INFO:
7649 case SMB_FILE_BASIC_INFORMATION:
7651 status = smb_set_file_basic_info(conn,
7652 pdata,
7653 total_data,
7654 fsp,
7655 smb_fname);
7656 break;
7659 case SMB_FILE_ALLOCATION_INFORMATION:
7660 case SMB_SET_FILE_ALLOCATION_INFO:
7662 status = smb_set_file_allocation_info(conn, req,
7663 pdata,
7664 total_data,
7665 fsp,
7666 smb_fname);
7667 break;
7670 case SMB_FILE_END_OF_FILE_INFORMATION:
7671 case SMB_SET_FILE_END_OF_FILE_INFO:
7674 * XP/Win7 both fail after the createfile with
7675 * SMB_SET_FILE_END_OF_FILE_INFO but not
7676 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7677 * The level is known here, so pass it down
7678 * appropriately.
7680 bool should_fail =
7681 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7683 status = smb_set_file_end_of_file_info(conn, req,
7684 pdata,
7685 total_data,
7686 fsp,
7687 smb_fname,
7688 should_fail);
7689 break;
7692 case SMB_FILE_DISPOSITION_INFORMATION:
7693 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7695 #if 0
7696 /* JRA - We used to just ignore this on a path ?
7697 * Shouldn't this be invalid level on a pathname
7698 * based call ?
7700 if (tran_call != TRANSACT2_SETFILEINFO) {
7701 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7703 #endif
7704 status = smb_set_file_disposition_info(conn,
7705 pdata,
7706 total_data,
7707 fsp,
7708 smb_fname);
7709 break;
7712 case SMB_FILE_POSITION_INFORMATION:
7714 status = smb_file_position_information(conn,
7715 pdata,
7716 total_data,
7717 fsp);
7718 break;
7721 case SMB_FILE_FULL_EA_INFORMATION:
7723 status = smb_set_file_full_ea_info(conn,
7724 pdata,
7725 total_data,
7726 fsp);
7727 break;
7730 /* From tridge Samba4 :
7731 * MODE_INFORMATION in setfileinfo (I have no
7732 * idea what "mode information" on a file is - it takes a value of 0,
7733 * 2, 4 or 6. What could it be?).
7736 case SMB_FILE_MODE_INFORMATION:
7738 status = smb_file_mode_information(conn,
7739 pdata,
7740 total_data);
7741 break;
7745 * CIFS UNIX extensions.
7748 case SMB_SET_FILE_UNIX_BASIC:
7750 status = smb_set_file_unix_basic(conn, req,
7751 pdata,
7752 total_data,
7753 fsp,
7754 smb_fname);
7755 break;
7758 case SMB_SET_FILE_UNIX_INFO2:
7760 status = smb_set_file_unix_info2(conn, req,
7761 pdata,
7762 total_data,
7763 fsp,
7764 smb_fname);
7765 break;
7768 case SMB_SET_FILE_UNIX_LINK:
7770 if (fsp) {
7771 /* We must have a pathname for this. */
7772 return NT_STATUS_INVALID_LEVEL;
7774 status = smb_set_file_unix_link(conn, req, pdata,
7775 total_data, smb_fname);
7776 break;
7779 case SMB_SET_FILE_UNIX_HLINK:
7781 if (fsp) {
7782 /* We must have a pathname for this. */
7783 return NT_STATUS_INVALID_LEVEL;
7785 status = smb_set_file_unix_hlink(conn, req,
7786 pdata, total_data,
7787 smb_fname);
7788 break;
7791 case SMB_FILE_RENAME_INFORMATION:
7793 status = smb_file_rename_information(conn, req,
7794 pdata, total_data,
7795 fsp, smb_fname);
7796 break;
7799 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7801 /* SMB2 rename information. */
7802 status = smb2_file_rename_information(conn, req,
7803 pdata, total_data,
7804 fsp, smb_fname);
7805 break;
7808 case SMB_FILE_LINK_INFORMATION:
7810 status = smb_file_link_information(conn, req,
7811 pdata, total_data,
7812 fsp, smb_fname);
7813 break;
7816 #if defined(HAVE_POSIX_ACLS)
7817 case SMB_SET_POSIX_ACL:
7819 status = smb_set_posix_acl(conn,
7820 pdata,
7821 total_data,
7822 fsp,
7823 smb_fname);
7824 break;
7826 #endif
7828 case SMB_SET_POSIX_LOCK:
7830 if (!fsp) {
7831 return NT_STATUS_INVALID_LEVEL;
7833 status = smb_set_posix_lock(conn, req,
7834 pdata, total_data, fsp);
7835 break;
7838 case SMB_POSIX_PATH_OPEN:
7840 if (fsp) {
7841 /* We must have a pathname for this. */
7842 return NT_STATUS_INVALID_LEVEL;
7845 status = smb_posix_open(conn, req,
7846 ppdata,
7847 total_data,
7848 smb_fname,
7849 &data_return_size);
7850 break;
7853 case SMB_POSIX_PATH_UNLINK:
7855 if (fsp) {
7856 /* We must have a pathname for this. */
7857 return NT_STATUS_INVALID_LEVEL;
7860 status = smb_posix_unlink(conn, req,
7861 pdata,
7862 total_data,
7863 smb_fname);
7864 break;
7867 default:
7868 return NT_STATUS_INVALID_LEVEL;
7871 if (!NT_STATUS_IS_OK(status)) {
7872 return status;
7875 *ret_data_size = data_return_size;
7876 return NT_STATUS_OK;
7879 /****************************************************************************
7880 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7881 ****************************************************************************/
7883 static void call_trans2setfilepathinfo(connection_struct *conn,
7884 struct smb_request *req,
7885 unsigned int tran_call,
7886 char **pparams, int total_params,
7887 char **ppdata, int total_data,
7888 unsigned int max_data_bytes)
7890 char *params = *pparams;
7891 char *pdata = *ppdata;
7892 uint16 info_level;
7893 struct smb_filename *smb_fname = NULL;
7894 files_struct *fsp = NULL;
7895 NTSTATUS status = NT_STATUS_OK;
7896 int data_return_size = 0;
7898 if (!params) {
7899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7900 return;
7903 if (tran_call == TRANSACT2_SETFILEINFO) {
7904 if (total_params < 4) {
7905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7906 return;
7909 fsp = file_fsp(req, SVAL(params,0));
7910 /* Basic check for non-null fsp. */
7911 if (!check_fsp_open(conn, req, fsp)) {
7912 return;
7914 info_level = SVAL(params,2);
7916 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7917 &smb_fname);
7918 if (!NT_STATUS_IS_OK(status)) {
7919 reply_nterror(req, status);
7920 return;
7923 if(fsp->fh->fd == -1) {
7925 * This is actually a SETFILEINFO on a directory
7926 * handle (returned from an NT SMB). NT5.0 seems
7927 * to do this call. JRA.
7929 if (INFO_LEVEL_IS_UNIX(info_level)) {
7930 /* Always do lstat for UNIX calls. */
7931 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7932 DEBUG(3,("call_trans2setfilepathinfo: "
7933 "SMB_VFS_LSTAT of %s failed "
7934 "(%s)\n",
7935 smb_fname_str_dbg(smb_fname),
7936 strerror(errno)));
7937 reply_nterror(req, map_nt_error_from_unix(errno));
7938 return;
7940 } else {
7941 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7942 DEBUG(3,("call_trans2setfilepathinfo: "
7943 "fileinfo of %s failed (%s)\n",
7944 smb_fname_str_dbg(smb_fname),
7945 strerror(errno)));
7946 reply_nterror(req, map_nt_error_from_unix(errno));
7947 return;
7950 } else if (fsp->print_file) {
7952 * Doing a DELETE_ON_CLOSE should cancel a print job.
7954 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7955 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7957 DEBUG(3,("call_trans2setfilepathinfo: "
7958 "Cancelling print job (%s)\n",
7959 fsp_str_dbg(fsp)));
7961 SSVAL(params,0,0);
7962 send_trans2_replies(conn, req, params, 2,
7963 *ppdata, 0,
7964 max_data_bytes);
7965 return;
7966 } else {
7967 reply_nterror(req,
7968 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7969 return;
7971 } else {
7973 * Original code - this is an open file.
7975 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7976 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7977 "of fnum %d failed (%s)\n", fsp->fnum,
7978 strerror(errno)));
7979 reply_nterror(req, map_nt_error_from_unix(errno));
7980 return;
7983 } else {
7984 char *fname = NULL;
7986 /* set path info */
7987 if (total_params < 7) {
7988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7989 return;
7992 info_level = SVAL(params,0);
7993 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7994 total_params - 6, STR_TERMINATE,
7995 &status);
7996 if (!NT_STATUS_IS_OK(status)) {
7997 reply_nterror(req, status);
7998 return;
8001 status = filename_convert(req, conn,
8002 req->flags2 & FLAGS2_DFS_PATHNAMES,
8003 fname,
8005 NULL,
8006 &smb_fname);
8007 if (!NT_STATUS_IS_OK(status)) {
8008 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8009 reply_botherror(req,
8010 NT_STATUS_PATH_NOT_COVERED,
8011 ERRSRV, ERRbadpath);
8012 return;
8014 reply_nterror(req, status);
8015 return;
8018 if (INFO_LEVEL_IS_UNIX(info_level)) {
8020 * For CIFS UNIX extensions the target name may not exist.
8023 /* Always do lstat for UNIX calls. */
8024 SMB_VFS_LSTAT(conn, smb_fname);
8026 } else if (!VALID_STAT(smb_fname->st) &&
8027 SMB_VFS_STAT(conn, smb_fname)) {
8028 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8029 "%s failed (%s)\n",
8030 smb_fname_str_dbg(smb_fname),
8031 strerror(errno)));
8032 reply_nterror(req, map_nt_error_from_unix(errno));
8033 return;
8037 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8038 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8039 fsp ? fsp->fnum : -1, info_level,total_data));
8041 /* Realloc the parameter size */
8042 *pparams = (char *)SMB_REALLOC(*pparams,2);
8043 if (*pparams == NULL) {
8044 reply_nterror(req, NT_STATUS_NO_MEMORY);
8045 return;
8047 params = *pparams;
8049 SSVAL(params,0,0);
8051 status = smbd_do_setfilepathinfo(conn, req, req,
8052 info_level,
8053 fsp,
8054 smb_fname,
8055 ppdata, total_data,
8056 &data_return_size);
8057 if (!NT_STATUS_IS_OK(status)) {
8058 if (open_was_deferred(req->sconn, req->mid)) {
8059 /* We have re-scheduled this call. */
8060 return;
8062 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8063 /* We have re-scheduled this call. */
8064 return;
8066 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8067 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8068 ERRSRV, ERRbadpath);
8069 return;
8071 if (info_level == SMB_POSIX_PATH_OPEN) {
8072 reply_openerror(req, status);
8073 return;
8076 reply_nterror(req, status);
8077 return;
8080 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8081 max_data_bytes);
8083 return;
8086 /****************************************************************************
8087 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8088 ****************************************************************************/
8090 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8091 char **pparams, int total_params,
8092 char **ppdata, int total_data,
8093 unsigned int max_data_bytes)
8095 struct smb_filename *smb_dname = NULL;
8096 char *params = *pparams;
8097 char *pdata = *ppdata;
8098 char *directory = NULL;
8099 NTSTATUS status = NT_STATUS_OK;
8100 struct ea_list *ea_list = NULL;
8101 TALLOC_CTX *ctx = talloc_tos();
8103 if (!CAN_WRITE(conn)) {
8104 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8105 return;
8108 if (total_params < 5) {
8109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8110 return;
8113 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8114 total_params - 4, STR_TERMINATE,
8115 &status);
8116 if (!NT_STATUS_IS_OK(status)) {
8117 reply_nterror(req, status);
8118 return;
8121 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8123 status = filename_convert(ctx,
8124 conn,
8125 req->flags2 & FLAGS2_DFS_PATHNAMES,
8126 directory,
8128 NULL,
8129 &smb_dname);
8131 if (!NT_STATUS_IS_OK(status)) {
8132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8133 reply_botherror(req,
8134 NT_STATUS_PATH_NOT_COVERED,
8135 ERRSRV, ERRbadpath);
8136 return;
8138 reply_nterror(req, status);
8139 return;
8143 * OS/2 workplace shell seems to send SET_EA requests of "null"
8144 * length (4 bytes containing IVAL 4).
8145 * They seem to have no effect. Bug #3212. JRA.
8148 if (total_data && (total_data != 4)) {
8149 /* Any data in this call is an EA list. */
8150 if (total_data < 10) {
8151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8152 goto out;
8155 if (IVAL(pdata,0) > total_data) {
8156 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8157 IVAL(pdata,0), (unsigned int)total_data));
8158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8159 goto out;
8162 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8163 total_data - 4);
8164 if (!ea_list) {
8165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8166 goto out;
8169 if (!lp_ea_support(SNUM(conn))) {
8170 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8171 goto out;
8174 /* If total_data == 4 Windows doesn't care what values
8175 * are placed in that field, it just ignores them.
8176 * The System i QNTC IBM SMB client puts bad values here,
8177 * so ignore them. */
8179 status = create_directory(conn, req, smb_dname);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 reply_nterror(req, status);
8183 goto out;
8186 /* Try and set any given EA. */
8187 if (ea_list) {
8188 status = set_ea(conn, NULL, smb_dname, ea_list);
8189 if (!NT_STATUS_IS_OK(status)) {
8190 reply_nterror(req, status);
8191 goto out;
8195 /* Realloc the parameter and data sizes */
8196 *pparams = (char *)SMB_REALLOC(*pparams,2);
8197 if(*pparams == NULL) {
8198 reply_nterror(req, NT_STATUS_NO_MEMORY);
8199 goto out;
8201 params = *pparams;
8203 SSVAL(params,0,0);
8205 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8207 out:
8208 TALLOC_FREE(smb_dname);
8209 return;
8212 /****************************************************************************
8213 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8214 We don't actually do this - we just send a null response.
8215 ****************************************************************************/
8217 static void call_trans2findnotifyfirst(connection_struct *conn,
8218 struct smb_request *req,
8219 char **pparams, int total_params,
8220 char **ppdata, int total_data,
8221 unsigned int max_data_bytes)
8223 char *params = *pparams;
8224 uint16 info_level;
8226 if (total_params < 6) {
8227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8228 return;
8231 info_level = SVAL(params,4);
8232 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8234 switch (info_level) {
8235 case 1:
8236 case 2:
8237 break;
8238 default:
8239 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8240 return;
8243 /* Realloc the parameter and data sizes */
8244 *pparams = (char *)SMB_REALLOC(*pparams,6);
8245 if (*pparams == NULL) {
8246 reply_nterror(req, NT_STATUS_NO_MEMORY);
8247 return;
8249 params = *pparams;
8251 SSVAL(params,0,fnf_handle);
8252 SSVAL(params,2,0); /* No changes */
8253 SSVAL(params,4,0); /* No EA errors */
8255 fnf_handle++;
8257 if(fnf_handle == 0)
8258 fnf_handle = 257;
8260 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8262 return;
8265 /****************************************************************************
8266 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8267 changes). Currently this does nothing.
8268 ****************************************************************************/
8270 static void call_trans2findnotifynext(connection_struct *conn,
8271 struct smb_request *req,
8272 char **pparams, int total_params,
8273 char **ppdata, int total_data,
8274 unsigned int max_data_bytes)
8276 char *params = *pparams;
8278 DEBUG(3,("call_trans2findnotifynext\n"));
8280 /* Realloc the parameter and data sizes */
8281 *pparams = (char *)SMB_REALLOC(*pparams,4);
8282 if (*pparams == NULL) {
8283 reply_nterror(req, NT_STATUS_NO_MEMORY);
8284 return;
8286 params = *pparams;
8288 SSVAL(params,0,0); /* No changes */
8289 SSVAL(params,2,0); /* No EA errors */
8291 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8293 return;
8296 /****************************************************************************
8297 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8298 ****************************************************************************/
8300 static void call_trans2getdfsreferral(connection_struct *conn,
8301 struct smb_request *req,
8302 char **pparams, int total_params,
8303 char **ppdata, int total_data,
8304 unsigned int max_data_bytes)
8306 char *params = *pparams;
8307 char *pathname = NULL;
8308 int reply_size = 0;
8309 int max_referral_level;
8310 NTSTATUS status = NT_STATUS_OK;
8311 TALLOC_CTX *ctx = talloc_tos();
8313 DEBUG(10,("call_trans2getdfsreferral\n"));
8315 if (total_params < 3) {
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 return;
8320 max_referral_level = SVAL(params,0);
8322 if(!lp_host_msdfs()) {
8323 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8324 return;
8327 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8328 total_params - 2, STR_TERMINATE);
8329 if (!pathname) {
8330 reply_nterror(req, NT_STATUS_NOT_FOUND);
8331 return;
8333 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8334 ppdata,&status)) < 0) {
8335 reply_nterror(req, status);
8336 return;
8339 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8340 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8341 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8343 return;
8346 #define LMCAT_SPL 0x53
8347 #define LMFUNC_GETJOBID 0x60
8349 /****************************************************************************
8350 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8351 ****************************************************************************/
8353 static void call_trans2ioctl(connection_struct *conn,
8354 struct smb_request *req,
8355 char **pparams, int total_params,
8356 char **ppdata, int total_data,
8357 unsigned int max_data_bytes)
8359 char *pdata = *ppdata;
8360 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8362 /* check for an invalid fid before proceeding */
8364 if (!fsp) {
8365 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8366 return;
8369 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8370 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8371 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8372 if (*ppdata == NULL) {
8373 reply_nterror(req, NT_STATUS_NO_MEMORY);
8374 return;
8376 pdata = *ppdata;
8378 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8379 CAN ACCEPT THIS IN UNICODE. JRA. */
8381 /* Job number */
8382 if (fsp->print_file) {
8383 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8384 } else {
8385 SSVAL(pdata, 0, 0);
8387 srvstr_push(pdata, req->flags2, pdata + 2,
8388 lp_netbios_name(), 15,
8389 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8390 srvstr_push(pdata, req->flags2, pdata+18,
8391 lp_servicename(SNUM(conn)), 13,
8392 STR_ASCII|STR_TERMINATE); /* Service name */
8393 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8394 max_data_bytes);
8395 return;
8398 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8399 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8402 /****************************************************************************
8403 Reply to a SMBfindclose (stop trans2 directory search).
8404 ****************************************************************************/
8406 void reply_findclose(struct smb_request *req)
8408 int dptr_num;
8409 struct smbd_server_connection *sconn = req->sconn;
8411 START_PROFILE(SMBfindclose);
8413 if (req->wct < 1) {
8414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8415 END_PROFILE(SMBfindclose);
8416 return;
8419 dptr_num = SVALS(req->vwv+0, 0);
8421 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8423 dptr_close(sconn, &dptr_num);
8425 reply_outbuf(req, 0, 0);
8427 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8429 END_PROFILE(SMBfindclose);
8430 return;
8433 /****************************************************************************
8434 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8435 ****************************************************************************/
8437 void reply_findnclose(struct smb_request *req)
8439 int dptr_num;
8441 START_PROFILE(SMBfindnclose);
8443 if (req->wct < 1) {
8444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445 END_PROFILE(SMBfindnclose);
8446 return;
8449 dptr_num = SVAL(req->vwv+0, 0);
8451 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8453 /* We never give out valid handles for a
8454 findnotifyfirst - so any dptr_num is ok here.
8455 Just ignore it. */
8457 reply_outbuf(req, 0, 0);
8459 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8461 END_PROFILE(SMBfindnclose);
8462 return;
8465 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8466 struct trans_state *state)
8468 if (get_Protocol() >= PROTOCOL_NT1) {
8469 req->flags2 |= 0x40; /* IS_LONG_NAME */
8470 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8473 if (conn->encrypt_level == Required && !req->encrypted) {
8474 if (state->call != TRANSACT2_QFSINFO &&
8475 state->call != TRANSACT2_SETFSINFO) {
8476 DEBUG(0,("handle_trans2: encryption required "
8477 "with call 0x%x\n",
8478 (unsigned int)state->call));
8479 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8480 return;
8484 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8486 /* Now we must call the relevant TRANS2 function */
8487 switch(state->call) {
8488 case TRANSACT2_OPEN:
8490 START_PROFILE(Trans2_open);
8491 call_trans2open(conn, req,
8492 &state->param, state->total_param,
8493 &state->data, state->total_data,
8494 state->max_data_return);
8495 END_PROFILE(Trans2_open);
8496 break;
8499 case TRANSACT2_FINDFIRST:
8501 START_PROFILE(Trans2_findfirst);
8502 call_trans2findfirst(conn, req,
8503 &state->param, state->total_param,
8504 &state->data, state->total_data,
8505 state->max_data_return);
8506 END_PROFILE(Trans2_findfirst);
8507 break;
8510 case TRANSACT2_FINDNEXT:
8512 START_PROFILE(Trans2_findnext);
8513 call_trans2findnext(conn, req,
8514 &state->param, state->total_param,
8515 &state->data, state->total_data,
8516 state->max_data_return);
8517 END_PROFILE(Trans2_findnext);
8518 break;
8521 case TRANSACT2_QFSINFO:
8523 START_PROFILE(Trans2_qfsinfo);
8524 call_trans2qfsinfo(conn, req,
8525 &state->param, state->total_param,
8526 &state->data, state->total_data,
8527 state->max_data_return);
8528 END_PROFILE(Trans2_qfsinfo);
8529 break;
8532 case TRANSACT2_SETFSINFO:
8534 START_PROFILE(Trans2_setfsinfo);
8535 call_trans2setfsinfo(conn, req,
8536 &state->param, state->total_param,
8537 &state->data, state->total_data,
8538 state->max_data_return);
8539 END_PROFILE(Trans2_setfsinfo);
8540 break;
8543 case TRANSACT2_QPATHINFO:
8544 case TRANSACT2_QFILEINFO:
8546 START_PROFILE(Trans2_qpathinfo);
8547 call_trans2qfilepathinfo(conn, req, state->call,
8548 &state->param, state->total_param,
8549 &state->data, state->total_data,
8550 state->max_data_return);
8551 END_PROFILE(Trans2_qpathinfo);
8552 break;
8555 case TRANSACT2_SETPATHINFO:
8556 case TRANSACT2_SETFILEINFO:
8558 START_PROFILE(Trans2_setpathinfo);
8559 call_trans2setfilepathinfo(conn, req, state->call,
8560 &state->param, state->total_param,
8561 &state->data, state->total_data,
8562 state->max_data_return);
8563 END_PROFILE(Trans2_setpathinfo);
8564 break;
8567 case TRANSACT2_FINDNOTIFYFIRST:
8569 START_PROFILE(Trans2_findnotifyfirst);
8570 call_trans2findnotifyfirst(conn, req,
8571 &state->param, state->total_param,
8572 &state->data, state->total_data,
8573 state->max_data_return);
8574 END_PROFILE(Trans2_findnotifyfirst);
8575 break;
8578 case TRANSACT2_FINDNOTIFYNEXT:
8580 START_PROFILE(Trans2_findnotifynext);
8581 call_trans2findnotifynext(conn, req,
8582 &state->param, state->total_param,
8583 &state->data, state->total_data,
8584 state->max_data_return);
8585 END_PROFILE(Trans2_findnotifynext);
8586 break;
8589 case TRANSACT2_MKDIR:
8591 START_PROFILE(Trans2_mkdir);
8592 call_trans2mkdir(conn, req,
8593 &state->param, state->total_param,
8594 &state->data, state->total_data,
8595 state->max_data_return);
8596 END_PROFILE(Trans2_mkdir);
8597 break;
8600 case TRANSACT2_GET_DFS_REFERRAL:
8602 START_PROFILE(Trans2_get_dfs_referral);
8603 call_trans2getdfsreferral(conn, req,
8604 &state->param, state->total_param,
8605 &state->data, state->total_data,
8606 state->max_data_return);
8607 END_PROFILE(Trans2_get_dfs_referral);
8608 break;
8611 case TRANSACT2_IOCTL:
8613 START_PROFILE(Trans2_ioctl);
8614 call_trans2ioctl(conn, req,
8615 &state->param, state->total_param,
8616 &state->data, state->total_data,
8617 state->max_data_return);
8618 END_PROFILE(Trans2_ioctl);
8619 break;
8622 default:
8623 /* Error in request */
8624 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8625 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8629 /****************************************************************************
8630 Reply to a SMBtrans2.
8631 ****************************************************************************/
8633 void reply_trans2(struct smb_request *req)
8635 connection_struct *conn = req->conn;
8636 unsigned int dsoff;
8637 unsigned int dscnt;
8638 unsigned int psoff;
8639 unsigned int pscnt;
8640 unsigned int tran_call;
8641 struct trans_state *state;
8642 NTSTATUS result;
8644 START_PROFILE(SMBtrans2);
8646 if (req->wct < 14) {
8647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8648 END_PROFILE(SMBtrans2);
8649 return;
8652 dsoff = SVAL(req->vwv+12, 0);
8653 dscnt = SVAL(req->vwv+11, 0);
8654 psoff = SVAL(req->vwv+10, 0);
8655 pscnt = SVAL(req->vwv+9, 0);
8656 tran_call = SVAL(req->vwv+14, 0);
8658 result = allow_new_trans(conn->pending_trans, req->mid);
8659 if (!NT_STATUS_IS_OK(result)) {
8660 DEBUG(2, ("Got invalid trans2 request: %s\n",
8661 nt_errstr(result)));
8662 reply_nterror(req, result);
8663 END_PROFILE(SMBtrans2);
8664 return;
8667 if (IS_IPC(conn)) {
8668 switch (tran_call) {
8669 /* List the allowed trans2 calls on IPC$ */
8670 case TRANSACT2_OPEN:
8671 case TRANSACT2_GET_DFS_REFERRAL:
8672 case TRANSACT2_QFILEINFO:
8673 case TRANSACT2_QFSINFO:
8674 case TRANSACT2_SETFSINFO:
8675 break;
8676 default:
8677 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8678 END_PROFILE(SMBtrans2);
8679 return;
8683 if ((state = talloc(conn, struct trans_state)) == NULL) {
8684 DEBUG(0, ("talloc failed\n"));
8685 reply_nterror(req, NT_STATUS_NO_MEMORY);
8686 END_PROFILE(SMBtrans2);
8687 return;
8690 state->cmd = SMBtrans2;
8692 state->mid = req->mid;
8693 state->vuid = req->vuid;
8694 state->setup_count = SVAL(req->vwv+13, 0);
8695 state->setup = NULL;
8696 state->total_param = SVAL(req->vwv+0, 0);
8697 state->param = NULL;
8698 state->total_data = SVAL(req->vwv+1, 0);
8699 state->data = NULL;
8700 state->max_param_return = SVAL(req->vwv+2, 0);
8701 state->max_data_return = SVAL(req->vwv+3, 0);
8702 state->max_setup_return = SVAL(req->vwv+4, 0);
8703 state->close_on_completion = BITSETW(req->vwv+5, 0);
8704 state->one_way = BITSETW(req->vwv+5, 1);
8706 state->call = tran_call;
8708 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8709 is so as a sanity check */
8710 if (state->setup_count != 1) {
8712 * Need to have rc=0 for ioctl to get job id for OS/2.
8713 * Network printing will fail if function is not successful.
8714 * Similar function in reply.c will be used if protocol
8715 * is LANMAN1.0 instead of LM1.2X002.
8716 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8717 * outbuf doesn't have to be set(only job id is used).
8719 if ( (state->setup_count == 4)
8720 && (tran_call == TRANSACT2_IOCTL)
8721 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8722 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8723 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8724 } else {
8725 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8726 DEBUG(2,("Transaction is %d\n",tran_call));
8727 TALLOC_FREE(state);
8728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8729 END_PROFILE(SMBtrans2);
8730 return;
8734 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8735 goto bad_param;
8737 if (state->total_data) {
8739 if (trans_oob(state->total_data, 0, dscnt)
8740 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8741 goto bad_param;
8744 /* Can't use talloc here, the core routines do realloc on the
8745 * params and data. */
8746 state->data = (char *)SMB_MALLOC(state->total_data);
8747 if (state->data == NULL) {
8748 DEBUG(0,("reply_trans2: data malloc fail for %u "
8749 "bytes !\n", (unsigned int)state->total_data));
8750 TALLOC_FREE(state);
8751 reply_nterror(req, NT_STATUS_NO_MEMORY);
8752 END_PROFILE(SMBtrans2);
8753 return;
8756 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8759 if (state->total_param) {
8761 if (trans_oob(state->total_param, 0, pscnt)
8762 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8763 goto bad_param;
8766 /* Can't use talloc here, the core routines do realloc on the
8767 * params and data. */
8768 state->param = (char *)SMB_MALLOC(state->total_param);
8769 if (state->param == NULL) {
8770 DEBUG(0,("reply_trans: param malloc fail for %u "
8771 "bytes !\n", (unsigned int)state->total_param));
8772 SAFE_FREE(state->data);
8773 TALLOC_FREE(state);
8774 reply_nterror(req, NT_STATUS_NO_MEMORY);
8775 END_PROFILE(SMBtrans2);
8776 return;
8779 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8782 state->received_data = dscnt;
8783 state->received_param = pscnt;
8785 if ((state->received_param == state->total_param) &&
8786 (state->received_data == state->total_data)) {
8788 handle_trans2(conn, req, state);
8790 SAFE_FREE(state->data);
8791 SAFE_FREE(state->param);
8792 TALLOC_FREE(state);
8793 END_PROFILE(SMBtrans2);
8794 return;
8797 DLIST_ADD(conn->pending_trans, state);
8799 /* We need to send an interim response then receive the rest
8800 of the parameter/data bytes */
8801 reply_outbuf(req, 0, 0);
8802 show_msg((char *)req->outbuf);
8803 END_PROFILE(SMBtrans2);
8804 return;
8806 bad_param:
8808 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8809 SAFE_FREE(state->data);
8810 SAFE_FREE(state->param);
8811 TALLOC_FREE(state);
8812 END_PROFILE(SMBtrans2);
8813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8817 /****************************************************************************
8818 Reply to a SMBtranss2
8819 ****************************************************************************/
8821 void reply_transs2(struct smb_request *req)
8823 connection_struct *conn = req->conn;
8824 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8825 struct trans_state *state;
8827 START_PROFILE(SMBtranss2);
8829 show_msg((const char *)req->inbuf);
8831 if (req->wct < 8) {
8832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8833 END_PROFILE(SMBtranss2);
8834 return;
8837 for (state = conn->pending_trans; state != NULL;
8838 state = state->next) {
8839 if (state->mid == req->mid) {
8840 break;
8844 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8846 END_PROFILE(SMBtranss2);
8847 return;
8850 /* Revise state->total_param and state->total_data in case they have
8851 changed downwards */
8853 if (SVAL(req->vwv+0, 0) < state->total_param)
8854 state->total_param = SVAL(req->vwv+0, 0);
8855 if (SVAL(req->vwv+1, 0) < state->total_data)
8856 state->total_data = SVAL(req->vwv+1, 0);
8858 pcnt = SVAL(req->vwv+2, 0);
8859 poff = SVAL(req->vwv+3, 0);
8860 pdisp = SVAL(req->vwv+4, 0);
8862 dcnt = SVAL(req->vwv+5, 0);
8863 doff = SVAL(req->vwv+6, 0);
8864 ddisp = SVAL(req->vwv+7, 0);
8866 state->received_param += pcnt;
8867 state->received_data += dcnt;
8869 if ((state->received_data > state->total_data) ||
8870 (state->received_param > state->total_param))
8871 goto bad_param;
8873 if (pcnt) {
8874 if (trans_oob(state->total_param, pdisp, pcnt)
8875 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8876 goto bad_param;
8878 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8881 if (dcnt) {
8882 if (trans_oob(state->total_data, ddisp, dcnt)
8883 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8884 goto bad_param;
8886 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8889 if ((state->received_param < state->total_param) ||
8890 (state->received_data < state->total_data)) {
8891 END_PROFILE(SMBtranss2);
8892 return;
8895 handle_trans2(conn, req, state);
8897 DLIST_REMOVE(conn->pending_trans, state);
8898 SAFE_FREE(state->data);
8899 SAFE_FREE(state->param);
8900 TALLOC_FREE(state);
8902 END_PROFILE(SMBtranss2);
8903 return;
8905 bad_param:
8907 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8908 DLIST_REMOVE(conn->pending_trans, state);
8909 SAFE_FREE(state->data);
8910 SAFE_FREE(state->param);
8911 TALLOC_FREE(state);
8912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8913 END_PROFILE(SMBtranss2);
8914 return;