s3-torture/denytest.c: replace cli_read_old() with cli_read()
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob90eb40a62f4d539d8958c845451b30a0230e3ae4
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, deny_mode, open_ofun,
1086 &access_mask, &share_mode,
1087 &create_disposition,
1088 &create_options,
1089 &private_flags)) {
1090 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1091 goto out;
1094 /* Any data in this call is an EA list. */
1095 if (total_data && (total_data != 4)) {
1096 if (total_data < 10) {
1097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1098 goto out;
1101 if (IVAL(pdata,0) > total_data) {
1102 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1103 IVAL(pdata,0), (unsigned int)total_data));
1104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1105 goto out;
1108 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1109 total_data - 4);
1110 if (!ea_list) {
1111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1112 goto out;
1115 if (!lp_ea_support(SNUM(conn))) {
1116 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1117 goto out;
1121 status = SMB_VFS_CREATE_FILE(
1122 conn, /* conn */
1123 req, /* req */
1124 0, /* root_dir_fid */
1125 smb_fname, /* fname */
1126 access_mask, /* access_mask */
1127 share_mode, /* share_access */
1128 create_disposition, /* create_disposition*/
1129 create_options, /* create_options */
1130 open_attr, /* file_attributes */
1131 oplock_request, /* oplock_request */
1132 open_size, /* allocation_size */
1133 private_flags,
1134 NULL, /* sd */
1135 ea_list, /* ea_list */
1136 &fsp, /* result */
1137 &smb_action); /* psbuf */
1139 if (!NT_STATUS_IS_OK(status)) {
1140 if (open_was_deferred(req->mid)) {
1141 /* We have re-scheduled this call. */
1142 goto out;
1144 reply_openerror(req, status);
1145 goto out;
1148 size = get_file_size_stat(&smb_fname->st);
1149 fattr = dos_mode(conn, smb_fname);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 inode = smb_fname->st.st_ex_ino;
1152 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1153 close_file(req, fsp, ERROR_CLOSE);
1154 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1155 goto out;
1158 /* Realloc the size of parameters and data we will return */
1159 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1160 if(*pparams == NULL ) {
1161 reply_nterror(req, NT_STATUS_NO_MEMORY);
1162 goto out;
1164 params = *pparams;
1166 SSVAL(params,0,fsp->fnum);
1167 SSVAL(params,2,fattr);
1168 srv_put_dos_date2(params,4, mtime);
1169 SIVAL(params,8, (uint32)size);
1170 SSVAL(params,12,deny_mode);
1171 SSVAL(params,14,0); /* open_type - file or directory. */
1172 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1174 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1175 smb_action |= EXTENDED_OPLOCK_GRANTED;
1178 SSVAL(params,18,smb_action);
1181 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1183 SIVAL(params,20,inode);
1184 SSVAL(params,24,0); /* Padding. */
1185 if (flags & 8) {
1186 uint32 ea_size = estimate_ea_size(conn, fsp,
1187 fsp->fsp_name->base_name);
1188 SIVAL(params, 26, ea_size);
1189 } else {
1190 SIVAL(params, 26, 0);
1193 /* Send the required number of replies */
1194 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1195 out:
1196 TALLOC_FREE(smb_fname);
1199 /*********************************************************
1200 Routine to check if a given string matches exactly.
1201 as a special case a mask of "." does NOT match. That
1202 is required for correct wildcard semantics
1203 Case can be significant or not.
1204 **********************************************************/
1206 static bool exact_match(bool has_wild,
1207 bool case_sensitive,
1208 const char *str,
1209 const char *mask)
1211 if (mask[0] == '.' && mask[1] == 0) {
1212 return false;
1215 if (has_wild) {
1216 return false;
1219 if (case_sensitive) {
1220 return strcmp(str,mask)==0;
1221 } else {
1222 return strcasecmp_m(str,mask) == 0;
1226 /****************************************************************************
1227 Return the filetype for UNIX extensions.
1228 ****************************************************************************/
1230 static uint32 unix_filetype(mode_t mode)
1232 if(S_ISREG(mode))
1233 return UNIX_TYPE_FILE;
1234 else if(S_ISDIR(mode))
1235 return UNIX_TYPE_DIR;
1236 #ifdef S_ISLNK
1237 else if(S_ISLNK(mode))
1238 return UNIX_TYPE_SYMLINK;
1239 #endif
1240 #ifdef S_ISCHR
1241 else if(S_ISCHR(mode))
1242 return UNIX_TYPE_CHARDEV;
1243 #endif
1244 #ifdef S_ISBLK
1245 else if(S_ISBLK(mode))
1246 return UNIX_TYPE_BLKDEV;
1247 #endif
1248 #ifdef S_ISFIFO
1249 else if(S_ISFIFO(mode))
1250 return UNIX_TYPE_FIFO;
1251 #endif
1252 #ifdef S_ISSOCK
1253 else if(S_ISSOCK(mode))
1254 return UNIX_TYPE_SOCKET;
1255 #endif
1257 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1258 return UNIX_TYPE_UNKNOWN;
1261 /****************************************************************************
1262 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1263 ****************************************************************************/
1265 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1267 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1268 const SMB_STRUCT_STAT *psbuf,
1269 uint32 perms,
1270 enum perm_type ptype,
1271 mode_t *ret_perms)
1273 mode_t ret = 0;
1275 if (perms == SMB_MODE_NO_CHANGE) {
1276 if (!VALID_STAT(*psbuf)) {
1277 return NT_STATUS_INVALID_PARAMETER;
1278 } else {
1279 *ret_perms = psbuf->st_ex_mode;
1280 return NT_STATUS_OK;
1284 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1285 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1286 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1287 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1288 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1289 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1290 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1291 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1292 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1293 #ifdef S_ISVTX
1294 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1295 #endif
1296 #ifdef S_ISGID
1297 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1298 #endif
1299 #ifdef S_ISUID
1300 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1301 #endif
1303 switch (ptype) {
1304 case PERM_NEW_FILE:
1305 /* Apply mode mask */
1306 ret &= lp_create_mask(SNUM(conn));
1307 /* Add in force bits */
1308 ret |= lp_force_create_mode(SNUM(conn));
1309 break;
1310 case PERM_NEW_DIR:
1311 ret &= lp_dir_mask(SNUM(conn));
1312 /* Add in force bits */
1313 ret |= lp_force_dir_mode(SNUM(conn));
1314 break;
1315 case PERM_EXISTING_FILE:
1316 /* Apply mode mask */
1317 ret &= lp_security_mask(SNUM(conn));
1318 /* Add in force bits */
1319 ret |= lp_force_security_mode(SNUM(conn));
1320 break;
1321 case PERM_EXISTING_DIR:
1322 /* Apply mode mask */
1323 ret &= lp_dir_security_mask(SNUM(conn));
1324 /* Add in force bits */
1325 ret |= lp_force_dir_security_mode(SNUM(conn));
1326 break;
1329 *ret_perms = ret;
1330 return NT_STATUS_OK;
1333 /****************************************************************************
1334 Needed to show the msdfs symlinks as directories. Modifies psbuf
1335 to be a directory if it's a msdfs link.
1336 ****************************************************************************/
1338 static bool check_msdfs_link(connection_struct *conn,
1339 const char *pathname,
1340 SMB_STRUCT_STAT *psbuf)
1342 int saved_errno = errno;
1343 if(lp_host_msdfs() &&
1344 lp_msdfs_root(SNUM(conn)) &&
1345 is_msdfs_link(conn, pathname, psbuf)) {
1347 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1348 "as a directory\n",
1349 pathname));
1350 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1351 errno = saved_errno;
1352 return true;
1354 errno = saved_errno;
1355 return false;
1359 /****************************************************************************
1360 Get a level dependent lanman2 dir entry.
1361 ****************************************************************************/
1363 struct smbd_dirptr_lanman2_state {
1364 connection_struct *conn;
1365 uint32_t info_level;
1366 bool check_mangled_names;
1367 bool has_wild;
1368 bool got_exact_match;
1371 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1372 void *private_data,
1373 const char *dname,
1374 const char *mask,
1375 char **_fname)
1377 struct smbd_dirptr_lanman2_state *state =
1378 (struct smbd_dirptr_lanman2_state *)private_data;
1379 bool ok;
1380 char mangled_name[13]; /* mangled 8.3 name. */
1381 bool got_match;
1382 const char *fname;
1384 /* Mangle fname if it's an illegal name. */
1385 if (mangle_must_mangle(dname, state->conn->params)) {
1386 ok = name_to_8_3(dname, mangled_name,
1387 true, state->conn->params);
1388 if (!ok) {
1389 return false;
1391 fname = mangled_name;
1392 } else {
1393 fname = dname;
1396 got_match = exact_match(state->has_wild,
1397 state->conn->case_sensitive,
1398 fname, mask);
1399 state->got_exact_match = got_match;
1400 if (!got_match) {
1401 got_match = mask_match(fname, mask,
1402 state->conn->case_sensitive);
1405 if(!got_match && state->check_mangled_names &&
1406 !mangle_is_8_3(fname, false, state->conn->params)) {
1408 * It turns out that NT matches wildcards against
1409 * both long *and* short names. This may explain some
1410 * of the wildcard wierdness from old DOS clients
1411 * that some people have been seeing.... JRA.
1413 /* Force the mangling into 8.3. */
1414 ok = name_to_8_3(fname, mangled_name,
1415 false, state->conn->params);
1416 if (!ok) {
1417 return false;
1420 got_match = exact_match(state->has_wild,
1421 state->conn->case_sensitive,
1422 mangled_name, mask);
1423 state->got_exact_match = got_match;
1424 if (!got_match) {
1425 got_match = mask_match(mangled_name, mask,
1426 state->conn->case_sensitive);
1430 if (!got_match) {
1431 return false;
1434 *_fname = talloc_strdup(ctx, fname);
1435 if (*_fname == NULL) {
1436 return false;
1439 return true;
1442 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1443 void *private_data,
1444 struct smb_filename *smb_fname,
1445 uint32_t *_mode)
1447 struct smbd_dirptr_lanman2_state *state =
1448 (struct smbd_dirptr_lanman2_state *)private_data;
1449 bool ms_dfs_link = false;
1450 uint32_t mode = 0;
1452 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1453 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1454 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1455 "Couldn't lstat [%s] (%s)\n",
1456 smb_fname_str_dbg(smb_fname),
1457 strerror(errno)));
1458 return false;
1460 } else if (!VALID_STAT(smb_fname->st) &&
1461 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1462 /* Needed to show the msdfs symlinks as
1463 * directories */
1465 ms_dfs_link = check_msdfs_link(state->conn,
1466 smb_fname->base_name,
1467 &smb_fname->st);
1468 if (!ms_dfs_link) {
1469 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1470 "Couldn't stat [%s] (%s)\n",
1471 smb_fname_str_dbg(smb_fname),
1472 strerror(errno)));
1473 return false;
1477 if (ms_dfs_link) {
1478 mode = dos_mode_msdfs(state->conn, smb_fname);
1479 } else {
1480 mode = dos_mode(state->conn, smb_fname);
1483 *_mode = mode;
1484 return true;
1487 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1488 connection_struct *conn,
1489 uint16_t flags2,
1490 uint32_t info_level,
1491 struct ea_list *name_list,
1492 bool check_mangled_names,
1493 bool requires_resume_key,
1494 uint32_t mode,
1495 const char *fname,
1496 const struct smb_filename *smb_fname,
1497 int space_remaining,
1498 uint8_t align,
1499 bool do_pad,
1500 char *base_data,
1501 char **ppdata,
1502 char *end_data,
1503 bool *out_of_space,
1504 uint64_t *last_entry_off)
1506 char *p, *q, *pdata = *ppdata;
1507 uint32_t reskey=0;
1508 uint64_t file_size = 0;
1509 uint64_t allocation_size = 0;
1510 uint64_t file_index = 0;
1511 uint32_t len;
1512 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1513 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1514 time_t c_date = (time_t)0;
1515 char *nameptr;
1516 char *last_entry_ptr;
1517 bool was_8_3;
1518 int off;
1519 int pad = 0;
1521 *out_of_space = false;
1523 ZERO_STRUCT(mdate_ts);
1524 ZERO_STRUCT(adate_ts);
1525 ZERO_STRUCT(create_date_ts);
1526 ZERO_STRUCT(cdate_ts);
1528 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1529 file_size = get_file_size_stat(&smb_fname->st);
1531 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1533 file_index = get_FileIndex(conn, &smb_fname->st);
1535 mdate_ts = smb_fname->st.st_ex_mtime;
1536 adate_ts = smb_fname->st.st_ex_atime;
1537 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1538 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1540 if (lp_dos_filetime_resolution(SNUM(conn))) {
1541 dos_filetime_timespec(&create_date_ts);
1542 dos_filetime_timespec(&mdate_ts);
1543 dos_filetime_timespec(&adate_ts);
1544 dos_filetime_timespec(&cdate_ts);
1547 create_date = convert_timespec_to_time_t(create_date_ts);
1548 mdate = convert_timespec_to_time_t(mdate_ts);
1549 adate = convert_timespec_to_time_t(adate_ts);
1550 c_date = convert_timespec_to_time_t(cdate_ts);
1552 /* align the record */
1553 SMB_ASSERT(align >= 1);
1555 off = (int)PTR_DIFF(pdata, base_data);
1556 pad = (off + (align-1)) & ~(align-1);
1557 pad -= off;
1559 if (pad && pad > space_remaining) {
1560 *out_of_space = true;
1561 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1562 "for padding (wanted %u, had %d)\n",
1563 (unsigned int)pad,
1564 space_remaining ));
1565 return false; /* Not finished - just out of space */
1568 off += pad;
1569 /* initialize padding to 0 */
1570 if (pad) {
1571 memset(pdata, 0, pad);
1573 space_remaining -= pad;
1575 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1576 space_remaining ));
1578 pdata += pad;
1579 p = pdata;
1580 last_entry_ptr = p;
1582 pad = 0;
1583 off = 0;
1585 switch (info_level) {
1586 case SMB_FIND_INFO_STANDARD:
1587 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1588 if(requires_resume_key) {
1589 SIVAL(p,0,reskey);
1590 p += 4;
1592 srv_put_dos_date2(p,0,create_date);
1593 srv_put_dos_date2(p,4,adate);
1594 srv_put_dos_date2(p,8,mdate);
1595 SIVAL(p,12,(uint32)file_size);
1596 SIVAL(p,16,(uint32)allocation_size);
1597 SSVAL(p,20,mode);
1598 p += 23;
1599 nameptr = p;
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1601 p += ucs2_align(base_data, p, 0);
1603 len = srvstr_push(base_data, flags2, p,
1604 fname, PTR_DIFF(end_data, p),
1605 STR_TERMINATE);
1606 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1607 if (len > 2) {
1608 SCVAL(nameptr, -1, len - 2);
1609 } else {
1610 SCVAL(nameptr, -1, 0);
1612 } else {
1613 if (len > 1) {
1614 SCVAL(nameptr, -1, len - 1);
1615 } else {
1616 SCVAL(nameptr, -1, 0);
1619 p += len;
1620 break;
1622 case SMB_FIND_EA_SIZE:
1623 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1624 if (requires_resume_key) {
1625 SIVAL(p,0,reskey);
1626 p += 4;
1628 srv_put_dos_date2(p,0,create_date);
1629 srv_put_dos_date2(p,4,adate);
1630 srv_put_dos_date2(p,8,mdate);
1631 SIVAL(p,12,(uint32)file_size);
1632 SIVAL(p,16,(uint32)allocation_size);
1633 SSVAL(p,20,mode);
1635 unsigned int ea_size = estimate_ea_size(conn, NULL,
1636 smb_fname->base_name);
1637 SIVAL(p,22,ea_size); /* Extended attributes */
1639 p += 27;
1640 nameptr = p - 1;
1641 len = srvstr_push(base_data, flags2,
1642 p, fname, PTR_DIFF(end_data, p),
1643 STR_TERMINATE | STR_NOALIGN);
1644 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1645 if (len > 2) {
1646 len -= 2;
1647 } else {
1648 len = 0;
1650 } else {
1651 if (len > 1) {
1652 len -= 1;
1653 } else {
1654 len = 0;
1657 SCVAL(nameptr,0,len);
1658 p += len;
1659 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1660 break;
1662 case SMB_FIND_EA_LIST:
1664 struct ea_list *file_list = NULL;
1665 size_t ea_len = 0;
1667 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1668 if (!name_list) {
1669 return false;
1671 if (requires_resume_key) {
1672 SIVAL(p,0,reskey);
1673 p += 4;
1675 srv_put_dos_date2(p,0,create_date);
1676 srv_put_dos_date2(p,4,adate);
1677 srv_put_dos_date2(p,8,mdate);
1678 SIVAL(p,12,(uint32)file_size);
1679 SIVAL(p,16,(uint32)allocation_size);
1680 SSVAL(p,20,mode);
1681 p += 22; /* p now points to the EA area. */
1683 file_list = get_ea_list_from_file(ctx, conn, NULL,
1684 smb_fname->base_name,
1685 &ea_len);
1686 name_list = ea_list_union(name_list, file_list, &ea_len);
1688 /* We need to determine if this entry will fit in the space available. */
1689 /* Max string size is 255 bytes. */
1690 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1691 *out_of_space = true;
1692 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1693 "(wanted %u, had %d)\n",
1694 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1695 space_remaining ));
1696 return False; /* Not finished - just out of space */
1699 /* Push the ea_data followed by the name. */
1700 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1701 nameptr = p;
1702 len = srvstr_push(base_data, flags2,
1703 p + 1, fname, PTR_DIFF(end_data, p+1),
1704 STR_TERMINATE | STR_NOALIGN);
1705 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1706 if (len > 2) {
1707 len -= 2;
1708 } else {
1709 len = 0;
1711 } else {
1712 if (len > 1) {
1713 len -= 1;
1714 } else {
1715 len = 0;
1718 SCVAL(nameptr,0,len);
1719 p += len + 1;
1720 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1721 break;
1724 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1725 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1726 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1727 p += 4;
1728 SIVAL(p,0,reskey); p += 4;
1729 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1730 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1733 SOFF_T(p,0,file_size); p += 8;
1734 SOFF_T(p,0,allocation_size); p += 8;
1735 SIVAL(p,0,mode); p += 4;
1736 q = p; p += 4; /* q is placeholder for name length. */
1738 unsigned int ea_size = estimate_ea_size(conn, NULL,
1739 smb_fname->base_name);
1740 SIVAL(p,0,ea_size); /* Extended attributes */
1741 p += 4;
1743 /* Clear the short name buffer. This is
1744 * IMPORTANT as not doing so will trigger
1745 * a Win2k client bug. JRA.
1747 if (!was_8_3 && check_mangled_names) {
1748 char mangled_name[13]; /* mangled 8.3 name. */
1749 if (!name_to_8_3(fname,mangled_name,True,
1750 conn->params)) {
1751 /* Error - mangle failed ! */
1752 memset(mangled_name,'\0',12);
1754 mangled_name[12] = 0;
1755 len = srvstr_push(base_data, flags2,
1756 p+2, mangled_name, 24,
1757 STR_UPPER|STR_UNICODE);
1758 if (len < 24) {
1759 memset(p + 2 + len,'\0',24 - len);
1761 SSVAL(p, 0, len);
1762 } else {
1763 memset(p,'\0',26);
1765 p += 2 + 24;
1766 len = srvstr_push(base_data, flags2, p,
1767 fname, PTR_DIFF(end_data, p),
1768 STR_TERMINATE_ASCII);
1769 SIVAL(q,0,len);
1770 p += len;
1772 len = PTR_DIFF(p, pdata);
1773 pad = (len + (align-1)) & ~(align-1);
1775 * offset to the next entry, the caller
1776 * will overwrite it for the last entry
1777 * that's why we always include the padding
1779 SIVAL(pdata,0,pad);
1781 * set padding to zero
1783 if (do_pad) {
1784 memset(p, 0, pad - len);
1785 p = pdata + pad;
1786 } else {
1787 p = pdata + len;
1789 break;
1791 case SMB_FIND_FILE_DIRECTORY_INFO:
1792 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1793 p += 4;
1794 SIVAL(p,0,reskey); p += 4;
1795 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1799 SOFF_T(p,0,file_size); p += 8;
1800 SOFF_T(p,0,allocation_size); p += 8;
1801 SIVAL(p,0,mode); p += 4;
1802 len = srvstr_push(base_data, flags2,
1803 p + 4, fname, PTR_DIFF(end_data, p+4),
1804 STR_TERMINATE_ASCII);
1805 SIVAL(p,0,len);
1806 p += 4 + len;
1808 len = PTR_DIFF(p, pdata);
1809 pad = (len + (align-1)) & ~(align-1);
1811 * offset to the next entry, the caller
1812 * will overwrite it for the last entry
1813 * that's why we always include the padding
1815 SIVAL(pdata,0,pad);
1817 * set padding to zero
1819 if (do_pad) {
1820 memset(p, 0, pad - len);
1821 p = pdata + pad;
1822 } else {
1823 p = pdata + len;
1825 break;
1827 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1828 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1829 p += 4;
1830 SIVAL(p,0,reskey); p += 4;
1831 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1832 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1835 SOFF_T(p,0,file_size); p += 8;
1836 SOFF_T(p,0,allocation_size); p += 8;
1837 SIVAL(p,0,mode); p += 4;
1838 q = p; p += 4; /* q is placeholder for name length. */
1840 unsigned int ea_size = estimate_ea_size(conn, NULL,
1841 smb_fname->base_name);
1842 SIVAL(p,0,ea_size); /* Extended attributes */
1843 p +=4;
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1848 SIVAL(q, 0, len);
1849 p += len;
1851 len = PTR_DIFF(p, pdata);
1852 pad = (len + (align-1)) & ~(align-1);
1854 * offset to the next entry, the caller
1855 * will overwrite it for the last entry
1856 * that's why we always include the padding
1858 SIVAL(pdata,0,pad);
1860 * set padding to zero
1862 if (do_pad) {
1863 memset(p, 0, pad - len);
1864 p = pdata + pad;
1865 } else {
1866 p = pdata + len;
1868 break;
1870 case SMB_FIND_FILE_NAMES_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1872 p += 4;
1873 SIVAL(p,0,reskey); p += 4;
1874 p += 4;
1875 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1876 acl on a dir (tridge) */
1877 len = srvstr_push(base_data, flags2, p,
1878 fname, PTR_DIFF(end_data, p),
1879 STR_TERMINATE_ASCII);
1880 SIVAL(p, -4, len);
1881 p += len;
1883 len = PTR_DIFF(p, pdata);
1884 pad = (len + (align-1)) & ~(align-1);
1886 * offset to the next entry, the caller
1887 * will overwrite it for the last entry
1888 * that's why we always include the padding
1890 SIVAL(pdata,0,pad);
1892 * set padding to zero
1894 if (do_pad) {
1895 memset(p, 0, pad - len);
1896 p = pdata + pad;
1897 } else {
1898 p = pdata + len;
1900 break;
1902 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1903 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1904 p += 4;
1905 SIVAL(p,0,reskey); p += 4;
1906 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1910 SOFF_T(p,0,file_size); p += 8;
1911 SOFF_T(p,0,allocation_size); p += 8;
1912 SIVAL(p,0,mode); p += 4;
1913 q = p; p += 4; /* q is placeholder for name length. */
1915 unsigned int ea_size = estimate_ea_size(conn, NULL,
1916 smb_fname->base_name);
1917 SIVAL(p,0,ea_size); /* Extended attributes */
1918 p +=4;
1920 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1921 SBVAL(p,0,file_index); p += 8;
1922 len = srvstr_push(base_data, flags2, p,
1923 fname, PTR_DIFF(end_data, p),
1924 STR_TERMINATE_ASCII);
1925 SIVAL(q, 0, len);
1926 p += len;
1928 len = PTR_DIFF(p, pdata);
1929 pad = (len + (align-1)) & ~(align-1);
1931 * offset to the next entry, the caller
1932 * will overwrite it for the last entry
1933 * that's why we always include the padding
1935 SIVAL(pdata,0,pad);
1937 * set padding to zero
1939 if (do_pad) {
1940 memset(p, 0, pad - len);
1941 p = pdata + pad;
1942 } else {
1943 p = pdata + len;
1945 break;
1947 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1948 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1949 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1950 p += 4;
1951 SIVAL(p,0,reskey); p += 4;
1952 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1953 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1956 SOFF_T(p,0,file_size); p += 8;
1957 SOFF_T(p,0,allocation_size); p += 8;
1958 SIVAL(p,0,mode); p += 4;
1959 q = p; p += 4; /* q is placeholder for name length */
1961 unsigned int ea_size = estimate_ea_size(conn, NULL,
1962 smb_fname->base_name);
1963 SIVAL(p,0,ea_size); /* Extended attributes */
1964 p +=4;
1966 /* Clear the short name buffer. This is
1967 * IMPORTANT as not doing so will trigger
1968 * a Win2k client bug. JRA.
1970 if (!was_8_3 && check_mangled_names) {
1971 char mangled_name[13]; /* mangled 8.3 name. */
1972 if (!name_to_8_3(fname,mangled_name,True,
1973 conn->params)) {
1974 /* Error - mangle failed ! */
1975 memset(mangled_name,'\0',12);
1977 mangled_name[12] = 0;
1978 len = srvstr_push(base_data, flags2,
1979 p+2, mangled_name, 24,
1980 STR_UPPER|STR_UNICODE);
1981 SSVAL(p, 0, len);
1982 if (len < 24) {
1983 memset(p + 2 + len,'\0',24 - len);
1985 SSVAL(p, 0, len);
1986 } else {
1987 memset(p,'\0',26);
1989 p += 26;
1990 SSVAL(p,0,0); p += 2; /* Reserved ? */
1991 SBVAL(p,0,file_index); p += 8;
1992 len = srvstr_push(base_data, flags2, p,
1993 fname, PTR_DIFF(end_data, p),
1994 STR_TERMINATE_ASCII);
1995 SIVAL(q,0,len);
1996 p += len;
1998 len = PTR_DIFF(p, pdata);
1999 pad = (len + (align-1)) & ~(align-1);
2001 * offset to the next entry, the caller
2002 * will overwrite it for the last entry
2003 * that's why we always include the padding
2005 SIVAL(pdata,0,pad);
2007 * set padding to zero
2009 if (do_pad) {
2010 memset(p, 0, pad - len);
2011 p = pdata + pad;
2012 } else {
2013 p = pdata + len;
2015 break;
2017 /* CIFS UNIX Extension. */
2019 case SMB_FIND_FILE_UNIX:
2020 case SMB_FIND_FILE_UNIX_INFO2:
2021 p+= 4;
2022 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2024 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2026 if (info_level == SMB_FIND_FILE_UNIX) {
2027 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2028 p = store_file_unix_basic(conn, p,
2029 NULL, &smb_fname->st);
2030 len = srvstr_push(base_data, flags2, p,
2031 fname, PTR_DIFF(end_data, p),
2032 STR_TERMINATE);
2033 } else {
2034 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2035 p = store_file_unix_basic_info2(conn, p,
2036 NULL, &smb_fname->st);
2037 nameptr = p;
2038 p += 4;
2039 len = srvstr_push(base_data, flags2, p, fname,
2040 PTR_DIFF(end_data, p), 0);
2041 SIVAL(nameptr, 0, len);
2044 p += len;
2046 len = PTR_DIFF(p, pdata);
2047 pad = (len + (align-1)) & ~(align-1);
2049 * offset to the next entry, the caller
2050 * will overwrite it for the last entry
2051 * that's why we always include the padding
2053 SIVAL(pdata,0,pad);
2055 * set padding to zero
2057 if (do_pad) {
2058 memset(p, 0, pad - len);
2059 p = pdata + pad;
2060 } else {
2061 p = pdata + len;
2063 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2065 break;
2067 default:
2068 return false;
2071 if (PTR_DIFF(p,pdata) > space_remaining) {
2072 *out_of_space = true;
2073 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2074 "(wanted %u, had %d)\n",
2075 (unsigned int)PTR_DIFF(p,pdata),
2076 space_remaining ));
2077 return false; /* Not finished - just out of space */
2080 /* Setup the last entry pointer, as an offset from base_data */
2081 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2082 /* Advance the data pointer to the next slot */
2083 *ppdata = p;
2085 return true;
2088 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2089 connection_struct *conn,
2090 struct dptr_struct *dirptr,
2091 uint16 flags2,
2092 const char *path_mask,
2093 uint32 dirtype,
2094 int info_level,
2095 int requires_resume_key,
2096 bool dont_descend,
2097 bool ask_sharemode,
2098 uint8_t align,
2099 bool do_pad,
2100 char **ppdata,
2101 char *base_data,
2102 char *end_data,
2103 int space_remaining,
2104 bool *out_of_space,
2105 bool *got_exact_match,
2106 int *_last_entry_off,
2107 struct ea_list *name_list)
2109 const char *p;
2110 const char *mask = NULL;
2111 long prev_dirpos = 0;
2112 uint32_t mode = 0;
2113 char *fname = NULL;
2114 struct smb_filename *smb_fname = NULL;
2115 struct smbd_dirptr_lanman2_state state;
2116 bool ok;
2117 uint64_t last_entry_off = 0;
2119 ZERO_STRUCT(state);
2120 state.conn = conn;
2121 state.info_level = info_level;
2122 state.check_mangled_names = lp_manglednames(conn->params);
2123 state.has_wild = dptr_has_wild(dirptr);
2124 state.got_exact_match = false;
2126 *out_of_space = false;
2127 *got_exact_match = false;
2129 p = strrchr_m(path_mask,'/');
2130 if(p != NULL) {
2131 if(p[1] == '\0') {
2132 mask = "*.*";
2133 } else {
2134 mask = p+1;
2136 } else {
2137 mask = path_mask;
2140 ok = smbd_dirptr_get_entry(ctx,
2141 dirptr,
2142 mask,
2143 dirtype,
2144 dont_descend,
2145 ask_sharemode,
2146 smbd_dirptr_lanman2_match_fn,
2147 smbd_dirptr_lanman2_mode_fn,
2148 &state,
2149 &fname,
2150 &smb_fname,
2151 &mode,
2152 &prev_dirpos);
2153 if (!ok) {
2154 return false;
2157 *got_exact_match = state.got_exact_match;
2159 ok = smbd_marshall_dir_entry(ctx,
2160 conn,
2161 flags2,
2162 info_level,
2163 name_list,
2164 state.check_mangled_names,
2165 requires_resume_key,
2166 mode,
2167 fname,
2168 smb_fname,
2169 space_remaining,
2170 align,
2171 do_pad,
2172 base_data,
2173 ppdata,
2174 end_data,
2175 out_of_space,
2176 &last_entry_off);
2177 TALLOC_FREE(fname);
2178 TALLOC_FREE(smb_fname);
2179 if (*out_of_space) {
2180 dptr_SeekDir(dirptr, prev_dirpos);
2181 return false;
2183 if (!ok) {
2184 return false;
2187 *_last_entry_off = last_entry_off;
2188 return true;
2191 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2192 connection_struct *conn,
2193 struct dptr_struct *dirptr,
2194 uint16 flags2,
2195 const char *path_mask,
2196 uint32 dirtype,
2197 int info_level,
2198 bool requires_resume_key,
2199 bool dont_descend,
2200 bool ask_sharemode,
2201 char **ppdata,
2202 char *base_data,
2203 char *end_data,
2204 int space_remaining,
2205 bool *out_of_space,
2206 bool *got_exact_match,
2207 int *last_entry_off,
2208 struct ea_list *name_list)
2210 uint8_t align = 4;
2211 const bool do_pad = true;
2213 if (info_level >= 1 && info_level <= 3) {
2214 /* No alignment on earlier info levels. */
2215 align = 1;
2218 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2219 path_mask, dirtype, info_level,
2220 requires_resume_key, dont_descend, ask_sharemode,
2221 align, do_pad,
2222 ppdata, base_data, end_data,
2223 space_remaining,
2224 out_of_space, got_exact_match,
2225 last_entry_off, name_list);
2228 /****************************************************************************
2229 Reply to a TRANS2_FINDFIRST.
2230 ****************************************************************************/
2232 static void call_trans2findfirst(connection_struct *conn,
2233 struct smb_request *req,
2234 char **pparams, int total_params,
2235 char **ppdata, int total_data,
2236 unsigned int max_data_bytes)
2238 /* We must be careful here that we don't return more than the
2239 allowed number of data bytes. If this means returning fewer than
2240 maxentries then so be it. We assume that the redirector has
2241 enough room for the fixed number of parameter bytes it has
2242 requested. */
2243 struct smb_filename *smb_dname = NULL;
2244 char *params = *pparams;
2245 char *pdata = *ppdata;
2246 char *data_end;
2247 uint32 dirtype;
2248 int maxentries;
2249 uint16 findfirst_flags;
2250 bool close_after_first;
2251 bool close_if_end;
2252 bool requires_resume_key;
2253 int info_level;
2254 char *directory = NULL;
2255 char *mask = NULL;
2256 char *p;
2257 int last_entry_off=0;
2258 int dptr_num = -1;
2259 int numentries = 0;
2260 int i;
2261 bool finished = False;
2262 bool dont_descend = False;
2263 bool out_of_space = False;
2264 int space_remaining;
2265 bool mask_contains_wcard = False;
2266 struct ea_list *ea_list = NULL;
2267 NTSTATUS ntstatus = NT_STATUS_OK;
2268 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2269 TALLOC_CTX *ctx = talloc_tos();
2270 struct dptr_struct *dirptr = NULL;
2271 struct smbd_server_connection *sconn = req->sconn;
2273 if (total_params < 13) {
2274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2275 goto out;
2278 dirtype = SVAL(params,0);
2279 maxentries = SVAL(params,2);
2280 findfirst_flags = SVAL(params,4);
2281 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2282 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2283 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2284 info_level = SVAL(params,6);
2286 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2287 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2288 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2289 info_level, max_data_bytes));
2291 if (!maxentries) {
2292 /* W2K3 seems to treat zero as 1. */
2293 maxentries = 1;
2296 switch (info_level) {
2297 case SMB_FIND_INFO_STANDARD:
2298 case SMB_FIND_EA_SIZE:
2299 case SMB_FIND_EA_LIST:
2300 case SMB_FIND_FILE_DIRECTORY_INFO:
2301 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_NAMES_INFO:
2303 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2304 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2305 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2306 break;
2307 case SMB_FIND_FILE_UNIX:
2308 case SMB_FIND_FILE_UNIX_INFO2:
2309 /* Always use filesystem for UNIX mtime query. */
2310 ask_sharemode = false;
2311 if (!lp_unix_extensions()) {
2312 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2313 goto out;
2315 break;
2316 default:
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 goto out;
2321 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2322 params+12, total_params - 12,
2323 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2324 if (!NT_STATUS_IS_OK(ntstatus)) {
2325 reply_nterror(req, ntstatus);
2326 goto out;
2329 ntstatus = filename_convert(ctx, conn,
2330 req->flags2 & FLAGS2_DFS_PATHNAMES,
2331 directory,
2332 (UCF_SAVE_LCOMP |
2333 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2334 &mask_contains_wcard,
2335 &smb_dname);
2336 if (!NT_STATUS_IS_OK(ntstatus)) {
2337 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2338 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2339 ERRSRV, ERRbadpath);
2340 goto out;
2342 reply_nterror(req, ntstatus);
2343 goto out;
2346 mask = smb_dname->original_lcomp;
2348 directory = smb_dname->base_name;
2350 p = strrchr_m(directory,'/');
2351 if(p == NULL) {
2352 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2353 if((directory[0] == '.') && (directory[1] == '\0')) {
2354 mask = talloc_strdup(ctx,"*");
2355 if (!mask) {
2356 reply_nterror(req, NT_STATUS_NO_MEMORY);
2357 goto out;
2359 mask_contains_wcard = True;
2361 } else {
2362 *p = 0;
2365 if (p == NULL || p == directory) {
2366 /* Ensure we don't have a directory name of "". */
2367 directory = talloc_strdup(talloc_tos(), ".");
2368 if (!directory) {
2369 reply_nterror(req, NT_STATUS_NO_MEMORY);
2370 goto out;
2374 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2376 if (info_level == SMB_FIND_EA_LIST) {
2377 uint32 ea_size;
2379 if (total_data < 4) {
2380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2381 goto out;
2384 ea_size = IVAL(pdata,0);
2385 if (ea_size != total_data) {
2386 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2387 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2389 goto out;
2392 if (!lp_ea_support(SNUM(conn))) {
2393 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2394 goto out;
2397 /* Pull out the list of names. */
2398 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2399 if (!ea_list) {
2400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2401 goto out;
2405 *ppdata = (char *)SMB_REALLOC(
2406 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2407 if(*ppdata == NULL ) {
2408 reply_nterror(req, NT_STATUS_NO_MEMORY);
2409 goto out;
2411 pdata = *ppdata;
2412 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2414 /* Realloc the params space */
2415 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2416 if (*pparams == NULL) {
2417 reply_nterror(req, NT_STATUS_NO_MEMORY);
2418 goto out;
2420 params = *pparams;
2422 /* Save the wildcard match and attribs we are using on this directory -
2423 needed as lanman2 assumes these are being saved between calls */
2425 ntstatus = dptr_create(conn,
2426 NULL, /* fsp */
2427 directory,
2428 False,
2429 True,
2430 req->smbpid,
2431 mask,
2432 mask_contains_wcard,
2433 dirtype,
2434 &dirptr);
2436 if (!NT_STATUS_IS_OK(ntstatus)) {
2437 reply_nterror(req, ntstatus);
2438 goto out;
2441 dptr_num = dptr_dnum(dirptr);
2442 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2444 /* Initialize per TRANS2_FIND_FIRST operation data */
2445 dptr_init_search_op(dirptr);
2447 /* We don't need to check for VOL here as this is returned by
2448 a different TRANS2 call. */
2450 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2451 directory,lp_dontdescend(SNUM(conn))));
2452 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2453 dont_descend = True;
2455 p = pdata;
2456 space_remaining = max_data_bytes;
2457 out_of_space = False;
2459 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2460 bool got_exact_match = False;
2462 /* this is a heuristic to avoid seeking the dirptr except when
2463 absolutely necessary. It allows for a filename of about 40 chars */
2464 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2465 out_of_space = True;
2466 finished = False;
2467 } else {
2468 finished = !get_lanman2_dir_entry(ctx,
2469 conn,
2470 dirptr,
2471 req->flags2,
2472 mask,dirtype,info_level,
2473 requires_resume_key,dont_descend,
2474 ask_sharemode,
2475 &p,pdata,data_end,
2476 space_remaining, &out_of_space,
2477 &got_exact_match,
2478 &last_entry_off, ea_list);
2481 if (finished && out_of_space)
2482 finished = False;
2484 if (!finished && !out_of_space)
2485 numentries++;
2488 * As an optimisation if we know we aren't looking
2489 * for a wildcard name (ie. the name matches the wildcard exactly)
2490 * then we can finish on any (first) match.
2491 * This speeds up large directory searches. JRA.
2494 if(got_exact_match)
2495 finished = True;
2497 /* Ensure space_remaining never goes -ve. */
2498 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2499 space_remaining = 0;
2500 out_of_space = true;
2501 } else {
2502 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2506 /* Check if we can close the dirptr */
2507 if(close_after_first || (finished && close_if_end)) {
2508 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2509 dptr_close(sconn, &dptr_num);
2513 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2514 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2515 * the protocol level is less than NT1. Tested with smbclient. JRA.
2516 * This should fix the OS/2 client bug #2335.
2519 if(numentries == 0) {
2520 dptr_close(sconn, &dptr_num);
2521 if (get_Protocol() < PROTOCOL_NT1) {
2522 reply_force_doserror(req, ERRDOS, ERRnofiles);
2523 goto out;
2524 } else {
2525 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2526 ERRDOS, ERRbadfile);
2527 goto out;
2531 /* At this point pdata points to numentries directory entries. */
2533 /* Set up the return parameter block */
2534 SSVAL(params,0,dptr_num);
2535 SSVAL(params,2,numentries);
2536 SSVAL(params,4,finished);
2537 SSVAL(params,6,0); /* Never an EA error */
2538 SSVAL(params,8,last_entry_off);
2540 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2541 max_data_bytes);
2543 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2544 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2545 if (!directory) {
2546 reply_nterror(req, NT_STATUS_NO_MEMORY);
2550 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2551 smb_fn_name(req->cmd),
2552 mask, directory, dirtype, numentries ) );
2555 * Force a name mangle here to ensure that the
2556 * mask as an 8.3 name is top of the mangled cache.
2557 * The reasons for this are subtle. Don't remove
2558 * this code unless you know what you are doing
2559 * (see PR#13758). JRA.
2562 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2563 char mangled_name[13];
2564 name_to_8_3(mask, mangled_name, True, conn->params);
2566 out:
2567 TALLOC_FREE(smb_dname);
2568 return;
2571 /****************************************************************************
2572 Reply to a TRANS2_FINDNEXT.
2573 ****************************************************************************/
2575 static void call_trans2findnext(connection_struct *conn,
2576 struct smb_request *req,
2577 char **pparams, int total_params,
2578 char **ppdata, int total_data,
2579 unsigned int max_data_bytes)
2581 /* We must be careful here that we don't return more than the
2582 allowed number of data bytes. If this means returning fewer than
2583 maxentries then so be it. We assume that the redirector has
2584 enough room for the fixed number of parameter bytes it has
2585 requested. */
2586 char *params = *pparams;
2587 char *pdata = *ppdata;
2588 char *data_end;
2589 int dptr_num;
2590 int maxentries;
2591 uint16 info_level;
2592 uint32 resume_key;
2593 uint16 findnext_flags;
2594 bool close_after_request;
2595 bool close_if_end;
2596 bool requires_resume_key;
2597 bool continue_bit;
2598 bool mask_contains_wcard = False;
2599 char *resume_name = NULL;
2600 const char *mask = NULL;
2601 const char *directory = NULL;
2602 char *p = NULL;
2603 uint16 dirtype;
2604 int numentries = 0;
2605 int i, last_entry_off=0;
2606 bool finished = False;
2607 bool dont_descend = False;
2608 bool out_of_space = False;
2609 int space_remaining;
2610 struct ea_list *ea_list = NULL;
2611 NTSTATUS ntstatus = NT_STATUS_OK;
2612 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2613 TALLOC_CTX *ctx = talloc_tos();
2614 struct dptr_struct *dirptr;
2615 struct smbd_server_connection *sconn = req->sconn;
2617 if (total_params < 13) {
2618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2619 return;
2622 dptr_num = SVAL(params,0);
2623 maxentries = SVAL(params,2);
2624 info_level = SVAL(params,4);
2625 resume_key = IVAL(params,6);
2626 findnext_flags = SVAL(params,10);
2627 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2628 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2629 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2630 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2632 if (!continue_bit) {
2633 /* We only need resume_name if continue_bit is zero. */
2634 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2635 params+12,
2636 total_params - 12, STR_TERMINATE, &ntstatus,
2637 &mask_contains_wcard);
2638 if (!NT_STATUS_IS_OK(ntstatus)) {
2639 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2640 complain (it thinks we're asking for the directory above the shared
2641 path or an invalid name). Catch this as the resume name is only compared, never used in
2642 a file access. JRA. */
2643 srvstr_pull_talloc(ctx, params, req->flags2,
2644 &resume_name, params+12,
2645 total_params - 12,
2646 STR_TERMINATE);
2648 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2649 reply_nterror(req, ntstatus);
2650 return;
2655 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2656 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2657 resume_key = %d resume name = %s continue=%d level = %d\n",
2658 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2659 requires_resume_key, resume_key,
2660 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2662 if (!maxentries) {
2663 /* W2K3 seems to treat zero as 1. */
2664 maxentries = 1;
2667 switch (info_level) {
2668 case SMB_FIND_INFO_STANDARD:
2669 case SMB_FIND_EA_SIZE:
2670 case SMB_FIND_EA_LIST:
2671 case SMB_FIND_FILE_DIRECTORY_INFO:
2672 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_NAMES_INFO:
2674 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2675 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2676 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2677 break;
2678 case SMB_FIND_FILE_UNIX:
2679 case SMB_FIND_FILE_UNIX_INFO2:
2680 /* Always use filesystem for UNIX mtime query. */
2681 ask_sharemode = false;
2682 if (!lp_unix_extensions()) {
2683 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2684 return;
2686 break;
2687 default:
2688 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2689 return;
2692 if (info_level == SMB_FIND_EA_LIST) {
2693 uint32 ea_size;
2695 if (total_data < 4) {
2696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2697 return;
2700 ea_size = IVAL(pdata,0);
2701 if (ea_size != total_data) {
2702 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2703 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2705 return;
2708 if (!lp_ea_support(SNUM(conn))) {
2709 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2710 return;
2713 /* Pull out the list of names. */
2714 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2715 if (!ea_list) {
2716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2717 return;
2721 *ppdata = (char *)SMB_REALLOC(
2722 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2723 if(*ppdata == NULL) {
2724 reply_nterror(req, NT_STATUS_NO_MEMORY);
2725 return;
2728 pdata = *ppdata;
2729 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2731 /* Realloc the params space */
2732 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2733 if(*pparams == NULL ) {
2734 reply_nterror(req, NT_STATUS_NO_MEMORY);
2735 return;
2738 params = *pparams;
2740 /* Check that the dptr is valid */
2741 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2742 reply_nterror(req, STATUS_NO_MORE_FILES);
2743 return;
2746 directory = dptr_path(sconn, dptr_num);
2748 /* Get the wildcard mask from the dptr */
2749 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2750 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2751 reply_nterror(req, STATUS_NO_MORE_FILES);
2752 return;
2755 mask = p;
2757 /* Get the attr mask from the dptr */
2758 dirtype = dptr_attr(sconn, dptr_num);
2760 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2761 dptr_num, mask, dirtype,
2762 (long)dirptr,
2763 dptr_TellDir(dirptr)));
2765 /* Initialize per TRANS2_FIND_NEXT operation data */
2766 dptr_init_search_op(dirptr);
2768 /* We don't need to check for VOL here as this is returned by
2769 a different TRANS2 call. */
2771 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2772 directory,lp_dontdescend(SNUM(conn))));
2773 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2774 dont_descend = True;
2776 p = pdata;
2777 space_remaining = max_data_bytes;
2778 out_of_space = False;
2781 * Seek to the correct position. We no longer use the resume key but
2782 * depend on the last file name instead.
2785 if(!continue_bit && resume_name && *resume_name) {
2786 SMB_STRUCT_STAT st;
2788 long current_pos = 0;
2790 * Remember, name_to_8_3 is called by
2791 * get_lanman2_dir_entry(), so the resume name
2792 * could be mangled. Ensure we check the unmangled name.
2795 if (mangle_is_mangled(resume_name, conn->params)) {
2796 char *new_resume_name = NULL;
2797 mangle_lookup_name_from_8_3(ctx,
2798 resume_name,
2799 &new_resume_name,
2800 conn->params);
2801 if (new_resume_name) {
2802 resume_name = new_resume_name;
2807 * Fix for NT redirector problem triggered by resume key indexes
2808 * changing between directory scans. We now return a resume key of 0
2809 * and instead look for the filename to continue from (also given
2810 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2811 * findfirst/findnext (as is usual) then the directory pointer
2812 * should already be at the correct place.
2815 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2816 } /* end if resume_name && !continue_bit */
2818 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2819 bool got_exact_match = False;
2821 /* this is a heuristic to avoid seeking the dirptr except when
2822 absolutely necessary. It allows for a filename of about 40 chars */
2823 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2824 out_of_space = True;
2825 finished = False;
2826 } else {
2827 finished = !get_lanman2_dir_entry(ctx,
2828 conn,
2829 dirptr,
2830 req->flags2,
2831 mask,dirtype,info_level,
2832 requires_resume_key,dont_descend,
2833 ask_sharemode,
2834 &p,pdata,data_end,
2835 space_remaining, &out_of_space,
2836 &got_exact_match,
2837 &last_entry_off, ea_list);
2840 if (finished && out_of_space)
2841 finished = False;
2843 if (!finished && !out_of_space)
2844 numentries++;
2847 * As an optimisation if we know we aren't looking
2848 * for a wildcard name (ie. the name matches the wildcard exactly)
2849 * then we can finish on any (first) match.
2850 * This speeds up large directory searches. JRA.
2853 if(got_exact_match)
2854 finished = True;
2856 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2859 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2860 smb_fn_name(req->cmd),
2861 mask, directory, dirtype, numentries ) );
2863 /* Check if we can close the dirptr */
2864 if(close_after_request || (finished && close_if_end)) {
2865 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2866 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2869 /* Set up the return parameter block */
2870 SSVAL(params,0,numentries);
2871 SSVAL(params,2,finished);
2872 SSVAL(params,4,0); /* Never an EA error */
2873 SSVAL(params,6,last_entry_off);
2875 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2876 max_data_bytes);
2878 return;
2881 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2883 E_md4hash(lp_servicename(SNUM(conn)),objid);
2884 return objid;
2887 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2889 SMB_ASSERT(extended_info != NULL);
2891 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2892 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2893 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2894 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2895 #ifdef SAMBA_VERSION_REVISION
2896 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2897 #endif
2898 extended_info->samba_subversion = 0;
2899 #ifdef SAMBA_VERSION_RC_RELEASE
2900 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2901 #else
2902 #ifdef SAMBA_VERSION_PRE_RELEASE
2903 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2904 #endif
2905 #endif
2906 #ifdef SAMBA_VERSION_VENDOR_PATCH
2907 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2908 #endif
2909 extended_info->samba_gitcommitdate = 0;
2910 #ifdef SAMBA_VERSION_COMMIT_TIME
2911 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2912 #endif
2914 memset(extended_info->samba_version_string, 0,
2915 sizeof(extended_info->samba_version_string));
2917 snprintf (extended_info->samba_version_string,
2918 sizeof(extended_info->samba_version_string),
2919 "%s", samba_version_string());
2922 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2923 TALLOC_CTX *mem_ctx,
2924 uint16_t info_level,
2925 uint16_t flags2,
2926 unsigned int max_data_bytes,
2927 char **ppdata,
2928 int *ret_data_len)
2930 char *pdata, *end_data;
2931 int data_len = 0, len;
2932 const char *vname = volume_label(SNUM(conn));
2933 int snum = SNUM(conn);
2934 char *fstype = lp_fstype(SNUM(conn));
2935 uint32 additional_flags = 0;
2936 struct smb_filename smb_fname_dot;
2937 SMB_STRUCT_STAT st;
2939 if (IS_IPC(conn)) {
2940 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2941 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2942 "info level (0x%x) on IPC$.\n",
2943 (unsigned int)info_level));
2944 return NT_STATUS_ACCESS_DENIED;
2948 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2950 ZERO_STRUCT(smb_fname_dot);
2951 smb_fname_dot.base_name = discard_const_p(char, ".");
2953 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2954 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2955 return map_nt_error_from_unix(errno);
2958 st = smb_fname_dot.st;
2960 *ppdata = (char *)SMB_REALLOC(
2961 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2962 if (*ppdata == NULL) {
2963 return NT_STATUS_NO_MEMORY;
2966 pdata = *ppdata;
2967 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2968 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2970 switch (info_level) {
2971 case SMB_INFO_ALLOCATION:
2973 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2974 data_len = 18;
2975 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2976 return map_nt_error_from_unix(errno);
2979 block_size = lp_block_size(snum);
2980 if (bsize < block_size) {
2981 uint64_t factor = block_size/bsize;
2982 bsize = block_size;
2983 dsize /= factor;
2984 dfree /= factor;
2986 if (bsize > block_size) {
2987 uint64_t factor = bsize/block_size;
2988 bsize = block_size;
2989 dsize *= factor;
2990 dfree *= factor;
2992 bytes_per_sector = 512;
2993 sectors_per_unit = bsize/bytes_per_sector;
2995 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2996 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2997 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2999 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3000 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3001 SIVAL(pdata,l1_cUnit,dsize);
3002 SIVAL(pdata,l1_cUnitAvail,dfree);
3003 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3004 break;
3007 case SMB_INFO_VOLUME:
3008 /* Return volume name */
3010 * Add volume serial number - hash of a combination of
3011 * the called hostname and the service name.
3013 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3015 * Win2k3 and previous mess this up by sending a name length
3016 * one byte short. I believe only older clients (OS/2 Win9x) use
3017 * this call so try fixing this by adding a terminating null to
3018 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3020 len = srvstr_push(
3021 pdata, flags2,
3022 pdata+l2_vol_szVolLabel, vname,
3023 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3024 STR_NOALIGN|STR_TERMINATE);
3025 SCVAL(pdata,l2_vol_cch,len);
3026 data_len = l2_vol_szVolLabel + len;
3027 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3028 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3029 len, vname));
3030 break;
3032 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3033 case SMB_FS_ATTRIBUTE_INFORMATION:
3035 additional_flags = 0;
3036 #if defined(HAVE_SYS_QUOTAS)
3037 additional_flags |= FILE_VOLUME_QUOTAS;
3038 #endif
3040 if(lp_nt_acl_support(SNUM(conn))) {
3041 additional_flags |= FILE_PERSISTENT_ACLS;
3044 /* Capabilities are filled in at connection time through STATVFS call */
3045 additional_flags |= conn->fs_capabilities;
3046 additional_flags |= lp_parm_int(conn->params->service,
3047 "share", "fake_fscaps",
3050 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3051 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3052 additional_flags); /* FS ATTRIBUTES */
3054 SIVAL(pdata,4,255); /* Max filename component length */
3055 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3056 and will think we can't do long filenames */
3057 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3058 PTR_DIFF(end_data, pdata+12),
3059 STR_UNICODE);
3060 SIVAL(pdata,8,len);
3061 data_len = 12 + len;
3062 break;
3064 case SMB_QUERY_FS_LABEL_INFO:
3065 case SMB_FS_LABEL_INFORMATION:
3066 len = srvstr_push(pdata, flags2, pdata+4, vname,
3067 PTR_DIFF(end_data, pdata+4), 0);
3068 data_len = 4 + len;
3069 SIVAL(pdata,0,len);
3070 break;
3072 case SMB_QUERY_FS_VOLUME_INFO:
3073 case SMB_FS_VOLUME_INFORMATION:
3076 * Add volume serial number - hash of a combination of
3077 * the called hostname and the service name.
3079 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3080 (str_checksum(get_local_machine_name())<<16));
3082 /* Max label len is 32 characters. */
3083 len = srvstr_push(pdata, flags2, pdata+18, vname,
3084 PTR_DIFF(end_data, pdata+18),
3085 STR_UNICODE);
3086 SIVAL(pdata,12,len);
3087 data_len = 18+len;
3089 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3090 (int)strlen(vname),vname, lp_servicename(snum)));
3091 break;
3093 case SMB_QUERY_FS_SIZE_INFO:
3094 case SMB_FS_SIZE_INFORMATION:
3096 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3097 data_len = 24;
3098 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3099 return map_nt_error_from_unix(errno);
3101 block_size = lp_block_size(snum);
3102 if (bsize < block_size) {
3103 uint64_t factor = block_size/bsize;
3104 bsize = block_size;
3105 dsize /= factor;
3106 dfree /= factor;
3108 if (bsize > block_size) {
3109 uint64_t factor = bsize/block_size;
3110 bsize = block_size;
3111 dsize *= factor;
3112 dfree *= factor;
3114 bytes_per_sector = 512;
3115 sectors_per_unit = bsize/bytes_per_sector;
3116 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3117 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3118 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3119 SBIG_UINT(pdata,0,dsize);
3120 SBIG_UINT(pdata,8,dfree);
3121 SIVAL(pdata,16,sectors_per_unit);
3122 SIVAL(pdata,20,bytes_per_sector);
3123 break;
3126 case SMB_FS_FULL_SIZE_INFORMATION:
3128 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3129 data_len = 32;
3130 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3131 return map_nt_error_from_unix(errno);
3133 block_size = lp_block_size(snum);
3134 if (bsize < block_size) {
3135 uint64_t factor = block_size/bsize;
3136 bsize = block_size;
3137 dsize /= factor;
3138 dfree /= factor;
3140 if (bsize > block_size) {
3141 uint64_t factor = bsize/block_size;
3142 bsize = block_size;
3143 dsize *= factor;
3144 dfree *= factor;
3146 bytes_per_sector = 512;
3147 sectors_per_unit = bsize/bytes_per_sector;
3148 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3149 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3150 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3151 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3152 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3153 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3154 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3155 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3156 break;
3159 case SMB_QUERY_FS_DEVICE_INFO:
3160 case SMB_FS_DEVICE_INFORMATION:
3162 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3164 if (!CAN_WRITE(conn)) {
3165 characteristics |= FILE_READ_ONLY_DEVICE;
3167 data_len = 8;
3168 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3169 SIVAL(pdata,4,characteristics);
3170 break;
3173 #ifdef HAVE_SYS_QUOTAS
3174 case SMB_FS_QUOTA_INFORMATION:
3176 * what we have to send --metze:
3178 * Unknown1: 24 NULL bytes
3179 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3180 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3181 * Quota Flags: 2 byte :
3182 * Unknown3: 6 NULL bytes
3184 * 48 bytes total
3186 * details for Quota Flags:
3188 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3189 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3190 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3191 * 0x0001 Enable Quotas: enable quota for this fs
3195 /* we need to fake up a fsp here,
3196 * because its not send in this call
3198 files_struct fsp;
3199 SMB_NTQUOTA_STRUCT quotas;
3201 ZERO_STRUCT(fsp);
3202 ZERO_STRUCT(quotas);
3204 fsp.conn = conn;
3205 fsp.fnum = -1;
3207 /* access check */
3208 if (get_current_uid(conn) != 0) {
3209 DEBUG(0,("set_user_quota: access_denied "
3210 "service [%s] user [%s]\n",
3211 lp_servicename(SNUM(conn)),
3212 conn->session_info->unix_info->unix_name));
3213 return NT_STATUS_ACCESS_DENIED;
3216 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3217 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3218 return map_nt_error_from_unix(errno);
3221 data_len = 48;
3223 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3224 lp_servicename(SNUM(conn))));
3226 /* Unknown1 24 NULL bytes*/
3227 SBIG_UINT(pdata,0,(uint64_t)0);
3228 SBIG_UINT(pdata,8,(uint64_t)0);
3229 SBIG_UINT(pdata,16,(uint64_t)0);
3231 /* Default Soft Quota 8 bytes */
3232 SBIG_UINT(pdata,24,quotas.softlim);
3234 /* Default Hard Quota 8 bytes */
3235 SBIG_UINT(pdata,32,quotas.hardlim);
3237 /* Quota flag 2 bytes */
3238 SSVAL(pdata,40,quotas.qflags);
3240 /* Unknown3 6 NULL bytes */
3241 SSVAL(pdata,42,0);
3242 SIVAL(pdata,44,0);
3244 break;
3246 #endif /* HAVE_SYS_QUOTAS */
3247 case SMB_FS_OBJECTID_INFORMATION:
3249 unsigned char objid[16];
3250 struct smb_extended_info extended_info;
3251 memcpy(pdata,create_volume_objectid(conn, objid),16);
3252 samba_extended_info_version (&extended_info);
3253 SIVAL(pdata,16,extended_info.samba_magic);
3254 SIVAL(pdata,20,extended_info.samba_version);
3255 SIVAL(pdata,24,extended_info.samba_subversion);
3256 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3257 memcpy(pdata+36,extended_info.samba_version_string,28);
3258 data_len = 64;
3259 break;
3263 * Query the version and capabilities of the CIFS UNIX extensions
3264 * in use.
3267 case SMB_QUERY_CIFS_UNIX_INFO:
3269 bool large_write = lp_min_receive_file_size() &&
3270 !srv_is_signing_active(conn->sconn);
3271 bool large_read = !srv_is_signing_active(conn->sconn);
3272 int encrypt_caps = 0;
3274 if (!lp_unix_extensions()) {
3275 return NT_STATUS_INVALID_LEVEL;
3278 switch (conn->encrypt_level) {
3279 case 0:
3280 encrypt_caps = 0;
3281 break;
3282 case 1:
3283 case Auto:
3284 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3285 break;
3286 case Required:
3287 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3288 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3289 large_write = false;
3290 large_read = false;
3291 break;
3294 data_len = 12;
3295 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3296 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3298 /* We have POSIX ACLs, pathname, encryption,
3299 * large read/write, and locking capability. */
3301 SBIG_UINT(pdata,4,((uint64_t)(
3302 CIFS_UNIX_POSIX_ACLS_CAP|
3303 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3304 CIFS_UNIX_FCNTL_LOCKS_CAP|
3305 CIFS_UNIX_EXTATTR_CAP|
3306 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3307 encrypt_caps|
3308 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3309 (large_write ?
3310 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3311 break;
3314 case SMB_QUERY_POSIX_FS_INFO:
3316 int rc;
3317 vfs_statvfs_struct svfs;
3319 if (!lp_unix_extensions()) {
3320 return NT_STATUS_INVALID_LEVEL;
3323 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3325 if (!rc) {
3326 data_len = 56;
3327 SIVAL(pdata,0,svfs.OptimalTransferSize);
3328 SIVAL(pdata,4,svfs.BlockSize);
3329 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3330 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3331 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3332 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3333 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3334 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3335 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3336 #ifdef EOPNOTSUPP
3337 } else if (rc == EOPNOTSUPP) {
3338 return NT_STATUS_INVALID_LEVEL;
3339 #endif /* EOPNOTSUPP */
3340 } else {
3341 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3342 return NT_STATUS_DOS(ERRSRV, ERRerror);
3344 break;
3347 case SMB_QUERY_POSIX_WHOAMI:
3349 uint32_t flags = 0;
3350 uint32_t sid_bytes;
3351 int i;
3353 if (!lp_unix_extensions()) {
3354 return NT_STATUS_INVALID_LEVEL;
3357 if (max_data_bytes < 40) {
3358 return NT_STATUS_BUFFER_TOO_SMALL;
3361 /* We ARE guest if global_sid_Builtin_Guests is
3362 * in our list of SIDs.
3364 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3365 conn->session_info->security_token)) {
3366 flags |= SMB_WHOAMI_GUEST;
3369 /* We are NOT guest if global_sid_Authenticated_Users
3370 * is in our list of SIDs.
3372 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3373 conn->session_info->security_token)) {
3374 flags &= ~SMB_WHOAMI_GUEST;
3377 /* NOTE: 8 bytes for UID/GID, irrespective of native
3378 * platform size. This matches
3379 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3381 data_len = 4 /* flags */
3382 + 4 /* flag mask */
3383 + 8 /* uid */
3384 + 8 /* gid */
3385 + 4 /* ngroups */
3386 + 4 /* num_sids */
3387 + 4 /* SID bytes */
3388 + 4 /* pad/reserved */
3389 + (conn->session_info->unix_token->ngroups * 8)
3390 /* groups list */
3391 + (conn->session_info->security_token->num_sids *
3392 SID_MAX_SIZE)
3393 /* SID list */;
3395 SIVAL(pdata, 0, flags);
3396 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3397 SBIG_UINT(pdata, 8,
3398 (uint64_t)conn->session_info->unix_token->uid);
3399 SBIG_UINT(pdata, 16,
3400 (uint64_t)conn->session_info->unix_token->gid);
3403 if (data_len >= max_data_bytes) {
3404 /* Potential overflow, skip the GIDs and SIDs. */
3406 SIVAL(pdata, 24, 0); /* num_groups */
3407 SIVAL(pdata, 28, 0); /* num_sids */
3408 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3409 SIVAL(pdata, 36, 0); /* reserved */
3411 data_len = 40;
3412 break;
3415 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3416 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3418 /* We walk the SID list twice, but this call is fairly
3419 * infrequent, and I don't expect that it's performance
3420 * sensitive -- jpeach
3422 for (i = 0, sid_bytes = 0;
3423 i < conn->session_info->security_token->num_sids; ++i) {
3424 sid_bytes += ndr_size_dom_sid(
3425 &conn->session_info->security_token->sids[i],
3429 /* SID list byte count */
3430 SIVAL(pdata, 32, sid_bytes);
3432 /* 4 bytes pad/reserved - must be zero */
3433 SIVAL(pdata, 36, 0);
3434 data_len = 40;
3436 /* GID list */
3437 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3438 SBIG_UINT(pdata, data_len,
3439 (uint64_t)conn->session_info->unix_token->groups[i]);
3440 data_len += 8;
3443 /* SID list */
3444 for (i = 0;
3445 i < conn->session_info->security_token->num_sids; ++i) {
3446 int sid_len = ndr_size_dom_sid(
3447 &conn->session_info->security_token->sids[i],
3450 sid_linearize(pdata + data_len, sid_len,
3451 &conn->session_info->security_token->sids[i]);
3452 data_len += sid_len;
3455 break;
3458 case SMB_MAC_QUERY_FS_INFO:
3460 * Thursby MAC extension... ONLY on NTFS filesystems
3461 * once we do streams then we don't need this
3463 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3464 data_len = 88;
3465 SIVAL(pdata,84,0x100); /* Don't support mac... */
3466 break;
3468 /* drop through */
3469 default:
3470 return NT_STATUS_INVALID_LEVEL;
3473 *ret_data_len = data_len;
3474 return NT_STATUS_OK;
3477 /****************************************************************************
3478 Reply to a TRANS2_QFSINFO (query filesystem info).
3479 ****************************************************************************/
3481 static void call_trans2qfsinfo(connection_struct *conn,
3482 struct smb_request *req,
3483 char **pparams, int total_params,
3484 char **ppdata, int total_data,
3485 unsigned int max_data_bytes)
3487 char *params = *pparams;
3488 uint16_t info_level;
3489 int data_len = 0;
3490 NTSTATUS status;
3492 if (total_params < 2) {
3493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3494 return;
3497 info_level = SVAL(params,0);
3499 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3500 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3501 DEBUG(0,("call_trans2qfsinfo: encryption required "
3502 "and info level 0x%x sent.\n",
3503 (unsigned int)info_level));
3504 exit_server_cleanly("encryption required "
3505 "on connection");
3506 return;
3510 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3512 status = smbd_do_qfsinfo(conn, req,
3513 info_level,
3514 req->flags2,
3515 max_data_bytes,
3516 ppdata, &data_len);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 reply_nterror(req, status);
3519 return;
3522 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3523 max_data_bytes);
3525 DEBUG( 4, ( "%s info_level = %d\n",
3526 smb_fn_name(req->cmd), info_level) );
3528 return;
3531 /****************************************************************************
3532 Reply to a TRANS2_SETFSINFO (set filesystem info).
3533 ****************************************************************************/
3535 static void call_trans2setfsinfo(connection_struct *conn,
3536 struct smb_request *req,
3537 char **pparams, int total_params,
3538 char **ppdata, int total_data,
3539 unsigned int max_data_bytes)
3541 char *pdata = *ppdata;
3542 char *params = *pparams;
3543 uint16 info_level;
3545 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3547 /* */
3548 if (total_params < 4) {
3549 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3550 total_params));
3551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3552 return;
3555 info_level = SVAL(params,2);
3557 if (IS_IPC(conn)) {
3558 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3559 info_level != SMB_SET_CIFS_UNIX_INFO) {
3560 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3561 "info level (0x%x) on IPC$.\n",
3562 (unsigned int)info_level));
3563 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3564 return;
3568 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3569 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3570 DEBUG(0,("call_trans2setfsinfo: encryption required "
3571 "and info level 0x%x sent.\n",
3572 (unsigned int)info_level));
3573 exit_server_cleanly("encryption required "
3574 "on connection");
3575 return;
3579 switch(info_level) {
3580 case SMB_SET_CIFS_UNIX_INFO:
3582 uint16 client_unix_major;
3583 uint16 client_unix_minor;
3584 uint32 client_unix_cap_low;
3585 uint32 client_unix_cap_high;
3587 if (!lp_unix_extensions()) {
3588 reply_nterror(req,
3589 NT_STATUS_INVALID_LEVEL);
3590 return;
3593 /* There should be 12 bytes of capabilities set. */
3594 if (total_data < 8) {
3595 reply_nterror(
3596 req,
3597 NT_STATUS_INVALID_PARAMETER);
3598 return;
3600 client_unix_major = SVAL(pdata,0);
3601 client_unix_minor = SVAL(pdata,2);
3602 client_unix_cap_low = IVAL(pdata,4);
3603 client_unix_cap_high = IVAL(pdata,8);
3604 /* Just print these values for now. */
3605 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3606 cap_low = 0x%x, cap_high = 0x%x\n",
3607 (unsigned int)client_unix_major,
3608 (unsigned int)client_unix_minor,
3609 (unsigned int)client_unix_cap_low,
3610 (unsigned int)client_unix_cap_high ));
3612 /* Here is where we must switch to posix pathname processing... */
3613 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3614 lp_set_posix_pathnames();
3615 mangle_change_to_posix();
3618 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3619 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3620 /* Client that knows how to do posix locks,
3621 * but not posix open/mkdir operations. Set a
3622 * default type for read/write checks. */
3624 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3627 break;
3630 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3632 NTSTATUS status;
3633 size_t param_len = 0;
3634 size_t data_len = total_data;
3636 if (!lp_unix_extensions()) {
3637 reply_nterror(
3638 req,
3639 NT_STATUS_INVALID_LEVEL);
3640 return;
3643 if (lp_smb_encrypt(SNUM(conn)) == false) {
3644 reply_nterror(
3645 req,
3646 NT_STATUS_NOT_SUPPORTED);
3647 return;
3650 if (req->sconn->smb1.echo_handler.trusted_fde) {
3651 DEBUG( 2,("call_trans2setfsinfo: "
3652 "request transport encryption disabled"
3653 "with 'fork echo handler = yes'\n"));
3654 reply_nterror(
3655 req,
3656 NT_STATUS_NOT_SUPPORTED);
3657 return;
3660 DEBUG( 4,("call_trans2setfsinfo: "
3661 "request transport encryption.\n"));
3663 status = srv_request_encryption_setup(conn,
3664 (unsigned char **)ppdata,
3665 &data_len,
3666 (unsigned char **)pparams,
3667 &param_len);
3669 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3670 !NT_STATUS_IS_OK(status)) {
3671 reply_nterror(req, status);
3672 return;
3675 send_trans2_replies(conn, req,
3676 *pparams,
3677 param_len,
3678 *ppdata,
3679 data_len,
3680 max_data_bytes);
3682 if (NT_STATUS_IS_OK(status)) {
3683 /* Server-side transport
3684 * encryption is now *on*. */
3685 status = srv_encryption_start(conn);
3686 if (!NT_STATUS_IS_OK(status)) {
3687 exit_server_cleanly(
3688 "Failure in setting "
3689 "up encrypted transport");
3692 return;
3695 case SMB_FS_QUOTA_INFORMATION:
3697 files_struct *fsp = NULL;
3698 SMB_NTQUOTA_STRUCT quotas;
3700 ZERO_STRUCT(quotas);
3702 /* access check */
3703 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3704 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3705 lp_servicename(SNUM(conn)),
3706 conn->session_info->unix_info->unix_name));
3707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3708 return;
3711 /* note: normaly there're 48 bytes,
3712 * but we didn't use the last 6 bytes for now
3713 * --metze
3715 fsp = file_fsp(req, SVAL(params,0));
3717 if (!check_fsp_ntquota_handle(conn, req,
3718 fsp)) {
3719 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3720 reply_nterror(
3721 req, NT_STATUS_INVALID_HANDLE);
3722 return;
3725 if (total_data < 42) {
3726 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3727 total_data));
3728 reply_nterror(
3729 req,
3730 NT_STATUS_INVALID_PARAMETER);
3731 return;
3734 /* unknown_1 24 NULL bytes in pdata*/
3736 /* the soft quotas 8 bytes (uint64_t)*/
3737 quotas.softlim = BVAL(pdata,24);
3739 /* the hard quotas 8 bytes (uint64_t)*/
3740 quotas.hardlim = BVAL(pdata,32);
3742 /* quota_flags 2 bytes **/
3743 quotas.qflags = SVAL(pdata,40);
3745 /* unknown_2 6 NULL bytes follow*/
3747 /* now set the quotas */
3748 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3749 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3750 reply_nterror(req, map_nt_error_from_unix(errno));
3751 return;
3754 break;
3756 default:
3757 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3758 info_level));
3759 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3760 return;
3761 break;
3765 * sending this reply works fine,
3766 * but I'm not sure it's the same
3767 * like windows do...
3768 * --metze
3770 reply_outbuf(req, 10, 0);
3773 #if defined(HAVE_POSIX_ACLS)
3774 /****************************************************************************
3775 Utility function to count the number of entries in a POSIX acl.
3776 ****************************************************************************/
3778 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3780 unsigned int ace_count = 0;
3781 int entry_id = SMB_ACL_FIRST_ENTRY;
3782 SMB_ACL_ENTRY_T entry;
3784 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3785 /* get_next... */
3786 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3787 entry_id = SMB_ACL_NEXT_ENTRY;
3789 ace_count++;
3791 return ace_count;
3794 /****************************************************************************
3795 Utility function to marshall a POSIX acl into wire format.
3796 ****************************************************************************/
3798 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3800 int entry_id = SMB_ACL_FIRST_ENTRY;
3801 SMB_ACL_ENTRY_T entry;
3803 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3804 SMB_ACL_TAG_T tagtype;
3805 SMB_ACL_PERMSET_T permset;
3806 unsigned char perms = 0;
3807 unsigned int own_grp;
3809 /* get_next... */
3810 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3811 entry_id = SMB_ACL_NEXT_ENTRY;
3814 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3815 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3816 return False;
3819 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3820 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3821 return False;
3824 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3825 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3826 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3828 SCVAL(pdata,1,perms);
3830 switch (tagtype) {
3831 case SMB_ACL_USER_OBJ:
3832 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3833 own_grp = (unsigned int)pst->st_ex_uid;
3834 SIVAL(pdata,2,own_grp);
3835 SIVAL(pdata,6,0);
3836 break;
3837 case SMB_ACL_USER:
3839 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3840 if (!puid) {
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3842 return False;
3844 own_grp = (unsigned int)*puid;
3845 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3846 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3847 SIVAL(pdata,2,own_grp);
3848 SIVAL(pdata,6,0);
3849 break;
3851 case SMB_ACL_GROUP_OBJ:
3852 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3853 own_grp = (unsigned int)pst->st_ex_gid;
3854 SIVAL(pdata,2,own_grp);
3855 SIVAL(pdata,6,0);
3856 break;
3857 case SMB_ACL_GROUP:
3859 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3860 if (!pgid) {
3861 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3862 return False;
3864 own_grp = (unsigned int)*pgid;
3865 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3866 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3867 SIVAL(pdata,2,own_grp);
3868 SIVAL(pdata,6,0);
3869 break;
3871 case SMB_ACL_MASK:
3872 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3873 SIVAL(pdata,2,0xFFFFFFFF);
3874 SIVAL(pdata,6,0xFFFFFFFF);
3875 break;
3876 case SMB_ACL_OTHER:
3877 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3878 SIVAL(pdata,2,0xFFFFFFFF);
3879 SIVAL(pdata,6,0xFFFFFFFF);
3880 break;
3881 default:
3882 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3883 return False;
3885 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3888 return True;
3890 #endif
3892 /****************************************************************************
3893 Store the FILE_UNIX_BASIC info.
3894 ****************************************************************************/
3896 static char *store_file_unix_basic(connection_struct *conn,
3897 char *pdata,
3898 files_struct *fsp,
3899 const SMB_STRUCT_STAT *psbuf)
3901 uint64_t file_index = get_FileIndex(conn, psbuf);
3903 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3904 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3906 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3907 pdata += 8;
3909 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3910 pdata += 8;
3912 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3913 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3914 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3915 pdata += 24;
3917 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3918 SIVAL(pdata,4,0);
3919 pdata += 8;
3921 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3922 SIVAL(pdata,4,0);
3923 pdata += 8;
3925 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3926 pdata += 4;
3928 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3929 SIVAL(pdata,4,0);
3930 pdata += 8;
3932 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3933 SIVAL(pdata,4,0);
3934 pdata += 8;
3936 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3937 pdata += 8;
3939 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3940 SIVAL(pdata,4,0);
3941 pdata += 8;
3943 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3944 SIVAL(pdata,4,0);
3945 pdata += 8;
3947 return pdata;
3950 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3951 * the chflags(2) (or equivalent) flags.
3953 * XXX: this really should be behind the VFS interface. To do this, we would
3954 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3955 * Each VFS module could then implement its own mapping as appropriate for the
3956 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3958 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3959 info2_flags_map[] =
3961 #ifdef UF_NODUMP
3962 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3963 #endif
3965 #ifdef UF_IMMUTABLE
3966 { UF_IMMUTABLE, EXT_IMMUTABLE },
3967 #endif
3969 #ifdef UF_APPEND
3970 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3971 #endif
3973 #ifdef UF_HIDDEN
3974 { UF_HIDDEN, EXT_HIDDEN },
3975 #endif
3977 /* Do not remove. We need to guarantee that this array has at least one
3978 * entry to build on HP-UX.
3980 { 0, 0 }
3984 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3985 uint32 *smb_fflags, uint32 *smb_fmask)
3987 int i;
3989 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3990 *smb_fmask |= info2_flags_map[i].smb_fflag;
3991 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3992 *smb_fflags |= info2_flags_map[i].smb_fflag;
3997 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3998 const uint32 smb_fflags,
3999 const uint32 smb_fmask,
4000 int *stat_fflags)
4002 uint32 max_fmask = 0;
4003 int i;
4005 *stat_fflags = psbuf->st_ex_flags;
4007 /* For each flags requested in smb_fmask, check the state of the
4008 * corresponding flag in smb_fflags and set or clear the matching
4009 * stat flag.
4012 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4013 max_fmask |= info2_flags_map[i].smb_fflag;
4014 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4015 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4016 *stat_fflags |= info2_flags_map[i].stat_fflag;
4017 } else {
4018 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4023 /* If smb_fmask is asking to set any bits that are not supported by
4024 * our flag mappings, we should fail.
4026 if ((smb_fmask & max_fmask) != smb_fmask) {
4027 return False;
4030 return True;
4034 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4035 * of file flags and birth (create) time.
4037 static char *store_file_unix_basic_info2(connection_struct *conn,
4038 char *pdata,
4039 files_struct *fsp,
4040 const SMB_STRUCT_STAT *psbuf)
4042 uint32 file_flags = 0;
4043 uint32 flags_mask = 0;
4045 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4047 /* Create (birth) time 64 bit */
4048 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4049 pdata += 8;
4051 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4052 SIVAL(pdata, 0, file_flags); /* flags */
4053 SIVAL(pdata, 4, flags_mask); /* mask */
4054 pdata += 8;
4056 return pdata;
4059 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4060 const struct stream_struct *streams,
4061 char *data,
4062 unsigned int max_data_bytes,
4063 unsigned int *data_size)
4065 unsigned int i;
4066 unsigned int ofs = 0;
4068 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4069 unsigned int next_offset;
4070 size_t namelen;
4071 smb_ucs2_t *namebuf;
4073 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4074 streams[i].name, &namelen) ||
4075 namelen <= 2)
4077 return NT_STATUS_INVALID_PARAMETER;
4081 * name_buf is now null-terminated, we need to marshall as not
4082 * terminated
4085 namelen -= 2;
4087 SIVAL(data, ofs+4, namelen);
4088 SOFF_T(data, ofs+8, streams[i].size);
4089 SOFF_T(data, ofs+16, streams[i].alloc_size);
4090 memcpy(data+ofs+24, namebuf, namelen);
4091 TALLOC_FREE(namebuf);
4093 next_offset = ofs + 24 + namelen;
4095 if (i == num_streams-1) {
4096 SIVAL(data, ofs, 0);
4098 else {
4099 unsigned int align = ndr_align_size(next_offset, 8);
4101 memset(data+next_offset, 0, align);
4102 next_offset += align;
4104 SIVAL(data, ofs, next_offset - ofs);
4105 ofs = next_offset;
4108 ofs = next_offset;
4111 *data_size = ofs;
4113 return NT_STATUS_OK;
4116 /****************************************************************************
4117 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4118 ****************************************************************************/
4120 static void call_trans2qpipeinfo(connection_struct *conn,
4121 struct smb_request *req,
4122 unsigned int tran_call,
4123 char **pparams, int total_params,
4124 char **ppdata, int total_data,
4125 unsigned int max_data_bytes)
4127 char *params = *pparams;
4128 char *pdata = *ppdata;
4129 unsigned int data_size = 0;
4130 unsigned int param_size = 2;
4131 uint16 info_level;
4132 files_struct *fsp;
4134 if (!params) {
4135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4136 return;
4139 if (total_params < 4) {
4140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4141 return;
4144 fsp = file_fsp(req, SVAL(params,0));
4145 if (!fsp_is_np(fsp)) {
4146 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4147 return;
4150 info_level = SVAL(params,2);
4152 *pparams = (char *)SMB_REALLOC(*pparams,2);
4153 if (*pparams == NULL) {
4154 reply_nterror(req, NT_STATUS_NO_MEMORY);
4155 return;
4157 params = *pparams;
4158 SSVAL(params,0,0);
4159 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4160 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4161 if (*ppdata == NULL ) {
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4163 return;
4165 pdata = *ppdata;
4167 switch (info_level) {
4168 case SMB_FILE_STANDARD_INFORMATION:
4169 memset(pdata,0,24);
4170 SOFF_T(pdata,0,4096LL);
4171 SIVAL(pdata,16,1);
4172 SIVAL(pdata,20,1);
4173 data_size = 24;
4174 break;
4176 default:
4177 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4178 return;
4181 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4182 max_data_bytes);
4184 return;
4187 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4188 TALLOC_CTX *mem_ctx,
4189 uint16_t info_level,
4190 files_struct *fsp,
4191 struct smb_filename *smb_fname,
4192 bool delete_pending,
4193 struct timespec write_time_ts,
4194 struct ea_list *ea_list,
4195 int lock_data_count,
4196 char *lock_data,
4197 uint16_t flags2,
4198 unsigned int max_data_bytes,
4199 char **ppdata,
4200 unsigned int *pdata_size)
4202 char *pdata = *ppdata;
4203 char *dstart, *dend;
4204 unsigned int data_size;
4205 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4206 time_t create_time, mtime, atime, c_time;
4207 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4208 char *p;
4209 char *base_name;
4210 char *dos_fname;
4211 int mode;
4212 int nlink;
4213 NTSTATUS status;
4214 uint64_t file_size = 0;
4215 uint64_t pos = 0;
4216 uint64_t allocation_size = 0;
4217 uint64_t file_index = 0;
4218 uint32_t access_mask = 0;
4220 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4221 return NT_STATUS_INVALID_LEVEL;
4224 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4225 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4226 info_level, max_data_bytes));
4228 mode = dos_mode(conn, smb_fname);
4229 nlink = psbuf->st_ex_nlink;
4231 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4232 nlink = 1;
4235 if ((nlink > 0) && delete_pending) {
4236 nlink -= 1;
4239 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4240 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4241 if (*ppdata == NULL) {
4242 return NT_STATUS_NO_MEMORY;
4244 pdata = *ppdata;
4245 dstart = pdata;
4246 dend = dstart + data_size - 1;
4248 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4249 update_stat_ex_mtime(psbuf, write_time_ts);
4252 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4253 mtime_ts = psbuf->st_ex_mtime;
4254 atime_ts = psbuf->st_ex_atime;
4255 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4257 if (lp_dos_filetime_resolution(SNUM(conn))) {
4258 dos_filetime_timespec(&create_time_ts);
4259 dos_filetime_timespec(&mtime_ts);
4260 dos_filetime_timespec(&atime_ts);
4261 dos_filetime_timespec(&ctime_ts);
4264 create_time = convert_timespec_to_time_t(create_time_ts);
4265 mtime = convert_timespec_to_time_t(mtime_ts);
4266 atime = convert_timespec_to_time_t(atime_ts);
4267 c_time = convert_timespec_to_time_t(ctime_ts);
4269 p = strrchr_m(smb_fname->base_name,'/');
4270 if (!p)
4271 base_name = smb_fname->base_name;
4272 else
4273 base_name = p+1;
4275 /* NT expects the name to be in an exact form of the *full*
4276 filename. See the trans2 torture test */
4277 if (ISDOT(base_name)) {
4278 dos_fname = talloc_strdup(mem_ctx, "\\");
4279 if (!dos_fname) {
4280 return NT_STATUS_NO_MEMORY;
4282 } else {
4283 dos_fname = talloc_asprintf(mem_ctx,
4284 "\\%s",
4285 smb_fname->base_name);
4286 if (!dos_fname) {
4287 return NT_STATUS_NO_MEMORY;
4289 if (is_ntfs_stream_smb_fname(smb_fname)) {
4290 dos_fname = talloc_asprintf(dos_fname, "%s",
4291 smb_fname->stream_name);
4292 if (!dos_fname) {
4293 return NT_STATUS_NO_MEMORY;
4297 string_replace(dos_fname, '/', '\\');
4300 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4302 if (!fsp) {
4303 /* Do we have this path open ? */
4304 files_struct *fsp1;
4305 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4306 fsp1 = file_find_di_first(conn->sconn, fileid);
4307 if (fsp1 && fsp1->initial_allocation_size) {
4308 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4312 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4313 file_size = get_file_size_stat(psbuf);
4316 if (fsp) {
4317 pos = fsp->fh->position_information;
4320 if (fsp) {
4321 access_mask = fsp->access_mask;
4322 } else {
4323 /* GENERIC_EXECUTE mapping from Windows */
4324 access_mask = 0x12019F;
4327 /* This should be an index number - looks like
4328 dev/ino to me :-)
4330 I think this causes us to fail the IFSKIT
4331 BasicFileInformationTest. -tpot */
4332 file_index = get_FileIndex(conn, psbuf);
4334 switch (info_level) {
4335 case SMB_INFO_STANDARD:
4336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4337 data_size = 22;
4338 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4339 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4340 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4341 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4342 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4343 SSVAL(pdata,l1_attrFile,mode);
4344 break;
4346 case SMB_INFO_QUERY_EA_SIZE:
4348 unsigned int ea_size =
4349 estimate_ea_size(conn, fsp,
4350 smb_fname->base_name);
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4352 data_size = 26;
4353 srv_put_dos_date2(pdata,0,create_time);
4354 srv_put_dos_date2(pdata,4,atime);
4355 srv_put_dos_date2(pdata,8,mtime); /* write time */
4356 SIVAL(pdata,12,(uint32)file_size);
4357 SIVAL(pdata,16,(uint32)allocation_size);
4358 SSVAL(pdata,20,mode);
4359 SIVAL(pdata,22,ea_size);
4360 break;
4363 case SMB_INFO_IS_NAME_VALID:
4364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4365 if (fsp) {
4366 /* os/2 needs this ? really ?*/
4367 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4369 /* This is only reached for qpathinfo */
4370 data_size = 0;
4371 break;
4373 case SMB_INFO_QUERY_EAS_FROM_LIST:
4375 size_t total_ea_len = 0;
4376 struct ea_list *ea_file_list = NULL;
4378 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4380 ea_file_list =
4381 get_ea_list_from_file(mem_ctx, conn, fsp,
4382 smb_fname->base_name,
4383 &total_ea_len);
4384 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4386 if (!ea_list || (total_ea_len > data_size)) {
4387 data_size = 4;
4388 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4389 break;
4392 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4393 break;
4396 case SMB_INFO_QUERY_ALL_EAS:
4398 /* We have data_size bytes to put EA's into. */
4399 size_t total_ea_len = 0;
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4403 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4404 smb_fname->base_name,
4405 &total_ea_len);
4406 if (!ea_list || (total_ea_len > data_size)) {
4407 data_size = 4;
4408 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4409 break;
4412 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4413 break;
4416 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4418 /* This is FileFullEaInformation - 0xF which maps to
4419 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4421 /* We have data_size bytes to put EA's into. */
4422 size_t total_ea_len = 0;
4423 struct ea_list *ea_file_list = NULL;
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4427 /*TODO: add filtering and index handling */
4429 ea_file_list =
4430 get_ea_list_from_file(mem_ctx, conn, fsp,
4431 smb_fname->base_name,
4432 &total_ea_len);
4433 if (!ea_file_list) {
4434 return NT_STATUS_NO_EAS_ON_FILE;
4437 status = fill_ea_chained_buffer(mem_ctx,
4438 pdata,
4439 data_size,
4440 &data_size,
4441 conn, ea_file_list);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 return status;
4445 break;
4448 case SMB_FILE_BASIC_INFORMATION:
4449 case SMB_QUERY_FILE_BASIC_INFO:
4451 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4453 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4454 } else {
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4456 data_size = 40;
4457 SIVAL(pdata,36,0);
4459 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4460 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4461 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4462 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4463 SIVAL(pdata,32,mode);
4465 DEBUG(5,("SMB_QFBI - "));
4466 DEBUG(5,("create: %s ", ctime(&create_time)));
4467 DEBUG(5,("access: %s ", ctime(&atime)));
4468 DEBUG(5,("write: %s ", ctime(&mtime)));
4469 DEBUG(5,("change: %s ", ctime(&c_time)));
4470 DEBUG(5,("mode: %x\n", mode));
4471 break;
4473 case SMB_FILE_STANDARD_INFORMATION:
4474 case SMB_QUERY_FILE_STANDARD_INFO:
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4477 data_size = 24;
4478 SOFF_T(pdata,0,allocation_size);
4479 SOFF_T(pdata,8,file_size);
4480 SIVAL(pdata,16,nlink);
4481 SCVAL(pdata,20,delete_pending?1:0);
4482 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4483 SSVAL(pdata,22,0); /* Padding. */
4484 break;
4486 case SMB_FILE_EA_INFORMATION:
4487 case SMB_QUERY_FILE_EA_INFO:
4489 unsigned int ea_size =
4490 estimate_ea_size(conn, fsp, smb_fname->base_name);
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4492 data_size = 4;
4493 SIVAL(pdata,0,ea_size);
4494 break;
4497 /* Get the 8.3 name - used if NT SMB was negotiated. */
4498 case SMB_QUERY_FILE_ALT_NAME_INFO:
4499 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4501 int len;
4502 char mangled_name[13];
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4504 if (!name_to_8_3(base_name,mangled_name,
4505 True,conn->params)) {
4506 return NT_STATUS_NO_MEMORY;
4508 len = srvstr_push(dstart, flags2,
4509 pdata+4, mangled_name,
4510 PTR_DIFF(dend, pdata+4),
4511 STR_UNICODE);
4512 data_size = 4 + len;
4513 SIVAL(pdata,0,len);
4514 break;
4517 case SMB_QUERY_FILE_NAME_INFO:
4519 int len;
4521 this must be *exactly* right for ACLs on mapped drives to work
4523 len = srvstr_push(dstart, flags2,
4524 pdata+4, dos_fname,
4525 PTR_DIFF(dend, pdata+4),
4526 STR_UNICODE);
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4528 data_size = 4 + len;
4529 SIVAL(pdata,0,len);
4530 break;
4533 case SMB_FILE_ALLOCATION_INFORMATION:
4534 case SMB_QUERY_FILE_ALLOCATION_INFO:
4535 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4536 data_size = 8;
4537 SOFF_T(pdata,0,allocation_size);
4538 break;
4540 case SMB_FILE_END_OF_FILE_INFORMATION:
4541 case SMB_QUERY_FILE_END_OF_FILEINFO:
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4543 data_size = 8;
4544 SOFF_T(pdata,0,file_size);
4545 break;
4547 case SMB_QUERY_FILE_ALL_INFO:
4548 case SMB_FILE_ALL_INFORMATION:
4550 int len;
4551 unsigned int ea_size =
4552 estimate_ea_size(conn, fsp, smb_fname->base_name);
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4554 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4555 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4556 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4557 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4558 SIVAL(pdata,32,mode);
4559 SIVAL(pdata,36,0); /* padding. */
4560 pdata += 40;
4561 SOFF_T(pdata,0,allocation_size);
4562 SOFF_T(pdata,8,file_size);
4563 SIVAL(pdata,16,nlink);
4564 SCVAL(pdata,20,delete_pending);
4565 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4566 SSVAL(pdata,22,0);
4567 pdata += 24;
4568 SIVAL(pdata,0,ea_size);
4569 pdata += 4; /* EA info */
4570 len = srvstr_push(dstart, flags2,
4571 pdata+4, dos_fname,
4572 PTR_DIFF(dend, pdata+4),
4573 STR_UNICODE);
4574 SIVAL(pdata,0,len);
4575 pdata += 4 + len;
4576 data_size = PTR_DIFF(pdata,(*ppdata));
4577 break;
4580 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4582 int len;
4583 unsigned int ea_size =
4584 estimate_ea_size(conn, fsp, smb_fname->base_name);
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4586 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4587 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4588 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4589 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4590 SIVAL(pdata, 0x20, mode);
4591 SIVAL(pdata, 0x24, 0); /* padding. */
4592 SBVAL(pdata, 0x28, allocation_size);
4593 SBVAL(pdata, 0x30, file_size);
4594 SIVAL(pdata, 0x38, nlink);
4595 SCVAL(pdata, 0x3C, delete_pending);
4596 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4597 SSVAL(pdata, 0x3E, 0); /* padding */
4598 SBVAL(pdata, 0x40, file_index);
4599 SIVAL(pdata, 0x48, ea_size);
4600 SIVAL(pdata, 0x4C, access_mask);
4601 SBVAL(pdata, 0x50, pos);
4602 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4603 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4605 pdata += 0x60;
4607 len = srvstr_push(dstart, flags2,
4608 pdata+4, dos_fname,
4609 PTR_DIFF(dend, pdata+4),
4610 STR_UNICODE);
4611 SIVAL(pdata,0,len);
4612 pdata += 4 + len;
4613 data_size = PTR_DIFF(pdata,(*ppdata));
4614 break;
4616 case SMB_FILE_INTERNAL_INFORMATION:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4619 SBVAL(pdata, 0, file_index);
4620 data_size = 8;
4621 break;
4623 case SMB_FILE_ACCESS_INFORMATION:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4625 SIVAL(pdata, 0, access_mask);
4626 data_size = 4;
4627 break;
4629 case SMB_FILE_NAME_INFORMATION:
4630 /* Pathname with leading '\'. */
4632 size_t byte_len;
4633 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4635 SIVAL(pdata,0,byte_len);
4636 data_size = 4 + byte_len;
4637 break;
4640 case SMB_FILE_DISPOSITION_INFORMATION:
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4642 data_size = 1;
4643 SCVAL(pdata,0,delete_pending);
4644 break;
4646 case SMB_FILE_POSITION_INFORMATION:
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4648 data_size = 8;
4649 SOFF_T(pdata,0,pos);
4650 break;
4652 case SMB_FILE_MODE_INFORMATION:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4654 SIVAL(pdata,0,mode);
4655 data_size = 4;
4656 break;
4658 case SMB_FILE_ALIGNMENT_INFORMATION:
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4660 SIVAL(pdata,0,0); /* No alignment needed. */
4661 data_size = 4;
4662 break;
4665 * NT4 server just returns "invalid query" to this - if we try
4666 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4667 * want this. JRA.
4669 /* The first statement above is false - verified using Thursby
4670 * client against NT4 -- gcolley.
4672 case SMB_QUERY_FILE_STREAM_INFO:
4673 case SMB_FILE_STREAM_INFORMATION: {
4674 unsigned int num_streams;
4675 struct stream_struct *streams;
4677 DEBUG(10,("smbd_do_qfilepathinfo: "
4678 "SMB_FILE_STREAM_INFORMATION\n"));
4680 if (is_ntfs_stream_smb_fname(smb_fname)) {
4681 return NT_STATUS_INVALID_PARAMETER;
4684 status = SMB_VFS_STREAMINFO(
4685 conn, fsp, smb_fname->base_name, talloc_tos(),
4686 &num_streams, &streams);
4688 if (!NT_STATUS_IS_OK(status)) {
4689 DEBUG(10, ("could not get stream info: %s\n",
4690 nt_errstr(status)));
4691 return status;
4694 status = marshall_stream_info(num_streams, streams,
4695 pdata, max_data_bytes,
4696 &data_size);
4698 if (!NT_STATUS_IS_OK(status)) {
4699 DEBUG(10, ("marshall_stream_info failed: %s\n",
4700 nt_errstr(status)));
4701 return status;
4704 TALLOC_FREE(streams);
4706 break;
4708 case SMB_QUERY_COMPRESSION_INFO:
4709 case SMB_FILE_COMPRESSION_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4711 SOFF_T(pdata,0,file_size);
4712 SIVAL(pdata,8,0); /* ??? */
4713 SIVAL(pdata,12,0); /* ??? */
4714 data_size = 16;
4715 break;
4717 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4719 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4722 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4723 SOFF_T(pdata,32,allocation_size);
4724 SOFF_T(pdata,40,file_size);
4725 SIVAL(pdata,48,mode);
4726 SIVAL(pdata,52,0); /* ??? */
4727 data_size = 56;
4728 break;
4730 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4732 SIVAL(pdata,0,mode);
4733 SIVAL(pdata,4,0);
4734 data_size = 8;
4735 break;
4738 * CIFS UNIX Extensions.
4741 case SMB_QUERY_FILE_UNIX_BASIC:
4743 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4744 data_size = PTR_DIFF(pdata,(*ppdata));
4746 DEBUG(4,("smbd_do_qfilepathinfo: "
4747 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4748 dump_data(4, (uint8_t *)(*ppdata), data_size);
4750 break;
4752 case SMB_QUERY_FILE_UNIX_INFO2:
4754 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4755 data_size = PTR_DIFF(pdata,(*ppdata));
4758 int i;
4759 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4761 for (i=0; i<100; i++)
4762 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4763 DEBUG(4,("\n"));
4766 break;
4768 case SMB_QUERY_FILE_UNIX_LINK:
4770 int len;
4771 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4773 if (!buffer) {
4774 return NT_STATUS_NO_MEMORY;
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4778 #ifdef S_ISLNK
4779 if(!S_ISLNK(psbuf->st_ex_mode)) {
4780 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4782 #else
4783 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4784 #endif
4785 len = SMB_VFS_READLINK(conn,
4786 smb_fname->base_name,
4787 buffer, PATH_MAX);
4788 if (len == -1) {
4789 return map_nt_error_from_unix(errno);
4791 buffer[len] = 0;
4792 len = srvstr_push(dstart, flags2,
4793 pdata, buffer,
4794 PTR_DIFF(dend, pdata),
4795 STR_TERMINATE);
4796 pdata += len;
4797 data_size = PTR_DIFF(pdata,(*ppdata));
4799 break;
4802 #if defined(HAVE_POSIX_ACLS)
4803 case SMB_QUERY_POSIX_ACL:
4805 SMB_ACL_T file_acl = NULL;
4806 SMB_ACL_T def_acl = NULL;
4807 uint16 num_file_acls = 0;
4808 uint16 num_def_acls = 0;
4810 if (fsp && fsp->fh->fd != -1) {
4811 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4812 } else {
4813 file_acl =
4814 SMB_VFS_SYS_ACL_GET_FILE(conn,
4815 smb_fname->base_name,
4816 SMB_ACL_TYPE_ACCESS);
4819 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4820 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4821 "not implemented on "
4822 "filesystem containing %s\n",
4823 smb_fname->base_name));
4824 return NT_STATUS_NOT_IMPLEMENTED;
4827 if (S_ISDIR(psbuf->st_ex_mode)) {
4828 if (fsp && fsp->is_directory) {
4829 def_acl =
4830 SMB_VFS_SYS_ACL_GET_FILE(
4831 conn,
4832 fsp->fsp_name->base_name,
4833 SMB_ACL_TYPE_DEFAULT);
4834 } else {
4835 def_acl =
4836 SMB_VFS_SYS_ACL_GET_FILE(
4837 conn,
4838 smb_fname->base_name,
4839 SMB_ACL_TYPE_DEFAULT);
4841 def_acl = free_empty_sys_acl(conn, def_acl);
4844 num_file_acls = count_acl_entries(conn, file_acl);
4845 num_def_acls = count_acl_entries(conn, def_acl);
4847 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4848 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4849 data_size,
4850 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4851 SMB_POSIX_ACL_HEADER_SIZE) ));
4852 if (file_acl) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4855 if (def_acl) {
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4858 return NT_STATUS_BUFFER_TOO_SMALL;
4861 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4862 SSVAL(pdata,2,num_file_acls);
4863 SSVAL(pdata,4,num_def_acls);
4864 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4865 if (file_acl) {
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4868 if (def_acl) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4871 return NT_STATUS_INTERNAL_ERROR;
4873 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4874 if (file_acl) {
4875 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4877 if (def_acl) {
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4880 return NT_STATUS_INTERNAL_ERROR;
4883 if (file_acl) {
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4886 if (def_acl) {
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4889 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4890 break;
4892 #endif
4895 case SMB_QUERY_POSIX_LOCK:
4897 uint64_t count;
4898 uint64_t offset;
4899 uint64_t smblctx;
4900 enum brl_type lock_type;
4902 /* We need an open file with a real fd for this. */
4903 if (!fsp || fsp->fh->fd == -1) {
4904 return NT_STATUS_INVALID_LEVEL;
4907 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4908 return NT_STATUS_INVALID_PARAMETER;
4911 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4912 case POSIX_LOCK_TYPE_READ:
4913 lock_type = READ_LOCK;
4914 break;
4915 case POSIX_LOCK_TYPE_WRITE:
4916 lock_type = WRITE_LOCK;
4917 break;
4918 case POSIX_LOCK_TYPE_UNLOCK:
4919 default:
4920 /* There's no point in asking for an unlock... */
4921 return NT_STATUS_INVALID_PARAMETER;
4924 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4925 #if defined(HAVE_LONGLONG)
4926 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4927 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4928 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4929 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4930 #else /* HAVE_LONGLONG */
4931 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4932 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4933 #endif /* HAVE_LONGLONG */
4935 status = query_lock(fsp,
4936 &smblctx,
4937 &count,
4938 &offset,
4939 &lock_type,
4940 POSIX_LOCK);
4942 if (ERROR_WAS_LOCK_DENIED(status)) {
4943 /* Here we need to report who has it locked... */
4944 data_size = POSIX_LOCK_DATA_SIZE;
4946 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4947 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4948 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4949 #if defined(HAVE_LONGLONG)
4950 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4951 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4952 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4953 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4954 #else /* HAVE_LONGLONG */
4955 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4956 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4957 #endif /* HAVE_LONGLONG */
4959 } else if (NT_STATUS_IS_OK(status)) {
4960 /* For success we just return a copy of what we sent
4961 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4962 data_size = POSIX_LOCK_DATA_SIZE;
4963 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4964 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4965 } else {
4966 return status;
4968 break;
4971 default:
4972 return NT_STATUS_INVALID_LEVEL;
4975 *pdata_size = data_size;
4976 return NT_STATUS_OK;
4979 /****************************************************************************
4980 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4981 file name or file id).
4982 ****************************************************************************/
4984 static void call_trans2qfilepathinfo(connection_struct *conn,
4985 struct smb_request *req,
4986 unsigned int tran_call,
4987 char **pparams, int total_params,
4988 char **ppdata, int total_data,
4989 unsigned int max_data_bytes)
4991 char *params = *pparams;
4992 char *pdata = *ppdata;
4993 uint16 info_level;
4994 unsigned int data_size = 0;
4995 unsigned int param_size = 2;
4996 struct smb_filename *smb_fname = NULL;
4997 bool delete_pending = False;
4998 struct timespec write_time_ts;
4999 files_struct *fsp = NULL;
5000 struct file_id fileid;
5001 struct ea_list *ea_list = NULL;
5002 int lock_data_count = 0;
5003 char *lock_data = NULL;
5004 NTSTATUS status = NT_STATUS_OK;
5006 if (!params) {
5007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5008 return;
5011 ZERO_STRUCT(write_time_ts);
5013 if (tran_call == TRANSACT2_QFILEINFO) {
5014 if (total_params < 4) {
5015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5016 return;
5019 if (IS_IPC(conn)) {
5020 call_trans2qpipeinfo(conn, req, tran_call,
5021 pparams, total_params,
5022 ppdata, total_data,
5023 max_data_bytes);
5024 return;
5027 fsp = file_fsp(req, SVAL(params,0));
5028 info_level = SVAL(params,2);
5030 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5032 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5033 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5034 return;
5037 /* Initial check for valid fsp ptr. */
5038 if (!check_fsp_open(conn, req, fsp)) {
5039 return;
5042 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5043 &smb_fname);
5044 if (!NT_STATUS_IS_OK(status)) {
5045 reply_nterror(req, status);
5046 return;
5049 if(fsp->fake_file_handle) {
5051 * This is actually for the QUOTA_FAKE_FILE --metze
5054 /* We know this name is ok, it's already passed the checks. */
5056 } else if(fsp->fh->fd == -1) {
5058 * This is actually a QFILEINFO on a directory
5059 * handle (returned from an NT SMB). NT5.0 seems
5060 * to do this call. JRA.
5063 if (INFO_LEVEL_IS_UNIX(info_level)) {
5064 /* Always do lstat for UNIX calls. */
5065 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5066 DEBUG(3,("call_trans2qfilepathinfo: "
5067 "SMB_VFS_LSTAT of %s failed "
5068 "(%s)\n",
5069 smb_fname_str_dbg(smb_fname),
5070 strerror(errno)));
5071 reply_nterror(req,
5072 map_nt_error_from_unix(errno));
5073 return;
5075 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5076 DEBUG(3,("call_trans2qfilepathinfo: "
5077 "SMB_VFS_STAT of %s failed (%s)\n",
5078 smb_fname_str_dbg(smb_fname),
5079 strerror(errno)));
5080 reply_nterror(req,
5081 map_nt_error_from_unix(errno));
5082 return;
5085 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5086 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5087 } else {
5089 * Original code - this is an open file.
5091 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5092 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5093 fsp->fnum, strerror(errno)));
5094 reply_nterror(req,
5095 map_nt_error_from_unix(errno));
5096 return;
5098 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5099 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5102 } else {
5103 uint32_t name_hash;
5104 char *fname = NULL;
5106 /* qpathinfo */
5107 if (total_params < 7) {
5108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5109 return;
5112 info_level = SVAL(params,0);
5114 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5116 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5117 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5118 return;
5121 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5122 total_params - 6,
5123 STR_TERMINATE, &status);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 reply_nterror(req, status);
5126 return;
5129 status = filename_convert(req,
5130 conn,
5131 req->flags2 & FLAGS2_DFS_PATHNAMES,
5132 fname,
5134 NULL,
5135 &smb_fname);
5136 if (!NT_STATUS_IS_OK(status)) {
5137 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5138 reply_botherror(req,
5139 NT_STATUS_PATH_NOT_COVERED,
5140 ERRSRV, ERRbadpath);
5141 return;
5143 reply_nterror(req, status);
5144 return;
5147 /* If this is a stream, check if there is a delete_pending. */
5148 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5149 && is_ntfs_stream_smb_fname(smb_fname)) {
5150 struct smb_filename *smb_fname_base = NULL;
5152 /* Create an smb_filename with stream_name == NULL. */
5153 status =
5154 create_synthetic_smb_fname(talloc_tos(),
5155 smb_fname->base_name,
5156 NULL, NULL,
5157 &smb_fname_base);
5158 if (!NT_STATUS_IS_OK(status)) {
5159 reply_nterror(req, status);
5160 return;
5163 if (INFO_LEVEL_IS_UNIX(info_level)) {
5164 /* Always do lstat for UNIX calls. */
5165 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5166 DEBUG(3,("call_trans2qfilepathinfo: "
5167 "SMB_VFS_LSTAT of %s failed "
5168 "(%s)\n",
5169 smb_fname_str_dbg(smb_fname_base),
5170 strerror(errno)));
5171 TALLOC_FREE(smb_fname_base);
5172 reply_nterror(req,
5173 map_nt_error_from_unix(errno));
5174 return;
5176 } else {
5177 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "fileinfo of %s failed "
5180 "(%s)\n",
5181 smb_fname_str_dbg(smb_fname_base),
5182 strerror(errno)));
5183 TALLOC_FREE(smb_fname_base);
5184 reply_nterror(req,
5185 map_nt_error_from_unix(errno));
5186 return;
5190 status = file_name_hash(conn,
5191 smb_fname_str_dbg(smb_fname_base),
5192 &name_hash);
5193 if (!NT_STATUS_IS_OK(status)) {
5194 TALLOC_FREE(smb_fname_base);
5195 reply_nterror(req, status);
5196 return;
5199 fileid = vfs_file_id_from_sbuf(conn,
5200 &smb_fname_base->st);
5201 TALLOC_FREE(smb_fname_base);
5202 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5203 if (delete_pending) {
5204 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5205 return;
5209 if (INFO_LEVEL_IS_UNIX(info_level)) {
5210 /* Always do lstat for UNIX calls. */
5211 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5212 DEBUG(3,("call_trans2qfilepathinfo: "
5213 "SMB_VFS_LSTAT of %s failed (%s)\n",
5214 smb_fname_str_dbg(smb_fname),
5215 strerror(errno)));
5216 reply_nterror(req,
5217 map_nt_error_from_unix(errno));
5218 return;
5221 } else {
5222 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5223 DEBUG(3,("call_trans2qfilepathinfo: "
5224 "SMB_VFS_STAT of %s failed (%s)\n",
5225 smb_fname_str_dbg(smb_fname),
5226 strerror(errno)));
5227 reply_nterror(req,
5228 map_nt_error_from_unix(errno));
5229 return;
5233 status = file_name_hash(conn,
5234 smb_fname_str_dbg(smb_fname),
5235 &name_hash);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 reply_nterror(req, status);
5238 return;
5241 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5242 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5243 if (delete_pending) {
5244 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5245 return;
5249 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5250 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5251 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5253 /* Pull out any data sent here before we realloc. */
5254 switch (info_level) {
5255 case SMB_INFO_QUERY_EAS_FROM_LIST:
5257 /* Pull any EA list from the data portion. */
5258 uint32 ea_size;
5260 if (total_data < 4) {
5261 reply_nterror(
5262 req, NT_STATUS_INVALID_PARAMETER);
5263 return;
5265 ea_size = IVAL(pdata,0);
5267 if (total_data > 0 && ea_size != total_data) {
5268 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5269 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5270 reply_nterror(
5271 req, NT_STATUS_INVALID_PARAMETER);
5272 return;
5275 if (!lp_ea_support(SNUM(conn))) {
5276 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5277 return;
5280 /* Pull out the list of names. */
5281 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5282 if (!ea_list) {
5283 reply_nterror(
5284 req, NT_STATUS_INVALID_PARAMETER);
5285 return;
5287 break;
5290 case SMB_QUERY_POSIX_LOCK:
5292 if (fsp == NULL || fsp->fh->fd == -1) {
5293 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5294 return;
5297 if (total_data != POSIX_LOCK_DATA_SIZE) {
5298 reply_nterror(
5299 req, NT_STATUS_INVALID_PARAMETER);
5300 return;
5303 /* Copy the lock range data. */
5304 lock_data = (char *)talloc_memdup(
5305 req, pdata, total_data);
5306 if (!lock_data) {
5307 reply_nterror(req, NT_STATUS_NO_MEMORY);
5308 return;
5310 lock_data_count = total_data;
5312 default:
5313 break;
5316 *pparams = (char *)SMB_REALLOC(*pparams,2);
5317 if (*pparams == NULL) {
5318 reply_nterror(req, NT_STATUS_NO_MEMORY);
5319 return;
5321 params = *pparams;
5322 SSVAL(params,0,0);
5325 * draft-leach-cifs-v1-spec-02.txt
5326 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5327 * says:
5329 * The requested information is placed in the Data portion of the
5330 * transaction response. For the information levels greater than 0x100,
5331 * the transaction response has 1 parameter word which should be
5332 * ignored by the client.
5334 * However Windows only follows this rule for the IS_NAME_VALID call.
5336 switch (info_level) {
5337 case SMB_INFO_IS_NAME_VALID:
5338 param_size = 0;
5339 break;
5342 if ((info_level & 0xFF00) == 0xFF00) {
5344 * We use levels that start with 0xFF00
5345 * internally to represent SMB2 specific levels
5347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5348 return;
5351 status = smbd_do_qfilepathinfo(conn, req, info_level,
5352 fsp, smb_fname,
5353 delete_pending, write_time_ts,
5354 ea_list,
5355 lock_data_count, lock_data,
5356 req->flags2, max_data_bytes,
5357 ppdata, &data_size);
5358 if (!NT_STATUS_IS_OK(status)) {
5359 reply_nterror(req, status);
5360 return;
5363 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5364 max_data_bytes);
5366 return;
5369 /****************************************************************************
5370 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5371 code.
5372 ****************************************************************************/
5374 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5375 connection_struct *conn,
5376 struct smb_request *req,
5377 bool overwrite_if_exists,
5378 const struct smb_filename *smb_fname_old,
5379 struct smb_filename *smb_fname_new)
5381 NTSTATUS status = NT_STATUS_OK;
5383 /* source must already exist. */
5384 if (!VALID_STAT(smb_fname_old->st)) {
5385 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5388 if (VALID_STAT(smb_fname_new->st)) {
5389 if (overwrite_if_exists) {
5390 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5391 return NT_STATUS_FILE_IS_A_DIRECTORY;
5393 status = unlink_internals(conn,
5394 req,
5395 FILE_ATTRIBUTE_NORMAL,
5396 smb_fname_new,
5397 false);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 return status;
5401 } else {
5402 /* Disallow if newname already exists. */
5403 return NT_STATUS_OBJECT_NAME_COLLISION;
5407 /* No links from a directory. */
5408 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5409 return NT_STATUS_FILE_IS_A_DIRECTORY;
5412 /* Setting a hardlink to/from a stream isn't currently supported. */
5413 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5414 is_ntfs_stream_smb_fname(smb_fname_new)) {
5415 return NT_STATUS_INVALID_PARAMETER;
5418 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5419 smb_fname_old->base_name, smb_fname_new->base_name));
5421 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5422 smb_fname_new->base_name) != 0) {
5423 status = map_nt_error_from_unix(errno);
5424 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5425 nt_errstr(status), smb_fname_old->base_name,
5426 smb_fname_new->base_name));
5428 return status;
5431 /****************************************************************************
5432 Deal with setting the time from any of the setfilepathinfo functions.
5433 ****************************************************************************/
5435 NTSTATUS smb_set_file_time(connection_struct *conn,
5436 files_struct *fsp,
5437 const struct smb_filename *smb_fname,
5438 struct smb_file_time *ft,
5439 bool setting_write_time)
5441 struct smb_filename smb_fname_base;
5442 uint32 action =
5443 FILE_NOTIFY_CHANGE_LAST_ACCESS
5444 |FILE_NOTIFY_CHANGE_LAST_WRITE
5445 |FILE_NOTIFY_CHANGE_CREATION;
5447 if (!VALID_STAT(smb_fname->st)) {
5448 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5451 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5452 return NT_STATUS_ACCESS_DENIED;
5455 /* get some defaults (no modifications) if any info is zero or -1. */
5456 if (null_timespec(ft->create_time)) {
5457 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5460 if (null_timespec(ft->atime)) {
5461 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5464 if (null_timespec(ft->mtime)) {
5465 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5468 if (!setting_write_time) {
5469 /* ft->mtime comes from change time, not write time. */
5470 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5473 /* Ensure the resolution is the correct for
5474 * what we can store on this filesystem. */
5476 round_timespec(conn->ts_res, &ft->create_time);
5477 round_timespec(conn->ts_res, &ft->ctime);
5478 round_timespec(conn->ts_res, &ft->atime);
5479 round_timespec(conn->ts_res, &ft->mtime);
5481 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5482 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5483 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5485 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5487 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5488 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5490 if (setting_write_time) {
5492 * This was a Windows setfileinfo on an open file.
5493 * NT does this a lot. We also need to
5494 * set the time here, as it can be read by
5495 * FindFirst/FindNext and with the patch for bug #2045
5496 * in smbd/fileio.c it ensures that this timestamp is
5497 * kept sticky even after a write. We save the request
5498 * away and will set it on file close and after a write. JRA.
5501 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5502 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5504 if (fsp != NULL) {
5505 if (fsp->base_fsp) {
5506 set_sticky_write_time_fsp(fsp->base_fsp,
5507 ft->mtime);
5508 } else {
5509 set_sticky_write_time_fsp(fsp, ft->mtime);
5511 } else {
5512 set_sticky_write_time_path(
5513 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5514 ft->mtime);
5518 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5520 /* Always call ntimes on the base, even if a stream was passed in. */
5521 smb_fname_base = *smb_fname;
5522 smb_fname_base.stream_name = NULL;
5524 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5525 return map_nt_error_from_unix(errno);
5528 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5529 smb_fname->base_name);
5530 return NT_STATUS_OK;
5533 /****************************************************************************
5534 Deal with setting the dosmode from any of the setfilepathinfo functions.
5535 ****************************************************************************/
5537 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5538 const struct smb_filename *smb_fname,
5539 uint32 dosmode)
5541 struct smb_filename *smb_fname_base = NULL;
5542 NTSTATUS status;
5544 if (!VALID_STAT(smb_fname->st)) {
5545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5548 /* Always operate on the base_name, even if a stream was passed in. */
5549 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5550 NULL, &smb_fname->st,
5551 &smb_fname_base);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 return status;
5556 if (dosmode) {
5557 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5558 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5559 } else {
5560 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5564 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5566 /* check the mode isn't different, before changing it */
5567 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5568 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5569 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5570 (unsigned int)dosmode));
5572 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5573 false)) {
5574 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5575 "%s failed (%s)\n",
5576 smb_fname_str_dbg(smb_fname_base),
5577 strerror(errno)));
5578 status = map_nt_error_from_unix(errno);
5579 goto out;
5582 status = NT_STATUS_OK;
5583 out:
5584 TALLOC_FREE(smb_fname_base);
5585 return status;
5588 /****************************************************************************
5589 Deal with setting the size from any of the setfilepathinfo functions.
5590 ****************************************************************************/
5592 static NTSTATUS smb_set_file_size(connection_struct *conn,
5593 struct smb_request *req,
5594 files_struct *fsp,
5595 const struct smb_filename *smb_fname,
5596 const SMB_STRUCT_STAT *psbuf,
5597 SMB_OFF_T size,
5598 bool fail_after_createfile)
5600 NTSTATUS status = NT_STATUS_OK;
5601 struct smb_filename *smb_fname_tmp = NULL;
5602 files_struct *new_fsp = NULL;
5604 if (!VALID_STAT(*psbuf)) {
5605 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5608 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5609 return NT_STATUS_ACCESS_DENIED;
5612 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5614 if (size == get_file_size_stat(psbuf)) {
5615 return NT_STATUS_OK;
5618 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5619 smb_fname_str_dbg(smb_fname), (double)size));
5621 if (fsp && fsp->fh->fd != -1) {
5622 /* Handle based call. */
5623 if (vfs_set_filelen(fsp, size) == -1) {
5624 return map_nt_error_from_unix(errno);
5626 trigger_write_time_update_immediate(fsp);
5627 return NT_STATUS_OK;
5630 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5631 if (!NT_STATUS_IS_OK(status)) {
5632 return status;
5635 smb_fname_tmp->st = *psbuf;
5637 status = SMB_VFS_CREATE_FILE(
5638 conn, /* conn */
5639 req, /* req */
5640 0, /* root_dir_fid */
5641 smb_fname_tmp, /* fname */
5642 FILE_WRITE_DATA, /* access_mask */
5643 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5644 FILE_SHARE_DELETE),
5645 FILE_OPEN, /* create_disposition*/
5646 0, /* create_options */
5647 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5648 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5649 0, /* allocation_size */
5650 0, /* private_flags */
5651 NULL, /* sd */
5652 NULL, /* ea_list */
5653 &new_fsp, /* result */
5654 NULL); /* pinfo */
5656 TALLOC_FREE(smb_fname_tmp);
5658 if (!NT_STATUS_IS_OK(status)) {
5659 /* NB. We check for open_was_deferred in the caller. */
5660 return status;
5663 /* See RAW-SFILEINFO-END-OF-FILE */
5664 if (fail_after_createfile) {
5665 close_file(req, new_fsp,NORMAL_CLOSE);
5666 return NT_STATUS_INVALID_LEVEL;
5669 if (vfs_set_filelen(new_fsp, size) == -1) {
5670 status = map_nt_error_from_unix(errno);
5671 close_file(req, new_fsp,NORMAL_CLOSE);
5672 return status;
5675 trigger_write_time_update_immediate(new_fsp);
5676 close_file(req, new_fsp,NORMAL_CLOSE);
5677 return NT_STATUS_OK;
5680 /****************************************************************************
5681 Deal with SMB_INFO_SET_EA.
5682 ****************************************************************************/
5684 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5685 const char *pdata,
5686 int total_data,
5687 files_struct *fsp,
5688 const struct smb_filename *smb_fname)
5690 struct ea_list *ea_list = NULL;
5691 TALLOC_CTX *ctx = NULL;
5692 NTSTATUS status = NT_STATUS_OK;
5694 if (total_data < 10) {
5696 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5697 length. They seem to have no effect. Bug #3212. JRA */
5699 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5700 /* We're done. We only get EA info in this call. */
5701 return NT_STATUS_OK;
5704 return NT_STATUS_INVALID_PARAMETER;
5707 if (IVAL(pdata,0) > total_data) {
5708 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5709 IVAL(pdata,0), (unsigned int)total_data));
5710 return NT_STATUS_INVALID_PARAMETER;
5713 ctx = talloc_tos();
5714 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5715 if (!ea_list) {
5716 return NT_STATUS_INVALID_PARAMETER;
5719 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5720 return NT_STATUS_ACCESS_DENIED;
5723 status = set_ea(conn, fsp, smb_fname, ea_list);
5725 return status;
5728 /****************************************************************************
5729 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5730 ****************************************************************************/
5732 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5733 const char *pdata,
5734 int total_data,
5735 files_struct *fsp)
5737 struct ea_list *ea_list = NULL;
5738 NTSTATUS status;
5740 if (!fsp) {
5741 return NT_STATUS_INVALID_HANDLE;
5744 if (!lp_ea_support(SNUM(conn))) {
5745 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5746 "EA's not supported.\n",
5747 (unsigned int)total_data));
5748 return NT_STATUS_EAS_NOT_SUPPORTED;
5751 if (total_data < 10) {
5752 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5753 "too small.\n",
5754 (unsigned int)total_data));
5755 return NT_STATUS_INVALID_PARAMETER;
5758 ea_list = read_nttrans_ea_list(talloc_tos(),
5759 pdata,
5760 total_data);
5762 if (!ea_list) {
5763 return NT_STATUS_INVALID_PARAMETER;
5766 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5767 return NT_STATUS_ACCESS_DENIED;
5770 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5772 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5773 smb_fname_str_dbg(fsp->fsp_name),
5774 nt_errstr(status) ));
5776 return status;
5780 /****************************************************************************
5781 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5782 ****************************************************************************/
5784 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5785 const char *pdata,
5786 int total_data,
5787 files_struct *fsp,
5788 struct smb_filename *smb_fname)
5790 NTSTATUS status = NT_STATUS_OK;
5791 bool delete_on_close;
5792 uint32 dosmode = 0;
5794 if (total_data < 1) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 if (fsp == NULL) {
5799 return NT_STATUS_INVALID_HANDLE;
5802 delete_on_close = (CVAL(pdata,0) ? True : False);
5803 dosmode = dos_mode(conn, smb_fname);
5805 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5806 "delete_on_close = %u\n",
5807 smb_fname_str_dbg(smb_fname),
5808 (unsigned int)dosmode,
5809 (unsigned int)delete_on_close ));
5811 if (delete_on_close) {
5812 status = can_set_delete_on_close(fsp, dosmode);
5813 if (!NT_STATUS_IS_OK(status)) {
5814 return status;
5818 /* The set is across all open files on this dev/inode pair. */
5819 if (!set_delete_on_close(fsp, delete_on_close,
5820 conn->session_info->unix_token)) {
5821 return NT_STATUS_ACCESS_DENIED;
5823 return NT_STATUS_OK;
5826 /****************************************************************************
5827 Deal with SMB_FILE_POSITION_INFORMATION.
5828 ****************************************************************************/
5830 static NTSTATUS smb_file_position_information(connection_struct *conn,
5831 const char *pdata,
5832 int total_data,
5833 files_struct *fsp)
5835 uint64_t position_information;
5837 if (total_data < 8) {
5838 return NT_STATUS_INVALID_PARAMETER;
5841 if (fsp == NULL) {
5842 /* Ignore on pathname based set. */
5843 return NT_STATUS_OK;
5846 position_information = (uint64_t)IVAL(pdata,0);
5847 #ifdef LARGE_SMB_OFF_T
5848 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5849 #else /* LARGE_SMB_OFF_T */
5850 if (IVAL(pdata,4) != 0) {
5851 /* more than 32 bits? */
5852 return NT_STATUS_INVALID_PARAMETER;
5854 #endif /* LARGE_SMB_OFF_T */
5856 DEBUG(10,("smb_file_position_information: Set file position "
5857 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5858 (double)position_information));
5859 fsp->fh->position_information = position_information;
5860 return NT_STATUS_OK;
5863 /****************************************************************************
5864 Deal with SMB_FILE_MODE_INFORMATION.
5865 ****************************************************************************/
5867 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5868 const char *pdata,
5869 int total_data)
5871 uint32 mode;
5873 if (total_data < 4) {
5874 return NT_STATUS_INVALID_PARAMETER;
5876 mode = IVAL(pdata,0);
5877 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5878 return NT_STATUS_INVALID_PARAMETER;
5880 return NT_STATUS_OK;
5883 /****************************************************************************
5884 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5885 ****************************************************************************/
5887 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5888 struct smb_request *req,
5889 const char *pdata,
5890 int total_data,
5891 const struct smb_filename *smb_fname)
5893 char *link_target = NULL;
5894 const char *newname = smb_fname->base_name;
5895 TALLOC_CTX *ctx = talloc_tos();
5897 /* Set a symbolic link. */
5898 /* Don't allow this if follow links is false. */
5900 if (total_data == 0) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 if (!lp_symlinks(SNUM(conn))) {
5905 return NT_STATUS_ACCESS_DENIED;
5908 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5909 total_data, STR_TERMINATE);
5911 if (!link_target) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5916 newname, link_target ));
5918 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5919 return map_nt_error_from_unix(errno);
5922 return NT_STATUS_OK;
5925 /****************************************************************************
5926 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5927 ****************************************************************************/
5929 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5930 struct smb_request *req,
5931 const char *pdata, int total_data,
5932 struct smb_filename *smb_fname_new)
5934 char *oldname = NULL;
5935 struct smb_filename *smb_fname_old = NULL;
5936 TALLOC_CTX *ctx = talloc_tos();
5937 NTSTATUS status = NT_STATUS_OK;
5939 /* Set a hard link. */
5940 if (total_data == 0) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5945 total_data, STR_TERMINATE, &status);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 return status;
5950 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5951 smb_fname_str_dbg(smb_fname_new), oldname));
5953 status = filename_convert(ctx,
5954 conn,
5955 req->flags2 & FLAGS2_DFS_PATHNAMES,
5956 oldname,
5958 NULL,
5959 &smb_fname_old);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 return status;
5964 return hardlink_internals(ctx, conn, req, false,
5965 smb_fname_old, smb_fname_new);
5968 /****************************************************************************
5969 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5970 ****************************************************************************/
5972 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5973 struct smb_request *req,
5974 const char *pdata,
5975 int total_data,
5976 files_struct *fsp,
5977 struct smb_filename *smb_fname_src)
5979 bool overwrite;
5980 uint32_t len;
5981 char *newname = NULL;
5982 struct smb_filename *smb_fname_dst = NULL;
5983 NTSTATUS status = NT_STATUS_OK;
5984 TALLOC_CTX *ctx = talloc_tos();
5986 if (!fsp) {
5987 return NT_STATUS_INVALID_HANDLE;
5990 if (total_data < 20) {
5991 return NT_STATUS_INVALID_PARAMETER;
5994 overwrite = (CVAL(pdata,0) ? True : False);
5995 len = IVAL(pdata,16);
5997 if (len > (total_data - 20) || (len == 0)) {
5998 return NT_STATUS_INVALID_PARAMETER;
6001 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6002 &pdata[20], len, STR_TERMINATE,
6003 &status);
6004 if (!NT_STATUS_IS_OK(status)) {
6005 return status;
6008 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6009 newname));
6011 status = filename_convert(ctx,
6012 conn,
6013 req->flags2 & FLAGS2_DFS_PATHNAMES,
6014 newname,
6015 UCF_SAVE_LCOMP,
6016 NULL,
6017 &smb_fname_dst);
6018 if (!NT_STATUS_IS_OK(status)) {
6019 return status;
6022 if (fsp->base_fsp) {
6023 /* newname must be a stream name. */
6024 if (newname[0] != ':') {
6025 return NT_STATUS_NOT_SUPPORTED;
6028 /* Create an smb_fname to call rename_internals_fsp() with. */
6029 status = create_synthetic_smb_fname(talloc_tos(),
6030 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6031 &smb_fname_dst);
6032 if (!NT_STATUS_IS_OK(status)) {
6033 goto out;
6037 * Set the original last component, since
6038 * rename_internals_fsp() requires it.
6040 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6041 newname);
6042 if (smb_fname_dst->original_lcomp == NULL) {
6043 status = NT_STATUS_NO_MEMORY;
6044 goto out;
6049 DEBUG(10,("smb2_file_rename_information: "
6050 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6051 fsp->fnum, fsp_str_dbg(fsp),
6052 smb_fname_str_dbg(smb_fname_dst)));
6053 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6054 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6055 overwrite);
6057 out:
6058 TALLOC_FREE(smb_fname_dst);
6059 return status;
6062 static NTSTATUS smb_file_link_information(connection_struct *conn,
6063 struct smb_request *req,
6064 const char *pdata,
6065 int total_data,
6066 files_struct *fsp,
6067 struct smb_filename *smb_fname_src)
6069 bool overwrite;
6070 uint32_t len;
6071 char *newname = NULL;
6072 struct smb_filename *smb_fname_dst = NULL;
6073 NTSTATUS status = NT_STATUS_OK;
6074 TALLOC_CTX *ctx = talloc_tos();
6076 if (!fsp) {
6077 return NT_STATUS_INVALID_HANDLE;
6080 if (total_data < 20) {
6081 return NT_STATUS_INVALID_PARAMETER;
6084 overwrite = (CVAL(pdata,0) ? true : false);
6085 len = IVAL(pdata,16);
6087 if (len > (total_data - 20) || (len == 0)) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6092 &pdata[20], len, STR_TERMINATE,
6093 &status);
6094 if (!NT_STATUS_IS_OK(status)) {
6095 return status;
6098 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6099 newname));
6101 status = filename_convert(ctx,
6102 conn,
6103 req->flags2 & FLAGS2_DFS_PATHNAMES,
6104 newname,
6105 UCF_SAVE_LCOMP,
6106 NULL,
6107 &smb_fname_dst);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 return status;
6112 if (fsp->base_fsp) {
6113 /* No stream names. */
6114 return NT_STATUS_NOT_SUPPORTED;
6117 DEBUG(10,("smb_file_link_information: "
6118 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6119 fsp->fnum, fsp_str_dbg(fsp),
6120 smb_fname_str_dbg(smb_fname_dst)));
6121 status = hardlink_internals(ctx,
6122 conn,
6123 req,
6124 overwrite,
6125 fsp->fsp_name,
6126 smb_fname_dst);
6128 TALLOC_FREE(smb_fname_dst);
6129 return status;
6132 /****************************************************************************
6133 Deal with SMB_FILE_RENAME_INFORMATION.
6134 ****************************************************************************/
6136 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6137 struct smb_request *req,
6138 const char *pdata,
6139 int total_data,
6140 files_struct *fsp,
6141 struct smb_filename *smb_fname_src)
6143 bool overwrite;
6144 uint32 root_fid;
6145 uint32 len;
6146 char *newname = NULL;
6147 struct smb_filename *smb_fname_dst = NULL;
6148 bool dest_has_wcard = False;
6149 NTSTATUS status = NT_STATUS_OK;
6150 char *p;
6151 TALLOC_CTX *ctx = talloc_tos();
6153 if (total_data < 13) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 overwrite = (CVAL(pdata,0) ? True : False);
6158 root_fid = IVAL(pdata,4);
6159 len = IVAL(pdata,8);
6161 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6166 len, 0, &status,
6167 &dest_has_wcard);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 return status;
6172 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6173 newname));
6175 status = resolve_dfspath_wcard(ctx, conn,
6176 req->flags2 & FLAGS2_DFS_PATHNAMES,
6177 newname,
6178 true,
6179 &newname,
6180 &dest_has_wcard);
6181 if (!NT_STATUS_IS_OK(status)) {
6182 return status;
6185 /* Check the new name has no '/' characters. */
6186 if (strchr_m(newname, '/')) {
6187 return NT_STATUS_NOT_SUPPORTED;
6190 if (fsp && fsp->base_fsp) {
6191 /* newname must be a stream name. */
6192 if (newname[0] != ':') {
6193 return NT_STATUS_NOT_SUPPORTED;
6196 /* Create an smb_fname to call rename_internals_fsp() with. */
6197 status = create_synthetic_smb_fname(talloc_tos(),
6198 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6199 &smb_fname_dst);
6200 if (!NT_STATUS_IS_OK(status)) {
6201 goto out;
6205 * Set the original last component, since
6206 * rename_internals_fsp() requires it.
6208 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6209 newname);
6210 if (smb_fname_dst->original_lcomp == NULL) {
6211 status = NT_STATUS_NO_MEMORY;
6212 goto out;
6215 } else {
6217 * Build up an smb_fname_dst based on the filename passed in.
6218 * We basically just strip off the last component, and put on
6219 * the newname instead.
6221 char *base_name = NULL;
6223 /* newname must *not* be a stream name. */
6224 if (newname[0] == ':') {
6225 return NT_STATUS_NOT_SUPPORTED;
6229 * Strip off the last component (filename) of the path passed
6230 * in.
6232 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6233 if (!base_name) {
6234 return NT_STATUS_NO_MEMORY;
6236 p = strrchr_m(base_name, '/');
6237 if (p) {
6238 p[1] = '\0';
6239 } else {
6240 base_name = talloc_strdup(ctx, "");
6241 if (!base_name) {
6242 return NT_STATUS_NO_MEMORY;
6245 /* Append the new name. */
6246 base_name = talloc_asprintf_append(base_name,
6247 "%s",
6248 newname);
6249 if (!base_name) {
6250 return NT_STATUS_NO_MEMORY;
6253 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6254 (UCF_SAVE_LCOMP |
6255 (dest_has_wcard ?
6256 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6257 0)));
6259 /* If an error we expect this to be
6260 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6262 if (!NT_STATUS_IS_OK(status)) {
6263 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6264 status)) {
6265 goto out;
6267 /* Create an smb_fname to call rename_internals_fsp() */
6268 status = create_synthetic_smb_fname(ctx,
6269 base_name, NULL,
6270 NULL,
6271 &smb_fname_dst);
6272 if (!NT_STATUS_IS_OK(status)) {
6273 goto out;
6278 if (fsp) {
6279 DEBUG(10,("smb_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6281 fsp->fnum, fsp_str_dbg(fsp),
6282 smb_fname_str_dbg(smb_fname_dst)));
6283 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6284 overwrite);
6285 } else {
6286 DEBUG(10,("smb_file_rename_information: "
6287 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6288 smb_fname_str_dbg(smb_fname_src),
6289 smb_fname_str_dbg(smb_fname_dst)));
6290 status = rename_internals(ctx, conn, req, smb_fname_src,
6291 smb_fname_dst, 0, overwrite, false,
6292 dest_has_wcard,
6293 FILE_WRITE_ATTRIBUTES);
6295 out:
6296 TALLOC_FREE(smb_fname_dst);
6297 return status;
6300 /****************************************************************************
6301 Deal with SMB_SET_POSIX_ACL.
6302 ****************************************************************************/
6304 #if defined(HAVE_POSIX_ACLS)
6305 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6306 const char *pdata,
6307 int total_data,
6308 files_struct *fsp,
6309 const struct smb_filename *smb_fname)
6311 uint16 posix_acl_version;
6312 uint16 num_file_acls;
6313 uint16 num_def_acls;
6314 bool valid_file_acls = True;
6315 bool valid_def_acls = True;
6317 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6318 return NT_STATUS_INVALID_PARAMETER;
6320 posix_acl_version = SVAL(pdata,0);
6321 num_file_acls = SVAL(pdata,2);
6322 num_def_acls = SVAL(pdata,4);
6324 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6325 valid_file_acls = False;
6326 num_file_acls = 0;
6329 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6330 valid_def_acls = False;
6331 num_def_acls = 0;
6334 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6335 return NT_STATUS_INVALID_PARAMETER;
6338 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6339 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6340 return NT_STATUS_INVALID_PARAMETER;
6343 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6344 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6345 (unsigned int)num_file_acls,
6346 (unsigned int)num_def_acls));
6348 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6349 smb_fname->base_name, num_file_acls,
6350 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6351 return map_nt_error_from_unix(errno);
6354 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6355 smb_fname->base_name, &smb_fname->st, num_def_acls,
6356 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6357 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6358 return map_nt_error_from_unix(errno);
6360 return NT_STATUS_OK;
6362 #endif
6364 /****************************************************************************
6365 Deal with SMB_SET_POSIX_LOCK.
6366 ****************************************************************************/
6368 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6369 struct smb_request *req,
6370 const char *pdata,
6371 int total_data,
6372 files_struct *fsp)
6374 uint64_t count;
6375 uint64_t offset;
6376 uint64_t smblctx;
6377 bool blocking_lock = False;
6378 enum brl_type lock_type;
6380 NTSTATUS status = NT_STATUS_OK;
6382 if (fsp == NULL || fsp->fh->fd == -1) {
6383 return NT_STATUS_INVALID_HANDLE;
6386 if (total_data != POSIX_LOCK_DATA_SIZE) {
6387 return NT_STATUS_INVALID_PARAMETER;
6390 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6391 case POSIX_LOCK_TYPE_READ:
6392 lock_type = READ_LOCK;
6393 break;
6394 case POSIX_LOCK_TYPE_WRITE:
6395 /* Return the right POSIX-mappable error code for files opened read-only. */
6396 if (!fsp->can_write) {
6397 return NT_STATUS_INVALID_HANDLE;
6399 lock_type = WRITE_LOCK;
6400 break;
6401 case POSIX_LOCK_TYPE_UNLOCK:
6402 lock_type = UNLOCK_LOCK;
6403 break;
6404 default:
6405 return NT_STATUS_INVALID_PARAMETER;
6408 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6409 blocking_lock = False;
6410 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6411 blocking_lock = True;
6412 } else {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 if (!lp_blocking_locks(SNUM(conn))) {
6417 blocking_lock = False;
6420 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6421 #if defined(HAVE_LONGLONG)
6422 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6423 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6424 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6425 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6426 #else /* HAVE_LONGLONG */
6427 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6428 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6429 #endif /* HAVE_LONGLONG */
6431 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6432 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6433 fsp_str_dbg(fsp),
6434 (unsigned int)lock_type,
6435 (unsigned long long)smblctx,
6436 (double)count,
6437 (double)offset ));
6439 if (lock_type == UNLOCK_LOCK) {
6440 status = do_unlock(req->sconn->msg_ctx,
6441 fsp,
6442 smblctx,
6443 count,
6444 offset,
6445 POSIX_LOCK);
6446 } else {
6447 uint64_t block_smblctx;
6449 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6450 fsp,
6451 smblctx,
6452 count,
6453 offset,
6454 lock_type,
6455 POSIX_LOCK,
6456 blocking_lock,
6457 &status,
6458 &block_smblctx,
6459 NULL);
6461 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6463 * A blocking lock was requested. Package up
6464 * this smb into a queued request and push it
6465 * onto the blocking lock queue.
6467 if(push_blocking_lock_request(br_lck,
6468 req,
6469 fsp,
6470 -1, /* infinite timeout. */
6472 smblctx,
6473 lock_type,
6474 POSIX_LOCK,
6475 offset,
6476 count,
6477 block_smblctx)) {
6478 TALLOC_FREE(br_lck);
6479 return status;
6482 TALLOC_FREE(br_lck);
6485 return status;
6488 /****************************************************************************
6489 Deal with SMB_SET_FILE_BASIC_INFO.
6490 ****************************************************************************/
6492 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6493 const char *pdata,
6494 int total_data,
6495 files_struct *fsp,
6496 const struct smb_filename *smb_fname)
6498 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6499 struct smb_file_time ft;
6500 uint32 dosmode = 0;
6501 NTSTATUS status = NT_STATUS_OK;
6503 ZERO_STRUCT(ft);
6505 if (total_data < 36) {
6506 return NT_STATUS_INVALID_PARAMETER;
6509 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6510 return NT_STATUS_ACCESS_DENIED;
6513 /* Set the attributes */
6514 dosmode = IVAL(pdata,32);
6515 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 return status;
6520 /* create time */
6521 ft.create_time = interpret_long_date(pdata);
6523 /* access time */
6524 ft.atime = interpret_long_date(pdata+8);
6526 /* write time. */
6527 ft.mtime = interpret_long_date(pdata+16);
6529 /* change time. */
6530 ft.ctime = interpret_long_date(pdata+24);
6532 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6533 smb_fname_str_dbg(smb_fname)));
6535 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6536 true);
6539 /****************************************************************************
6540 Deal with SMB_INFO_STANDARD.
6541 ****************************************************************************/
6543 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6544 const char *pdata,
6545 int total_data,
6546 files_struct *fsp,
6547 const struct smb_filename *smb_fname)
6549 struct smb_file_time ft;
6551 ZERO_STRUCT(ft);
6553 if (total_data < 12) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6558 return NT_STATUS_ACCESS_DENIED;
6561 /* create time */
6562 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6563 /* access time */
6564 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6565 /* write time */
6566 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6568 DEBUG(10,("smb_set_info_standard: file %s\n",
6569 smb_fname_str_dbg(smb_fname)));
6571 return smb_set_file_time(conn,
6572 fsp,
6573 smb_fname,
6574 &ft,
6575 true);
6578 /****************************************************************************
6579 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6580 ****************************************************************************/
6582 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6583 struct smb_request *req,
6584 const char *pdata,
6585 int total_data,
6586 files_struct *fsp,
6587 struct smb_filename *smb_fname)
6589 uint64_t allocation_size = 0;
6590 NTSTATUS status = NT_STATUS_OK;
6591 files_struct *new_fsp = NULL;
6593 if (!VALID_STAT(smb_fname->st)) {
6594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6597 if (total_data < 8) {
6598 return NT_STATUS_INVALID_PARAMETER;
6601 allocation_size = (uint64_t)IVAL(pdata,0);
6602 #ifdef LARGE_SMB_OFF_T
6603 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6604 #else /* LARGE_SMB_OFF_T */
6605 if (IVAL(pdata,4) != 0) {
6606 /* more than 32 bits? */
6607 return NT_STATUS_INVALID_PARAMETER;
6609 #endif /* LARGE_SMB_OFF_T */
6611 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6612 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6613 (double)allocation_size));
6615 if (allocation_size) {
6616 allocation_size = smb_roundup(conn, allocation_size);
6619 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6620 return NT_STATUS_ACCESS_DENIED;
6623 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6624 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6625 (double)allocation_size));
6627 if (fsp && fsp->fh->fd != -1) {
6628 /* Open file handle. */
6629 /* Only change if needed. */
6630 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6631 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6632 return map_nt_error_from_unix(errno);
6635 /* But always update the time. */
6637 * This is equivalent to a write. Ensure it's seen immediately
6638 * if there are no pending writes.
6640 trigger_write_time_update_immediate(fsp);
6641 return NT_STATUS_OK;
6644 /* Pathname or stat or directory file. */
6645 status = SMB_VFS_CREATE_FILE(
6646 conn, /* conn */
6647 req, /* req */
6648 0, /* root_dir_fid */
6649 smb_fname, /* fname */
6650 FILE_WRITE_DATA, /* access_mask */
6651 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6652 FILE_SHARE_DELETE),
6653 FILE_OPEN, /* create_disposition*/
6654 0, /* create_options */
6655 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6656 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6657 0, /* allocation_size */
6658 0, /* private_flags */
6659 NULL, /* sd */
6660 NULL, /* ea_list */
6661 &new_fsp, /* result */
6662 NULL); /* pinfo */
6664 if (!NT_STATUS_IS_OK(status)) {
6665 /* NB. We check for open_was_deferred in the caller. */
6666 return status;
6669 /* Only change if needed. */
6670 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6671 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6672 status = map_nt_error_from_unix(errno);
6673 close_file(req, new_fsp, NORMAL_CLOSE);
6674 return status;
6678 /* Changing the allocation size should set the last mod time. */
6680 * This is equivalent to a write. Ensure it's seen immediately
6681 * if there are no pending writes.
6683 trigger_write_time_update_immediate(new_fsp);
6685 close_file(req, new_fsp, NORMAL_CLOSE);
6686 return NT_STATUS_OK;
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6694 struct smb_request *req,
6695 const char *pdata,
6696 int total_data,
6697 files_struct *fsp,
6698 const struct smb_filename *smb_fname,
6699 bool fail_after_createfile)
6701 SMB_OFF_T size;
6703 if (total_data < 8) {
6704 return NT_STATUS_INVALID_PARAMETER;
6707 size = IVAL(pdata,0);
6708 #ifdef LARGE_SMB_OFF_T
6709 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6710 #else /* LARGE_SMB_OFF_T */
6711 if (IVAL(pdata,4) != 0) {
6712 /* more than 32 bits? */
6713 return NT_STATUS_INVALID_PARAMETER;
6715 #endif /* LARGE_SMB_OFF_T */
6716 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6717 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6718 (double)size));
6720 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6721 return NT_STATUS_ACCESS_DENIED;
6724 return smb_set_file_size(conn, req,
6725 fsp,
6726 smb_fname,
6727 &smb_fname->st,
6728 size,
6729 fail_after_createfile);
6732 /****************************************************************************
6733 Allow a UNIX info mknod.
6734 ****************************************************************************/
6736 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6737 const char *pdata,
6738 int total_data,
6739 const struct smb_filename *smb_fname)
6741 uint32 file_type = IVAL(pdata,56);
6742 #if defined(HAVE_MAKEDEV)
6743 uint32 dev_major = IVAL(pdata,60);
6744 uint32 dev_minor = IVAL(pdata,68);
6745 #endif
6746 SMB_DEV_T dev = (SMB_DEV_T)0;
6747 uint32 raw_unixmode = IVAL(pdata,84);
6748 NTSTATUS status;
6749 mode_t unixmode;
6751 if (total_data < 100) {
6752 return NT_STATUS_INVALID_PARAMETER;
6755 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6756 PERM_NEW_FILE, &unixmode);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 return status;
6761 #if defined(HAVE_MAKEDEV)
6762 dev = makedev(dev_major, dev_minor);
6763 #endif
6765 switch (file_type) {
6766 #if defined(S_IFIFO)
6767 case UNIX_TYPE_FIFO:
6768 unixmode |= S_IFIFO;
6769 break;
6770 #endif
6771 #if defined(S_IFSOCK)
6772 case UNIX_TYPE_SOCKET:
6773 unixmode |= S_IFSOCK;
6774 break;
6775 #endif
6776 #if defined(S_IFCHR)
6777 case UNIX_TYPE_CHARDEV:
6778 unixmode |= S_IFCHR;
6779 break;
6780 #endif
6781 #if defined(S_IFBLK)
6782 case UNIX_TYPE_BLKDEV:
6783 unixmode |= S_IFBLK;
6784 break;
6785 #endif
6786 default:
6787 return NT_STATUS_INVALID_PARAMETER;
6790 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6791 "%.0f mode 0%o for file %s\n", (double)dev,
6792 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6794 /* Ok - do the mknod. */
6795 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6796 return map_nt_error_from_unix(errno);
6799 /* If any of the other "set" calls fail we
6800 * don't want to end up with a half-constructed mknod.
6803 if (lp_inherit_perms(SNUM(conn))) {
6804 char *parent;
6805 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6806 &parent, NULL)) {
6807 return NT_STATUS_NO_MEMORY;
6809 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6810 unixmode);
6811 TALLOC_FREE(parent);
6814 return NT_STATUS_OK;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_UNIX_BASIC.
6819 ****************************************************************************/
6821 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6822 struct smb_request *req,
6823 const char *pdata,
6824 int total_data,
6825 files_struct *fsp,
6826 const struct smb_filename *smb_fname)
6828 struct smb_file_time ft;
6829 uint32 raw_unixmode;
6830 mode_t unixmode;
6831 SMB_OFF_T size = 0;
6832 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6833 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6834 NTSTATUS status = NT_STATUS_OK;
6835 bool delete_on_fail = False;
6836 enum perm_type ptype;
6837 files_struct *all_fsps = NULL;
6838 bool modify_mtime = true;
6839 struct file_id id;
6840 struct smb_filename *smb_fname_tmp = NULL;
6841 SMB_STRUCT_STAT sbuf;
6843 ZERO_STRUCT(ft);
6845 if (total_data < 100) {
6846 return NT_STATUS_INVALID_PARAMETER;
6849 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6850 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6851 size=IVAL(pdata,0); /* first 8 Bytes are size */
6852 #ifdef LARGE_SMB_OFF_T
6853 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6854 #else /* LARGE_SMB_OFF_T */
6855 if (IVAL(pdata,4) != 0) {
6856 /* more than 32 bits? */
6857 return NT_STATUS_INVALID_PARAMETER;
6859 #endif /* LARGE_SMB_OFF_T */
6862 ft.atime = interpret_long_date(pdata+24); /* access_time */
6863 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6864 set_owner = (uid_t)IVAL(pdata,40);
6865 set_grp = (gid_t)IVAL(pdata,48);
6866 raw_unixmode = IVAL(pdata,84);
6868 if (VALID_STAT(smb_fname->st)) {
6869 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6870 ptype = PERM_EXISTING_DIR;
6871 } else {
6872 ptype = PERM_EXISTING_FILE;
6874 } else {
6875 ptype = PERM_NEW_FILE;
6878 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6879 ptype, &unixmode);
6880 if (!NT_STATUS_IS_OK(status)) {
6881 return status;
6884 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6885 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6886 smb_fname_str_dbg(smb_fname), (double)size,
6887 (unsigned int)set_owner, (unsigned int)set_grp,
6888 (int)raw_unixmode));
6890 sbuf = smb_fname->st;
6892 if (!VALID_STAT(sbuf)) {
6894 * The only valid use of this is to create character and block
6895 * devices, and named pipes. This is deprecated (IMHO) and
6896 * a new info level should be used for mknod. JRA.
6899 status = smb_unix_mknod(conn,
6900 pdata,
6901 total_data,
6902 smb_fname);
6903 if (!NT_STATUS_IS_OK(status)) {
6904 return status;
6907 status = copy_smb_filename(talloc_tos(), smb_fname,
6908 &smb_fname_tmp);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 return status;
6913 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6914 status = map_nt_error_from_unix(errno);
6915 TALLOC_FREE(smb_fname_tmp);
6916 SMB_VFS_UNLINK(conn, smb_fname);
6917 return status;
6920 sbuf = smb_fname_tmp->st;
6921 smb_fname = smb_fname_tmp;
6923 /* Ensure we don't try and change anything else. */
6924 raw_unixmode = SMB_MODE_NO_CHANGE;
6925 size = get_file_size_stat(&sbuf);
6926 ft.atime = sbuf.st_ex_atime;
6927 ft.mtime = sbuf.st_ex_mtime;
6929 * We continue here as we might want to change the
6930 * owner uid/gid.
6932 delete_on_fail = True;
6935 #if 1
6936 /* Horrible backwards compatibility hack as an old server bug
6937 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6938 * */
6940 if (!size) {
6941 size = get_file_size_stat(&sbuf);
6943 #endif
6946 * Deal with the UNIX specific mode set.
6949 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6950 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6951 "setting mode 0%o for file %s\n",
6952 (unsigned int)unixmode,
6953 smb_fname_str_dbg(smb_fname)));
6954 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6955 return map_nt_error_from_unix(errno);
6960 * Deal with the UNIX specific uid set.
6963 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6964 (sbuf.st_ex_uid != set_owner)) {
6965 int ret;
6967 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6968 "changing owner %u for path %s\n",
6969 (unsigned int)set_owner,
6970 smb_fname_str_dbg(smb_fname)));
6972 if (S_ISLNK(sbuf.st_ex_mode)) {
6973 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6974 set_owner, (gid_t)-1);
6975 } else {
6976 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6977 set_owner, (gid_t)-1);
6980 if (ret != 0) {
6981 status = map_nt_error_from_unix(errno);
6982 if (delete_on_fail) {
6983 SMB_VFS_UNLINK(conn, smb_fname);
6985 return status;
6990 * Deal with the UNIX specific gid set.
6993 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6994 (sbuf.st_ex_gid != set_grp)) {
6995 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6996 "changing group %u for file %s\n",
6997 (unsigned int)set_owner,
6998 smb_fname_str_dbg(smb_fname)));
6999 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7000 set_grp) != 0) {
7001 status = map_nt_error_from_unix(errno);
7002 if (delete_on_fail) {
7003 SMB_VFS_UNLINK(conn, smb_fname);
7005 return status;
7009 /* Deal with any size changes. */
7011 status = smb_set_file_size(conn, req,
7012 fsp,
7013 smb_fname,
7014 &sbuf,
7015 size,
7016 false);
7017 if (!NT_STATUS_IS_OK(status)) {
7018 return status;
7021 /* Deal with any time changes. */
7022 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7023 /* No change, don't cancel anything. */
7024 return status;
7027 id = vfs_file_id_from_sbuf(conn, &sbuf);
7028 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7029 all_fsps = file_find_di_next(all_fsps)) {
7031 * We're setting the time explicitly for UNIX.
7032 * Cancel any pending changes over all handles.
7034 all_fsps->update_write_time_on_close = false;
7035 TALLOC_FREE(all_fsps->update_write_time_event);
7039 * Override the "setting_write_time"
7040 * parameter here as it almost does what
7041 * we need. Just remember if we modified
7042 * mtime and send the notify ourselves.
7044 if (null_timespec(ft.mtime)) {
7045 modify_mtime = false;
7048 status = smb_set_file_time(conn,
7049 fsp,
7050 smb_fname,
7051 &ft,
7052 false);
7053 if (modify_mtime) {
7054 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7055 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7057 return status;
7060 /****************************************************************************
7061 Deal with SMB_SET_FILE_UNIX_INFO2.
7062 ****************************************************************************/
7064 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7065 struct smb_request *req,
7066 const char *pdata,
7067 int total_data,
7068 files_struct *fsp,
7069 const struct smb_filename *smb_fname)
7071 NTSTATUS status;
7072 uint32 smb_fflags;
7073 uint32 smb_fmask;
7075 if (total_data < 116) {
7076 return NT_STATUS_INVALID_PARAMETER;
7079 /* Start by setting all the fields that are common between UNIX_BASIC
7080 * and UNIX_INFO2.
7082 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7083 fsp, smb_fname);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 return status;
7088 smb_fflags = IVAL(pdata, 108);
7089 smb_fmask = IVAL(pdata, 112);
7091 /* NB: We should only attempt to alter the file flags if the client
7092 * sends a non-zero mask.
7094 if (smb_fmask != 0) {
7095 int stat_fflags = 0;
7097 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7098 smb_fmask, &stat_fflags)) {
7099 /* Client asked to alter a flag we don't understand. */
7100 return NT_STATUS_INVALID_PARAMETER;
7103 if (fsp && fsp->fh->fd != -1) {
7104 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7105 return NT_STATUS_NOT_SUPPORTED;
7106 } else {
7107 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7108 stat_fflags) != 0) {
7109 return map_nt_error_from_unix(errno);
7114 /* XXX: need to add support for changing the create_time here. You
7115 * can do this for paths on Darwin with setattrlist(2). The right way
7116 * to hook this up is probably by extending the VFS utimes interface.
7119 return NT_STATUS_OK;
7122 /****************************************************************************
7123 Create a directory with POSIX semantics.
7124 ****************************************************************************/
7126 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7127 struct smb_request *req,
7128 char **ppdata,
7129 int total_data,
7130 struct smb_filename *smb_fname,
7131 int *pdata_return_size)
7133 NTSTATUS status = NT_STATUS_OK;
7134 uint32 raw_unixmode = 0;
7135 uint32 mod_unixmode = 0;
7136 mode_t unixmode = (mode_t)0;
7137 files_struct *fsp = NULL;
7138 uint16 info_level_return = 0;
7139 int info;
7140 char *pdata = *ppdata;
7142 if (total_data < 18) {
7143 return NT_STATUS_INVALID_PARAMETER;
7146 raw_unixmode = IVAL(pdata,8);
7147 /* Next 4 bytes are not yet defined. */
7149 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7150 PERM_NEW_DIR, &unixmode);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 return status;
7155 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7157 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7158 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7160 status = SMB_VFS_CREATE_FILE(
7161 conn, /* conn */
7162 req, /* req */
7163 0, /* root_dir_fid */
7164 smb_fname, /* fname */
7165 FILE_READ_ATTRIBUTES, /* access_mask */
7166 FILE_SHARE_NONE, /* share_access */
7167 FILE_CREATE, /* create_disposition*/
7168 FILE_DIRECTORY_FILE, /* create_options */
7169 mod_unixmode, /* file_attributes */
7170 0, /* oplock_request */
7171 0, /* allocation_size */
7172 0, /* private_flags */
7173 NULL, /* sd */
7174 NULL, /* ea_list */
7175 &fsp, /* result */
7176 &info); /* pinfo */
7178 if (NT_STATUS_IS_OK(status)) {
7179 close_file(req, fsp, NORMAL_CLOSE);
7182 info_level_return = SVAL(pdata,16);
7184 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7185 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7186 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7187 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7188 } else {
7189 *pdata_return_size = 12;
7192 /* Realloc the data size */
7193 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7194 if (*ppdata == NULL) {
7195 *pdata_return_size = 0;
7196 return NT_STATUS_NO_MEMORY;
7198 pdata = *ppdata;
7200 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7201 SSVAL(pdata,2,0); /* No fnum. */
7202 SIVAL(pdata,4,info); /* Was directory created. */
7204 switch (info_level_return) {
7205 case SMB_QUERY_FILE_UNIX_BASIC:
7206 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7207 SSVAL(pdata,10,0); /* Padding. */
7208 store_file_unix_basic(conn, pdata + 12, fsp,
7209 &smb_fname->st);
7210 break;
7211 case SMB_QUERY_FILE_UNIX_INFO2:
7212 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7213 SSVAL(pdata,10,0); /* Padding. */
7214 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7215 &smb_fname->st);
7216 break;
7217 default:
7218 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7219 SSVAL(pdata,10,0); /* Padding. */
7220 break;
7223 return status;
7226 /****************************************************************************
7227 Open/Create a file with POSIX semantics.
7228 ****************************************************************************/
7230 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7231 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7233 static NTSTATUS smb_posix_open(connection_struct *conn,
7234 struct smb_request *req,
7235 char **ppdata,
7236 int total_data,
7237 struct smb_filename *smb_fname,
7238 int *pdata_return_size)
7240 bool extended_oplock_granted = False;
7241 char *pdata = *ppdata;
7242 uint32 flags = 0;
7243 uint32 wire_open_mode = 0;
7244 uint32 raw_unixmode = 0;
7245 uint32 mod_unixmode = 0;
7246 uint32 create_disp = 0;
7247 uint32 access_mask = 0;
7248 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7249 NTSTATUS status = NT_STATUS_OK;
7250 mode_t unixmode = (mode_t)0;
7251 files_struct *fsp = NULL;
7252 int oplock_request = 0;
7253 int info = 0;
7254 uint16 info_level_return = 0;
7256 if (total_data < 18) {
7257 return NT_STATUS_INVALID_PARAMETER;
7260 flags = IVAL(pdata,0);
7261 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7262 if (oplock_request) {
7263 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7266 wire_open_mode = IVAL(pdata,4);
7268 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7269 return smb_posix_mkdir(conn, req,
7270 ppdata,
7271 total_data,
7272 smb_fname,
7273 pdata_return_size);
7276 switch (wire_open_mode & SMB_ACCMODE) {
7277 case SMB_O_RDONLY:
7278 access_mask = SMB_O_RDONLY_MAPPING;
7279 break;
7280 case SMB_O_WRONLY:
7281 access_mask = SMB_O_WRONLY_MAPPING;
7282 break;
7283 case SMB_O_RDWR:
7284 access_mask = (SMB_O_RDONLY_MAPPING|
7285 SMB_O_WRONLY_MAPPING);
7286 break;
7287 default:
7288 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7289 (unsigned int)wire_open_mode ));
7290 return NT_STATUS_INVALID_PARAMETER;
7293 wire_open_mode &= ~SMB_ACCMODE;
7295 /* First take care of O_CREAT|O_EXCL interactions. */
7296 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7297 case (SMB_O_CREAT | SMB_O_EXCL):
7298 /* File exists fail. File not exist create. */
7299 create_disp = FILE_CREATE;
7300 break;
7301 case SMB_O_CREAT:
7302 /* File exists open. File not exist create. */
7303 create_disp = FILE_OPEN_IF;
7304 break;
7305 case 0:
7306 /* File exists open. File not exist fail. */
7307 create_disp = FILE_OPEN;
7308 break;
7309 case SMB_O_EXCL:
7310 /* O_EXCL on its own without O_CREAT is undefined. */
7311 default:
7312 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7313 (unsigned int)wire_open_mode ));
7314 return NT_STATUS_INVALID_PARAMETER;
7317 /* Next factor in the effects of O_TRUNC. */
7318 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7320 if (wire_open_mode & SMB_O_TRUNC) {
7321 switch (create_disp) {
7322 case FILE_CREATE:
7323 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7324 /* Leave create_disp alone as
7325 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7327 /* File exists fail. File not exist create. */
7328 break;
7329 case FILE_OPEN_IF:
7330 /* SMB_O_CREAT | SMB_O_TRUNC */
7331 /* File exists overwrite. File not exist create. */
7332 create_disp = FILE_OVERWRITE_IF;
7333 break;
7334 case FILE_OPEN:
7335 /* SMB_O_TRUNC */
7336 /* File exists overwrite. File not exist fail. */
7337 create_disp = FILE_OVERWRITE;
7338 break;
7339 default:
7340 /* Cannot get here. */
7341 smb_panic("smb_posix_open: logic error");
7342 return NT_STATUS_INVALID_PARAMETER;
7346 raw_unixmode = IVAL(pdata,8);
7347 /* Next 4 bytes are not yet defined. */
7349 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7350 (VALID_STAT(smb_fname->st) ?
7351 PERM_EXISTING_FILE : PERM_NEW_FILE),
7352 &unixmode);
7354 if (!NT_STATUS_IS_OK(status)) {
7355 return status;
7358 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7360 if (wire_open_mode & SMB_O_SYNC) {
7361 create_options |= FILE_WRITE_THROUGH;
7363 if (wire_open_mode & SMB_O_APPEND) {
7364 access_mask |= FILE_APPEND_DATA;
7366 if (wire_open_mode & SMB_O_DIRECT) {
7367 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7370 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7371 VALID_STAT_OF_DIR(smb_fname->st)) {
7372 if (access_mask != SMB_O_RDONLY_MAPPING) {
7373 return NT_STATUS_FILE_IS_A_DIRECTORY;
7375 create_options &= ~FILE_NON_DIRECTORY_FILE;
7376 create_options |= FILE_DIRECTORY_FILE;
7379 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7380 smb_fname_str_dbg(smb_fname),
7381 (unsigned int)wire_open_mode,
7382 (unsigned int)unixmode ));
7384 status = SMB_VFS_CREATE_FILE(
7385 conn, /* conn */
7386 req, /* req */
7387 0, /* root_dir_fid */
7388 smb_fname, /* fname */
7389 access_mask, /* access_mask */
7390 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7391 FILE_SHARE_DELETE),
7392 create_disp, /* create_disposition*/
7393 create_options, /* create_options */
7394 mod_unixmode, /* file_attributes */
7395 oplock_request, /* oplock_request */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7398 NULL, /* sd */
7399 NULL, /* ea_list */
7400 &fsp, /* result */
7401 &info); /* pinfo */
7403 if (!NT_STATUS_IS_OK(status)) {
7404 return status;
7407 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7408 extended_oplock_granted = True;
7411 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7412 extended_oplock_granted = True;
7415 info_level_return = SVAL(pdata,16);
7417 /* Allocate the correct return size. */
7419 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7420 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7421 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7422 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7423 } else {
7424 *pdata_return_size = 12;
7427 /* Realloc the data size */
7428 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7429 if (*ppdata == NULL) {
7430 close_file(req, fsp, ERROR_CLOSE);
7431 *pdata_return_size = 0;
7432 return NT_STATUS_NO_MEMORY;
7434 pdata = *ppdata;
7436 if (extended_oplock_granted) {
7437 if (flags & REQUEST_BATCH_OPLOCK) {
7438 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7439 } else {
7440 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7442 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7443 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7444 } else {
7445 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7448 SSVAL(pdata,2,fsp->fnum);
7449 SIVAL(pdata,4,info); /* Was file created etc. */
7451 switch (info_level_return) {
7452 case SMB_QUERY_FILE_UNIX_BASIC:
7453 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7454 SSVAL(pdata,10,0); /* padding. */
7455 store_file_unix_basic(conn, pdata + 12, fsp,
7456 &smb_fname->st);
7457 break;
7458 case SMB_QUERY_FILE_UNIX_INFO2:
7459 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7460 SSVAL(pdata,10,0); /* padding. */
7461 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7462 &smb_fname->st);
7463 break;
7464 default:
7465 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7466 SSVAL(pdata,10,0); /* padding. */
7467 break;
7469 return NT_STATUS_OK;
7472 /****************************************************************************
7473 Delete a file with POSIX semantics.
7474 ****************************************************************************/
7476 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7477 struct smb_request *req,
7478 const char *pdata,
7479 int total_data,
7480 struct smb_filename *smb_fname)
7482 NTSTATUS status = NT_STATUS_OK;
7483 files_struct *fsp = NULL;
7484 uint16 flags = 0;
7485 char del = 1;
7486 int info = 0;
7487 int create_options = 0;
7488 int i;
7489 struct share_mode_lock *lck = NULL;
7491 if (total_data < 2) {
7492 return NT_STATUS_INVALID_PARAMETER;
7495 flags = SVAL(pdata,0);
7497 if (!VALID_STAT(smb_fname->st)) {
7498 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7501 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7502 !VALID_STAT_OF_DIR(smb_fname->st)) {
7503 return NT_STATUS_NOT_A_DIRECTORY;
7506 DEBUG(10,("smb_posix_unlink: %s %s\n",
7507 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7508 smb_fname_str_dbg(smb_fname)));
7510 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7511 create_options |= FILE_DIRECTORY_FILE;
7514 status = SMB_VFS_CREATE_FILE(
7515 conn, /* conn */
7516 req, /* req */
7517 0, /* root_dir_fid */
7518 smb_fname, /* fname */
7519 DELETE_ACCESS, /* access_mask */
7520 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7521 FILE_SHARE_DELETE),
7522 FILE_OPEN, /* create_disposition*/
7523 create_options, /* create_options */
7524 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7525 0, /* oplock_request */
7526 0, /* allocation_size */
7527 0, /* private_flags */
7528 NULL, /* sd */
7529 NULL, /* ea_list */
7530 &fsp, /* result */
7531 &info); /* pinfo */
7533 if (!NT_STATUS_IS_OK(status)) {
7534 return status;
7538 * Don't lie to client. If we can't really delete due to
7539 * non-POSIX opens return SHARING_VIOLATION.
7542 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7543 NULL);
7544 if (lck == NULL) {
7545 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7546 "lock for file %s\n", fsp_str_dbg(fsp)));
7547 close_file(req, fsp, NORMAL_CLOSE);
7548 return NT_STATUS_INVALID_PARAMETER;
7552 * See if others still have the file open. If this is the case, then
7553 * don't delete. If all opens are POSIX delete we can set the delete
7554 * on close disposition.
7556 for (i=0; i<lck->num_share_modes; i++) {
7557 struct share_mode_entry *e = &lck->share_modes[i];
7558 if (is_valid_share_mode_entry(e)) {
7559 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7560 continue;
7562 /* Fail with sharing violation. */
7563 close_file(req, fsp, NORMAL_CLOSE);
7564 TALLOC_FREE(lck);
7565 return NT_STATUS_SHARING_VIOLATION;
7570 * Set the delete on close.
7572 status = smb_set_file_disposition_info(conn,
7573 &del,
7575 fsp,
7576 smb_fname);
7578 if (!NT_STATUS_IS_OK(status)) {
7579 close_file(req, fsp, NORMAL_CLOSE);
7580 TALLOC_FREE(lck);
7581 return status;
7583 TALLOC_FREE(lck);
7584 return close_file(req, fsp, NORMAL_CLOSE);
7587 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7588 struct smb_request *req,
7589 TALLOC_CTX *mem_ctx,
7590 uint16_t info_level,
7591 files_struct *fsp,
7592 struct smb_filename *smb_fname,
7593 char **ppdata, int total_data,
7594 int *ret_data_size)
7596 char *pdata = *ppdata;
7597 NTSTATUS status = NT_STATUS_OK;
7598 int data_return_size = 0;
7600 *ret_data_size = 0;
7602 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7603 return NT_STATUS_INVALID_LEVEL;
7606 if (!CAN_WRITE(conn)) {
7607 /* Allow POSIX opens. The open path will deny
7608 * any non-readonly opens. */
7609 if (info_level != SMB_POSIX_PATH_OPEN) {
7610 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7614 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7615 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7616 fsp ? fsp->fnum : -1, info_level, total_data));
7618 switch (info_level) {
7620 case SMB_INFO_STANDARD:
7622 status = smb_set_info_standard(conn,
7623 pdata,
7624 total_data,
7625 fsp,
7626 smb_fname);
7627 break;
7630 case SMB_INFO_SET_EA:
7632 status = smb_info_set_ea(conn,
7633 pdata,
7634 total_data,
7635 fsp,
7636 smb_fname);
7637 break;
7640 case SMB_SET_FILE_BASIC_INFO:
7641 case SMB_FILE_BASIC_INFORMATION:
7643 status = smb_set_file_basic_info(conn,
7644 pdata,
7645 total_data,
7646 fsp,
7647 smb_fname);
7648 break;
7651 case SMB_FILE_ALLOCATION_INFORMATION:
7652 case SMB_SET_FILE_ALLOCATION_INFO:
7654 status = smb_set_file_allocation_info(conn, req,
7655 pdata,
7656 total_data,
7657 fsp,
7658 smb_fname);
7659 break;
7662 case SMB_FILE_END_OF_FILE_INFORMATION:
7663 case SMB_SET_FILE_END_OF_FILE_INFO:
7666 * XP/Win7 both fail after the createfile with
7667 * SMB_SET_FILE_END_OF_FILE_INFO but not
7668 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7669 * The level is known here, so pass it down
7670 * appropriately.
7672 bool should_fail =
7673 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7675 status = smb_set_file_end_of_file_info(conn, req,
7676 pdata,
7677 total_data,
7678 fsp,
7679 smb_fname,
7680 should_fail);
7681 break;
7684 case SMB_FILE_DISPOSITION_INFORMATION:
7685 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7687 #if 0
7688 /* JRA - We used to just ignore this on a path ?
7689 * Shouldn't this be invalid level on a pathname
7690 * based call ?
7692 if (tran_call != TRANSACT2_SETFILEINFO) {
7693 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7695 #endif
7696 status = smb_set_file_disposition_info(conn,
7697 pdata,
7698 total_data,
7699 fsp,
7700 smb_fname);
7701 break;
7704 case SMB_FILE_POSITION_INFORMATION:
7706 status = smb_file_position_information(conn,
7707 pdata,
7708 total_data,
7709 fsp);
7710 break;
7713 case SMB_FILE_FULL_EA_INFORMATION:
7715 status = smb_set_file_full_ea_info(conn,
7716 pdata,
7717 total_data,
7718 fsp);
7719 break;
7722 /* From tridge Samba4 :
7723 * MODE_INFORMATION in setfileinfo (I have no
7724 * idea what "mode information" on a file is - it takes a value of 0,
7725 * 2, 4 or 6. What could it be?).
7728 case SMB_FILE_MODE_INFORMATION:
7730 status = smb_file_mode_information(conn,
7731 pdata,
7732 total_data);
7733 break;
7737 * CIFS UNIX extensions.
7740 case SMB_SET_FILE_UNIX_BASIC:
7742 status = smb_set_file_unix_basic(conn, req,
7743 pdata,
7744 total_data,
7745 fsp,
7746 smb_fname);
7747 break;
7750 case SMB_SET_FILE_UNIX_INFO2:
7752 status = smb_set_file_unix_info2(conn, req,
7753 pdata,
7754 total_data,
7755 fsp,
7756 smb_fname);
7757 break;
7760 case SMB_SET_FILE_UNIX_LINK:
7762 if (fsp) {
7763 /* We must have a pathname for this. */
7764 return NT_STATUS_INVALID_LEVEL;
7766 status = smb_set_file_unix_link(conn, req, pdata,
7767 total_data, smb_fname);
7768 break;
7771 case SMB_SET_FILE_UNIX_HLINK:
7773 if (fsp) {
7774 /* We must have a pathname for this. */
7775 return NT_STATUS_INVALID_LEVEL;
7777 status = smb_set_file_unix_hlink(conn, req,
7778 pdata, total_data,
7779 smb_fname);
7780 break;
7783 case SMB_FILE_RENAME_INFORMATION:
7785 status = smb_file_rename_information(conn, req,
7786 pdata, total_data,
7787 fsp, smb_fname);
7788 break;
7791 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7793 /* SMB2 rename information. */
7794 status = smb2_file_rename_information(conn, req,
7795 pdata, total_data,
7796 fsp, smb_fname);
7797 break;
7800 case SMB_FILE_LINK_INFORMATION:
7802 status = smb_file_link_information(conn, req,
7803 pdata, total_data,
7804 fsp, smb_fname);
7805 break;
7808 #if defined(HAVE_POSIX_ACLS)
7809 case SMB_SET_POSIX_ACL:
7811 status = smb_set_posix_acl(conn,
7812 pdata,
7813 total_data,
7814 fsp,
7815 smb_fname);
7816 break;
7818 #endif
7820 case SMB_SET_POSIX_LOCK:
7822 if (!fsp) {
7823 return NT_STATUS_INVALID_LEVEL;
7825 status = smb_set_posix_lock(conn, req,
7826 pdata, total_data, fsp);
7827 break;
7830 case SMB_POSIX_PATH_OPEN:
7832 if (fsp) {
7833 /* We must have a pathname for this. */
7834 return NT_STATUS_INVALID_LEVEL;
7837 status = smb_posix_open(conn, req,
7838 ppdata,
7839 total_data,
7840 smb_fname,
7841 &data_return_size);
7842 break;
7845 case SMB_POSIX_PATH_UNLINK:
7847 if (fsp) {
7848 /* We must have a pathname for this. */
7849 return NT_STATUS_INVALID_LEVEL;
7852 status = smb_posix_unlink(conn, req,
7853 pdata,
7854 total_data,
7855 smb_fname);
7856 break;
7859 default:
7860 return NT_STATUS_INVALID_LEVEL;
7863 if (!NT_STATUS_IS_OK(status)) {
7864 return status;
7867 *ret_data_size = data_return_size;
7868 return NT_STATUS_OK;
7871 /****************************************************************************
7872 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7873 ****************************************************************************/
7875 static void call_trans2setfilepathinfo(connection_struct *conn,
7876 struct smb_request *req,
7877 unsigned int tran_call,
7878 char **pparams, int total_params,
7879 char **ppdata, int total_data,
7880 unsigned int max_data_bytes)
7882 char *params = *pparams;
7883 char *pdata = *ppdata;
7884 uint16 info_level;
7885 struct smb_filename *smb_fname = NULL;
7886 files_struct *fsp = NULL;
7887 NTSTATUS status = NT_STATUS_OK;
7888 int data_return_size = 0;
7890 if (!params) {
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7892 return;
7895 if (tran_call == TRANSACT2_SETFILEINFO) {
7896 if (total_params < 4) {
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 return;
7901 fsp = file_fsp(req, SVAL(params,0));
7902 /* Basic check for non-null fsp. */
7903 if (!check_fsp_open(conn, req, fsp)) {
7904 return;
7906 info_level = SVAL(params,2);
7908 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7909 &smb_fname);
7910 if (!NT_STATUS_IS_OK(status)) {
7911 reply_nterror(req, status);
7912 return;
7915 if(fsp->fh->fd == -1) {
7917 * This is actually a SETFILEINFO on a directory
7918 * handle (returned from an NT SMB). NT5.0 seems
7919 * to do this call. JRA.
7921 if (INFO_LEVEL_IS_UNIX(info_level)) {
7922 /* Always do lstat for UNIX calls. */
7923 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7924 DEBUG(3,("call_trans2setfilepathinfo: "
7925 "SMB_VFS_LSTAT of %s failed "
7926 "(%s)\n",
7927 smb_fname_str_dbg(smb_fname),
7928 strerror(errno)));
7929 reply_nterror(req, map_nt_error_from_unix(errno));
7930 return;
7932 } else {
7933 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7934 DEBUG(3,("call_trans2setfilepathinfo: "
7935 "fileinfo of %s failed (%s)\n",
7936 smb_fname_str_dbg(smb_fname),
7937 strerror(errno)));
7938 reply_nterror(req, map_nt_error_from_unix(errno));
7939 return;
7942 } else if (fsp->print_file) {
7944 * Doing a DELETE_ON_CLOSE should cancel a print job.
7946 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7947 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7949 DEBUG(3,("call_trans2setfilepathinfo: "
7950 "Cancelling print job (%s)\n",
7951 fsp_str_dbg(fsp)));
7953 SSVAL(params,0,0);
7954 send_trans2_replies(conn, req, params, 2,
7955 *ppdata, 0,
7956 max_data_bytes);
7957 return;
7958 } else {
7959 reply_nterror(req,
7960 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7961 return;
7963 } else {
7965 * Original code - this is an open file.
7967 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7968 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7969 "of fnum %d failed (%s)\n", fsp->fnum,
7970 strerror(errno)));
7971 reply_nterror(req, map_nt_error_from_unix(errno));
7972 return;
7975 } else {
7976 char *fname = NULL;
7978 /* set path info */
7979 if (total_params < 7) {
7980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7981 return;
7984 info_level = SVAL(params,0);
7985 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7986 total_params - 6, STR_TERMINATE,
7987 &status);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 reply_nterror(req, status);
7990 return;
7993 status = filename_convert(req, conn,
7994 req->flags2 & FLAGS2_DFS_PATHNAMES,
7995 fname,
7997 NULL,
7998 &smb_fname);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8001 reply_botherror(req,
8002 NT_STATUS_PATH_NOT_COVERED,
8003 ERRSRV, ERRbadpath);
8004 return;
8006 reply_nterror(req, status);
8007 return;
8010 if (INFO_LEVEL_IS_UNIX(info_level)) {
8012 * For CIFS UNIX extensions the target name may not exist.
8015 /* Always do lstat for UNIX calls. */
8016 SMB_VFS_LSTAT(conn, smb_fname);
8018 } else if (!VALID_STAT(smb_fname->st) &&
8019 SMB_VFS_STAT(conn, smb_fname)) {
8020 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8021 "%s failed (%s)\n",
8022 smb_fname_str_dbg(smb_fname),
8023 strerror(errno)));
8024 reply_nterror(req, map_nt_error_from_unix(errno));
8025 return;
8029 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8030 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8031 fsp ? fsp->fnum : -1, info_level,total_data));
8033 /* Realloc the parameter size */
8034 *pparams = (char *)SMB_REALLOC(*pparams,2);
8035 if (*pparams == NULL) {
8036 reply_nterror(req, NT_STATUS_NO_MEMORY);
8037 return;
8039 params = *pparams;
8041 SSVAL(params,0,0);
8043 status = smbd_do_setfilepathinfo(conn, req, req,
8044 info_level,
8045 fsp,
8046 smb_fname,
8047 ppdata, total_data,
8048 &data_return_size);
8049 if (!NT_STATUS_IS_OK(status)) {
8050 if (open_was_deferred(req->mid)) {
8051 /* We have re-scheduled this call. */
8052 return;
8054 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8055 /* We have re-scheduled this call. */
8056 return;
8058 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8059 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8060 ERRSRV, ERRbadpath);
8061 return;
8063 if (info_level == SMB_POSIX_PATH_OPEN) {
8064 reply_openerror(req, status);
8065 return;
8068 reply_nterror(req, status);
8069 return;
8072 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8073 max_data_bytes);
8075 return;
8078 /****************************************************************************
8079 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8080 ****************************************************************************/
8082 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8083 char **pparams, int total_params,
8084 char **ppdata, int total_data,
8085 unsigned int max_data_bytes)
8087 struct smb_filename *smb_dname = NULL;
8088 char *params = *pparams;
8089 char *pdata = *ppdata;
8090 char *directory = NULL;
8091 NTSTATUS status = NT_STATUS_OK;
8092 struct ea_list *ea_list = NULL;
8093 TALLOC_CTX *ctx = talloc_tos();
8095 if (!CAN_WRITE(conn)) {
8096 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8097 return;
8100 if (total_params < 5) {
8101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8102 return;
8105 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8106 total_params - 4, STR_TERMINATE,
8107 &status);
8108 if (!NT_STATUS_IS_OK(status)) {
8109 reply_nterror(req, status);
8110 return;
8113 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8115 status = filename_convert(ctx,
8116 conn,
8117 req->flags2 & FLAGS2_DFS_PATHNAMES,
8118 directory,
8120 NULL,
8121 &smb_dname);
8123 if (!NT_STATUS_IS_OK(status)) {
8124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8125 reply_botherror(req,
8126 NT_STATUS_PATH_NOT_COVERED,
8127 ERRSRV, ERRbadpath);
8128 return;
8130 reply_nterror(req, status);
8131 return;
8135 * OS/2 workplace shell seems to send SET_EA requests of "null"
8136 * length (4 bytes containing IVAL 4).
8137 * They seem to have no effect. Bug #3212. JRA.
8140 if (total_data && (total_data != 4)) {
8141 /* Any data in this call is an EA list. */
8142 if (total_data < 10) {
8143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8144 goto out;
8147 if (IVAL(pdata,0) > total_data) {
8148 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8149 IVAL(pdata,0), (unsigned int)total_data));
8150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8151 goto out;
8154 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8155 total_data - 4);
8156 if (!ea_list) {
8157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8158 goto out;
8161 if (!lp_ea_support(SNUM(conn))) {
8162 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8163 goto out;
8166 /* If total_data == 4 Windows doesn't care what values
8167 * are placed in that field, it just ignores them.
8168 * The System i QNTC IBM SMB client puts bad values here,
8169 * so ignore them. */
8171 status = create_directory(conn, req, smb_dname);
8173 if (!NT_STATUS_IS_OK(status)) {
8174 reply_nterror(req, status);
8175 goto out;
8178 /* Try and set any given EA. */
8179 if (ea_list) {
8180 status = set_ea(conn, NULL, smb_dname, ea_list);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 reply_nterror(req, status);
8183 goto out;
8187 /* Realloc the parameter and data sizes */
8188 *pparams = (char *)SMB_REALLOC(*pparams,2);
8189 if(*pparams == NULL) {
8190 reply_nterror(req, NT_STATUS_NO_MEMORY);
8191 goto out;
8193 params = *pparams;
8195 SSVAL(params,0,0);
8197 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8199 out:
8200 TALLOC_FREE(smb_dname);
8201 return;
8204 /****************************************************************************
8205 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8206 We don't actually do this - we just send a null response.
8207 ****************************************************************************/
8209 static void call_trans2findnotifyfirst(connection_struct *conn,
8210 struct smb_request *req,
8211 char **pparams, int total_params,
8212 char **ppdata, int total_data,
8213 unsigned int max_data_bytes)
8215 char *params = *pparams;
8216 uint16 info_level;
8218 if (total_params < 6) {
8219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8220 return;
8223 info_level = SVAL(params,4);
8224 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8226 switch (info_level) {
8227 case 1:
8228 case 2:
8229 break;
8230 default:
8231 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8232 return;
8235 /* Realloc the parameter and data sizes */
8236 *pparams = (char *)SMB_REALLOC(*pparams,6);
8237 if (*pparams == NULL) {
8238 reply_nterror(req, NT_STATUS_NO_MEMORY);
8239 return;
8241 params = *pparams;
8243 SSVAL(params,0,fnf_handle);
8244 SSVAL(params,2,0); /* No changes */
8245 SSVAL(params,4,0); /* No EA errors */
8247 fnf_handle++;
8249 if(fnf_handle == 0)
8250 fnf_handle = 257;
8252 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8254 return;
8257 /****************************************************************************
8258 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8259 changes). Currently this does nothing.
8260 ****************************************************************************/
8262 static void call_trans2findnotifynext(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *params = *pparams;
8270 DEBUG(3,("call_trans2findnotifynext\n"));
8272 /* Realloc the parameter and data sizes */
8273 *pparams = (char *)SMB_REALLOC(*pparams,4);
8274 if (*pparams == NULL) {
8275 reply_nterror(req, NT_STATUS_NO_MEMORY);
8276 return;
8278 params = *pparams;
8280 SSVAL(params,0,0); /* No changes */
8281 SSVAL(params,2,0); /* No EA errors */
8283 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8285 return;
8288 /****************************************************************************
8289 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8290 ****************************************************************************/
8292 static void call_trans2getdfsreferral(connection_struct *conn,
8293 struct smb_request *req,
8294 char **pparams, int total_params,
8295 char **ppdata, int total_data,
8296 unsigned int max_data_bytes)
8298 char *params = *pparams;
8299 char *pathname = NULL;
8300 int reply_size = 0;
8301 int max_referral_level;
8302 NTSTATUS status = NT_STATUS_OK;
8303 TALLOC_CTX *ctx = talloc_tos();
8305 DEBUG(10,("call_trans2getdfsreferral\n"));
8307 if (total_params < 3) {
8308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8309 return;
8312 max_referral_level = SVAL(params,0);
8314 if(!lp_host_msdfs()) {
8315 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8316 return;
8319 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8320 total_params - 2, STR_TERMINATE);
8321 if (!pathname) {
8322 reply_nterror(req, NT_STATUS_NOT_FOUND);
8323 return;
8325 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8326 ppdata,&status)) < 0) {
8327 reply_nterror(req, status);
8328 return;
8331 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8332 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8333 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8335 return;
8338 #define LMCAT_SPL 0x53
8339 #define LMFUNC_GETJOBID 0x60
8341 /****************************************************************************
8342 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8343 ****************************************************************************/
8345 static void call_trans2ioctl(connection_struct *conn,
8346 struct smb_request *req,
8347 char **pparams, int total_params,
8348 char **ppdata, int total_data,
8349 unsigned int max_data_bytes)
8351 char *pdata = *ppdata;
8352 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8354 /* check for an invalid fid before proceeding */
8356 if (!fsp) {
8357 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8358 return;
8361 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8362 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8363 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8364 if (*ppdata == NULL) {
8365 reply_nterror(req, NT_STATUS_NO_MEMORY);
8366 return;
8368 pdata = *ppdata;
8370 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8371 CAN ACCEPT THIS IN UNICODE. JRA. */
8373 /* Job number */
8374 if (fsp->print_file) {
8375 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8376 } else {
8377 SSVAL(pdata, 0, 0);
8379 srvstr_push(pdata, req->flags2, pdata + 2,
8380 lp_netbios_name(), 15,
8381 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8382 srvstr_push(pdata, req->flags2, pdata+18,
8383 lp_servicename(SNUM(conn)), 13,
8384 STR_ASCII|STR_TERMINATE); /* Service name */
8385 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8386 max_data_bytes);
8387 return;
8390 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8391 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8394 /****************************************************************************
8395 Reply to a SMBfindclose (stop trans2 directory search).
8396 ****************************************************************************/
8398 void reply_findclose(struct smb_request *req)
8400 int dptr_num;
8401 struct smbd_server_connection *sconn = req->sconn;
8403 START_PROFILE(SMBfindclose);
8405 if (req->wct < 1) {
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 END_PROFILE(SMBfindclose);
8408 return;
8411 dptr_num = SVALS(req->vwv+0, 0);
8413 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8415 dptr_close(sconn, &dptr_num);
8417 reply_outbuf(req, 0, 0);
8419 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8421 END_PROFILE(SMBfindclose);
8422 return;
8425 /****************************************************************************
8426 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8427 ****************************************************************************/
8429 void reply_findnclose(struct smb_request *req)
8431 int dptr_num;
8433 START_PROFILE(SMBfindnclose);
8435 if (req->wct < 1) {
8436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8437 END_PROFILE(SMBfindnclose);
8438 return;
8441 dptr_num = SVAL(req->vwv+0, 0);
8443 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8445 /* We never give out valid handles for a
8446 findnotifyfirst - so any dptr_num is ok here.
8447 Just ignore it. */
8449 reply_outbuf(req, 0, 0);
8451 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8453 END_PROFILE(SMBfindnclose);
8454 return;
8457 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8458 struct trans_state *state)
8460 if (get_Protocol() >= PROTOCOL_NT1) {
8461 req->flags2 |= 0x40; /* IS_LONG_NAME */
8462 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8465 if (conn->encrypt_level == Required && !req->encrypted) {
8466 if (state->call != TRANSACT2_QFSINFO &&
8467 state->call != TRANSACT2_SETFSINFO) {
8468 DEBUG(0,("handle_trans2: encryption required "
8469 "with call 0x%x\n",
8470 (unsigned int)state->call));
8471 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8472 return;
8476 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8478 /* Now we must call the relevant TRANS2 function */
8479 switch(state->call) {
8480 case TRANSACT2_OPEN:
8482 START_PROFILE(Trans2_open);
8483 call_trans2open(conn, req,
8484 &state->param, state->total_param,
8485 &state->data, state->total_data,
8486 state->max_data_return);
8487 END_PROFILE(Trans2_open);
8488 break;
8491 case TRANSACT2_FINDFIRST:
8493 START_PROFILE(Trans2_findfirst);
8494 call_trans2findfirst(conn, req,
8495 &state->param, state->total_param,
8496 &state->data, state->total_data,
8497 state->max_data_return);
8498 END_PROFILE(Trans2_findfirst);
8499 break;
8502 case TRANSACT2_FINDNEXT:
8504 START_PROFILE(Trans2_findnext);
8505 call_trans2findnext(conn, req,
8506 &state->param, state->total_param,
8507 &state->data, state->total_data,
8508 state->max_data_return);
8509 END_PROFILE(Trans2_findnext);
8510 break;
8513 case TRANSACT2_QFSINFO:
8515 START_PROFILE(Trans2_qfsinfo);
8516 call_trans2qfsinfo(conn, req,
8517 &state->param, state->total_param,
8518 &state->data, state->total_data,
8519 state->max_data_return);
8520 END_PROFILE(Trans2_qfsinfo);
8521 break;
8524 case TRANSACT2_SETFSINFO:
8526 START_PROFILE(Trans2_setfsinfo);
8527 call_trans2setfsinfo(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_setfsinfo);
8532 break;
8535 case TRANSACT2_QPATHINFO:
8536 case TRANSACT2_QFILEINFO:
8538 START_PROFILE(Trans2_qpathinfo);
8539 call_trans2qfilepathinfo(conn, req, state->call,
8540 &state->param, state->total_param,
8541 &state->data, state->total_data,
8542 state->max_data_return);
8543 END_PROFILE(Trans2_qpathinfo);
8544 break;
8547 case TRANSACT2_SETPATHINFO:
8548 case TRANSACT2_SETFILEINFO:
8550 START_PROFILE(Trans2_setpathinfo);
8551 call_trans2setfilepathinfo(conn, req, state->call,
8552 &state->param, state->total_param,
8553 &state->data, state->total_data,
8554 state->max_data_return);
8555 END_PROFILE(Trans2_setpathinfo);
8556 break;
8559 case TRANSACT2_FINDNOTIFYFIRST:
8561 START_PROFILE(Trans2_findnotifyfirst);
8562 call_trans2findnotifyfirst(conn, req,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_findnotifyfirst);
8567 break;
8570 case TRANSACT2_FINDNOTIFYNEXT:
8572 START_PROFILE(Trans2_findnotifynext);
8573 call_trans2findnotifynext(conn, req,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_findnotifynext);
8578 break;
8581 case TRANSACT2_MKDIR:
8583 START_PROFILE(Trans2_mkdir);
8584 call_trans2mkdir(conn, req,
8585 &state->param, state->total_param,
8586 &state->data, state->total_data,
8587 state->max_data_return);
8588 END_PROFILE(Trans2_mkdir);
8589 break;
8592 case TRANSACT2_GET_DFS_REFERRAL:
8594 START_PROFILE(Trans2_get_dfs_referral);
8595 call_trans2getdfsreferral(conn, req,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_get_dfs_referral);
8600 break;
8603 case TRANSACT2_IOCTL:
8605 START_PROFILE(Trans2_ioctl);
8606 call_trans2ioctl(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_ioctl);
8611 break;
8614 default:
8615 /* Error in request */
8616 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8617 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8621 /****************************************************************************
8622 Reply to a SMBtrans2.
8623 ****************************************************************************/
8625 void reply_trans2(struct smb_request *req)
8627 connection_struct *conn = req->conn;
8628 unsigned int dsoff;
8629 unsigned int dscnt;
8630 unsigned int psoff;
8631 unsigned int pscnt;
8632 unsigned int tran_call;
8633 struct trans_state *state;
8634 NTSTATUS result;
8636 START_PROFILE(SMBtrans2);
8638 if (req->wct < 14) {
8639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8640 END_PROFILE(SMBtrans2);
8641 return;
8644 dsoff = SVAL(req->vwv+12, 0);
8645 dscnt = SVAL(req->vwv+11, 0);
8646 psoff = SVAL(req->vwv+10, 0);
8647 pscnt = SVAL(req->vwv+9, 0);
8648 tran_call = SVAL(req->vwv+14, 0);
8650 result = allow_new_trans(conn->pending_trans, req->mid);
8651 if (!NT_STATUS_IS_OK(result)) {
8652 DEBUG(2, ("Got invalid trans2 request: %s\n",
8653 nt_errstr(result)));
8654 reply_nterror(req, result);
8655 END_PROFILE(SMBtrans2);
8656 return;
8659 if (IS_IPC(conn)) {
8660 switch (tran_call) {
8661 /* List the allowed trans2 calls on IPC$ */
8662 case TRANSACT2_OPEN:
8663 case TRANSACT2_GET_DFS_REFERRAL:
8664 case TRANSACT2_QFILEINFO:
8665 case TRANSACT2_QFSINFO:
8666 case TRANSACT2_SETFSINFO:
8667 break;
8668 default:
8669 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8670 END_PROFILE(SMBtrans2);
8671 return;
8675 if ((state = talloc(conn, struct trans_state)) == NULL) {
8676 DEBUG(0, ("talloc failed\n"));
8677 reply_nterror(req, NT_STATUS_NO_MEMORY);
8678 END_PROFILE(SMBtrans2);
8679 return;
8682 state->cmd = SMBtrans2;
8684 state->mid = req->mid;
8685 state->vuid = req->vuid;
8686 state->setup_count = SVAL(req->vwv+13, 0);
8687 state->setup = NULL;
8688 state->total_param = SVAL(req->vwv+0, 0);
8689 state->param = NULL;
8690 state->total_data = SVAL(req->vwv+1, 0);
8691 state->data = NULL;
8692 state->max_param_return = SVAL(req->vwv+2, 0);
8693 state->max_data_return = SVAL(req->vwv+3, 0);
8694 state->max_setup_return = SVAL(req->vwv+4, 0);
8695 state->close_on_completion = BITSETW(req->vwv+5, 0);
8696 state->one_way = BITSETW(req->vwv+5, 1);
8698 state->call = tran_call;
8700 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8701 is so as a sanity check */
8702 if (state->setup_count != 1) {
8704 * Need to have rc=0 for ioctl to get job id for OS/2.
8705 * Network printing will fail if function is not successful.
8706 * Similar function in reply.c will be used if protocol
8707 * is LANMAN1.0 instead of LM1.2X002.
8708 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8709 * outbuf doesn't have to be set(only job id is used).
8711 if ( (state->setup_count == 4)
8712 && (tran_call == TRANSACT2_IOCTL)
8713 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8714 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8715 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8716 } else {
8717 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8718 DEBUG(2,("Transaction is %d\n",tran_call));
8719 TALLOC_FREE(state);
8720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8721 END_PROFILE(SMBtrans2);
8722 return;
8726 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8727 goto bad_param;
8729 if (state->total_data) {
8731 if (trans_oob(state->total_data, 0, dscnt)
8732 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8733 goto bad_param;
8736 /* Can't use talloc here, the core routines do realloc on the
8737 * params and data. */
8738 state->data = (char *)SMB_MALLOC(state->total_data);
8739 if (state->data == NULL) {
8740 DEBUG(0,("reply_trans2: data malloc fail for %u "
8741 "bytes !\n", (unsigned int)state->total_data));
8742 TALLOC_FREE(state);
8743 reply_nterror(req, NT_STATUS_NO_MEMORY);
8744 END_PROFILE(SMBtrans2);
8745 return;
8748 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8751 if (state->total_param) {
8753 if (trans_oob(state->total_param, 0, pscnt)
8754 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8755 goto bad_param;
8758 /* Can't use talloc here, the core routines do realloc on the
8759 * params and data. */
8760 state->param = (char *)SMB_MALLOC(state->total_param);
8761 if (state->param == NULL) {
8762 DEBUG(0,("reply_trans: param malloc fail for %u "
8763 "bytes !\n", (unsigned int)state->total_param));
8764 SAFE_FREE(state->data);
8765 TALLOC_FREE(state);
8766 reply_nterror(req, NT_STATUS_NO_MEMORY);
8767 END_PROFILE(SMBtrans2);
8768 return;
8771 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8774 state->received_data = dscnt;
8775 state->received_param = pscnt;
8777 if ((state->received_param == state->total_param) &&
8778 (state->received_data == state->total_data)) {
8780 handle_trans2(conn, req, state);
8782 SAFE_FREE(state->data);
8783 SAFE_FREE(state->param);
8784 TALLOC_FREE(state);
8785 END_PROFILE(SMBtrans2);
8786 return;
8789 DLIST_ADD(conn->pending_trans, state);
8791 /* We need to send an interim response then receive the rest
8792 of the parameter/data bytes */
8793 reply_outbuf(req, 0, 0);
8794 show_msg((char *)req->outbuf);
8795 END_PROFILE(SMBtrans2);
8796 return;
8798 bad_param:
8800 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8801 SAFE_FREE(state->data);
8802 SAFE_FREE(state->param);
8803 TALLOC_FREE(state);
8804 END_PROFILE(SMBtrans2);
8805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8809 /****************************************************************************
8810 Reply to a SMBtranss2
8811 ****************************************************************************/
8813 void reply_transs2(struct smb_request *req)
8815 connection_struct *conn = req->conn;
8816 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8817 struct trans_state *state;
8819 START_PROFILE(SMBtranss2);
8821 show_msg((const char *)req->inbuf);
8823 if (req->wct < 8) {
8824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8825 END_PROFILE(SMBtranss2);
8826 return;
8829 for (state = conn->pending_trans; state != NULL;
8830 state = state->next) {
8831 if (state->mid == req->mid) {
8832 break;
8836 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8838 END_PROFILE(SMBtranss2);
8839 return;
8842 /* Revise state->total_param and state->total_data in case they have
8843 changed downwards */
8845 if (SVAL(req->vwv+0, 0) < state->total_param)
8846 state->total_param = SVAL(req->vwv+0, 0);
8847 if (SVAL(req->vwv+1, 0) < state->total_data)
8848 state->total_data = SVAL(req->vwv+1, 0);
8850 pcnt = SVAL(req->vwv+2, 0);
8851 poff = SVAL(req->vwv+3, 0);
8852 pdisp = SVAL(req->vwv+4, 0);
8854 dcnt = SVAL(req->vwv+5, 0);
8855 doff = SVAL(req->vwv+6, 0);
8856 ddisp = SVAL(req->vwv+7, 0);
8858 state->received_param += pcnt;
8859 state->received_data += dcnt;
8861 if ((state->received_data > state->total_data) ||
8862 (state->received_param > state->total_param))
8863 goto bad_param;
8865 if (pcnt) {
8866 if (trans_oob(state->total_param, pdisp, pcnt)
8867 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8868 goto bad_param;
8870 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8873 if (dcnt) {
8874 if (trans_oob(state->total_data, ddisp, dcnt)
8875 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8876 goto bad_param;
8878 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8881 if ((state->received_param < state->total_param) ||
8882 (state->received_data < state->total_data)) {
8883 END_PROFILE(SMBtranss2);
8884 return;
8887 handle_trans2(conn, req, state);
8889 DLIST_REMOVE(conn->pending_trans, state);
8890 SAFE_FREE(state->data);
8891 SAFE_FREE(state->param);
8892 TALLOC_FREE(state);
8894 END_PROFILE(SMBtranss2);
8895 return;
8897 bad_param:
8899 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8900 DLIST_REMOVE(conn->pending_trans, state);
8901 SAFE_FREE(state->data);
8902 SAFE_FREE(state->param);
8903 TALLOC_FREE(state);
8904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8905 END_PROFILE(SMBtranss2);
8906 return;