s3-docs: Fix typo.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobfbb450476079f0b651e9b34bf6bc13c06b3a3e23
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
43 char *pdata,
44 files_struct *fsp,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 Roundup a value to the nearest allocation roundup size boundary.
54 Only do this for Windows clients.
55 ********************************************************************/
57 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
59 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
61 /* Only roundup for Windows clients. */
62 enum remote_arch_types ra_type = get_remote_arch();
63 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
64 val = SMB_ROUNDUP(val,rval);
66 return val;
69 /********************************************************************
70 Create a 64 bit FileIndex. If the file is on the same device as
71 the root of the share, just return the 64-bit inode. If it isn't,
72 mangle as we used to do.
73 ********************************************************************/
75 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
77 uint64_t file_index;
78 if (conn->base_share_dev == psbuf->st_ex_dev) {
79 return (uint64_t)psbuf->st_ex_ino;
81 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
82 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
83 return file_index;
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
99 SAMBA_XATTR_MARKER,
100 XATTR_NTACL_NAME,
101 NULL
104 int i;
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 return true;
110 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
112 return true;
114 return false;
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
127 char *val = NULL;
128 ssize_t sizeret;
130 again:
132 val = talloc_realloc(mem_ctx, val, char, attr_size);
133 if (!val) {
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 } else {
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
144 attr_size = 65536;
145 goto again;
148 if (sizeret == -1) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
155 pea->flags = 0;
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 } else {
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
162 TALLOC_FREE(val);
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
167 return NT_STATUS_OK;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
178 char *p;
179 char **names, **tmp;
180 size_t num_names;
181 ssize_t sizeret = -1;
183 if (!lp_ea_support(SNUM(conn))) {
184 if (pnames) {
185 *pnames = NULL;
187 *pnum_names = 0;
188 return NT_STATUS_OK;
192 * TALLOC the result early to get the talloc hierarchy right.
195 names = talloc_array(mem_ctx, char *, 1);
196 if (names == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 return NT_STATUS_NO_MEMORY;
201 while (ea_namelist_size <= 65536) {
203 ea_namelist = talloc_realloc(
204 names, ea_namelist, char, ea_namelist_size);
205 if (ea_namelist == NULL) {
206 DEBUG(0, ("talloc failed\n"));
207 TALLOC_FREE(names);
208 return NT_STATUS_NO_MEMORY;
211 if (fsp && fsp->fh->fd != -1) {
212 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 ea_namelist_size);
214 } else {
215 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
216 ea_namelist_size);
219 if ((sizeret == -1) && (errno == ERANGE)) {
220 ea_namelist_size *= 2;
222 else {
223 break;
227 if (sizeret == -1) {
228 TALLOC_FREE(names);
229 return map_nt_error_from_unix(errno);
232 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
233 (unsigned int)sizeret));
235 if (sizeret == 0) {
236 TALLOC_FREE(names);
237 if (pnames) {
238 *pnames = NULL;
240 *pnum_names = 0;
241 return NT_STATUS_OK;
245 * Ensure the result is 0-terminated
248 if (ea_namelist[sizeret-1] != '\0') {
249 TALLOC_FREE(names);
250 return NT_STATUS_INTERNAL_ERROR;
254 * count the names
256 num_names = 0;
258 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
259 num_names += 1;
262 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
263 if (tmp == NULL) {
264 DEBUG(0, ("talloc failed\n"));
265 TALLOC_FREE(names);
266 return NT_STATUS_NO_MEMORY;
269 names = tmp;
270 num_names = 0;
272 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
273 names[num_names++] = p;
276 if (pnames) {
277 *pnames = names;
278 } else {
279 TALLOC_FREE(names);
281 *pnum_names = num_names;
282 return NT_STATUS_OK;
285 /****************************************************************************
286 Return a linked list of the total EA's. Plus the total size
287 ****************************************************************************/
289 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
290 const char *fname, size_t *pea_total_len)
292 /* Get a list of all xattrs. Max namesize is 64k. */
293 size_t i, num_names;
294 char **names;
295 struct ea_list *ea_list_head = NULL;
296 NTSTATUS status;
298 *pea_total_len = 0;
300 if (!lp_ea_support(SNUM(conn))) {
301 return NULL;
304 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
305 &names, &num_names);
307 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
308 return NULL;
311 for (i=0; i<num_names; i++) {
312 struct ea_list *listp;
313 fstring dos_ea_name;
315 if (strnequal(names[i], "system.", 7)
316 || samba_private_attr_name(names[i]))
317 continue;
319 listp = talloc(mem_ctx, struct ea_list);
320 if (listp == NULL) {
321 return NULL;
324 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
325 fname, names[i],
326 &listp->ea))) {
327 return NULL;
330 push_ascii_fstring(dos_ea_name, listp->ea.name);
332 *pea_total_len +=
333 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
335 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
336 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
337 (unsigned int)listp->ea.value.length));
339 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
343 /* Add on 4 for total length. */
344 if (*pea_total_len) {
345 *pea_total_len += 4;
348 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
349 (unsigned int)*pea_total_len));
351 return ea_list_head;
354 /****************************************************************************
355 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
356 that was filled.
357 ****************************************************************************/
359 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
360 connection_struct *conn, struct ea_list *ea_list)
362 unsigned int ret_data_size = 4;
363 char *p = pdata;
365 SMB_ASSERT(total_data_size >= 4);
367 if (!lp_ea_support(SNUM(conn))) {
368 SIVAL(pdata,4,0);
369 return 4;
372 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
373 size_t dos_namelen;
374 fstring dos_ea_name;
375 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
376 dos_namelen = strlen(dos_ea_name);
377 if (dos_namelen > 255 || dos_namelen == 0) {
378 break;
380 if (ea_list->ea.value.length > 65535) {
381 break;
383 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
384 break;
387 /* We know we have room. */
388 SCVAL(p,0,ea_list->ea.flags);
389 SCVAL(p,1,dos_namelen);
390 SSVAL(p,2,ea_list->ea.value.length);
391 strlcpy(p+4, dos_ea_name, dos_namelen+1);
392 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
394 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
398 ret_data_size = PTR_DIFF(p, pdata);
399 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
400 SIVAL(pdata,0,ret_data_size);
401 return ret_data_size;
404 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
405 char *pdata,
406 unsigned int total_data_size,
407 unsigned int *ret_data_size,
408 connection_struct *conn,
409 struct ea_list *ea_list)
411 uint8_t *p = (uint8_t *)pdata;
412 uint8_t *last_start = NULL;
414 *ret_data_size = 0;
416 if (!lp_ea_support(SNUM(conn))) {
417 return NT_STATUS_NO_EAS_ON_FILE;
420 for (; ea_list; ea_list = ea_list->next) {
421 size_t dos_namelen;
422 fstring dos_ea_name;
423 size_t this_size;
425 if (last_start) {
426 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
428 last_start = p;
430 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
431 dos_namelen = strlen(dos_ea_name);
432 if (dos_namelen > 255 || dos_namelen == 0) {
433 return NT_STATUS_INTERNAL_ERROR;
435 if (ea_list->ea.value.length > 65535) {
436 return NT_STATUS_INTERNAL_ERROR;
439 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
441 if (ea_list->next) {
442 size_t pad = 4 - (this_size % 4);
443 this_size += pad;
446 if (this_size > total_data_size) {
447 return NT_STATUS_INFO_LENGTH_MISMATCH;
450 /* We know we have room. */
451 SIVAL(p, 0x00, 0); /* next offset */
452 SCVAL(p, 0x04, ea_list->ea.flags);
453 SCVAL(p, 0x05, dos_namelen);
454 SSVAL(p, 0x06, ea_list->ea.value.length);
455 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
456 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
458 total_data_size -= this_size;
459 p += this_size;
462 *ret_data_size = PTR_DIFF(p, pdata);
463 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
464 return NT_STATUS_OK;
467 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
469 size_t total_ea_len = 0;
470 TALLOC_CTX *mem_ctx = NULL;
472 if (!lp_ea_support(SNUM(conn))) {
473 return 0;
475 mem_ctx = talloc_tos();
476 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
477 return total_ea_len;
480 /****************************************************************************
481 Ensure the EA name is case insensitive by matching any existing EA name.
482 ****************************************************************************/
484 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
486 size_t total_ea_len;
487 TALLOC_CTX *mem_ctx = talloc_tos();
488 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
490 for (; ea_list; ea_list = ea_list->next) {
491 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
492 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
493 &unix_ea_name[5], ea_list->ea.name));
494 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
495 break;
500 /****************************************************************************
501 Set or delete an extended attribute.
502 ****************************************************************************/
504 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, struct ea_list *ea_list)
507 char *fname = NULL;
509 if (!lp_ea_support(SNUM(conn))) {
510 return NT_STATUS_EAS_NOT_SUPPORTED;
513 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
514 return NT_STATUS_ACCESS_DENIED;
517 /* For now setting EAs on streams isn't supported. */
518 fname = smb_fname->base_name;
520 for (;ea_list; ea_list = ea_list->next) {
521 int ret;
522 fstring unix_ea_name;
524 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
525 fstrcat(unix_ea_name, ea_list->ea.name);
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
543 } else {
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
548 #ifdef ENOATTR
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
552 unix_ea_name));
553 ret = 0;
555 #endif
556 } else {
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
563 } else {
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
571 if (ret == -1) {
572 #ifdef ENOTSUP
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
576 #endif
577 return map_nt_error_from_unix(errno);
581 return NT_STATUS_OK;
583 /****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585 ****************************************************************************/
587 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
596 offset++; /* Go past the namelen byte. */
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
602 break;
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
606 return NULL;
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
609 &converted_size)) {
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
613 if (!eal->ea.name) {
614 return NULL;
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
622 return ea_list_head;
625 /****************************************************************************
626 Read one EA list entry from the buffer.
627 ****************************************************************************/
629 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
631 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
632 uint16 val_len;
633 unsigned int namelen;
634 size_t converted_size;
636 if (!eal) {
637 return NULL;
640 if (data_size < 6) {
641 return NULL;
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
648 if (4 + namelen + 1 + val_len > data_size) {
649 return NULL;
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
654 return NULL;
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
658 strerror(errno)));
660 if (!eal->ea.name) {
661 return NULL;
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
666 return NULL;
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
676 if (pbytes_used) {
677 *pbytes_used = 4 + namelen + 1 + val_len;
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
683 return eal;
686 /****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688 ****************************************************************************/
690 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
692 struct ea_list *ea_list_head = NULL;
693 size_t offset = 0;
694 size_t bytes_used = 0;
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
699 if (!eal) {
700 return NULL;
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
707 return ea_list_head;
710 /****************************************************************************
711 Count the total EA size needed.
712 ****************************************************************************/
714 static size_t ea_list_size(struct ea_list *ealist)
716 fstring dos_ea_name;
717 struct ea_list *listp;
718 size_t ret = 0;
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
724 /* Add on 4 for total length. */
725 if (ret) {
726 ret += 4;
729 return ret;
732 /****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736 ****************************************************************************/
738 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
740 struct ea_list *nlistp, *flistp;
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
745 break;
749 if (flistp) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
753 } else {
754 /* Null entry. */
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
760 *total_ea_len = ea_list_size(name_list);
761 return name_list;
764 /****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769 ****************************************************************************/
771 void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
773 const char *params,
774 int paramsize,
775 const char *pdata,
776 int datasize,
777 int max_data_bytes)
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
787 int useable_space;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = req->sconn;
795 int max_send = sconn->smb1.sessions.max_send;
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
800 for OS/2. */
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
806 overflow = True;
809 /* If there genuinely are no parameters or data to send just send the empty packet */
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(sconn,
815 (char *)req->outbuf,
816 true, req->seqnum+1,
817 IS_CONN_ENCRYPTED(conn),
818 &req->pcd)) {
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
821 TALLOC_FREE(req->outbuf);
822 return;
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
836 useable_space = max_send - (smb_size
837 + 2 * 10 /* wct */
838 + alignment_offset
839 + data_alignment_offset);
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
850 total_sent_thistime = params_to_send + data_to_send;
852 /* We can never send more than useable_space */
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
866 * We might have SMBtrans2s in req which was transferred to
867 * the outbuf, fix that.
869 SCVAL(req->outbuf, smb_com, SMBtrans2);
871 /* Set total params and data to be sent */
872 SSVAL(req->outbuf,smb_tprcnt,paramsize);
873 SSVAL(req->outbuf,smb_tdrcnt,datasize);
875 /* Calculate how many parameters and data we can fit into
876 * this packet. Parameters get precedence
879 params_sent_thistime = MIN(params_to_send,useable_space);
880 data_sent_thistime = useable_space - params_sent_thistime;
881 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
883 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
885 /* smb_proff is the offset from the start of the SMB header to the
886 parameter bytes, however the first 4 bytes of outbuf are
887 the Netbios over TCP header. Thus use smb_base() to subtract
888 them from the calculation */
890 SSVAL(req->outbuf,smb_proff,
891 ((smb_buf(req->outbuf)+alignment_offset)
892 - smb_base(req->outbuf)));
894 if(params_sent_thistime == 0)
895 SSVAL(req->outbuf,smb_prdisp,0);
896 else
897 /* Absolute displacement of param bytes sent in this packet */
898 SSVAL(req->outbuf,smb_prdisp,pp - params);
900 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
901 if(data_sent_thistime == 0) {
902 SSVAL(req->outbuf,smb_droff,0);
903 SSVAL(req->outbuf,smb_drdisp, 0);
904 } else {
905 /* The offset of the data bytes is the offset of the
906 parameter bytes plus the number of parameters being sent this time */
907 SSVAL(req->outbuf, smb_droff,
908 ((smb_buf(req->outbuf)+alignment_offset)
909 - smb_base(req->outbuf))
910 + params_sent_thistime + data_alignment_offset);
911 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
914 /* Initialize the padding for alignment */
916 if (alignment_offset != 0) {
917 memset(smb_buf(req->outbuf), 0, alignment_offset);
920 /* Copy the param bytes into the packet */
922 if(params_sent_thistime) {
923 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
924 params_sent_thistime);
927 /* Copy in the data bytes */
928 if(data_sent_thistime) {
929 if (data_alignment_offset != 0) {
930 memset((smb_buf(req->outbuf)+alignment_offset+
931 params_sent_thistime), 0,
932 data_alignment_offset);
934 memcpy(smb_buf(req->outbuf)+alignment_offset
935 +params_sent_thistime+data_alignment_offset,
936 pd,data_sent_thistime);
939 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
940 params_sent_thistime, data_sent_thistime, useable_space));
941 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
942 params_to_send, data_to_send, paramsize, datasize));
944 if (overflow) {
945 error_packet_set((char *)req->outbuf,
946 ERRDOS,ERRbufferoverflow,
947 STATUS_BUFFER_OVERFLOW,
948 __LINE__,__FILE__);
951 /* Send the packet */
952 show_msg((char *)req->outbuf);
953 if (!srv_send_smb(sconn,
954 (char *)req->outbuf,
955 true, req->seqnum+1,
956 IS_CONN_ENCRYPTED(conn),
957 &req->pcd))
958 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
960 TALLOC_FREE(req->outbuf);
962 pp += params_sent_thistime;
963 pd += data_sent_thistime;
965 params_to_send -= params_sent_thistime;
966 data_to_send -= data_sent_thistime;
968 /* Sanity check */
969 if(params_to_send < 0 || data_to_send < 0) {
970 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
971 params_to_send, data_to_send));
972 return;
976 return;
979 /****************************************************************************
980 Reply to a TRANSACT2_OPEN.
981 ****************************************************************************/
983 static void call_trans2open(connection_struct *conn,
984 struct smb_request *req,
985 char **pparams, int total_params,
986 char **ppdata, int total_data,
987 unsigned int max_data_bytes)
989 struct smb_filename *smb_fname = NULL;
990 char *params = *pparams;
991 char *pdata = *ppdata;
992 int deny_mode;
993 int32 open_attr;
994 bool oplock_request;
995 #if 0
996 bool return_additional_info;
997 int16 open_sattr;
998 time_t open_time;
999 #endif
1000 int open_ofun;
1001 uint32 open_size;
1002 char *pname;
1003 char *fname = NULL;
1004 SMB_OFF_T size=0;
1005 int fattr=0,mtime=0;
1006 SMB_INO_T inode = 0;
1007 int smb_action = 0;
1008 files_struct *fsp;
1009 struct ea_list *ea_list = NULL;
1010 uint16 flags = 0;
1011 NTSTATUS status;
1012 uint32 access_mask;
1013 uint32 share_mode;
1014 uint32 create_disposition;
1015 uint32 create_options = 0;
1016 uint32_t private_flags = 0;
1017 TALLOC_CTX *ctx = talloc_tos();
1020 * Ensure we have enough parameters to perform the operation.
1023 if (total_params < 29) {
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1025 goto out;
1028 flags = SVAL(params, 0);
1029 deny_mode = SVAL(params, 2);
1030 open_attr = SVAL(params,6);
1031 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1032 if (oplock_request) {
1033 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1036 #if 0
1037 return_additional_info = BITSETW(params,0);
1038 open_sattr = SVAL(params, 4);
1039 open_time = make_unix_date3(params+8);
1040 #endif
1041 open_ofun = SVAL(params,12);
1042 open_size = IVAL(params,14);
1043 pname = &params[28];
1045 if (IS_IPC(conn)) {
1046 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1047 goto out;
1050 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1051 total_params - 28, STR_TERMINATE,
1052 &status);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 reply_nterror(req, status);
1055 goto out;
1058 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1059 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1060 (unsigned int)open_ofun, open_size));
1062 status = filename_convert(ctx,
1063 conn,
1064 req->flags2 & FLAGS2_DFS_PATHNAMES,
1065 fname,
1067 NULL,
1068 &smb_fname);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1071 reply_botherror(req,
1072 NT_STATUS_PATH_NOT_COVERED,
1073 ERRSRV, ERRbadpath);
1074 goto out;
1076 reply_nterror(req, status);
1077 goto out;
1080 if (open_ofun == 0) {
1081 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1082 goto out;
1085 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1086 open_ofun,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1089 &create_options,
1090 &private_flags)) {
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1092 goto out;
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1099 goto out;
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 goto out;
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1110 total_data - 4);
1111 if (!ea_list) {
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1113 goto out;
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1118 goto out;
1122 status = SMB_VFS_CREATE_FILE(
1123 conn, /* conn */
1124 req, /* req */
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1134 private_flags,
1135 NULL, /* sd */
1136 ea_list, /* ea_list */
1137 &fsp, /* result */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->sconn, req->mid)) {
1142 /* We have re-scheduled this call. */
1143 goto out;
1145 reply_openerror(req, status);
1146 goto out;
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1156 goto out;
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1163 goto out;
1165 params = *pparams;
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1186 if (flags & 8) {
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1190 } else {
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1196 out:
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1209 const char *str,
1210 const char *mask)
1212 if (mask[0] == '.' && mask[1] == 0) {
1213 return false;
1216 if (has_wild) {
1217 return false;
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1222 } else {
1223 return strcasecmp_m(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1233 if(S_ISREG(mode))
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1237 #ifdef S_ISLNK
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1240 #endif
1241 #ifdef S_ISCHR
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1244 #endif
1245 #ifdef S_ISBLK
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1248 #endif
1249 #ifdef S_ISFIFO
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1252 #endif
1253 #ifdef S_ISSOCK
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1256 #endif
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1270 uint32 perms,
1271 enum perm_type ptype,
1272 mode_t *ret_perms)
1274 mode_t ret = 0;
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1279 } else {
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1294 #ifdef S_ISVTX
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1296 #endif
1297 #ifdef S_ISGID
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1299 #endif
1300 #ifdef S_ISUID
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1302 #endif
1304 switch (ptype) {
1305 case PERM_NEW_FILE:
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1310 break;
1311 case PERM_NEW_DIR:
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1315 break;
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1321 break;
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1327 break;
1330 *ret_perms = ret;
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1349 "as a directory\n",
1350 pathname));
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1353 return true;
1355 errno = saved_errno;
1356 return false;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1368 bool has_wild;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1373 void *private_data,
1374 const char *dname,
1375 const char *mask,
1376 char **_fname)
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1380 bool ok;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1382 bool got_match;
1383 const char *fname;
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1389 if (!ok) {
1390 return false;
1392 fname = mangled_name;
1393 } else {
1394 fname = dname;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1399 fname, mask);
1400 state->got_exact_match = got_match;
1401 if (!got_match) {
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1417 if (!ok) {
1418 return false;
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1425 if (!got_match) {
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1431 if (!got_match) {
1432 return false;
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1437 return false;
1440 return true;
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1444 void *private_data,
1445 struct smb_filename *smb_fname,
1446 uint32_t *_mode)
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1451 uint32_t mode = 0;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1458 strerror(errno)));
1459 return false;
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1464 * directories */
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1468 &smb_fname->st);
1469 if (!ms_dfs_link) {
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1473 strerror(errno)));
1474 return false;
1478 if (ms_dfs_link) {
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1480 } else {
1481 mode = dos_mode(state->conn, smb_fname);
1484 *_mode = mode;
1485 return true;
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1490 uint16_t flags2,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1495 uint32_t mode,
1496 const char *fname,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1499 uint8_t align,
1500 bool do_pad,
1501 char *base_data,
1502 char **ppdata,
1503 char *end_data,
1504 bool *out_of_space,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1508 uint32_t reskey=0;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1512 uint32_t len;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1516 char *nameptr;
1517 char *last_entry_ptr;
1518 bool was_8_3;
1519 int off;
1520 int pad = 0;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1558 pad -= off;
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1564 (unsigned int)pad,
1565 space_remaining ));
1566 return false; /* Not finished - just out of space */
1569 off += pad;
1570 /* initialize padding to 0 */
1571 if (pad) {
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1577 space_remaining ));
1579 pdata += pad;
1580 p = pdata;
1581 last_entry_ptr = p;
1583 pad = 0;
1584 off = 0;
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1590 SIVAL(p,0,reskey);
1591 p += 4;
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1598 SSVAL(p,20,mode);
1599 p += 23;
1600 nameptr = p;
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE);
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1608 if (len > 2) {
1609 SCVAL(nameptr, -1, len - 2);
1610 } else {
1611 SCVAL(nameptr, -1, 0);
1613 } else {
1614 if (len > 1) {
1615 SCVAL(nameptr, -1, len - 1);
1616 } else {
1617 SCVAL(nameptr, -1, 0);
1620 p += len;
1621 break;
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1626 SIVAL(p,0,reskey);
1627 p += 4;
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1634 SSVAL(p,20,mode);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1640 p += 27;
1641 nameptr = p - 1;
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1646 if (len > 2) {
1647 len -= 2;
1648 } else {
1649 len = 0;
1651 } else {
1652 if (len > 1) {
1653 len -= 1;
1654 } else {
1655 len = 0;
1658 SCVAL(nameptr,0,len);
1659 p += len;
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1661 break;
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1666 size_t ea_len = 0;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1669 if (!name_list) {
1670 return false;
1672 if (requires_resume_key) {
1673 SIVAL(p,0,reskey);
1674 p += 4;
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1681 SSVAL(p,20,mode);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1686 &ea_len);
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1696 space_remaining ));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702 nameptr = p;
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707 if (len > 2) {
1708 len -= 2;
1709 } else {
1710 len = 0;
1712 } else {
1713 if (len > 1) {
1714 len -= 1;
1715 } else {
1716 len = 0;
1719 SCVAL(nameptr,0,len);
1720 p += len + 1;
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722 break;
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728 p += 4;
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1742 p += 4;
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1751 conn->params)) {
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1759 if (len < 24) {
1760 memset(p + 2 + len,'\0',24 - len);
1762 SSVAL(p, 0, len);
1763 } else {
1764 memset(p,'\0',26);
1766 p += 2 + 24;
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1770 SIVAL(q,0,len);
1771 p += len;
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1780 SIVAL(pdata,0,pad);
1782 * set padding to zero
1784 if (do_pad) {
1785 memset(p, 0, pad - len);
1786 p = pdata + pad;
1787 } else {
1788 p = pdata + len;
1790 break;
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1794 p += 4;
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1806 SIVAL(p,0,len);
1807 p += 4 + len;
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1816 SIVAL(pdata,0,pad);
1818 * set padding to zero
1820 if (do_pad) {
1821 memset(p, 0, pad - len);
1822 p = pdata + pad;
1823 } else {
1824 p = pdata + len;
1826 break;
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1830 p += 4;
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1844 p +=4;
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1849 SIVAL(q, 0, len);
1850 p += len;
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1859 SIVAL(pdata,0,pad);
1861 * set padding to zero
1863 if (do_pad) {
1864 memset(p, 0, pad - len);
1865 p = pdata + pad;
1866 } else {
1867 p = pdata + len;
1869 break;
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1873 p += 4;
1874 SIVAL(p,0,reskey); p += 4;
1875 p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1881 SIVAL(p, -4, len);
1882 p += len;
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1891 SIVAL(pdata,0,pad);
1893 * set padding to zero
1895 if (do_pad) {
1896 memset(p, 0, pad - len);
1897 p = pdata + pad;
1898 } else {
1899 p = pdata + len;
1901 break;
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1905 p += 4;
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1919 p +=4;
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1926 SIVAL(q, 0, len);
1927 p += len;
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1936 SIVAL(pdata,0,pad);
1938 * set padding to zero
1940 if (do_pad) {
1941 memset(p, 0, pad - len);
1942 p = pdata + pad;
1943 } else {
1944 p = pdata + len;
1946 break;
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1951 p += 4;
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1965 p +=4;
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1974 conn->params)) {
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1982 SSVAL(p, 0, len);
1983 if (len < 24) {
1984 memset(p + 2 + len,'\0',24 - len);
1986 SSVAL(p, 0, len);
1987 } else {
1988 memset(p,'\0',26);
1990 p += 26;
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1996 SIVAL(q,0,len);
1997 p += len;
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2006 SIVAL(pdata,0,pad);
2008 * set padding to zero
2010 if (do_pad) {
2011 memset(p, 0, pad - len);
2012 p = pdata + pad;
2013 } else {
2014 p = pdata + len;
2016 break;
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2022 p+= 4;
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2033 STR_TERMINATE);
2034 } else {
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2038 nameptr = p;
2039 p += 4;
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2045 p += len;
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2054 SIVAL(pdata,0,pad);
2056 * set padding to zero
2058 if (do_pad) {
2059 memset(p, 0, pad - len);
2060 p = pdata + pad;
2061 } else {
2062 p = pdata + len;
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2066 break;
2068 default:
2069 return false;
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2077 space_remaining ));
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2084 *ppdata = p;
2086 return true;
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2092 uint16 flags2,
2093 const char *path_mask,
2094 uint32 dirtype,
2095 int info_level,
2096 int requires_resume_key,
2097 bool dont_descend,
2098 bool ask_sharemode,
2099 uint8_t align,
2100 bool do_pad,
2101 char **ppdata,
2102 char *base_data,
2103 char *end_data,
2104 int space_remaining,
2105 bool *out_of_space,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2110 const char *p;
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2113 uint32_t mode = 0;
2114 char *fname = NULL;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2117 bool ok;
2118 uint64_t last_entry_off = 0;
2120 ZERO_STRUCT(state);
2121 state.conn = conn;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2131 if(p != NULL) {
2132 if(p[1] == '\0') {
2133 mask = "*.*";
2134 } else {
2135 mask = p+1;
2137 } else {
2138 mask = path_mask;
2141 ok = smbd_dirptr_get_entry(ctx,
2142 dirptr,
2143 mask,
2144 dirtype,
2145 dont_descend,
2146 ask_sharemode,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2149 &state,
2150 &fname,
2151 &smb_fname,
2152 &mode,
2153 &prev_dirpos);
2154 if (!ok) {
2155 return false;
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2161 conn,
2162 flags2,
2163 info_level,
2164 name_list,
2165 state.check_mangled_names,
2166 requires_resume_key,
2167 mode,
2168 fname,
2169 smb_fname,
2170 space_remaining,
2171 align,
2172 do_pad,
2173 base_data,
2174 ppdata,
2175 end_data,
2176 out_of_space,
2177 &last_entry_off);
2178 TALLOC_FREE(fname);
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2182 return false;
2184 if (!ok) {
2185 return false;
2188 *_last_entry_off = last_entry_off;
2189 return true;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2195 uint16 flags2,
2196 const char *path_mask,
2197 uint32 dirtype,
2198 int info_level,
2199 bool requires_resume_key,
2200 bool dont_descend,
2201 bool ask_sharemode,
2202 char **ppdata,
2203 char *base_data,
2204 char *end_data,
2205 int space_remaining,
2206 bool *out_of_space,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2211 uint8_t align = 4;
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2216 align = 1;
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2222 align, do_pad,
2223 ppdata, base_data, end_data,
2224 space_remaining,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2243 requested. */
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2247 char *data_end;
2248 uint32 dirtype;
2249 int maxentries;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2252 bool close_if_end;
2253 bool requires_resume_key;
2254 int info_level;
2255 char *directory = NULL;
2256 char *mask = NULL;
2257 char *p;
2258 int last_entry_off=0;
2259 int dptr_num = -1;
2260 int numentries = 0;
2261 int i;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2274 if (total_params < 13) {
2275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2276 goto out;
2279 dirtype = SVAL(params,0);
2280 maxentries = SVAL(params,2);
2281 findfirst_flags = SVAL(params,4);
2282 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2283 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2284 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2285 info_level = SVAL(params,6);
2287 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2288 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2289 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2290 info_level, max_data_bytes));
2292 if (!maxentries) {
2293 /* W2K3 seems to treat zero as 1. */
2294 maxentries = 1;
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 break;
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314 goto out;
2316 break;
2317 default:
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 goto out;
2322 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2323 params+12, total_params - 12,
2324 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 reply_nterror(req, ntstatus);
2327 goto out;
2330 ntstatus = filename_convert(ctx, conn,
2331 req->flags2 & FLAGS2_DFS_PATHNAMES,
2332 directory,
2333 (UCF_SAVE_LCOMP |
2334 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2335 &mask_contains_wcard,
2336 &smb_dname);
2337 if (!NT_STATUS_IS_OK(ntstatus)) {
2338 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2339 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2340 ERRSRV, ERRbadpath);
2341 goto out;
2343 reply_nterror(req, ntstatus);
2344 goto out;
2347 mask = smb_dname->original_lcomp;
2349 directory = smb_dname->base_name;
2351 p = strrchr_m(directory,'/');
2352 if(p == NULL) {
2353 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2354 if((directory[0] == '.') && (directory[1] == '\0')) {
2355 mask = talloc_strdup(ctx,"*");
2356 if (!mask) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2358 goto out;
2360 mask_contains_wcard = True;
2362 } else {
2363 *p = 0;
2366 if (p == NULL || p == directory) {
2367 /* Ensure we don't have a directory name of "". */
2368 directory = talloc_strdup(talloc_tos(), ".");
2369 if (!directory) {
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2371 goto out;
2375 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2377 if (info_level == SMB_FIND_EA_LIST) {
2378 uint32 ea_size;
2380 if (total_data < 4) {
2381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2382 goto out;
2385 ea_size = IVAL(pdata,0);
2386 if (ea_size != total_data) {
2387 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2388 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2390 goto out;
2393 if (!lp_ea_support(SNUM(conn))) {
2394 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2395 goto out;
2398 /* Pull out the list of names. */
2399 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2400 if (!ea_list) {
2401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2402 goto out;
2406 *ppdata = (char *)SMB_REALLOC(
2407 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2408 if(*ppdata == NULL ) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2410 goto out;
2412 pdata = *ppdata;
2413 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2415 /* Realloc the params space */
2416 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2417 if (*pparams == NULL) {
2418 reply_nterror(req, NT_STATUS_NO_MEMORY);
2419 goto out;
2421 params = *pparams;
2423 /* Save the wildcard match and attribs we are using on this directory -
2424 needed as lanman2 assumes these are being saved between calls */
2426 ntstatus = dptr_create(conn,
2427 NULL, /* fsp */
2428 directory,
2429 False,
2430 True,
2431 req->smbpid,
2432 mask,
2433 mask_contains_wcard,
2434 dirtype,
2435 &dirptr);
2437 if (!NT_STATUS_IS_OK(ntstatus)) {
2438 reply_nterror(req, ntstatus);
2439 goto out;
2442 dptr_num = dptr_dnum(dirptr);
2443 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2445 /* Initialize per TRANS2_FIND_FIRST operation data */
2446 dptr_init_search_op(dirptr);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2452 directory,lp_dontdescend(SNUM(conn))));
2453 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2454 dont_descend = True;
2456 p = pdata;
2457 space_remaining = max_data_bytes;
2458 out_of_space = False;
2460 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2461 bool got_exact_match = False;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2466 out_of_space = True;
2467 finished = False;
2468 } else {
2469 finished = !get_lanman2_dir_entry(ctx,
2470 conn,
2471 dirptr,
2472 req->flags2,
2473 mask,dirtype,info_level,
2474 requires_resume_key,dont_descend,
2475 ask_sharemode,
2476 &p,pdata,data_end,
2477 space_remaining, &out_of_space,
2478 &got_exact_match,
2479 &last_entry_off, ea_list);
2482 if (finished && out_of_space)
2483 finished = False;
2485 if (!finished && !out_of_space)
2486 numentries++;
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2495 if(got_exact_match)
2496 finished = True;
2498 /* Ensure space_remaining never goes -ve. */
2499 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2500 space_remaining = 0;
2501 out_of_space = true;
2502 } else {
2503 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2507 /* Check if we can close the dirptr */
2508 if(close_after_first || (finished && close_if_end)) {
2509 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2510 dptr_close(sconn, &dptr_num);
2514 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2515 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2516 * the protocol level is less than NT1. Tested with smbclient. JRA.
2517 * This should fix the OS/2 client bug #2335.
2520 if(numentries == 0) {
2521 dptr_close(sconn, &dptr_num);
2522 if (get_Protocol() < PROTOCOL_NT1) {
2523 reply_force_doserror(req, ERRDOS, ERRnofiles);
2524 goto out;
2525 } else {
2526 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2527 ERRDOS, ERRbadfile);
2528 goto out;
2532 /* At this point pdata points to numentries directory entries. */
2534 /* Set up the return parameter block */
2535 SSVAL(params,0,dptr_num);
2536 SSVAL(params,2,numentries);
2537 SSVAL(params,4,finished);
2538 SSVAL(params,6,0); /* Never an EA error */
2539 SSVAL(params,8,last_entry_off);
2541 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2542 max_data_bytes);
2544 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2545 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2546 if (!directory) {
2547 reply_nterror(req, NT_STATUS_NO_MEMORY);
2551 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2552 smb_fn_name(req->cmd),
2553 mask, directory, dirtype, numentries ) );
2556 * Force a name mangle here to ensure that the
2557 * mask as an 8.3 name is top of the mangled cache.
2558 * The reasons for this are subtle. Don't remove
2559 * this code unless you know what you are doing
2560 * (see PR#13758). JRA.
2563 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2564 char mangled_name[13];
2565 name_to_8_3(mask, mangled_name, True, conn->params);
2567 out:
2568 TALLOC_FREE(smb_dname);
2569 return;
2572 /****************************************************************************
2573 Reply to a TRANS2_FINDNEXT.
2574 ****************************************************************************/
2576 static void call_trans2findnext(connection_struct *conn,
2577 struct smb_request *req,
2578 char **pparams, int total_params,
2579 char **ppdata, int total_data,
2580 unsigned int max_data_bytes)
2582 /* We must be careful here that we don't return more than the
2583 allowed number of data bytes. If this means returning fewer than
2584 maxentries then so be it. We assume that the redirector has
2585 enough room for the fixed number of parameter bytes it has
2586 requested. */
2587 char *params = *pparams;
2588 char *pdata = *ppdata;
2589 char *data_end;
2590 int dptr_num;
2591 int maxentries;
2592 uint16 info_level;
2593 uint32 resume_key;
2594 uint16 findnext_flags;
2595 bool close_after_request;
2596 bool close_if_end;
2597 bool requires_resume_key;
2598 bool continue_bit;
2599 bool mask_contains_wcard = False;
2600 char *resume_name = NULL;
2601 const char *mask = NULL;
2602 const char *directory = NULL;
2603 char *p = NULL;
2604 uint16 dirtype;
2605 int numentries = 0;
2606 int i, last_entry_off=0;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 struct ea_list *ea_list = NULL;
2612 NTSTATUS ntstatus = NT_STATUS_OK;
2613 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2614 TALLOC_CTX *ctx = talloc_tos();
2615 struct dptr_struct *dirptr;
2616 struct smbd_server_connection *sconn = req->sconn;
2618 if (total_params < 13) {
2619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2620 return;
2623 dptr_num = SVAL(params,0);
2624 maxentries = SVAL(params,2);
2625 info_level = SVAL(params,4);
2626 resume_key = IVAL(params,6);
2627 findnext_flags = SVAL(params,10);
2628 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2629 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2630 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2631 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2633 if (!continue_bit) {
2634 /* We only need resume_name if continue_bit is zero. */
2635 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2636 params+12,
2637 total_params - 12, STR_TERMINATE, &ntstatus,
2638 &mask_contains_wcard);
2639 if (!NT_STATUS_IS_OK(ntstatus)) {
2640 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2641 complain (it thinks we're asking for the directory above the shared
2642 path or an invalid name). Catch this as the resume name is only compared, never used in
2643 a file access. JRA. */
2644 srvstr_pull_talloc(ctx, params, req->flags2,
2645 &resume_name, params+12,
2646 total_params - 12,
2647 STR_TERMINATE);
2649 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2650 reply_nterror(req, ntstatus);
2651 return;
2656 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2657 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2658 resume_key = %d resume name = %s continue=%d level = %d\n",
2659 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2660 requires_resume_key, resume_key,
2661 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2663 if (!maxentries) {
2664 /* W2K3 seems to treat zero as 1. */
2665 maxentries = 1;
2668 switch (info_level) {
2669 case SMB_FIND_INFO_STANDARD:
2670 case SMB_FIND_EA_SIZE:
2671 case SMB_FIND_EA_LIST:
2672 case SMB_FIND_FILE_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_FILE_NAMES_INFO:
2675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2676 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2677 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2678 break;
2679 case SMB_FIND_FILE_UNIX:
2680 case SMB_FIND_FILE_UNIX_INFO2:
2681 /* Always use filesystem for UNIX mtime query. */
2682 ask_sharemode = false;
2683 if (!lp_unix_extensions()) {
2684 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2685 return;
2687 break;
2688 default:
2689 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2690 return;
2693 if (info_level == SMB_FIND_EA_LIST) {
2694 uint32 ea_size;
2696 if (total_data < 4) {
2697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2698 return;
2701 ea_size = IVAL(pdata,0);
2702 if (ea_size != total_data) {
2703 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2704 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2709 if (!lp_ea_support(SNUM(conn))) {
2710 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2711 return;
2714 /* Pull out the list of names. */
2715 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2716 if (!ea_list) {
2717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2718 return;
2722 *ppdata = (char *)SMB_REALLOC(
2723 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2724 if(*ppdata == NULL) {
2725 reply_nterror(req, NT_STATUS_NO_MEMORY);
2726 return;
2729 pdata = *ppdata;
2730 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2732 /* Realloc the params space */
2733 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2734 if(*pparams == NULL ) {
2735 reply_nterror(req, NT_STATUS_NO_MEMORY);
2736 return;
2739 params = *pparams;
2741 /* Check that the dptr is valid */
2742 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2743 reply_nterror(req, STATUS_NO_MORE_FILES);
2744 return;
2747 directory = dptr_path(sconn, dptr_num);
2749 /* Get the wildcard mask from the dptr */
2750 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2751 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2752 reply_nterror(req, STATUS_NO_MORE_FILES);
2753 return;
2756 mask = p;
2758 /* Get the attr mask from the dptr */
2759 dirtype = dptr_attr(sconn, dptr_num);
2761 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2762 dptr_num, mask, dirtype,
2763 (long)dirptr,
2764 dptr_TellDir(dirptr)));
2766 /* Initialize per TRANS2_FIND_NEXT operation data */
2767 dptr_init_search_op(dirptr);
2769 /* We don't need to check for VOL here as this is returned by
2770 a different TRANS2 call. */
2772 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2773 directory,lp_dontdescend(SNUM(conn))));
2774 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2775 dont_descend = True;
2777 p = pdata;
2778 space_remaining = max_data_bytes;
2779 out_of_space = False;
2782 * Seek to the correct position. We no longer use the resume key but
2783 * depend on the last file name instead.
2786 if(!continue_bit && resume_name && *resume_name) {
2787 SMB_STRUCT_STAT st;
2789 long current_pos = 0;
2791 * Remember, name_to_8_3 is called by
2792 * get_lanman2_dir_entry(), so the resume name
2793 * could be mangled. Ensure we check the unmangled name.
2796 if (mangle_is_mangled(resume_name, conn->params)) {
2797 char *new_resume_name = NULL;
2798 mangle_lookup_name_from_8_3(ctx,
2799 resume_name,
2800 &new_resume_name,
2801 conn->params);
2802 if (new_resume_name) {
2803 resume_name = new_resume_name;
2808 * Fix for NT redirector problem triggered by resume key indexes
2809 * changing between directory scans. We now return a resume key of 0
2810 * and instead look for the filename to continue from (also given
2811 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2812 * findfirst/findnext (as is usual) then the directory pointer
2813 * should already be at the correct place.
2816 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2817 } /* end if resume_name && !continue_bit */
2819 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2820 bool got_exact_match = False;
2822 /* this is a heuristic to avoid seeking the dirptr except when
2823 absolutely necessary. It allows for a filename of about 40 chars */
2824 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2825 out_of_space = True;
2826 finished = False;
2827 } else {
2828 finished = !get_lanman2_dir_entry(ctx,
2829 conn,
2830 dirptr,
2831 req->flags2,
2832 mask,dirtype,info_level,
2833 requires_resume_key,dont_descend,
2834 ask_sharemode,
2835 &p,pdata,data_end,
2836 space_remaining, &out_of_space,
2837 &got_exact_match,
2838 &last_entry_off, ea_list);
2841 if (finished && out_of_space)
2842 finished = False;
2844 if (!finished && !out_of_space)
2845 numentries++;
2848 * As an optimisation if we know we aren't looking
2849 * for a wildcard name (ie. the name matches the wildcard exactly)
2850 * then we can finish on any (first) match.
2851 * This speeds up large directory searches. JRA.
2854 if(got_exact_match)
2855 finished = True;
2857 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2860 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2861 smb_fn_name(req->cmd),
2862 mask, directory, dirtype, numentries ) );
2864 /* Check if we can close the dirptr */
2865 if(close_after_request || (finished && close_if_end)) {
2866 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2867 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2870 /* Set up the return parameter block */
2871 SSVAL(params,0,numentries);
2872 SSVAL(params,2,finished);
2873 SSVAL(params,4,0); /* Never an EA error */
2874 SSVAL(params,6,last_entry_off);
2876 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2877 max_data_bytes);
2879 return;
2882 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2884 E_md4hash(lp_servicename(SNUM(conn)),objid);
2885 return objid;
2888 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2890 SMB_ASSERT(extended_info != NULL);
2892 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2893 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2894 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2895 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2896 #ifdef SAMBA_VERSION_REVISION
2897 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2898 #endif
2899 extended_info->samba_subversion = 0;
2900 #ifdef SAMBA_VERSION_RC_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2902 #else
2903 #ifdef SAMBA_VERSION_PRE_RELEASE
2904 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2905 #endif
2906 #endif
2907 #ifdef SAMBA_VERSION_VENDOR_PATCH
2908 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2909 #endif
2910 extended_info->samba_gitcommitdate = 0;
2911 #ifdef SAMBA_VERSION_COMMIT_TIME
2912 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2913 #endif
2915 memset(extended_info->samba_version_string, 0,
2916 sizeof(extended_info->samba_version_string));
2918 snprintf (extended_info->samba_version_string,
2919 sizeof(extended_info->samba_version_string),
2920 "%s", samba_version_string());
2923 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2924 TALLOC_CTX *mem_ctx,
2925 uint16_t info_level,
2926 uint16_t flags2,
2927 unsigned int max_data_bytes,
2928 char **ppdata,
2929 int *ret_data_len)
2931 char *pdata, *end_data;
2932 int data_len = 0, len;
2933 const char *vname = volume_label(SNUM(conn));
2934 int snum = SNUM(conn);
2935 char *fstype = lp_fstype(SNUM(conn));
2936 uint32 additional_flags = 0;
2937 struct smb_filename smb_fname_dot;
2938 SMB_STRUCT_STAT st;
2940 if (IS_IPC(conn)) {
2941 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2942 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2943 "info level (0x%x) on IPC$.\n",
2944 (unsigned int)info_level));
2945 return NT_STATUS_ACCESS_DENIED;
2949 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2951 ZERO_STRUCT(smb_fname_dot);
2952 smb_fname_dot.base_name = discard_const_p(char, ".");
2954 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2955 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2956 return map_nt_error_from_unix(errno);
2959 st = smb_fname_dot.st;
2961 *ppdata = (char *)SMB_REALLOC(
2962 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2963 if (*ppdata == NULL) {
2964 return NT_STATUS_NO_MEMORY;
2967 pdata = *ppdata;
2968 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2969 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2971 switch (info_level) {
2972 case SMB_INFO_ALLOCATION:
2974 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2975 data_len = 18;
2976 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2977 return map_nt_error_from_unix(errno);
2980 block_size = lp_block_size(snum);
2981 if (bsize < block_size) {
2982 uint64_t factor = block_size/bsize;
2983 bsize = block_size;
2984 dsize /= factor;
2985 dfree /= factor;
2987 if (bsize > block_size) {
2988 uint64_t factor = bsize/block_size;
2989 bsize = block_size;
2990 dsize *= factor;
2991 dfree *= factor;
2993 bytes_per_sector = 512;
2994 sectors_per_unit = bsize/bytes_per_sector;
2996 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2997 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2998 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3000 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3001 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3002 SIVAL(pdata,l1_cUnit,dsize);
3003 SIVAL(pdata,l1_cUnitAvail,dfree);
3004 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3005 break;
3008 case SMB_INFO_VOLUME:
3009 /* Return volume name */
3011 * Add volume serial number - hash of a combination of
3012 * the called hostname and the service name.
3014 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3016 * Win2k3 and previous mess this up by sending a name length
3017 * one byte short. I believe only older clients (OS/2 Win9x) use
3018 * this call so try fixing this by adding a terminating null to
3019 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3021 len = srvstr_push(
3022 pdata, flags2,
3023 pdata+l2_vol_szVolLabel, vname,
3024 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3025 STR_NOALIGN|STR_TERMINATE);
3026 SCVAL(pdata,l2_vol_cch,len);
3027 data_len = l2_vol_szVolLabel + len;
3028 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3029 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3030 len, vname));
3031 break;
3033 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3034 case SMB_FS_ATTRIBUTE_INFORMATION:
3036 additional_flags = 0;
3037 #if defined(HAVE_SYS_QUOTAS)
3038 additional_flags |= FILE_VOLUME_QUOTAS;
3039 #endif
3041 if(lp_nt_acl_support(SNUM(conn))) {
3042 additional_flags |= FILE_PERSISTENT_ACLS;
3045 /* Capabilities are filled in at connection time through STATVFS call */
3046 additional_flags |= conn->fs_capabilities;
3047 additional_flags |= lp_parm_int(conn->params->service,
3048 "share", "fake_fscaps",
3051 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3052 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3053 additional_flags); /* FS ATTRIBUTES */
3055 SIVAL(pdata,4,255); /* Max filename component length */
3056 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3057 and will think we can't do long filenames */
3058 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3059 PTR_DIFF(end_data, pdata+12),
3060 STR_UNICODE);
3061 SIVAL(pdata,8,len);
3062 data_len = 12 + len;
3063 break;
3065 case SMB_QUERY_FS_LABEL_INFO:
3066 case SMB_FS_LABEL_INFORMATION:
3067 len = srvstr_push(pdata, flags2, pdata+4, vname,
3068 PTR_DIFF(end_data, pdata+4), 0);
3069 data_len = 4 + len;
3070 SIVAL(pdata,0,len);
3071 break;
3073 case SMB_QUERY_FS_VOLUME_INFO:
3074 case SMB_FS_VOLUME_INFORMATION:
3077 * Add volume serial number - hash of a combination of
3078 * the called hostname and the service name.
3080 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3081 (str_checksum(get_local_machine_name())<<16));
3083 /* Max label len is 32 characters. */
3084 len = srvstr_push(pdata, flags2, pdata+18, vname,
3085 PTR_DIFF(end_data, pdata+18),
3086 STR_UNICODE);
3087 SIVAL(pdata,12,len);
3088 data_len = 18+len;
3090 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3091 (int)strlen(vname),vname, lp_servicename(snum)));
3092 break;
3094 case SMB_QUERY_FS_SIZE_INFO:
3095 case SMB_FS_SIZE_INFORMATION:
3097 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3098 data_len = 24;
3099 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3100 return map_nt_error_from_unix(errno);
3102 block_size = lp_block_size(snum);
3103 if (bsize < block_size) {
3104 uint64_t factor = block_size/bsize;
3105 bsize = block_size;
3106 dsize /= factor;
3107 dfree /= factor;
3109 if (bsize > block_size) {
3110 uint64_t factor = bsize/block_size;
3111 bsize = block_size;
3112 dsize *= factor;
3113 dfree *= factor;
3115 bytes_per_sector = 512;
3116 sectors_per_unit = bsize/bytes_per_sector;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3118 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3119 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3120 SBIG_UINT(pdata,0,dsize);
3121 SBIG_UINT(pdata,8,dfree);
3122 SIVAL(pdata,16,sectors_per_unit);
3123 SIVAL(pdata,20,bytes_per_sector);
3124 break;
3127 case SMB_FS_FULL_SIZE_INFORMATION:
3129 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3130 data_len = 32;
3131 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3137 bsize = block_size;
3138 dsize /= factor;
3139 dfree /= factor;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3143 bsize = block_size;
3144 dsize *= factor;
3145 dfree *= factor;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3153 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3154 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3155 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3156 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3157 break;
3160 case SMB_QUERY_FS_DEVICE_INFO:
3161 case SMB_FS_DEVICE_INFORMATION:
3163 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3165 if (!CAN_WRITE(conn)) {
3166 characteristics |= FILE_READ_ONLY_DEVICE;
3168 data_len = 8;
3169 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3170 SIVAL(pdata,4,characteristics);
3171 break;
3174 #ifdef HAVE_SYS_QUOTAS
3175 case SMB_FS_QUOTA_INFORMATION:
3177 * what we have to send --metze:
3179 * Unknown1: 24 NULL bytes
3180 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3181 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3182 * Quota Flags: 2 byte :
3183 * Unknown3: 6 NULL bytes
3185 * 48 bytes total
3187 * details for Quota Flags:
3189 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3190 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3191 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3192 * 0x0001 Enable Quotas: enable quota for this fs
3196 /* we need to fake up a fsp here,
3197 * because its not send in this call
3199 files_struct fsp;
3200 SMB_NTQUOTA_STRUCT quotas;
3202 ZERO_STRUCT(fsp);
3203 ZERO_STRUCT(quotas);
3205 fsp.conn = conn;
3206 fsp.fnum = -1;
3208 /* access check */
3209 if (get_current_uid(conn) != 0) {
3210 DEBUG(0,("set_user_quota: access_denied "
3211 "service [%s] user [%s]\n",
3212 lp_servicename(SNUM(conn)),
3213 conn->session_info->unix_info->unix_name));
3214 return NT_STATUS_ACCESS_DENIED;
3217 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3218 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3219 return map_nt_error_from_unix(errno);
3222 data_len = 48;
3224 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3225 lp_servicename(SNUM(conn))));
3227 /* Unknown1 24 NULL bytes*/
3228 SBIG_UINT(pdata,0,(uint64_t)0);
3229 SBIG_UINT(pdata,8,(uint64_t)0);
3230 SBIG_UINT(pdata,16,(uint64_t)0);
3232 /* Default Soft Quota 8 bytes */
3233 SBIG_UINT(pdata,24,quotas.softlim);
3235 /* Default Hard Quota 8 bytes */
3236 SBIG_UINT(pdata,32,quotas.hardlim);
3238 /* Quota flag 2 bytes */
3239 SSVAL(pdata,40,quotas.qflags);
3241 /* Unknown3 6 NULL bytes */
3242 SSVAL(pdata,42,0);
3243 SIVAL(pdata,44,0);
3245 break;
3247 #endif /* HAVE_SYS_QUOTAS */
3248 case SMB_FS_OBJECTID_INFORMATION:
3250 unsigned char objid[16];
3251 struct smb_extended_info extended_info;
3252 memcpy(pdata,create_volume_objectid(conn, objid),16);
3253 samba_extended_info_version (&extended_info);
3254 SIVAL(pdata,16,extended_info.samba_magic);
3255 SIVAL(pdata,20,extended_info.samba_version);
3256 SIVAL(pdata,24,extended_info.samba_subversion);
3257 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3258 memcpy(pdata+36,extended_info.samba_version_string,28);
3259 data_len = 64;
3260 break;
3264 * Query the version and capabilities of the CIFS UNIX extensions
3265 * in use.
3268 case SMB_QUERY_CIFS_UNIX_INFO:
3270 bool large_write = lp_min_receive_file_size() &&
3271 !srv_is_signing_active(conn->sconn);
3272 bool large_read = !srv_is_signing_active(conn->sconn);
3273 int encrypt_caps = 0;
3275 if (!lp_unix_extensions()) {
3276 return NT_STATUS_INVALID_LEVEL;
3279 switch (conn->encrypt_level) {
3280 case 0:
3281 encrypt_caps = 0;
3282 break;
3283 case 1:
3284 case Auto:
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3286 break;
3287 case Required:
3288 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3289 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3290 large_write = false;
3291 large_read = false;
3292 break;
3295 data_len = 12;
3296 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3297 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3299 /* We have POSIX ACLs, pathname, encryption,
3300 * large read/write, and locking capability. */
3302 SBIG_UINT(pdata,4,((uint64_t)(
3303 CIFS_UNIX_POSIX_ACLS_CAP|
3304 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3305 CIFS_UNIX_FCNTL_LOCKS_CAP|
3306 CIFS_UNIX_EXTATTR_CAP|
3307 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3308 encrypt_caps|
3309 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3310 (large_write ?
3311 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3312 break;
3315 case SMB_QUERY_POSIX_FS_INFO:
3317 int rc;
3318 vfs_statvfs_struct svfs;
3320 if (!lp_unix_extensions()) {
3321 return NT_STATUS_INVALID_LEVEL;
3324 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3326 if (!rc) {
3327 data_len = 56;
3328 SIVAL(pdata,0,svfs.OptimalTransferSize);
3329 SIVAL(pdata,4,svfs.BlockSize);
3330 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3331 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3332 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3333 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3334 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3335 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3337 #ifdef EOPNOTSUPP
3338 } else if (rc == EOPNOTSUPP) {
3339 return NT_STATUS_INVALID_LEVEL;
3340 #endif /* EOPNOTSUPP */
3341 } else {
3342 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3343 return NT_STATUS_DOS(ERRSRV, ERRerror);
3345 break;
3348 case SMB_QUERY_POSIX_WHOAMI:
3350 uint32_t flags = 0;
3351 uint32_t sid_bytes;
3352 int i;
3354 if (!lp_unix_extensions()) {
3355 return NT_STATUS_INVALID_LEVEL;
3358 if (max_data_bytes < 40) {
3359 return NT_STATUS_BUFFER_TOO_SMALL;
3362 /* We ARE guest if global_sid_Builtin_Guests is
3363 * in our list of SIDs.
3365 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3366 conn->session_info->security_token)) {
3367 flags |= SMB_WHOAMI_GUEST;
3370 /* We are NOT guest if global_sid_Authenticated_Users
3371 * is in our list of SIDs.
3373 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3374 conn->session_info->security_token)) {
3375 flags &= ~SMB_WHOAMI_GUEST;
3378 /* NOTE: 8 bytes for UID/GID, irrespective of native
3379 * platform size. This matches
3380 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3382 data_len = 4 /* flags */
3383 + 4 /* flag mask */
3384 + 8 /* uid */
3385 + 8 /* gid */
3386 + 4 /* ngroups */
3387 + 4 /* num_sids */
3388 + 4 /* SID bytes */
3389 + 4 /* pad/reserved */
3390 + (conn->session_info->unix_token->ngroups * 8)
3391 /* groups list */
3392 + (conn->session_info->security_token->num_sids *
3393 SID_MAX_SIZE)
3394 /* SID list */;
3396 SIVAL(pdata, 0, flags);
3397 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3398 SBIG_UINT(pdata, 8,
3399 (uint64_t)conn->session_info->unix_token->uid);
3400 SBIG_UINT(pdata, 16,
3401 (uint64_t)conn->session_info->unix_token->gid);
3404 if (data_len >= max_data_bytes) {
3405 /* Potential overflow, skip the GIDs and SIDs. */
3407 SIVAL(pdata, 24, 0); /* num_groups */
3408 SIVAL(pdata, 28, 0); /* num_sids */
3409 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3410 SIVAL(pdata, 36, 0); /* reserved */
3412 data_len = 40;
3413 break;
3416 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3417 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3419 /* We walk the SID list twice, but this call is fairly
3420 * infrequent, and I don't expect that it's performance
3421 * sensitive -- jpeach
3423 for (i = 0, sid_bytes = 0;
3424 i < conn->session_info->security_token->num_sids; ++i) {
3425 sid_bytes += ndr_size_dom_sid(
3426 &conn->session_info->security_token->sids[i],
3430 /* SID list byte count */
3431 SIVAL(pdata, 32, sid_bytes);
3433 /* 4 bytes pad/reserved - must be zero */
3434 SIVAL(pdata, 36, 0);
3435 data_len = 40;
3437 /* GID list */
3438 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3439 SBIG_UINT(pdata, data_len,
3440 (uint64_t)conn->session_info->unix_token->groups[i]);
3441 data_len += 8;
3444 /* SID list */
3445 for (i = 0;
3446 i < conn->session_info->security_token->num_sids; ++i) {
3447 int sid_len = ndr_size_dom_sid(
3448 &conn->session_info->security_token->sids[i],
3451 sid_linearize(pdata + data_len, sid_len,
3452 &conn->session_info->security_token->sids[i]);
3453 data_len += sid_len;
3456 break;
3459 case SMB_MAC_QUERY_FS_INFO:
3461 * Thursby MAC extension... ONLY on NTFS filesystems
3462 * once we do streams then we don't need this
3464 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3465 data_len = 88;
3466 SIVAL(pdata,84,0x100); /* Don't support mac... */
3467 break;
3469 /* drop through */
3470 default:
3471 return NT_STATUS_INVALID_LEVEL;
3474 *ret_data_len = data_len;
3475 return NT_STATUS_OK;
3478 /****************************************************************************
3479 Reply to a TRANS2_QFSINFO (query filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2qfsinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 char **pparams, int total_params,
3485 char **ppdata, int total_data,
3486 unsigned int max_data_bytes)
3488 char *params = *pparams;
3489 uint16_t info_level;
3490 int data_len = 0;
3491 NTSTATUS status;
3493 if (total_params < 2) {
3494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3495 return;
3498 info_level = SVAL(params,0);
3500 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3501 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3502 DEBUG(0,("call_trans2qfsinfo: encryption required "
3503 "and info level 0x%x sent.\n",
3504 (unsigned int)info_level));
3505 exit_server_cleanly("encryption required "
3506 "on connection");
3507 return;
3511 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3513 status = smbd_do_qfsinfo(conn, req,
3514 info_level,
3515 req->flags2,
3516 max_data_bytes,
3517 ppdata, &data_len);
3518 if (!NT_STATUS_IS_OK(status)) {
3519 reply_nterror(req, status);
3520 return;
3523 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3524 max_data_bytes);
3526 DEBUG( 4, ( "%s info_level = %d\n",
3527 smb_fn_name(req->cmd), info_level) );
3529 return;
3532 /****************************************************************************
3533 Reply to a TRANS2_SETFSINFO (set filesystem info).
3534 ****************************************************************************/
3536 static void call_trans2setfsinfo(connection_struct *conn,
3537 struct smb_request *req,
3538 char **pparams, int total_params,
3539 char **ppdata, int total_data,
3540 unsigned int max_data_bytes)
3542 struct smbd_server_connection *sconn = req->sconn;
3543 char *pdata = *ppdata;
3544 char *params = *pparams;
3545 uint16 info_level;
3547 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3549 /* */
3550 if (total_params < 4) {
3551 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3552 total_params));
3553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3554 return;
3557 info_level = SVAL(params,2);
3559 if (IS_IPC(conn)) {
3560 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3561 info_level != SMB_SET_CIFS_UNIX_INFO) {
3562 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3563 "info level (0x%x) on IPC$.\n",
3564 (unsigned int)info_level));
3565 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3566 return;
3570 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3571 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3572 DEBUG(0,("call_trans2setfsinfo: encryption required "
3573 "and info level 0x%x sent.\n",
3574 (unsigned int)info_level));
3575 exit_server_cleanly("encryption required "
3576 "on connection");
3577 return;
3581 switch(info_level) {
3582 case SMB_SET_CIFS_UNIX_INFO:
3583 if (!lp_unix_extensions()) {
3584 reply_nterror(req,
3585 NT_STATUS_INVALID_LEVEL);
3586 return;
3589 /* There should be 12 bytes of capabilities set. */
3590 if (total_data < 8) {
3591 reply_nterror(
3592 req,
3593 NT_STATUS_INVALID_PARAMETER);
3594 return;
3596 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3597 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3598 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3599 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3600 /* Just print these values for now. */
3601 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3602 "major = %u, minor = %u cap_low = 0x%x, "
3603 "cap_high = 0x%xn",
3604 (unsigned int)sconn->
3605 smb1.unix_info.client_major,
3606 (unsigned int)sconn->
3607 smb1.unix_info.client_minor,
3608 (unsigned int)sconn->
3609 smb1.unix_info.client_cap_low,
3610 (unsigned int)sconn->
3611 smb1.unix_info.client_cap_high));
3613 /* Here is where we must switch to posix pathname processing... */
3614 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3615 lp_set_posix_pathnames();
3616 mangle_change_to_posix();
3619 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3620 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3621 /* Client that knows how to do posix locks,
3622 * but not posix open/mkdir operations. Set a
3623 * default type for read/write checks. */
3625 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3628 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->sconn, 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;