docs: Fix variable list in man vfs_crossrename.
[Samba.git] / source3 / smbd / trans2.c
blob01b0130a38de3d7b06fabd01362fd3c76e67e4e5
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"
39 #include "libsmb/libsmb.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 Roundup a value to the nearest allocation roundup size boundary.
55 Only do this for Windows clients.
56 ********************************************************************/
58 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
60 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
62 /* Only roundup for Windows clients. */
63 enum remote_arch_types ra_type = get_remote_arch();
64 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
65 val = SMB_ROUNDUP(val,rval);
67 return val;
70 /********************************************************************
71 Create a 64 bit FileIndex. If the file is on the same device as
72 the root of the share, just return the 64-bit inode. If it isn't,
73 mangle as we used to do.
74 ********************************************************************/
76 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 uint64_t file_index;
79 if (conn->base_share_dev == psbuf->st_ex_dev) {
80 return (uint64_t)psbuf->st_ex_ino;
82 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
83 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
84 return file_index;
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char * const prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 SAMBA_XATTR_MARKER,
101 XATTR_NTACL_NAME,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return true;
111 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
112 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
113 return true;
115 return false;
118 /****************************************************************************
119 Get one EA value. Fill in a struct ea_struct.
120 ****************************************************************************/
122 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
123 files_struct *fsp, const char *fname,
124 const char *ea_name, struct ea_struct *pea)
126 /* Get the value of this xattr. Max size is 64k. */
127 size_t attr_size = 256;
128 char *val = NULL;
129 ssize_t sizeret;
131 again:
133 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (!val) {
135 return NT_STATUS_NO_MEMORY;
138 if (fsp && fsp->fh->fd != -1) {
139 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 } else {
141 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
144 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
145 attr_size = 65536;
146 goto again;
149 if (sizeret == -1) {
150 return map_nt_error_from_unix(errno);
153 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
154 dump_data(10, (uint8 *)val, sizeret);
156 pea->flags = 0;
157 if (strnequal(ea_name, "user.", 5)) {
158 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 } else {
160 pea->name = talloc_strdup(mem_ctx, ea_name);
162 if (pea->name == NULL) {
163 TALLOC_FREE(val);
164 return NT_STATUS_NO_MEMORY;
166 pea->value.data = (unsigned char *)val;
167 pea->value.length = (size_t)sizeret;
168 return NT_STATUS_OK;
171 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
172 files_struct *fsp, const char *fname,
173 char ***pnames, size_t *pnum_names)
175 /* Get a list of all xattrs. Max namesize is 64k. */
176 size_t ea_namelist_size = 1024;
177 char *ea_namelist = NULL;
179 char *p;
180 char **names, **tmp;
181 size_t num_names;
182 ssize_t sizeret = -1;
184 if (!lp_ea_support(SNUM(conn))) {
185 if (pnames) {
186 *pnames = NULL;
188 *pnum_names = 0;
189 return NT_STATUS_OK;
193 * TALLOC the result early to get the talloc hierarchy right.
196 names = TALLOC_ARRAY(mem_ctx, char *, 1);
197 if (names == NULL) {
198 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY;
202 while (ea_namelist_size <= 65536) {
204 ea_namelist = TALLOC_REALLOC_ARRAY(
205 names, ea_namelist, char, ea_namelist_size);
206 if (ea_namelist == NULL) {
207 DEBUG(0, ("talloc failed\n"));
208 TALLOC_FREE(names);
209 return NT_STATUS_NO_MEMORY;
212 if (fsp && fsp->fh->fd != -1) {
213 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
214 ea_namelist_size);
215 } else {
216 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 ea_namelist_size);
220 if ((sizeret == -1) && (errno == ERANGE)) {
221 ea_namelist_size *= 2;
223 else {
224 break;
228 if (sizeret == -1) {
229 TALLOC_FREE(names);
230 return map_nt_error_from_unix(errno);
233 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
234 (unsigned int)sizeret));
236 if (sizeret == 0) {
237 TALLOC_FREE(names);
238 if (pnames) {
239 *pnames = NULL;
241 *pnum_names = 0;
242 return NT_STATUS_OK;
246 * Ensure the result is 0-terminated
249 if (ea_namelist[sizeret-1] != '\0') {
250 TALLOC_FREE(names);
251 return NT_STATUS_INTERNAL_ERROR;
255 * count the names
257 num_names = 0;
259 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
260 num_names += 1;
263 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
264 if (tmp == NULL) {
265 DEBUG(0, ("talloc failed\n"));
266 TALLOC_FREE(names);
267 return NT_STATUS_NO_MEMORY;
270 names = tmp;
271 num_names = 0;
273 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
274 names[num_names++] = p;
277 if (pnames) {
278 *pnames = names;
279 } else {
280 TALLOC_FREE(names);
282 *pnum_names = num_names;
283 return NT_STATUS_OK;
286 /****************************************************************************
287 Return a linked list of the total EA's. Plus the total size
288 ****************************************************************************/
290 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
291 const char *fname, size_t *pea_total_len)
293 /* Get a list of all xattrs. Max namesize is 64k. */
294 size_t i, num_names;
295 char **names;
296 struct ea_list *ea_list_head = NULL;
297 NTSTATUS status;
299 *pea_total_len = 0;
301 if (!lp_ea_support(SNUM(conn))) {
302 return NULL;
305 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
306 &names, &num_names);
308 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
309 return NULL;
312 for (i=0; i<num_names; i++) {
313 struct ea_list *listp;
314 fstring dos_ea_name;
316 if (strnequal(names[i], "system.", 7)
317 || samba_private_attr_name(names[i]))
318 continue;
320 listp = TALLOC_P(mem_ctx, struct ea_list);
321 if (listp == NULL) {
322 return NULL;
325 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
326 fname, names[i],
327 &listp->ea))) {
328 return NULL;
331 if (listp->ea.value.length == 0) {
333 * We can never return a zero length EA.
334 * Windows reports the EA's as corrupted.
336 TALLOC_FREE(listp);
337 continue;
340 push_ascii_fstring(dos_ea_name, listp->ea.name);
342 *pea_total_len +=
343 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
345 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
346 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
347 (unsigned int)listp->ea.value.length));
349 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
353 /* Add on 4 for total length. */
354 if (*pea_total_len) {
355 *pea_total_len += 4;
358 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
359 (unsigned int)*pea_total_len));
361 return ea_list_head;
364 /****************************************************************************
365 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
366 that was filled.
367 ****************************************************************************/
369 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
370 connection_struct *conn, struct ea_list *ea_list)
372 unsigned int ret_data_size = 4;
373 char *p = pdata;
375 SMB_ASSERT(total_data_size >= 4);
377 if (!lp_ea_support(SNUM(conn))) {
378 SIVAL(pdata,4,0);
379 return 4;
382 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
383 size_t dos_namelen;
384 fstring dos_ea_name;
385 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
386 dos_namelen = strlen(dos_ea_name);
387 if (dos_namelen > 255 || dos_namelen == 0) {
388 break;
390 if (ea_list->ea.value.length > 65535) {
391 break;
393 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
394 break;
397 /* We know we have room. */
398 SCVAL(p,0,ea_list->ea.flags);
399 SCVAL(p,1,dos_namelen);
400 SSVAL(p,2,ea_list->ea.value.length);
401 fstrcpy(p+4, dos_ea_name);
402 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
404 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
405 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
408 ret_data_size = PTR_DIFF(p, pdata);
409 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
410 SIVAL(pdata,0,ret_data_size);
411 return ret_data_size;
414 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
415 char *pdata,
416 unsigned int total_data_size,
417 unsigned int *ret_data_size,
418 connection_struct *conn,
419 struct ea_list *ea_list)
421 uint8_t *p = (uint8_t *)pdata;
422 uint8_t *last_start = NULL;
423 bool store_data = (pdata != NULL);
425 *ret_data_size = 0;
427 if (!lp_ea_support(SNUM(conn))) {
428 return NT_STATUS_NO_EAS_ON_FILE;
431 for (; ea_list; ea_list = ea_list->next) {
432 size_t dos_namelen;
433 fstring dos_ea_name;
434 size_t this_size;
435 size_t pad = 0;
437 if (last_start && store_data) {
438 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
440 last_start = p;
442 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
443 dos_namelen = strlen(dos_ea_name);
444 if (dos_namelen > 255 || dos_namelen == 0) {
445 return NT_STATUS_INTERNAL_ERROR;
447 if (ea_list->ea.value.length > 65535) {
448 return NT_STATUS_INTERNAL_ERROR;
451 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
453 if (ea_list->next) {
454 pad = (4 - (this_size % 4)) % 4;
455 this_size += pad;
458 if (this_size > total_data_size) {
459 return NT_STATUS_INFO_LENGTH_MISMATCH;
462 /* We know we have room. */
463 if (store_data) {
464 SIVAL(p, 0x00, 0); /* next offset */
465 SCVAL(p, 0x04, ea_list->ea.flags);
466 SCVAL(p, 0x05, dos_namelen);
467 SSVAL(p, 0x06, ea_list->ea.value.length);
468 fstrcpy((char *)(p+0x08), dos_ea_name);
469 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
470 if (pad) {
471 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
472 '\0',
473 pad);
477 total_data_size -= this_size;
478 p += this_size;
481 *ret_data_size = PTR_DIFF(p, pdata);
482 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
483 return NT_STATUS_OK;
486 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
488 size_t total_ea_len = 0;
489 struct ea_list *ea_list = NULL;
490 TALLOC_CTX *mem_ctx = NULL;
492 if (!lp_ea_support(SNUM(conn))) {
493 return 0;
495 mem_ctx = talloc_tos();
496 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
497 if (ea_list == NULL) {
498 return 0;
500 if(conn->sconn->using_smb2) {
501 NTSTATUS status;
502 unsigned int ret_data_size;
504 * We're going to be using fill_ea_chained_buffer() to
505 * marshall EA's - this size is significantly larger
506 * than the SMB1 buffer. Re-calculate the size without
507 * marshalling.
509 status = fill_ea_chained_buffer(mem_ctx,
510 NULL,
511 65535,
512 &ret_data_size,
513 conn,
514 ea_list);
515 if (!NT_STATUS_IS_OK(status)) {
516 ret_data_size = 0;
518 total_ea_len = ret_data_size;
521 return total_ea_len;
524 /****************************************************************************
525 Ensure the EA name is case insensitive by matching any existing EA name.
526 ****************************************************************************/
528 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
530 size_t total_ea_len;
531 TALLOC_CTX *mem_ctx = talloc_tos();
532 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
534 for (; ea_list; ea_list = ea_list->next) {
535 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
536 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
537 &unix_ea_name[5], ea_list->ea.name));
538 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
539 break;
544 /****************************************************************************
545 Set or delete an extended attribute.
546 ****************************************************************************/
548 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
549 const struct smb_filename *smb_fname, struct ea_list *ea_list)
551 char *fname = NULL;
553 if (!lp_ea_support(SNUM(conn))) {
554 return NT_STATUS_EAS_NOT_SUPPORTED;
557 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
558 return NT_STATUS_ACCESS_DENIED;
561 /* For now setting EAs on streams isn't supported. */
562 fname = smb_fname->base_name;
564 for (;ea_list; ea_list = ea_list->next) {
565 int ret;
566 fstring unix_ea_name;
568 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
569 fstrcat(unix_ea_name, ea_list->ea.name);
571 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
573 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
575 if (samba_private_attr_name(unix_ea_name)) {
576 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
577 return NT_STATUS_ACCESS_DENIED;
580 if (ea_list->ea.value.length == 0) {
581 /* Remove the attribute. */
582 if (fsp && (fsp->fh->fd != -1)) {
583 DEBUG(10,("set_ea: deleting ea name %s on "
584 "file %s by file descriptor.\n",
585 unix_ea_name, fsp_str_dbg(fsp)));
586 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
587 } else {
588 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
589 unix_ea_name, fname));
590 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
592 #ifdef ENOATTR
593 /* Removing a non existent attribute always succeeds. */
594 if (ret == -1 && errno == ENOATTR) {
595 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
596 unix_ea_name));
597 ret = 0;
599 #endif
600 } else {
601 if (fsp && (fsp->fh->fd != -1)) {
602 DEBUG(10,("set_ea: setting ea name %s on file "
603 "%s by file descriptor.\n",
604 unix_ea_name, fsp_str_dbg(fsp)));
605 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
606 ea_list->ea.value.data, ea_list->ea.value.length, 0);
607 } else {
608 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
609 unix_ea_name, fname));
610 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
611 ea_list->ea.value.data, ea_list->ea.value.length, 0);
615 if (ret == -1) {
616 #ifdef ENOTSUP
617 if (errno == ENOTSUP) {
618 return NT_STATUS_EAS_NOT_SUPPORTED;
620 #endif
621 return map_nt_error_from_unix(errno);
625 return NT_STATUS_OK;
627 /****************************************************************************
628 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
629 ****************************************************************************/
631 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
633 struct ea_list *ea_list_head = NULL;
634 size_t converted_size, offset = 0;
636 while (offset + 2 < data_size) {
637 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
638 unsigned int namelen = CVAL(pdata,offset);
640 offset++; /* Go past the namelen byte. */
642 /* integer wrap paranioa. */
643 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
644 (offset > data_size) || (namelen > data_size) ||
645 (offset + namelen >= data_size)) {
646 break;
648 /* Ensure the name is null terminated. */
649 if (pdata[offset + namelen] != '\0') {
650 return NULL;
652 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
653 &converted_size)) {
654 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
655 "failed: %s", strerror(errno)));
657 if (!eal->ea.name) {
658 return NULL;
661 offset += (namelen + 1); /* Go past the name + terminating zero. */
662 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
663 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
666 return ea_list_head;
669 /****************************************************************************
670 Read one EA list entry from the buffer.
671 ****************************************************************************/
673 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
675 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
676 uint16 val_len;
677 unsigned int namelen;
678 size_t converted_size;
680 if (!eal) {
681 return NULL;
684 if (data_size < 6) {
685 return NULL;
688 eal->ea.flags = CVAL(pdata,0);
689 namelen = CVAL(pdata,1);
690 val_len = SVAL(pdata,2);
692 if (4 + namelen + 1 + val_len > data_size) {
693 return NULL;
696 /* Ensure the name is null terminated. */
697 if (pdata[namelen + 4] != '\0') {
698 return NULL;
700 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
701 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
702 strerror(errno)));
704 if (!eal->ea.name) {
705 return NULL;
708 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
709 if (!eal->ea.value.data) {
710 return NULL;
713 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
715 /* Ensure we're null terminated just in case we print the value. */
716 eal->ea.value.data[val_len] = '\0';
717 /* But don't count the null. */
718 eal->ea.value.length--;
720 if (pbytes_used) {
721 *pbytes_used = 4 + namelen + 1 + val_len;
724 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
725 dump_data(10, eal->ea.value.data, eal->ea.value.length);
727 return eal;
730 /****************************************************************************
731 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
732 ****************************************************************************/
734 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
736 struct ea_list *ea_list_head = NULL;
737 size_t offset = 0;
738 size_t bytes_used = 0;
740 while (offset < data_size) {
741 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
743 if (!eal) {
744 return NULL;
747 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
748 offset += bytes_used;
751 return ea_list_head;
754 /****************************************************************************
755 Count the total EA size needed.
756 ****************************************************************************/
758 static size_t ea_list_size(struct ea_list *ealist)
760 fstring dos_ea_name;
761 struct ea_list *listp;
762 size_t ret = 0;
764 for (listp = ealist; listp; listp = listp->next) {
765 push_ascii_fstring(dos_ea_name, listp->ea.name);
766 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
768 /* Add on 4 for total length. */
769 if (ret) {
770 ret += 4;
773 return ret;
776 /****************************************************************************
777 Return a union of EA's from a file list and a list of names.
778 The TALLOC context for the two lists *MUST* be identical as we steal
779 memory from one list to add to another. JRA.
780 ****************************************************************************/
782 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
784 struct ea_list *nlistp, *flistp;
786 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
787 for (flistp = file_list; flistp; flistp = flistp->next) {
788 if (strequal(nlistp->ea.name, flistp->ea.name)) {
789 break;
793 if (flistp) {
794 /* Copy the data from this entry. */
795 nlistp->ea.flags = flistp->ea.flags;
796 nlistp->ea.value = flistp->ea.value;
797 } else {
798 /* Null entry. */
799 nlistp->ea.flags = 0;
800 ZERO_STRUCT(nlistp->ea.value);
804 *total_ea_len = ea_list_size(name_list);
805 return name_list;
808 /****************************************************************************
809 Send the required number of replies back.
810 We assume all fields other than the data fields are
811 set correctly for the type of call.
812 HACK ! Always assumes smb_setup field is zero.
813 ****************************************************************************/
815 void send_trans2_replies(connection_struct *conn,
816 struct smb_request *req,
817 const char *params,
818 int paramsize,
819 const char *pdata,
820 int datasize,
821 int max_data_bytes)
823 /* As we are using a protocol > LANMAN1 then the max_send
824 variable must have been set in the sessetupX call.
825 This takes precedence over the max_xmit field in the
826 global struct. These different max_xmit variables should
827 be merged as this is now too confusing */
829 int data_to_send = datasize;
830 int params_to_send = paramsize;
831 int useable_space;
832 const char *pp = params;
833 const char *pd = pdata;
834 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
835 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
836 int data_alignment_offset = 0;
837 bool overflow = False;
838 struct smbd_server_connection *sconn = req->sconn;
839 int max_send = sconn->smb1.sessions.max_send;
841 /* Modify the data_to_send and datasize and set the error if
842 we're trying to send more than max_data_bytes. We still send
843 the part of the packet(s) that fit. Strange, but needed
844 for OS/2. */
846 if (max_data_bytes > 0 && datasize > max_data_bytes) {
847 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
848 max_data_bytes, datasize ));
849 datasize = data_to_send = max_data_bytes;
850 overflow = True;
853 /* If there genuinely are no parameters or data to send just send the empty packet */
855 if(params_to_send == 0 && data_to_send == 0) {
856 reply_outbuf(req, 10, 0);
857 show_msg((char *)req->outbuf);
858 if (!srv_send_smb(sconn,
859 (char *)req->outbuf,
860 true, req->seqnum+1,
861 IS_CONN_ENCRYPTED(conn),
862 &req->pcd)) {
863 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
865 TALLOC_FREE(req->outbuf);
866 return;
869 /* When sending params and data ensure that both are nicely aligned */
870 /* Only do this alignment when there is also data to send - else
871 can cause NT redirector problems. */
873 if (((params_to_send % 4) != 0) && (data_to_send != 0))
874 data_alignment_offset = 4 - (params_to_send % 4);
876 /* Space is bufsize minus Netbios over TCP header minus SMB header */
877 /* The alignment_offset is to align the param bytes on an even byte
878 boundary. NT 4.0 Beta needs this to work correctly. */
880 useable_space = max_send - (smb_size
881 + 2 * 10 /* wct */
882 + alignment_offset
883 + data_alignment_offset);
885 if (useable_space < 0) {
886 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
887 "= %d!!!", useable_space));
888 exit_server_cleanly("send_trans2_replies: Not enough space");
891 while (params_to_send || data_to_send) {
892 /* Calculate whether we will totally or partially fill this packet */
894 total_sent_thistime = params_to_send + data_to_send;
896 /* We can never send more than useable_space */
898 * Note that 'useable_space' does not include the alignment offsets,
899 * but we must include the alignment offsets in the calculation of
900 * the length of the data we send over the wire, as the alignment offsets
901 * are sent here. Fix from Marc_Jacobsen@hp.com.
904 total_sent_thistime = MIN(total_sent_thistime, useable_space);
906 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
907 + data_alignment_offset);
909 /* Set total params and data to be sent */
910 SSVAL(req->outbuf,smb_tprcnt,paramsize);
911 SSVAL(req->outbuf,smb_tdrcnt,datasize);
913 /* Calculate how many parameters and data we can fit into
914 * this packet. Parameters get precedence
917 params_sent_thistime = MIN(params_to_send,useable_space);
918 data_sent_thistime = useable_space - params_sent_thistime;
919 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
921 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
923 /* smb_proff is the offset from the start of the SMB header to the
924 parameter bytes, however the first 4 bytes of outbuf are
925 the Netbios over TCP header. Thus use smb_base() to subtract
926 them from the calculation */
928 SSVAL(req->outbuf,smb_proff,
929 ((smb_buf(req->outbuf)+alignment_offset)
930 - smb_base(req->outbuf)));
932 if(params_sent_thistime == 0)
933 SSVAL(req->outbuf,smb_prdisp,0);
934 else
935 /* Absolute displacement of param bytes sent in this packet */
936 SSVAL(req->outbuf,smb_prdisp,pp - params);
938 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
939 if(data_sent_thistime == 0) {
940 SSVAL(req->outbuf,smb_droff,0);
941 SSVAL(req->outbuf,smb_drdisp, 0);
942 } else {
943 /* The offset of the data bytes is the offset of the
944 parameter bytes plus the number of parameters being sent this time */
945 SSVAL(req->outbuf, smb_droff,
946 ((smb_buf(req->outbuf)+alignment_offset)
947 - smb_base(req->outbuf))
948 + params_sent_thistime + data_alignment_offset);
949 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
952 /* Initialize the padding for alignment */
954 if (alignment_offset != 0) {
955 memset(smb_buf(req->outbuf), 0, alignment_offset);
958 /* Copy the param bytes into the packet */
960 if(params_sent_thistime) {
961 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
962 params_sent_thistime);
965 /* Copy in the data bytes */
966 if(data_sent_thistime) {
967 if (data_alignment_offset != 0) {
968 memset((smb_buf(req->outbuf)+alignment_offset+
969 params_sent_thistime), 0,
970 data_alignment_offset);
972 memcpy(smb_buf(req->outbuf)+alignment_offset
973 +params_sent_thistime+data_alignment_offset,
974 pd,data_sent_thistime);
977 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
978 params_sent_thistime, data_sent_thistime, useable_space));
979 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
980 params_to_send, data_to_send, paramsize, datasize));
982 if (overflow) {
983 error_packet_set((char *)req->outbuf,
984 ERRDOS,ERRbufferoverflow,
985 STATUS_BUFFER_OVERFLOW,
986 __LINE__,__FILE__);
989 /* Send the packet */
990 show_msg((char *)req->outbuf);
991 if (!srv_send_smb(sconn,
992 (char *)req->outbuf,
993 true, req->seqnum+1,
994 IS_CONN_ENCRYPTED(conn),
995 &req->pcd))
996 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
998 TALLOC_FREE(req->outbuf);
1000 pp += params_sent_thistime;
1001 pd += data_sent_thistime;
1003 params_to_send -= params_sent_thistime;
1004 data_to_send -= data_sent_thistime;
1006 /* Sanity check */
1007 if(params_to_send < 0 || data_to_send < 0) {
1008 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1009 params_to_send, data_to_send));
1010 return;
1014 return;
1017 /****************************************************************************
1018 Reply to a TRANSACT2_OPEN.
1019 ****************************************************************************/
1021 static void call_trans2open(connection_struct *conn,
1022 struct smb_request *req,
1023 char **pparams, int total_params,
1024 char **ppdata, int total_data,
1025 unsigned int max_data_bytes)
1027 struct smb_filename *smb_fname = NULL;
1028 char *params = *pparams;
1029 char *pdata = *ppdata;
1030 int deny_mode;
1031 int32 open_attr;
1032 bool oplock_request;
1033 #if 0
1034 bool return_additional_info;
1035 int16 open_sattr;
1036 time_t open_time;
1037 #endif
1038 int open_ofun;
1039 uint32 open_size;
1040 char *pname;
1041 char *fname = NULL;
1042 SMB_OFF_T size=0;
1043 int fattr=0,mtime=0;
1044 SMB_INO_T inode = 0;
1045 int smb_action = 0;
1046 files_struct *fsp;
1047 struct ea_list *ea_list = NULL;
1048 uint16 flags = 0;
1049 NTSTATUS status;
1050 uint32 access_mask;
1051 uint32 share_mode;
1052 uint32 create_disposition;
1053 uint32 create_options = 0;
1054 uint32_t private_flags = 0;
1055 TALLOC_CTX *ctx = talloc_tos();
1058 * Ensure we have enough parameters to perform the operation.
1061 if (total_params < 29) {
1062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1063 goto out;
1066 flags = SVAL(params, 0);
1067 deny_mode = SVAL(params, 2);
1068 open_attr = SVAL(params,6);
1069 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1070 if (oplock_request) {
1071 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1074 #if 0
1075 return_additional_info = BITSETW(params,0);
1076 open_sattr = SVAL(params, 4);
1077 open_time = make_unix_date3(params+8);
1078 #endif
1079 open_ofun = SVAL(params,12);
1080 open_size = IVAL(params,14);
1081 pname = &params[28];
1083 if (IS_IPC(conn)) {
1084 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1085 goto out;
1088 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1089 total_params - 28, STR_TERMINATE,
1090 &status);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 reply_nterror(req, status);
1093 goto out;
1096 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1097 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1098 (unsigned int)open_ofun, open_size));
1100 status = filename_convert(ctx,
1101 conn,
1102 req->flags2 & FLAGS2_DFS_PATHNAMES,
1103 fname,
1105 NULL,
1106 &smb_fname);
1107 if (!NT_STATUS_IS_OK(status)) {
1108 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1109 reply_botherror(req,
1110 NT_STATUS_PATH_NOT_COVERED,
1111 ERRSRV, ERRbadpath);
1112 goto out;
1114 reply_nterror(req, status);
1115 goto out;
1118 if (open_ofun == 0) {
1119 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1120 goto out;
1123 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1124 open_ofun,
1125 &access_mask, &share_mode,
1126 &create_disposition,
1127 &create_options,
1128 &private_flags)) {
1129 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1130 goto out;
1133 /* Any data in this call is an EA list. */
1134 if (total_data && (total_data != 4)) {
1135 if (total_data < 10) {
1136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1137 goto out;
1140 if (IVAL(pdata,0) > total_data) {
1141 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1142 IVAL(pdata,0), (unsigned int)total_data));
1143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1144 goto out;
1147 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1148 total_data - 4);
1149 if (!ea_list) {
1150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1151 goto out;
1154 if (!lp_ea_support(SNUM(conn))) {
1155 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1156 goto out;
1160 status = SMB_VFS_CREATE_FILE(
1161 conn, /* conn */
1162 req, /* req */
1163 0, /* root_dir_fid */
1164 smb_fname, /* fname */
1165 access_mask, /* access_mask */
1166 share_mode, /* share_access */
1167 create_disposition, /* create_disposition*/
1168 create_options, /* create_options */
1169 open_attr, /* file_attributes */
1170 oplock_request, /* oplock_request */
1171 open_size, /* allocation_size */
1172 private_flags,
1173 NULL, /* sd */
1174 ea_list, /* ea_list */
1175 &fsp, /* result */
1176 &smb_action); /* psbuf */
1178 if (!NT_STATUS_IS_OK(status)) {
1179 if (open_was_deferred(req->mid)) {
1180 /* We have re-scheduled this call. */
1181 goto out;
1183 reply_openerror(req, status);
1184 goto out;
1187 size = get_file_size_stat(&smb_fname->st);
1188 fattr = dos_mode(conn, smb_fname);
1189 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1190 inode = smb_fname->st.st_ex_ino;
1191 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1192 close_file(req, fsp, ERROR_CLOSE);
1193 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1194 goto out;
1197 /* Realloc the size of parameters and data we will return */
1198 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1199 if(*pparams == NULL ) {
1200 reply_nterror(req, NT_STATUS_NO_MEMORY);
1201 goto out;
1203 params = *pparams;
1205 SSVAL(params,0,fsp->fnum);
1206 SSVAL(params,2,fattr);
1207 srv_put_dos_date2(params,4, mtime);
1208 SIVAL(params,8, (uint32)size);
1209 SSVAL(params,12,deny_mode);
1210 SSVAL(params,14,0); /* open_type - file or directory. */
1211 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1213 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1214 smb_action |= EXTENDED_OPLOCK_GRANTED;
1217 SSVAL(params,18,smb_action);
1220 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1222 SIVAL(params,20,inode);
1223 SSVAL(params,24,0); /* Padding. */
1224 if (flags & 8) {
1225 uint32 ea_size = estimate_ea_size(conn, fsp,
1226 fsp->fsp_name->base_name);
1227 SIVAL(params, 26, ea_size);
1228 } else {
1229 SIVAL(params, 26, 0);
1232 /* Send the required number of replies */
1233 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1234 out:
1235 TALLOC_FREE(smb_fname);
1238 /*********************************************************
1239 Routine to check if a given string matches exactly.
1240 as a special case a mask of "." does NOT match. That
1241 is required for correct wildcard semantics
1242 Case can be significant or not.
1243 **********************************************************/
1245 static bool exact_match(bool has_wild,
1246 bool case_sensitive,
1247 const char *str,
1248 const char *mask)
1250 if (mask[0] == '.' && mask[1] == 0) {
1251 return false;
1254 if (has_wild) {
1255 return false;
1258 if (case_sensitive) {
1259 return strcmp(str,mask)==0;
1260 } else {
1261 return StrCaseCmp(str,mask) == 0;
1265 /****************************************************************************
1266 Return the filetype for UNIX extensions.
1267 ****************************************************************************/
1269 static uint32 unix_filetype(mode_t mode)
1271 if(S_ISREG(mode))
1272 return UNIX_TYPE_FILE;
1273 else if(S_ISDIR(mode))
1274 return UNIX_TYPE_DIR;
1275 #ifdef S_ISLNK
1276 else if(S_ISLNK(mode))
1277 return UNIX_TYPE_SYMLINK;
1278 #endif
1279 #ifdef S_ISCHR
1280 else if(S_ISCHR(mode))
1281 return UNIX_TYPE_CHARDEV;
1282 #endif
1283 #ifdef S_ISBLK
1284 else if(S_ISBLK(mode))
1285 return UNIX_TYPE_BLKDEV;
1286 #endif
1287 #ifdef S_ISFIFO
1288 else if(S_ISFIFO(mode))
1289 return UNIX_TYPE_FIFO;
1290 #endif
1291 #ifdef S_ISSOCK
1292 else if(S_ISSOCK(mode))
1293 return UNIX_TYPE_SOCKET;
1294 #endif
1296 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1297 return UNIX_TYPE_UNKNOWN;
1300 /****************************************************************************
1301 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1302 ****************************************************************************/
1304 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1306 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1307 const SMB_STRUCT_STAT *psbuf,
1308 uint32 perms,
1309 enum perm_type ptype,
1310 mode_t *ret_perms)
1312 mode_t ret = 0;
1314 if (perms == SMB_MODE_NO_CHANGE) {
1315 if (!VALID_STAT(*psbuf)) {
1316 return NT_STATUS_INVALID_PARAMETER;
1317 } else {
1318 *ret_perms = psbuf->st_ex_mode;
1319 return NT_STATUS_OK;
1323 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1324 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1325 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1326 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1327 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1328 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1329 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1330 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1331 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1332 #ifdef S_ISVTX
1333 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1334 #endif
1335 #ifdef S_ISGID
1336 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1337 #endif
1338 #ifdef S_ISUID
1339 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1340 #endif
1342 switch (ptype) {
1343 case PERM_NEW_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_create_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_create_mode(SNUM(conn));
1348 break;
1349 case PERM_NEW_DIR:
1350 ret &= lp_dir_mask(SNUM(conn));
1351 /* Add in force bits */
1352 ret |= lp_force_dir_mode(SNUM(conn));
1353 break;
1354 case PERM_EXISTING_FILE:
1355 /* Apply mode mask */
1356 ret &= lp_security_mask(SNUM(conn));
1357 /* Add in force bits */
1358 ret |= lp_force_security_mode(SNUM(conn));
1359 break;
1360 case PERM_EXISTING_DIR:
1361 /* Apply mode mask */
1362 ret &= lp_dir_security_mask(SNUM(conn));
1363 /* Add in force bits */
1364 ret |= lp_force_dir_security_mode(SNUM(conn));
1365 break;
1368 *ret_perms = ret;
1369 return NT_STATUS_OK;
1372 /****************************************************************************
1373 Needed to show the msdfs symlinks as directories. Modifies psbuf
1374 to be a directory if it's a msdfs link.
1375 ****************************************************************************/
1377 static bool check_msdfs_link(connection_struct *conn,
1378 const char *pathname,
1379 SMB_STRUCT_STAT *psbuf)
1381 int saved_errno = errno;
1382 if(lp_host_msdfs() &&
1383 lp_msdfs_root(SNUM(conn)) &&
1384 is_msdfs_link(conn, pathname, psbuf)) {
1386 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1387 "as a directory\n",
1388 pathname));
1389 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1390 errno = saved_errno;
1391 return true;
1393 errno = saved_errno;
1394 return false;
1398 /****************************************************************************
1399 Get a level dependent lanman2 dir entry.
1400 ****************************************************************************/
1402 struct smbd_dirptr_lanman2_state {
1403 connection_struct *conn;
1404 uint32_t info_level;
1405 bool check_mangled_names;
1406 bool has_wild;
1407 bool got_exact_match;
1410 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1411 void *private_data,
1412 const char *dname,
1413 const char *mask,
1414 char **_fname)
1416 struct smbd_dirptr_lanman2_state *state =
1417 (struct smbd_dirptr_lanman2_state *)private_data;
1418 bool ok;
1419 char mangled_name[13]; /* mangled 8.3 name. */
1420 bool got_match;
1421 const char *fname;
1423 /* Mangle fname if it's an illegal name. */
1424 if (mangle_must_mangle(dname, state->conn->params)) {
1425 ok = name_to_8_3(dname, mangled_name,
1426 true, state->conn->params);
1427 if (!ok) {
1428 return false;
1430 fname = mangled_name;
1431 } else {
1432 fname = dname;
1435 got_match = exact_match(state->has_wild,
1436 state->conn->case_sensitive,
1437 fname, mask);
1438 state->got_exact_match = got_match;
1439 if (!got_match) {
1440 got_match = mask_match(fname, mask,
1441 state->conn->case_sensitive);
1444 if(!got_match && state->check_mangled_names &&
1445 !mangle_is_8_3(fname, false, state->conn->params)) {
1447 * It turns out that NT matches wildcards against
1448 * both long *and* short names. This may explain some
1449 * of the wildcard wierdness from old DOS clients
1450 * that some people have been seeing.... JRA.
1452 /* Force the mangling into 8.3. */
1453 ok = name_to_8_3(fname, mangled_name,
1454 false, state->conn->params);
1455 if (!ok) {
1456 return false;
1459 got_match = exact_match(state->has_wild,
1460 state->conn->case_sensitive,
1461 mangled_name, mask);
1462 state->got_exact_match = got_match;
1463 if (!got_match) {
1464 got_match = mask_match(mangled_name, mask,
1465 state->conn->case_sensitive);
1469 if (!got_match) {
1470 return false;
1473 *_fname = talloc_strdup(ctx, fname);
1474 if (*_fname == NULL) {
1475 return false;
1478 return true;
1481 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1482 void *private_data,
1483 struct smb_filename *smb_fname,
1484 uint32_t *_mode)
1486 struct smbd_dirptr_lanman2_state *state =
1487 (struct smbd_dirptr_lanman2_state *)private_data;
1488 bool ms_dfs_link = false;
1489 uint32_t mode = 0;
1491 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1492 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1493 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1494 "Couldn't lstat [%s] (%s)\n",
1495 smb_fname_str_dbg(smb_fname),
1496 strerror(errno)));
1497 return false;
1499 } else if (!VALID_STAT(smb_fname->st) &&
1500 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1501 /* Needed to show the msdfs symlinks as
1502 * directories */
1504 ms_dfs_link = check_msdfs_link(state->conn,
1505 smb_fname->base_name,
1506 &smb_fname->st);
1507 if (!ms_dfs_link) {
1508 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1509 "Couldn't stat [%s] (%s)\n",
1510 smb_fname_str_dbg(smb_fname),
1511 strerror(errno)));
1512 return false;
1516 if (ms_dfs_link) {
1517 mode = dos_mode_msdfs(state->conn, smb_fname);
1518 } else {
1519 mode = dos_mode(state->conn, smb_fname);
1522 *_mode = mode;
1523 return true;
1526 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1527 connection_struct *conn,
1528 uint16_t flags2,
1529 uint32_t info_level,
1530 struct ea_list *name_list,
1531 bool check_mangled_names,
1532 bool requires_resume_key,
1533 uint32_t mode,
1534 const char *fname,
1535 const struct smb_filename *smb_fname,
1536 int space_remaining,
1537 uint8_t align,
1538 bool do_pad,
1539 char *base_data,
1540 char **ppdata,
1541 char *end_data,
1542 bool *out_of_space,
1543 uint64_t *last_entry_off)
1545 char *p, *q, *pdata = *ppdata;
1546 uint32_t reskey=0;
1547 uint64_t file_size = 0;
1548 uint64_t allocation_size = 0;
1549 uint64_t file_index = 0;
1550 uint32_t len;
1551 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1552 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1553 time_t c_date = (time_t)0;
1554 char *nameptr;
1555 char *last_entry_ptr;
1556 bool was_8_3;
1557 int off;
1558 int pad = 0;
1560 *out_of_space = false;
1562 ZERO_STRUCT(mdate_ts);
1563 ZERO_STRUCT(adate_ts);
1564 ZERO_STRUCT(create_date_ts);
1565 ZERO_STRUCT(cdate_ts);
1567 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1568 file_size = get_file_size_stat(&smb_fname->st);
1570 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1572 file_index = get_FileIndex(conn, &smb_fname->st);
1574 mdate_ts = smb_fname->st.st_ex_mtime;
1575 adate_ts = smb_fname->st.st_ex_atime;
1576 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1577 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1579 if (lp_dos_filetime_resolution(SNUM(conn))) {
1580 dos_filetime_timespec(&create_date_ts);
1581 dos_filetime_timespec(&mdate_ts);
1582 dos_filetime_timespec(&adate_ts);
1583 dos_filetime_timespec(&cdate_ts);
1586 create_date = convert_timespec_to_time_t(create_date_ts);
1587 mdate = convert_timespec_to_time_t(mdate_ts);
1588 adate = convert_timespec_to_time_t(adate_ts);
1589 c_date = convert_timespec_to_time_t(cdate_ts);
1591 /* align the record */
1592 SMB_ASSERT(align >= 1);
1594 off = (int)PTR_DIFF(pdata, base_data);
1595 pad = (off + (align-1)) & ~(align-1);
1596 pad -= off;
1598 if (pad && pad > space_remaining) {
1599 *out_of_space = true;
1600 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1601 "for padding (wanted %u, had %d)\n",
1602 (unsigned int)pad,
1603 space_remaining ));
1604 return false; /* Not finished - just out of space */
1607 off += pad;
1608 /* initialize padding to 0 */
1609 if (pad) {
1610 memset(pdata, 0, pad);
1612 space_remaining -= pad;
1614 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1615 space_remaining ));
1617 pdata += pad;
1618 p = pdata;
1619 last_entry_ptr = p;
1621 pad = 0;
1622 off = 0;
1624 switch (info_level) {
1625 case SMB_FIND_INFO_STANDARD:
1626 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1627 if(requires_resume_key) {
1628 SIVAL(p,0,reskey);
1629 p += 4;
1631 srv_put_dos_date2(p,0,create_date);
1632 srv_put_dos_date2(p,4,adate);
1633 srv_put_dos_date2(p,8,mdate);
1634 SIVAL(p,12,(uint32)file_size);
1635 SIVAL(p,16,(uint32)allocation_size);
1636 SSVAL(p,20,mode);
1637 p += 23;
1638 nameptr = p;
1639 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1640 p += ucs2_align(base_data, p, 0);
1642 len = srvstr_push(base_data, flags2, p,
1643 fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1646 if (len > 2) {
1647 SCVAL(nameptr, -1, len - 2);
1648 } else {
1649 SCVAL(nameptr, -1, 0);
1651 } else {
1652 if (len > 1) {
1653 SCVAL(nameptr, -1, len - 1);
1654 } else {
1655 SCVAL(nameptr, -1, 0);
1658 p += len;
1659 break;
1661 case SMB_FIND_EA_SIZE:
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1663 if (requires_resume_key) {
1664 SIVAL(p,0,reskey);
1665 p += 4;
1667 srv_put_dos_date2(p,0,create_date);
1668 srv_put_dos_date2(p,4,adate);
1669 srv_put_dos_date2(p,8,mdate);
1670 SIVAL(p,12,(uint32)file_size);
1671 SIVAL(p,16,(uint32)allocation_size);
1672 SSVAL(p,20,mode);
1674 unsigned int ea_size = estimate_ea_size(conn, NULL,
1675 smb_fname->base_name);
1676 SIVAL(p,22,ea_size); /* Extended attributes */
1678 p += 27;
1679 nameptr = p - 1;
1680 len = srvstr_push(base_data, flags2,
1681 p, fname, PTR_DIFF(end_data, p),
1682 STR_TERMINATE | STR_NOALIGN);
1683 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1684 if (len > 2) {
1685 len -= 2;
1686 } else {
1687 len = 0;
1689 } else {
1690 if (len > 1) {
1691 len -= 1;
1692 } else {
1693 len = 0;
1696 SCVAL(nameptr,0,len);
1697 p += len;
1698 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1699 break;
1701 case SMB_FIND_EA_LIST:
1703 struct ea_list *file_list = NULL;
1704 size_t ea_len = 0;
1706 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1707 if (!name_list) {
1708 return false;
1710 if (requires_resume_key) {
1711 SIVAL(p,0,reskey);
1712 p += 4;
1714 srv_put_dos_date2(p,0,create_date);
1715 srv_put_dos_date2(p,4,adate);
1716 srv_put_dos_date2(p,8,mdate);
1717 SIVAL(p,12,(uint32)file_size);
1718 SIVAL(p,16,(uint32)allocation_size);
1719 SSVAL(p,20,mode);
1720 p += 22; /* p now points to the EA area. */
1722 file_list = get_ea_list_from_file(ctx, conn, NULL,
1723 smb_fname->base_name,
1724 &ea_len);
1725 name_list = ea_list_union(name_list, file_list, &ea_len);
1727 /* We need to determine if this entry will fit in the space available. */
1728 /* Max string size is 255 bytes. */
1729 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1730 *out_of_space = true;
1731 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1732 "(wanted %u, had %d)\n",
1733 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1734 space_remaining ));
1735 return False; /* Not finished - just out of space */
1738 /* Push the ea_data followed by the name. */
1739 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1740 nameptr = p;
1741 len = srvstr_push(base_data, flags2,
1742 p + 1, fname, PTR_DIFF(end_data, p+1),
1743 STR_TERMINATE | STR_NOALIGN);
1744 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1745 if (len > 2) {
1746 len -= 2;
1747 } else {
1748 len = 0;
1750 } else {
1751 if (len > 1) {
1752 len -= 1;
1753 } else {
1754 len = 0;
1757 SCVAL(nameptr,0,len);
1758 p += len + 1;
1759 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1760 break;
1763 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1764 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1765 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1766 p += 4;
1767 SIVAL(p,0,reskey); p += 4;
1768 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1769 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1770 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1771 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1772 SOFF_T(p,0,file_size); p += 8;
1773 SOFF_T(p,0,allocation_size); p += 8;
1774 SIVAL(p,0,mode); p += 4;
1775 q = p; p += 4; /* q is placeholder for name length. */
1777 unsigned int ea_size = estimate_ea_size(conn, NULL,
1778 smb_fname->base_name);
1779 SIVAL(p,0,ea_size); /* Extended attributes */
1780 p += 4;
1782 /* Clear the short name buffer. This is
1783 * IMPORTANT as not doing so will trigger
1784 * a Win2k client bug. JRA.
1786 if (!was_8_3 && check_mangled_names) {
1787 char mangled_name[13]; /* mangled 8.3 name. */
1788 if (!name_to_8_3(fname,mangled_name,True,
1789 conn->params)) {
1790 /* Error - mangle failed ! */
1791 memset(mangled_name,'\0',12);
1793 mangled_name[12] = 0;
1794 len = srvstr_push(base_data, flags2,
1795 p+2, mangled_name, 24,
1796 STR_UPPER|STR_UNICODE);
1797 if (len < 24) {
1798 memset(p + 2 + len,'\0',24 - len);
1800 SSVAL(p, 0, len);
1801 } else {
1802 memset(p,'\0',26);
1804 p += 2 + 24;
1805 len = srvstr_push(base_data, flags2, p,
1806 fname, PTR_DIFF(end_data, p),
1807 STR_TERMINATE_ASCII);
1808 SIVAL(q,0,len);
1809 p += len;
1811 len = PTR_DIFF(p, pdata);
1812 pad = (len + (align-1)) & ~(align-1);
1814 * offset to the next entry, the caller
1815 * will overwrite it for the last entry
1816 * that's why we always include the padding
1818 SIVAL(pdata,0,pad);
1820 * set padding to zero
1822 if (do_pad) {
1823 memset(p, 0, pad - len);
1824 p = pdata + pad;
1825 } else {
1826 p = pdata + len;
1828 break;
1830 case SMB_FIND_FILE_DIRECTORY_INFO:
1831 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1832 p += 4;
1833 SIVAL(p,0,reskey); p += 4;
1834 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1836 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1837 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1838 SOFF_T(p,0,file_size); p += 8;
1839 SOFF_T(p,0,allocation_size); p += 8;
1840 SIVAL(p,0,mode); p += 4;
1841 len = srvstr_push(base_data, flags2,
1842 p + 4, fname, PTR_DIFF(end_data, p+4),
1843 STR_TERMINATE_ASCII);
1844 SIVAL(p,0,len);
1845 p += 4 + len;
1847 len = PTR_DIFF(p, pdata);
1848 pad = (len + (align-1)) & ~(align-1);
1850 * offset to the next entry, the caller
1851 * will overwrite it for the last entry
1852 * that's why we always include the padding
1854 SIVAL(pdata,0,pad);
1856 * set padding to zero
1858 if (do_pad) {
1859 memset(p, 0, pad - len);
1860 p = pdata + pad;
1861 } else {
1862 p = pdata + len;
1864 break;
1866 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1867 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1868 p += 4;
1869 SIVAL(p,0,reskey); p += 4;
1870 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1871 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1872 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1874 SOFF_T(p,0,file_size); p += 8;
1875 SOFF_T(p,0,allocation_size); p += 8;
1876 SIVAL(p,0,mode); p += 4;
1877 q = p; p += 4; /* q is placeholder for name length. */
1879 unsigned int ea_size = estimate_ea_size(conn, NULL,
1880 smb_fname->base_name);
1881 SIVAL(p,0,ea_size); /* Extended attributes */
1882 p +=4;
1884 len = srvstr_push(base_data, flags2, p,
1885 fname, PTR_DIFF(end_data, p),
1886 STR_TERMINATE_ASCII);
1887 SIVAL(q, 0, len);
1888 p += len;
1890 len = PTR_DIFF(p, pdata);
1891 pad = (len + (align-1)) & ~(align-1);
1893 * offset to the next entry, the caller
1894 * will overwrite it for the last entry
1895 * that's why we always include the padding
1897 SIVAL(pdata,0,pad);
1899 * set padding to zero
1901 if (do_pad) {
1902 memset(p, 0, pad - len);
1903 p = pdata + pad;
1904 } else {
1905 p = pdata + len;
1907 break;
1909 case SMB_FIND_FILE_NAMES_INFO:
1910 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1911 p += 4;
1912 SIVAL(p,0,reskey); p += 4;
1913 p += 4;
1914 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1915 acl on a dir (tridge) */
1916 len = srvstr_push(base_data, flags2, p,
1917 fname, PTR_DIFF(end_data, p),
1918 STR_TERMINATE_ASCII);
1919 SIVAL(p, -4, len);
1920 p += len;
1922 len = PTR_DIFF(p, pdata);
1923 pad = (len + (align-1)) & ~(align-1);
1925 * offset to the next entry, the caller
1926 * will overwrite it for the last entry
1927 * that's why we always include the padding
1929 SIVAL(pdata,0,pad);
1931 * set padding to zero
1933 if (do_pad) {
1934 memset(p, 0, pad - len);
1935 p = pdata + pad;
1936 } else {
1937 p = pdata + len;
1939 break;
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1943 p += 4;
1944 SIVAL(p,0,reskey); p += 4;
1945 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1946 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1947 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1948 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1949 SOFF_T(p,0,file_size); p += 8;
1950 SOFF_T(p,0,allocation_size); p += 8;
1951 SIVAL(p,0,mode); p += 4;
1952 q = p; p += 4; /* q is placeholder for name length. */
1954 unsigned int ea_size = estimate_ea_size(conn, NULL,
1955 smb_fname->base_name);
1956 SIVAL(p,0,ea_size); /* Extended attributes */
1957 p +=4;
1959 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1960 SBVAL(p,0,file_index); p += 8;
1961 len = srvstr_push(base_data, flags2, p,
1962 fname, PTR_DIFF(end_data, p),
1963 STR_TERMINATE_ASCII);
1964 SIVAL(q, 0, len);
1965 p += len;
1967 len = PTR_DIFF(p, pdata);
1968 pad = (len + (align-1)) & ~(align-1);
1970 * offset to the next entry, the caller
1971 * will overwrite it for the last entry
1972 * that's why we always include the padding
1974 SIVAL(pdata,0,pad);
1976 * set padding to zero
1978 if (do_pad) {
1979 memset(p, 0, pad - len);
1980 p = pdata + pad;
1981 } else {
1982 p = pdata + len;
1984 break;
1986 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1987 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1988 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1989 p += 4;
1990 SIVAL(p,0,reskey); p += 4;
1991 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1992 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1993 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1994 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1995 SOFF_T(p,0,file_size); p += 8;
1996 SOFF_T(p,0,allocation_size); p += 8;
1997 SIVAL(p,0,mode); p += 4;
1998 q = p; p += 4; /* q is placeholder for name length */
2000 unsigned int ea_size = estimate_ea_size(conn, NULL,
2001 smb_fname->base_name);
2002 SIVAL(p,0,ea_size); /* Extended attributes */
2003 p +=4;
2005 /* Clear the short name buffer. This is
2006 * IMPORTANT as not doing so will trigger
2007 * a Win2k client bug. JRA.
2009 if (!was_8_3 && check_mangled_names) {
2010 char mangled_name[13]; /* mangled 8.3 name. */
2011 if (!name_to_8_3(fname,mangled_name,True,
2012 conn->params)) {
2013 /* Error - mangle failed ! */
2014 memset(mangled_name,'\0',12);
2016 mangled_name[12] = 0;
2017 len = srvstr_push(base_data, flags2,
2018 p+2, mangled_name, 24,
2019 STR_UPPER|STR_UNICODE);
2020 SSVAL(p, 0, len);
2021 if (len < 24) {
2022 memset(p + 2 + len,'\0',24 - len);
2024 SSVAL(p, 0, len);
2025 } else {
2026 memset(p,'\0',26);
2028 p += 26;
2029 SSVAL(p,0,0); p += 2; /* Reserved ? */
2030 SBVAL(p,0,file_index); p += 8;
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2033 STR_TERMINATE_ASCII);
2034 SIVAL(q,0,len);
2035 p += len;
2037 len = PTR_DIFF(p, pdata);
2038 pad = (len + (align-1)) & ~(align-1);
2040 * offset to the next entry, the caller
2041 * will overwrite it for the last entry
2042 * that's why we always include the padding
2044 SIVAL(pdata,0,pad);
2046 * set padding to zero
2048 if (do_pad) {
2049 memset(p, 0, pad - len);
2050 p = pdata + pad;
2051 } else {
2052 p = pdata + len;
2054 break;
2056 /* CIFS UNIX Extension. */
2058 case SMB_FIND_FILE_UNIX:
2059 case SMB_FIND_FILE_UNIX_INFO2:
2060 p+= 4;
2061 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2063 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2065 if (info_level == SMB_FIND_FILE_UNIX) {
2066 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2067 p = store_file_unix_basic(conn, p,
2068 NULL, &smb_fname->st);
2069 len = srvstr_push(base_data, flags2, p,
2070 fname, PTR_DIFF(end_data, p),
2071 STR_TERMINATE);
2072 } else {
2073 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2074 p = store_file_unix_basic_info2(conn, p,
2075 NULL, &smb_fname->st);
2076 nameptr = p;
2077 p += 4;
2078 len = srvstr_push(base_data, flags2, p, fname,
2079 PTR_DIFF(end_data, p), 0);
2080 SIVAL(nameptr, 0, len);
2083 p += len;
2085 len = PTR_DIFF(p, pdata);
2086 pad = (len + (align-1)) & ~(align-1);
2088 * offset to the next entry, the caller
2089 * will overwrite it for the last entry
2090 * that's why we always include the padding
2092 SIVAL(pdata,0,pad);
2094 * set padding to zero
2096 if (do_pad) {
2097 memset(p, 0, pad - len);
2098 p = pdata + pad;
2099 } else {
2100 p = pdata + len;
2102 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2104 break;
2106 default:
2107 return false;
2110 if (PTR_DIFF(p,pdata) > space_remaining) {
2111 *out_of_space = true;
2112 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2113 "(wanted %u, had %d)\n",
2114 (unsigned int)PTR_DIFF(p,pdata),
2115 space_remaining ));
2116 return false; /* Not finished - just out of space */
2119 /* Setup the last entry pointer, as an offset from base_data */
2120 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2121 /* Advance the data pointer to the next slot */
2122 *ppdata = p;
2124 return true;
2127 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2128 connection_struct *conn,
2129 struct dptr_struct *dirptr,
2130 uint16 flags2,
2131 const char *path_mask,
2132 uint32 dirtype,
2133 int info_level,
2134 int requires_resume_key,
2135 bool dont_descend,
2136 bool ask_sharemode,
2137 uint8_t align,
2138 bool do_pad,
2139 char **ppdata,
2140 char *base_data,
2141 char *end_data,
2142 int space_remaining,
2143 bool *out_of_space,
2144 bool *got_exact_match,
2145 int *_last_entry_off,
2146 struct ea_list *name_list)
2148 const char *p;
2149 const char *mask = NULL;
2150 long prev_dirpos = 0;
2151 uint32_t mode = 0;
2152 char *fname = NULL;
2153 struct smb_filename *smb_fname = NULL;
2154 struct smbd_dirptr_lanman2_state state;
2155 bool ok;
2156 uint64_t last_entry_off = 0;
2158 ZERO_STRUCT(state);
2159 state.conn = conn;
2160 state.info_level = info_level;
2161 state.check_mangled_names = lp_manglednames(conn->params);
2162 state.has_wild = dptr_has_wild(dirptr);
2163 state.got_exact_match = false;
2165 *out_of_space = false;
2166 *got_exact_match = false;
2168 p = strrchr_m(path_mask,'/');
2169 if(p != NULL) {
2170 if(p[1] == '\0') {
2171 mask = "*.*";
2172 } else {
2173 mask = p+1;
2175 } else {
2176 mask = path_mask;
2179 ok = smbd_dirptr_get_entry(ctx,
2180 dirptr,
2181 mask,
2182 dirtype,
2183 dont_descend,
2184 ask_sharemode,
2185 smbd_dirptr_lanman2_match_fn,
2186 smbd_dirptr_lanman2_mode_fn,
2187 &state,
2188 &fname,
2189 &smb_fname,
2190 &mode,
2191 &prev_dirpos);
2192 if (!ok) {
2193 return false;
2196 *got_exact_match = state.got_exact_match;
2198 ok = smbd_marshall_dir_entry(ctx,
2199 conn,
2200 flags2,
2201 info_level,
2202 name_list,
2203 state.check_mangled_names,
2204 requires_resume_key,
2205 mode,
2206 fname,
2207 smb_fname,
2208 space_remaining,
2209 align,
2210 do_pad,
2211 base_data,
2212 ppdata,
2213 end_data,
2214 out_of_space,
2215 &last_entry_off);
2216 TALLOC_FREE(fname);
2217 TALLOC_FREE(smb_fname);
2218 if (*out_of_space) {
2219 dptr_SeekDir(dirptr, prev_dirpos);
2220 return false;
2222 if (!ok) {
2223 return false;
2226 *_last_entry_off = last_entry_off;
2227 return true;
2230 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2231 connection_struct *conn,
2232 struct dptr_struct *dirptr,
2233 uint16 flags2,
2234 const char *path_mask,
2235 uint32 dirtype,
2236 int info_level,
2237 bool requires_resume_key,
2238 bool dont_descend,
2239 bool ask_sharemode,
2240 char **ppdata,
2241 char *base_data,
2242 char *end_data,
2243 int space_remaining,
2244 bool *out_of_space,
2245 bool *got_exact_match,
2246 int *last_entry_off,
2247 struct ea_list *name_list)
2249 uint8_t align = 4;
2250 const bool do_pad = true;
2252 if (info_level >= 1 && info_level <= 3) {
2253 /* No alignment on earlier info levels. */
2254 align = 1;
2257 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2258 path_mask, dirtype, info_level,
2259 requires_resume_key, dont_descend, ask_sharemode,
2260 align, do_pad,
2261 ppdata, base_data, end_data,
2262 space_remaining,
2263 out_of_space, got_exact_match,
2264 last_entry_off, name_list);
2267 /****************************************************************************
2268 Reply to a TRANS2_FINDFIRST.
2269 ****************************************************************************/
2271 static void call_trans2findfirst(connection_struct *conn,
2272 struct smb_request *req,
2273 char **pparams, int total_params,
2274 char **ppdata, int total_data,
2275 unsigned int max_data_bytes)
2277 /* We must be careful here that we don't return more than the
2278 allowed number of data bytes. If this means returning fewer than
2279 maxentries then so be it. We assume that the redirector has
2280 enough room for the fixed number of parameter bytes it has
2281 requested. */
2282 struct smb_filename *smb_dname = NULL;
2283 char *params = *pparams;
2284 char *pdata = *ppdata;
2285 char *data_end;
2286 uint32 dirtype;
2287 int maxentries;
2288 uint16 findfirst_flags;
2289 bool close_after_first;
2290 bool close_if_end;
2291 bool requires_resume_key;
2292 int info_level;
2293 char *directory = NULL;
2294 char *mask = NULL;
2295 char *p;
2296 int last_entry_off=0;
2297 int dptr_num = -1;
2298 int numentries = 0;
2299 int i;
2300 bool finished = False;
2301 bool dont_descend = False;
2302 bool out_of_space = False;
2303 int space_remaining;
2304 bool mask_contains_wcard = False;
2305 struct ea_list *ea_list = NULL;
2306 NTSTATUS ntstatus = NT_STATUS_OK;
2307 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2308 TALLOC_CTX *ctx = talloc_tos();
2309 struct dptr_struct *dirptr = NULL;
2310 struct smbd_server_connection *sconn = req->sconn;
2311 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2313 if (total_params < 13) {
2314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2315 goto out;
2318 dirtype = SVAL(params,0);
2319 maxentries = SVAL(params,2);
2320 findfirst_flags = SVAL(params,4);
2321 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2322 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2323 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2324 info_level = SVAL(params,6);
2326 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2327 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2328 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2329 info_level, max_data_bytes));
2331 if (!maxentries) {
2332 /* W2K3 seems to treat zero as 1. */
2333 maxentries = 1;
2336 switch (info_level) {
2337 case SMB_FIND_INFO_STANDARD:
2338 case SMB_FIND_EA_SIZE:
2339 case SMB_FIND_EA_LIST:
2340 case SMB_FIND_FILE_DIRECTORY_INFO:
2341 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2342 case SMB_FIND_FILE_NAMES_INFO:
2343 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2344 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2345 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2346 break;
2347 case SMB_FIND_FILE_UNIX:
2348 case SMB_FIND_FILE_UNIX_INFO2:
2349 /* Always use filesystem for UNIX mtime query. */
2350 ask_sharemode = false;
2351 if (!lp_unix_extensions()) {
2352 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2353 goto out;
2355 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2356 break;
2357 default:
2358 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2359 goto out;
2362 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2363 params+12, total_params - 12,
2364 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2365 if (!NT_STATUS_IS_OK(ntstatus)) {
2366 reply_nterror(req, ntstatus);
2367 goto out;
2370 ntstatus = filename_convert(ctx, conn,
2371 req->flags2 & FLAGS2_DFS_PATHNAMES,
2372 directory,
2373 ucf_flags,
2374 &mask_contains_wcard,
2375 &smb_dname);
2376 if (!NT_STATUS_IS_OK(ntstatus)) {
2377 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2378 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2379 ERRSRV, ERRbadpath);
2380 goto out;
2382 reply_nterror(req, ntstatus);
2383 goto out;
2386 mask = smb_dname->original_lcomp;
2388 directory = smb_dname->base_name;
2390 p = strrchr_m(directory,'/');
2391 if(p == NULL) {
2392 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2393 if((directory[0] == '.') && (directory[1] == '\0')) {
2394 mask = talloc_strdup(ctx,"*");
2395 if (!mask) {
2396 reply_nterror(req, NT_STATUS_NO_MEMORY);
2397 goto out;
2399 mask_contains_wcard = True;
2401 } else {
2402 *p = 0;
2405 if (p == NULL || p == directory) {
2406 /* Ensure we don't have a directory name of "". */
2407 directory = talloc_strdup(talloc_tos(), ".");
2408 if (!directory) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2410 goto out;
2414 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2416 if (info_level == SMB_FIND_EA_LIST) {
2417 uint32 ea_size;
2419 if (total_data < 4) {
2420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2421 goto out;
2424 ea_size = IVAL(pdata,0);
2425 if (ea_size != total_data) {
2426 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2427 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2429 goto out;
2432 if (!lp_ea_support(SNUM(conn))) {
2433 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2434 goto out;
2437 /* Pull out the list of names. */
2438 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2439 if (!ea_list) {
2440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2441 goto out;
2445 *ppdata = (char *)SMB_REALLOC(
2446 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2447 if(*ppdata == NULL ) {
2448 reply_nterror(req, NT_STATUS_NO_MEMORY);
2449 goto out;
2451 pdata = *ppdata;
2452 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2454 /* Realloc the params space */
2455 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2456 if (*pparams == NULL) {
2457 reply_nterror(req, NT_STATUS_NO_MEMORY);
2458 goto out;
2460 params = *pparams;
2462 /* Save the wildcard match and attribs we are using on this directory -
2463 needed as lanman2 assumes these are being saved between calls */
2465 ntstatus = dptr_create(conn,
2466 NULL, /* fsp */
2467 directory,
2468 False,
2469 True,
2470 req->smbpid,
2471 mask,
2472 mask_contains_wcard,
2473 dirtype,
2474 &dirptr);
2476 if (!NT_STATUS_IS_OK(ntstatus)) {
2477 reply_nterror(req, ntstatus);
2478 goto out;
2481 dptr_num = dptr_dnum(dirptr);
2482 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2484 /* Initialize per TRANS2_FIND_FIRST operation data */
2485 dptr_init_search_op(dirptr);
2487 /* We don't need to check for VOL here as this is returned by
2488 a different TRANS2 call. */
2490 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2491 directory,lp_dontdescend(SNUM(conn))));
2492 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2493 dont_descend = True;
2495 p = pdata;
2496 space_remaining = max_data_bytes;
2497 out_of_space = False;
2499 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2500 bool got_exact_match = False;
2502 /* this is a heuristic to avoid seeking the dirptr except when
2503 absolutely necessary. It allows for a filename of about 40 chars */
2504 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2505 out_of_space = True;
2506 finished = False;
2507 } else {
2508 finished = !get_lanman2_dir_entry(ctx,
2509 conn,
2510 dirptr,
2511 req->flags2,
2512 mask,dirtype,info_level,
2513 requires_resume_key,dont_descend,
2514 ask_sharemode,
2515 &p,pdata,data_end,
2516 space_remaining, &out_of_space,
2517 &got_exact_match,
2518 &last_entry_off, ea_list);
2521 if (finished && out_of_space)
2522 finished = False;
2524 if (!finished && !out_of_space)
2525 numentries++;
2528 * As an optimisation if we know we aren't looking
2529 * for a wildcard name (ie. the name matches the wildcard exactly)
2530 * then we can finish on any (first) match.
2531 * This speeds up large directory searches. JRA.
2534 if(got_exact_match)
2535 finished = True;
2537 /* Ensure space_remaining never goes -ve. */
2538 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2539 space_remaining = 0;
2540 out_of_space = true;
2541 } else {
2542 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2546 /* Check if we can close the dirptr */
2547 if(close_after_first || (finished && close_if_end)) {
2548 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2549 dptr_close(sconn, &dptr_num);
2553 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2554 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2555 * the protocol level is less than NT1. Tested with smbclient. JRA.
2556 * This should fix the OS/2 client bug #2335.
2559 if(numentries == 0) {
2560 dptr_close(sconn, &dptr_num);
2561 if (get_Protocol() < PROTOCOL_NT1) {
2562 reply_force_doserror(req, ERRDOS, ERRnofiles);
2563 goto out;
2564 } else {
2565 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2566 ERRDOS, ERRbadfile);
2567 goto out;
2571 /* At this point pdata points to numentries directory entries. */
2573 /* Set up the return parameter block */
2574 SSVAL(params,0,dptr_num);
2575 SSVAL(params,2,numentries);
2576 SSVAL(params,4,finished);
2577 SSVAL(params,6,0); /* Never an EA error */
2578 SSVAL(params,8,last_entry_off);
2580 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2581 max_data_bytes);
2583 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2584 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2585 if (!directory) {
2586 reply_nterror(req, NT_STATUS_NO_MEMORY);
2590 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2591 smb_fn_name(req->cmd),
2592 mask, directory, dirtype, numentries ) );
2595 * Force a name mangle here to ensure that the
2596 * mask as an 8.3 name is top of the mangled cache.
2597 * The reasons for this are subtle. Don't remove
2598 * this code unless you know what you are doing
2599 * (see PR#13758). JRA.
2602 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2603 char mangled_name[13];
2604 name_to_8_3(mask, mangled_name, True, conn->params);
2606 out:
2607 TALLOC_FREE(smb_dname);
2608 return;
2611 /****************************************************************************
2612 Reply to a TRANS2_FINDNEXT.
2613 ****************************************************************************/
2615 static void call_trans2findnext(connection_struct *conn,
2616 struct smb_request *req,
2617 char **pparams, int total_params,
2618 char **ppdata, int total_data,
2619 unsigned int max_data_bytes)
2621 /* We must be careful here that we don't return more than the
2622 allowed number of data bytes. If this means returning fewer than
2623 maxentries then so be it. We assume that the redirector has
2624 enough room for the fixed number of parameter bytes it has
2625 requested. */
2626 char *params = *pparams;
2627 char *pdata = *ppdata;
2628 char *data_end;
2629 int dptr_num;
2630 int maxentries;
2631 uint16 info_level;
2632 uint32 resume_key;
2633 uint16 findnext_flags;
2634 bool close_after_request;
2635 bool close_if_end;
2636 bool requires_resume_key;
2637 bool continue_bit;
2638 bool mask_contains_wcard = False;
2639 char *resume_name = NULL;
2640 const char *mask = NULL;
2641 const char *directory = NULL;
2642 char *p = NULL;
2643 uint16 dirtype;
2644 int numentries = 0;
2645 int i, last_entry_off=0;
2646 bool finished = False;
2647 bool dont_descend = False;
2648 bool out_of_space = False;
2649 int space_remaining;
2650 struct ea_list *ea_list = NULL;
2651 NTSTATUS ntstatus = NT_STATUS_OK;
2652 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2653 TALLOC_CTX *ctx = talloc_tos();
2654 struct dptr_struct *dirptr;
2655 struct smbd_server_connection *sconn = req->sconn;
2657 if (total_params < 13) {
2658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2659 return;
2662 dptr_num = SVAL(params,0);
2663 maxentries = SVAL(params,2);
2664 info_level = SVAL(params,4);
2665 resume_key = IVAL(params,6);
2666 findnext_flags = SVAL(params,10);
2667 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2668 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2669 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2670 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2672 if (!continue_bit) {
2673 /* We only need resume_name if continue_bit is zero. */
2674 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2675 params+12,
2676 total_params - 12, STR_TERMINATE, &ntstatus,
2677 &mask_contains_wcard);
2678 if (!NT_STATUS_IS_OK(ntstatus)) {
2679 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2680 complain (it thinks we're asking for the directory above the shared
2681 path or an invalid name). Catch this as the resume name is only compared, never used in
2682 a file access. JRA. */
2683 srvstr_pull_talloc(ctx, params, req->flags2,
2684 &resume_name, params+12,
2685 total_params - 12,
2686 STR_TERMINATE);
2688 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2689 reply_nterror(req, ntstatus);
2690 return;
2695 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2696 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2697 resume_key = %d resume name = %s continue=%d level = %d\n",
2698 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2699 requires_resume_key, resume_key,
2700 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2702 if (!maxentries) {
2703 /* W2K3 seems to treat zero as 1. */
2704 maxentries = 1;
2707 switch (info_level) {
2708 case SMB_FIND_INFO_STANDARD:
2709 case SMB_FIND_EA_SIZE:
2710 case SMB_FIND_EA_LIST:
2711 case SMB_FIND_FILE_DIRECTORY_INFO:
2712 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2713 case SMB_FIND_FILE_NAMES_INFO:
2714 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2715 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2716 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2717 break;
2718 case SMB_FIND_FILE_UNIX:
2719 case SMB_FIND_FILE_UNIX_INFO2:
2720 /* Always use filesystem for UNIX mtime query. */
2721 ask_sharemode = false;
2722 if (!lp_unix_extensions()) {
2723 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2724 return;
2726 break;
2727 default:
2728 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2729 return;
2732 if (info_level == SMB_FIND_EA_LIST) {
2733 uint32 ea_size;
2735 if (total_data < 4) {
2736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2737 return;
2740 ea_size = IVAL(pdata,0);
2741 if (ea_size != total_data) {
2742 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2743 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2745 return;
2748 if (!lp_ea_support(SNUM(conn))) {
2749 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2750 return;
2753 /* Pull out the list of names. */
2754 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2755 if (!ea_list) {
2756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2757 return;
2761 *ppdata = (char *)SMB_REALLOC(
2762 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2763 if(*ppdata == NULL) {
2764 reply_nterror(req, NT_STATUS_NO_MEMORY);
2765 return;
2768 pdata = *ppdata;
2769 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2771 /* Realloc the params space */
2772 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2773 if(*pparams == NULL ) {
2774 reply_nterror(req, NT_STATUS_NO_MEMORY);
2775 return;
2778 params = *pparams;
2780 /* Check that the dptr is valid */
2781 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2782 reply_nterror(req, STATUS_NO_MORE_FILES);
2783 return;
2786 directory = dptr_path(sconn, dptr_num);
2788 /* Get the wildcard mask from the dptr */
2789 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2790 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2791 reply_nterror(req, STATUS_NO_MORE_FILES);
2792 return;
2795 mask = p;
2797 /* Get the attr mask from the dptr */
2798 dirtype = dptr_attr(sconn, dptr_num);
2800 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2801 dptr_num, mask, dirtype,
2802 (long)dirptr,
2803 dptr_TellDir(dirptr)));
2805 /* Initialize per TRANS2_FIND_NEXT operation data */
2806 dptr_init_search_op(dirptr);
2808 /* We don't need to check for VOL here as this is returned by
2809 a different TRANS2 call. */
2811 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2812 directory,lp_dontdescend(SNUM(conn))));
2813 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2814 dont_descend = True;
2816 p = pdata;
2817 space_remaining = max_data_bytes;
2818 out_of_space = False;
2821 * Seek to the correct position. We no longer use the resume key but
2822 * depend on the last file name instead.
2825 if(!continue_bit && resume_name && *resume_name) {
2826 SMB_STRUCT_STAT st;
2828 long current_pos = 0;
2830 * Remember, name_to_8_3 is called by
2831 * get_lanman2_dir_entry(), so the resume name
2832 * could be mangled. Ensure we check the unmangled name.
2835 if (mangle_is_mangled(resume_name, conn->params)) {
2836 char *new_resume_name = NULL;
2837 mangle_lookup_name_from_8_3(ctx,
2838 resume_name,
2839 &new_resume_name,
2840 conn->params);
2841 if (new_resume_name) {
2842 resume_name = new_resume_name;
2847 * Fix for NT redirector problem triggered by resume key indexes
2848 * changing between directory scans. We now return a resume key of 0
2849 * and instead look for the filename to continue from (also given
2850 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2851 * findfirst/findnext (as is usual) then the directory pointer
2852 * should already be at the correct place.
2855 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2856 } /* end if resume_name && !continue_bit */
2858 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2859 bool got_exact_match = False;
2861 /* this is a heuristic to avoid seeking the dirptr except when
2862 absolutely necessary. It allows for a filename of about 40 chars */
2863 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2864 out_of_space = True;
2865 finished = False;
2866 } else {
2867 finished = !get_lanman2_dir_entry(ctx,
2868 conn,
2869 dirptr,
2870 req->flags2,
2871 mask,dirtype,info_level,
2872 requires_resume_key,dont_descend,
2873 ask_sharemode,
2874 &p,pdata,data_end,
2875 space_remaining, &out_of_space,
2876 &got_exact_match,
2877 &last_entry_off, ea_list);
2880 if (finished && out_of_space)
2881 finished = False;
2883 if (!finished && !out_of_space)
2884 numentries++;
2887 * As an optimisation if we know we aren't looking
2888 * for a wildcard name (ie. the name matches the wildcard exactly)
2889 * then we can finish on any (first) match.
2890 * This speeds up large directory searches. JRA.
2893 if(got_exact_match)
2894 finished = True;
2896 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2899 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2900 smb_fn_name(req->cmd),
2901 mask, directory, dirtype, numentries ) );
2903 /* Check if we can close the dirptr */
2904 if(close_after_request || (finished && close_if_end)) {
2905 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2906 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2909 /* Set up the return parameter block */
2910 SSVAL(params,0,numentries);
2911 SSVAL(params,2,finished);
2912 SSVAL(params,4,0); /* Never an EA error */
2913 SSVAL(params,6,last_entry_off);
2915 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2916 max_data_bytes);
2918 return;
2921 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2923 E_md4hash(lp_servicename(SNUM(conn)),objid);
2924 return objid;
2927 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2929 SMB_ASSERT(extended_info != NULL);
2931 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2932 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2933 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2934 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2935 #ifdef SAMBA_VERSION_REVISION
2936 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2937 #endif
2938 extended_info->samba_subversion = 0;
2939 #ifdef SAMBA_VERSION_RC_RELEASE
2940 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2941 #else
2942 #ifdef SAMBA_VERSION_PRE_RELEASE
2943 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2944 #endif
2945 #endif
2946 #ifdef SAMBA_VERSION_VENDOR_PATCH
2947 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2948 #endif
2949 extended_info->samba_gitcommitdate = 0;
2950 #ifdef SAMBA_VERSION_COMMIT_TIME
2951 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2952 #endif
2954 memset(extended_info->samba_version_string, 0,
2955 sizeof(extended_info->samba_version_string));
2957 snprintf (extended_info->samba_version_string,
2958 sizeof(extended_info->samba_version_string),
2959 "%s", samba_version_string());
2962 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2963 TALLOC_CTX *mem_ctx,
2964 uint16_t info_level,
2965 uint16_t flags2,
2966 unsigned int max_data_bytes,
2967 struct smb_filename *fname,
2968 char **ppdata,
2969 int *ret_data_len)
2971 char *pdata, *end_data;
2972 int data_len = 0, len;
2973 const char *vname = volume_label(SNUM(conn));
2974 int snum = SNUM(conn);
2975 char *fstype = lp_fstype(SNUM(conn));
2976 const char *filename = NULL;
2977 uint32 additional_flags = 0;
2978 struct smb_filename smb_fname;
2979 SMB_STRUCT_STAT st;
2981 if (fname == NULL || fname->base_name == NULL) {
2982 filename = ".";
2983 } else {
2984 filename = fname->base_name;
2987 if (IS_IPC(conn)) {
2988 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2989 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2990 "info level (0x%x) on IPC$.\n",
2991 (unsigned int)info_level));
2992 return NT_STATUS_ACCESS_DENIED;
2996 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2998 ZERO_STRUCT(smb_fname);
2999 smb_fname.base_name = discard_const_p(char, filename);
3001 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3002 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3003 return map_nt_error_from_unix(errno);
3006 st = smb_fname.st;
3008 *ppdata = (char *)SMB_REALLOC(
3009 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3010 if (*ppdata == NULL) {
3011 return NT_STATUS_NO_MEMORY;
3014 pdata = *ppdata;
3015 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3016 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3018 switch (info_level) {
3019 case SMB_INFO_ALLOCATION:
3021 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3022 data_len = 18;
3023 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3024 return map_nt_error_from_unix(errno);
3027 block_size = lp_block_size(snum);
3028 if (bsize < block_size) {
3029 uint64_t factor = block_size/bsize;
3030 bsize = block_size;
3031 dsize /= factor;
3032 dfree /= factor;
3034 if (bsize > block_size) {
3035 uint64_t factor = bsize/block_size;
3036 bsize = block_size;
3037 dsize *= factor;
3038 dfree *= factor;
3040 bytes_per_sector = 512;
3041 sectors_per_unit = bsize/bytes_per_sector;
3043 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3044 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3045 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3047 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3048 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3049 SIVAL(pdata,l1_cUnit,dsize);
3050 SIVAL(pdata,l1_cUnitAvail,dfree);
3051 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3052 break;
3055 case SMB_INFO_VOLUME:
3056 /* Return volume name */
3058 * Add volume serial number - hash of a combination of
3059 * the called hostname and the service name.
3061 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3063 * Win2k3 and previous mess this up by sending a name length
3064 * one byte short. I believe only older clients (OS/2 Win9x) use
3065 * this call so try fixing this by adding a terminating null to
3066 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3068 len = srvstr_push(
3069 pdata, flags2,
3070 pdata+l2_vol_szVolLabel, vname,
3071 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3072 STR_NOALIGN|STR_TERMINATE);
3073 SCVAL(pdata,l2_vol_cch,len);
3074 data_len = l2_vol_szVolLabel + len;
3075 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3076 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3077 len, vname));
3078 break;
3080 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3081 case SMB_FS_ATTRIBUTE_INFORMATION:
3083 additional_flags = 0;
3084 #if defined(HAVE_SYS_QUOTAS)
3085 additional_flags |= FILE_VOLUME_QUOTAS;
3086 #endif
3088 if(lp_nt_acl_support(SNUM(conn))) {
3089 additional_flags |= FILE_PERSISTENT_ACLS;
3092 /* Capabilities are filled in at connection time through STATVFS call */
3093 additional_flags |= conn->fs_capabilities;
3094 additional_flags |= lp_parm_int(conn->params->service,
3095 "share", "fake_fscaps",
3098 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3099 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3100 additional_flags); /* FS ATTRIBUTES */
3102 SIVAL(pdata,4,255); /* Max filename component length */
3103 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3104 and will think we can't do long filenames */
3105 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3106 PTR_DIFF(end_data, pdata+12),
3107 STR_UNICODE);
3108 SIVAL(pdata,8,len);
3109 data_len = 12 + len;
3110 break;
3112 case SMB_QUERY_FS_LABEL_INFO:
3113 case SMB_FS_LABEL_INFORMATION:
3114 len = srvstr_push(pdata, flags2, pdata+4, vname,
3115 PTR_DIFF(end_data, pdata+4), 0);
3116 data_len = 4 + len;
3117 SIVAL(pdata,0,len);
3118 break;
3120 case SMB_QUERY_FS_VOLUME_INFO:
3121 case SMB_FS_VOLUME_INFORMATION:
3124 * Add volume serial number - hash of a combination of
3125 * the called hostname and the service name.
3127 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3128 (str_checksum(get_local_machine_name())<<16));
3130 /* Max label len is 32 characters. */
3131 len = srvstr_push(pdata, flags2, pdata+18, vname,
3132 PTR_DIFF(end_data, pdata+18),
3133 STR_UNICODE);
3134 SIVAL(pdata,12,len);
3135 data_len = 18+len;
3137 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3138 (int)strlen(vname),vname, lp_servicename(snum)));
3139 break;
3141 case SMB_QUERY_FS_SIZE_INFO:
3142 case SMB_FS_SIZE_INFORMATION:
3144 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3145 data_len = 24;
3146 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3147 return map_nt_error_from_unix(errno);
3149 block_size = lp_block_size(snum);
3150 if (bsize < block_size) {
3151 uint64_t factor = block_size/bsize;
3152 bsize = block_size;
3153 dsize /= factor;
3154 dfree /= factor;
3156 if (bsize > block_size) {
3157 uint64_t factor = bsize/block_size;
3158 bsize = block_size;
3159 dsize *= factor;
3160 dfree *= factor;
3162 bytes_per_sector = 512;
3163 sectors_per_unit = bsize/bytes_per_sector;
3164 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3165 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3166 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3167 SBIG_UINT(pdata,0,dsize);
3168 SBIG_UINT(pdata,8,dfree);
3169 SIVAL(pdata,16,sectors_per_unit);
3170 SIVAL(pdata,20,bytes_per_sector);
3171 break;
3174 case SMB_FS_FULL_SIZE_INFORMATION:
3176 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3177 data_len = 32;
3178 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3179 return map_nt_error_from_unix(errno);
3181 block_size = lp_block_size(snum);
3182 if (bsize < block_size) {
3183 uint64_t factor = block_size/bsize;
3184 bsize = block_size;
3185 dsize /= factor;
3186 dfree /= factor;
3188 if (bsize > block_size) {
3189 uint64_t factor = bsize/block_size;
3190 bsize = block_size;
3191 dsize *= factor;
3192 dfree *= factor;
3194 bytes_per_sector = 512;
3195 sectors_per_unit = bsize/bytes_per_sector;
3196 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3197 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3198 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3199 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3200 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3201 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3202 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3203 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3204 break;
3207 case SMB_QUERY_FS_DEVICE_INFO:
3208 case SMB_FS_DEVICE_INFORMATION:
3210 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3212 if (!CAN_WRITE(conn)) {
3213 characteristics |= FILE_READ_ONLY_DEVICE;
3215 data_len = 8;
3216 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3217 SIVAL(pdata,4,characteristics);
3218 break;
3221 #ifdef HAVE_SYS_QUOTAS
3222 case SMB_FS_QUOTA_INFORMATION:
3224 * what we have to send --metze:
3226 * Unknown1: 24 NULL bytes
3227 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3228 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3229 * Quota Flags: 2 byte :
3230 * Unknown3: 6 NULL bytes
3232 * 48 bytes total
3234 * details for Quota Flags:
3236 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3237 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3238 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3239 * 0x0001 Enable Quotas: enable quota for this fs
3243 /* we need to fake up a fsp here,
3244 * because its not send in this call
3246 files_struct fsp;
3247 SMB_NTQUOTA_STRUCT quotas;
3249 ZERO_STRUCT(fsp);
3250 ZERO_STRUCT(quotas);
3252 fsp.conn = conn;
3253 fsp.fnum = -1;
3255 /* access check */
3256 if (get_current_uid(conn) != 0) {
3257 DEBUG(0,("set_user_quota: access_denied "
3258 "service [%s] user [%s]\n",
3259 lp_servicename(SNUM(conn)),
3260 conn->session_info->unix_name));
3261 return NT_STATUS_ACCESS_DENIED;
3264 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3265 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3266 return map_nt_error_from_unix(errno);
3269 data_len = 48;
3271 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3272 lp_servicename(SNUM(conn))));
3274 /* Unknown1 24 NULL bytes*/
3275 SBIG_UINT(pdata,0,(uint64_t)0);
3276 SBIG_UINT(pdata,8,(uint64_t)0);
3277 SBIG_UINT(pdata,16,(uint64_t)0);
3279 /* Default Soft Quota 8 bytes */
3280 SBIG_UINT(pdata,24,quotas.softlim);
3282 /* Default Hard Quota 8 bytes */
3283 SBIG_UINT(pdata,32,quotas.hardlim);
3285 /* Quota flag 2 bytes */
3286 SSVAL(pdata,40,quotas.qflags);
3288 /* Unknown3 6 NULL bytes */
3289 SSVAL(pdata,42,0);
3290 SIVAL(pdata,44,0);
3292 break;
3294 #endif /* HAVE_SYS_QUOTAS */
3295 case SMB_FS_OBJECTID_INFORMATION:
3297 unsigned char objid[16];
3298 struct smb_extended_info extended_info;
3299 memcpy(pdata,create_volume_objectid(conn, objid),16);
3300 samba_extended_info_version (&extended_info);
3301 SIVAL(pdata,16,extended_info.samba_magic);
3302 SIVAL(pdata,20,extended_info.samba_version);
3303 SIVAL(pdata,24,extended_info.samba_subversion);
3304 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3305 memcpy(pdata+36,extended_info.samba_version_string,28);
3306 data_len = 64;
3307 break;
3311 * Query the version and capabilities of the CIFS UNIX extensions
3312 * in use.
3315 case SMB_QUERY_CIFS_UNIX_INFO:
3317 bool large_write = lp_min_receive_file_size() &&
3318 !srv_is_signing_active(conn->sconn);
3319 bool large_read = !srv_is_signing_active(conn->sconn);
3320 int encrypt_caps = 0;
3322 if (!lp_unix_extensions()) {
3323 return NT_STATUS_INVALID_LEVEL;
3326 switch (conn->encrypt_level) {
3327 case 0:
3328 encrypt_caps = 0;
3329 break;
3330 case 1:
3331 case Auto:
3332 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3333 break;
3334 case Required:
3335 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3336 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3337 large_write = false;
3338 large_read = false;
3339 break;
3342 data_len = 12;
3343 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3344 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3346 /* We have POSIX ACLs, pathname, encryption,
3347 * large read/write, and locking capability. */
3349 SBIG_UINT(pdata,4,((uint64_t)(
3350 CIFS_UNIX_POSIX_ACLS_CAP|
3351 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3352 CIFS_UNIX_FCNTL_LOCKS_CAP|
3353 CIFS_UNIX_EXTATTR_CAP|
3354 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3355 encrypt_caps|
3356 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3357 (large_write ?
3358 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3359 break;
3362 case SMB_QUERY_POSIX_FS_INFO:
3364 int rc;
3365 vfs_statvfs_struct svfs;
3367 if (!lp_unix_extensions()) {
3368 return NT_STATUS_INVALID_LEVEL;
3371 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3373 if (!rc) {
3374 data_len = 56;
3375 SIVAL(pdata,0,svfs.OptimalTransferSize);
3376 SIVAL(pdata,4,svfs.BlockSize);
3377 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3378 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3379 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3380 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3381 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3382 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3383 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3384 #ifdef EOPNOTSUPP
3385 } else if (rc == EOPNOTSUPP) {
3386 return NT_STATUS_INVALID_LEVEL;
3387 #endif /* EOPNOTSUPP */
3388 } else {
3389 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3390 return NT_STATUS_DOS(ERRSRV, ERRerror);
3392 break;
3395 case SMB_QUERY_POSIX_WHOAMI:
3397 uint32_t flags = 0;
3398 uint32_t sid_bytes;
3399 int i;
3401 if (!lp_unix_extensions()) {
3402 return NT_STATUS_INVALID_LEVEL;
3405 if (max_data_bytes < 40) {
3406 return NT_STATUS_BUFFER_TOO_SMALL;
3409 /* We ARE guest if global_sid_Builtin_Guests is
3410 * in our list of SIDs.
3412 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3413 conn->session_info->security_token)) {
3414 flags |= SMB_WHOAMI_GUEST;
3417 /* We are NOT guest if global_sid_Authenticated_Users
3418 * is in our list of SIDs.
3420 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3421 conn->session_info->security_token)) {
3422 flags &= ~SMB_WHOAMI_GUEST;
3425 /* NOTE: 8 bytes for UID/GID, irrespective of native
3426 * platform size. This matches
3427 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3429 data_len = 4 /* flags */
3430 + 4 /* flag mask */
3431 + 8 /* uid */
3432 + 8 /* gid */
3433 + 4 /* ngroups */
3434 + 4 /* num_sids */
3435 + 4 /* SID bytes */
3436 + 4 /* pad/reserved */
3437 + (conn->session_info->utok.ngroups * 8)
3438 /* groups list */
3439 + (conn->session_info->security_token->num_sids *
3440 SID_MAX_SIZE)
3441 /* SID list */;
3443 SIVAL(pdata, 0, flags);
3444 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3445 SBIG_UINT(pdata, 8,
3446 (uint64_t)conn->session_info->utok.uid);
3447 SBIG_UINT(pdata, 16,
3448 (uint64_t)conn->session_info->utok.gid);
3451 if (data_len >= max_data_bytes) {
3452 /* Potential overflow, skip the GIDs and SIDs. */
3454 SIVAL(pdata, 24, 0); /* num_groups */
3455 SIVAL(pdata, 28, 0); /* num_sids */
3456 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3457 SIVAL(pdata, 36, 0); /* reserved */
3459 data_len = 40;
3460 break;
3463 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3464 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3466 /* We walk the SID list twice, but this call is fairly
3467 * infrequent, and I don't expect that it's performance
3468 * sensitive -- jpeach
3470 for (i = 0, sid_bytes = 0;
3471 i < conn->session_info->security_token->num_sids; ++i) {
3472 sid_bytes += ndr_size_dom_sid(
3473 &conn->session_info->security_token->sids[i],
3477 /* SID list byte count */
3478 SIVAL(pdata, 32, sid_bytes);
3480 /* 4 bytes pad/reserved - must be zero */
3481 SIVAL(pdata, 36, 0);
3482 data_len = 40;
3484 /* GID list */
3485 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3486 SBIG_UINT(pdata, data_len,
3487 (uint64_t)conn->session_info->utok.groups[i]);
3488 data_len += 8;
3491 /* SID list */
3492 for (i = 0;
3493 i < conn->session_info->security_token->num_sids; ++i) {
3494 int sid_len = ndr_size_dom_sid(
3495 &conn->session_info->security_token->sids[i],
3498 sid_linearize(pdata + data_len, sid_len,
3499 &conn->session_info->security_token->sids[i]);
3500 data_len += sid_len;
3503 break;
3506 case SMB_MAC_QUERY_FS_INFO:
3508 * Thursby MAC extension... ONLY on NTFS filesystems
3509 * once we do streams then we don't need this
3511 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3512 data_len = 88;
3513 SIVAL(pdata,84,0x100); /* Don't support mac... */
3514 break;
3516 /* drop through */
3517 default:
3518 return NT_STATUS_INVALID_LEVEL;
3521 *ret_data_len = data_len;
3522 return NT_STATUS_OK;
3525 /****************************************************************************
3526 Reply to a TRANS2_QFSINFO (query filesystem info).
3527 ****************************************************************************/
3529 static void call_trans2qfsinfo(connection_struct *conn,
3530 struct smb_request *req,
3531 char **pparams, int total_params,
3532 char **ppdata, int total_data,
3533 unsigned int max_data_bytes)
3535 char *params = *pparams;
3536 uint16_t info_level;
3537 int data_len = 0;
3538 NTSTATUS status;
3540 if (total_params < 2) {
3541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3542 return;
3545 info_level = SVAL(params,0);
3547 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3548 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3549 DEBUG(0,("call_trans2qfsinfo: encryption required "
3550 "and info level 0x%x sent.\n",
3551 (unsigned int)info_level));
3552 exit_server_cleanly("encryption required "
3553 "on connection");
3554 return;
3558 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3560 status = smbd_do_qfsinfo(conn, req,
3561 info_level,
3562 req->flags2,
3563 max_data_bytes,
3564 NULL,
3565 ppdata, &data_len);
3566 if (!NT_STATUS_IS_OK(status)) {
3567 reply_nterror(req, status);
3568 return;
3571 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3572 max_data_bytes);
3574 DEBUG( 4, ( "%s info_level = %d\n",
3575 smb_fn_name(req->cmd), info_level) );
3577 return;
3580 /****************************************************************************
3581 Reply to a TRANS2_SETFSINFO (set filesystem info).
3582 ****************************************************************************/
3584 static void call_trans2setfsinfo(connection_struct *conn,
3585 struct smb_request *req,
3586 char **pparams, int total_params,
3587 char **ppdata, int total_data,
3588 unsigned int max_data_bytes)
3590 char *pdata = *ppdata;
3591 char *params = *pparams;
3592 uint16 info_level;
3594 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3596 /* */
3597 if (total_params < 4) {
3598 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3599 total_params));
3600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3601 return;
3604 info_level = SVAL(params,2);
3606 if (IS_IPC(conn)) {
3607 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3608 info_level != SMB_SET_CIFS_UNIX_INFO) {
3609 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3610 "info level (0x%x) on IPC$.\n",
3611 (unsigned int)info_level));
3612 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3613 return;
3617 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3618 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3619 DEBUG(0,("call_trans2setfsinfo: encryption required "
3620 "and info level 0x%x sent.\n",
3621 (unsigned int)info_level));
3622 exit_server_cleanly("encryption required "
3623 "on connection");
3624 return;
3628 switch(info_level) {
3629 case SMB_SET_CIFS_UNIX_INFO:
3631 uint16 client_unix_major;
3632 uint16 client_unix_minor;
3633 uint32 client_unix_cap_low;
3634 uint32 client_unix_cap_high;
3636 if (!lp_unix_extensions()) {
3637 reply_nterror(req,
3638 NT_STATUS_INVALID_LEVEL);
3639 return;
3642 /* There should be 12 bytes of capabilities set. */
3643 if (total_data < 8) {
3644 reply_nterror(
3645 req,
3646 NT_STATUS_INVALID_PARAMETER);
3647 return;
3649 client_unix_major = SVAL(pdata,0);
3650 client_unix_minor = SVAL(pdata,2);
3651 client_unix_cap_low = IVAL(pdata,4);
3652 client_unix_cap_high = IVAL(pdata,8);
3653 /* Just print these values for now. */
3654 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3655 cap_low = 0x%x, cap_high = 0x%x\n",
3656 (unsigned int)client_unix_major,
3657 (unsigned int)client_unix_minor,
3658 (unsigned int)client_unix_cap_low,
3659 (unsigned int)client_unix_cap_high ));
3661 /* Here is where we must switch to posix pathname processing... */
3662 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3663 lp_set_posix_pathnames();
3664 mangle_change_to_posix();
3667 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3668 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3669 /* Client that knows how to do posix locks,
3670 * but not posix open/mkdir operations. Set a
3671 * default type for read/write checks. */
3673 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3676 break;
3679 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3681 NTSTATUS status;
3682 size_t param_len = 0;
3683 size_t data_len = total_data;
3685 if (!lp_unix_extensions()) {
3686 reply_nterror(
3687 req,
3688 NT_STATUS_INVALID_LEVEL);
3689 return;
3692 if (lp_smb_encrypt(SNUM(conn)) == false) {
3693 reply_nterror(
3694 req,
3695 NT_STATUS_NOT_SUPPORTED);
3696 return;
3699 if (req->sconn->smb1.echo_handler.trusted_fde) {
3700 DEBUG( 2,("call_trans2setfsinfo: "
3701 "request transport encryption disabled"
3702 "with 'fork echo handler = yes'\n"));
3703 reply_nterror(
3704 req,
3705 NT_STATUS_NOT_SUPPORTED);
3706 return;
3709 DEBUG( 4,("call_trans2setfsinfo: "
3710 "request transport encryption.\n"));
3712 status = srv_request_encryption_setup(conn,
3713 (unsigned char **)ppdata,
3714 &data_len,
3715 (unsigned char **)pparams,
3716 &param_len);
3718 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3719 !NT_STATUS_IS_OK(status)) {
3720 reply_nterror(req, status);
3721 return;
3724 send_trans2_replies(conn, req,
3725 *pparams,
3726 param_len,
3727 *ppdata,
3728 data_len,
3729 max_data_bytes);
3731 if (NT_STATUS_IS_OK(status)) {
3732 /* Server-side transport
3733 * encryption is now *on*. */
3734 status = srv_encryption_start(conn);
3735 if (!NT_STATUS_IS_OK(status)) {
3736 exit_server_cleanly(
3737 "Failure in setting "
3738 "up encrypted transport");
3741 return;
3744 case SMB_FS_QUOTA_INFORMATION:
3746 files_struct *fsp = NULL;
3747 SMB_NTQUOTA_STRUCT quotas;
3749 ZERO_STRUCT(quotas);
3751 /* access check */
3752 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3753 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3754 lp_servicename(SNUM(conn)),
3755 conn->session_info->unix_name));
3756 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3757 return;
3760 /* note: normaly there're 48 bytes,
3761 * but we didn't use the last 6 bytes for now
3762 * --metze
3764 fsp = file_fsp(req, SVAL(params,0));
3766 if (!check_fsp_ntquota_handle(conn, req,
3767 fsp)) {
3768 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3769 reply_nterror(
3770 req, NT_STATUS_INVALID_HANDLE);
3771 return;
3774 if (total_data < 42) {
3775 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3776 total_data));
3777 reply_nterror(
3778 req,
3779 NT_STATUS_INVALID_PARAMETER);
3780 return;
3783 /* unknown_1 24 NULL bytes in pdata*/
3785 /* the soft quotas 8 bytes (uint64_t)*/
3786 quotas.softlim = BVAL(pdata,24);
3788 /* the hard quotas 8 bytes (uint64_t)*/
3789 quotas.hardlim = BVAL(pdata,32);
3791 /* quota_flags 2 bytes **/
3792 quotas.qflags = SVAL(pdata,40);
3794 /* unknown_2 6 NULL bytes follow*/
3796 /* now set the quotas */
3797 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3798 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3799 reply_nterror(req, map_nt_error_from_unix(errno));
3800 return;
3803 break;
3805 default:
3806 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3807 info_level));
3808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3809 return;
3810 break;
3814 * sending this reply works fine,
3815 * but I'm not sure it's the same
3816 * like windows do...
3817 * --metze
3819 reply_outbuf(req, 10, 0);
3822 #if defined(HAVE_POSIX_ACLS)
3823 /****************************************************************************
3824 Utility function to count the number of entries in a POSIX acl.
3825 ****************************************************************************/
3827 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3829 unsigned int ace_count = 0;
3830 int entry_id = SMB_ACL_FIRST_ENTRY;
3831 SMB_ACL_ENTRY_T entry;
3833 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3834 /* get_next... */
3835 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3836 entry_id = SMB_ACL_NEXT_ENTRY;
3838 ace_count++;
3840 return ace_count;
3843 /****************************************************************************
3844 Utility function to marshall a POSIX acl into wire format.
3845 ****************************************************************************/
3847 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3849 int entry_id = SMB_ACL_FIRST_ENTRY;
3850 SMB_ACL_ENTRY_T entry;
3852 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3853 SMB_ACL_TAG_T tagtype;
3854 SMB_ACL_PERMSET_T permset;
3855 unsigned char perms = 0;
3856 unsigned int own_grp;
3858 /* get_next... */
3859 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3860 entry_id = SMB_ACL_NEXT_ENTRY;
3863 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3864 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3865 return False;
3868 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3869 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3870 return False;
3873 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3874 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3875 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3877 SCVAL(pdata,1,perms);
3879 switch (tagtype) {
3880 case SMB_ACL_USER_OBJ:
3881 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3882 own_grp = (unsigned int)pst->st_ex_uid;
3883 SIVAL(pdata,2,own_grp);
3884 SIVAL(pdata,6,0);
3885 break;
3886 case SMB_ACL_USER:
3888 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3889 if (!puid) {
3890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3891 return False;
3893 own_grp = (unsigned int)*puid;
3894 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3895 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3896 SIVAL(pdata,2,own_grp);
3897 SIVAL(pdata,6,0);
3898 break;
3900 case SMB_ACL_GROUP_OBJ:
3901 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3902 own_grp = (unsigned int)pst->st_ex_gid;
3903 SIVAL(pdata,2,own_grp);
3904 SIVAL(pdata,6,0);
3905 break;
3906 case SMB_ACL_GROUP:
3908 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3909 if (!pgid) {
3910 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3911 return False;
3913 own_grp = (unsigned int)*pgid;
3914 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3915 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3916 SIVAL(pdata,2,own_grp);
3917 SIVAL(pdata,6,0);
3918 break;
3920 case SMB_ACL_MASK:
3921 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3922 SIVAL(pdata,2,0xFFFFFFFF);
3923 SIVAL(pdata,6,0xFFFFFFFF);
3924 break;
3925 case SMB_ACL_OTHER:
3926 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3927 SIVAL(pdata,2,0xFFFFFFFF);
3928 SIVAL(pdata,6,0xFFFFFFFF);
3929 break;
3930 default:
3931 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3932 return False;
3934 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3937 return True;
3939 #endif
3941 /****************************************************************************
3942 Store the FILE_UNIX_BASIC info.
3943 ****************************************************************************/
3945 static char *store_file_unix_basic(connection_struct *conn,
3946 char *pdata,
3947 files_struct *fsp,
3948 const SMB_STRUCT_STAT *psbuf)
3950 uint64_t file_index = get_FileIndex(conn, psbuf);
3952 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3953 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3955 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3956 pdata += 8;
3958 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3959 pdata += 8;
3961 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3962 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3963 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3964 pdata += 24;
3966 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3967 SIVAL(pdata,4,0);
3968 pdata += 8;
3970 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3971 SIVAL(pdata,4,0);
3972 pdata += 8;
3974 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3975 pdata += 4;
3977 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3978 SIVAL(pdata,4,0);
3979 pdata += 8;
3981 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3982 SIVAL(pdata,4,0);
3983 pdata += 8;
3985 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3986 pdata += 8;
3988 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3989 SIVAL(pdata,4,0);
3990 pdata += 8;
3992 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3993 SIVAL(pdata,4,0);
3994 pdata += 8;
3996 return pdata;
3999 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4000 * the chflags(2) (or equivalent) flags.
4002 * XXX: this really should be behind the VFS interface. To do this, we would
4003 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4004 * Each VFS module could then implement its own mapping as appropriate for the
4005 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4007 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4008 info2_flags_map[] =
4010 #ifdef UF_NODUMP
4011 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4012 #endif
4014 #ifdef UF_IMMUTABLE
4015 { UF_IMMUTABLE, EXT_IMMUTABLE },
4016 #endif
4018 #ifdef UF_APPEND
4019 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4020 #endif
4022 #ifdef UF_HIDDEN
4023 { UF_HIDDEN, EXT_HIDDEN },
4024 #endif
4026 /* Do not remove. We need to guarantee that this array has at least one
4027 * entry to build on HP-UX.
4029 { 0, 0 }
4033 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4034 uint32 *smb_fflags, uint32 *smb_fmask)
4036 int i;
4038 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4039 *smb_fmask |= info2_flags_map[i].smb_fflag;
4040 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4041 *smb_fflags |= info2_flags_map[i].smb_fflag;
4046 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4047 const uint32 smb_fflags,
4048 const uint32 smb_fmask,
4049 int *stat_fflags)
4051 uint32 max_fmask = 0;
4052 int i;
4054 *stat_fflags = psbuf->st_ex_flags;
4056 /* For each flags requested in smb_fmask, check the state of the
4057 * corresponding flag in smb_fflags and set or clear the matching
4058 * stat flag.
4061 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4062 max_fmask |= info2_flags_map[i].smb_fflag;
4063 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4064 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4065 *stat_fflags |= info2_flags_map[i].stat_fflag;
4066 } else {
4067 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4072 /* If smb_fmask is asking to set any bits that are not supported by
4073 * our flag mappings, we should fail.
4075 if ((smb_fmask & max_fmask) != smb_fmask) {
4076 return False;
4079 return True;
4083 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4084 * of file flags and birth (create) time.
4086 static char *store_file_unix_basic_info2(connection_struct *conn,
4087 char *pdata,
4088 files_struct *fsp,
4089 const SMB_STRUCT_STAT *psbuf)
4091 uint32 file_flags = 0;
4092 uint32 flags_mask = 0;
4094 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4096 /* Create (birth) time 64 bit */
4097 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4098 pdata += 8;
4100 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4101 SIVAL(pdata, 0, file_flags); /* flags */
4102 SIVAL(pdata, 4, flags_mask); /* mask */
4103 pdata += 8;
4105 return pdata;
4108 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4109 const struct stream_struct *streams,
4110 char *data,
4111 unsigned int max_data_bytes,
4112 unsigned int *data_size)
4114 unsigned int i;
4115 unsigned int ofs = 0;
4117 for (i = 0; i < num_streams; i++) {
4118 unsigned int next_offset;
4119 size_t namelen;
4120 smb_ucs2_t *namebuf;
4122 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4123 streams[i].name, &namelen) ||
4124 namelen <= 2)
4126 return NT_STATUS_INVALID_PARAMETER;
4130 * name_buf is now null-terminated, we need to marshall as not
4131 * terminated
4134 namelen -= 2;
4137 * We cannot overflow ...
4139 if ((ofs + 24 + namelen) > max_data_bytes) {
4140 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4141 i));
4142 TALLOC_FREE(namebuf);
4143 return STATUS_BUFFER_OVERFLOW;
4146 SIVAL(data, ofs+4, namelen);
4147 SOFF_T(data, ofs+8, streams[i].size);
4148 SOFF_T(data, ofs+16, streams[i].alloc_size);
4149 memcpy(data+ofs+24, namebuf, namelen);
4150 TALLOC_FREE(namebuf);
4152 next_offset = ofs + 24 + namelen;
4154 if (i == num_streams-1) {
4155 SIVAL(data, ofs, 0);
4157 else {
4158 unsigned int align = ndr_align_size(next_offset, 8);
4160 if ((next_offset + align) > max_data_bytes) {
4161 DEBUG(10, ("refusing to overflow align "
4162 "reply at stream %u\n",
4163 i));
4164 TALLOC_FREE(namebuf);
4165 return STATUS_BUFFER_OVERFLOW;
4168 memset(data+next_offset, 0, align);
4169 next_offset += align;
4171 SIVAL(data, ofs, next_offset - ofs);
4172 ofs = next_offset;
4175 ofs = next_offset;
4178 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4180 *data_size = ofs;
4182 return NT_STATUS_OK;
4185 /****************************************************************************
4186 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4187 ****************************************************************************/
4189 static void call_trans2qpipeinfo(connection_struct *conn,
4190 struct smb_request *req,
4191 unsigned int tran_call,
4192 char **pparams, int total_params,
4193 char **ppdata, int total_data,
4194 unsigned int max_data_bytes)
4196 char *params = *pparams;
4197 char *pdata = *ppdata;
4198 unsigned int data_size = 0;
4199 unsigned int param_size = 2;
4200 uint16 info_level;
4201 files_struct *fsp;
4203 if (!params) {
4204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4205 return;
4208 if (total_params < 4) {
4209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4210 return;
4213 fsp = file_fsp(req, SVAL(params,0));
4214 if (!fsp_is_np(fsp)) {
4215 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4216 return;
4219 info_level = SVAL(params,2);
4221 *pparams = (char *)SMB_REALLOC(*pparams,2);
4222 if (*pparams == NULL) {
4223 reply_nterror(req, NT_STATUS_NO_MEMORY);
4224 return;
4226 params = *pparams;
4227 SSVAL(params,0,0);
4228 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4229 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4230 if (*ppdata == NULL ) {
4231 reply_nterror(req, NT_STATUS_NO_MEMORY);
4232 return;
4234 pdata = *ppdata;
4236 switch (info_level) {
4237 case SMB_FILE_STANDARD_INFORMATION:
4238 memset(pdata,0,24);
4239 SOFF_T(pdata,0,4096LL);
4240 SIVAL(pdata,16,1);
4241 SIVAL(pdata,20,1);
4242 data_size = 24;
4243 break;
4245 default:
4246 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4247 return;
4250 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4251 max_data_bytes);
4253 return;
4256 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4257 TALLOC_CTX *mem_ctx,
4258 uint16_t info_level,
4259 files_struct *fsp,
4260 struct smb_filename *smb_fname,
4261 bool delete_pending,
4262 struct timespec write_time_ts,
4263 struct ea_list *ea_list,
4264 int lock_data_count,
4265 char *lock_data,
4266 uint16_t flags2,
4267 unsigned int max_data_bytes,
4268 char **ppdata,
4269 unsigned int *pdata_size)
4271 char *pdata = *ppdata;
4272 char *dstart, *dend;
4273 unsigned int data_size;
4274 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4275 time_t create_time, mtime, atime, c_time;
4276 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4277 char *p;
4278 char *base_name;
4279 char *dos_fname;
4280 int mode;
4281 int nlink;
4282 NTSTATUS status;
4283 uint64_t file_size = 0;
4284 uint64_t pos = 0;
4285 uint64_t allocation_size = 0;
4286 uint64_t file_index = 0;
4287 uint32_t access_mask = 0;
4289 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4290 return NT_STATUS_INVALID_LEVEL;
4293 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4294 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4295 info_level, max_data_bytes));
4297 mode = dos_mode(conn, smb_fname);
4298 nlink = psbuf->st_ex_nlink;
4300 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4301 nlink = 1;
4304 if ((nlink > 0) && delete_pending) {
4305 nlink -= 1;
4308 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4309 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4310 if (*ppdata == NULL) {
4311 return NT_STATUS_NO_MEMORY;
4313 pdata = *ppdata;
4314 dstart = pdata;
4315 dend = dstart + data_size - 1;
4317 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4318 update_stat_ex_mtime(psbuf, write_time_ts);
4321 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4322 mtime_ts = psbuf->st_ex_mtime;
4323 atime_ts = psbuf->st_ex_atime;
4324 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4326 if (lp_dos_filetime_resolution(SNUM(conn))) {
4327 dos_filetime_timespec(&create_time_ts);
4328 dos_filetime_timespec(&mtime_ts);
4329 dos_filetime_timespec(&atime_ts);
4330 dos_filetime_timespec(&ctime_ts);
4333 create_time = convert_timespec_to_time_t(create_time_ts);
4334 mtime = convert_timespec_to_time_t(mtime_ts);
4335 atime = convert_timespec_to_time_t(atime_ts);
4336 c_time = convert_timespec_to_time_t(ctime_ts);
4338 p = strrchr_m(smb_fname->base_name,'/');
4339 if (!p)
4340 base_name = smb_fname->base_name;
4341 else
4342 base_name = p+1;
4344 /* NT expects the name to be in an exact form of the *full*
4345 filename. See the trans2 torture test */
4346 if (ISDOT(base_name)) {
4347 dos_fname = talloc_strdup(mem_ctx, "\\");
4348 if (!dos_fname) {
4349 return NT_STATUS_NO_MEMORY;
4351 } else {
4352 dos_fname = talloc_asprintf(mem_ctx,
4353 "\\%s",
4354 smb_fname->base_name);
4355 if (!dos_fname) {
4356 return NT_STATUS_NO_MEMORY;
4358 if (is_ntfs_stream_smb_fname(smb_fname)) {
4359 dos_fname = talloc_asprintf(dos_fname, "%s",
4360 smb_fname->stream_name);
4361 if (!dos_fname) {
4362 return NT_STATUS_NO_MEMORY;
4366 string_replace(dos_fname, '/', '\\');
4369 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4371 if (!fsp) {
4372 /* Do we have this path open ? */
4373 files_struct *fsp1;
4374 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4375 fsp1 = file_find_di_first(conn->sconn, fileid);
4376 if (fsp1 && fsp1->initial_allocation_size) {
4377 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4381 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4382 file_size = get_file_size_stat(psbuf);
4385 if (fsp) {
4386 pos = fsp->fh->position_information;
4389 if (fsp) {
4390 access_mask = fsp->access_mask;
4391 } else {
4392 /* GENERIC_EXECUTE mapping from Windows */
4393 access_mask = 0x12019F;
4396 /* This should be an index number - looks like
4397 dev/ino to me :-)
4399 I think this causes us to fail the IFSKIT
4400 BasicFileInformationTest. -tpot */
4401 file_index = get_FileIndex(conn, psbuf);
4403 switch (info_level) {
4404 case SMB_INFO_STANDARD:
4405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4406 data_size = 22;
4407 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4408 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4409 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4410 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4411 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4412 SSVAL(pdata,l1_attrFile,mode);
4413 break;
4415 case SMB_INFO_QUERY_EA_SIZE:
4417 unsigned int ea_size =
4418 estimate_ea_size(conn, fsp,
4419 smb_fname->base_name);
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4421 data_size = 26;
4422 srv_put_dos_date2(pdata,0,create_time);
4423 srv_put_dos_date2(pdata,4,atime);
4424 srv_put_dos_date2(pdata,8,mtime); /* write time */
4425 SIVAL(pdata,12,(uint32)file_size);
4426 SIVAL(pdata,16,(uint32)allocation_size);
4427 SSVAL(pdata,20,mode);
4428 SIVAL(pdata,22,ea_size);
4429 break;
4432 case SMB_INFO_IS_NAME_VALID:
4433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4434 if (fsp) {
4435 /* os/2 needs this ? really ?*/
4436 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4438 /* This is only reached for qpathinfo */
4439 data_size = 0;
4440 break;
4442 case SMB_INFO_QUERY_EAS_FROM_LIST:
4444 size_t total_ea_len = 0;
4445 struct ea_list *ea_file_list = NULL;
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4449 ea_file_list =
4450 get_ea_list_from_file(mem_ctx, conn, fsp,
4451 smb_fname->base_name,
4452 &total_ea_len);
4453 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4455 if (!ea_list || (total_ea_len > data_size)) {
4456 data_size = 4;
4457 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4458 break;
4461 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4462 break;
4465 case SMB_INFO_QUERY_ALL_EAS:
4467 /* We have data_size bytes to put EA's into. */
4468 size_t total_ea_len = 0;
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4472 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4473 smb_fname->base_name,
4474 &total_ea_len);
4475 if (!ea_list || (total_ea_len > data_size)) {
4476 data_size = 4;
4477 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4478 break;
4481 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4482 break;
4485 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4487 /* This is FileFullEaInformation - 0xF which maps to
4488 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4490 /* We have data_size bytes to put EA's into. */
4491 size_t total_ea_len = 0;
4492 struct ea_list *ea_file_list = NULL;
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4496 /*TODO: add filtering and index handling */
4498 ea_file_list =
4499 get_ea_list_from_file(mem_ctx, conn, fsp,
4500 smb_fname->base_name,
4501 &total_ea_len);
4502 if (!ea_file_list) {
4503 return NT_STATUS_NO_EAS_ON_FILE;
4506 status = fill_ea_chained_buffer(mem_ctx,
4507 pdata,
4508 data_size,
4509 &data_size,
4510 conn, ea_file_list);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 return status;
4514 break;
4517 case SMB_FILE_BASIC_INFORMATION:
4518 case SMB_QUERY_FILE_BASIC_INFO:
4520 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4522 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4523 } else {
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4525 data_size = 40;
4526 SIVAL(pdata,36,0);
4528 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4529 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4530 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4531 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4532 SIVAL(pdata,32,mode);
4534 DEBUG(5,("SMB_QFBI - "));
4535 DEBUG(5,("create: %s ", ctime(&create_time)));
4536 DEBUG(5,("access: %s ", ctime(&atime)));
4537 DEBUG(5,("write: %s ", ctime(&mtime)));
4538 DEBUG(5,("change: %s ", ctime(&c_time)));
4539 DEBUG(5,("mode: %x\n", mode));
4540 break;
4542 case SMB_FILE_STANDARD_INFORMATION:
4543 case SMB_QUERY_FILE_STANDARD_INFO:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4546 data_size = 24;
4547 SOFF_T(pdata,0,allocation_size);
4548 SOFF_T(pdata,8,file_size);
4549 SIVAL(pdata,16,nlink);
4550 SCVAL(pdata,20,delete_pending?1:0);
4551 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4552 SSVAL(pdata,22,0); /* Padding. */
4553 break;
4555 case SMB_FILE_EA_INFORMATION:
4556 case SMB_QUERY_FILE_EA_INFO:
4558 unsigned int ea_size =
4559 estimate_ea_size(conn, fsp, smb_fname->base_name);
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4561 data_size = 4;
4562 SIVAL(pdata,0,ea_size);
4563 break;
4566 /* Get the 8.3 name - used if NT SMB was negotiated. */
4567 case SMB_QUERY_FILE_ALT_NAME_INFO:
4568 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4570 int len;
4571 char mangled_name[13];
4572 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4573 if (!name_to_8_3(base_name,mangled_name,
4574 True,conn->params)) {
4575 return NT_STATUS_NO_MEMORY;
4577 len = srvstr_push(dstart, flags2,
4578 pdata+4, mangled_name,
4579 PTR_DIFF(dend, pdata+4),
4580 STR_UNICODE);
4581 data_size = 4 + len;
4582 SIVAL(pdata,0,len);
4583 break;
4586 case SMB_QUERY_FILE_NAME_INFO:
4588 int len;
4590 this must be *exactly* right for ACLs on mapped drives to work
4592 len = srvstr_push(dstart, flags2,
4593 pdata+4, dos_fname,
4594 PTR_DIFF(dend, pdata+4),
4595 STR_UNICODE);
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4597 data_size = 4 + len;
4598 SIVAL(pdata,0,len);
4599 break;
4602 case SMB_FILE_ALLOCATION_INFORMATION:
4603 case SMB_QUERY_FILE_ALLOCATION_INFO:
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4605 data_size = 8;
4606 SOFF_T(pdata,0,allocation_size);
4607 break;
4609 case SMB_FILE_END_OF_FILE_INFORMATION:
4610 case SMB_QUERY_FILE_END_OF_FILEINFO:
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4612 data_size = 8;
4613 SOFF_T(pdata,0,file_size);
4614 break;
4616 case SMB_QUERY_FILE_ALL_INFO:
4617 case SMB_FILE_ALL_INFORMATION:
4619 int len;
4620 unsigned int ea_size =
4621 estimate_ea_size(conn, fsp, smb_fname->base_name);
4622 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4623 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4624 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4625 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4626 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4627 SIVAL(pdata,32,mode);
4628 SIVAL(pdata,36,0); /* padding. */
4629 pdata += 40;
4630 SOFF_T(pdata,0,allocation_size);
4631 SOFF_T(pdata,8,file_size);
4632 SIVAL(pdata,16,nlink);
4633 SCVAL(pdata,20,delete_pending);
4634 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4635 SSVAL(pdata,22,0);
4636 pdata += 24;
4637 SIVAL(pdata,0,ea_size);
4638 pdata += 4; /* EA info */
4639 len = srvstr_push(dstart, flags2,
4640 pdata+4, dos_fname,
4641 PTR_DIFF(dend, pdata+4),
4642 STR_UNICODE);
4643 SIVAL(pdata,0,len);
4644 pdata += 4 + len;
4645 data_size = PTR_DIFF(pdata,(*ppdata));
4646 break;
4649 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4651 int len;
4652 unsigned int ea_size =
4653 estimate_ea_size(conn, fsp, smb_fname->base_name);
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4655 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4656 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4657 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4658 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4659 SIVAL(pdata, 0x20, mode);
4660 SIVAL(pdata, 0x24, 0); /* padding. */
4661 SBVAL(pdata, 0x28, allocation_size);
4662 SBVAL(pdata, 0x30, file_size);
4663 SIVAL(pdata, 0x38, nlink);
4664 SCVAL(pdata, 0x3C, delete_pending);
4665 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4666 SSVAL(pdata, 0x3E, 0); /* padding */
4667 SBVAL(pdata, 0x40, file_index);
4668 SIVAL(pdata, 0x48, ea_size);
4669 SIVAL(pdata, 0x4C, access_mask);
4670 SBVAL(pdata, 0x50, pos);
4671 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4672 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4674 pdata += 0x60;
4676 len = srvstr_push(dstart, flags2,
4677 pdata+4, dos_fname,
4678 PTR_DIFF(dend, pdata+4),
4679 STR_UNICODE);
4680 SIVAL(pdata,0,len);
4681 pdata += 4 + len;
4682 data_size = PTR_DIFF(pdata,(*ppdata));
4683 break;
4685 case SMB_FILE_INTERNAL_INFORMATION:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4688 SBVAL(pdata, 0, file_index);
4689 data_size = 8;
4690 break;
4692 case SMB_FILE_ACCESS_INFORMATION:
4693 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4694 SIVAL(pdata, 0, access_mask);
4695 data_size = 4;
4696 break;
4698 case SMB_FILE_NAME_INFORMATION:
4699 /* Pathname with leading '\'. */
4701 size_t byte_len;
4702 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4703 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4704 SIVAL(pdata,0,byte_len);
4705 data_size = 4 + byte_len;
4706 break;
4709 case SMB_FILE_DISPOSITION_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4711 data_size = 1;
4712 SCVAL(pdata,0,delete_pending);
4713 break;
4715 case SMB_FILE_POSITION_INFORMATION:
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4717 data_size = 8;
4718 SOFF_T(pdata,0,pos);
4719 break;
4721 case SMB_FILE_MODE_INFORMATION:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4723 SIVAL(pdata,0,mode);
4724 data_size = 4;
4725 break;
4727 case SMB_FILE_ALIGNMENT_INFORMATION:
4728 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4729 SIVAL(pdata,0,0); /* No alignment needed. */
4730 data_size = 4;
4731 break;
4734 * NT4 server just returns "invalid query" to this - if we try
4735 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4736 * want this. JRA.
4738 /* The first statement above is false - verified using Thursby
4739 * client against NT4 -- gcolley.
4741 case SMB_QUERY_FILE_STREAM_INFO:
4742 case SMB_FILE_STREAM_INFORMATION: {
4743 unsigned int num_streams = 0;
4744 struct stream_struct *streams = NULL;
4746 DEBUG(10,("smbd_do_qfilepathinfo: "
4747 "SMB_FILE_STREAM_INFORMATION\n"));
4749 if (is_ntfs_stream_smb_fname(smb_fname)) {
4750 return NT_STATUS_INVALID_PARAMETER;
4753 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4754 talloc_tos(), &num_streams, &streams);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 DEBUG(10, ("could not get stream info: %s\n",
4758 nt_errstr(status)));
4759 return status;
4762 status = marshall_stream_info(num_streams, streams,
4763 pdata, max_data_bytes,
4764 &data_size);
4766 if (!NT_STATUS_IS_OK(status)) {
4767 DEBUG(10, ("marshall_stream_info failed: %s\n",
4768 nt_errstr(status)));
4769 TALLOC_FREE(streams);
4770 return status;
4773 TALLOC_FREE(streams);
4775 break;
4777 case SMB_QUERY_COMPRESSION_INFO:
4778 case SMB_FILE_COMPRESSION_INFORMATION:
4779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4780 SOFF_T(pdata,0,file_size);
4781 SIVAL(pdata,8,0); /* ??? */
4782 SIVAL(pdata,12,0); /* ??? */
4783 data_size = 16;
4784 break;
4786 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4787 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4788 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4789 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4790 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4791 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4792 SOFF_T(pdata,32,allocation_size);
4793 SOFF_T(pdata,40,file_size);
4794 SIVAL(pdata,48,mode);
4795 SIVAL(pdata,52,0); /* ??? */
4796 data_size = 56;
4797 break;
4799 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4800 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4801 SIVAL(pdata,0,mode);
4802 SIVAL(pdata,4,0);
4803 data_size = 8;
4804 break;
4807 * CIFS UNIX Extensions.
4810 case SMB_QUERY_FILE_UNIX_BASIC:
4812 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4813 data_size = PTR_DIFF(pdata,(*ppdata));
4815 DEBUG(4,("smbd_do_qfilepathinfo: "
4816 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4817 dump_data(4, (uint8_t *)(*ppdata), data_size);
4819 break;
4821 case SMB_QUERY_FILE_UNIX_INFO2:
4823 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4824 data_size = PTR_DIFF(pdata,(*ppdata));
4827 int i;
4828 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4830 for (i=0; i<100; i++)
4831 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4832 DEBUG(4,("\n"));
4835 break;
4837 case SMB_QUERY_FILE_UNIX_LINK:
4839 int len;
4840 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4842 if (!buffer) {
4843 return NT_STATUS_NO_MEMORY;
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4847 #ifdef S_ISLNK
4848 if(!S_ISLNK(psbuf->st_ex_mode)) {
4849 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4851 #else
4852 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4853 #endif
4854 len = SMB_VFS_READLINK(conn,
4855 smb_fname->base_name,
4856 buffer, PATH_MAX);
4857 if (len == -1) {
4858 return map_nt_error_from_unix(errno);
4860 buffer[len] = 0;
4861 len = srvstr_push(dstart, flags2,
4862 pdata, buffer,
4863 PTR_DIFF(dend, pdata),
4864 STR_TERMINATE);
4865 pdata += len;
4866 data_size = PTR_DIFF(pdata,(*ppdata));
4868 break;
4871 #if defined(HAVE_POSIX_ACLS)
4872 case SMB_QUERY_POSIX_ACL:
4874 SMB_ACL_T file_acl = NULL;
4875 SMB_ACL_T def_acl = NULL;
4876 uint16 num_file_acls = 0;
4877 uint16 num_def_acls = 0;
4879 if (fsp && fsp->fh->fd != -1) {
4880 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4881 } else {
4882 file_acl =
4883 SMB_VFS_SYS_ACL_GET_FILE(conn,
4884 smb_fname->base_name,
4885 SMB_ACL_TYPE_ACCESS);
4888 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4889 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4890 "not implemented on "
4891 "filesystem containing %s\n",
4892 smb_fname->base_name));
4893 return NT_STATUS_NOT_IMPLEMENTED;
4896 if (S_ISDIR(psbuf->st_ex_mode)) {
4897 if (fsp && fsp->is_directory) {
4898 def_acl =
4899 SMB_VFS_SYS_ACL_GET_FILE(
4900 conn,
4901 fsp->fsp_name->base_name,
4902 SMB_ACL_TYPE_DEFAULT);
4903 } else {
4904 def_acl =
4905 SMB_VFS_SYS_ACL_GET_FILE(
4906 conn,
4907 smb_fname->base_name,
4908 SMB_ACL_TYPE_DEFAULT);
4910 def_acl = free_empty_sys_acl(conn, def_acl);
4913 num_file_acls = count_acl_entries(conn, file_acl);
4914 num_def_acls = count_acl_entries(conn, def_acl);
4916 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4917 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4918 data_size,
4919 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4920 SMB_POSIX_ACL_HEADER_SIZE) ));
4921 if (file_acl) {
4922 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4924 if (def_acl) {
4925 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4927 return NT_STATUS_BUFFER_TOO_SMALL;
4930 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4931 SSVAL(pdata,2,num_file_acls);
4932 SSVAL(pdata,4,num_def_acls);
4933 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4934 if (file_acl) {
4935 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4937 if (def_acl) {
4938 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4940 return NT_STATUS_INTERNAL_ERROR;
4942 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4943 if (file_acl) {
4944 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4946 if (def_acl) {
4947 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4949 return NT_STATUS_INTERNAL_ERROR;
4952 if (file_acl) {
4953 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4955 if (def_acl) {
4956 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4958 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4959 break;
4961 #endif
4964 case SMB_QUERY_POSIX_LOCK:
4966 uint64_t count;
4967 uint64_t offset;
4968 uint64_t smblctx;
4969 enum brl_type lock_type;
4971 /* We need an open file with a real fd for this. */
4972 if (!fsp || fsp->fh->fd == -1) {
4973 return NT_STATUS_INVALID_LEVEL;
4976 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4977 return NT_STATUS_INVALID_PARAMETER;
4980 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4981 case POSIX_LOCK_TYPE_READ:
4982 lock_type = READ_LOCK;
4983 break;
4984 case POSIX_LOCK_TYPE_WRITE:
4985 lock_type = WRITE_LOCK;
4986 break;
4987 case POSIX_LOCK_TYPE_UNLOCK:
4988 default:
4989 /* There's no point in asking for an unlock... */
4990 return NT_STATUS_INVALID_PARAMETER;
4993 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4994 #if defined(HAVE_LONGLONG)
4995 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4996 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4997 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4998 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4999 #else /* HAVE_LONGLONG */
5000 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5001 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5002 #endif /* HAVE_LONGLONG */
5004 status = query_lock(fsp,
5005 &smblctx,
5006 &count,
5007 &offset,
5008 &lock_type,
5009 POSIX_LOCK);
5011 if (ERROR_WAS_LOCK_DENIED(status)) {
5012 /* Here we need to report who has it locked... */
5013 data_size = POSIX_LOCK_DATA_SIZE;
5015 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5016 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5017 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5018 #if defined(HAVE_LONGLONG)
5019 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5020 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5021 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5022 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5023 #else /* HAVE_LONGLONG */
5024 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5025 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5026 #endif /* HAVE_LONGLONG */
5028 } else if (NT_STATUS_IS_OK(status)) {
5029 /* For success we just return a copy of what we sent
5030 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5031 data_size = POSIX_LOCK_DATA_SIZE;
5032 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5033 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5034 } else {
5035 return status;
5037 break;
5040 default:
5041 return NT_STATUS_INVALID_LEVEL;
5044 *pdata_size = data_size;
5045 return NT_STATUS_OK;
5048 /****************************************************************************
5049 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5050 file name or file id).
5051 ****************************************************************************/
5053 static void call_trans2qfilepathinfo(connection_struct *conn,
5054 struct smb_request *req,
5055 unsigned int tran_call,
5056 char **pparams, int total_params,
5057 char **ppdata, int total_data,
5058 unsigned int max_data_bytes)
5060 char *params = *pparams;
5061 char *pdata = *ppdata;
5062 uint16 info_level;
5063 unsigned int data_size = 0;
5064 unsigned int param_size = 2;
5065 struct smb_filename *smb_fname = NULL;
5066 bool delete_pending = False;
5067 struct timespec write_time_ts;
5068 files_struct *fsp = NULL;
5069 struct file_id fileid;
5070 struct ea_list *ea_list = NULL;
5071 int lock_data_count = 0;
5072 char *lock_data = NULL;
5073 NTSTATUS status = NT_STATUS_OK;
5075 if (!params) {
5076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5077 return;
5080 ZERO_STRUCT(write_time_ts);
5082 if (tran_call == TRANSACT2_QFILEINFO) {
5083 if (total_params < 4) {
5084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5085 return;
5088 if (IS_IPC(conn)) {
5089 call_trans2qpipeinfo(conn, req, tran_call,
5090 pparams, total_params,
5091 ppdata, total_data,
5092 max_data_bytes);
5093 return;
5096 fsp = file_fsp(req, SVAL(params,0));
5097 info_level = SVAL(params,2);
5099 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5101 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5102 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5103 return;
5106 /* Initial check for valid fsp ptr. */
5107 if (!check_fsp_open(conn, req, fsp)) {
5108 return;
5111 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5112 &smb_fname);
5113 if (!NT_STATUS_IS_OK(status)) {
5114 reply_nterror(req, status);
5115 return;
5118 if(fsp->fake_file_handle) {
5120 * This is actually for the QUOTA_FAKE_FILE --metze
5123 /* We know this name is ok, it's already passed the checks. */
5125 } else if(fsp->fh->fd == -1) {
5127 * This is actually a QFILEINFO on a directory
5128 * handle (returned from an NT SMB). NT5.0 seems
5129 * to do this call. JRA.
5132 if (INFO_LEVEL_IS_UNIX(info_level)) {
5133 /* Always do lstat for UNIX calls. */
5134 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5135 DEBUG(3,("call_trans2qfilepathinfo: "
5136 "SMB_VFS_LSTAT of %s failed "
5137 "(%s)\n",
5138 smb_fname_str_dbg(smb_fname),
5139 strerror(errno)));
5140 reply_nterror(req,
5141 map_nt_error_from_unix(errno));
5142 return;
5144 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5145 DEBUG(3,("call_trans2qfilepathinfo: "
5146 "SMB_VFS_STAT of %s failed (%s)\n",
5147 smb_fname_str_dbg(smb_fname),
5148 strerror(errno)));
5149 reply_nterror(req,
5150 map_nt_error_from_unix(errno));
5151 return;
5154 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5155 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5156 } else {
5158 * Original code - this is an open file.
5160 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5161 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5162 fsp->fnum, strerror(errno)));
5163 reply_nterror(req,
5164 map_nt_error_from_unix(errno));
5165 return;
5167 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5168 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5171 } else {
5172 uint32_t name_hash;
5173 char *fname = NULL;
5174 uint32_t ucf_flags = 0;
5176 /* qpathinfo */
5177 if (total_params < 7) {
5178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5179 return;
5182 info_level = SVAL(params,0);
5184 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5186 if (INFO_LEVEL_IS_UNIX(info_level)) {
5187 if (!lp_unix_extensions()) {
5188 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5189 return;
5191 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5192 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5193 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5194 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5198 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5199 total_params - 6,
5200 STR_TERMINATE, &status);
5201 if (!NT_STATUS_IS_OK(status)) {
5202 reply_nterror(req, status);
5203 return;
5206 status = filename_convert(req,
5207 conn,
5208 req->flags2 & FLAGS2_DFS_PATHNAMES,
5209 fname,
5210 ucf_flags,
5211 NULL,
5212 &smb_fname);
5213 if (!NT_STATUS_IS_OK(status)) {
5214 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5215 reply_botherror(req,
5216 NT_STATUS_PATH_NOT_COVERED,
5217 ERRSRV, ERRbadpath);
5218 return;
5220 reply_nterror(req, status);
5221 return;
5224 /* If this is a stream, check if there is a delete_pending. */
5225 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5226 && is_ntfs_stream_smb_fname(smb_fname)) {
5227 struct smb_filename *smb_fname_base = NULL;
5229 /* Create an smb_filename with stream_name == NULL. */
5230 status =
5231 create_synthetic_smb_fname(talloc_tos(),
5232 smb_fname->base_name,
5233 NULL, NULL,
5234 &smb_fname_base);
5235 if (!NT_STATUS_IS_OK(status)) {
5236 reply_nterror(req, status);
5237 return;
5240 if (INFO_LEVEL_IS_UNIX(info_level)) {
5241 /* Always do lstat for UNIX calls. */
5242 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5243 DEBUG(3,("call_trans2qfilepathinfo: "
5244 "SMB_VFS_LSTAT of %s failed "
5245 "(%s)\n",
5246 smb_fname_str_dbg(smb_fname_base),
5247 strerror(errno)));
5248 TALLOC_FREE(smb_fname_base);
5249 reply_nterror(req,
5250 map_nt_error_from_unix(errno));
5251 return;
5253 } else {
5254 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5255 DEBUG(3,("call_trans2qfilepathinfo: "
5256 "fileinfo of %s failed "
5257 "(%s)\n",
5258 smb_fname_str_dbg(smb_fname_base),
5259 strerror(errno)));
5260 TALLOC_FREE(smb_fname_base);
5261 reply_nterror(req,
5262 map_nt_error_from_unix(errno));
5263 return;
5267 status = file_name_hash(conn,
5268 smb_fname_str_dbg(smb_fname_base),
5269 &name_hash);
5270 if (!NT_STATUS_IS_OK(status)) {
5271 TALLOC_FREE(smb_fname_base);
5272 reply_nterror(req, status);
5273 return;
5276 fileid = vfs_file_id_from_sbuf(conn,
5277 &smb_fname_base->st);
5278 TALLOC_FREE(smb_fname_base);
5279 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5280 if (delete_pending) {
5281 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5282 return;
5286 if (INFO_LEVEL_IS_UNIX(info_level)) {
5287 /* Always do lstat for UNIX calls. */
5288 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5289 DEBUG(3,("call_trans2qfilepathinfo: "
5290 "SMB_VFS_LSTAT of %s failed (%s)\n",
5291 smb_fname_str_dbg(smb_fname),
5292 strerror(errno)));
5293 reply_nterror(req,
5294 map_nt_error_from_unix(errno));
5295 return;
5298 } else {
5299 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5300 DEBUG(3,("call_trans2qfilepathinfo: "
5301 "SMB_VFS_STAT of %s failed (%s)\n",
5302 smb_fname_str_dbg(smb_fname),
5303 strerror(errno)));
5304 reply_nterror(req,
5305 map_nt_error_from_unix(errno));
5306 return;
5310 status = file_name_hash(conn,
5311 smb_fname_str_dbg(smb_fname),
5312 &name_hash);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 reply_nterror(req, status);
5315 return;
5318 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5319 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5320 if (delete_pending) {
5321 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5322 return;
5326 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5327 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5328 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5330 /* Pull out any data sent here before we realloc. */
5331 switch (info_level) {
5332 case SMB_INFO_QUERY_EAS_FROM_LIST:
5334 /* Pull any EA list from the data portion. */
5335 uint32 ea_size;
5337 if (total_data < 4) {
5338 reply_nterror(
5339 req, NT_STATUS_INVALID_PARAMETER);
5340 return;
5342 ea_size = IVAL(pdata,0);
5344 if (total_data > 0 && ea_size != total_data) {
5345 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5346 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5347 reply_nterror(
5348 req, NT_STATUS_INVALID_PARAMETER);
5349 return;
5352 if (!lp_ea_support(SNUM(conn))) {
5353 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5354 return;
5357 /* Pull out the list of names. */
5358 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5359 if (!ea_list) {
5360 reply_nterror(
5361 req, NT_STATUS_INVALID_PARAMETER);
5362 return;
5364 break;
5367 case SMB_QUERY_POSIX_LOCK:
5369 if (fsp == NULL || fsp->fh->fd == -1) {
5370 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5371 return;
5374 if (total_data != POSIX_LOCK_DATA_SIZE) {
5375 reply_nterror(
5376 req, NT_STATUS_INVALID_PARAMETER);
5377 return;
5380 /* Copy the lock range data. */
5381 lock_data = (char *)TALLOC_MEMDUP(
5382 req, pdata, total_data);
5383 if (!lock_data) {
5384 reply_nterror(req, NT_STATUS_NO_MEMORY);
5385 return;
5387 lock_data_count = total_data;
5389 default:
5390 break;
5393 *pparams = (char *)SMB_REALLOC(*pparams,2);
5394 if (*pparams == NULL) {
5395 reply_nterror(req, NT_STATUS_NO_MEMORY);
5396 return;
5398 params = *pparams;
5399 SSVAL(params,0,0);
5402 * draft-leach-cifs-v1-spec-02.txt
5403 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5404 * says:
5406 * The requested information is placed in the Data portion of the
5407 * transaction response. For the information levels greater than 0x100,
5408 * the transaction response has 1 parameter word which should be
5409 * ignored by the client.
5411 * However Windows only follows this rule for the IS_NAME_VALID call.
5413 switch (info_level) {
5414 case SMB_INFO_IS_NAME_VALID:
5415 param_size = 0;
5416 break;
5419 if ((info_level & 0xFF00) == 0xFF00) {
5421 * We use levels that start with 0xFF00
5422 * internally to represent SMB2 specific levels
5424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5425 return;
5428 status = smbd_do_qfilepathinfo(conn, req, info_level,
5429 fsp, smb_fname,
5430 delete_pending, write_time_ts,
5431 ea_list,
5432 lock_data_count, lock_data,
5433 req->flags2, max_data_bytes,
5434 ppdata, &data_size);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 reply_nterror(req, status);
5437 return;
5440 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5441 max_data_bytes);
5443 return;
5446 /****************************************************************************
5447 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5448 code.
5449 ****************************************************************************/
5451 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5452 connection_struct *conn,
5453 struct smb_request *req,
5454 bool overwrite_if_exists,
5455 const struct smb_filename *smb_fname_old,
5456 struct smb_filename *smb_fname_new)
5458 NTSTATUS status = NT_STATUS_OK;
5460 /* source must already exist. */
5461 if (!VALID_STAT(smb_fname_old->st)) {
5462 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5465 if (VALID_STAT(smb_fname_new->st)) {
5466 if (overwrite_if_exists) {
5467 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5468 return NT_STATUS_FILE_IS_A_DIRECTORY;
5470 status = unlink_internals(conn,
5471 req,
5472 FILE_ATTRIBUTE_NORMAL,
5473 smb_fname_new,
5474 false);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 return status;
5478 } else {
5479 /* Disallow if newname already exists. */
5480 return NT_STATUS_OBJECT_NAME_COLLISION;
5484 /* No links from a directory. */
5485 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5486 return NT_STATUS_FILE_IS_A_DIRECTORY;
5489 /* Setting a hardlink to/from a stream isn't currently supported. */
5490 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5491 is_ntfs_stream_smb_fname(smb_fname_new)) {
5492 return NT_STATUS_INVALID_PARAMETER;
5495 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5496 smb_fname_old->base_name, smb_fname_new->base_name));
5498 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5499 smb_fname_new->base_name) != 0) {
5500 status = map_nt_error_from_unix(errno);
5501 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5502 nt_errstr(status), smb_fname_old->base_name,
5503 smb_fname_new->base_name));
5505 return status;
5508 /****************************************************************************
5509 Deal with setting the time from any of the setfilepathinfo functions.
5510 ****************************************************************************/
5512 NTSTATUS smb_set_file_time(connection_struct *conn,
5513 files_struct *fsp,
5514 const struct smb_filename *smb_fname,
5515 struct smb_file_time *ft,
5516 bool setting_write_time)
5518 struct smb_filename smb_fname_base;
5519 uint32 action =
5520 FILE_NOTIFY_CHANGE_LAST_ACCESS
5521 |FILE_NOTIFY_CHANGE_LAST_WRITE
5522 |FILE_NOTIFY_CHANGE_CREATION;
5524 if (!VALID_STAT(smb_fname->st)) {
5525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5528 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5529 return NT_STATUS_ACCESS_DENIED;
5532 /* get some defaults (no modifications) if any info is zero or -1. */
5533 if (null_timespec(ft->create_time)) {
5534 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5537 if (null_timespec(ft->atime)) {
5538 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5541 if (null_timespec(ft->mtime)) {
5542 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5545 if (!setting_write_time) {
5546 /* ft->mtime comes from change time, not write time. */
5547 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5550 /* Ensure the resolution is the correct for
5551 * what we can store on this filesystem. */
5553 round_timespec(conn->ts_res, &ft->create_time);
5554 round_timespec(conn->ts_res, &ft->ctime);
5555 round_timespec(conn->ts_res, &ft->atime);
5556 round_timespec(conn->ts_res, &ft->mtime);
5558 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5560 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5561 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5562 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5563 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5564 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5565 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5567 if (setting_write_time) {
5569 * This was a Windows setfileinfo on an open file.
5570 * NT does this a lot. We also need to
5571 * set the time here, as it can be read by
5572 * FindFirst/FindNext and with the patch for bug #2045
5573 * in smbd/fileio.c it ensures that this timestamp is
5574 * kept sticky even after a write. We save the request
5575 * away and will set it on file close and after a write. JRA.
5578 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5579 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5581 if (fsp != NULL) {
5582 if (fsp->base_fsp) {
5583 set_sticky_write_time_fsp(fsp->base_fsp,
5584 ft->mtime);
5585 } else {
5586 set_sticky_write_time_fsp(fsp, ft->mtime);
5588 } else {
5589 set_sticky_write_time_path(
5590 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5591 ft->mtime);
5595 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5597 /* Always call ntimes on the base, even if a stream was passed in. */
5598 smb_fname_base = *smb_fname;
5599 smb_fname_base.stream_name = NULL;
5601 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5602 return map_nt_error_from_unix(errno);
5605 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5606 smb_fname->base_name);
5607 return NT_STATUS_OK;
5610 /****************************************************************************
5611 Deal with setting the dosmode from any of the setfilepathinfo functions.
5612 ****************************************************************************/
5614 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5615 const struct smb_filename *smb_fname,
5616 uint32 dosmode)
5618 struct smb_filename *smb_fname_base = NULL;
5619 NTSTATUS status;
5621 if (!VALID_STAT(smb_fname->st)) {
5622 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5625 /* Always operate on the base_name, even if a stream was passed in. */
5626 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5627 NULL, &smb_fname->st,
5628 &smb_fname_base);
5629 if (!NT_STATUS_IS_OK(status)) {
5630 return status;
5633 if (dosmode) {
5634 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5635 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5636 } else {
5637 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5641 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5643 /* check the mode isn't different, before changing it */
5644 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5645 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5646 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5647 (unsigned int)dosmode));
5649 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5650 false)) {
5651 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5652 "%s failed (%s)\n",
5653 smb_fname_str_dbg(smb_fname_base),
5654 strerror(errno)));
5655 status = map_nt_error_from_unix(errno);
5656 goto out;
5659 status = NT_STATUS_OK;
5660 out:
5661 TALLOC_FREE(smb_fname_base);
5662 return status;
5665 /****************************************************************************
5666 Deal with setting the size from any of the setfilepathinfo functions.
5667 ****************************************************************************/
5669 static NTSTATUS smb_set_file_size(connection_struct *conn,
5670 struct smb_request *req,
5671 files_struct *fsp,
5672 const struct smb_filename *smb_fname,
5673 const SMB_STRUCT_STAT *psbuf,
5674 SMB_OFF_T size,
5675 bool fail_after_createfile)
5677 NTSTATUS status = NT_STATUS_OK;
5678 struct smb_filename *smb_fname_tmp = NULL;
5679 files_struct *new_fsp = NULL;
5681 if (!VALID_STAT(*psbuf)) {
5682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5685 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5686 return NT_STATUS_ACCESS_DENIED;
5689 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5691 if (size == get_file_size_stat(psbuf)) {
5692 return NT_STATUS_OK;
5695 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5696 smb_fname_str_dbg(smb_fname), (double)size));
5698 if (fsp && fsp->fh->fd != -1) {
5699 /* Handle based call. */
5700 if (vfs_set_filelen(fsp, size) == -1) {
5701 return map_nt_error_from_unix(errno);
5703 trigger_write_time_update_immediate(fsp);
5704 return NT_STATUS_OK;
5707 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5708 if (!NT_STATUS_IS_OK(status)) {
5709 return status;
5712 smb_fname_tmp->st = *psbuf;
5714 status = SMB_VFS_CREATE_FILE(
5715 conn, /* conn */
5716 req, /* req */
5717 0, /* root_dir_fid */
5718 smb_fname_tmp, /* fname */
5719 FILE_WRITE_DATA, /* access_mask */
5720 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5721 FILE_SHARE_DELETE),
5722 FILE_OPEN, /* create_disposition*/
5723 0, /* create_options */
5724 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5725 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5726 0, /* allocation_size */
5727 0, /* private_flags */
5728 NULL, /* sd */
5729 NULL, /* ea_list */
5730 &new_fsp, /* result */
5731 NULL); /* pinfo */
5733 TALLOC_FREE(smb_fname_tmp);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 /* NB. We check for open_was_deferred in the caller. */
5737 return status;
5740 /* See RAW-SFILEINFO-END-OF-FILE */
5741 if (fail_after_createfile) {
5742 close_file(req, new_fsp,NORMAL_CLOSE);
5743 return NT_STATUS_INVALID_LEVEL;
5746 if (vfs_set_filelen(new_fsp, size) == -1) {
5747 status = map_nt_error_from_unix(errno);
5748 close_file(req, new_fsp,NORMAL_CLOSE);
5749 return status;
5752 trigger_write_time_update_immediate(new_fsp);
5753 close_file(req, new_fsp,NORMAL_CLOSE);
5754 return NT_STATUS_OK;
5757 /****************************************************************************
5758 Deal with SMB_INFO_SET_EA.
5759 ****************************************************************************/
5761 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5762 const char *pdata,
5763 int total_data,
5764 files_struct *fsp,
5765 const struct smb_filename *smb_fname)
5767 struct ea_list *ea_list = NULL;
5768 TALLOC_CTX *ctx = NULL;
5769 NTSTATUS status = NT_STATUS_OK;
5771 if (total_data < 10) {
5773 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5774 length. They seem to have no effect. Bug #3212. JRA */
5776 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5777 /* We're done. We only get EA info in this call. */
5778 return NT_STATUS_OK;
5781 return NT_STATUS_INVALID_PARAMETER;
5784 if (IVAL(pdata,0) > total_data) {
5785 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5786 IVAL(pdata,0), (unsigned int)total_data));
5787 return NT_STATUS_INVALID_PARAMETER;
5790 ctx = talloc_tos();
5791 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5792 if (!ea_list) {
5793 return NT_STATUS_INVALID_PARAMETER;
5796 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5797 return NT_STATUS_ACCESS_DENIED;
5800 status = set_ea(conn, fsp, smb_fname, ea_list);
5802 return status;
5805 /****************************************************************************
5806 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5807 ****************************************************************************/
5809 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5810 const char *pdata,
5811 int total_data,
5812 files_struct *fsp)
5814 struct ea_list *ea_list = NULL;
5815 NTSTATUS status;
5817 if (!fsp) {
5818 return NT_STATUS_INVALID_HANDLE;
5821 if (!lp_ea_support(SNUM(conn))) {
5822 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5823 "EA's not supported.\n",
5824 (unsigned int)total_data));
5825 return NT_STATUS_EAS_NOT_SUPPORTED;
5828 if (total_data < 10) {
5829 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5830 "too small.\n",
5831 (unsigned int)total_data));
5832 return NT_STATUS_INVALID_PARAMETER;
5835 ea_list = read_nttrans_ea_list(talloc_tos(),
5836 pdata,
5837 total_data);
5839 if (!ea_list) {
5840 return NT_STATUS_INVALID_PARAMETER;
5843 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5844 return NT_STATUS_ACCESS_DENIED;
5847 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5849 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5850 smb_fname_str_dbg(fsp->fsp_name),
5851 nt_errstr(status) ));
5853 return status;
5857 /****************************************************************************
5858 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5859 ****************************************************************************/
5861 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5862 const char *pdata,
5863 int total_data,
5864 files_struct *fsp,
5865 struct smb_filename *smb_fname)
5867 NTSTATUS status = NT_STATUS_OK;
5868 bool delete_on_close;
5869 uint32 dosmode = 0;
5871 if (total_data < 1) {
5872 return NT_STATUS_INVALID_PARAMETER;
5875 if (fsp == NULL) {
5876 return NT_STATUS_INVALID_HANDLE;
5879 delete_on_close = (CVAL(pdata,0) ? True : False);
5880 dosmode = dos_mode(conn, smb_fname);
5882 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5883 "delete_on_close = %u\n",
5884 smb_fname_str_dbg(smb_fname),
5885 (unsigned int)dosmode,
5886 (unsigned int)delete_on_close ));
5888 if (delete_on_close) {
5889 status = can_set_delete_on_close(fsp, dosmode);
5890 if (!NT_STATUS_IS_OK(status)) {
5891 return status;
5895 /* The set is across all open files on this dev/inode pair. */
5896 if (!set_delete_on_close(fsp, delete_on_close,
5897 conn->session_info->security_token,
5898 &conn->session_info->utok)) {
5899 return NT_STATUS_ACCESS_DENIED;
5901 return NT_STATUS_OK;
5904 /****************************************************************************
5905 Deal with SMB_FILE_POSITION_INFORMATION.
5906 ****************************************************************************/
5908 static NTSTATUS smb_file_position_information(connection_struct *conn,
5909 const char *pdata,
5910 int total_data,
5911 files_struct *fsp)
5913 uint64_t position_information;
5915 if (total_data < 8) {
5916 return NT_STATUS_INVALID_PARAMETER;
5919 if (fsp == NULL) {
5920 /* Ignore on pathname based set. */
5921 return NT_STATUS_OK;
5924 position_information = (uint64_t)IVAL(pdata,0);
5925 #ifdef LARGE_SMB_OFF_T
5926 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5927 #else /* LARGE_SMB_OFF_T */
5928 if (IVAL(pdata,4) != 0) {
5929 /* more than 32 bits? */
5930 return NT_STATUS_INVALID_PARAMETER;
5932 #endif /* LARGE_SMB_OFF_T */
5934 DEBUG(10,("smb_file_position_information: Set file position "
5935 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5936 (double)position_information));
5937 fsp->fh->position_information = position_information;
5938 return NT_STATUS_OK;
5941 /****************************************************************************
5942 Deal with SMB_FILE_MODE_INFORMATION.
5943 ****************************************************************************/
5945 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5946 const char *pdata,
5947 int total_data)
5949 uint32 mode;
5951 if (total_data < 4) {
5952 return NT_STATUS_INVALID_PARAMETER;
5954 mode = IVAL(pdata,0);
5955 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5956 return NT_STATUS_INVALID_PARAMETER;
5958 return NT_STATUS_OK;
5961 /****************************************************************************
5962 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5963 ****************************************************************************/
5965 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5966 struct smb_request *req,
5967 const char *pdata,
5968 int total_data,
5969 const struct smb_filename *smb_fname)
5971 char *link_target = NULL;
5972 const char *newname = smb_fname->base_name;
5973 TALLOC_CTX *ctx = talloc_tos();
5975 /* Set a symbolic link. */
5976 /* Don't allow this if follow links is false. */
5978 if (total_data == 0) {
5979 return NT_STATUS_INVALID_PARAMETER;
5982 if (!lp_symlinks(SNUM(conn))) {
5983 return NT_STATUS_ACCESS_DENIED;
5986 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5987 total_data, STR_TERMINATE);
5989 if (!link_target) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5994 newname, link_target ));
5996 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5997 return map_nt_error_from_unix(errno);
6000 return NT_STATUS_OK;
6003 /****************************************************************************
6004 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6005 ****************************************************************************/
6007 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6008 struct smb_request *req,
6009 const char *pdata, int total_data,
6010 struct smb_filename *smb_fname_new)
6012 char *oldname = NULL;
6013 struct smb_filename *smb_fname_old = NULL;
6014 TALLOC_CTX *ctx = talloc_tos();
6015 NTSTATUS status = NT_STATUS_OK;
6017 /* Set a hard link. */
6018 if (total_data == 0) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6023 total_data, STR_TERMINATE, &status);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 return status;
6028 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6029 smb_fname_str_dbg(smb_fname_new), oldname));
6031 status = filename_convert(ctx,
6032 conn,
6033 req->flags2 & FLAGS2_DFS_PATHNAMES,
6034 oldname,
6036 NULL,
6037 &smb_fname_old);
6038 if (!NT_STATUS_IS_OK(status)) {
6039 return status;
6042 return hardlink_internals(ctx, conn, req, false,
6043 smb_fname_old, smb_fname_new);
6046 /****************************************************************************
6047 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6048 ****************************************************************************/
6050 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6051 struct smb_request *req,
6052 const char *pdata,
6053 int total_data,
6054 files_struct *fsp,
6055 struct smb_filename *smb_fname_src)
6057 bool overwrite;
6058 uint32_t len;
6059 char *newname = NULL;
6060 struct smb_filename *smb_fname_dst = NULL;
6061 NTSTATUS status = NT_STATUS_OK;
6062 TALLOC_CTX *ctx = talloc_tos();
6064 if (!fsp) {
6065 return NT_STATUS_INVALID_HANDLE;
6068 if (total_data < 20) {
6069 return NT_STATUS_INVALID_PARAMETER;
6072 overwrite = (CVAL(pdata,0) ? True : False);
6073 len = IVAL(pdata,16);
6075 if (len > (total_data - 20) || (len == 0)) {
6076 return NT_STATUS_INVALID_PARAMETER;
6079 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6080 &pdata[20], len, STR_TERMINATE,
6081 &status);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 return status;
6086 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6087 newname));
6089 status = filename_convert(ctx,
6090 conn,
6091 req->flags2 & FLAGS2_DFS_PATHNAMES,
6092 newname,
6093 UCF_SAVE_LCOMP,
6094 NULL,
6095 &smb_fname_dst);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 return status;
6100 if (fsp->base_fsp) {
6101 /* newname must be a stream name. */
6102 if (newname[0] != ':') {
6103 return NT_STATUS_NOT_SUPPORTED;
6106 /* Create an smb_fname to call rename_internals_fsp() with. */
6107 status = create_synthetic_smb_fname(talloc_tos(),
6108 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6109 &smb_fname_dst);
6110 if (!NT_STATUS_IS_OK(status)) {
6111 goto out;
6115 * Set the original last component, since
6116 * rename_internals_fsp() requires it.
6118 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6119 newname);
6120 if (smb_fname_dst->original_lcomp == NULL) {
6121 status = NT_STATUS_NO_MEMORY;
6122 goto out;
6127 DEBUG(10,("smb2_file_rename_information: "
6128 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6129 fsp->fnum, fsp_str_dbg(fsp),
6130 smb_fname_str_dbg(smb_fname_dst)));
6131 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6132 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6133 overwrite);
6135 out:
6136 TALLOC_FREE(smb_fname_dst);
6137 return status;
6140 static NTSTATUS smb_file_link_information(connection_struct *conn,
6141 struct smb_request *req,
6142 const char *pdata,
6143 int total_data,
6144 files_struct *fsp,
6145 struct smb_filename *smb_fname_src)
6147 bool overwrite;
6148 uint32_t len;
6149 char *newname = NULL;
6150 struct smb_filename *smb_fname_dst = NULL;
6151 NTSTATUS status = NT_STATUS_OK;
6152 TALLOC_CTX *ctx = talloc_tos();
6154 if (!fsp) {
6155 return NT_STATUS_INVALID_HANDLE;
6158 if (total_data < 20) {
6159 return NT_STATUS_INVALID_PARAMETER;
6162 overwrite = (CVAL(pdata,0) ? true : false);
6163 len = IVAL(pdata,16);
6165 if (len > (total_data - 20) || (len == 0)) {
6166 return NT_STATUS_INVALID_PARAMETER;
6169 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6170 &pdata[20], len, STR_TERMINATE,
6171 &status);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 return status;
6176 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6177 newname));
6179 status = filename_convert(ctx,
6180 conn,
6181 req->flags2 & FLAGS2_DFS_PATHNAMES,
6182 newname,
6183 UCF_SAVE_LCOMP,
6184 NULL,
6185 &smb_fname_dst);
6186 if (!NT_STATUS_IS_OK(status)) {
6187 return status;
6190 if (fsp->base_fsp) {
6191 /* No stream names. */
6192 return NT_STATUS_NOT_SUPPORTED;
6195 DEBUG(10,("smb_file_link_information: "
6196 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6197 fsp->fnum, fsp_str_dbg(fsp),
6198 smb_fname_str_dbg(smb_fname_dst)));
6199 status = hardlink_internals(ctx,
6200 conn,
6201 req,
6202 overwrite,
6203 fsp->fsp_name,
6204 smb_fname_dst);
6206 TALLOC_FREE(smb_fname_dst);
6207 return status;
6210 /****************************************************************************
6211 Deal with SMB_FILE_RENAME_INFORMATION.
6212 ****************************************************************************/
6214 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6215 struct smb_request *req,
6216 const char *pdata,
6217 int total_data,
6218 files_struct *fsp,
6219 struct smb_filename *smb_fname_src)
6221 bool overwrite;
6222 uint32 root_fid;
6223 uint32 len;
6224 char *newname = NULL;
6225 struct smb_filename *smb_fname_dst = NULL;
6226 bool dest_has_wcard = False;
6227 NTSTATUS status = NT_STATUS_OK;
6228 char *p;
6229 TALLOC_CTX *ctx = talloc_tos();
6231 if (total_data < 13) {
6232 return NT_STATUS_INVALID_PARAMETER;
6235 overwrite = (CVAL(pdata,0) ? True : False);
6236 root_fid = IVAL(pdata,4);
6237 len = IVAL(pdata,8);
6239 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6240 return NT_STATUS_INVALID_PARAMETER;
6243 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6244 len, 0, &status,
6245 &dest_has_wcard);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 return status;
6250 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6251 newname));
6253 status = resolve_dfspath_wcard(ctx, conn,
6254 req->flags2 & FLAGS2_DFS_PATHNAMES,
6255 newname,
6256 true,
6257 &newname,
6258 &dest_has_wcard);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 return status;
6263 /* Check the new name has no '/' characters. */
6264 if (strchr_m(newname, '/')) {
6265 return NT_STATUS_NOT_SUPPORTED;
6268 if (fsp && fsp->base_fsp) {
6269 /* newname must be a stream name. */
6270 if (newname[0] != ':') {
6271 return NT_STATUS_NOT_SUPPORTED;
6274 /* Create an smb_fname to call rename_internals_fsp() with. */
6275 status = create_synthetic_smb_fname(talloc_tos(),
6276 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6277 &smb_fname_dst);
6278 if (!NT_STATUS_IS_OK(status)) {
6279 goto out;
6283 * Set the original last component, since
6284 * rename_internals_fsp() requires it.
6286 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6287 newname);
6288 if (smb_fname_dst->original_lcomp == NULL) {
6289 status = NT_STATUS_NO_MEMORY;
6290 goto out;
6293 } else {
6295 * Build up an smb_fname_dst based on the filename passed in.
6296 * We basically just strip off the last component, and put on
6297 * the newname instead.
6299 char *base_name = NULL;
6301 /* newname must *not* be a stream name. */
6302 if (newname[0] == ':') {
6303 return NT_STATUS_NOT_SUPPORTED;
6307 * Strip off the last component (filename) of the path passed
6308 * in.
6310 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6311 if (!base_name) {
6312 return NT_STATUS_NO_MEMORY;
6314 p = strrchr_m(base_name, '/');
6315 if (p) {
6316 p[1] = '\0';
6317 } else {
6318 base_name = talloc_strdup(ctx, "");
6319 if (!base_name) {
6320 return NT_STATUS_NO_MEMORY;
6323 /* Append the new name. */
6324 base_name = talloc_asprintf_append(base_name,
6325 "%s",
6326 newname);
6327 if (!base_name) {
6328 return NT_STATUS_NO_MEMORY;
6331 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6332 (UCF_SAVE_LCOMP |
6333 (dest_has_wcard ?
6334 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6335 0)));
6337 /* If an error we expect this to be
6338 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6340 if (!NT_STATUS_IS_OK(status)) {
6341 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6342 status)) {
6343 goto out;
6345 /* Create an smb_fname to call rename_internals_fsp() */
6346 status = create_synthetic_smb_fname(ctx,
6347 base_name, NULL,
6348 NULL,
6349 &smb_fname_dst);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 goto out;
6356 if (fsp) {
6357 DEBUG(10,("smb_file_rename_information: "
6358 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6359 fsp->fnum, fsp_str_dbg(fsp),
6360 smb_fname_str_dbg(smb_fname_dst)));
6361 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6362 overwrite);
6363 } else {
6364 DEBUG(10,("smb_file_rename_information: "
6365 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6366 smb_fname_str_dbg(smb_fname_src),
6367 smb_fname_str_dbg(smb_fname_dst)));
6368 status = rename_internals(ctx, conn, req, smb_fname_src,
6369 smb_fname_dst, 0, overwrite, false,
6370 dest_has_wcard,
6371 FILE_WRITE_ATTRIBUTES);
6373 out:
6374 TALLOC_FREE(smb_fname_dst);
6375 return status;
6378 /****************************************************************************
6379 Deal with SMB_SET_POSIX_ACL.
6380 ****************************************************************************/
6382 #if defined(HAVE_POSIX_ACLS)
6383 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6384 const char *pdata,
6385 int total_data,
6386 files_struct *fsp,
6387 const struct smb_filename *smb_fname)
6389 uint16 posix_acl_version;
6390 uint16 num_file_acls;
6391 uint16 num_def_acls;
6392 bool valid_file_acls = True;
6393 bool valid_def_acls = True;
6395 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6396 return NT_STATUS_INVALID_PARAMETER;
6398 posix_acl_version = SVAL(pdata,0);
6399 num_file_acls = SVAL(pdata,2);
6400 num_def_acls = SVAL(pdata,4);
6402 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6403 valid_file_acls = False;
6404 num_file_acls = 0;
6407 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6408 valid_def_acls = False;
6409 num_def_acls = 0;
6412 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6417 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6418 return NT_STATUS_INVALID_PARAMETER;
6421 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6422 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6423 (unsigned int)num_file_acls,
6424 (unsigned int)num_def_acls));
6426 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6427 smb_fname->base_name, num_file_acls,
6428 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6429 return map_nt_error_from_unix(errno);
6432 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6433 smb_fname->base_name, &smb_fname->st, num_def_acls,
6434 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6435 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6436 return map_nt_error_from_unix(errno);
6438 return NT_STATUS_OK;
6440 #endif
6442 /****************************************************************************
6443 Deal with SMB_SET_POSIX_LOCK.
6444 ****************************************************************************/
6446 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6447 struct smb_request *req,
6448 const char *pdata,
6449 int total_data,
6450 files_struct *fsp)
6452 uint64_t count;
6453 uint64_t offset;
6454 uint64_t smblctx;
6455 bool blocking_lock = False;
6456 enum brl_type lock_type;
6458 NTSTATUS status = NT_STATUS_OK;
6460 if (fsp == NULL || fsp->fh->fd == -1) {
6461 return NT_STATUS_INVALID_HANDLE;
6464 if (total_data != POSIX_LOCK_DATA_SIZE) {
6465 return NT_STATUS_INVALID_PARAMETER;
6468 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6469 case POSIX_LOCK_TYPE_READ:
6470 lock_type = READ_LOCK;
6471 break;
6472 case POSIX_LOCK_TYPE_WRITE:
6473 /* Return the right POSIX-mappable error code for files opened read-only. */
6474 if (!fsp->can_write) {
6475 return NT_STATUS_INVALID_HANDLE;
6477 lock_type = WRITE_LOCK;
6478 break;
6479 case POSIX_LOCK_TYPE_UNLOCK:
6480 lock_type = UNLOCK_LOCK;
6481 break;
6482 default:
6483 return NT_STATUS_INVALID_PARAMETER;
6486 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6487 blocking_lock = False;
6488 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6489 blocking_lock = True;
6490 } else {
6491 return NT_STATUS_INVALID_PARAMETER;
6494 if (!lp_blocking_locks(SNUM(conn))) {
6495 blocking_lock = False;
6498 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6499 #if defined(HAVE_LONGLONG)
6500 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6501 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6502 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6503 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6504 #else /* HAVE_LONGLONG */
6505 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6506 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6507 #endif /* HAVE_LONGLONG */
6509 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6510 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6511 fsp_str_dbg(fsp),
6512 (unsigned int)lock_type,
6513 (unsigned long long)smblctx,
6514 (double)count,
6515 (double)offset ));
6517 if (lock_type == UNLOCK_LOCK) {
6518 status = do_unlock(req->sconn->msg_ctx,
6519 fsp,
6520 smblctx,
6521 count,
6522 offset,
6523 POSIX_LOCK);
6524 } else {
6525 uint64_t block_smblctx;
6527 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6528 fsp,
6529 smblctx,
6530 count,
6531 offset,
6532 lock_type,
6533 POSIX_LOCK,
6534 blocking_lock,
6535 &status,
6536 &block_smblctx,
6537 NULL);
6539 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6541 * A blocking lock was requested. Package up
6542 * this smb into a queued request and push it
6543 * onto the blocking lock queue.
6545 if(push_blocking_lock_request(br_lck,
6546 req,
6547 fsp,
6548 -1, /* infinite timeout. */
6550 smblctx,
6551 lock_type,
6552 POSIX_LOCK,
6553 offset,
6554 count,
6555 block_smblctx)) {
6556 TALLOC_FREE(br_lck);
6557 return status;
6560 TALLOC_FREE(br_lck);
6563 return status;
6566 /****************************************************************************
6567 Deal with SMB_SET_FILE_BASIC_INFO.
6568 ****************************************************************************/
6570 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6571 const char *pdata,
6572 int total_data,
6573 files_struct *fsp,
6574 const struct smb_filename *smb_fname)
6576 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6577 struct smb_file_time ft;
6578 uint32 dosmode = 0;
6579 NTSTATUS status = NT_STATUS_OK;
6581 ZERO_STRUCT(ft);
6583 if (total_data < 36) {
6584 return NT_STATUS_INVALID_PARAMETER;
6587 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6588 return NT_STATUS_ACCESS_DENIED;
6591 /* Set the attributes */
6592 dosmode = IVAL(pdata,32);
6593 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6594 if (!NT_STATUS_IS_OK(status)) {
6595 return status;
6598 /* create time */
6599 ft.create_time = interpret_long_date(pdata);
6601 /* access time */
6602 ft.atime = interpret_long_date(pdata+8);
6604 /* write time. */
6605 ft.mtime = interpret_long_date(pdata+16);
6607 /* change time. */
6608 ft.ctime = interpret_long_date(pdata+24);
6610 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6611 smb_fname_str_dbg(smb_fname)));
6613 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6614 true);
6617 /****************************************************************************
6618 Deal with SMB_INFO_STANDARD.
6619 ****************************************************************************/
6621 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6622 const char *pdata,
6623 int total_data,
6624 files_struct *fsp,
6625 const struct smb_filename *smb_fname)
6627 struct smb_file_time ft;
6629 ZERO_STRUCT(ft);
6631 if (total_data < 12) {
6632 return NT_STATUS_INVALID_PARAMETER;
6635 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6636 return NT_STATUS_ACCESS_DENIED;
6639 /* create time */
6640 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6641 /* access time */
6642 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6643 /* write time */
6644 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6646 DEBUG(10,("smb_set_info_standard: file %s\n",
6647 smb_fname_str_dbg(smb_fname)));
6649 return smb_set_file_time(conn,
6650 fsp,
6651 smb_fname,
6652 &ft,
6653 true);
6656 /****************************************************************************
6657 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6658 ****************************************************************************/
6660 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6661 struct smb_request *req,
6662 const char *pdata,
6663 int total_data,
6664 files_struct *fsp,
6665 struct smb_filename *smb_fname)
6667 uint64_t allocation_size = 0;
6668 NTSTATUS status = NT_STATUS_OK;
6669 files_struct *new_fsp = NULL;
6671 if (!VALID_STAT(smb_fname->st)) {
6672 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6675 if (total_data < 8) {
6676 return NT_STATUS_INVALID_PARAMETER;
6679 allocation_size = (uint64_t)IVAL(pdata,0);
6680 #ifdef LARGE_SMB_OFF_T
6681 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6682 #else /* LARGE_SMB_OFF_T */
6683 if (IVAL(pdata,4) != 0) {
6684 /* more than 32 bits? */
6685 return NT_STATUS_INVALID_PARAMETER;
6687 #endif /* LARGE_SMB_OFF_T */
6689 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6690 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6691 (double)allocation_size));
6693 if (allocation_size) {
6694 allocation_size = smb_roundup(conn, allocation_size);
6697 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6698 return NT_STATUS_ACCESS_DENIED;
6701 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6702 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6703 (double)allocation_size));
6705 if (fsp && fsp->fh->fd != -1) {
6706 /* Open file handle. */
6707 /* Only change if needed. */
6708 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6709 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6710 return map_nt_error_from_unix(errno);
6713 /* But always update the time. */
6715 * This is equivalent to a write. Ensure it's seen immediately
6716 * if there are no pending writes.
6718 trigger_write_time_update_immediate(fsp);
6719 return NT_STATUS_OK;
6722 /* Pathname or stat or directory file. */
6723 status = SMB_VFS_CREATE_FILE(
6724 conn, /* conn */
6725 req, /* req */
6726 0, /* root_dir_fid */
6727 smb_fname, /* fname */
6728 FILE_WRITE_DATA, /* access_mask */
6729 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6730 FILE_SHARE_DELETE),
6731 FILE_OPEN, /* create_disposition*/
6732 0, /* create_options */
6733 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6734 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6735 0, /* allocation_size */
6736 0, /* private_flags */
6737 NULL, /* sd */
6738 NULL, /* ea_list */
6739 &new_fsp, /* result */
6740 NULL); /* pinfo */
6742 if (!NT_STATUS_IS_OK(status)) {
6743 /* NB. We check for open_was_deferred in the caller. */
6744 return status;
6747 /* Only change if needed. */
6748 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6749 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6750 status = map_nt_error_from_unix(errno);
6751 close_file(req, new_fsp, NORMAL_CLOSE);
6752 return status;
6756 /* Changing the allocation size should set the last mod time. */
6758 * This is equivalent to a write. Ensure it's seen immediately
6759 * if there are no pending writes.
6761 trigger_write_time_update_immediate(new_fsp);
6763 close_file(req, new_fsp, NORMAL_CLOSE);
6764 return NT_STATUS_OK;
6767 /****************************************************************************
6768 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6769 ****************************************************************************/
6771 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6772 struct smb_request *req,
6773 const char *pdata,
6774 int total_data,
6775 files_struct *fsp,
6776 const struct smb_filename *smb_fname,
6777 bool fail_after_createfile)
6779 SMB_OFF_T size;
6781 if (total_data < 8) {
6782 return NT_STATUS_INVALID_PARAMETER;
6785 size = IVAL(pdata,0);
6786 #ifdef LARGE_SMB_OFF_T
6787 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6788 #else /* LARGE_SMB_OFF_T */
6789 if (IVAL(pdata,4) != 0) {
6790 /* more than 32 bits? */
6791 return NT_STATUS_INVALID_PARAMETER;
6793 #endif /* LARGE_SMB_OFF_T */
6794 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6795 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6796 (double)size));
6798 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6799 return NT_STATUS_ACCESS_DENIED;
6802 return smb_set_file_size(conn, req,
6803 fsp,
6804 smb_fname,
6805 &smb_fname->st,
6806 size,
6807 fail_after_createfile);
6810 /****************************************************************************
6811 Allow a UNIX info mknod.
6812 ****************************************************************************/
6814 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6815 const char *pdata,
6816 int total_data,
6817 const struct smb_filename *smb_fname)
6819 uint32 file_type = IVAL(pdata,56);
6820 #if defined(HAVE_MAKEDEV)
6821 uint32 dev_major = IVAL(pdata,60);
6822 uint32 dev_minor = IVAL(pdata,68);
6823 #endif
6824 SMB_DEV_T dev = (SMB_DEV_T)0;
6825 uint32 raw_unixmode = IVAL(pdata,84);
6826 NTSTATUS status;
6827 mode_t unixmode;
6829 if (total_data < 100) {
6830 return NT_STATUS_INVALID_PARAMETER;
6833 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6834 PERM_NEW_FILE, &unixmode);
6835 if (!NT_STATUS_IS_OK(status)) {
6836 return status;
6839 #if defined(HAVE_MAKEDEV)
6840 dev = makedev(dev_major, dev_minor);
6841 #endif
6843 switch (file_type) {
6844 #if defined(S_IFIFO)
6845 case UNIX_TYPE_FIFO:
6846 unixmode |= S_IFIFO;
6847 break;
6848 #endif
6849 #if defined(S_IFSOCK)
6850 case UNIX_TYPE_SOCKET:
6851 unixmode |= S_IFSOCK;
6852 break;
6853 #endif
6854 #if defined(S_IFCHR)
6855 case UNIX_TYPE_CHARDEV:
6856 unixmode |= S_IFCHR;
6857 break;
6858 #endif
6859 #if defined(S_IFBLK)
6860 case UNIX_TYPE_BLKDEV:
6861 unixmode |= S_IFBLK;
6862 break;
6863 #endif
6864 default:
6865 return NT_STATUS_INVALID_PARAMETER;
6868 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6869 "%.0f mode 0%o for file %s\n", (double)dev,
6870 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6872 /* Ok - do the mknod. */
6873 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6874 return map_nt_error_from_unix(errno);
6877 /* If any of the other "set" calls fail we
6878 * don't want to end up with a half-constructed mknod.
6881 if (lp_inherit_perms(SNUM(conn))) {
6882 char *parent;
6883 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6884 &parent, NULL)) {
6885 return NT_STATUS_NO_MEMORY;
6887 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6888 unixmode);
6889 TALLOC_FREE(parent);
6892 return NT_STATUS_OK;
6895 /****************************************************************************
6896 Deal with SMB_SET_FILE_UNIX_BASIC.
6897 ****************************************************************************/
6899 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6900 struct smb_request *req,
6901 const char *pdata,
6902 int total_data,
6903 files_struct *fsp,
6904 const struct smb_filename *smb_fname)
6906 struct smb_file_time ft;
6907 uint32 raw_unixmode;
6908 mode_t unixmode;
6909 SMB_OFF_T size = 0;
6910 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6911 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6912 NTSTATUS status = NT_STATUS_OK;
6913 bool delete_on_fail = False;
6914 enum perm_type ptype;
6915 files_struct *all_fsps = NULL;
6916 bool modify_mtime = true;
6917 struct file_id id;
6918 struct smb_filename *smb_fname_tmp = NULL;
6919 SMB_STRUCT_STAT sbuf;
6921 ZERO_STRUCT(ft);
6923 if (total_data < 100) {
6924 return NT_STATUS_INVALID_PARAMETER;
6927 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6928 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6929 size=IVAL(pdata,0); /* first 8 Bytes are size */
6930 #ifdef LARGE_SMB_OFF_T
6931 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6932 #else /* LARGE_SMB_OFF_T */
6933 if (IVAL(pdata,4) != 0) {
6934 /* more than 32 bits? */
6935 return NT_STATUS_INVALID_PARAMETER;
6937 #endif /* LARGE_SMB_OFF_T */
6940 ft.atime = interpret_long_date(pdata+24); /* access_time */
6941 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6942 set_owner = (uid_t)IVAL(pdata,40);
6943 set_grp = (gid_t)IVAL(pdata,48);
6944 raw_unixmode = IVAL(pdata,84);
6946 if (VALID_STAT(smb_fname->st)) {
6947 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6948 ptype = PERM_EXISTING_DIR;
6949 } else {
6950 ptype = PERM_EXISTING_FILE;
6952 } else {
6953 ptype = PERM_NEW_FILE;
6956 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6957 ptype, &unixmode);
6958 if (!NT_STATUS_IS_OK(status)) {
6959 return status;
6962 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6963 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6964 smb_fname_str_dbg(smb_fname), (double)size,
6965 (unsigned int)set_owner, (unsigned int)set_grp,
6966 (int)raw_unixmode));
6968 sbuf = smb_fname->st;
6970 if (!VALID_STAT(sbuf)) {
6972 * The only valid use of this is to create character and block
6973 * devices, and named pipes. This is deprecated (IMHO) and
6974 * a new info level should be used for mknod. JRA.
6977 status = smb_unix_mknod(conn,
6978 pdata,
6979 total_data,
6980 smb_fname);
6981 if (!NT_STATUS_IS_OK(status)) {
6982 return status;
6985 status = copy_smb_filename(talloc_tos(), smb_fname,
6986 &smb_fname_tmp);
6987 if (!NT_STATUS_IS_OK(status)) {
6988 return status;
6991 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6992 status = map_nt_error_from_unix(errno);
6993 TALLOC_FREE(smb_fname_tmp);
6994 SMB_VFS_UNLINK(conn, smb_fname);
6995 return status;
6998 sbuf = smb_fname_tmp->st;
6999 smb_fname = smb_fname_tmp;
7001 /* Ensure we don't try and change anything else. */
7002 raw_unixmode = SMB_MODE_NO_CHANGE;
7003 size = get_file_size_stat(&sbuf);
7004 ft.atime = sbuf.st_ex_atime;
7005 ft.mtime = sbuf.st_ex_mtime;
7007 * We continue here as we might want to change the
7008 * owner uid/gid.
7010 delete_on_fail = True;
7013 #if 1
7014 /* Horrible backwards compatibility hack as an old server bug
7015 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7016 * */
7018 if (!size) {
7019 size = get_file_size_stat(&sbuf);
7021 #endif
7024 * Deal with the UNIX specific mode set.
7027 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7028 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7029 "setting mode 0%o for file %s\n",
7030 (unsigned int)unixmode,
7031 smb_fname_str_dbg(smb_fname)));
7032 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7033 return map_nt_error_from_unix(errno);
7038 * Deal with the UNIX specific uid set.
7041 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7042 (sbuf.st_ex_uid != set_owner)) {
7043 int ret;
7045 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7046 "changing owner %u for path %s\n",
7047 (unsigned int)set_owner,
7048 smb_fname_str_dbg(smb_fname)));
7050 if (S_ISLNK(sbuf.st_ex_mode)) {
7051 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7052 set_owner, (gid_t)-1);
7053 } else {
7054 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7055 set_owner, (gid_t)-1);
7058 if (ret != 0) {
7059 status = map_nt_error_from_unix(errno);
7060 if (delete_on_fail) {
7061 SMB_VFS_UNLINK(conn, smb_fname);
7063 return status;
7068 * Deal with the UNIX specific gid set.
7071 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7072 (sbuf.st_ex_gid != set_grp)) {
7073 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7074 "changing group %u for file %s\n",
7075 (unsigned int)set_owner,
7076 smb_fname_str_dbg(smb_fname)));
7077 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7078 set_grp) != 0) {
7079 status = map_nt_error_from_unix(errno);
7080 if (delete_on_fail) {
7081 SMB_VFS_UNLINK(conn, smb_fname);
7083 return status;
7087 /* Deal with any size changes. */
7089 status = smb_set_file_size(conn, req,
7090 fsp,
7091 smb_fname,
7092 &sbuf,
7093 size,
7094 false);
7095 if (!NT_STATUS_IS_OK(status)) {
7096 return status;
7099 /* Deal with any time changes. */
7100 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7101 /* No change, don't cancel anything. */
7102 return status;
7105 id = vfs_file_id_from_sbuf(conn, &sbuf);
7106 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7107 all_fsps = file_find_di_next(all_fsps)) {
7109 * We're setting the time explicitly for UNIX.
7110 * Cancel any pending changes over all handles.
7112 all_fsps->update_write_time_on_close = false;
7113 TALLOC_FREE(all_fsps->update_write_time_event);
7117 * Override the "setting_write_time"
7118 * parameter here as it almost does what
7119 * we need. Just remember if we modified
7120 * mtime and send the notify ourselves.
7122 if (null_timespec(ft.mtime)) {
7123 modify_mtime = false;
7126 status = smb_set_file_time(conn,
7127 fsp,
7128 smb_fname,
7129 &ft,
7130 false);
7131 if (modify_mtime) {
7132 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7133 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7135 return status;
7138 /****************************************************************************
7139 Deal with SMB_SET_FILE_UNIX_INFO2.
7140 ****************************************************************************/
7142 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7143 struct smb_request *req,
7144 const char *pdata,
7145 int total_data,
7146 files_struct *fsp,
7147 const struct smb_filename *smb_fname)
7149 NTSTATUS status;
7150 uint32 smb_fflags;
7151 uint32 smb_fmask;
7153 if (total_data < 116) {
7154 return NT_STATUS_INVALID_PARAMETER;
7157 /* Start by setting all the fields that are common between UNIX_BASIC
7158 * and UNIX_INFO2.
7160 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7161 fsp, smb_fname);
7162 if (!NT_STATUS_IS_OK(status)) {
7163 return status;
7166 smb_fflags = IVAL(pdata, 108);
7167 smb_fmask = IVAL(pdata, 112);
7169 /* NB: We should only attempt to alter the file flags if the client
7170 * sends a non-zero mask.
7172 if (smb_fmask != 0) {
7173 int stat_fflags = 0;
7175 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7176 smb_fmask, &stat_fflags)) {
7177 /* Client asked to alter a flag we don't understand. */
7178 return NT_STATUS_INVALID_PARAMETER;
7181 if (fsp && fsp->fh->fd != -1) {
7182 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7183 return NT_STATUS_NOT_SUPPORTED;
7184 } else {
7185 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7186 stat_fflags) != 0) {
7187 return map_nt_error_from_unix(errno);
7192 /* XXX: need to add support for changing the create_time here. You
7193 * can do this for paths on Darwin with setattrlist(2). The right way
7194 * to hook this up is probably by extending the VFS utimes interface.
7197 return NT_STATUS_OK;
7200 /****************************************************************************
7201 Create a directory with POSIX semantics.
7202 ****************************************************************************/
7204 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7205 struct smb_request *req,
7206 char **ppdata,
7207 int total_data,
7208 struct smb_filename *smb_fname,
7209 int *pdata_return_size)
7211 NTSTATUS status = NT_STATUS_OK;
7212 uint32 raw_unixmode = 0;
7213 uint32 mod_unixmode = 0;
7214 mode_t unixmode = (mode_t)0;
7215 files_struct *fsp = NULL;
7216 uint16 info_level_return = 0;
7217 int info;
7218 char *pdata = *ppdata;
7220 if (total_data < 18) {
7221 return NT_STATUS_INVALID_PARAMETER;
7224 raw_unixmode = IVAL(pdata,8);
7225 /* Next 4 bytes are not yet defined. */
7227 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7228 PERM_NEW_DIR, &unixmode);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 return status;
7233 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7235 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7236 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7238 status = SMB_VFS_CREATE_FILE(
7239 conn, /* conn */
7240 req, /* req */
7241 0, /* root_dir_fid */
7242 smb_fname, /* fname */
7243 FILE_READ_ATTRIBUTES, /* access_mask */
7244 FILE_SHARE_NONE, /* share_access */
7245 FILE_CREATE, /* create_disposition*/
7246 FILE_DIRECTORY_FILE, /* create_options */
7247 mod_unixmode, /* file_attributes */
7248 0, /* oplock_request */
7249 0, /* allocation_size */
7250 0, /* private_flags */
7251 NULL, /* sd */
7252 NULL, /* ea_list */
7253 &fsp, /* result */
7254 &info); /* pinfo */
7256 if (NT_STATUS_IS_OK(status)) {
7257 close_file(req, fsp, NORMAL_CLOSE);
7260 info_level_return = SVAL(pdata,16);
7262 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7263 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7264 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7265 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7266 } else {
7267 *pdata_return_size = 12;
7270 /* Realloc the data size */
7271 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7272 if (*ppdata == NULL) {
7273 *pdata_return_size = 0;
7274 return NT_STATUS_NO_MEMORY;
7276 pdata = *ppdata;
7278 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7279 SSVAL(pdata,2,0); /* No fnum. */
7280 SIVAL(pdata,4,info); /* Was directory created. */
7282 switch (info_level_return) {
7283 case SMB_QUERY_FILE_UNIX_BASIC:
7284 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7285 SSVAL(pdata,10,0); /* Padding. */
7286 store_file_unix_basic(conn, pdata + 12, fsp,
7287 &smb_fname->st);
7288 break;
7289 case SMB_QUERY_FILE_UNIX_INFO2:
7290 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7291 SSVAL(pdata,10,0); /* Padding. */
7292 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7293 &smb_fname->st);
7294 break;
7295 default:
7296 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7297 SSVAL(pdata,10,0); /* Padding. */
7298 break;
7301 return status;
7304 /****************************************************************************
7305 Open/Create a file with POSIX semantics.
7306 ****************************************************************************/
7308 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7309 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7311 static NTSTATUS smb_posix_open(connection_struct *conn,
7312 struct smb_request *req,
7313 char **ppdata,
7314 int total_data,
7315 struct smb_filename *smb_fname,
7316 int *pdata_return_size)
7318 bool extended_oplock_granted = False;
7319 char *pdata = *ppdata;
7320 uint32 flags = 0;
7321 uint32 wire_open_mode = 0;
7322 uint32 raw_unixmode = 0;
7323 uint32 mod_unixmode = 0;
7324 uint32 create_disp = 0;
7325 uint32 access_mask = 0;
7326 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7327 NTSTATUS status = NT_STATUS_OK;
7328 mode_t unixmode = (mode_t)0;
7329 files_struct *fsp = NULL;
7330 int oplock_request = 0;
7331 int info = 0;
7332 uint16 info_level_return = 0;
7334 if (total_data < 18) {
7335 return NT_STATUS_INVALID_PARAMETER;
7338 flags = IVAL(pdata,0);
7339 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7340 if (oplock_request) {
7341 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7344 wire_open_mode = IVAL(pdata,4);
7346 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7347 return smb_posix_mkdir(conn, req,
7348 ppdata,
7349 total_data,
7350 smb_fname,
7351 pdata_return_size);
7354 switch (wire_open_mode & SMB_ACCMODE) {
7355 case SMB_O_RDONLY:
7356 access_mask = SMB_O_RDONLY_MAPPING;
7357 break;
7358 case SMB_O_WRONLY:
7359 access_mask = SMB_O_WRONLY_MAPPING;
7360 break;
7361 case SMB_O_RDWR:
7362 access_mask = (SMB_O_RDONLY_MAPPING|
7363 SMB_O_WRONLY_MAPPING);
7364 break;
7365 default:
7366 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7367 (unsigned int)wire_open_mode ));
7368 return NT_STATUS_INVALID_PARAMETER;
7371 wire_open_mode &= ~SMB_ACCMODE;
7373 /* First take care of O_CREAT|O_EXCL interactions. */
7374 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7375 case (SMB_O_CREAT | SMB_O_EXCL):
7376 /* File exists fail. File not exist create. */
7377 create_disp = FILE_CREATE;
7378 break;
7379 case SMB_O_CREAT:
7380 /* File exists open. File not exist create. */
7381 create_disp = FILE_OPEN_IF;
7382 break;
7383 case SMB_O_EXCL:
7384 /* O_EXCL on its own without O_CREAT is undefined.
7385 We deliberately ignore it as some versions of
7386 Linux CIFSFS can send a bare O_EXCL on the
7387 wire which other filesystems in the kernel
7388 ignore. See bug 9519 for details. */
7390 /* Fallthrough. */
7392 case 0:
7393 /* File exists open. File not exist fail. */
7394 create_disp = FILE_OPEN;
7395 break;
7396 default:
7397 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7398 (unsigned int)wire_open_mode ));
7399 return NT_STATUS_INVALID_PARAMETER;
7402 /* Next factor in the effects of O_TRUNC. */
7403 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7405 if (wire_open_mode & SMB_O_TRUNC) {
7406 switch (create_disp) {
7407 case FILE_CREATE:
7408 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7409 /* Leave create_disp alone as
7410 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7412 /* File exists fail. File not exist create. */
7413 break;
7414 case FILE_OPEN_IF:
7415 /* SMB_O_CREAT | SMB_O_TRUNC */
7416 /* File exists overwrite. File not exist create. */
7417 create_disp = FILE_OVERWRITE_IF;
7418 break;
7419 case FILE_OPEN:
7420 /* SMB_O_TRUNC */
7421 /* File exists overwrite. File not exist fail. */
7422 create_disp = FILE_OVERWRITE;
7423 break;
7424 default:
7425 /* Cannot get here. */
7426 smb_panic("smb_posix_open: logic error");
7427 return NT_STATUS_INVALID_PARAMETER;
7431 raw_unixmode = IVAL(pdata,8);
7432 /* Next 4 bytes are not yet defined. */
7434 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7435 (VALID_STAT(smb_fname->st) ?
7436 PERM_EXISTING_FILE : PERM_NEW_FILE),
7437 &unixmode);
7439 if (!NT_STATUS_IS_OK(status)) {
7440 return status;
7443 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7445 if (wire_open_mode & SMB_O_SYNC) {
7446 create_options |= FILE_WRITE_THROUGH;
7448 if (wire_open_mode & SMB_O_APPEND) {
7449 access_mask |= FILE_APPEND_DATA;
7451 if (wire_open_mode & SMB_O_DIRECT) {
7452 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7455 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7456 VALID_STAT_OF_DIR(smb_fname->st)) {
7457 if (access_mask != SMB_O_RDONLY_MAPPING) {
7458 return NT_STATUS_FILE_IS_A_DIRECTORY;
7460 create_options &= ~FILE_NON_DIRECTORY_FILE;
7461 create_options |= FILE_DIRECTORY_FILE;
7464 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7465 smb_fname_str_dbg(smb_fname),
7466 (unsigned int)wire_open_mode,
7467 (unsigned int)unixmode ));
7469 status = SMB_VFS_CREATE_FILE(
7470 conn, /* conn */
7471 req, /* req */
7472 0, /* root_dir_fid */
7473 smb_fname, /* fname */
7474 access_mask, /* access_mask */
7475 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7476 FILE_SHARE_DELETE),
7477 create_disp, /* create_disposition*/
7478 create_options, /* create_options */
7479 mod_unixmode, /* file_attributes */
7480 oplock_request, /* oplock_request */
7481 0, /* allocation_size */
7482 0, /* private_flags */
7483 NULL, /* sd */
7484 NULL, /* ea_list */
7485 &fsp, /* result */
7486 &info); /* pinfo */
7488 if (!NT_STATUS_IS_OK(status)) {
7489 return status;
7492 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7493 extended_oplock_granted = True;
7496 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7497 extended_oplock_granted = True;
7500 info_level_return = SVAL(pdata,16);
7502 /* Allocate the correct return size. */
7504 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7505 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7506 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7507 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7508 } else {
7509 *pdata_return_size = 12;
7512 /* Realloc the data size */
7513 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7514 if (*ppdata == NULL) {
7515 close_file(req, fsp, ERROR_CLOSE);
7516 *pdata_return_size = 0;
7517 return NT_STATUS_NO_MEMORY;
7519 pdata = *ppdata;
7521 if (extended_oplock_granted) {
7522 if (flags & REQUEST_BATCH_OPLOCK) {
7523 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7524 } else {
7525 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7527 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7528 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7529 } else {
7530 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7533 SSVAL(pdata,2,fsp->fnum);
7534 SIVAL(pdata,4,info); /* Was file created etc. */
7536 switch (info_level_return) {
7537 case SMB_QUERY_FILE_UNIX_BASIC:
7538 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7539 SSVAL(pdata,10,0); /* padding. */
7540 store_file_unix_basic(conn, pdata + 12, fsp,
7541 &smb_fname->st);
7542 break;
7543 case SMB_QUERY_FILE_UNIX_INFO2:
7544 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7545 SSVAL(pdata,10,0); /* padding. */
7546 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7547 &smb_fname->st);
7548 break;
7549 default:
7550 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7551 SSVAL(pdata,10,0); /* padding. */
7552 break;
7554 return NT_STATUS_OK;
7557 /****************************************************************************
7558 Delete a file with POSIX semantics.
7559 ****************************************************************************/
7561 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7562 struct smb_request *req,
7563 const char *pdata,
7564 int total_data,
7565 struct smb_filename *smb_fname)
7567 NTSTATUS status = NT_STATUS_OK;
7568 files_struct *fsp = NULL;
7569 uint16 flags = 0;
7570 char del = 1;
7571 int info = 0;
7572 int create_options = 0;
7573 int i;
7574 struct share_mode_lock *lck = NULL;
7576 if (total_data < 2) {
7577 return NT_STATUS_INVALID_PARAMETER;
7580 flags = SVAL(pdata,0);
7582 if (!VALID_STAT(smb_fname->st)) {
7583 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7586 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7587 !VALID_STAT_OF_DIR(smb_fname->st)) {
7588 return NT_STATUS_NOT_A_DIRECTORY;
7591 DEBUG(10,("smb_posix_unlink: %s %s\n",
7592 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7593 smb_fname_str_dbg(smb_fname)));
7595 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7596 create_options |= FILE_DIRECTORY_FILE;
7599 status = SMB_VFS_CREATE_FILE(
7600 conn, /* conn */
7601 req, /* req */
7602 0, /* root_dir_fid */
7603 smb_fname, /* fname */
7604 DELETE_ACCESS, /* access_mask */
7605 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7606 FILE_SHARE_DELETE),
7607 FILE_OPEN, /* create_disposition*/
7608 create_options, /* create_options */
7609 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7610 0, /* oplock_request */
7611 0, /* allocation_size */
7612 0, /* private_flags */
7613 NULL, /* sd */
7614 NULL, /* ea_list */
7615 &fsp, /* result */
7616 &info); /* pinfo */
7618 if (!NT_STATUS_IS_OK(status)) {
7619 return status;
7623 * Don't lie to client. If we can't really delete due to
7624 * non-POSIX opens return SHARING_VIOLATION.
7627 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7628 NULL);
7629 if (lck == NULL) {
7630 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7631 "lock for file %s\n", fsp_str_dbg(fsp)));
7632 close_file(req, fsp, NORMAL_CLOSE);
7633 return NT_STATUS_INVALID_PARAMETER;
7637 * See if others still have the file open. If this is the case, then
7638 * don't delete. If all opens are POSIX delete we can set the delete
7639 * on close disposition.
7641 for (i=0; i<lck->num_share_modes; i++) {
7642 struct share_mode_entry *e = &lck->share_modes[i];
7643 if (is_valid_share_mode_entry(e)) {
7644 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7645 continue;
7647 /* Fail with sharing violation. */
7648 TALLOC_FREE(lck);
7649 close_file(req, fsp, NORMAL_CLOSE);
7650 return NT_STATUS_SHARING_VIOLATION;
7655 * Set the delete on close.
7657 status = smb_set_file_disposition_info(conn,
7658 &del,
7660 fsp,
7661 smb_fname);
7663 TALLOC_FREE(lck);
7665 if (!NT_STATUS_IS_OK(status)) {
7666 close_file(req, fsp, NORMAL_CLOSE);
7667 return status;
7669 return close_file(req, fsp, NORMAL_CLOSE);
7672 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7673 struct smb_request *req,
7674 TALLOC_CTX *mem_ctx,
7675 uint16_t info_level,
7676 files_struct *fsp,
7677 struct smb_filename *smb_fname,
7678 char **ppdata, int total_data,
7679 int *ret_data_size)
7681 char *pdata = *ppdata;
7682 NTSTATUS status = NT_STATUS_OK;
7683 int data_return_size = 0;
7685 *ret_data_size = 0;
7687 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7688 return NT_STATUS_INVALID_LEVEL;
7691 if (!CAN_WRITE(conn)) {
7692 /* Allow POSIX opens. The open path will deny
7693 * any non-readonly opens. */
7694 if (info_level != SMB_POSIX_PATH_OPEN) {
7695 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7699 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7700 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7701 fsp ? fsp->fnum : -1, info_level, total_data));
7703 switch (info_level) {
7705 case SMB_INFO_STANDARD:
7707 status = smb_set_info_standard(conn,
7708 pdata,
7709 total_data,
7710 fsp,
7711 smb_fname);
7712 break;
7715 case SMB_INFO_SET_EA:
7717 status = smb_info_set_ea(conn,
7718 pdata,
7719 total_data,
7720 fsp,
7721 smb_fname);
7722 break;
7725 case SMB_SET_FILE_BASIC_INFO:
7726 case SMB_FILE_BASIC_INFORMATION:
7728 status = smb_set_file_basic_info(conn,
7729 pdata,
7730 total_data,
7731 fsp,
7732 smb_fname);
7733 break;
7736 case SMB_FILE_ALLOCATION_INFORMATION:
7737 case SMB_SET_FILE_ALLOCATION_INFO:
7739 status = smb_set_file_allocation_info(conn, req,
7740 pdata,
7741 total_data,
7742 fsp,
7743 smb_fname);
7744 break;
7747 case SMB_FILE_END_OF_FILE_INFORMATION:
7748 case SMB_SET_FILE_END_OF_FILE_INFO:
7751 * XP/Win7 both fail after the createfile with
7752 * SMB_SET_FILE_END_OF_FILE_INFO but not
7753 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7754 * The level is known here, so pass it down
7755 * appropriately.
7757 bool should_fail =
7758 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7760 status = smb_set_file_end_of_file_info(conn, req,
7761 pdata,
7762 total_data,
7763 fsp,
7764 smb_fname,
7765 should_fail);
7766 break;
7769 case SMB_FILE_DISPOSITION_INFORMATION:
7770 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7772 #if 0
7773 /* JRA - We used to just ignore this on a path ?
7774 * Shouldn't this be invalid level on a pathname
7775 * based call ?
7777 if (tran_call != TRANSACT2_SETFILEINFO) {
7778 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7780 #endif
7781 status = smb_set_file_disposition_info(conn,
7782 pdata,
7783 total_data,
7784 fsp,
7785 smb_fname);
7786 break;
7789 case SMB_FILE_POSITION_INFORMATION:
7791 status = smb_file_position_information(conn,
7792 pdata,
7793 total_data,
7794 fsp);
7795 break;
7798 case SMB_FILE_FULL_EA_INFORMATION:
7800 status = smb_set_file_full_ea_info(conn,
7801 pdata,
7802 total_data,
7803 fsp);
7804 break;
7807 /* From tridge Samba4 :
7808 * MODE_INFORMATION in setfileinfo (I have no
7809 * idea what "mode information" on a file is - it takes a value of 0,
7810 * 2, 4 or 6. What could it be?).
7813 case SMB_FILE_MODE_INFORMATION:
7815 status = smb_file_mode_information(conn,
7816 pdata,
7817 total_data);
7818 break;
7822 * CIFS UNIX extensions.
7825 case SMB_SET_FILE_UNIX_BASIC:
7827 status = smb_set_file_unix_basic(conn, req,
7828 pdata,
7829 total_data,
7830 fsp,
7831 smb_fname);
7832 break;
7835 case SMB_SET_FILE_UNIX_INFO2:
7837 status = smb_set_file_unix_info2(conn, req,
7838 pdata,
7839 total_data,
7840 fsp,
7841 smb_fname);
7842 break;
7845 case SMB_SET_FILE_UNIX_LINK:
7847 if (fsp) {
7848 /* We must have a pathname for this. */
7849 return NT_STATUS_INVALID_LEVEL;
7851 status = smb_set_file_unix_link(conn, req, pdata,
7852 total_data, smb_fname);
7853 break;
7856 case SMB_SET_FILE_UNIX_HLINK:
7858 if (fsp) {
7859 /* We must have a pathname for this. */
7860 return NT_STATUS_INVALID_LEVEL;
7862 status = smb_set_file_unix_hlink(conn, req,
7863 pdata, total_data,
7864 smb_fname);
7865 break;
7868 case SMB_FILE_RENAME_INFORMATION:
7870 status = smb_file_rename_information(conn, req,
7871 pdata, total_data,
7872 fsp, smb_fname);
7873 break;
7876 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7878 /* SMB2 rename information. */
7879 status = smb2_file_rename_information(conn, req,
7880 pdata, total_data,
7881 fsp, smb_fname);
7882 break;
7885 case SMB_FILE_LINK_INFORMATION:
7887 status = smb_file_link_information(conn, req,
7888 pdata, total_data,
7889 fsp, smb_fname);
7890 break;
7893 #if defined(HAVE_POSIX_ACLS)
7894 case SMB_SET_POSIX_ACL:
7896 status = smb_set_posix_acl(conn,
7897 pdata,
7898 total_data,
7899 fsp,
7900 smb_fname);
7901 break;
7903 #endif
7905 case SMB_SET_POSIX_LOCK:
7907 if (!fsp) {
7908 return NT_STATUS_INVALID_LEVEL;
7910 status = smb_set_posix_lock(conn, req,
7911 pdata, total_data, fsp);
7912 break;
7915 case SMB_POSIX_PATH_OPEN:
7917 if (fsp) {
7918 /* We must have a pathname for this. */
7919 return NT_STATUS_INVALID_LEVEL;
7922 status = smb_posix_open(conn, req,
7923 ppdata,
7924 total_data,
7925 smb_fname,
7926 &data_return_size);
7927 break;
7930 case SMB_POSIX_PATH_UNLINK:
7932 if (fsp) {
7933 /* We must have a pathname for this. */
7934 return NT_STATUS_INVALID_LEVEL;
7937 status = smb_posix_unlink(conn, req,
7938 pdata,
7939 total_data,
7940 smb_fname);
7941 break;
7944 default:
7945 return NT_STATUS_INVALID_LEVEL;
7948 if (!NT_STATUS_IS_OK(status)) {
7949 return status;
7952 *ret_data_size = data_return_size;
7953 return NT_STATUS_OK;
7956 /****************************************************************************
7957 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7958 ****************************************************************************/
7960 static void call_trans2setfilepathinfo(connection_struct *conn,
7961 struct smb_request *req,
7962 unsigned int tran_call,
7963 char **pparams, int total_params,
7964 char **ppdata, int total_data,
7965 unsigned int max_data_bytes)
7967 char *params = *pparams;
7968 char *pdata = *ppdata;
7969 uint16 info_level;
7970 struct smb_filename *smb_fname = NULL;
7971 files_struct *fsp = NULL;
7972 NTSTATUS status = NT_STATUS_OK;
7973 int data_return_size = 0;
7975 if (!params) {
7976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7977 return;
7980 if (tran_call == TRANSACT2_SETFILEINFO) {
7981 if (total_params < 4) {
7982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7983 return;
7986 fsp = file_fsp(req, SVAL(params,0));
7987 /* Basic check for non-null fsp. */
7988 if (!check_fsp_open(conn, req, fsp)) {
7989 return;
7991 info_level = SVAL(params,2);
7993 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7994 &smb_fname);
7995 if (!NT_STATUS_IS_OK(status)) {
7996 reply_nterror(req, status);
7997 return;
8000 if(fsp->fh->fd == -1) {
8002 * This is actually a SETFILEINFO on a directory
8003 * handle (returned from an NT SMB). NT5.0 seems
8004 * to do this call. JRA.
8006 if (INFO_LEVEL_IS_UNIX(info_level)) {
8007 /* Always do lstat for UNIX calls. */
8008 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8009 DEBUG(3,("call_trans2setfilepathinfo: "
8010 "SMB_VFS_LSTAT of %s failed "
8011 "(%s)\n",
8012 smb_fname_str_dbg(smb_fname),
8013 strerror(errno)));
8014 reply_nterror(req, map_nt_error_from_unix(errno));
8015 return;
8017 } else {
8018 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8019 DEBUG(3,("call_trans2setfilepathinfo: "
8020 "fileinfo of %s failed (%s)\n",
8021 smb_fname_str_dbg(smb_fname),
8022 strerror(errno)));
8023 reply_nterror(req, map_nt_error_from_unix(errno));
8024 return;
8027 } else if (fsp->print_file) {
8029 * Doing a DELETE_ON_CLOSE should cancel a print job.
8031 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8032 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8034 DEBUG(3,("call_trans2setfilepathinfo: "
8035 "Cancelling print job (%s)\n",
8036 fsp_str_dbg(fsp)));
8038 SSVAL(params,0,0);
8039 send_trans2_replies(conn, req, params, 2,
8040 *ppdata, 0,
8041 max_data_bytes);
8042 return;
8043 } else {
8044 reply_nterror(req,
8045 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8046 return;
8048 } else {
8050 * Original code - this is an open file.
8052 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8053 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8054 "of fnum %d failed (%s)\n", fsp->fnum,
8055 strerror(errno)));
8056 reply_nterror(req, map_nt_error_from_unix(errno));
8057 return;
8060 } else {
8061 char *fname = NULL;
8062 uint32_t ucf_flags = 0;
8064 /* set path info */
8065 if (total_params < 7) {
8066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8067 return;
8070 info_level = SVAL(params,0);
8071 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8072 total_params - 6, STR_TERMINATE,
8073 &status);
8074 if (!NT_STATUS_IS_OK(status)) {
8075 reply_nterror(req, status);
8076 return;
8079 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8080 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8081 info_level == SMB_FILE_RENAME_INFORMATION ||
8082 info_level == SMB_POSIX_PATH_UNLINK) {
8083 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8086 status = filename_convert(req, conn,
8087 req->flags2 & FLAGS2_DFS_PATHNAMES,
8088 fname,
8089 ucf_flags,
8090 NULL,
8091 &smb_fname);
8092 if (!NT_STATUS_IS_OK(status)) {
8093 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8094 reply_botherror(req,
8095 NT_STATUS_PATH_NOT_COVERED,
8096 ERRSRV, ERRbadpath);
8097 return;
8099 reply_nterror(req, status);
8100 return;
8103 if (INFO_LEVEL_IS_UNIX(info_level)) {
8105 * For CIFS UNIX extensions the target name may not exist.
8108 /* Always do lstat for UNIX calls. */
8109 SMB_VFS_LSTAT(conn, smb_fname);
8111 } else if (!VALID_STAT(smb_fname->st) &&
8112 SMB_VFS_STAT(conn, smb_fname)) {
8113 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8114 "%s failed (%s)\n",
8115 smb_fname_str_dbg(smb_fname),
8116 strerror(errno)));
8117 reply_nterror(req, map_nt_error_from_unix(errno));
8118 return;
8122 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8123 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8124 fsp ? fsp->fnum : -1, info_level,total_data));
8126 /* Realloc the parameter size */
8127 *pparams = (char *)SMB_REALLOC(*pparams,2);
8128 if (*pparams == NULL) {
8129 reply_nterror(req, NT_STATUS_NO_MEMORY);
8130 return;
8132 params = *pparams;
8134 SSVAL(params,0,0);
8136 status = smbd_do_setfilepathinfo(conn, req, req,
8137 info_level,
8138 fsp,
8139 smb_fname,
8140 ppdata, total_data,
8141 &data_return_size);
8142 if (!NT_STATUS_IS_OK(status)) {
8143 if (open_was_deferred(req->mid)) {
8144 /* We have re-scheduled this call. */
8145 return;
8147 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8148 /* We have re-scheduled this call. */
8149 return;
8151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8152 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8153 ERRSRV, ERRbadpath);
8154 return;
8156 if (info_level == SMB_POSIX_PATH_OPEN) {
8157 reply_openerror(req, status);
8158 return;
8161 reply_nterror(req, status);
8162 return;
8165 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8166 max_data_bytes);
8168 return;
8171 /****************************************************************************
8172 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8173 ****************************************************************************/
8175 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8176 char **pparams, int total_params,
8177 char **ppdata, int total_data,
8178 unsigned int max_data_bytes)
8180 struct smb_filename *smb_dname = NULL;
8181 char *params = *pparams;
8182 char *pdata = *ppdata;
8183 char *directory = NULL;
8184 NTSTATUS status = NT_STATUS_OK;
8185 struct ea_list *ea_list = NULL;
8186 TALLOC_CTX *ctx = talloc_tos();
8188 if (!CAN_WRITE(conn)) {
8189 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8190 return;
8193 if (total_params < 5) {
8194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 return;
8198 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8199 total_params - 4, STR_TERMINATE,
8200 &status);
8201 if (!NT_STATUS_IS_OK(status)) {
8202 reply_nterror(req, status);
8203 return;
8206 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8208 status = filename_convert(ctx,
8209 conn,
8210 req->flags2 & FLAGS2_DFS_PATHNAMES,
8211 directory,
8213 NULL,
8214 &smb_dname);
8216 if (!NT_STATUS_IS_OK(status)) {
8217 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8218 reply_botherror(req,
8219 NT_STATUS_PATH_NOT_COVERED,
8220 ERRSRV, ERRbadpath);
8221 return;
8223 reply_nterror(req, status);
8224 return;
8228 * OS/2 workplace shell seems to send SET_EA requests of "null"
8229 * length (4 bytes containing IVAL 4).
8230 * They seem to have no effect. Bug #3212. JRA.
8233 if (total_data && (total_data != 4)) {
8234 /* Any data in this call is an EA list. */
8235 if (total_data < 10) {
8236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8237 goto out;
8240 if (IVAL(pdata,0) > total_data) {
8241 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8242 IVAL(pdata,0), (unsigned int)total_data));
8243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8244 goto out;
8247 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8248 total_data - 4);
8249 if (!ea_list) {
8250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8251 goto out;
8254 if (!lp_ea_support(SNUM(conn))) {
8255 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8256 goto out;
8259 /* If total_data == 4 Windows doesn't care what values
8260 * are placed in that field, it just ignores them.
8261 * The System i QNTC IBM SMB client puts bad values here,
8262 * so ignore them. */
8264 status = create_directory(conn, req, smb_dname);
8266 if (!NT_STATUS_IS_OK(status)) {
8267 reply_nterror(req, status);
8268 goto out;
8271 /* Try and set any given EA. */
8272 if (ea_list) {
8273 status = set_ea(conn, NULL, smb_dname, ea_list);
8274 if (!NT_STATUS_IS_OK(status)) {
8275 reply_nterror(req, status);
8276 goto out;
8280 /* Realloc the parameter and data sizes */
8281 *pparams = (char *)SMB_REALLOC(*pparams,2);
8282 if(*pparams == NULL) {
8283 reply_nterror(req, NT_STATUS_NO_MEMORY);
8284 goto out;
8286 params = *pparams;
8288 SSVAL(params,0,0);
8290 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8292 out:
8293 TALLOC_FREE(smb_dname);
8294 return;
8297 /****************************************************************************
8298 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8299 We don't actually do this - we just send a null response.
8300 ****************************************************************************/
8302 static void call_trans2findnotifyfirst(connection_struct *conn,
8303 struct smb_request *req,
8304 char **pparams, int total_params,
8305 char **ppdata, int total_data,
8306 unsigned int max_data_bytes)
8308 char *params = *pparams;
8309 uint16 info_level;
8311 if (total_params < 6) {
8312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8313 return;
8316 info_level = SVAL(params,4);
8317 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8319 switch (info_level) {
8320 case 1:
8321 case 2:
8322 break;
8323 default:
8324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8325 return;
8328 /* Realloc the parameter and data sizes */
8329 *pparams = (char *)SMB_REALLOC(*pparams,6);
8330 if (*pparams == NULL) {
8331 reply_nterror(req, NT_STATUS_NO_MEMORY);
8332 return;
8334 params = *pparams;
8336 SSVAL(params,0,fnf_handle);
8337 SSVAL(params,2,0); /* No changes */
8338 SSVAL(params,4,0); /* No EA errors */
8340 fnf_handle++;
8342 if(fnf_handle == 0)
8343 fnf_handle = 257;
8345 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8347 return;
8350 /****************************************************************************
8351 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8352 changes). Currently this does nothing.
8353 ****************************************************************************/
8355 static void call_trans2findnotifynext(connection_struct *conn,
8356 struct smb_request *req,
8357 char **pparams, int total_params,
8358 char **ppdata, int total_data,
8359 unsigned int max_data_bytes)
8361 char *params = *pparams;
8363 DEBUG(3,("call_trans2findnotifynext\n"));
8365 /* Realloc the parameter and data sizes */
8366 *pparams = (char *)SMB_REALLOC(*pparams,4);
8367 if (*pparams == NULL) {
8368 reply_nterror(req, NT_STATUS_NO_MEMORY);
8369 return;
8371 params = *pparams;
8373 SSVAL(params,0,0); /* No changes */
8374 SSVAL(params,2,0); /* No EA errors */
8376 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8378 return;
8381 /****************************************************************************
8382 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8383 ****************************************************************************/
8385 static void call_trans2getdfsreferral(connection_struct *conn,
8386 struct smb_request *req,
8387 char **pparams, int total_params,
8388 char **ppdata, int total_data,
8389 unsigned int max_data_bytes)
8391 char *params = *pparams;
8392 char *pathname = NULL;
8393 int reply_size = 0;
8394 int max_referral_level;
8395 NTSTATUS status = NT_STATUS_OK;
8396 TALLOC_CTX *ctx = talloc_tos();
8398 DEBUG(10,("call_trans2getdfsreferral\n"));
8400 if (total_params < 3) {
8401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8402 return;
8405 max_referral_level = SVAL(params,0);
8407 if(!lp_host_msdfs()) {
8408 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8409 return;
8412 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8413 total_params - 2, STR_TERMINATE);
8414 if (!pathname) {
8415 reply_nterror(req, NT_STATUS_NOT_FOUND);
8416 return;
8418 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8419 ppdata,&status)) < 0) {
8420 reply_nterror(req, status);
8421 return;
8424 SSVAL(req->inbuf, smb_flg2,
8425 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8426 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8428 return;
8431 #define LMCAT_SPL 0x53
8432 #define LMFUNC_GETJOBID 0x60
8434 /****************************************************************************
8435 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8436 ****************************************************************************/
8438 static void call_trans2ioctl(connection_struct *conn,
8439 struct smb_request *req,
8440 char **pparams, int total_params,
8441 char **ppdata, int total_data,
8442 unsigned int max_data_bytes)
8444 char *pdata = *ppdata;
8445 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8447 /* check for an invalid fid before proceeding */
8449 if (!fsp) {
8450 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8451 return;
8454 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8455 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8456 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8457 if (*ppdata == NULL) {
8458 reply_nterror(req, NT_STATUS_NO_MEMORY);
8459 return;
8461 pdata = *ppdata;
8463 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8464 CAN ACCEPT THIS IN UNICODE. JRA. */
8466 /* Job number */
8467 if (fsp->print_file) {
8468 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8469 } else {
8470 SSVAL(pdata, 0, 0);
8472 srvstr_push(pdata, req->flags2, pdata + 2,
8473 global_myname(), 15,
8474 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8475 srvstr_push(pdata, req->flags2, pdata+18,
8476 lp_servicename(SNUM(conn)), 13,
8477 STR_ASCII|STR_TERMINATE); /* Service name */
8478 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8479 max_data_bytes);
8480 return;
8483 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8484 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8487 /****************************************************************************
8488 Reply to a SMBfindclose (stop trans2 directory search).
8489 ****************************************************************************/
8491 void reply_findclose(struct smb_request *req)
8493 int dptr_num;
8494 struct smbd_server_connection *sconn = req->sconn;
8496 START_PROFILE(SMBfindclose);
8498 if (req->wct < 1) {
8499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8500 END_PROFILE(SMBfindclose);
8501 return;
8504 dptr_num = SVALS(req->vwv+0, 0);
8506 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8508 dptr_close(sconn, &dptr_num);
8510 reply_outbuf(req, 0, 0);
8512 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8514 END_PROFILE(SMBfindclose);
8515 return;
8518 /****************************************************************************
8519 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8520 ****************************************************************************/
8522 void reply_findnclose(struct smb_request *req)
8524 int dptr_num;
8526 START_PROFILE(SMBfindnclose);
8528 if (req->wct < 1) {
8529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8530 END_PROFILE(SMBfindnclose);
8531 return;
8534 dptr_num = SVAL(req->vwv+0, 0);
8536 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8538 /* We never give out valid handles for a
8539 findnotifyfirst - so any dptr_num is ok here.
8540 Just ignore it. */
8542 reply_outbuf(req, 0, 0);
8544 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8546 END_PROFILE(SMBfindnclose);
8547 return;
8550 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8551 struct trans_state *state)
8553 if (get_Protocol() >= PROTOCOL_NT1) {
8554 req->flags2 |= 0x40; /* IS_LONG_NAME */
8555 SSVAL(req->inbuf,smb_flg2,req->flags2);
8558 if (conn->encrypt_level == Required && !req->encrypted) {
8559 if (state->call != TRANSACT2_QFSINFO &&
8560 state->call != TRANSACT2_SETFSINFO) {
8561 DEBUG(0,("handle_trans2: encryption required "
8562 "with call 0x%x\n",
8563 (unsigned int)state->call));
8564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8565 return;
8569 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8571 /* Now we must call the relevant TRANS2 function */
8572 switch(state->call) {
8573 case TRANSACT2_OPEN:
8575 START_PROFILE(Trans2_open);
8576 call_trans2open(conn, req,
8577 &state->param, state->total_param,
8578 &state->data, state->total_data,
8579 state->max_data_return);
8580 END_PROFILE(Trans2_open);
8581 break;
8584 case TRANSACT2_FINDFIRST:
8586 START_PROFILE(Trans2_findfirst);
8587 call_trans2findfirst(conn, req,
8588 &state->param, state->total_param,
8589 &state->data, state->total_data,
8590 state->max_data_return);
8591 END_PROFILE(Trans2_findfirst);
8592 break;
8595 case TRANSACT2_FINDNEXT:
8597 START_PROFILE(Trans2_findnext);
8598 call_trans2findnext(conn, req,
8599 &state->param, state->total_param,
8600 &state->data, state->total_data,
8601 state->max_data_return);
8602 END_PROFILE(Trans2_findnext);
8603 break;
8606 case TRANSACT2_QFSINFO:
8608 START_PROFILE(Trans2_qfsinfo);
8609 call_trans2qfsinfo(conn, req,
8610 &state->param, state->total_param,
8611 &state->data, state->total_data,
8612 state->max_data_return);
8613 END_PROFILE(Trans2_qfsinfo);
8614 break;
8617 case TRANSACT2_SETFSINFO:
8619 START_PROFILE(Trans2_setfsinfo);
8620 call_trans2setfsinfo(conn, req,
8621 &state->param, state->total_param,
8622 &state->data, state->total_data,
8623 state->max_data_return);
8624 END_PROFILE(Trans2_setfsinfo);
8625 break;
8628 case TRANSACT2_QPATHINFO:
8629 case TRANSACT2_QFILEINFO:
8631 START_PROFILE(Trans2_qpathinfo);
8632 call_trans2qfilepathinfo(conn, req, state->call,
8633 &state->param, state->total_param,
8634 &state->data, state->total_data,
8635 state->max_data_return);
8636 END_PROFILE(Trans2_qpathinfo);
8637 break;
8640 case TRANSACT2_SETPATHINFO:
8641 case TRANSACT2_SETFILEINFO:
8643 START_PROFILE(Trans2_setpathinfo);
8644 call_trans2setfilepathinfo(conn, req, state->call,
8645 &state->param, state->total_param,
8646 &state->data, state->total_data,
8647 state->max_data_return);
8648 END_PROFILE(Trans2_setpathinfo);
8649 break;
8652 case TRANSACT2_FINDNOTIFYFIRST:
8654 START_PROFILE(Trans2_findnotifyfirst);
8655 call_trans2findnotifyfirst(conn, req,
8656 &state->param, state->total_param,
8657 &state->data, state->total_data,
8658 state->max_data_return);
8659 END_PROFILE(Trans2_findnotifyfirst);
8660 break;
8663 case TRANSACT2_FINDNOTIFYNEXT:
8665 START_PROFILE(Trans2_findnotifynext);
8666 call_trans2findnotifynext(conn, req,
8667 &state->param, state->total_param,
8668 &state->data, state->total_data,
8669 state->max_data_return);
8670 END_PROFILE(Trans2_findnotifynext);
8671 break;
8674 case TRANSACT2_MKDIR:
8676 START_PROFILE(Trans2_mkdir);
8677 call_trans2mkdir(conn, req,
8678 &state->param, state->total_param,
8679 &state->data, state->total_data,
8680 state->max_data_return);
8681 END_PROFILE(Trans2_mkdir);
8682 break;
8685 case TRANSACT2_GET_DFS_REFERRAL:
8687 START_PROFILE(Trans2_get_dfs_referral);
8688 call_trans2getdfsreferral(conn, req,
8689 &state->param, state->total_param,
8690 &state->data, state->total_data,
8691 state->max_data_return);
8692 END_PROFILE(Trans2_get_dfs_referral);
8693 break;
8696 case TRANSACT2_IOCTL:
8698 START_PROFILE(Trans2_ioctl);
8699 call_trans2ioctl(conn, req,
8700 &state->param, state->total_param,
8701 &state->data, state->total_data,
8702 state->max_data_return);
8703 END_PROFILE(Trans2_ioctl);
8704 break;
8707 default:
8708 /* Error in request */
8709 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8710 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8714 /****************************************************************************
8715 Reply to a SMBtrans2.
8716 ****************************************************************************/
8718 void reply_trans2(struct smb_request *req)
8720 connection_struct *conn = req->conn;
8721 unsigned int dsoff;
8722 unsigned int dscnt;
8723 unsigned int psoff;
8724 unsigned int pscnt;
8725 unsigned int tran_call;
8726 struct trans_state *state;
8727 NTSTATUS result;
8729 START_PROFILE(SMBtrans2);
8731 if (req->wct < 14) {
8732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8733 END_PROFILE(SMBtrans2);
8734 return;
8737 dsoff = SVAL(req->vwv+12, 0);
8738 dscnt = SVAL(req->vwv+11, 0);
8739 psoff = SVAL(req->vwv+10, 0);
8740 pscnt = SVAL(req->vwv+9, 0);
8741 tran_call = SVAL(req->vwv+14, 0);
8743 result = allow_new_trans(conn->pending_trans, req->mid);
8744 if (!NT_STATUS_IS_OK(result)) {
8745 DEBUG(2, ("Got invalid trans2 request: %s\n",
8746 nt_errstr(result)));
8747 reply_nterror(req, result);
8748 END_PROFILE(SMBtrans2);
8749 return;
8752 if (IS_IPC(conn)) {
8753 switch (tran_call) {
8754 /* List the allowed trans2 calls on IPC$ */
8755 case TRANSACT2_OPEN:
8756 case TRANSACT2_GET_DFS_REFERRAL:
8757 case TRANSACT2_QFILEINFO:
8758 case TRANSACT2_QFSINFO:
8759 case TRANSACT2_SETFSINFO:
8760 break;
8761 default:
8762 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8763 END_PROFILE(SMBtrans2);
8764 return;
8768 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8769 DEBUG(0, ("talloc failed\n"));
8770 reply_nterror(req, NT_STATUS_NO_MEMORY);
8771 END_PROFILE(SMBtrans2);
8772 return;
8775 state->cmd = SMBtrans2;
8777 state->mid = req->mid;
8778 state->vuid = req->vuid;
8779 state->setup_count = SVAL(req->vwv+13, 0);
8780 state->setup = NULL;
8781 state->total_param = SVAL(req->vwv+0, 0);
8782 state->param = NULL;
8783 state->total_data = SVAL(req->vwv+1, 0);
8784 state->data = NULL;
8785 state->max_param_return = SVAL(req->vwv+2, 0);
8786 state->max_data_return = SVAL(req->vwv+3, 0);
8787 state->max_setup_return = SVAL(req->vwv+4, 0);
8788 state->close_on_completion = BITSETW(req->vwv+5, 0);
8789 state->one_way = BITSETW(req->vwv+5, 1);
8791 state->call = tran_call;
8793 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8794 is so as a sanity check */
8795 if (state->setup_count != 1) {
8797 * Need to have rc=0 for ioctl to get job id for OS/2.
8798 * Network printing will fail if function is not successful.
8799 * Similar function in reply.c will be used if protocol
8800 * is LANMAN1.0 instead of LM1.2X002.
8801 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8802 * outbuf doesn't have to be set(only job id is used).
8804 if ( (state->setup_count == 4)
8805 && (tran_call == TRANSACT2_IOCTL)
8806 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8807 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8808 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8809 } else {
8810 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8811 DEBUG(2,("Transaction is %d\n",tran_call));
8812 TALLOC_FREE(state);
8813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8814 END_PROFILE(SMBtrans2);
8815 return;
8819 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8820 goto bad_param;
8822 if (state->total_data) {
8824 if (trans_oob(state->total_data, 0, dscnt)
8825 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8826 goto bad_param;
8829 /* Can't use talloc here, the core routines do realloc on the
8830 * params and data. */
8831 state->data = (char *)SMB_MALLOC(state->total_data);
8832 if (state->data == NULL) {
8833 DEBUG(0,("reply_trans2: data malloc fail for %u "
8834 "bytes !\n", (unsigned int)state->total_data));
8835 TALLOC_FREE(state);
8836 reply_nterror(req, NT_STATUS_NO_MEMORY);
8837 END_PROFILE(SMBtrans2);
8838 return;
8841 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8844 if (state->total_param) {
8846 if (trans_oob(state->total_param, 0, pscnt)
8847 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8848 goto bad_param;
8851 /* Can't use talloc here, the core routines do realloc on the
8852 * params and data. */
8853 state->param = (char *)SMB_MALLOC(state->total_param);
8854 if (state->param == NULL) {
8855 DEBUG(0,("reply_trans: param malloc fail for %u "
8856 "bytes !\n", (unsigned int)state->total_param));
8857 SAFE_FREE(state->data);
8858 TALLOC_FREE(state);
8859 reply_nterror(req, NT_STATUS_NO_MEMORY);
8860 END_PROFILE(SMBtrans2);
8861 return;
8864 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8867 state->received_data = dscnt;
8868 state->received_param = pscnt;
8870 if ((state->received_param == state->total_param) &&
8871 (state->received_data == state->total_data)) {
8873 handle_trans2(conn, req, state);
8875 SAFE_FREE(state->data);
8876 SAFE_FREE(state->param);
8877 TALLOC_FREE(state);
8878 END_PROFILE(SMBtrans2);
8879 return;
8882 DLIST_ADD(conn->pending_trans, state);
8884 /* We need to send an interim response then receive the rest
8885 of the parameter/data bytes */
8886 reply_outbuf(req, 0, 0);
8887 show_msg((char *)req->outbuf);
8888 END_PROFILE(SMBtrans2);
8889 return;
8891 bad_param:
8893 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8894 SAFE_FREE(state->data);
8895 SAFE_FREE(state->param);
8896 TALLOC_FREE(state);
8897 END_PROFILE(SMBtrans2);
8898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8902 /****************************************************************************
8903 Reply to a SMBtranss2
8904 ****************************************************************************/
8906 void reply_transs2(struct smb_request *req)
8908 connection_struct *conn = req->conn;
8909 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8910 struct trans_state *state;
8912 START_PROFILE(SMBtranss2);
8914 show_msg((char *)req->inbuf);
8916 /* Windows clients expect all replies to
8917 a transact secondary (SMBtranss2 0x33)
8918 to have a command code of transact
8919 (SMBtrans2 0x32). See bug #8989
8920 and also [MS-CIFS] section 2.2.4.47.2
8921 for details.
8923 req->cmd = SMBtrans2;
8925 if (req->wct < 8) {
8926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8927 END_PROFILE(SMBtranss2);
8928 return;
8931 for (state = conn->pending_trans; state != NULL;
8932 state = state->next) {
8933 if (state->mid == req->mid) {
8934 break;
8938 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8940 END_PROFILE(SMBtranss2);
8941 return;
8944 /* Revise state->total_param and state->total_data in case they have
8945 changed downwards */
8947 if (SVAL(req->vwv+0, 0) < state->total_param)
8948 state->total_param = SVAL(req->vwv+0, 0);
8949 if (SVAL(req->vwv+1, 0) < state->total_data)
8950 state->total_data = SVAL(req->vwv+1, 0);
8952 pcnt = SVAL(req->vwv+2, 0);
8953 poff = SVAL(req->vwv+3, 0);
8954 pdisp = SVAL(req->vwv+4, 0);
8956 dcnt = SVAL(req->vwv+5, 0);
8957 doff = SVAL(req->vwv+6, 0);
8958 ddisp = SVAL(req->vwv+7, 0);
8960 state->received_param += pcnt;
8961 state->received_data += dcnt;
8963 if ((state->received_data > state->total_data) ||
8964 (state->received_param > state->total_param))
8965 goto bad_param;
8967 if (pcnt) {
8968 if (trans_oob(state->total_param, pdisp, pcnt)
8969 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8970 goto bad_param;
8972 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8975 if (dcnt) {
8976 if (trans_oob(state->total_data, ddisp, dcnt)
8977 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8978 goto bad_param;
8980 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8983 if ((state->received_param < state->total_param) ||
8984 (state->received_data < state->total_data)) {
8985 END_PROFILE(SMBtranss2);
8986 return;
8989 handle_trans2(conn, req, state);
8991 DLIST_REMOVE(conn->pending_trans, state);
8992 SAFE_FREE(state->data);
8993 SAFE_FREE(state->param);
8994 TALLOC_FREE(state);
8996 END_PROFILE(SMBtranss2);
8997 return;
8999 bad_param:
9001 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9002 DLIST_REMOVE(conn->pending_trans, state);
9003 SAFE_FREE(state->data);
9004 SAFE_FREE(state->param);
9005 TALLOC_FREE(state);
9006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9007 END_PROFILE(SMBtranss2);
9008 return;