Add open_dir_with_privilege() to ensure we're opening the correct directory when...
[Samba/gbeck.git] / source3 / smbd / trans2.c
blob24642cd8181760d67e98cdc43f7387b87078bb43
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 The canonical "check access" based on object handle or path function.
55 ********************************************************************/
57 NTSTATUS check_access(connection_struct *conn,
58 files_struct *fsp,
59 const struct smb_filename *smb_fname,
60 uint32_t access_mask)
62 if (fsp) {
63 if (!(fsp->access_mask & access_mask)) {
64 return NT_STATUS_ACCESS_DENIED;
66 } else {
67 NTSTATUS status = smbd_check_access_rights(conn,
68 smb_fname,
69 access_mask);
70 if (!NT_STATUS_IS_OK(status)) {
71 return status;
74 return NT_STATUS_OK;
77 /********************************************************************
78 Roundup a value to the nearest allocation roundup size boundary.
79 Only do this for Windows clients.
80 ********************************************************************/
82 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
84 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
86 /* Only roundup for Windows clients. */
87 enum remote_arch_types ra_type = get_remote_arch();
88 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
89 val = SMB_ROUNDUP(val,rval);
91 return val;
94 /********************************************************************
95 Create a 64 bit FileIndex. If the file is on the same device as
96 the root of the share, just return the 64-bit inode. If it isn't,
97 mangle as we used to do.
98 ********************************************************************/
100 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
102 uint64_t file_index;
103 if (conn->base_share_dev == psbuf->st_ex_dev) {
104 return (uint64_t)psbuf->st_ex_ino;
106 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
107 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
108 return file_index;
111 /****************************************************************************
112 Utility functions for dealing with extended attributes.
113 ****************************************************************************/
115 /****************************************************************************
116 Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
119 static bool samba_private_attr_name(const char *unix_ea_name)
121 static const char * const prohibited_ea_names[] = {
122 SAMBA_POSIX_INHERITANCE_EA_NAME,
123 SAMBA_XATTR_DOS_ATTRIB,
124 SAMBA_XATTR_MARKER,
125 XATTR_NTACL_NAME,
126 NULL
129 int i;
131 for (i = 0; prohibited_ea_names[i]; i++) {
132 if (strequal( prohibited_ea_names[i], unix_ea_name))
133 return true;
135 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
136 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
137 return true;
139 return false;
142 /****************************************************************************
143 Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
146 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 const char *ea_name, struct ea_struct *pea)
150 /* Get the value of this xattr. Max size is 64k. */
151 size_t attr_size = 256;
152 char *val = NULL;
153 ssize_t sizeret;
155 again:
157 val = talloc_realloc(mem_ctx, val, char, attr_size);
158 if (!val) {
159 return NT_STATUS_NO_MEMORY;
162 if (fsp && fsp->fh->fd != -1) {
163 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
164 } else {
165 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
168 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
169 attr_size = 65536;
170 goto again;
173 if (sizeret == -1) {
174 return map_nt_error_from_unix(errno);
177 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
178 dump_data(10, (uint8 *)val, sizeret);
180 pea->flags = 0;
181 if (strnequal(ea_name, "user.", 5)) {
182 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
183 } else {
184 pea->name = talloc_strdup(mem_ctx, ea_name);
186 if (pea->name == NULL) {
187 TALLOC_FREE(val);
188 return NT_STATUS_NO_MEMORY;
190 pea->value.data = (unsigned char *)val;
191 pea->value.length = (size_t)sizeret;
192 return NT_STATUS_OK;
195 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
196 files_struct *fsp, const char *fname,
197 char ***pnames, size_t *pnum_names)
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size = 1024;
201 char *ea_namelist = NULL;
203 char *p;
204 char **names, **tmp;
205 size_t num_names;
206 ssize_t sizeret = -1;
208 if (!lp_ea_support(SNUM(conn))) {
209 if (pnames) {
210 *pnames = NULL;
212 *pnum_names = 0;
213 return NT_STATUS_OK;
217 * TALLOC the result early to get the talloc hierarchy right.
220 names = talloc_array(mem_ctx, char *, 1);
221 if (names == NULL) {
222 DEBUG(0, ("talloc failed\n"));
223 return NT_STATUS_NO_MEMORY;
226 while (ea_namelist_size <= 65536) {
228 ea_namelist = talloc_realloc(
229 names, ea_namelist, char, ea_namelist_size);
230 if (ea_namelist == NULL) {
231 DEBUG(0, ("talloc failed\n"));
232 TALLOC_FREE(names);
233 return NT_STATUS_NO_MEMORY;
236 if (fsp && fsp->fh->fd != -1) {
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238 ea_namelist_size);
239 } else {
240 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
241 ea_namelist_size);
244 if ((sizeret == -1) && (errno == ERANGE)) {
245 ea_namelist_size *= 2;
247 else {
248 break;
252 if (sizeret == -1) {
253 TALLOC_FREE(names);
254 return map_nt_error_from_unix(errno);
257 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258 (unsigned int)sizeret));
260 if (sizeret == 0) {
261 TALLOC_FREE(names);
262 if (pnames) {
263 *pnames = NULL;
265 *pnum_names = 0;
266 return NT_STATUS_OK;
270 * Ensure the result is 0-terminated
273 if (ea_namelist[sizeret-1] != '\0') {
274 TALLOC_FREE(names);
275 return NT_STATUS_INTERNAL_ERROR;
279 * count the names
281 num_names = 0;
283 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
284 num_names += 1;
287 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
288 if (tmp == NULL) {
289 DEBUG(0, ("talloc failed\n"));
290 TALLOC_FREE(names);
291 return NT_STATUS_NO_MEMORY;
294 names = tmp;
295 num_names = 0;
297 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298 names[num_names++] = p;
301 if (pnames) {
302 *pnames = names;
303 } else {
304 TALLOC_FREE(names);
306 *pnum_names = num_names;
307 return NT_STATUS_OK;
310 /****************************************************************************
311 Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
314 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
315 const char *fname, size_t *pea_total_len)
317 /* Get a list of all xattrs. Max namesize is 64k. */
318 size_t i, num_names;
319 char **names;
320 struct ea_list *ea_list_head = NULL;
321 NTSTATUS status;
323 *pea_total_len = 0;
325 if (!lp_ea_support(SNUM(conn))) {
326 return NULL;
329 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
330 &names, &num_names);
332 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
333 return NULL;
336 for (i=0; i<num_names; i++) {
337 struct ea_list *listp;
338 fstring dos_ea_name;
340 if (strnequal(names[i], "system.", 7)
341 || samba_private_attr_name(names[i]))
342 continue;
344 listp = talloc(mem_ctx, struct ea_list);
345 if (listp == NULL) {
346 return NULL;
349 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
350 fname, names[i],
351 &listp->ea))) {
352 return NULL;
355 push_ascii_fstring(dos_ea_name, listp->ea.name);
357 *pea_total_len +=
358 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
360 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
362 (unsigned int)listp->ea.value.length));
364 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
368 /* Add on 4 for total length. */
369 if (*pea_total_len) {
370 *pea_total_len += 4;
373 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374 (unsigned int)*pea_total_len));
376 return ea_list_head;
379 /****************************************************************************
380 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
381 that was filled.
382 ****************************************************************************/
384 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
385 connection_struct *conn, struct ea_list *ea_list)
387 unsigned int ret_data_size = 4;
388 char *p = pdata;
390 SMB_ASSERT(total_data_size >= 4);
392 if (!lp_ea_support(SNUM(conn))) {
393 SIVAL(pdata,4,0);
394 return 4;
397 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
398 size_t dos_namelen;
399 fstring dos_ea_name;
400 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
401 dos_namelen = strlen(dos_ea_name);
402 if (dos_namelen > 255 || dos_namelen == 0) {
403 break;
405 if (ea_list->ea.value.length > 65535) {
406 break;
408 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
409 break;
412 /* We know we have room. */
413 SCVAL(p,0,ea_list->ea.flags);
414 SCVAL(p,1,dos_namelen);
415 SSVAL(p,2,ea_list->ea.value.length);
416 strlcpy(p+4, dos_ea_name, dos_namelen+1);
417 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
419 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
420 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
423 ret_data_size = PTR_DIFF(p, pdata);
424 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
425 SIVAL(pdata,0,ret_data_size);
426 return ret_data_size;
429 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
430 char *pdata,
431 unsigned int total_data_size,
432 unsigned int *ret_data_size,
433 connection_struct *conn,
434 struct ea_list *ea_list)
436 uint8_t *p = (uint8_t *)pdata;
437 uint8_t *last_start = NULL;
439 *ret_data_size = 0;
441 if (!lp_ea_support(SNUM(conn))) {
442 return NT_STATUS_NO_EAS_ON_FILE;
445 for (; ea_list; ea_list = ea_list->next) {
446 size_t dos_namelen;
447 fstring dos_ea_name;
448 size_t this_size;
450 if (last_start) {
451 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
453 last_start = p;
455 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
456 dos_namelen = strlen(dos_ea_name);
457 if (dos_namelen > 255 || dos_namelen == 0) {
458 return NT_STATUS_INTERNAL_ERROR;
460 if (ea_list->ea.value.length > 65535) {
461 return NT_STATUS_INTERNAL_ERROR;
464 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
466 if (ea_list->next) {
467 size_t pad = 4 - (this_size % 4);
468 this_size += pad;
471 if (this_size > total_data_size) {
472 return NT_STATUS_INFO_LENGTH_MISMATCH;
475 /* We know we have room. */
476 SIVAL(p, 0x00, 0); /* next offset */
477 SCVAL(p, 0x04, ea_list->ea.flags);
478 SCVAL(p, 0x05, dos_namelen);
479 SSVAL(p, 0x06, ea_list->ea.value.length);
480 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
481 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
483 total_data_size -= this_size;
484 p += this_size;
487 *ret_data_size = PTR_DIFF(p, pdata);
488 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
489 return NT_STATUS_OK;
492 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
494 size_t total_ea_len = 0;
495 TALLOC_CTX *mem_ctx = NULL;
497 if (!lp_ea_support(SNUM(conn))) {
498 return 0;
500 mem_ctx = talloc_tos();
501 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
502 return total_ea_len;
505 /****************************************************************************
506 Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
509 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
511 size_t total_ea_len;
512 TALLOC_CTX *mem_ctx = talloc_tos();
513 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
515 for (; ea_list; ea_list = ea_list->next) {
516 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
517 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518 &unix_ea_name[5], ea_list->ea.name));
519 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
520 break;
525 /****************************************************************************
526 Set or delete an extended attribute.
527 ****************************************************************************/
529 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
530 const struct smb_filename *smb_fname, struct ea_list *ea_list)
532 NTSTATUS status;
533 char *fname = NULL;
535 if (!lp_ea_support(SNUM(conn))) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
540 if (!NT_STATUS_IS_OK(status)) {
541 return status;
544 /* For now setting EAs on streams isn't supported. */
545 fname = smb_fname->base_name;
547 for (;ea_list; ea_list = ea_list->next) {
548 int ret;
549 fstring unix_ea_name;
551 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
552 fstrcat(unix_ea_name, ea_list->ea.name);
554 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
556 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
558 if (samba_private_attr_name(unix_ea_name)) {
559 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
560 return NT_STATUS_ACCESS_DENIED;
563 if (ea_list->ea.value.length == 0) {
564 /* Remove the attribute. */
565 if (fsp && (fsp->fh->fd != -1)) {
566 DEBUG(10,("set_ea: deleting ea name %s on "
567 "file %s by file descriptor.\n",
568 unix_ea_name, fsp_str_dbg(fsp)));
569 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
570 } else {
571 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572 unix_ea_name, fname));
573 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
575 #ifdef ENOATTR
576 /* Removing a non existent attribute always succeeds. */
577 if (ret == -1 && errno == ENOATTR) {
578 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
579 unix_ea_name));
580 ret = 0;
582 #endif
583 } else {
584 if (fsp && (fsp->fh->fd != -1)) {
585 DEBUG(10,("set_ea: setting ea name %s on file "
586 "%s by file descriptor.\n",
587 unix_ea_name, fsp_str_dbg(fsp)));
588 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
589 ea_list->ea.value.data, ea_list->ea.value.length, 0);
590 } else {
591 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592 unix_ea_name, fname));
593 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
594 ea_list->ea.value.data, ea_list->ea.value.length, 0);
598 if (ret == -1) {
599 #ifdef ENOTSUP
600 if (errno == ENOTSUP) {
601 return NT_STATUS_EAS_NOT_SUPPORTED;
603 #endif
604 return map_nt_error_from_unix(errno);
608 return NT_STATUS_OK;
610 /****************************************************************************
611 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
614 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
616 struct ea_list *ea_list_head = NULL;
617 size_t converted_size, offset = 0;
619 while (offset + 2 < data_size) {
620 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
621 unsigned int namelen = CVAL(pdata,offset);
623 offset++; /* Go past the namelen byte. */
625 /* integer wrap paranioa. */
626 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
627 (offset > data_size) || (namelen > data_size) ||
628 (offset + namelen >= data_size)) {
629 break;
631 /* Ensure the name is null terminated. */
632 if (pdata[offset + namelen] != '\0') {
633 return NULL;
635 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
636 &converted_size)) {
637 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638 "failed: %s", strerror(errno)));
640 if (!eal->ea.name) {
641 return NULL;
644 offset += (namelen + 1); /* Go past the name + terminating zero. */
645 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
646 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
649 return ea_list_head;
652 /****************************************************************************
653 Read one EA list entry from the buffer.
654 ****************************************************************************/
656 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
658 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
659 uint16 val_len;
660 unsigned int namelen;
661 size_t converted_size;
663 if (!eal) {
664 return NULL;
667 if (data_size < 6) {
668 return NULL;
671 eal->ea.flags = CVAL(pdata,0);
672 namelen = CVAL(pdata,1);
673 val_len = SVAL(pdata,2);
675 if (4 + namelen + 1 + val_len > data_size) {
676 return NULL;
679 /* Ensure the name is null terminated. */
680 if (pdata[namelen + 4] != '\0') {
681 return NULL;
683 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
684 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
685 strerror(errno)));
687 if (!eal->ea.name) {
688 return NULL;
691 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
692 if (!eal->ea.value.data) {
693 return NULL;
696 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
698 /* Ensure we're null terminated just in case we print the value. */
699 eal->ea.value.data[val_len] = '\0';
700 /* But don't count the null. */
701 eal->ea.value.length--;
703 if (pbytes_used) {
704 *pbytes_used = 4 + namelen + 1 + val_len;
707 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
708 dump_data(10, eal->ea.value.data, eal->ea.value.length);
710 return eal;
713 /****************************************************************************
714 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
717 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
719 struct ea_list *ea_list_head = NULL;
720 size_t offset = 0;
721 size_t bytes_used = 0;
723 while (offset < data_size) {
724 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
726 if (!eal) {
727 return NULL;
730 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
731 offset += bytes_used;
734 return ea_list_head;
737 /****************************************************************************
738 Count the total EA size needed.
739 ****************************************************************************/
741 static size_t ea_list_size(struct ea_list *ealist)
743 fstring dos_ea_name;
744 struct ea_list *listp;
745 size_t ret = 0;
747 for (listp = ealist; listp; listp = listp->next) {
748 push_ascii_fstring(dos_ea_name, listp->ea.name);
749 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
751 /* Add on 4 for total length. */
752 if (ret) {
753 ret += 4;
756 return ret;
759 /****************************************************************************
760 Return a union of EA's from a file list and a list of names.
761 The TALLOC context for the two lists *MUST* be identical as we steal
762 memory from one list to add to another. JRA.
763 ****************************************************************************/
765 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
767 struct ea_list *nlistp, *flistp;
769 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
770 for (flistp = file_list; flistp; flistp = flistp->next) {
771 if (strequal(nlistp->ea.name, flistp->ea.name)) {
772 break;
776 if (flistp) {
777 /* Copy the data from this entry. */
778 nlistp->ea.flags = flistp->ea.flags;
779 nlistp->ea.value = flistp->ea.value;
780 } else {
781 /* Null entry. */
782 nlistp->ea.flags = 0;
783 ZERO_STRUCT(nlistp->ea.value);
787 *total_ea_len = ea_list_size(name_list);
788 return name_list;
791 /****************************************************************************
792 Send the required number of replies back.
793 We assume all fields other than the data fields are
794 set correctly for the type of call.
795 HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
798 void send_trans2_replies(connection_struct *conn,
799 struct smb_request *req,
800 const char *params,
801 int paramsize,
802 const char *pdata,
803 int datasize,
804 int max_data_bytes)
806 /* As we are using a protocol > LANMAN1 then the max_send
807 variable must have been set in the sessetupX call.
808 This takes precedence over the max_xmit field in the
809 global struct. These different max_xmit variables should
810 be merged as this is now too confusing */
812 int data_to_send = datasize;
813 int params_to_send = paramsize;
814 int useable_space;
815 const char *pp = params;
816 const char *pd = pdata;
817 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
818 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819 int data_alignment_offset = 0;
820 bool overflow = False;
821 struct smbd_server_connection *sconn = req->sconn;
822 int max_send = sconn->smb1.sessions.max_send;
824 /* Modify the data_to_send and datasize and set the error if
825 we're trying to send more than max_data_bytes. We still send
826 the part of the packet(s) that fit. Strange, but needed
827 for OS/2. */
829 if (max_data_bytes > 0 && datasize > max_data_bytes) {
830 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831 max_data_bytes, datasize ));
832 datasize = data_to_send = max_data_bytes;
833 overflow = True;
836 /* If there genuinely are no parameters or data to send just send the empty packet */
838 if(params_to_send == 0 && data_to_send == 0) {
839 reply_outbuf(req, 10, 0);
840 show_msg((char *)req->outbuf);
841 if (!srv_send_smb(sconn,
842 (char *)req->outbuf,
843 true, req->seqnum+1,
844 IS_CONN_ENCRYPTED(conn),
845 &req->pcd)) {
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
849 return;
852 /* When sending params and data ensure that both are nicely aligned */
853 /* Only do this alignment when there is also data to send - else
854 can cause NT redirector problems. */
856 if (((params_to_send % 4) != 0) && (data_to_send != 0))
857 data_alignment_offset = 4 - (params_to_send % 4);
859 /* Space is bufsize minus Netbios over TCP header minus SMB header */
860 /* The alignment_offset is to align the param bytes on an even byte
861 boundary. NT 4.0 Beta needs this to work correctly. */
863 useable_space = max_send - (smb_size
864 + 2 * 10 /* wct */
865 + alignment_offset
866 + data_alignment_offset);
868 if (useable_space < 0) {
869 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870 "= %d!!!", useable_space));
871 exit_server_cleanly("send_trans2_replies: Not enough space");
874 while (params_to_send || data_to_send) {
875 /* Calculate whether we will totally or partially fill this packet */
877 total_sent_thistime = params_to_send + data_to_send;
879 /* We can never send more than useable_space */
881 * Note that 'useable_space' does not include the alignment offsets,
882 * but we must include the alignment offsets in the calculation of
883 * the length of the data we send over the wire, as the alignment offsets
884 * are sent here. Fix from Marc_Jacobsen@hp.com.
887 total_sent_thistime = MIN(total_sent_thistime, useable_space);
889 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
890 + data_alignment_offset);
893 * We might have SMBtrans2s in req which was transferred to
894 * the outbuf, fix that.
896 SCVAL(req->outbuf, smb_com, SMBtrans2);
898 /* Set total params and data to be sent */
899 SSVAL(req->outbuf,smb_tprcnt,paramsize);
900 SSVAL(req->outbuf,smb_tdrcnt,datasize);
902 /* Calculate how many parameters and data we can fit into
903 * this packet. Parameters get precedence
906 params_sent_thistime = MIN(params_to_send,useable_space);
907 data_sent_thistime = useable_space - params_sent_thistime;
908 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
910 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
912 /* smb_proff is the offset from the start of the SMB header to the
913 parameter bytes, however the first 4 bytes of outbuf are
914 the Netbios over TCP header. Thus use smb_base() to subtract
915 them from the calculation */
917 SSVAL(req->outbuf,smb_proff,
918 ((smb_buf(req->outbuf)+alignment_offset)
919 - smb_base(req->outbuf)));
921 if(params_sent_thistime == 0)
922 SSVAL(req->outbuf,smb_prdisp,0);
923 else
924 /* Absolute displacement of param bytes sent in this packet */
925 SSVAL(req->outbuf,smb_prdisp,pp - params);
927 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
928 if(data_sent_thistime == 0) {
929 SSVAL(req->outbuf,smb_droff,0);
930 SSVAL(req->outbuf,smb_drdisp, 0);
931 } else {
932 /* The offset of the data bytes is the offset of the
933 parameter bytes plus the number of parameters being sent this time */
934 SSVAL(req->outbuf, smb_droff,
935 ((smb_buf(req->outbuf)+alignment_offset)
936 - smb_base(req->outbuf))
937 + params_sent_thistime + data_alignment_offset);
938 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
941 /* Initialize the padding for alignment */
943 if (alignment_offset != 0) {
944 memset(smb_buf(req->outbuf), 0, alignment_offset);
947 /* Copy the param bytes into the packet */
949 if(params_sent_thistime) {
950 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
951 params_sent_thistime);
954 /* Copy in the data bytes */
955 if(data_sent_thistime) {
956 if (data_alignment_offset != 0) {
957 memset((smb_buf(req->outbuf)+alignment_offset+
958 params_sent_thistime), 0,
959 data_alignment_offset);
961 memcpy(smb_buf(req->outbuf)+alignment_offset
962 +params_sent_thistime+data_alignment_offset,
963 pd,data_sent_thistime);
966 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967 params_sent_thistime, data_sent_thistime, useable_space));
968 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969 params_to_send, data_to_send, paramsize, datasize));
971 if (overflow) {
972 error_packet_set((char *)req->outbuf,
973 ERRDOS,ERRbufferoverflow,
974 STATUS_BUFFER_OVERFLOW,
975 __LINE__,__FILE__);
978 /* Send the packet */
979 show_msg((char *)req->outbuf);
980 if (!srv_send_smb(sconn,
981 (char *)req->outbuf,
982 true, req->seqnum+1,
983 IS_CONN_ENCRYPTED(conn),
984 &req->pcd))
985 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
987 TALLOC_FREE(req->outbuf);
989 pp += params_sent_thistime;
990 pd += data_sent_thistime;
992 params_to_send -= params_sent_thistime;
993 data_to_send -= data_sent_thistime;
995 /* Sanity check */
996 if(params_to_send < 0 || data_to_send < 0) {
997 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998 params_to_send, data_to_send));
999 return;
1003 return;
1006 /****************************************************************************
1007 Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1010 static void call_trans2open(connection_struct *conn,
1011 struct smb_request *req,
1012 char **pparams, int total_params,
1013 char **ppdata, int total_data,
1014 unsigned int max_data_bytes)
1016 struct smb_filename *smb_fname = NULL;
1017 char *params = *pparams;
1018 char *pdata = *ppdata;
1019 int deny_mode;
1020 int32 open_attr;
1021 bool oplock_request;
1022 #if 0
1023 bool return_additional_info;
1024 int16 open_sattr;
1025 time_t open_time;
1026 #endif
1027 int open_ofun;
1028 uint32 open_size;
1029 char *pname;
1030 char *fname = NULL;
1031 SMB_OFF_T size=0;
1032 int fattr=0,mtime=0;
1033 SMB_INO_T inode = 0;
1034 int smb_action = 0;
1035 files_struct *fsp;
1036 struct ea_list *ea_list = NULL;
1037 uint16 flags = 0;
1038 NTSTATUS status;
1039 uint32 access_mask;
1040 uint32 share_mode;
1041 uint32 create_disposition;
1042 uint32 create_options = 0;
1043 uint32_t private_flags = 0;
1044 TALLOC_CTX *ctx = talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params < 29) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 goto out;
1055 flags = SVAL(params, 0);
1056 deny_mode = SVAL(params, 2);
1057 open_attr = SVAL(params,6);
1058 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1059 if (oplock_request) {
1060 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1063 #if 0
1064 return_additional_info = BITSETW(params,0);
1065 open_sattr = SVAL(params, 4);
1066 open_time = make_unix_date3(params+8);
1067 #endif
1068 open_ofun = SVAL(params,12);
1069 open_size = IVAL(params,14);
1070 pname = &params[28];
1072 if (IS_IPC(conn)) {
1073 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1074 goto out;
1077 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1078 total_params - 28, STR_TERMINATE,
1079 &status);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 reply_nterror(req, status);
1082 goto out;
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1087 (unsigned int)open_ofun, open_size));
1089 status = filename_convert(ctx,
1090 conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092 fname,
1094 NULL,
1095 &smb_fname);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req,
1099 NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 goto out;
1103 reply_nterror(req, status);
1104 goto out;
1107 if (open_ofun == 0) {
1108 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1109 goto out;
1112 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1113 open_ofun,
1114 &access_mask, &share_mode,
1115 &create_disposition,
1116 &create_options,
1117 &private_flags)) {
1118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1119 goto out;
1122 /* Any data in this call is an EA list. */
1123 if (total_data && (total_data != 4)) {
1124 if (total_data < 10) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126 goto out;
1129 if (IVAL(pdata,0) > total_data) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata,0), (unsigned int)total_data));
1132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1133 goto out;
1136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1137 total_data - 4);
1138 if (!ea_list) {
1139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1140 goto out;
1143 if (!lp_ea_support(SNUM(conn))) {
1144 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1145 goto out;
1149 status = SMB_VFS_CREATE_FILE(
1150 conn, /* conn */
1151 req, /* req */
1152 0, /* root_dir_fid */
1153 smb_fname, /* fname */
1154 access_mask, /* access_mask */
1155 share_mode, /* share_access */
1156 create_disposition, /* create_disposition*/
1157 create_options, /* create_options */
1158 open_attr, /* file_attributes */
1159 oplock_request, /* oplock_request */
1160 open_size, /* allocation_size */
1161 private_flags,
1162 NULL, /* sd */
1163 ea_list, /* ea_list */
1164 &fsp, /* result */
1165 &smb_action); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (open_was_deferred(req->sconn, req->mid)) {
1169 /* We have re-scheduled this call. */
1170 goto out;
1172 reply_openerror(req, status);
1173 goto out;
1176 size = get_file_size_stat(&smb_fname->st);
1177 fattr = dos_mode(conn, smb_fname);
1178 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1179 inode = smb_fname->st.st_ex_ino;
1180 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1181 close_file(req, fsp, ERROR_CLOSE);
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1183 goto out;
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1188 if(*pparams == NULL ) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1190 goto out;
1192 params = *pparams;
1194 SSVAL(params,0,fsp->fnum);
1195 SSVAL(params,2,fattr);
1196 srv_put_dos_date2(params,4, mtime);
1197 SIVAL(params,8, (uint32)size);
1198 SSVAL(params,12,deny_mode);
1199 SSVAL(params,14,0); /* open_type - file or directory. */
1200 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1206 SSVAL(params,18,smb_action);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params,20,inode);
1212 SSVAL(params,24,0); /* Padding. */
1213 if (flags & 8) {
1214 uint32 ea_size = estimate_ea_size(conn, fsp,
1215 fsp->fsp_name->base_name);
1216 SIVAL(params, 26, ea_size);
1217 } else {
1218 SIVAL(params, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1223 out:
1224 TALLOC_FREE(smb_fname);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild,
1235 bool case_sensitive,
1236 const char *str,
1237 const char *mask)
1239 if (mask[0] == '.' && mask[1] == 0) {
1240 return false;
1243 if (has_wild) {
1244 return false;
1247 if (case_sensitive) {
1248 return strcmp(str,mask)==0;
1249 } else {
1250 return strcasecmp_m(str,mask) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32 unix_filetype(mode_t mode)
1260 if(S_ISREG(mode))
1261 return UNIX_TYPE_FILE;
1262 else if(S_ISDIR(mode))
1263 return UNIX_TYPE_DIR;
1264 #ifdef S_ISLNK
1265 else if(S_ISLNK(mode))
1266 return UNIX_TYPE_SYMLINK;
1267 #endif
1268 #ifdef S_ISCHR
1269 else if(S_ISCHR(mode))
1270 return UNIX_TYPE_CHARDEV;
1271 #endif
1272 #ifdef S_ISBLK
1273 else if(S_ISBLK(mode))
1274 return UNIX_TYPE_BLKDEV;
1275 #endif
1276 #ifdef S_ISFIFO
1277 else if(S_ISFIFO(mode))
1278 return UNIX_TYPE_FIFO;
1279 #endif
1280 #ifdef S_ISSOCK
1281 else if(S_ISSOCK(mode))
1282 return UNIX_TYPE_SOCKET;
1283 #endif
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1286 return UNIX_TYPE_UNKNOWN;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1295 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1296 const SMB_STRUCT_STAT *psbuf,
1297 uint32 perms,
1298 enum perm_type ptype,
1299 mode_t *ret_perms)
1301 mode_t ret = 0;
1303 if (perms == SMB_MODE_NO_CHANGE) {
1304 if (!VALID_STAT(*psbuf)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1306 } else {
1307 *ret_perms = psbuf->st_ex_mode;
1308 return NT_STATUS_OK;
1312 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1313 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1314 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1315 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1316 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1317 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1318 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1319 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1320 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1321 #ifdef S_ISVTX
1322 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1323 #endif
1324 #ifdef S_ISGID
1325 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1326 #endif
1327 #ifdef S_ISUID
1328 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1329 #endif
1331 switch (ptype) {
1332 case PERM_NEW_FILE:
1333 /* Apply mode mask */
1334 ret &= lp_create_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_create_mode(SNUM(conn));
1337 break;
1338 case PERM_NEW_DIR:
1339 ret &= lp_dir_mask(SNUM(conn));
1340 /* Add in force bits */
1341 ret |= lp_force_dir_mode(SNUM(conn));
1342 break;
1343 case PERM_EXISTING_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_security_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_security_mode(SNUM(conn));
1348 break;
1349 case PERM_EXISTING_DIR:
1350 /* Apply mode mask */
1351 ret &= lp_dir_security_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_security_mode(SNUM(conn));
1354 break;
1357 *ret_perms = ret;
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct *conn,
1367 const char *pathname,
1368 SMB_STRUCT_STAT *psbuf)
1370 int saved_errno = errno;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn)) &&
1373 is_msdfs_link(conn, pathname, psbuf)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1376 "as a directory\n",
1377 pathname));
1378 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1379 errno = saved_errno;
1380 return true;
1382 errno = saved_errno;
1383 return false;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state {
1392 connection_struct *conn;
1393 uint32_t info_level;
1394 bool check_mangled_names;
1395 bool has_wild;
1396 bool got_exact_match;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1400 void *private_data,
1401 const char *dname,
1402 const char *mask,
1403 char **_fname)
1405 struct smbd_dirptr_lanman2_state *state =
1406 (struct smbd_dirptr_lanman2_state *)private_data;
1407 bool ok;
1408 char mangled_name[13]; /* mangled 8.3 name. */
1409 bool got_match;
1410 const char *fname;
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname, state->conn->params)) {
1414 ok = name_to_8_3(dname, mangled_name,
1415 true, state->conn->params);
1416 if (!ok) {
1417 return false;
1419 fname = mangled_name;
1420 } else {
1421 fname = dname;
1424 got_match = exact_match(state->has_wild,
1425 state->conn->case_sensitive,
1426 fname, mask);
1427 state->got_exact_match = got_match;
1428 if (!got_match) {
1429 got_match = mask_match(fname, mask,
1430 state->conn->case_sensitive);
1433 if(!got_match && state->check_mangled_names &&
1434 !mangle_is_8_3(fname, false, state->conn->params)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok = name_to_8_3(fname, mangled_name,
1443 false, state->conn->params);
1444 if (!ok) {
1445 return false;
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1450 mangled_name, mask);
1451 state->got_exact_match = got_match;
1452 if (!got_match) {
1453 got_match = mask_match(mangled_name, mask,
1454 state->conn->case_sensitive);
1458 if (!got_match) {
1459 return false;
1462 *_fname = talloc_strdup(ctx, fname);
1463 if (*_fname == NULL) {
1464 return false;
1467 return true;
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1471 void *private_data,
1472 struct smb_filename *smb_fname,
1473 uint32_t *_mode)
1475 struct smbd_dirptr_lanman2_state *state =
1476 (struct smbd_dirptr_lanman2_state *)private_data;
1477 bool ms_dfs_link = false;
1478 uint32_t mode = 0;
1480 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1481 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname),
1485 strerror(errno)));
1486 return false;
1488 } else if (!VALID_STAT(smb_fname->st) &&
1489 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1490 /* Needed to show the msdfs symlinks as
1491 * directories */
1493 ms_dfs_link = check_msdfs_link(state->conn,
1494 smb_fname->base_name,
1495 &smb_fname->st);
1496 if (!ms_dfs_link) {
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname),
1500 strerror(errno)));
1501 return false;
1505 if (ms_dfs_link) {
1506 mode = dos_mode_msdfs(state->conn, smb_fname);
1507 } else {
1508 mode = dos_mode(state->conn, smb_fname);
1511 *_mode = mode;
1512 return true;
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1516 connection_struct *conn,
1517 uint16_t flags2,
1518 uint32_t info_level,
1519 struct ea_list *name_list,
1520 bool check_mangled_names,
1521 bool requires_resume_key,
1522 uint32_t mode,
1523 const char *fname,
1524 const struct smb_filename *smb_fname,
1525 int space_remaining,
1526 uint8_t align,
1527 bool do_pad,
1528 char *base_data,
1529 char **ppdata,
1530 char *end_data,
1531 bool *out_of_space,
1532 uint64_t *last_entry_off)
1534 char *p, *q, *pdata = *ppdata;
1535 uint32_t reskey=0;
1536 uint64_t file_size = 0;
1537 uint64_t allocation_size = 0;
1538 uint64_t file_index = 0;
1539 uint32_t len;
1540 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1541 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1542 char *nameptr;
1543 char *last_entry_ptr;
1544 bool was_8_3;
1545 int off;
1546 int pad = 0;
1548 *out_of_space = false;
1550 ZERO_STRUCT(mdate_ts);
1551 ZERO_STRUCT(adate_ts);
1552 ZERO_STRUCT(create_date_ts);
1553 ZERO_STRUCT(cdate_ts);
1555 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1556 file_size = get_file_size_stat(&smb_fname->st);
1558 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1560 file_index = get_FileIndex(conn, &smb_fname->st);
1562 mdate_ts = smb_fname->st.st_ex_mtime;
1563 adate_ts = smb_fname->st.st_ex_atime;
1564 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1565 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1567 if (lp_dos_filetime_resolution(SNUM(conn))) {
1568 dos_filetime_timespec(&create_date_ts);
1569 dos_filetime_timespec(&mdate_ts);
1570 dos_filetime_timespec(&adate_ts);
1571 dos_filetime_timespec(&cdate_ts);
1574 create_date = convert_timespec_to_time_t(create_date_ts);
1575 mdate = convert_timespec_to_time_t(mdate_ts);
1576 adate = convert_timespec_to_time_t(adate_ts);
1578 /* align the record */
1579 SMB_ASSERT(align >= 1);
1581 off = (int)PTR_DIFF(pdata, base_data);
1582 pad = (off + (align-1)) & ~(align-1);
1583 pad -= off;
1585 if (pad && pad > space_remaining) {
1586 *out_of_space = true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1589 (unsigned int)pad,
1590 space_remaining ));
1591 return false; /* Not finished - just out of space */
1594 off += pad;
1595 /* initialize padding to 0 */
1596 if (pad) {
1597 memset(pdata, 0, pad);
1599 space_remaining -= pad;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1602 space_remaining ));
1604 pdata += pad;
1605 p = pdata;
1606 last_entry_ptr = p;
1608 pad = 0;
1609 off = 0;
1611 switch (info_level) {
1612 case SMB_FIND_INFO_STANDARD:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1614 if(requires_resume_key) {
1615 SIVAL(p,0,reskey);
1616 p += 4;
1618 srv_put_dos_date2(p,0,create_date);
1619 srv_put_dos_date2(p,4,adate);
1620 srv_put_dos_date2(p,8,mdate);
1621 SIVAL(p,12,(uint32)file_size);
1622 SIVAL(p,16,(uint32)allocation_size);
1623 SSVAL(p,20,mode);
1624 p += 23;
1625 nameptr = p;
1626 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 p += ucs2_align(base_data, p, 0);
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE);
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1633 if (len > 2) {
1634 SCVAL(nameptr, -1, len - 2);
1635 } else {
1636 SCVAL(nameptr, -1, 0);
1638 } else {
1639 if (len > 1) {
1640 SCVAL(nameptr, -1, len - 1);
1641 } else {
1642 SCVAL(nameptr, -1, 0);
1645 p += len;
1646 break;
1648 case SMB_FIND_EA_SIZE:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key) {
1651 SIVAL(p,0,reskey);
1652 p += 4;
1654 srv_put_dos_date2(p,0,create_date);
1655 srv_put_dos_date2(p,4,adate);
1656 srv_put_dos_date2(p,8,mdate);
1657 SIVAL(p,12,(uint32)file_size);
1658 SIVAL(p,16,(uint32)allocation_size);
1659 SSVAL(p,20,mode);
1661 unsigned int ea_size = estimate_ea_size(conn, NULL,
1662 smb_fname->base_name);
1663 SIVAL(p,22,ea_size); /* Extended attributes */
1665 p += 27;
1666 nameptr = p - 1;
1667 len = srvstr_push(base_data, flags2,
1668 p, fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE | STR_NOALIGN);
1670 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1671 if (len > 2) {
1672 len -= 2;
1673 } else {
1674 len = 0;
1676 } else {
1677 if (len > 1) {
1678 len -= 1;
1679 } else {
1680 len = 0;
1683 SCVAL(nameptr,0,len);
1684 p += len;
1685 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1686 break;
1688 case SMB_FIND_EA_LIST:
1690 struct ea_list *file_list = NULL;
1691 size_t ea_len = 0;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1694 if (!name_list) {
1695 return false;
1697 if (requires_resume_key) {
1698 SIVAL(p,0,reskey);
1699 p += 4;
1701 srv_put_dos_date2(p,0,create_date);
1702 srv_put_dos_date2(p,4,adate);
1703 srv_put_dos_date2(p,8,mdate);
1704 SIVAL(p,12,(uint32)file_size);
1705 SIVAL(p,16,(uint32)allocation_size);
1706 SSVAL(p,20,mode);
1707 p += 22; /* p now points to the EA area. */
1709 file_list = get_ea_list_from_file(ctx, conn, NULL,
1710 smb_fname->base_name,
1711 &ea_len);
1712 name_list = ea_list_union(name_list, file_list, &ea_len);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1717 *out_of_space = true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1721 space_remaining ));
1722 return False; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1727 nameptr = p;
1728 len = srvstr_push(base_data, flags2,
1729 p + 1, fname, PTR_DIFF(end_data, p+1),
1730 STR_TERMINATE | STR_NOALIGN);
1731 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1732 if (len > 2) {
1733 len -= 2;
1734 } else {
1735 len = 0;
1737 } else {
1738 if (len > 1) {
1739 len -= 1;
1740 } else {
1741 len = 0;
1744 SCVAL(nameptr,0,len);
1745 p += len + 1;
1746 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1747 break;
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1753 p += 4;
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,mode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL,
1765 smb_fname->base_name);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1767 p += 4;
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 char mangled_name[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 memset(p,'\0',26);
1791 p += 2 + 24;
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1795 SIVAL(q,0,len);
1796 p += len;
1798 len = PTR_DIFF(p, pdata);
1799 pad = (len + (align-1)) & ~(align-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1805 SIVAL(pdata,0,pad);
1807 * set padding to zero
1809 if (do_pad) {
1810 memset(p, 0, pad - len);
1811 p = pdata + pad;
1812 } else {
1813 p = pdata + len;
1815 break;
1817 case SMB_FIND_FILE_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1819 p += 4;
1820 SIVAL(p,0,reskey); p += 4;
1821 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1825 SOFF_T(p,0,file_size); p += 8;
1826 SOFF_T(p,0,allocation_size); p += 8;
1827 SIVAL(p,0,mode); p += 4;
1828 len = srvstr_push(base_data, flags2,
1829 p + 4, fname, PTR_DIFF(end_data, p+4),
1830 STR_TERMINATE_ASCII);
1831 SIVAL(p,0,len);
1832 p += 4 + len;
1834 len = PTR_DIFF(p, pdata);
1835 pad = (len + (align-1)) & ~(align-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1841 SIVAL(pdata,0,pad);
1843 * set padding to zero
1845 if (do_pad) {
1846 memset(p, 0, pad - len);
1847 p = pdata + pad;
1848 } else {
1849 p = pdata + len;
1851 break;
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1855 p += 4;
1856 SIVAL(p,0,reskey); p += 4;
1857 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1861 SOFF_T(p,0,file_size); p += 8;
1862 SOFF_T(p,0,allocation_size); p += 8;
1863 SIVAL(p,0,mode); p += 4;
1864 q = p; p += 4; /* q is placeholder for name length. */
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1867 smb_fname->base_name);
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1869 p +=4;
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1874 SIVAL(q, 0, len);
1875 p += len;
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1884 SIVAL(pdata,0,pad);
1886 * set padding to zero
1888 if (do_pad) {
1889 memset(p, 0, pad - len);
1890 p = pdata + pad;
1891 } else {
1892 p = pdata + len;
1894 break;
1896 case SMB_FIND_FILE_NAMES_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1898 p += 4;
1899 SIVAL(p,0,reskey); p += 4;
1900 p += 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1906 SIVAL(p, -4, len);
1907 p += len;
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1916 SIVAL(pdata,0,pad);
1918 * set padding to zero
1920 if (do_pad) {
1921 memset(p, 0, pad - len);
1922 p = pdata + pad;
1923 } else {
1924 p = pdata + len;
1926 break;
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1930 p += 4;
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 q = p; p += 4; /* q is placeholder for name length. */
1941 unsigned int ea_size = estimate_ea_size(conn, NULL,
1942 smb_fname->base_name);
1943 SIVAL(p,0,ea_size); /* Extended attributes */
1944 p +=4;
1946 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1947 SBVAL(p,0,file_index); p += 8;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q, 0, len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1976 p += 4;
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname->base_name);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1990 p +=4;
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3 && check_mangled_names) {
1997 char mangled_name[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname,mangled_name,True,
1999 conn->params)) {
2000 /* Error - mangle failed ! */
2001 memset(mangled_name,'\0',12);
2003 mangled_name[12] = 0;
2004 len = srvstr_push(base_data, flags2,
2005 p+2, mangled_name, 24,
2006 STR_UPPER|STR_UNICODE);
2007 SSVAL(p, 0, len);
2008 if (len < 24) {
2009 memset(p + 2 + len,'\0',24 - len);
2011 SSVAL(p, 0, len);
2012 } else {
2013 memset(p,'\0',26);
2015 p += 26;
2016 SSVAL(p,0,0); p += 2; /* Reserved ? */
2017 SBVAL(p,0,file_index); p += 8;
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE_ASCII);
2021 SIVAL(q,0,len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX:
2046 case SMB_FIND_FILE_UNIX_INFO2:
2047 p+= 4;
2048 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level == SMB_FIND_FILE_UNIX) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p = store_file_unix_basic(conn, p,
2055 NULL, &smb_fname->st);
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2058 STR_TERMINATE);
2059 } else {
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p = store_file_unix_basic_info2(conn, p,
2062 NULL, &smb_fname->st);
2063 nameptr = p;
2064 p += 4;
2065 len = srvstr_push(base_data, flags2, p, fname,
2066 PTR_DIFF(end_data, p), 0);
2067 SIVAL(nameptr, 0, len);
2070 p += len;
2072 len = PTR_DIFF(p, pdata);
2073 pad = (len + (align-1)) & ~(align-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2079 SIVAL(pdata,0,pad);
2081 * set padding to zero
2083 if (do_pad) {
2084 memset(p, 0, pad - len);
2085 p = pdata + pad;
2086 } else {
2087 p = pdata + len;
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2091 break;
2093 default:
2094 return false;
2097 if (PTR_DIFF(p,pdata) > space_remaining) {
2098 *out_of_space = true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p,pdata),
2102 space_remaining ));
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2108 /* Advance the data pointer to the next slot */
2109 *ppdata = p;
2111 return true;
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2115 connection_struct *conn,
2116 struct dptr_struct *dirptr,
2117 uint16 flags2,
2118 const char *path_mask,
2119 uint32 dirtype,
2120 int info_level,
2121 int requires_resume_key,
2122 bool dont_descend,
2123 bool ask_sharemode,
2124 uint8_t align,
2125 bool do_pad,
2126 char **ppdata,
2127 char *base_data,
2128 char *end_data,
2129 int space_remaining,
2130 bool *out_of_space,
2131 bool *got_exact_match,
2132 int *_last_entry_off,
2133 struct ea_list *name_list)
2135 const char *p;
2136 const char *mask = NULL;
2137 long prev_dirpos = 0;
2138 uint32_t mode = 0;
2139 char *fname = NULL;
2140 struct smb_filename *smb_fname = NULL;
2141 struct smbd_dirptr_lanman2_state state;
2142 bool ok;
2143 uint64_t last_entry_off = 0;
2145 ZERO_STRUCT(state);
2146 state.conn = conn;
2147 state.info_level = info_level;
2148 state.check_mangled_names = lp_manglednames(conn->params);
2149 state.has_wild = dptr_has_wild(dirptr);
2150 state.got_exact_match = false;
2152 *out_of_space = false;
2153 *got_exact_match = false;
2155 p = strrchr_m(path_mask,'/');
2156 if(p != NULL) {
2157 if(p[1] == '\0') {
2158 mask = "*.*";
2159 } else {
2160 mask = p+1;
2162 } else {
2163 mask = path_mask;
2166 ok = smbd_dirptr_get_entry(ctx,
2167 dirptr,
2168 mask,
2169 dirtype,
2170 dont_descend,
2171 ask_sharemode,
2172 smbd_dirptr_lanman2_match_fn,
2173 smbd_dirptr_lanman2_mode_fn,
2174 &state,
2175 &fname,
2176 &smb_fname,
2177 &mode,
2178 &prev_dirpos);
2179 if (!ok) {
2180 return false;
2183 *got_exact_match = state.got_exact_match;
2185 ok = smbd_marshall_dir_entry(ctx,
2186 conn,
2187 flags2,
2188 info_level,
2189 name_list,
2190 state.check_mangled_names,
2191 requires_resume_key,
2192 mode,
2193 fname,
2194 smb_fname,
2195 space_remaining,
2196 align,
2197 do_pad,
2198 base_data,
2199 ppdata,
2200 end_data,
2201 out_of_space,
2202 &last_entry_off);
2203 TALLOC_FREE(fname);
2204 TALLOC_FREE(smb_fname);
2205 if (*out_of_space) {
2206 dptr_SeekDir(dirptr, prev_dirpos);
2207 return false;
2209 if (!ok) {
2210 return false;
2213 *_last_entry_off = last_entry_off;
2214 return true;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2218 connection_struct *conn,
2219 struct dptr_struct *dirptr,
2220 uint16 flags2,
2221 const char *path_mask,
2222 uint32 dirtype,
2223 int info_level,
2224 bool requires_resume_key,
2225 bool dont_descend,
2226 bool ask_sharemode,
2227 char **ppdata,
2228 char *base_data,
2229 char *end_data,
2230 int space_remaining,
2231 bool *out_of_space,
2232 bool *got_exact_match,
2233 int *last_entry_off,
2234 struct ea_list *name_list)
2236 uint8_t align = 4;
2237 const bool do_pad = true;
2239 if (info_level >= 1 && info_level <= 3) {
2240 /* No alignment on earlier info levels. */
2241 align = 1;
2244 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2245 path_mask, dirtype, info_level,
2246 requires_resume_key, dont_descend, ask_sharemode,
2247 align, do_pad,
2248 ppdata, base_data, end_data,
2249 space_remaining,
2250 out_of_space, got_exact_match,
2251 last_entry_off, name_list);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct *conn,
2259 struct smb_request *req,
2260 char **pparams, int total_params,
2261 char **ppdata, int total_data,
2262 unsigned int max_data_bytes)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2268 requested. */
2269 struct smb_filename *smb_dname = NULL;
2270 char *params = *pparams;
2271 char *pdata = *ppdata;
2272 char *data_end;
2273 uint32 dirtype;
2274 int maxentries;
2275 uint16 findfirst_flags;
2276 bool close_after_first;
2277 bool close_if_end;
2278 bool requires_resume_key;
2279 int info_level;
2280 char *directory = NULL;
2281 char *mask = NULL;
2282 char *p;
2283 int last_entry_off=0;
2284 int dptr_num = -1;
2285 int numentries = 0;
2286 int i;
2287 bool finished = False;
2288 bool dont_descend = False;
2289 bool out_of_space = False;
2290 int space_remaining;
2291 bool mask_contains_wcard = False;
2292 struct ea_list *ea_list = NULL;
2293 NTSTATUS ntstatus = NT_STATUS_OK;
2294 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX *ctx = talloc_tos();
2296 struct dptr_struct *dirptr = NULL;
2297 struct smbd_server_connection *sconn = req->sconn;
2298 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2299 bool backup_priv = false;
2301 if (total_params < 13) {
2302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2303 goto out;
2306 dirtype = SVAL(params,0);
2307 maxentries = SVAL(params,2);
2308 findfirst_flags = SVAL(params,4);
2309 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2310 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2311 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2312 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2313 security_token_has_privilege(get_current_nttok(conn),
2314 SEC_PRIV_BACKUP));
2316 info_level = SVAL(params,6);
2318 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2319 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2320 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2321 (int)backup_priv,
2322 info_level, max_data_bytes));
2324 if (!maxentries) {
2325 /* W2K3 seems to treat zero as 1. */
2326 maxentries = 1;
2329 switch (info_level) {
2330 case SMB_FIND_INFO_STANDARD:
2331 case SMB_FIND_EA_SIZE:
2332 case SMB_FIND_EA_LIST:
2333 case SMB_FIND_FILE_DIRECTORY_INFO:
2334 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2335 case SMB_FIND_FILE_NAMES_INFO:
2336 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2337 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2338 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2339 break;
2340 case SMB_FIND_FILE_UNIX:
2341 case SMB_FIND_FILE_UNIX_INFO2:
2342 /* Always use filesystem for UNIX mtime query. */
2343 ask_sharemode = false;
2344 if (!lp_unix_extensions()) {
2345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346 goto out;
2348 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2349 break;
2350 default:
2351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2352 goto out;
2355 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2356 params+12, total_params - 12,
2357 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2358 if (!NT_STATUS_IS_OK(ntstatus)) {
2359 reply_nterror(req, ntstatus);
2360 goto out;
2363 if (backup_priv) {
2364 become_root();
2365 ntstatus = filename_convert_with_privilege(ctx,
2366 conn,
2367 req,
2368 directory,
2369 ucf_flags,
2370 &mask_contains_wcard,
2371 &smb_dname);
2372 } else {
2373 ntstatus = filename_convert(ctx, conn,
2374 req->flags2 & FLAGS2_DFS_PATHNAMES,
2375 directory,
2376 ucf_flags,
2377 &mask_contains_wcard,
2378 &smb_dname);
2381 if (!NT_STATUS_IS_OK(ntstatus)) {
2382 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2383 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2384 ERRSRV, ERRbadpath);
2385 goto out;
2387 reply_nterror(req, ntstatus);
2388 goto out;
2391 mask = smb_dname->original_lcomp;
2393 directory = smb_dname->base_name;
2395 p = strrchr_m(directory,'/');
2396 if(p == NULL) {
2397 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2398 if((directory[0] == '.') && (directory[1] == '\0')) {
2399 mask = talloc_strdup(ctx,"*");
2400 if (!mask) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2402 goto out;
2404 mask_contains_wcard = True;
2406 } else {
2407 *p = 0;
2410 if (p == NULL || p == directory) {
2411 /* Ensure we don't have a directory name of "". */
2412 directory = talloc_strdup(talloc_tos(), ".");
2413 if (!directory) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 goto out;
2419 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2421 if (info_level == SMB_FIND_EA_LIST) {
2422 uint32 ea_size;
2424 if (total_data < 4) {
2425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 goto out;
2429 ea_size = IVAL(pdata,0);
2430 if (ea_size != total_data) {
2431 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2432 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2434 goto out;
2437 if (!lp_ea_support(SNUM(conn))) {
2438 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2439 goto out;
2442 /* Pull out the list of names. */
2443 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2444 if (!ea_list) {
2445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2446 goto out;
2450 *ppdata = (char *)SMB_REALLOC(
2451 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2452 if(*ppdata == NULL ) {
2453 reply_nterror(req, NT_STATUS_NO_MEMORY);
2454 goto out;
2456 pdata = *ppdata;
2457 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2459 /* Realloc the params space */
2460 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2461 if (*pparams == NULL) {
2462 reply_nterror(req, NT_STATUS_NO_MEMORY);
2463 goto out;
2465 params = *pparams;
2467 /* Save the wildcard match and attribs we are using on this directory -
2468 needed as lanman2 assumes these are being saved between calls */
2470 ntstatus = dptr_create(conn,
2471 req,
2472 NULL, /* fsp */
2473 directory,
2474 False,
2475 True,
2476 req->smbpid,
2477 mask,
2478 mask_contains_wcard,
2479 dirtype,
2480 &dirptr);
2482 if (!NT_STATUS_IS_OK(ntstatus)) {
2483 reply_nterror(req, ntstatus);
2484 goto out;
2487 if (backup_priv) {
2488 /* Remember this in case we have
2489 to do a findnext. */
2490 dptr_set_priv(dirptr);
2493 dptr_num = dptr_dnum(dirptr);
2494 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2496 /* Initialize per TRANS2_FIND_FIRST operation data */
2497 dptr_init_search_op(dirptr);
2499 /* We don't need to check for VOL here as this is returned by
2500 a different TRANS2 call. */
2502 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2503 directory,lp_dontdescend(SNUM(conn))));
2504 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2505 dont_descend = True;
2507 p = pdata;
2508 space_remaining = max_data_bytes;
2509 out_of_space = False;
2511 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2512 bool got_exact_match = False;
2514 /* this is a heuristic to avoid seeking the dirptr except when
2515 absolutely necessary. It allows for a filename of about 40 chars */
2516 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2517 out_of_space = True;
2518 finished = False;
2519 } else {
2520 finished = !get_lanman2_dir_entry(ctx,
2521 conn,
2522 dirptr,
2523 req->flags2,
2524 mask,dirtype,info_level,
2525 requires_resume_key,dont_descend,
2526 ask_sharemode,
2527 &p,pdata,data_end,
2528 space_remaining, &out_of_space,
2529 &got_exact_match,
2530 &last_entry_off, ea_list);
2533 if (finished && out_of_space)
2534 finished = False;
2536 if (!finished && !out_of_space)
2537 numentries++;
2540 * As an optimisation if we know we aren't looking
2541 * for a wildcard name (ie. the name matches the wildcard exactly)
2542 * then we can finish on any (first) match.
2543 * This speeds up large directory searches. JRA.
2546 if(got_exact_match)
2547 finished = True;
2549 /* Ensure space_remaining never goes -ve. */
2550 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2551 space_remaining = 0;
2552 out_of_space = true;
2553 } else {
2554 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2558 /* Check if we can close the dirptr */
2559 if(close_after_first || (finished && close_if_end)) {
2560 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2561 dptr_close(sconn, &dptr_num);
2565 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2566 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2567 * the protocol level is less than NT1. Tested with smbclient. JRA.
2568 * This should fix the OS/2 client bug #2335.
2571 if(numentries == 0) {
2572 dptr_close(sconn, &dptr_num);
2573 if (get_Protocol() < PROTOCOL_NT1) {
2574 reply_force_doserror(req, ERRDOS, ERRnofiles);
2575 goto out;
2576 } else {
2577 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2578 ERRDOS, ERRbadfile);
2579 goto out;
2583 /* At this point pdata points to numentries directory entries. */
2585 /* Set up the return parameter block */
2586 SSVAL(params,0,dptr_num);
2587 SSVAL(params,2,numentries);
2588 SSVAL(params,4,finished);
2589 SSVAL(params,6,0); /* Never an EA error */
2590 SSVAL(params,8,last_entry_off);
2592 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2593 max_data_bytes);
2595 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2596 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2597 if (!directory) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2602 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2603 smb_fn_name(req->cmd),
2604 mask, directory, dirtype, numentries ) );
2607 * Force a name mangle here to ensure that the
2608 * mask as an 8.3 name is top of the mangled cache.
2609 * The reasons for this are subtle. Don't remove
2610 * this code unless you know what you are doing
2611 * (see PR#13758). JRA.
2614 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2615 char mangled_name[13];
2616 name_to_8_3(mask, mangled_name, True, conn->params);
2618 out:
2620 if (backup_priv) {
2621 unbecome_root();
2624 TALLOC_FREE(smb_dname);
2625 return;
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDNEXT.
2630 ****************************************************************************/
2632 static void call_trans2findnext(connection_struct *conn,
2633 struct smb_request *req,
2634 char **pparams, int total_params,
2635 char **ppdata, int total_data,
2636 unsigned int max_data_bytes)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2642 requested. */
2643 char *params = *pparams;
2644 char *pdata = *ppdata;
2645 char *data_end;
2646 int dptr_num;
2647 int maxentries;
2648 uint16 info_level;
2649 uint32 resume_key;
2650 uint16 findnext_flags;
2651 bool close_after_request;
2652 bool close_if_end;
2653 bool requires_resume_key;
2654 bool continue_bit;
2655 bool mask_contains_wcard = False;
2656 char *resume_name = NULL;
2657 const char *mask = NULL;
2658 const char *directory = NULL;
2659 char *p = NULL;
2660 uint16 dirtype;
2661 int numentries = 0;
2662 int i, last_entry_off=0;
2663 bool finished = False;
2664 bool dont_descend = False;
2665 bool out_of_space = False;
2666 int space_remaining;
2667 struct ea_list *ea_list = NULL;
2668 NTSTATUS ntstatus = NT_STATUS_OK;
2669 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2670 TALLOC_CTX *ctx = talloc_tos();
2671 struct dptr_struct *dirptr;
2672 struct smbd_server_connection *sconn = req->sconn;
2673 bool backup_priv = false;
2675 if (total_params < 13) {
2676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2677 return;
2680 dptr_num = SVAL(params,0);
2681 maxentries = SVAL(params,2);
2682 info_level = SVAL(params,4);
2683 resume_key = IVAL(params,6);
2684 findnext_flags = SVAL(params,10);
2685 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2686 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2687 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2688 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2690 if (!continue_bit) {
2691 /* We only need resume_name if continue_bit is zero. */
2692 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2693 params+12,
2694 total_params - 12, STR_TERMINATE, &ntstatus,
2695 &mask_contains_wcard);
2696 if (!NT_STATUS_IS_OK(ntstatus)) {
2697 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2698 complain (it thinks we're asking for the directory above the shared
2699 path or an invalid name). Catch this as the resume name is only compared, never used in
2700 a file access. JRA. */
2701 srvstr_pull_talloc(ctx, params, req->flags2,
2702 &resume_name, params+12,
2703 total_params - 12,
2704 STR_TERMINATE);
2706 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2707 reply_nterror(req, ntstatus);
2708 return;
2713 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2714 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2715 resume_key = %d resume name = %s continue=%d level = %d\n",
2716 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2717 requires_resume_key, resume_key,
2718 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2720 if (!maxentries) {
2721 /* W2K3 seems to treat zero as 1. */
2722 maxentries = 1;
2725 switch (info_level) {
2726 case SMB_FIND_INFO_STANDARD:
2727 case SMB_FIND_EA_SIZE:
2728 case SMB_FIND_EA_LIST:
2729 case SMB_FIND_FILE_DIRECTORY_INFO:
2730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2731 case SMB_FIND_FILE_NAMES_INFO:
2732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2733 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2735 break;
2736 case SMB_FIND_FILE_UNIX:
2737 case SMB_FIND_FILE_UNIX_INFO2:
2738 /* Always use filesystem for UNIX mtime query. */
2739 ask_sharemode = false;
2740 if (!lp_unix_extensions()) {
2741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2742 return;
2744 break;
2745 default:
2746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2747 return;
2750 if (info_level == SMB_FIND_EA_LIST) {
2751 uint32 ea_size;
2753 if (total_data < 4) {
2754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2755 return;
2758 ea_size = IVAL(pdata,0);
2759 if (ea_size != total_data) {
2760 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2761 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 return;
2766 if (!lp_ea_support(SNUM(conn))) {
2767 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2768 return;
2771 /* Pull out the list of names. */
2772 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2773 if (!ea_list) {
2774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2775 return;
2779 *ppdata = (char *)SMB_REALLOC(
2780 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2781 if(*ppdata == NULL) {
2782 reply_nterror(req, NT_STATUS_NO_MEMORY);
2783 return;
2786 pdata = *ppdata;
2787 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2789 /* Realloc the params space */
2790 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2791 if(*pparams == NULL ) {
2792 reply_nterror(req, NT_STATUS_NO_MEMORY);
2793 return;
2796 params = *pparams;
2798 /* Check that the dptr is valid */
2799 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2800 reply_nterror(req, STATUS_NO_MORE_FILES);
2801 return;
2804 directory = dptr_path(sconn, dptr_num);
2806 /* Get the wildcard mask from the dptr */
2807 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2808 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2809 reply_nterror(req, STATUS_NO_MORE_FILES);
2810 return;
2813 /* Get the attr mask from the dptr */
2814 dirtype = dptr_attr(sconn, dptr_num);
2816 backup_priv = dptr_get_priv(dirptr);
2818 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2819 "backup_priv = %d\n",
2820 dptr_num, mask, dirtype,
2821 (long)dirptr,
2822 dptr_TellDir(dirptr),
2823 (int)backup_priv));
2825 /* Initialize per TRANS2_FIND_NEXT operation data */
2826 dptr_init_search_op(dirptr);
2828 /* We don't need to check for VOL here as this is returned by
2829 a different TRANS2 call. */
2831 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2832 directory,lp_dontdescend(SNUM(conn))));
2833 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2834 dont_descend = True;
2836 p = pdata;
2837 space_remaining = max_data_bytes;
2838 out_of_space = False;
2840 if (backup_priv) {
2841 become_root();
2845 * Seek to the correct position. We no longer use the resume key but
2846 * depend on the last file name instead.
2849 if(!continue_bit && resume_name && *resume_name) {
2850 SMB_STRUCT_STAT st;
2852 long current_pos = 0;
2854 * Remember, name_to_8_3 is called by
2855 * get_lanman2_dir_entry(), so the resume name
2856 * could be mangled. Ensure we check the unmangled name.
2859 if (mangle_is_mangled(resume_name, conn->params)) {
2860 char *new_resume_name = NULL;
2861 mangle_lookup_name_from_8_3(ctx,
2862 resume_name,
2863 &new_resume_name,
2864 conn->params);
2865 if (new_resume_name) {
2866 resume_name = new_resume_name;
2871 * Fix for NT redirector problem triggered by resume key indexes
2872 * changing between directory scans. We now return a resume key of 0
2873 * and instead look for the filename to continue from (also given
2874 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2875 * findfirst/findnext (as is usual) then the directory pointer
2876 * should already be at the correct place.
2879 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2880 } /* end if resume_name && !continue_bit */
2882 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2883 bool got_exact_match = False;
2885 /* this is a heuristic to avoid seeking the dirptr except when
2886 absolutely necessary. It allows for a filename of about 40 chars */
2887 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2888 out_of_space = True;
2889 finished = False;
2890 } else {
2891 finished = !get_lanman2_dir_entry(ctx,
2892 conn,
2893 dirptr,
2894 req->flags2,
2895 mask,dirtype,info_level,
2896 requires_resume_key,dont_descend,
2897 ask_sharemode,
2898 &p,pdata,data_end,
2899 space_remaining, &out_of_space,
2900 &got_exact_match,
2901 &last_entry_off, ea_list);
2904 if (finished && out_of_space)
2905 finished = False;
2907 if (!finished && !out_of_space)
2908 numentries++;
2911 * As an optimisation if we know we aren't looking
2912 * for a wildcard name (ie. the name matches the wildcard exactly)
2913 * then we can finish on any (first) match.
2914 * This speeds up large directory searches. JRA.
2917 if(got_exact_match)
2918 finished = True;
2920 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2923 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2924 smb_fn_name(req->cmd),
2925 mask, directory, dirtype, numentries ) );
2927 /* Check if we can close the dirptr */
2928 if(close_after_request || (finished && close_if_end)) {
2929 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2930 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2933 if (backup_priv) {
2934 unbecome_root();
2937 /* Set up the return parameter block */
2938 SSVAL(params,0,numentries);
2939 SSVAL(params,2,finished);
2940 SSVAL(params,4,0); /* Never an EA error */
2941 SSVAL(params,6,last_entry_off);
2943 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2944 max_data_bytes);
2946 return;
2949 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2951 E_md4hash(lp_servicename(SNUM(conn)),objid);
2952 return objid;
2955 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2957 SMB_ASSERT(extended_info != NULL);
2959 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2960 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2961 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2962 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2963 #ifdef SAMBA_VERSION_REVISION
2964 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2965 #endif
2966 extended_info->samba_subversion = 0;
2967 #ifdef SAMBA_VERSION_RC_RELEASE
2968 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2969 #else
2970 #ifdef SAMBA_VERSION_PRE_RELEASE
2971 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2972 #endif
2973 #endif
2974 #ifdef SAMBA_VERSION_VENDOR_PATCH
2975 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2976 #endif
2977 extended_info->samba_gitcommitdate = 0;
2978 #ifdef SAMBA_VERSION_COMMIT_TIME
2979 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2980 #endif
2982 memset(extended_info->samba_version_string, 0,
2983 sizeof(extended_info->samba_version_string));
2985 snprintf (extended_info->samba_version_string,
2986 sizeof(extended_info->samba_version_string),
2987 "%s", samba_version_string());
2990 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2991 TALLOC_CTX *mem_ctx,
2992 uint16_t info_level,
2993 uint16_t flags2,
2994 unsigned int max_data_bytes,
2995 char **ppdata,
2996 int *ret_data_len)
2998 char *pdata, *end_data;
2999 int data_len = 0, len;
3000 const char *vname = volume_label(SNUM(conn));
3001 int snum = SNUM(conn);
3002 char *fstype = lp_fstype(SNUM(conn));
3003 uint32 additional_flags = 0;
3004 struct smb_filename smb_fname_dot;
3005 SMB_STRUCT_STAT st;
3007 if (IS_IPC(conn)) {
3008 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3009 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3010 "info level (0x%x) on IPC$.\n",
3011 (unsigned int)info_level));
3012 return NT_STATUS_ACCESS_DENIED;
3016 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3018 ZERO_STRUCT(smb_fname_dot);
3019 smb_fname_dot.base_name = discard_const_p(char, ".");
3021 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3022 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3023 return map_nt_error_from_unix(errno);
3026 st = smb_fname_dot.st;
3028 *ppdata = (char *)SMB_REALLOC(
3029 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3030 if (*ppdata == NULL) {
3031 return NT_STATUS_NO_MEMORY;
3034 pdata = *ppdata;
3035 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3036 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3038 switch (info_level) {
3039 case SMB_INFO_ALLOCATION:
3041 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3042 data_len = 18;
3043 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno);
3047 block_size = lp_block_size(snum);
3048 if (bsize < block_size) {
3049 uint64_t factor = block_size/bsize;
3050 bsize = block_size;
3051 dsize /= factor;
3052 dfree /= factor;
3054 if (bsize > block_size) {
3055 uint64_t factor = bsize/block_size;
3056 bsize = block_size;
3057 dsize *= factor;
3058 dfree *= factor;
3060 bytes_per_sector = 512;
3061 sectors_per_unit = bsize/bytes_per_sector;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3065 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3067 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3068 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3069 SIVAL(pdata,l1_cUnit,dsize);
3070 SIVAL(pdata,l1_cUnitAvail,dfree);
3071 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3072 break;
3075 case SMB_INFO_VOLUME:
3076 /* Return volume name */
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3083 * Win2k3 and previous mess this up by sending a name length
3084 * one byte short. I believe only older clients (OS/2 Win9x) use
3085 * this call so try fixing this by adding a terminating null to
3086 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3088 len = srvstr_push(
3089 pdata, flags2,
3090 pdata+l2_vol_szVolLabel, vname,
3091 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3092 STR_NOALIGN|STR_TERMINATE);
3093 SCVAL(pdata,l2_vol_cch,len);
3094 data_len = l2_vol_szVolLabel + len;
3095 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3096 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3097 len, vname));
3098 break;
3100 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3101 case SMB_FS_ATTRIBUTE_INFORMATION:
3103 additional_flags = 0;
3104 #if defined(HAVE_SYS_QUOTAS)
3105 additional_flags |= FILE_VOLUME_QUOTAS;
3106 #endif
3108 if(lp_nt_acl_support(SNUM(conn))) {
3109 additional_flags |= FILE_PERSISTENT_ACLS;
3112 /* Capabilities are filled in at connection time through STATVFS call */
3113 additional_flags |= conn->fs_capabilities;
3114 additional_flags |= lp_parm_int(conn->params->service,
3115 "share", "fake_fscaps",
3118 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3119 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3120 additional_flags); /* FS ATTRIBUTES */
3122 SIVAL(pdata,4,255); /* Max filename component length */
3123 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3124 and will think we can't do long filenames */
3125 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3126 PTR_DIFF(end_data, pdata+12),
3127 STR_UNICODE);
3128 SIVAL(pdata,8,len);
3129 data_len = 12 + len;
3130 break;
3132 case SMB_QUERY_FS_LABEL_INFO:
3133 case SMB_FS_LABEL_INFORMATION:
3134 len = srvstr_push(pdata, flags2, pdata+4, vname,
3135 PTR_DIFF(end_data, pdata+4), 0);
3136 data_len = 4 + len;
3137 SIVAL(pdata,0,len);
3138 break;
3140 case SMB_QUERY_FS_VOLUME_INFO:
3141 case SMB_FS_VOLUME_INFORMATION:
3144 * Add volume serial number - hash of a combination of
3145 * the called hostname and the service name.
3147 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3148 (str_checksum(get_local_machine_name())<<16));
3150 /* Max label len is 32 characters. */
3151 len = srvstr_push(pdata, flags2, pdata+18, vname,
3152 PTR_DIFF(end_data, pdata+18),
3153 STR_UNICODE);
3154 SIVAL(pdata,12,len);
3155 data_len = 18+len;
3157 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3158 (int)strlen(vname),vname, lp_servicename(snum)));
3159 break;
3161 case SMB_QUERY_FS_SIZE_INFO:
3162 case SMB_FS_SIZE_INFORMATION:
3164 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3165 data_len = 24;
3166 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3167 return map_nt_error_from_unix(errno);
3169 block_size = lp_block_size(snum);
3170 if (bsize < block_size) {
3171 uint64_t factor = block_size/bsize;
3172 bsize = block_size;
3173 dsize /= factor;
3174 dfree /= factor;
3176 if (bsize > block_size) {
3177 uint64_t factor = bsize/block_size;
3178 bsize = block_size;
3179 dsize *= factor;
3180 dfree *= factor;
3182 bytes_per_sector = 512;
3183 sectors_per_unit = bsize/bytes_per_sector;
3184 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3185 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3186 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3187 SBIG_UINT(pdata,0,dsize);
3188 SBIG_UINT(pdata,8,dfree);
3189 SIVAL(pdata,16,sectors_per_unit);
3190 SIVAL(pdata,20,bytes_per_sector);
3191 break;
3194 case SMB_FS_FULL_SIZE_INFORMATION:
3196 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3197 data_len = 32;
3198 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3199 return map_nt_error_from_unix(errno);
3201 block_size = lp_block_size(snum);
3202 if (bsize < block_size) {
3203 uint64_t factor = block_size/bsize;
3204 bsize = block_size;
3205 dsize /= factor;
3206 dfree /= factor;
3208 if (bsize > block_size) {
3209 uint64_t factor = bsize/block_size;
3210 bsize = block_size;
3211 dsize *= factor;
3212 dfree *= factor;
3214 bytes_per_sector = 512;
3215 sectors_per_unit = bsize/bytes_per_sector;
3216 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3217 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3218 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3219 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3220 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3221 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3222 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3223 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3224 break;
3227 case SMB_QUERY_FS_DEVICE_INFO:
3228 case SMB_FS_DEVICE_INFORMATION:
3230 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3232 if (!CAN_WRITE(conn)) {
3233 characteristics |= FILE_READ_ONLY_DEVICE;
3235 data_len = 8;
3236 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3237 SIVAL(pdata,4,characteristics);
3238 break;
3241 #ifdef HAVE_SYS_QUOTAS
3242 case SMB_FS_QUOTA_INFORMATION:
3244 * what we have to send --metze:
3246 * Unknown1: 24 NULL bytes
3247 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3248 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3249 * Quota Flags: 2 byte :
3250 * Unknown3: 6 NULL bytes
3252 * 48 bytes total
3254 * details for Quota Flags:
3256 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3257 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3258 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3259 * 0x0001 Enable Quotas: enable quota for this fs
3263 /* we need to fake up a fsp here,
3264 * because its not send in this call
3266 files_struct fsp;
3267 SMB_NTQUOTA_STRUCT quotas;
3269 ZERO_STRUCT(fsp);
3270 ZERO_STRUCT(quotas);
3272 fsp.conn = conn;
3273 fsp.fnum = -1;
3275 /* access check */
3276 if (get_current_uid(conn) != 0) {
3277 DEBUG(0,("set_user_quota: access_denied "
3278 "service [%s] user [%s]\n",
3279 lp_servicename(SNUM(conn)),
3280 conn->session_info->unix_info->unix_name));
3281 return NT_STATUS_ACCESS_DENIED;
3284 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3285 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3286 return map_nt_error_from_unix(errno);
3289 data_len = 48;
3291 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3292 lp_servicename(SNUM(conn))));
3294 /* Unknown1 24 NULL bytes*/
3295 SBIG_UINT(pdata,0,(uint64_t)0);
3296 SBIG_UINT(pdata,8,(uint64_t)0);
3297 SBIG_UINT(pdata,16,(uint64_t)0);
3299 /* Default Soft Quota 8 bytes */
3300 SBIG_UINT(pdata,24,quotas.softlim);
3302 /* Default Hard Quota 8 bytes */
3303 SBIG_UINT(pdata,32,quotas.hardlim);
3305 /* Quota flag 2 bytes */
3306 SSVAL(pdata,40,quotas.qflags);
3308 /* Unknown3 6 NULL bytes */
3309 SSVAL(pdata,42,0);
3310 SIVAL(pdata,44,0);
3312 break;
3314 #endif /* HAVE_SYS_QUOTAS */
3315 case SMB_FS_OBJECTID_INFORMATION:
3317 unsigned char objid[16];
3318 struct smb_extended_info extended_info;
3319 memcpy(pdata,create_volume_objectid(conn, objid),16);
3320 samba_extended_info_version (&extended_info);
3321 SIVAL(pdata,16,extended_info.samba_magic);
3322 SIVAL(pdata,20,extended_info.samba_version);
3323 SIVAL(pdata,24,extended_info.samba_subversion);
3324 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3325 memcpy(pdata+36,extended_info.samba_version_string,28);
3326 data_len = 64;
3327 break;
3331 * Query the version and capabilities of the CIFS UNIX extensions
3332 * in use.
3335 case SMB_QUERY_CIFS_UNIX_INFO:
3337 bool large_write = lp_min_receive_file_size() &&
3338 !srv_is_signing_active(conn->sconn);
3339 bool large_read = !srv_is_signing_active(conn->sconn);
3340 int encrypt_caps = 0;
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL;
3346 switch (conn->encrypt_level) {
3347 case 0:
3348 encrypt_caps = 0;
3349 break;
3350 case 1:
3351 case Auto:
3352 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3353 break;
3354 case Required:
3355 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3356 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3357 large_write = false;
3358 large_read = false;
3359 break;
3362 data_len = 12;
3363 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3364 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3366 /* We have POSIX ACLs, pathname, encryption,
3367 * large read/write, and locking capability. */
3369 SBIG_UINT(pdata,4,((uint64_t)(
3370 CIFS_UNIX_POSIX_ACLS_CAP|
3371 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3372 CIFS_UNIX_FCNTL_LOCKS_CAP|
3373 CIFS_UNIX_EXTATTR_CAP|
3374 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3375 encrypt_caps|
3376 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3377 (large_write ?
3378 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3379 break;
3382 case SMB_QUERY_POSIX_FS_INFO:
3384 int rc;
3385 vfs_statvfs_struct svfs;
3387 if (!lp_unix_extensions()) {
3388 return NT_STATUS_INVALID_LEVEL;
3391 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3393 if (!rc) {
3394 data_len = 56;
3395 SIVAL(pdata,0,svfs.OptimalTransferSize);
3396 SIVAL(pdata,4,svfs.BlockSize);
3397 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3398 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3399 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3400 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3401 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3402 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3403 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3404 #ifdef EOPNOTSUPP
3405 } else if (rc == EOPNOTSUPP) {
3406 return NT_STATUS_INVALID_LEVEL;
3407 #endif /* EOPNOTSUPP */
3408 } else {
3409 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3410 return NT_STATUS_DOS(ERRSRV, ERRerror);
3412 break;
3415 case SMB_QUERY_POSIX_WHOAMI:
3417 uint32_t flags = 0;
3418 uint32_t sid_bytes;
3419 int i;
3421 if (!lp_unix_extensions()) {
3422 return NT_STATUS_INVALID_LEVEL;
3425 if (max_data_bytes < 40) {
3426 return NT_STATUS_BUFFER_TOO_SMALL;
3429 /* We ARE guest if global_sid_Builtin_Guests is
3430 * in our list of SIDs.
3432 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3433 conn->session_info->security_token)) {
3434 flags |= SMB_WHOAMI_GUEST;
3437 /* We are NOT guest if global_sid_Authenticated_Users
3438 * is in our list of SIDs.
3440 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3441 conn->session_info->security_token)) {
3442 flags &= ~SMB_WHOAMI_GUEST;
3445 /* NOTE: 8 bytes for UID/GID, irrespective of native
3446 * platform size. This matches
3447 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3449 data_len = 4 /* flags */
3450 + 4 /* flag mask */
3451 + 8 /* uid */
3452 + 8 /* gid */
3453 + 4 /* ngroups */
3454 + 4 /* num_sids */
3455 + 4 /* SID bytes */
3456 + 4 /* pad/reserved */
3457 + (conn->session_info->unix_token->ngroups * 8)
3458 /* groups list */
3459 + (conn->session_info->security_token->num_sids *
3460 SID_MAX_SIZE)
3461 /* SID list */;
3463 SIVAL(pdata, 0, flags);
3464 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3465 SBIG_UINT(pdata, 8,
3466 (uint64_t)conn->session_info->unix_token->uid);
3467 SBIG_UINT(pdata, 16,
3468 (uint64_t)conn->session_info->unix_token->gid);
3471 if (data_len >= max_data_bytes) {
3472 /* Potential overflow, skip the GIDs and SIDs. */
3474 SIVAL(pdata, 24, 0); /* num_groups */
3475 SIVAL(pdata, 28, 0); /* num_sids */
3476 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3477 SIVAL(pdata, 36, 0); /* reserved */
3479 data_len = 40;
3480 break;
3483 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3484 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3486 /* We walk the SID list twice, but this call is fairly
3487 * infrequent, and I don't expect that it's performance
3488 * sensitive -- jpeach
3490 for (i = 0, sid_bytes = 0;
3491 i < conn->session_info->security_token->num_sids; ++i) {
3492 sid_bytes += ndr_size_dom_sid(
3493 &conn->session_info->security_token->sids[i],
3497 /* SID list byte count */
3498 SIVAL(pdata, 32, sid_bytes);
3500 /* 4 bytes pad/reserved - must be zero */
3501 SIVAL(pdata, 36, 0);
3502 data_len = 40;
3504 /* GID list */
3505 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3506 SBIG_UINT(pdata, data_len,
3507 (uint64_t)conn->session_info->unix_token->groups[i]);
3508 data_len += 8;
3511 /* SID list */
3512 for (i = 0;
3513 i < conn->session_info->security_token->num_sids; ++i) {
3514 int sid_len = ndr_size_dom_sid(
3515 &conn->session_info->security_token->sids[i],
3518 sid_linearize(pdata + data_len, sid_len,
3519 &conn->session_info->security_token->sids[i]);
3520 data_len += sid_len;
3523 break;
3526 case SMB_MAC_QUERY_FS_INFO:
3528 * Thursby MAC extension... ONLY on NTFS filesystems
3529 * once we do streams then we don't need this
3531 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3532 data_len = 88;
3533 SIVAL(pdata,84,0x100); /* Don't support mac... */
3534 break;
3536 /* drop through */
3537 default:
3538 return NT_STATUS_INVALID_LEVEL;
3541 *ret_data_len = data_len;
3542 return NT_STATUS_OK;
3545 /****************************************************************************
3546 Reply to a TRANS2_QFSINFO (query filesystem info).
3547 ****************************************************************************/
3549 static void call_trans2qfsinfo(connection_struct *conn,
3550 struct smb_request *req,
3551 char **pparams, int total_params,
3552 char **ppdata, int total_data,
3553 unsigned int max_data_bytes)
3555 char *params = *pparams;
3556 uint16_t info_level;
3557 int data_len = 0;
3558 NTSTATUS status;
3560 if (total_params < 2) {
3561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3562 return;
3565 info_level = SVAL(params,0);
3567 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3568 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3569 DEBUG(0,("call_trans2qfsinfo: encryption required "
3570 "and info level 0x%x sent.\n",
3571 (unsigned int)info_level));
3572 exit_server_cleanly("encryption required "
3573 "on connection");
3574 return;
3578 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3580 status = smbd_do_qfsinfo(conn, req,
3581 info_level,
3582 req->flags2,
3583 max_data_bytes,
3584 ppdata, &data_len);
3585 if (!NT_STATUS_IS_OK(status)) {
3586 reply_nterror(req, status);
3587 return;
3590 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3591 max_data_bytes);
3593 DEBUG( 4, ( "%s info_level = %d\n",
3594 smb_fn_name(req->cmd), info_level) );
3596 return;
3599 /****************************************************************************
3600 Reply to a TRANS2_SETFSINFO (set filesystem info).
3601 ****************************************************************************/
3603 static void call_trans2setfsinfo(connection_struct *conn,
3604 struct smb_request *req,
3605 char **pparams, int total_params,
3606 char **ppdata, int total_data,
3607 unsigned int max_data_bytes)
3609 struct smbd_server_connection *sconn = req->sconn;
3610 char *pdata = *ppdata;
3611 char *params = *pparams;
3612 uint16 info_level;
3614 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3616 /* */
3617 if (total_params < 4) {
3618 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3619 total_params));
3620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3621 return;
3624 info_level = SVAL(params,2);
3626 if (IS_IPC(conn)) {
3627 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3628 info_level != SMB_SET_CIFS_UNIX_INFO) {
3629 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3630 "info level (0x%x) on IPC$.\n",
3631 (unsigned int)info_level));
3632 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3633 return;
3637 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3638 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3639 DEBUG(0,("call_trans2setfsinfo: encryption required "
3640 "and info level 0x%x sent.\n",
3641 (unsigned int)info_level));
3642 exit_server_cleanly("encryption required "
3643 "on connection");
3644 return;
3648 switch(info_level) {
3649 case SMB_SET_CIFS_UNIX_INFO:
3650 if (!lp_unix_extensions()) {
3651 reply_nterror(req,
3652 NT_STATUS_INVALID_LEVEL);
3653 return;
3656 /* There should be 12 bytes of capabilities set. */
3657 if (total_data < 8) {
3658 reply_nterror(
3659 req,
3660 NT_STATUS_INVALID_PARAMETER);
3661 return;
3663 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3664 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3665 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3666 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3667 /* Just print these values for now. */
3668 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3669 "major = %u, minor = %u cap_low = 0x%x, "
3670 "cap_high = 0x%xn",
3671 (unsigned int)sconn->
3672 smb1.unix_info.client_major,
3673 (unsigned int)sconn->
3674 smb1.unix_info.client_minor,
3675 (unsigned int)sconn->
3676 smb1.unix_info.client_cap_low,
3677 (unsigned int)sconn->
3678 smb1.unix_info.client_cap_high));
3680 /* Here is where we must switch to posix pathname processing... */
3681 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3682 lp_set_posix_pathnames();
3683 mangle_change_to_posix();
3686 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3687 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3688 /* Client that knows how to do posix locks,
3689 * but not posix open/mkdir operations. Set a
3690 * default type for read/write checks. */
3692 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3695 break;
3697 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3699 NTSTATUS status;
3700 size_t param_len = 0;
3701 size_t data_len = total_data;
3703 if (!lp_unix_extensions()) {
3704 reply_nterror(
3705 req,
3706 NT_STATUS_INVALID_LEVEL);
3707 return;
3710 if (lp_smb_encrypt(SNUM(conn)) == false) {
3711 reply_nterror(
3712 req,
3713 NT_STATUS_NOT_SUPPORTED);
3714 return;
3717 if (req->sconn->smb1.echo_handler.trusted_fde) {
3718 DEBUG( 2,("call_trans2setfsinfo: "
3719 "request transport encryption disabled"
3720 "with 'fork echo handler = yes'\n"));
3721 reply_nterror(
3722 req,
3723 NT_STATUS_NOT_SUPPORTED);
3724 return;
3727 DEBUG( 4,("call_trans2setfsinfo: "
3728 "request transport encryption.\n"));
3730 status = srv_request_encryption_setup(conn,
3731 (unsigned char **)ppdata,
3732 &data_len,
3733 (unsigned char **)pparams,
3734 &param_len);
3736 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3737 !NT_STATUS_IS_OK(status)) {
3738 reply_nterror(req, status);
3739 return;
3742 send_trans2_replies(conn, req,
3743 *pparams,
3744 param_len,
3745 *ppdata,
3746 data_len,
3747 max_data_bytes);
3749 if (NT_STATUS_IS_OK(status)) {
3750 /* Server-side transport
3751 * encryption is now *on*. */
3752 status = srv_encryption_start(conn);
3753 if (!NT_STATUS_IS_OK(status)) {
3754 char *reason = talloc_asprintf(talloc_tos(),
3755 "Failure in setting "
3756 "up encrypted transport: %s",
3757 nt_errstr(status));
3758 exit_server_cleanly(reason);
3761 return;
3764 case SMB_FS_QUOTA_INFORMATION:
3766 files_struct *fsp = NULL;
3767 SMB_NTQUOTA_STRUCT quotas;
3769 ZERO_STRUCT(quotas);
3771 /* access check */
3772 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3773 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3774 lp_servicename(SNUM(conn)),
3775 conn->session_info->unix_info->unix_name));
3776 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3777 return;
3780 /* note: normaly there're 48 bytes,
3781 * but we didn't use the last 6 bytes for now
3782 * --metze
3784 fsp = file_fsp(req, SVAL(params,0));
3786 if (!check_fsp_ntquota_handle(conn, req,
3787 fsp)) {
3788 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3789 reply_nterror(
3790 req, NT_STATUS_INVALID_HANDLE);
3791 return;
3794 if (total_data < 42) {
3795 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3796 total_data));
3797 reply_nterror(
3798 req,
3799 NT_STATUS_INVALID_PARAMETER);
3800 return;
3803 /* unknown_1 24 NULL bytes in pdata*/
3805 /* the soft quotas 8 bytes (uint64_t)*/
3806 quotas.softlim = BVAL(pdata,24);
3808 /* the hard quotas 8 bytes (uint64_t)*/
3809 quotas.hardlim = BVAL(pdata,32);
3811 /* quota_flags 2 bytes **/
3812 quotas.qflags = SVAL(pdata,40);
3814 /* unknown_2 6 NULL bytes follow*/
3816 /* now set the quotas */
3817 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3818 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3819 reply_nterror(req, map_nt_error_from_unix(errno));
3820 return;
3823 break;
3825 default:
3826 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3827 info_level));
3828 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3829 return;
3830 break;
3834 * sending this reply works fine,
3835 * but I'm not sure it's the same
3836 * like windows do...
3837 * --metze
3839 reply_outbuf(req, 10, 0);
3842 #if defined(HAVE_POSIX_ACLS)
3843 /****************************************************************************
3844 Utility function to count the number of entries in a POSIX acl.
3845 ****************************************************************************/
3847 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3849 unsigned int ace_count = 0;
3850 int entry_id = SMB_ACL_FIRST_ENTRY;
3851 SMB_ACL_ENTRY_T entry;
3853 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3854 /* get_next... */
3855 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3856 entry_id = SMB_ACL_NEXT_ENTRY;
3858 ace_count++;
3860 return ace_count;
3863 /****************************************************************************
3864 Utility function to marshall a POSIX acl into wire format.
3865 ****************************************************************************/
3867 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3869 int entry_id = SMB_ACL_FIRST_ENTRY;
3870 SMB_ACL_ENTRY_T entry;
3872 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3873 SMB_ACL_TAG_T tagtype;
3874 SMB_ACL_PERMSET_T permset;
3875 unsigned char perms = 0;
3876 unsigned int own_grp;
3878 /* get_next... */
3879 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3880 entry_id = SMB_ACL_NEXT_ENTRY;
3883 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3884 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3885 return False;
3888 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3889 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3890 return False;
3893 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3894 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3895 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3897 SCVAL(pdata,1,perms);
3899 switch (tagtype) {
3900 case SMB_ACL_USER_OBJ:
3901 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3902 own_grp = (unsigned int)pst->st_ex_uid;
3903 SIVAL(pdata,2,own_grp);
3904 SIVAL(pdata,6,0);
3905 break;
3906 case SMB_ACL_USER:
3908 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3909 if (!puid) {
3910 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3911 return False;
3913 own_grp = (unsigned int)*puid;
3914 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3915 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3916 SIVAL(pdata,2,own_grp);
3917 SIVAL(pdata,6,0);
3918 break;
3920 case SMB_ACL_GROUP_OBJ:
3921 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3922 own_grp = (unsigned int)pst->st_ex_gid;
3923 SIVAL(pdata,2,own_grp);
3924 SIVAL(pdata,6,0);
3925 break;
3926 case SMB_ACL_GROUP:
3928 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3929 if (!pgid) {
3930 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3931 return False;
3933 own_grp = (unsigned int)*pgid;
3934 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3935 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3936 SIVAL(pdata,2,own_grp);
3937 SIVAL(pdata,6,0);
3938 break;
3940 case SMB_ACL_MASK:
3941 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3942 SIVAL(pdata,2,0xFFFFFFFF);
3943 SIVAL(pdata,6,0xFFFFFFFF);
3944 break;
3945 case SMB_ACL_OTHER:
3946 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3947 SIVAL(pdata,2,0xFFFFFFFF);
3948 SIVAL(pdata,6,0xFFFFFFFF);
3949 break;
3950 default:
3951 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3952 return False;
3954 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3957 return True;
3959 #endif
3961 /****************************************************************************
3962 Store the FILE_UNIX_BASIC info.
3963 ****************************************************************************/
3965 static char *store_file_unix_basic(connection_struct *conn,
3966 char *pdata,
3967 files_struct *fsp,
3968 const SMB_STRUCT_STAT *psbuf)
3970 uint64_t file_index = get_FileIndex(conn, psbuf);
3972 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3973 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3975 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3976 pdata += 8;
3978 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3979 pdata += 8;
3981 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3982 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3983 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3984 pdata += 24;
3986 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3987 SIVAL(pdata,4,0);
3988 pdata += 8;
3990 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3991 SIVAL(pdata,4,0);
3992 pdata += 8;
3994 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3995 pdata += 4;
3997 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3998 SIVAL(pdata,4,0);
3999 pdata += 8;
4001 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
4002 SIVAL(pdata,4,0);
4003 pdata += 8;
4005 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4006 pdata += 8;
4008 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4009 SIVAL(pdata,4,0);
4010 pdata += 8;
4012 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4013 SIVAL(pdata,4,0);
4014 pdata += 8;
4016 return pdata;
4019 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4020 * the chflags(2) (or equivalent) flags.
4022 * XXX: this really should be behind the VFS interface. To do this, we would
4023 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4024 * Each VFS module could then implement its own mapping as appropriate for the
4025 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4027 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4028 info2_flags_map[] =
4030 #ifdef UF_NODUMP
4031 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4032 #endif
4034 #ifdef UF_IMMUTABLE
4035 { UF_IMMUTABLE, EXT_IMMUTABLE },
4036 #endif
4038 #ifdef UF_APPEND
4039 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4040 #endif
4042 #ifdef UF_HIDDEN
4043 { UF_HIDDEN, EXT_HIDDEN },
4044 #endif
4046 /* Do not remove. We need to guarantee that this array has at least one
4047 * entry to build on HP-UX.
4049 { 0, 0 }
4053 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4054 uint32 *smb_fflags, uint32 *smb_fmask)
4056 int i;
4058 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4059 *smb_fmask |= info2_flags_map[i].smb_fflag;
4060 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4061 *smb_fflags |= info2_flags_map[i].smb_fflag;
4066 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4067 const uint32 smb_fflags,
4068 const uint32 smb_fmask,
4069 int *stat_fflags)
4071 uint32 max_fmask = 0;
4072 int i;
4074 *stat_fflags = psbuf->st_ex_flags;
4076 /* For each flags requested in smb_fmask, check the state of the
4077 * corresponding flag in smb_fflags and set or clear the matching
4078 * stat flag.
4081 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4082 max_fmask |= info2_flags_map[i].smb_fflag;
4083 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4084 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4085 *stat_fflags |= info2_flags_map[i].stat_fflag;
4086 } else {
4087 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4092 /* If smb_fmask is asking to set any bits that are not supported by
4093 * our flag mappings, we should fail.
4095 if ((smb_fmask & max_fmask) != smb_fmask) {
4096 return False;
4099 return True;
4103 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4104 * of file flags and birth (create) time.
4106 static char *store_file_unix_basic_info2(connection_struct *conn,
4107 char *pdata,
4108 files_struct *fsp,
4109 const SMB_STRUCT_STAT *psbuf)
4111 uint32 file_flags = 0;
4112 uint32 flags_mask = 0;
4114 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4116 /* Create (birth) time 64 bit */
4117 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4118 pdata += 8;
4120 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4121 SIVAL(pdata, 0, file_flags); /* flags */
4122 SIVAL(pdata, 4, flags_mask); /* mask */
4123 pdata += 8;
4125 return pdata;
4128 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4129 const struct stream_struct *streams,
4130 char *data,
4131 unsigned int max_data_bytes,
4132 unsigned int *data_size)
4134 unsigned int i;
4135 unsigned int ofs = 0;
4137 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4138 unsigned int next_offset;
4139 size_t namelen;
4140 smb_ucs2_t *namebuf;
4142 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4143 streams[i].name, &namelen) ||
4144 namelen <= 2)
4146 return NT_STATUS_INVALID_PARAMETER;
4150 * name_buf is now null-terminated, we need to marshall as not
4151 * terminated
4154 namelen -= 2;
4156 SIVAL(data, ofs+4, namelen);
4157 SOFF_T(data, ofs+8, streams[i].size);
4158 SOFF_T(data, ofs+16, streams[i].alloc_size);
4159 memcpy(data+ofs+24, namebuf, namelen);
4160 TALLOC_FREE(namebuf);
4162 next_offset = ofs + 24 + namelen;
4164 if (i == num_streams-1) {
4165 SIVAL(data, ofs, 0);
4167 else {
4168 unsigned int align = ndr_align_size(next_offset, 8);
4170 memset(data+next_offset, 0, align);
4171 next_offset += align;
4173 SIVAL(data, ofs, next_offset - ofs);
4174 ofs = next_offset;
4177 ofs = next_offset;
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 return status;
4772 TALLOC_FREE(streams);
4774 break;
4776 case SMB_QUERY_COMPRESSION_INFO:
4777 case SMB_FILE_COMPRESSION_INFORMATION:
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4779 SOFF_T(pdata,0,file_size);
4780 SIVAL(pdata,8,0); /* ??? */
4781 SIVAL(pdata,12,0); /* ??? */
4782 data_size = 16;
4783 break;
4785 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4787 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4788 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4789 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4790 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4791 SOFF_T(pdata,32,allocation_size);
4792 SOFF_T(pdata,40,file_size);
4793 SIVAL(pdata,48,mode);
4794 SIVAL(pdata,52,0); /* ??? */
4795 data_size = 56;
4796 break;
4798 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4800 SIVAL(pdata,0,mode);
4801 SIVAL(pdata,4,0);
4802 data_size = 8;
4803 break;
4806 * CIFS UNIX Extensions.
4809 case SMB_QUERY_FILE_UNIX_BASIC:
4811 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4812 data_size = PTR_DIFF(pdata,(*ppdata));
4814 DEBUG(4,("smbd_do_qfilepathinfo: "
4815 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4816 dump_data(4, (uint8_t *)(*ppdata), data_size);
4818 break;
4820 case SMB_QUERY_FILE_UNIX_INFO2:
4822 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4823 data_size = PTR_DIFF(pdata,(*ppdata));
4826 int i;
4827 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4829 for (i=0; i<100; i++)
4830 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4831 DEBUG(4,("\n"));
4834 break;
4836 case SMB_QUERY_FILE_UNIX_LINK:
4838 int len;
4839 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4841 if (!buffer) {
4842 return NT_STATUS_NO_MEMORY;
4845 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4846 #ifdef S_ISLNK
4847 if(!S_ISLNK(psbuf->st_ex_mode)) {
4848 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4850 #else
4851 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4852 #endif
4853 len = SMB_VFS_READLINK(conn,
4854 smb_fname->base_name,
4855 buffer, PATH_MAX);
4856 if (len == -1) {
4857 return map_nt_error_from_unix(errno);
4859 buffer[len] = 0;
4860 len = srvstr_push(dstart, flags2,
4861 pdata, buffer,
4862 PTR_DIFF(dend, pdata),
4863 STR_TERMINATE);
4864 pdata += len;
4865 data_size = PTR_DIFF(pdata,(*ppdata));
4867 break;
4870 #if defined(HAVE_POSIX_ACLS)
4871 case SMB_QUERY_POSIX_ACL:
4873 SMB_ACL_T file_acl = NULL;
4874 SMB_ACL_T def_acl = NULL;
4875 uint16 num_file_acls = 0;
4876 uint16 num_def_acls = 0;
4878 if (fsp && fsp->fh->fd != -1) {
4879 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4880 } else {
4881 file_acl =
4882 SMB_VFS_SYS_ACL_GET_FILE(conn,
4883 smb_fname->base_name,
4884 SMB_ACL_TYPE_ACCESS);
4887 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4888 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4889 "not implemented on "
4890 "filesystem containing %s\n",
4891 smb_fname->base_name));
4892 return NT_STATUS_NOT_IMPLEMENTED;
4895 if (S_ISDIR(psbuf->st_ex_mode)) {
4896 if (fsp && fsp->is_directory) {
4897 def_acl =
4898 SMB_VFS_SYS_ACL_GET_FILE(
4899 conn,
4900 fsp->fsp_name->base_name,
4901 SMB_ACL_TYPE_DEFAULT);
4902 } else {
4903 def_acl =
4904 SMB_VFS_SYS_ACL_GET_FILE(
4905 conn,
4906 smb_fname->base_name,
4907 SMB_ACL_TYPE_DEFAULT);
4909 def_acl = free_empty_sys_acl(conn, def_acl);
4912 num_file_acls = count_acl_entries(conn, file_acl);
4913 num_def_acls = count_acl_entries(conn, def_acl);
4915 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4916 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4917 data_size,
4918 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4919 SMB_POSIX_ACL_HEADER_SIZE) ));
4920 if (file_acl) {
4921 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4923 if (def_acl) {
4924 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4926 return NT_STATUS_BUFFER_TOO_SMALL;
4929 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4930 SSVAL(pdata,2,num_file_acls);
4931 SSVAL(pdata,4,num_def_acls);
4932 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4933 if (file_acl) {
4934 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4936 if (def_acl) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4939 return NT_STATUS_INTERNAL_ERROR;
4941 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4942 if (file_acl) {
4943 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4945 if (def_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4948 return NT_STATUS_INTERNAL_ERROR;
4951 if (file_acl) {
4952 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4954 if (def_acl) {
4955 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4957 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4958 break;
4960 #endif
4963 case SMB_QUERY_POSIX_LOCK:
4965 uint64_t count;
4966 uint64_t offset;
4967 uint64_t smblctx;
4968 enum brl_type lock_type;
4970 /* We need an open file with a real fd for this. */
4971 if (!fsp || fsp->fh->fd == -1) {
4972 return NT_STATUS_INVALID_LEVEL;
4975 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4976 return NT_STATUS_INVALID_PARAMETER;
4979 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4980 case POSIX_LOCK_TYPE_READ:
4981 lock_type = READ_LOCK;
4982 break;
4983 case POSIX_LOCK_TYPE_WRITE:
4984 lock_type = WRITE_LOCK;
4985 break;
4986 case POSIX_LOCK_TYPE_UNLOCK:
4987 default:
4988 /* There's no point in asking for an unlock... */
4989 return NT_STATUS_INVALID_PARAMETER;
4992 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4993 #if defined(HAVE_LONGLONG)
4994 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4995 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4996 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4997 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4998 #else /* HAVE_LONGLONG */
4999 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5000 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5001 #endif /* HAVE_LONGLONG */
5003 status = query_lock(fsp,
5004 &smblctx,
5005 &count,
5006 &offset,
5007 &lock_type,
5008 POSIX_LOCK);
5010 if (ERROR_WAS_LOCK_DENIED(status)) {
5011 /* Here we need to report who has it locked... */
5012 data_size = POSIX_LOCK_DATA_SIZE;
5014 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5015 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5016 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5017 #if defined(HAVE_LONGLONG)
5018 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5019 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5020 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5021 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5022 #else /* HAVE_LONGLONG */
5023 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5024 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5025 #endif /* HAVE_LONGLONG */
5027 } else if (NT_STATUS_IS_OK(status)) {
5028 /* For success we just return a copy of what we sent
5029 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5030 data_size = POSIX_LOCK_DATA_SIZE;
5031 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5032 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5033 } else {
5034 return status;
5036 break;
5039 default:
5040 return NT_STATUS_INVALID_LEVEL;
5043 *pdata_size = data_size;
5044 return NT_STATUS_OK;
5047 /****************************************************************************
5048 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5049 file name or file id).
5050 ****************************************************************************/
5052 static void call_trans2qfilepathinfo(connection_struct *conn,
5053 struct smb_request *req,
5054 unsigned int tran_call,
5055 char **pparams, int total_params,
5056 char **ppdata, int total_data,
5057 unsigned int max_data_bytes)
5059 char *params = *pparams;
5060 char *pdata = *ppdata;
5061 uint16 info_level;
5062 unsigned int data_size = 0;
5063 unsigned int param_size = 2;
5064 struct smb_filename *smb_fname = NULL;
5065 bool delete_pending = False;
5066 struct timespec write_time_ts;
5067 files_struct *fsp = NULL;
5068 struct file_id fileid;
5069 struct ea_list *ea_list = NULL;
5070 int lock_data_count = 0;
5071 char *lock_data = NULL;
5072 NTSTATUS status = NT_STATUS_OK;
5074 if (!params) {
5075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5076 return;
5079 ZERO_STRUCT(write_time_ts);
5081 if (tran_call == TRANSACT2_QFILEINFO) {
5082 if (total_params < 4) {
5083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5084 return;
5087 if (IS_IPC(conn)) {
5088 call_trans2qpipeinfo(conn, req, tran_call,
5089 pparams, total_params,
5090 ppdata, total_data,
5091 max_data_bytes);
5092 return;
5095 fsp = file_fsp(req, SVAL(params,0));
5096 info_level = SVAL(params,2);
5098 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5100 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5102 return;
5105 /* Initial check for valid fsp ptr. */
5106 if (!check_fsp_open(conn, req, fsp)) {
5107 return;
5110 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5111 &smb_fname);
5112 if (!NT_STATUS_IS_OK(status)) {
5113 reply_nterror(req, status);
5114 return;
5117 if(fsp->fake_file_handle) {
5119 * This is actually for the QUOTA_FAKE_FILE --metze
5122 /* We know this name is ok, it's already passed the checks. */
5124 } else if(fsp->fh->fd == -1) {
5126 * This is actually a QFILEINFO on a directory
5127 * handle (returned from an NT SMB). NT5.0 seems
5128 * to do this call. JRA.
5131 if (INFO_LEVEL_IS_UNIX(info_level)) {
5132 /* Always do lstat for UNIX calls. */
5133 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5134 DEBUG(3,("call_trans2qfilepathinfo: "
5135 "SMB_VFS_LSTAT of %s failed "
5136 "(%s)\n",
5137 smb_fname_str_dbg(smb_fname),
5138 strerror(errno)));
5139 reply_nterror(req,
5140 map_nt_error_from_unix(errno));
5141 return;
5143 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5144 DEBUG(3,("call_trans2qfilepathinfo: "
5145 "SMB_VFS_STAT of %s failed (%s)\n",
5146 smb_fname_str_dbg(smb_fname),
5147 strerror(errno)));
5148 reply_nterror(req,
5149 map_nt_error_from_unix(errno));
5150 return;
5153 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5154 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5155 } else {
5157 * Original code - this is an open file.
5159 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5160 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5161 fsp->fnum, strerror(errno)));
5162 reply_nterror(req,
5163 map_nt_error_from_unix(errno));
5164 return;
5166 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5167 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5170 } else {
5171 uint32_t name_hash;
5172 char *fname = NULL;
5173 uint32_t ucf_flags = 0;
5175 /* qpathinfo */
5176 if (total_params < 7) {
5177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5178 return;
5181 info_level = SVAL(params,0);
5183 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5185 if (INFO_LEVEL_IS_UNIX(info_level)) {
5186 if (!lp_unix_extensions()) {
5187 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5188 return;
5190 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5191 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5192 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5193 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5197 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5198 total_params - 6,
5199 STR_TERMINATE, &status);
5200 if (!NT_STATUS_IS_OK(status)) {
5201 reply_nterror(req, status);
5202 return;
5205 status = filename_convert(req,
5206 conn,
5207 req->flags2 & FLAGS2_DFS_PATHNAMES,
5208 fname,
5209 ucf_flags,
5210 NULL,
5211 &smb_fname);
5212 if (!NT_STATUS_IS_OK(status)) {
5213 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5214 reply_botherror(req,
5215 NT_STATUS_PATH_NOT_COVERED,
5216 ERRSRV, ERRbadpath);
5217 return;
5219 reply_nterror(req, status);
5220 return;
5223 /* If this is a stream, check if there is a delete_pending. */
5224 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5225 && is_ntfs_stream_smb_fname(smb_fname)) {
5226 struct smb_filename *smb_fname_base = NULL;
5228 /* Create an smb_filename with stream_name == NULL. */
5229 status =
5230 create_synthetic_smb_fname(talloc_tos(),
5231 smb_fname->base_name,
5232 NULL, NULL,
5233 &smb_fname_base);
5234 if (!NT_STATUS_IS_OK(status)) {
5235 reply_nterror(req, status);
5236 return;
5239 if (INFO_LEVEL_IS_UNIX(info_level)) {
5240 /* Always do lstat for UNIX calls. */
5241 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5242 DEBUG(3,("call_trans2qfilepathinfo: "
5243 "SMB_VFS_LSTAT of %s failed "
5244 "(%s)\n",
5245 smb_fname_str_dbg(smb_fname_base),
5246 strerror(errno)));
5247 TALLOC_FREE(smb_fname_base);
5248 reply_nterror(req,
5249 map_nt_error_from_unix(errno));
5250 return;
5252 } else {
5253 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5254 DEBUG(3,("call_trans2qfilepathinfo: "
5255 "fileinfo of %s failed "
5256 "(%s)\n",
5257 smb_fname_str_dbg(smb_fname_base),
5258 strerror(errno)));
5259 TALLOC_FREE(smb_fname_base);
5260 reply_nterror(req,
5261 map_nt_error_from_unix(errno));
5262 return;
5266 status = file_name_hash(conn,
5267 smb_fname_str_dbg(smb_fname_base),
5268 &name_hash);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 TALLOC_FREE(smb_fname_base);
5271 reply_nterror(req, status);
5272 return;
5275 fileid = vfs_file_id_from_sbuf(conn,
5276 &smb_fname_base->st);
5277 TALLOC_FREE(smb_fname_base);
5278 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5279 if (delete_pending) {
5280 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5281 return;
5285 if (INFO_LEVEL_IS_UNIX(info_level)) {
5286 /* Always do lstat for UNIX calls. */
5287 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5288 DEBUG(3,("call_trans2qfilepathinfo: "
5289 "SMB_VFS_LSTAT of %s failed (%s)\n",
5290 smb_fname_str_dbg(smb_fname),
5291 strerror(errno)));
5292 reply_nterror(req,
5293 map_nt_error_from_unix(errno));
5294 return;
5297 } else {
5298 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_STAT of %s failed (%s)\n",
5301 smb_fname_str_dbg(smb_fname),
5302 strerror(errno)));
5303 reply_nterror(req,
5304 map_nt_error_from_unix(errno));
5305 return;
5309 status = file_name_hash(conn,
5310 smb_fname_str_dbg(smb_fname),
5311 &name_hash);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 reply_nterror(req, status);
5314 return;
5317 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5318 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5319 if (delete_pending) {
5320 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5321 return;
5325 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5326 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5327 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5329 /* Pull out any data sent here before we realloc. */
5330 switch (info_level) {
5331 case SMB_INFO_QUERY_EAS_FROM_LIST:
5333 /* Pull any EA list from the data portion. */
5334 uint32 ea_size;
5336 if (total_data < 4) {
5337 reply_nterror(
5338 req, NT_STATUS_INVALID_PARAMETER);
5339 return;
5341 ea_size = IVAL(pdata,0);
5343 if (total_data > 0 && ea_size != total_data) {
5344 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5345 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5346 reply_nterror(
5347 req, NT_STATUS_INVALID_PARAMETER);
5348 return;
5351 if (!lp_ea_support(SNUM(conn))) {
5352 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5353 return;
5356 /* Pull out the list of names. */
5357 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5358 if (!ea_list) {
5359 reply_nterror(
5360 req, NT_STATUS_INVALID_PARAMETER);
5361 return;
5363 break;
5366 case SMB_QUERY_POSIX_LOCK:
5368 if (fsp == NULL || fsp->fh->fd == -1) {
5369 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5370 return;
5373 if (total_data != POSIX_LOCK_DATA_SIZE) {
5374 reply_nterror(
5375 req, NT_STATUS_INVALID_PARAMETER);
5376 return;
5379 /* Copy the lock range data. */
5380 lock_data = (char *)talloc_memdup(
5381 req, pdata, total_data);
5382 if (!lock_data) {
5383 reply_nterror(req, NT_STATUS_NO_MEMORY);
5384 return;
5386 lock_data_count = total_data;
5388 default:
5389 break;
5392 *pparams = (char *)SMB_REALLOC(*pparams,2);
5393 if (*pparams == NULL) {
5394 reply_nterror(req, NT_STATUS_NO_MEMORY);
5395 return;
5397 params = *pparams;
5398 SSVAL(params,0,0);
5401 * draft-leach-cifs-v1-spec-02.txt
5402 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5403 * says:
5405 * The requested information is placed in the Data portion of the
5406 * transaction response. For the information levels greater than 0x100,
5407 * the transaction response has 1 parameter word which should be
5408 * ignored by the client.
5410 * However Windows only follows this rule for the IS_NAME_VALID call.
5412 switch (info_level) {
5413 case SMB_INFO_IS_NAME_VALID:
5414 param_size = 0;
5415 break;
5418 if ((info_level & 0xFF00) == 0xFF00) {
5420 * We use levels that start with 0xFF00
5421 * internally to represent SMB2 specific levels
5423 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5424 return;
5427 status = smbd_do_qfilepathinfo(conn, req, info_level,
5428 fsp, smb_fname,
5429 delete_pending, write_time_ts,
5430 ea_list,
5431 lock_data_count, lock_data,
5432 req->flags2, max_data_bytes,
5433 ppdata, &data_size);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 reply_nterror(req, status);
5436 return;
5439 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5440 max_data_bytes);
5442 return;
5445 /****************************************************************************
5446 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5447 code.
5448 ****************************************************************************/
5450 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5451 connection_struct *conn,
5452 struct smb_request *req,
5453 bool overwrite_if_exists,
5454 const struct smb_filename *smb_fname_old,
5455 struct smb_filename *smb_fname_new)
5457 NTSTATUS status = NT_STATUS_OK;
5459 /* source must already exist. */
5460 if (!VALID_STAT(smb_fname_old->st)) {
5461 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5464 if (VALID_STAT(smb_fname_new->st)) {
5465 if (overwrite_if_exists) {
5466 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5467 return NT_STATUS_FILE_IS_A_DIRECTORY;
5469 status = unlink_internals(conn,
5470 req,
5471 FILE_ATTRIBUTE_NORMAL,
5472 smb_fname_new,
5473 false);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 return status;
5477 } else {
5478 /* Disallow if newname already exists. */
5479 return NT_STATUS_OBJECT_NAME_COLLISION;
5483 /* No links from a directory. */
5484 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5485 return NT_STATUS_FILE_IS_A_DIRECTORY;
5488 /* Setting a hardlink to/from a stream isn't currently supported. */
5489 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5490 is_ntfs_stream_smb_fname(smb_fname_new)) {
5491 return NT_STATUS_INVALID_PARAMETER;
5494 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5495 smb_fname_old->base_name, smb_fname_new->base_name));
5497 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5498 smb_fname_new->base_name) != 0) {
5499 status = map_nt_error_from_unix(errno);
5500 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5501 nt_errstr(status), smb_fname_old->base_name,
5502 smb_fname_new->base_name));
5504 return status;
5507 /****************************************************************************
5508 Deal with setting the time from any of the setfilepathinfo functions.
5509 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5510 calling this function.
5511 ****************************************************************************/
5513 NTSTATUS smb_set_file_time(connection_struct *conn,
5514 files_struct *fsp,
5515 const struct smb_filename *smb_fname,
5516 struct smb_file_time *ft,
5517 bool setting_write_time)
5519 struct smb_filename smb_fname_base;
5520 uint32 action =
5521 FILE_NOTIFY_CHANGE_LAST_ACCESS
5522 |FILE_NOTIFY_CHANGE_LAST_WRITE
5523 |FILE_NOTIFY_CHANGE_CREATION;
5525 if (!VALID_STAT(smb_fname->st)) {
5526 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5529 /* get some defaults (no modifications) if any info is zero or -1. */
5530 if (null_timespec(ft->create_time)) {
5531 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5534 if (null_timespec(ft->atime)) {
5535 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5538 if (null_timespec(ft->mtime)) {
5539 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5542 if (!setting_write_time) {
5543 /* ft->mtime comes from change time, not write time. */
5544 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5547 /* Ensure the resolution is the correct for
5548 * what we can store on this filesystem. */
5550 round_timespec(conn->ts_res, &ft->create_time);
5551 round_timespec(conn->ts_res, &ft->ctime);
5552 round_timespec(conn->ts_res, &ft->atime);
5553 round_timespec(conn->ts_res, &ft->mtime);
5555 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5556 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5557 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5558 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5559 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5560 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5561 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5562 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5564 if (setting_write_time) {
5566 * This was a Windows setfileinfo on an open file.
5567 * NT does this a lot. We also need to
5568 * set the time here, as it can be read by
5569 * FindFirst/FindNext and with the patch for bug #2045
5570 * in smbd/fileio.c it ensures that this timestamp is
5571 * kept sticky even after a write. We save the request
5572 * away and will set it on file close and after a write. JRA.
5575 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5576 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5578 if (fsp != NULL) {
5579 if (fsp->base_fsp) {
5580 set_sticky_write_time_fsp(fsp->base_fsp,
5581 ft->mtime);
5582 } else {
5583 set_sticky_write_time_fsp(fsp, ft->mtime);
5585 } else {
5586 set_sticky_write_time_path(
5587 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5588 ft->mtime);
5592 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5594 /* Always call ntimes on the base, even if a stream was passed in. */
5595 smb_fname_base = *smb_fname;
5596 smb_fname_base.stream_name = NULL;
5598 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5599 return map_nt_error_from_unix(errno);
5602 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5603 smb_fname->base_name);
5604 return NT_STATUS_OK;
5607 /****************************************************************************
5608 Deal with setting the dosmode from any of the setfilepathinfo functions.
5609 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5610 done before calling this function.
5611 ****************************************************************************/
5613 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5614 const struct smb_filename *smb_fname,
5615 uint32 dosmode)
5617 struct smb_filename *smb_fname_base = NULL;
5618 NTSTATUS status;
5620 if (!VALID_STAT(smb_fname->st)) {
5621 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5624 /* Always operate on the base_name, even if a stream was passed in. */
5625 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5626 NULL, &smb_fname->st,
5627 &smb_fname_base);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 return status;
5632 if (dosmode) {
5633 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5634 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5635 } else {
5636 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5640 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5642 /* check the mode isn't different, before changing it */
5643 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5644 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5645 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5646 (unsigned int)dosmode));
5648 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5649 false)) {
5650 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5651 "%s failed (%s)\n",
5652 smb_fname_str_dbg(smb_fname_base),
5653 strerror(errno)));
5654 status = map_nt_error_from_unix(errno);
5655 goto out;
5658 status = NT_STATUS_OK;
5659 out:
5660 TALLOC_FREE(smb_fname_base);
5661 return status;
5664 /****************************************************************************
5665 Deal with setting the size from any of the setfilepathinfo functions.
5666 ****************************************************************************/
5668 static NTSTATUS smb_set_file_size(connection_struct *conn,
5669 struct smb_request *req,
5670 files_struct *fsp,
5671 const struct smb_filename *smb_fname,
5672 const SMB_STRUCT_STAT *psbuf,
5673 SMB_OFF_T size,
5674 bool fail_after_createfile)
5676 NTSTATUS status = NT_STATUS_OK;
5677 struct smb_filename *smb_fname_tmp = NULL;
5678 files_struct *new_fsp = NULL;
5680 if (!VALID_STAT(*psbuf)) {
5681 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5684 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5686 if (size == get_file_size_stat(psbuf)) {
5687 return NT_STATUS_OK;
5690 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5691 smb_fname_str_dbg(smb_fname), (double)size));
5693 if (fsp && fsp->fh->fd != -1) {
5694 /* Handle based call. */
5695 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5696 return NT_STATUS_ACCESS_DENIED;
5699 if (vfs_set_filelen(fsp, size) == -1) {
5700 return map_nt_error_from_unix(errno);
5702 trigger_write_time_update_immediate(fsp);
5703 return NT_STATUS_OK;
5706 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5707 if (!NT_STATUS_IS_OK(status)) {
5708 return status;
5711 smb_fname_tmp->st = *psbuf;
5713 status = SMB_VFS_CREATE_FILE(
5714 conn, /* conn */
5715 req, /* req */
5716 0, /* root_dir_fid */
5717 smb_fname_tmp, /* fname */
5718 FILE_WRITE_DATA, /* access_mask */
5719 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5720 FILE_SHARE_DELETE),
5721 FILE_OPEN, /* create_disposition*/
5722 0, /* create_options */
5723 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5724 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5725 0, /* allocation_size */
5726 0, /* private_flags */
5727 NULL, /* sd */
5728 NULL, /* ea_list */
5729 &new_fsp, /* result */
5730 NULL); /* pinfo */
5732 TALLOC_FREE(smb_fname_tmp);
5734 if (!NT_STATUS_IS_OK(status)) {
5735 /* NB. We check for open_was_deferred in the caller. */
5736 return status;
5739 /* See RAW-SFILEINFO-END-OF-FILE */
5740 if (fail_after_createfile) {
5741 close_file(req, new_fsp,NORMAL_CLOSE);
5742 return NT_STATUS_INVALID_LEVEL;
5745 if (vfs_set_filelen(new_fsp, size) == -1) {
5746 status = map_nt_error_from_unix(errno);
5747 close_file(req, new_fsp,NORMAL_CLOSE);
5748 return status;
5751 trigger_write_time_update_immediate(new_fsp);
5752 close_file(req, new_fsp,NORMAL_CLOSE);
5753 return NT_STATUS_OK;
5756 /****************************************************************************
5757 Deal with SMB_INFO_SET_EA.
5758 ****************************************************************************/
5760 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5761 const char *pdata,
5762 int total_data,
5763 files_struct *fsp,
5764 const struct smb_filename *smb_fname)
5766 struct ea_list *ea_list = NULL;
5767 TALLOC_CTX *ctx = NULL;
5768 NTSTATUS status = NT_STATUS_OK;
5770 if (total_data < 10) {
5772 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5773 length. They seem to have no effect. Bug #3212. JRA */
5775 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5776 /* We're done. We only get EA info in this call. */
5777 return NT_STATUS_OK;
5780 return NT_STATUS_INVALID_PARAMETER;
5783 if (IVAL(pdata,0) > total_data) {
5784 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5785 IVAL(pdata,0), (unsigned int)total_data));
5786 return NT_STATUS_INVALID_PARAMETER;
5789 ctx = talloc_tos();
5790 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5791 if (!ea_list) {
5792 return NT_STATUS_INVALID_PARAMETER;
5795 status = set_ea(conn, fsp, smb_fname, ea_list);
5797 return status;
5800 /****************************************************************************
5801 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5802 ****************************************************************************/
5804 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5805 const char *pdata,
5806 int total_data,
5807 files_struct *fsp)
5809 struct ea_list *ea_list = NULL;
5810 NTSTATUS status;
5812 if (!fsp) {
5813 return NT_STATUS_INVALID_HANDLE;
5816 if (!lp_ea_support(SNUM(conn))) {
5817 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5818 "EA's not supported.\n",
5819 (unsigned int)total_data));
5820 return NT_STATUS_EAS_NOT_SUPPORTED;
5823 if (total_data < 10) {
5824 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5825 "too small.\n",
5826 (unsigned int)total_data));
5827 return NT_STATUS_INVALID_PARAMETER;
5830 ea_list = read_nttrans_ea_list(talloc_tos(),
5831 pdata,
5832 total_data);
5834 if (!ea_list) {
5835 return NT_STATUS_INVALID_PARAMETER;
5838 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5840 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5841 smb_fname_str_dbg(fsp->fsp_name),
5842 nt_errstr(status) ));
5844 return status;
5848 /****************************************************************************
5849 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5850 ****************************************************************************/
5852 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5853 const char *pdata,
5854 int total_data,
5855 files_struct *fsp,
5856 struct smb_filename *smb_fname)
5858 NTSTATUS status = NT_STATUS_OK;
5859 bool delete_on_close;
5860 uint32 dosmode = 0;
5862 if (total_data < 1) {
5863 return NT_STATUS_INVALID_PARAMETER;
5866 if (fsp == NULL) {
5867 return NT_STATUS_INVALID_HANDLE;
5870 delete_on_close = (CVAL(pdata,0) ? True : False);
5871 dosmode = dos_mode(conn, smb_fname);
5873 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5874 "delete_on_close = %u\n",
5875 smb_fname_str_dbg(smb_fname),
5876 (unsigned int)dosmode,
5877 (unsigned int)delete_on_close ));
5879 if (delete_on_close) {
5880 status = can_set_delete_on_close(fsp, dosmode);
5881 if (!NT_STATUS_IS_OK(status)) {
5882 return status;
5886 /* The set is across all open files on this dev/inode pair. */
5887 if (!set_delete_on_close(fsp, delete_on_close,
5888 conn->session_info->unix_token)) {
5889 return NT_STATUS_ACCESS_DENIED;
5891 return NT_STATUS_OK;
5894 /****************************************************************************
5895 Deal with SMB_FILE_POSITION_INFORMATION.
5896 ****************************************************************************/
5898 static NTSTATUS smb_file_position_information(connection_struct *conn,
5899 const char *pdata,
5900 int total_data,
5901 files_struct *fsp)
5903 uint64_t position_information;
5905 if (total_data < 8) {
5906 return NT_STATUS_INVALID_PARAMETER;
5909 if (fsp == NULL) {
5910 /* Ignore on pathname based set. */
5911 return NT_STATUS_OK;
5914 position_information = (uint64_t)IVAL(pdata,0);
5915 #ifdef LARGE_SMB_OFF_T
5916 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5917 #else /* LARGE_SMB_OFF_T */
5918 if (IVAL(pdata,4) != 0) {
5919 /* more than 32 bits? */
5920 return NT_STATUS_INVALID_PARAMETER;
5922 #endif /* LARGE_SMB_OFF_T */
5924 DEBUG(10,("smb_file_position_information: Set file position "
5925 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5926 (double)position_information));
5927 fsp->fh->position_information = position_information;
5928 return NT_STATUS_OK;
5931 /****************************************************************************
5932 Deal with SMB_FILE_MODE_INFORMATION.
5933 ****************************************************************************/
5935 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5936 const char *pdata,
5937 int total_data)
5939 uint32 mode;
5941 if (total_data < 4) {
5942 return NT_STATUS_INVALID_PARAMETER;
5944 mode = IVAL(pdata,0);
5945 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5946 return NT_STATUS_INVALID_PARAMETER;
5948 return NT_STATUS_OK;
5951 /****************************************************************************
5952 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5953 ****************************************************************************/
5955 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5956 struct smb_request *req,
5957 const char *pdata,
5958 int total_data,
5959 const struct smb_filename *smb_fname)
5961 char *link_target = NULL;
5962 const char *newname = smb_fname->base_name;
5963 TALLOC_CTX *ctx = talloc_tos();
5965 /* Set a symbolic link. */
5966 /* Don't allow this if follow links is false. */
5968 if (total_data == 0) {
5969 return NT_STATUS_INVALID_PARAMETER;
5972 if (!lp_symlinks(SNUM(conn))) {
5973 return NT_STATUS_ACCESS_DENIED;
5976 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5977 total_data, STR_TERMINATE);
5979 if (!link_target) {
5980 return NT_STATUS_INVALID_PARAMETER;
5983 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5984 newname, link_target ));
5986 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5987 return map_nt_error_from_unix(errno);
5990 return NT_STATUS_OK;
5993 /****************************************************************************
5994 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5995 ****************************************************************************/
5997 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5998 struct smb_request *req,
5999 const char *pdata, int total_data,
6000 struct smb_filename *smb_fname_new)
6002 char *oldname = NULL;
6003 struct smb_filename *smb_fname_old = NULL;
6004 TALLOC_CTX *ctx = talloc_tos();
6005 NTSTATUS status = NT_STATUS_OK;
6007 /* Set a hard link. */
6008 if (total_data == 0) {
6009 return NT_STATUS_INVALID_PARAMETER;
6012 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6013 total_data, STR_TERMINATE, &status);
6014 if (!NT_STATUS_IS_OK(status)) {
6015 return status;
6018 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6019 smb_fname_str_dbg(smb_fname_new), oldname));
6021 status = filename_convert(ctx,
6022 conn,
6023 req->flags2 & FLAGS2_DFS_PATHNAMES,
6024 oldname,
6026 NULL,
6027 &smb_fname_old);
6028 if (!NT_STATUS_IS_OK(status)) {
6029 return status;
6032 return hardlink_internals(ctx, conn, req, false,
6033 smb_fname_old, smb_fname_new);
6036 /****************************************************************************
6037 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6038 ****************************************************************************/
6040 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6041 struct smb_request *req,
6042 const char *pdata,
6043 int total_data,
6044 files_struct *fsp,
6045 struct smb_filename *smb_fname_src)
6047 bool overwrite;
6048 uint32_t len;
6049 char *newname = NULL;
6050 struct smb_filename *smb_fname_dst = NULL;
6051 NTSTATUS status = NT_STATUS_OK;
6052 TALLOC_CTX *ctx = talloc_tos();
6054 if (!fsp) {
6055 return NT_STATUS_INVALID_HANDLE;
6058 if (total_data < 20) {
6059 return NT_STATUS_INVALID_PARAMETER;
6062 overwrite = (CVAL(pdata,0) ? True : False);
6063 len = IVAL(pdata,16);
6065 if (len > (total_data - 20) || (len == 0)) {
6066 return NT_STATUS_INVALID_PARAMETER;
6069 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6070 &pdata[20], len, STR_TERMINATE,
6071 &status);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 return status;
6076 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6077 newname));
6079 status = filename_convert(ctx,
6080 conn,
6081 req->flags2 & FLAGS2_DFS_PATHNAMES,
6082 newname,
6083 UCF_SAVE_LCOMP,
6084 NULL,
6085 &smb_fname_dst);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 return status;
6090 if (fsp->base_fsp) {
6091 /* newname must be a stream name. */
6092 if (newname[0] != ':') {
6093 return NT_STATUS_NOT_SUPPORTED;
6096 /* Create an smb_fname to call rename_internals_fsp() with. */
6097 status = create_synthetic_smb_fname(talloc_tos(),
6098 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6099 &smb_fname_dst);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 goto out;
6105 * Set the original last component, since
6106 * rename_internals_fsp() requires it.
6108 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6109 newname);
6110 if (smb_fname_dst->original_lcomp == NULL) {
6111 status = NT_STATUS_NO_MEMORY;
6112 goto out;
6117 DEBUG(10,("smb2_file_rename_information: "
6118 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6119 fsp->fnum, fsp_str_dbg(fsp),
6120 smb_fname_str_dbg(smb_fname_dst)));
6121 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6122 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6123 overwrite);
6125 out:
6126 TALLOC_FREE(smb_fname_dst);
6127 return status;
6130 static NTSTATUS smb_file_link_information(connection_struct *conn,
6131 struct smb_request *req,
6132 const char *pdata,
6133 int total_data,
6134 files_struct *fsp,
6135 struct smb_filename *smb_fname_src)
6137 bool overwrite;
6138 uint32_t len;
6139 char *newname = NULL;
6140 struct smb_filename *smb_fname_dst = NULL;
6141 NTSTATUS status = NT_STATUS_OK;
6142 TALLOC_CTX *ctx = talloc_tos();
6144 if (!fsp) {
6145 return NT_STATUS_INVALID_HANDLE;
6148 if (total_data < 20) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 overwrite = (CVAL(pdata,0) ? true : false);
6153 len = IVAL(pdata,16);
6155 if (len > (total_data - 20) || (len == 0)) {
6156 return NT_STATUS_INVALID_PARAMETER;
6159 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6160 &pdata[20], len, STR_TERMINATE,
6161 &status);
6162 if (!NT_STATUS_IS_OK(status)) {
6163 return status;
6166 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6167 newname));
6169 status = filename_convert(ctx,
6170 conn,
6171 req->flags2 & FLAGS2_DFS_PATHNAMES,
6172 newname,
6173 UCF_SAVE_LCOMP,
6174 NULL,
6175 &smb_fname_dst);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 return status;
6180 if (fsp->base_fsp) {
6181 /* No stream names. */
6182 return NT_STATUS_NOT_SUPPORTED;
6185 DEBUG(10,("smb_file_link_information: "
6186 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6187 fsp->fnum, fsp_str_dbg(fsp),
6188 smb_fname_str_dbg(smb_fname_dst)));
6189 status = hardlink_internals(ctx,
6190 conn,
6191 req,
6192 overwrite,
6193 fsp->fsp_name,
6194 smb_fname_dst);
6196 TALLOC_FREE(smb_fname_dst);
6197 return status;
6200 /****************************************************************************
6201 Deal with SMB_FILE_RENAME_INFORMATION.
6202 ****************************************************************************/
6204 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6205 struct smb_request *req,
6206 const char *pdata,
6207 int total_data,
6208 files_struct *fsp,
6209 struct smb_filename *smb_fname_src)
6211 bool overwrite;
6212 uint32 root_fid;
6213 uint32 len;
6214 char *newname = NULL;
6215 struct smb_filename *smb_fname_dst = NULL;
6216 bool dest_has_wcard = False;
6217 NTSTATUS status = NT_STATUS_OK;
6218 char *p;
6219 TALLOC_CTX *ctx = talloc_tos();
6221 if (total_data < 13) {
6222 return NT_STATUS_INVALID_PARAMETER;
6225 overwrite = (CVAL(pdata,0) ? True : False);
6226 root_fid = IVAL(pdata,4);
6227 len = IVAL(pdata,8);
6229 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6230 return NT_STATUS_INVALID_PARAMETER;
6233 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6234 len, 0, &status,
6235 &dest_has_wcard);
6236 if (!NT_STATUS_IS_OK(status)) {
6237 return status;
6240 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6241 newname));
6243 status = resolve_dfspath_wcard(ctx, conn,
6244 req->flags2 & FLAGS2_DFS_PATHNAMES,
6245 newname,
6246 true,
6247 &newname,
6248 &dest_has_wcard);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 return status;
6253 /* Check the new name has no '/' characters. */
6254 if (strchr_m(newname, '/')) {
6255 return NT_STATUS_NOT_SUPPORTED;
6258 if (fsp && fsp->base_fsp) {
6259 /* newname must be a stream name. */
6260 if (newname[0] != ':') {
6261 return NT_STATUS_NOT_SUPPORTED;
6264 /* Create an smb_fname to call rename_internals_fsp() with. */
6265 status = create_synthetic_smb_fname(talloc_tos(),
6266 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6267 &smb_fname_dst);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 goto out;
6273 * Set the original last component, since
6274 * rename_internals_fsp() requires it.
6276 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6277 newname);
6278 if (smb_fname_dst->original_lcomp == NULL) {
6279 status = NT_STATUS_NO_MEMORY;
6280 goto out;
6283 } else {
6285 * Build up an smb_fname_dst based on the filename passed in.
6286 * We basically just strip off the last component, and put on
6287 * the newname instead.
6289 char *base_name = NULL;
6291 /* newname must *not* be a stream name. */
6292 if (newname[0] == ':') {
6293 return NT_STATUS_NOT_SUPPORTED;
6297 * Strip off the last component (filename) of the path passed
6298 * in.
6300 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6301 if (!base_name) {
6302 return NT_STATUS_NO_MEMORY;
6304 p = strrchr_m(base_name, '/');
6305 if (p) {
6306 p[1] = '\0';
6307 } else {
6308 base_name = talloc_strdup(ctx, "");
6309 if (!base_name) {
6310 return NT_STATUS_NO_MEMORY;
6313 /* Append the new name. */
6314 base_name = talloc_asprintf_append(base_name,
6315 "%s",
6316 newname);
6317 if (!base_name) {
6318 return NT_STATUS_NO_MEMORY;
6321 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6322 (UCF_SAVE_LCOMP |
6323 (dest_has_wcard ?
6324 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6325 0)));
6327 /* If an error we expect this to be
6328 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6330 if (!NT_STATUS_IS_OK(status)) {
6331 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6332 status)) {
6333 goto out;
6335 /* Create an smb_fname to call rename_internals_fsp() */
6336 status = create_synthetic_smb_fname(ctx,
6337 base_name, NULL,
6338 NULL,
6339 &smb_fname_dst);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 goto out;
6346 if (fsp) {
6347 DEBUG(10,("smb_file_rename_information: "
6348 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6349 fsp->fnum, fsp_str_dbg(fsp),
6350 smb_fname_str_dbg(smb_fname_dst)));
6351 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6352 overwrite);
6353 } else {
6354 DEBUG(10,("smb_file_rename_information: "
6355 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6356 smb_fname_str_dbg(smb_fname_src),
6357 smb_fname_str_dbg(smb_fname_dst)));
6358 status = rename_internals(ctx, conn, req, smb_fname_src,
6359 smb_fname_dst, 0, overwrite, false,
6360 dest_has_wcard,
6361 FILE_WRITE_ATTRIBUTES);
6363 out:
6364 TALLOC_FREE(smb_fname_dst);
6365 return status;
6368 /****************************************************************************
6369 Deal with SMB_SET_POSIX_ACL.
6370 ****************************************************************************/
6372 #if defined(HAVE_POSIX_ACLS)
6373 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6374 const char *pdata,
6375 int total_data,
6376 files_struct *fsp,
6377 const struct smb_filename *smb_fname)
6379 uint16 posix_acl_version;
6380 uint16 num_file_acls;
6381 uint16 num_def_acls;
6382 bool valid_file_acls = True;
6383 bool valid_def_acls = True;
6385 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6386 return NT_STATUS_INVALID_PARAMETER;
6388 posix_acl_version = SVAL(pdata,0);
6389 num_file_acls = SVAL(pdata,2);
6390 num_def_acls = SVAL(pdata,4);
6392 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6393 valid_file_acls = False;
6394 num_file_acls = 0;
6397 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6398 valid_def_acls = False;
6399 num_def_acls = 0;
6402 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6403 return NT_STATUS_INVALID_PARAMETER;
6406 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6407 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6408 return NT_STATUS_INVALID_PARAMETER;
6411 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6412 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6413 (unsigned int)num_file_acls,
6414 (unsigned int)num_def_acls));
6416 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6417 smb_fname->base_name, num_file_acls,
6418 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6419 return map_nt_error_from_unix(errno);
6422 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6423 smb_fname->base_name, &smb_fname->st, num_def_acls,
6424 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6425 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6426 return map_nt_error_from_unix(errno);
6428 return NT_STATUS_OK;
6430 #endif
6432 /****************************************************************************
6433 Deal with SMB_SET_POSIX_LOCK.
6434 ****************************************************************************/
6436 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6437 struct smb_request *req,
6438 const char *pdata,
6439 int total_data,
6440 files_struct *fsp)
6442 uint64_t count;
6443 uint64_t offset;
6444 uint64_t smblctx;
6445 bool blocking_lock = False;
6446 enum brl_type lock_type;
6448 NTSTATUS status = NT_STATUS_OK;
6450 if (fsp == NULL || fsp->fh->fd == -1) {
6451 return NT_STATUS_INVALID_HANDLE;
6454 if (total_data != POSIX_LOCK_DATA_SIZE) {
6455 return NT_STATUS_INVALID_PARAMETER;
6458 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6459 case POSIX_LOCK_TYPE_READ:
6460 lock_type = READ_LOCK;
6461 break;
6462 case POSIX_LOCK_TYPE_WRITE:
6463 /* Return the right POSIX-mappable error code for files opened read-only. */
6464 if (!fsp->can_write) {
6465 return NT_STATUS_INVALID_HANDLE;
6467 lock_type = WRITE_LOCK;
6468 break;
6469 case POSIX_LOCK_TYPE_UNLOCK:
6470 lock_type = UNLOCK_LOCK;
6471 break;
6472 default:
6473 return NT_STATUS_INVALID_PARAMETER;
6476 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6477 blocking_lock = False;
6478 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6479 blocking_lock = True;
6480 } else {
6481 return NT_STATUS_INVALID_PARAMETER;
6484 if (!lp_blocking_locks(SNUM(conn))) {
6485 blocking_lock = False;
6488 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6489 #if defined(HAVE_LONGLONG)
6490 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6491 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6492 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6493 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6494 #else /* HAVE_LONGLONG */
6495 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6496 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6497 #endif /* HAVE_LONGLONG */
6499 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6500 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6501 fsp_str_dbg(fsp),
6502 (unsigned int)lock_type,
6503 (unsigned long long)smblctx,
6504 (double)count,
6505 (double)offset ));
6507 if (lock_type == UNLOCK_LOCK) {
6508 status = do_unlock(req->sconn->msg_ctx,
6509 fsp,
6510 smblctx,
6511 count,
6512 offset,
6513 POSIX_LOCK);
6514 } else {
6515 uint64_t block_smblctx;
6517 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6518 fsp,
6519 smblctx,
6520 count,
6521 offset,
6522 lock_type,
6523 POSIX_LOCK,
6524 blocking_lock,
6525 &status,
6526 &block_smblctx,
6527 NULL);
6529 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6531 * A blocking lock was requested. Package up
6532 * this smb into a queued request and push it
6533 * onto the blocking lock queue.
6535 if(push_blocking_lock_request(br_lck,
6536 req,
6537 fsp,
6538 -1, /* infinite timeout. */
6540 smblctx,
6541 lock_type,
6542 POSIX_LOCK,
6543 offset,
6544 count,
6545 block_smblctx)) {
6546 TALLOC_FREE(br_lck);
6547 return status;
6550 TALLOC_FREE(br_lck);
6553 return status;
6556 /****************************************************************************
6557 Deal with SMB_SET_FILE_BASIC_INFO.
6558 ****************************************************************************/
6560 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6561 const char *pdata,
6562 int total_data,
6563 files_struct *fsp,
6564 const struct smb_filename *smb_fname)
6566 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6567 struct smb_file_time ft;
6568 uint32 dosmode = 0;
6569 NTSTATUS status = NT_STATUS_OK;
6571 ZERO_STRUCT(ft);
6573 if (total_data < 36) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 return status;
6582 /* Set the attributes */
6583 dosmode = IVAL(pdata,32);
6584 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 return status;
6589 /* create time */
6590 ft.create_time = interpret_long_date(pdata);
6592 /* access time */
6593 ft.atime = interpret_long_date(pdata+8);
6595 /* write time. */
6596 ft.mtime = interpret_long_date(pdata+16);
6598 /* change time. */
6599 ft.ctime = interpret_long_date(pdata+24);
6601 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6602 smb_fname_str_dbg(smb_fname)));
6604 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6605 true);
6608 /****************************************************************************
6609 Deal with SMB_INFO_STANDARD.
6610 ****************************************************************************/
6612 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6613 const char *pdata,
6614 int total_data,
6615 files_struct *fsp,
6616 const struct smb_filename *smb_fname)
6618 NTSTATUS status;
6619 struct smb_file_time ft;
6621 ZERO_STRUCT(ft);
6623 if (total_data < 12) {
6624 return NT_STATUS_INVALID_PARAMETER;
6627 /* create time */
6628 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6629 /* access time */
6630 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6631 /* write time */
6632 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6634 DEBUG(10,("smb_set_info_standard: file %s\n",
6635 smb_fname_str_dbg(smb_fname)));
6637 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 return status;
6642 return smb_set_file_time(conn,
6643 fsp,
6644 smb_fname,
6645 &ft,
6646 true);
6649 /****************************************************************************
6650 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6651 ****************************************************************************/
6653 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6654 struct smb_request *req,
6655 const char *pdata,
6656 int total_data,
6657 files_struct *fsp,
6658 struct smb_filename *smb_fname)
6660 uint64_t allocation_size = 0;
6661 NTSTATUS status = NT_STATUS_OK;
6662 files_struct *new_fsp = NULL;
6664 if (!VALID_STAT(smb_fname->st)) {
6665 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6668 if (total_data < 8) {
6669 return NT_STATUS_INVALID_PARAMETER;
6672 allocation_size = (uint64_t)IVAL(pdata,0);
6673 #ifdef LARGE_SMB_OFF_T
6674 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6675 #else /* LARGE_SMB_OFF_T */
6676 if (IVAL(pdata,4) != 0) {
6677 /* more than 32 bits? */
6678 return NT_STATUS_INVALID_PARAMETER;
6680 #endif /* LARGE_SMB_OFF_T */
6682 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6683 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6684 (double)allocation_size));
6686 if (allocation_size) {
6687 allocation_size = smb_roundup(conn, allocation_size);
6690 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6691 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6692 (double)allocation_size));
6694 if (fsp && fsp->fh->fd != -1) {
6695 /* Open file handle. */
6696 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6697 return NT_STATUS_ACCESS_DENIED;
6700 /* Only change if needed. */
6701 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6702 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6703 return map_nt_error_from_unix(errno);
6706 /* But always update the time. */
6708 * This is equivalent to a write. Ensure it's seen immediately
6709 * if there are no pending writes.
6711 trigger_write_time_update_immediate(fsp);
6712 return NT_STATUS_OK;
6715 /* Pathname or stat or directory file. */
6716 status = SMB_VFS_CREATE_FILE(
6717 conn, /* conn */
6718 req, /* req */
6719 0, /* root_dir_fid */
6720 smb_fname, /* fname */
6721 FILE_WRITE_DATA, /* access_mask */
6722 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6723 FILE_SHARE_DELETE),
6724 FILE_OPEN, /* create_disposition*/
6725 0, /* create_options */
6726 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6727 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6728 0, /* allocation_size */
6729 0, /* private_flags */
6730 NULL, /* sd */
6731 NULL, /* ea_list */
6732 &new_fsp, /* result */
6733 NULL); /* pinfo */
6735 if (!NT_STATUS_IS_OK(status)) {
6736 /* NB. We check for open_was_deferred in the caller. */
6737 return status;
6740 /* Only change if needed. */
6741 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6742 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6743 status = map_nt_error_from_unix(errno);
6744 close_file(req, new_fsp, NORMAL_CLOSE);
6745 return status;
6749 /* Changing the allocation size should set the last mod time. */
6751 * This is equivalent to a write. Ensure it's seen immediately
6752 * if there are no pending writes.
6754 trigger_write_time_update_immediate(new_fsp);
6756 close_file(req, new_fsp, NORMAL_CLOSE);
6757 return NT_STATUS_OK;
6760 /****************************************************************************
6761 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6762 ****************************************************************************/
6764 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6765 struct smb_request *req,
6766 const char *pdata,
6767 int total_data,
6768 files_struct *fsp,
6769 const struct smb_filename *smb_fname,
6770 bool fail_after_createfile)
6772 SMB_OFF_T size;
6774 if (total_data < 8) {
6775 return NT_STATUS_INVALID_PARAMETER;
6778 size = IVAL(pdata,0);
6779 #ifdef LARGE_SMB_OFF_T
6780 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6781 #else /* LARGE_SMB_OFF_T */
6782 if (IVAL(pdata,4) != 0) {
6783 /* more than 32 bits? */
6784 return NT_STATUS_INVALID_PARAMETER;
6786 #endif /* LARGE_SMB_OFF_T */
6787 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6788 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6789 (double)size));
6791 return smb_set_file_size(conn, req,
6792 fsp,
6793 smb_fname,
6794 &smb_fname->st,
6795 size,
6796 fail_after_createfile);
6799 /****************************************************************************
6800 Allow a UNIX info mknod.
6801 ****************************************************************************/
6803 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6804 const char *pdata,
6805 int total_data,
6806 const struct smb_filename *smb_fname)
6808 uint32 file_type = IVAL(pdata,56);
6809 #if defined(HAVE_MAKEDEV)
6810 uint32 dev_major = IVAL(pdata,60);
6811 uint32 dev_minor = IVAL(pdata,68);
6812 #endif
6813 SMB_DEV_T dev = (SMB_DEV_T)0;
6814 uint32 raw_unixmode = IVAL(pdata,84);
6815 NTSTATUS status;
6816 mode_t unixmode;
6818 if (total_data < 100) {
6819 return NT_STATUS_INVALID_PARAMETER;
6822 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6823 PERM_NEW_FILE, &unixmode);
6824 if (!NT_STATUS_IS_OK(status)) {
6825 return status;
6828 #if defined(HAVE_MAKEDEV)
6829 dev = makedev(dev_major, dev_minor);
6830 #endif
6832 switch (file_type) {
6833 #if defined(S_IFIFO)
6834 case UNIX_TYPE_FIFO:
6835 unixmode |= S_IFIFO;
6836 break;
6837 #endif
6838 #if defined(S_IFSOCK)
6839 case UNIX_TYPE_SOCKET:
6840 unixmode |= S_IFSOCK;
6841 break;
6842 #endif
6843 #if defined(S_IFCHR)
6844 case UNIX_TYPE_CHARDEV:
6845 unixmode |= S_IFCHR;
6846 break;
6847 #endif
6848 #if defined(S_IFBLK)
6849 case UNIX_TYPE_BLKDEV:
6850 unixmode |= S_IFBLK;
6851 break;
6852 #endif
6853 default:
6854 return NT_STATUS_INVALID_PARAMETER;
6857 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6858 "%.0f mode 0%o for file %s\n", (double)dev,
6859 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6861 /* Ok - do the mknod. */
6862 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6863 return map_nt_error_from_unix(errno);
6866 /* If any of the other "set" calls fail we
6867 * don't want to end up with a half-constructed mknod.
6870 if (lp_inherit_perms(SNUM(conn))) {
6871 char *parent;
6872 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6873 &parent, NULL)) {
6874 return NT_STATUS_NO_MEMORY;
6876 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6877 unixmode);
6878 TALLOC_FREE(parent);
6881 return NT_STATUS_OK;
6884 /****************************************************************************
6885 Deal with SMB_SET_FILE_UNIX_BASIC.
6886 ****************************************************************************/
6888 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6889 struct smb_request *req,
6890 const char *pdata,
6891 int total_data,
6892 files_struct *fsp,
6893 const struct smb_filename *smb_fname)
6895 struct smb_file_time ft;
6896 uint32 raw_unixmode;
6897 mode_t unixmode;
6898 SMB_OFF_T size = 0;
6899 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6900 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6901 NTSTATUS status = NT_STATUS_OK;
6902 bool delete_on_fail = False;
6903 enum perm_type ptype;
6904 files_struct *all_fsps = NULL;
6905 bool modify_mtime = true;
6906 struct file_id id;
6907 struct smb_filename *smb_fname_tmp = NULL;
6908 SMB_STRUCT_STAT sbuf;
6910 ZERO_STRUCT(ft);
6912 if (total_data < 100) {
6913 return NT_STATUS_INVALID_PARAMETER;
6916 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6917 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6918 size=IVAL(pdata,0); /* first 8 Bytes are size */
6919 #ifdef LARGE_SMB_OFF_T
6920 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6921 #else /* LARGE_SMB_OFF_T */
6922 if (IVAL(pdata,4) != 0) {
6923 /* more than 32 bits? */
6924 return NT_STATUS_INVALID_PARAMETER;
6926 #endif /* LARGE_SMB_OFF_T */
6929 ft.atime = interpret_long_date(pdata+24); /* access_time */
6930 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6931 set_owner = (uid_t)IVAL(pdata,40);
6932 set_grp = (gid_t)IVAL(pdata,48);
6933 raw_unixmode = IVAL(pdata,84);
6935 if (VALID_STAT(smb_fname->st)) {
6936 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6937 ptype = PERM_EXISTING_DIR;
6938 } else {
6939 ptype = PERM_EXISTING_FILE;
6941 } else {
6942 ptype = PERM_NEW_FILE;
6945 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6946 ptype, &unixmode);
6947 if (!NT_STATUS_IS_OK(status)) {
6948 return status;
6951 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6952 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6953 smb_fname_str_dbg(smb_fname), (double)size,
6954 (unsigned int)set_owner, (unsigned int)set_grp,
6955 (int)raw_unixmode));
6957 sbuf = smb_fname->st;
6959 if (!VALID_STAT(sbuf)) {
6961 * The only valid use of this is to create character and block
6962 * devices, and named pipes. This is deprecated (IMHO) and
6963 * a new info level should be used for mknod. JRA.
6966 status = smb_unix_mknod(conn,
6967 pdata,
6968 total_data,
6969 smb_fname);
6970 if (!NT_STATUS_IS_OK(status)) {
6971 return status;
6974 status = copy_smb_filename(talloc_tos(), smb_fname,
6975 &smb_fname_tmp);
6976 if (!NT_STATUS_IS_OK(status)) {
6977 return status;
6980 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6981 status = map_nt_error_from_unix(errno);
6982 TALLOC_FREE(smb_fname_tmp);
6983 SMB_VFS_UNLINK(conn, smb_fname);
6984 return status;
6987 sbuf = smb_fname_tmp->st;
6988 smb_fname = smb_fname_tmp;
6990 /* Ensure we don't try and change anything else. */
6991 raw_unixmode = SMB_MODE_NO_CHANGE;
6992 size = get_file_size_stat(&sbuf);
6993 ft.atime = sbuf.st_ex_atime;
6994 ft.mtime = sbuf.st_ex_mtime;
6996 * We continue here as we might want to change the
6997 * owner uid/gid.
6999 delete_on_fail = True;
7002 #if 1
7003 /* Horrible backwards compatibility hack as an old server bug
7004 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7005 * */
7007 if (!size) {
7008 size = get_file_size_stat(&sbuf);
7010 #endif
7013 * Deal with the UNIX specific mode set.
7016 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7017 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7018 "setting mode 0%o for file %s\n",
7019 (unsigned int)unixmode,
7020 smb_fname_str_dbg(smb_fname)));
7021 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7022 return map_nt_error_from_unix(errno);
7027 * Deal with the UNIX specific uid set.
7030 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7031 (sbuf.st_ex_uid != set_owner)) {
7032 int ret;
7034 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7035 "changing owner %u for path %s\n",
7036 (unsigned int)set_owner,
7037 smb_fname_str_dbg(smb_fname)));
7039 if (S_ISLNK(sbuf.st_ex_mode)) {
7040 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7041 set_owner, (gid_t)-1);
7042 } else {
7043 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7044 set_owner, (gid_t)-1);
7047 if (ret != 0) {
7048 status = map_nt_error_from_unix(errno);
7049 if (delete_on_fail) {
7050 SMB_VFS_UNLINK(conn, smb_fname);
7052 return status;
7057 * Deal with the UNIX specific gid set.
7060 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7061 (sbuf.st_ex_gid != set_grp)) {
7062 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7063 "changing group %u for file %s\n",
7064 (unsigned int)set_owner,
7065 smb_fname_str_dbg(smb_fname)));
7066 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7067 set_grp) != 0) {
7068 status = map_nt_error_from_unix(errno);
7069 if (delete_on_fail) {
7070 SMB_VFS_UNLINK(conn, smb_fname);
7072 return status;
7076 /* Deal with any size changes. */
7078 status = smb_set_file_size(conn, req,
7079 fsp,
7080 smb_fname,
7081 &sbuf,
7082 size,
7083 false);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 return status;
7088 /* Deal with any time changes. */
7089 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7090 /* No change, don't cancel anything. */
7091 return status;
7094 id = vfs_file_id_from_sbuf(conn, &sbuf);
7095 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7096 all_fsps = file_find_di_next(all_fsps)) {
7098 * We're setting the time explicitly for UNIX.
7099 * Cancel any pending changes over all handles.
7101 all_fsps->update_write_time_on_close = false;
7102 TALLOC_FREE(all_fsps->update_write_time_event);
7106 * Override the "setting_write_time"
7107 * parameter here as it almost does what
7108 * we need. Just remember if we modified
7109 * mtime and send the notify ourselves.
7111 if (null_timespec(ft.mtime)) {
7112 modify_mtime = false;
7115 status = smb_set_file_time(conn,
7116 fsp,
7117 smb_fname,
7118 &ft,
7119 false);
7120 if (modify_mtime) {
7121 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7122 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7124 return status;
7127 /****************************************************************************
7128 Deal with SMB_SET_FILE_UNIX_INFO2.
7129 ****************************************************************************/
7131 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7132 struct smb_request *req,
7133 const char *pdata,
7134 int total_data,
7135 files_struct *fsp,
7136 const struct smb_filename *smb_fname)
7138 NTSTATUS status;
7139 uint32 smb_fflags;
7140 uint32 smb_fmask;
7142 if (total_data < 116) {
7143 return NT_STATUS_INVALID_PARAMETER;
7146 /* Start by setting all the fields that are common between UNIX_BASIC
7147 * and UNIX_INFO2.
7149 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7150 fsp, smb_fname);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 return status;
7155 smb_fflags = IVAL(pdata, 108);
7156 smb_fmask = IVAL(pdata, 112);
7158 /* NB: We should only attempt to alter the file flags if the client
7159 * sends a non-zero mask.
7161 if (smb_fmask != 0) {
7162 int stat_fflags = 0;
7164 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7165 smb_fmask, &stat_fflags)) {
7166 /* Client asked to alter a flag we don't understand. */
7167 return NT_STATUS_INVALID_PARAMETER;
7170 if (fsp && fsp->fh->fd != -1) {
7171 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7172 return NT_STATUS_NOT_SUPPORTED;
7173 } else {
7174 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7175 stat_fflags) != 0) {
7176 return map_nt_error_from_unix(errno);
7181 /* XXX: need to add support for changing the create_time here. You
7182 * can do this for paths on Darwin with setattrlist(2). The right way
7183 * to hook this up is probably by extending the VFS utimes interface.
7186 return NT_STATUS_OK;
7189 /****************************************************************************
7190 Create a directory with POSIX semantics.
7191 ****************************************************************************/
7193 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7194 struct smb_request *req,
7195 char **ppdata,
7196 int total_data,
7197 struct smb_filename *smb_fname,
7198 int *pdata_return_size)
7200 NTSTATUS status = NT_STATUS_OK;
7201 uint32 raw_unixmode = 0;
7202 uint32 mod_unixmode = 0;
7203 mode_t unixmode = (mode_t)0;
7204 files_struct *fsp = NULL;
7205 uint16 info_level_return = 0;
7206 int info;
7207 char *pdata = *ppdata;
7209 if (total_data < 18) {
7210 return NT_STATUS_INVALID_PARAMETER;
7213 raw_unixmode = IVAL(pdata,8);
7214 /* Next 4 bytes are not yet defined. */
7216 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7217 PERM_NEW_DIR, &unixmode);
7218 if (!NT_STATUS_IS_OK(status)) {
7219 return status;
7222 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7224 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7225 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7227 status = SMB_VFS_CREATE_FILE(
7228 conn, /* conn */
7229 req, /* req */
7230 0, /* root_dir_fid */
7231 smb_fname, /* fname */
7232 FILE_READ_ATTRIBUTES, /* access_mask */
7233 FILE_SHARE_NONE, /* share_access */
7234 FILE_CREATE, /* create_disposition*/
7235 FILE_DIRECTORY_FILE, /* create_options */
7236 mod_unixmode, /* file_attributes */
7237 0, /* oplock_request */
7238 0, /* allocation_size */
7239 0, /* private_flags */
7240 NULL, /* sd */
7241 NULL, /* ea_list */
7242 &fsp, /* result */
7243 &info); /* pinfo */
7245 if (NT_STATUS_IS_OK(status)) {
7246 close_file(req, fsp, NORMAL_CLOSE);
7249 info_level_return = SVAL(pdata,16);
7251 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7252 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7253 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7254 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7255 } else {
7256 *pdata_return_size = 12;
7259 /* Realloc the data size */
7260 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7261 if (*ppdata == NULL) {
7262 *pdata_return_size = 0;
7263 return NT_STATUS_NO_MEMORY;
7265 pdata = *ppdata;
7267 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7268 SSVAL(pdata,2,0); /* No fnum. */
7269 SIVAL(pdata,4,info); /* Was directory created. */
7271 switch (info_level_return) {
7272 case SMB_QUERY_FILE_UNIX_BASIC:
7273 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7274 SSVAL(pdata,10,0); /* Padding. */
7275 store_file_unix_basic(conn, pdata + 12, fsp,
7276 &smb_fname->st);
7277 break;
7278 case SMB_QUERY_FILE_UNIX_INFO2:
7279 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7280 SSVAL(pdata,10,0); /* Padding. */
7281 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7282 &smb_fname->st);
7283 break;
7284 default:
7285 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7286 SSVAL(pdata,10,0); /* Padding. */
7287 break;
7290 return status;
7293 /****************************************************************************
7294 Open/Create a file with POSIX semantics.
7295 ****************************************************************************/
7297 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7298 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7300 static NTSTATUS smb_posix_open(connection_struct *conn,
7301 struct smb_request *req,
7302 char **ppdata,
7303 int total_data,
7304 struct smb_filename *smb_fname,
7305 int *pdata_return_size)
7307 bool extended_oplock_granted = False;
7308 char *pdata = *ppdata;
7309 uint32 flags = 0;
7310 uint32 wire_open_mode = 0;
7311 uint32 raw_unixmode = 0;
7312 uint32 mod_unixmode = 0;
7313 uint32 create_disp = 0;
7314 uint32 access_mask = 0;
7315 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7316 NTSTATUS status = NT_STATUS_OK;
7317 mode_t unixmode = (mode_t)0;
7318 files_struct *fsp = NULL;
7319 int oplock_request = 0;
7320 int info = 0;
7321 uint16 info_level_return = 0;
7323 if (total_data < 18) {
7324 return NT_STATUS_INVALID_PARAMETER;
7327 flags = IVAL(pdata,0);
7328 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7329 if (oplock_request) {
7330 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7333 wire_open_mode = IVAL(pdata,4);
7335 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7336 return smb_posix_mkdir(conn, req,
7337 ppdata,
7338 total_data,
7339 smb_fname,
7340 pdata_return_size);
7343 switch (wire_open_mode & SMB_ACCMODE) {
7344 case SMB_O_RDONLY:
7345 access_mask = SMB_O_RDONLY_MAPPING;
7346 break;
7347 case SMB_O_WRONLY:
7348 access_mask = SMB_O_WRONLY_MAPPING;
7349 break;
7350 case SMB_O_RDWR:
7351 access_mask = (SMB_O_RDONLY_MAPPING|
7352 SMB_O_WRONLY_MAPPING);
7353 break;
7354 default:
7355 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7356 (unsigned int)wire_open_mode ));
7357 return NT_STATUS_INVALID_PARAMETER;
7360 wire_open_mode &= ~SMB_ACCMODE;
7362 /* First take care of O_CREAT|O_EXCL interactions. */
7363 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7364 case (SMB_O_CREAT | SMB_O_EXCL):
7365 /* File exists fail. File not exist create. */
7366 create_disp = FILE_CREATE;
7367 break;
7368 case SMB_O_CREAT:
7369 /* File exists open. File not exist create. */
7370 create_disp = FILE_OPEN_IF;
7371 break;
7372 case 0:
7373 /* File exists open. File not exist fail. */
7374 create_disp = FILE_OPEN;
7375 break;
7376 case SMB_O_EXCL:
7377 /* O_EXCL on its own without O_CREAT is undefined. */
7378 default:
7379 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7380 (unsigned int)wire_open_mode ));
7381 return NT_STATUS_INVALID_PARAMETER;
7384 /* Next factor in the effects of O_TRUNC. */
7385 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7387 if (wire_open_mode & SMB_O_TRUNC) {
7388 switch (create_disp) {
7389 case FILE_CREATE:
7390 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7391 /* Leave create_disp alone as
7392 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7394 /* File exists fail. File not exist create. */
7395 break;
7396 case FILE_OPEN_IF:
7397 /* SMB_O_CREAT | SMB_O_TRUNC */
7398 /* File exists overwrite. File not exist create. */
7399 create_disp = FILE_OVERWRITE_IF;
7400 break;
7401 case FILE_OPEN:
7402 /* SMB_O_TRUNC */
7403 /* File exists overwrite. File not exist fail. */
7404 create_disp = FILE_OVERWRITE;
7405 break;
7406 default:
7407 /* Cannot get here. */
7408 smb_panic("smb_posix_open: logic error");
7409 return NT_STATUS_INVALID_PARAMETER;
7413 raw_unixmode = IVAL(pdata,8);
7414 /* Next 4 bytes are not yet defined. */
7416 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7417 (VALID_STAT(smb_fname->st) ?
7418 PERM_EXISTING_FILE : PERM_NEW_FILE),
7419 &unixmode);
7421 if (!NT_STATUS_IS_OK(status)) {
7422 return status;
7425 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7427 if (wire_open_mode & SMB_O_SYNC) {
7428 create_options |= FILE_WRITE_THROUGH;
7430 if (wire_open_mode & SMB_O_APPEND) {
7431 access_mask |= FILE_APPEND_DATA;
7433 if (wire_open_mode & SMB_O_DIRECT) {
7434 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7437 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7438 VALID_STAT_OF_DIR(smb_fname->st)) {
7439 if (access_mask != SMB_O_RDONLY_MAPPING) {
7440 return NT_STATUS_FILE_IS_A_DIRECTORY;
7442 create_options &= ~FILE_NON_DIRECTORY_FILE;
7443 create_options |= FILE_DIRECTORY_FILE;
7446 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7447 smb_fname_str_dbg(smb_fname),
7448 (unsigned int)wire_open_mode,
7449 (unsigned int)unixmode ));
7451 status = SMB_VFS_CREATE_FILE(
7452 conn, /* conn */
7453 req, /* req */
7454 0, /* root_dir_fid */
7455 smb_fname, /* fname */
7456 access_mask, /* access_mask */
7457 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7458 FILE_SHARE_DELETE),
7459 create_disp, /* create_disposition*/
7460 create_options, /* create_options */
7461 mod_unixmode, /* file_attributes */
7462 oplock_request, /* oplock_request */
7463 0, /* allocation_size */
7464 0, /* private_flags */
7465 NULL, /* sd */
7466 NULL, /* ea_list */
7467 &fsp, /* result */
7468 &info); /* pinfo */
7470 if (!NT_STATUS_IS_OK(status)) {
7471 return status;
7474 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7475 extended_oplock_granted = True;
7478 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7479 extended_oplock_granted = True;
7482 info_level_return = SVAL(pdata,16);
7484 /* Allocate the correct return size. */
7486 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7487 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7488 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7489 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7490 } else {
7491 *pdata_return_size = 12;
7494 /* Realloc the data size */
7495 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7496 if (*ppdata == NULL) {
7497 close_file(req, fsp, ERROR_CLOSE);
7498 *pdata_return_size = 0;
7499 return NT_STATUS_NO_MEMORY;
7501 pdata = *ppdata;
7503 if (extended_oplock_granted) {
7504 if (flags & REQUEST_BATCH_OPLOCK) {
7505 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7506 } else {
7507 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7509 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7510 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7511 } else {
7512 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7515 SSVAL(pdata,2,fsp->fnum);
7516 SIVAL(pdata,4,info); /* Was file created etc. */
7518 switch (info_level_return) {
7519 case SMB_QUERY_FILE_UNIX_BASIC:
7520 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7521 SSVAL(pdata,10,0); /* padding. */
7522 store_file_unix_basic(conn, pdata + 12, fsp,
7523 &smb_fname->st);
7524 break;
7525 case SMB_QUERY_FILE_UNIX_INFO2:
7526 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7527 SSVAL(pdata,10,0); /* padding. */
7528 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7529 &smb_fname->st);
7530 break;
7531 default:
7532 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7533 SSVAL(pdata,10,0); /* padding. */
7534 break;
7536 return NT_STATUS_OK;
7539 /****************************************************************************
7540 Delete a file with POSIX semantics.
7541 ****************************************************************************/
7543 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7544 struct smb_request *req,
7545 const char *pdata,
7546 int total_data,
7547 struct smb_filename *smb_fname)
7549 NTSTATUS status = NT_STATUS_OK;
7550 files_struct *fsp = NULL;
7551 uint16 flags = 0;
7552 char del = 1;
7553 int info = 0;
7554 int create_options = 0;
7555 int i;
7556 struct share_mode_lock *lck = NULL;
7558 if (total_data < 2) {
7559 return NT_STATUS_INVALID_PARAMETER;
7562 flags = SVAL(pdata,0);
7564 if (!VALID_STAT(smb_fname->st)) {
7565 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7568 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7569 !VALID_STAT_OF_DIR(smb_fname->st)) {
7570 return NT_STATUS_NOT_A_DIRECTORY;
7573 DEBUG(10,("smb_posix_unlink: %s %s\n",
7574 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7575 smb_fname_str_dbg(smb_fname)));
7577 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7578 create_options |= FILE_DIRECTORY_FILE;
7581 status = SMB_VFS_CREATE_FILE(
7582 conn, /* conn */
7583 req, /* req */
7584 0, /* root_dir_fid */
7585 smb_fname, /* fname */
7586 DELETE_ACCESS, /* access_mask */
7587 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7588 FILE_SHARE_DELETE),
7589 FILE_OPEN, /* create_disposition*/
7590 create_options, /* create_options */
7591 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7592 0, /* oplock_request */
7593 0, /* allocation_size */
7594 0, /* private_flags */
7595 NULL, /* sd */
7596 NULL, /* ea_list */
7597 &fsp, /* result */
7598 &info); /* pinfo */
7600 if (!NT_STATUS_IS_OK(status)) {
7601 return status;
7605 * Don't lie to client. If we can't really delete due to
7606 * non-POSIX opens return SHARING_VIOLATION.
7609 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7610 if (lck == NULL) {
7611 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7612 "lock for file %s\n", fsp_str_dbg(fsp)));
7613 close_file(req, fsp, NORMAL_CLOSE);
7614 return NT_STATUS_INVALID_PARAMETER;
7618 * See if others still have the file open. If this is the case, then
7619 * don't delete. If all opens are POSIX delete we can set the delete
7620 * on close disposition.
7622 for (i=0; i<lck->data->num_share_modes; i++) {
7623 struct share_mode_entry *e = &lck->data->share_modes[i];
7624 if (is_valid_share_mode_entry(e)) {
7625 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7626 continue;
7628 /* Fail with sharing violation. */
7629 close_file(req, fsp, NORMAL_CLOSE);
7630 TALLOC_FREE(lck);
7631 return NT_STATUS_SHARING_VIOLATION;
7636 * Set the delete on close.
7638 status = smb_set_file_disposition_info(conn,
7639 &del,
7641 fsp,
7642 smb_fname);
7644 if (!NT_STATUS_IS_OK(status)) {
7645 close_file(req, fsp, NORMAL_CLOSE);
7646 TALLOC_FREE(lck);
7647 return status;
7649 TALLOC_FREE(lck);
7650 return close_file(req, fsp, NORMAL_CLOSE);
7653 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7654 struct smb_request *req,
7655 TALLOC_CTX *mem_ctx,
7656 uint16_t info_level,
7657 files_struct *fsp,
7658 struct smb_filename *smb_fname,
7659 char **ppdata, int total_data,
7660 int *ret_data_size)
7662 char *pdata = *ppdata;
7663 NTSTATUS status = NT_STATUS_OK;
7664 int data_return_size = 0;
7666 *ret_data_size = 0;
7668 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7669 return NT_STATUS_INVALID_LEVEL;
7672 if (!CAN_WRITE(conn)) {
7673 /* Allow POSIX opens. The open path will deny
7674 * any non-readonly opens. */
7675 if (info_level != SMB_POSIX_PATH_OPEN) {
7676 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7680 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7681 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7682 fsp ? fsp->fnum : -1, info_level, total_data));
7684 switch (info_level) {
7686 case SMB_INFO_STANDARD:
7688 status = smb_set_info_standard(conn,
7689 pdata,
7690 total_data,
7691 fsp,
7692 smb_fname);
7693 break;
7696 case SMB_INFO_SET_EA:
7698 status = smb_info_set_ea(conn,
7699 pdata,
7700 total_data,
7701 fsp,
7702 smb_fname);
7703 break;
7706 case SMB_SET_FILE_BASIC_INFO:
7707 case SMB_FILE_BASIC_INFORMATION:
7709 status = smb_set_file_basic_info(conn,
7710 pdata,
7711 total_data,
7712 fsp,
7713 smb_fname);
7714 break;
7717 case SMB_FILE_ALLOCATION_INFORMATION:
7718 case SMB_SET_FILE_ALLOCATION_INFO:
7720 status = smb_set_file_allocation_info(conn, req,
7721 pdata,
7722 total_data,
7723 fsp,
7724 smb_fname);
7725 break;
7728 case SMB_FILE_END_OF_FILE_INFORMATION:
7729 case SMB_SET_FILE_END_OF_FILE_INFO:
7732 * XP/Win7 both fail after the createfile with
7733 * SMB_SET_FILE_END_OF_FILE_INFO but not
7734 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7735 * The level is known here, so pass it down
7736 * appropriately.
7738 bool should_fail =
7739 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7741 status = smb_set_file_end_of_file_info(conn, req,
7742 pdata,
7743 total_data,
7744 fsp,
7745 smb_fname,
7746 should_fail);
7747 break;
7750 case SMB_FILE_DISPOSITION_INFORMATION:
7751 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7753 #if 0
7754 /* JRA - We used to just ignore this on a path ?
7755 * Shouldn't this be invalid level on a pathname
7756 * based call ?
7758 if (tran_call != TRANSACT2_SETFILEINFO) {
7759 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7761 #endif
7762 status = smb_set_file_disposition_info(conn,
7763 pdata,
7764 total_data,
7765 fsp,
7766 smb_fname);
7767 break;
7770 case SMB_FILE_POSITION_INFORMATION:
7772 status = smb_file_position_information(conn,
7773 pdata,
7774 total_data,
7775 fsp);
7776 break;
7779 case SMB_FILE_FULL_EA_INFORMATION:
7781 status = smb_set_file_full_ea_info(conn,
7782 pdata,
7783 total_data,
7784 fsp);
7785 break;
7788 /* From tridge Samba4 :
7789 * MODE_INFORMATION in setfileinfo (I have no
7790 * idea what "mode information" on a file is - it takes a value of 0,
7791 * 2, 4 or 6. What could it be?).
7794 case SMB_FILE_MODE_INFORMATION:
7796 status = smb_file_mode_information(conn,
7797 pdata,
7798 total_data);
7799 break;
7803 * CIFS UNIX extensions.
7806 case SMB_SET_FILE_UNIX_BASIC:
7808 status = smb_set_file_unix_basic(conn, req,
7809 pdata,
7810 total_data,
7811 fsp,
7812 smb_fname);
7813 break;
7816 case SMB_SET_FILE_UNIX_INFO2:
7818 status = smb_set_file_unix_info2(conn, req,
7819 pdata,
7820 total_data,
7821 fsp,
7822 smb_fname);
7823 break;
7826 case SMB_SET_FILE_UNIX_LINK:
7828 if (fsp) {
7829 /* We must have a pathname for this. */
7830 return NT_STATUS_INVALID_LEVEL;
7832 status = smb_set_file_unix_link(conn, req, pdata,
7833 total_data, smb_fname);
7834 break;
7837 case SMB_SET_FILE_UNIX_HLINK:
7839 if (fsp) {
7840 /* We must have a pathname for this. */
7841 return NT_STATUS_INVALID_LEVEL;
7843 status = smb_set_file_unix_hlink(conn, req,
7844 pdata, total_data,
7845 smb_fname);
7846 break;
7849 case SMB_FILE_RENAME_INFORMATION:
7851 status = smb_file_rename_information(conn, req,
7852 pdata, total_data,
7853 fsp, smb_fname);
7854 break;
7857 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7859 /* SMB2 rename information. */
7860 status = smb2_file_rename_information(conn, req,
7861 pdata, total_data,
7862 fsp, smb_fname);
7863 break;
7866 case SMB_FILE_LINK_INFORMATION:
7868 status = smb_file_link_information(conn, req,
7869 pdata, total_data,
7870 fsp, smb_fname);
7871 break;
7874 #if defined(HAVE_POSIX_ACLS)
7875 case SMB_SET_POSIX_ACL:
7877 status = smb_set_posix_acl(conn,
7878 pdata,
7879 total_data,
7880 fsp,
7881 smb_fname);
7882 break;
7884 #endif
7886 case SMB_SET_POSIX_LOCK:
7888 if (!fsp) {
7889 return NT_STATUS_INVALID_LEVEL;
7891 status = smb_set_posix_lock(conn, req,
7892 pdata, total_data, fsp);
7893 break;
7896 case SMB_POSIX_PATH_OPEN:
7898 if (fsp) {
7899 /* We must have a pathname for this. */
7900 return NT_STATUS_INVALID_LEVEL;
7903 status = smb_posix_open(conn, req,
7904 ppdata,
7905 total_data,
7906 smb_fname,
7907 &data_return_size);
7908 break;
7911 case SMB_POSIX_PATH_UNLINK:
7913 if (fsp) {
7914 /* We must have a pathname for this. */
7915 return NT_STATUS_INVALID_LEVEL;
7918 status = smb_posix_unlink(conn, req,
7919 pdata,
7920 total_data,
7921 smb_fname);
7922 break;
7925 default:
7926 return NT_STATUS_INVALID_LEVEL;
7929 if (!NT_STATUS_IS_OK(status)) {
7930 return status;
7933 *ret_data_size = data_return_size;
7934 return NT_STATUS_OK;
7937 /****************************************************************************
7938 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7939 ****************************************************************************/
7941 static void call_trans2setfilepathinfo(connection_struct *conn,
7942 struct smb_request *req,
7943 unsigned int tran_call,
7944 char **pparams, int total_params,
7945 char **ppdata, int total_data,
7946 unsigned int max_data_bytes)
7948 char *params = *pparams;
7949 char *pdata = *ppdata;
7950 uint16 info_level;
7951 struct smb_filename *smb_fname = NULL;
7952 files_struct *fsp = NULL;
7953 NTSTATUS status = NT_STATUS_OK;
7954 int data_return_size = 0;
7956 if (!params) {
7957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7958 return;
7961 if (tran_call == TRANSACT2_SETFILEINFO) {
7962 if (total_params < 4) {
7963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7964 return;
7967 fsp = file_fsp(req, SVAL(params,0));
7968 /* Basic check for non-null fsp. */
7969 if (!check_fsp_open(conn, req, fsp)) {
7970 return;
7972 info_level = SVAL(params,2);
7974 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7975 &smb_fname);
7976 if (!NT_STATUS_IS_OK(status)) {
7977 reply_nterror(req, status);
7978 return;
7981 if(fsp->fh->fd == -1) {
7983 * This is actually a SETFILEINFO on a directory
7984 * handle (returned from an NT SMB). NT5.0 seems
7985 * to do this call. JRA.
7987 if (INFO_LEVEL_IS_UNIX(info_level)) {
7988 /* Always do lstat for UNIX calls. */
7989 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7990 DEBUG(3,("call_trans2setfilepathinfo: "
7991 "SMB_VFS_LSTAT of %s failed "
7992 "(%s)\n",
7993 smb_fname_str_dbg(smb_fname),
7994 strerror(errno)));
7995 reply_nterror(req, map_nt_error_from_unix(errno));
7996 return;
7998 } else {
7999 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8000 DEBUG(3,("call_trans2setfilepathinfo: "
8001 "fileinfo of %s failed (%s)\n",
8002 smb_fname_str_dbg(smb_fname),
8003 strerror(errno)));
8004 reply_nterror(req, map_nt_error_from_unix(errno));
8005 return;
8008 } else if (fsp->print_file) {
8010 * Doing a DELETE_ON_CLOSE should cancel a print job.
8012 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8013 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8015 DEBUG(3,("call_trans2setfilepathinfo: "
8016 "Cancelling print job (%s)\n",
8017 fsp_str_dbg(fsp)));
8019 SSVAL(params,0,0);
8020 send_trans2_replies(conn, req, params, 2,
8021 *ppdata, 0,
8022 max_data_bytes);
8023 return;
8024 } else {
8025 reply_nterror(req,
8026 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8027 return;
8029 } else {
8031 * Original code - this is an open file.
8033 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8034 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8035 "of fnum %d failed (%s)\n", fsp->fnum,
8036 strerror(errno)));
8037 reply_nterror(req, map_nt_error_from_unix(errno));
8038 return;
8041 } else {
8042 char *fname = NULL;
8043 uint32_t ucf_flags = 0;
8045 /* set path info */
8046 if (total_params < 7) {
8047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8048 return;
8051 info_level = SVAL(params,0);
8052 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8053 total_params - 6, STR_TERMINATE,
8054 &status);
8055 if (!NT_STATUS_IS_OK(status)) {
8056 reply_nterror(req, status);
8057 return;
8060 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8061 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8062 info_level == SMB_FILE_RENAME_INFORMATION ||
8063 info_level == SMB_POSIX_PATH_UNLINK) {
8064 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8067 status = filename_convert(req, conn,
8068 req->flags2 & FLAGS2_DFS_PATHNAMES,
8069 fname,
8070 ucf_flags,
8071 NULL,
8072 &smb_fname);
8073 if (!NT_STATUS_IS_OK(status)) {
8074 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8075 reply_botherror(req,
8076 NT_STATUS_PATH_NOT_COVERED,
8077 ERRSRV, ERRbadpath);
8078 return;
8080 reply_nterror(req, status);
8081 return;
8084 if (INFO_LEVEL_IS_UNIX(info_level)) {
8086 * For CIFS UNIX extensions the target name may not exist.
8089 /* Always do lstat for UNIX calls. */
8090 SMB_VFS_LSTAT(conn, smb_fname);
8092 } else if (!VALID_STAT(smb_fname->st) &&
8093 SMB_VFS_STAT(conn, smb_fname)) {
8094 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8095 "%s failed (%s)\n",
8096 smb_fname_str_dbg(smb_fname),
8097 strerror(errno)));
8098 reply_nterror(req, map_nt_error_from_unix(errno));
8099 return;
8103 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8104 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8105 fsp ? fsp->fnum : -1, info_level,total_data));
8107 /* Realloc the parameter size */
8108 *pparams = (char *)SMB_REALLOC(*pparams,2);
8109 if (*pparams == NULL) {
8110 reply_nterror(req, NT_STATUS_NO_MEMORY);
8111 return;
8113 params = *pparams;
8115 SSVAL(params,0,0);
8117 status = smbd_do_setfilepathinfo(conn, req, req,
8118 info_level,
8119 fsp,
8120 smb_fname,
8121 ppdata, total_data,
8122 &data_return_size);
8123 if (!NT_STATUS_IS_OK(status)) {
8124 if (open_was_deferred(req->sconn, req->mid)) {
8125 /* We have re-scheduled this call. */
8126 return;
8128 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8129 /* We have re-scheduled this call. */
8130 return;
8132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8133 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8134 ERRSRV, ERRbadpath);
8135 return;
8137 if (info_level == SMB_POSIX_PATH_OPEN) {
8138 reply_openerror(req, status);
8139 return;
8142 reply_nterror(req, status);
8143 return;
8146 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8147 max_data_bytes);
8149 return;
8152 /****************************************************************************
8153 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8154 ****************************************************************************/
8156 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8157 char **pparams, int total_params,
8158 char **ppdata, int total_data,
8159 unsigned int max_data_bytes)
8161 struct smb_filename *smb_dname = NULL;
8162 char *params = *pparams;
8163 char *pdata = *ppdata;
8164 char *directory = NULL;
8165 NTSTATUS status = NT_STATUS_OK;
8166 struct ea_list *ea_list = NULL;
8167 TALLOC_CTX *ctx = talloc_tos();
8169 if (!CAN_WRITE(conn)) {
8170 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8171 return;
8174 if (total_params < 5) {
8175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8176 return;
8179 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8180 total_params - 4, STR_TERMINATE,
8181 &status);
8182 if (!NT_STATUS_IS_OK(status)) {
8183 reply_nterror(req, status);
8184 return;
8187 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8189 status = filename_convert(ctx,
8190 conn,
8191 req->flags2 & FLAGS2_DFS_PATHNAMES,
8192 directory,
8194 NULL,
8195 &smb_dname);
8197 if (!NT_STATUS_IS_OK(status)) {
8198 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8199 reply_botherror(req,
8200 NT_STATUS_PATH_NOT_COVERED,
8201 ERRSRV, ERRbadpath);
8202 return;
8204 reply_nterror(req, status);
8205 return;
8209 * OS/2 workplace shell seems to send SET_EA requests of "null"
8210 * length (4 bytes containing IVAL 4).
8211 * They seem to have no effect. Bug #3212. JRA.
8214 if (total_data && (total_data != 4)) {
8215 /* Any data in this call is an EA list. */
8216 if (total_data < 10) {
8217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8218 goto out;
8221 if (IVAL(pdata,0) > total_data) {
8222 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8223 IVAL(pdata,0), (unsigned int)total_data));
8224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8225 goto out;
8228 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8229 total_data - 4);
8230 if (!ea_list) {
8231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8232 goto out;
8235 if (!lp_ea_support(SNUM(conn))) {
8236 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8237 goto out;
8240 /* If total_data == 4 Windows doesn't care what values
8241 * are placed in that field, it just ignores them.
8242 * The System i QNTC IBM SMB client puts bad values here,
8243 * so ignore them. */
8245 status = create_directory(conn, req, smb_dname);
8247 if (!NT_STATUS_IS_OK(status)) {
8248 reply_nterror(req, status);
8249 goto out;
8252 /* Try and set any given EA. */
8253 if (ea_list) {
8254 status = set_ea(conn, NULL, smb_dname, ea_list);
8255 if (!NT_STATUS_IS_OK(status)) {
8256 reply_nterror(req, status);
8257 goto out;
8261 /* Realloc the parameter and data sizes */
8262 *pparams = (char *)SMB_REALLOC(*pparams,2);
8263 if(*pparams == NULL) {
8264 reply_nterror(req, NT_STATUS_NO_MEMORY);
8265 goto out;
8267 params = *pparams;
8269 SSVAL(params,0,0);
8271 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8273 out:
8274 TALLOC_FREE(smb_dname);
8275 return;
8278 /****************************************************************************
8279 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8280 We don't actually do this - we just send a null response.
8281 ****************************************************************************/
8283 static void call_trans2findnotifyfirst(connection_struct *conn,
8284 struct smb_request *req,
8285 char **pparams, int total_params,
8286 char **ppdata, int total_data,
8287 unsigned int max_data_bytes)
8289 char *params = *pparams;
8290 uint16 info_level;
8292 if (total_params < 6) {
8293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8294 return;
8297 info_level = SVAL(params,4);
8298 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8300 switch (info_level) {
8301 case 1:
8302 case 2:
8303 break;
8304 default:
8305 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8306 return;
8309 /* Realloc the parameter and data sizes */
8310 *pparams = (char *)SMB_REALLOC(*pparams,6);
8311 if (*pparams == NULL) {
8312 reply_nterror(req, NT_STATUS_NO_MEMORY);
8313 return;
8315 params = *pparams;
8317 SSVAL(params,0,fnf_handle);
8318 SSVAL(params,2,0); /* No changes */
8319 SSVAL(params,4,0); /* No EA errors */
8321 fnf_handle++;
8323 if(fnf_handle == 0)
8324 fnf_handle = 257;
8326 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8328 return;
8331 /****************************************************************************
8332 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8333 changes). Currently this does nothing.
8334 ****************************************************************************/
8336 static void call_trans2findnotifynext(connection_struct *conn,
8337 struct smb_request *req,
8338 char **pparams, int total_params,
8339 char **ppdata, int total_data,
8340 unsigned int max_data_bytes)
8342 char *params = *pparams;
8344 DEBUG(3,("call_trans2findnotifynext\n"));
8346 /* Realloc the parameter and data sizes */
8347 *pparams = (char *)SMB_REALLOC(*pparams,4);
8348 if (*pparams == NULL) {
8349 reply_nterror(req, NT_STATUS_NO_MEMORY);
8350 return;
8352 params = *pparams;
8354 SSVAL(params,0,0); /* No changes */
8355 SSVAL(params,2,0); /* No EA errors */
8357 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8359 return;
8362 /****************************************************************************
8363 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8364 ****************************************************************************/
8366 static void call_trans2getdfsreferral(connection_struct *conn,
8367 struct smb_request *req,
8368 char **pparams, int total_params,
8369 char **ppdata, int total_data,
8370 unsigned int max_data_bytes)
8372 char *params = *pparams;
8373 char *pathname = NULL;
8374 int reply_size = 0;
8375 int max_referral_level;
8376 NTSTATUS status = NT_STATUS_OK;
8377 TALLOC_CTX *ctx = talloc_tos();
8379 DEBUG(10,("call_trans2getdfsreferral\n"));
8381 if (total_params < 3) {
8382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8383 return;
8386 max_referral_level = SVAL(params,0);
8388 if(!lp_host_msdfs()) {
8389 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8390 return;
8393 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8394 total_params - 2, STR_TERMINATE);
8395 if (!pathname) {
8396 reply_nterror(req, NT_STATUS_NOT_FOUND);
8397 return;
8399 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8400 ppdata,&status)) < 0) {
8401 reply_nterror(req, status);
8402 return;
8405 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8406 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8407 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8409 return;
8412 #define LMCAT_SPL 0x53
8413 #define LMFUNC_GETJOBID 0x60
8415 /****************************************************************************
8416 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8417 ****************************************************************************/
8419 static void call_trans2ioctl(connection_struct *conn,
8420 struct smb_request *req,
8421 char **pparams, int total_params,
8422 char **ppdata, int total_data,
8423 unsigned int max_data_bytes)
8425 char *pdata = *ppdata;
8426 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8428 /* check for an invalid fid before proceeding */
8430 if (!fsp) {
8431 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8432 return;
8435 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8436 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8437 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8438 if (*ppdata == NULL) {
8439 reply_nterror(req, NT_STATUS_NO_MEMORY);
8440 return;
8442 pdata = *ppdata;
8444 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8445 CAN ACCEPT THIS IN UNICODE. JRA. */
8447 /* Job number */
8448 if (fsp->print_file) {
8449 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8450 } else {
8451 SSVAL(pdata, 0, 0);
8453 srvstr_push(pdata, req->flags2, pdata + 2,
8454 lp_netbios_name(), 15,
8455 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8456 srvstr_push(pdata, req->flags2, pdata+18,
8457 lp_servicename(SNUM(conn)), 13,
8458 STR_ASCII|STR_TERMINATE); /* Service name */
8459 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8460 max_data_bytes);
8461 return;
8464 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8465 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8468 /****************************************************************************
8469 Reply to a SMBfindclose (stop trans2 directory search).
8470 ****************************************************************************/
8472 void reply_findclose(struct smb_request *req)
8474 int dptr_num;
8475 struct smbd_server_connection *sconn = req->sconn;
8477 START_PROFILE(SMBfindclose);
8479 if (req->wct < 1) {
8480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8481 END_PROFILE(SMBfindclose);
8482 return;
8485 dptr_num = SVALS(req->vwv+0, 0);
8487 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8489 dptr_close(sconn, &dptr_num);
8491 reply_outbuf(req, 0, 0);
8493 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8495 END_PROFILE(SMBfindclose);
8496 return;
8499 /****************************************************************************
8500 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8501 ****************************************************************************/
8503 void reply_findnclose(struct smb_request *req)
8505 int dptr_num;
8507 START_PROFILE(SMBfindnclose);
8509 if (req->wct < 1) {
8510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8511 END_PROFILE(SMBfindnclose);
8512 return;
8515 dptr_num = SVAL(req->vwv+0, 0);
8517 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8519 /* We never give out valid handles for a
8520 findnotifyfirst - so any dptr_num is ok here.
8521 Just ignore it. */
8523 reply_outbuf(req, 0, 0);
8525 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8527 END_PROFILE(SMBfindnclose);
8528 return;
8531 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8532 struct trans_state *state)
8534 if (get_Protocol() >= PROTOCOL_NT1) {
8535 req->flags2 |= 0x40; /* IS_LONG_NAME */
8536 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8539 if (conn->encrypt_level == Required && !req->encrypted) {
8540 if (state->call != TRANSACT2_QFSINFO &&
8541 state->call != TRANSACT2_SETFSINFO) {
8542 DEBUG(0,("handle_trans2: encryption required "
8543 "with call 0x%x\n",
8544 (unsigned int)state->call));
8545 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8546 return;
8550 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8552 /* Now we must call the relevant TRANS2 function */
8553 switch(state->call) {
8554 case TRANSACT2_OPEN:
8556 START_PROFILE(Trans2_open);
8557 call_trans2open(conn, req,
8558 &state->param, state->total_param,
8559 &state->data, state->total_data,
8560 state->max_data_return);
8561 END_PROFILE(Trans2_open);
8562 break;
8565 case TRANSACT2_FINDFIRST:
8567 START_PROFILE(Trans2_findfirst);
8568 call_trans2findfirst(conn, req,
8569 &state->param, state->total_param,
8570 &state->data, state->total_data,
8571 state->max_data_return);
8572 END_PROFILE(Trans2_findfirst);
8573 break;
8576 case TRANSACT2_FINDNEXT:
8578 START_PROFILE(Trans2_findnext);
8579 call_trans2findnext(conn, req,
8580 &state->param, state->total_param,
8581 &state->data, state->total_data,
8582 state->max_data_return);
8583 END_PROFILE(Trans2_findnext);
8584 break;
8587 case TRANSACT2_QFSINFO:
8589 START_PROFILE(Trans2_qfsinfo);
8590 call_trans2qfsinfo(conn, req,
8591 &state->param, state->total_param,
8592 &state->data, state->total_data,
8593 state->max_data_return);
8594 END_PROFILE(Trans2_qfsinfo);
8595 break;
8598 case TRANSACT2_SETFSINFO:
8600 START_PROFILE(Trans2_setfsinfo);
8601 call_trans2setfsinfo(conn, req,
8602 &state->param, state->total_param,
8603 &state->data, state->total_data,
8604 state->max_data_return);
8605 END_PROFILE(Trans2_setfsinfo);
8606 break;
8609 case TRANSACT2_QPATHINFO:
8610 case TRANSACT2_QFILEINFO:
8612 START_PROFILE(Trans2_qpathinfo);
8613 call_trans2qfilepathinfo(conn, req, state->call,
8614 &state->param, state->total_param,
8615 &state->data, state->total_data,
8616 state->max_data_return);
8617 END_PROFILE(Trans2_qpathinfo);
8618 break;
8621 case TRANSACT2_SETPATHINFO:
8622 case TRANSACT2_SETFILEINFO:
8624 START_PROFILE(Trans2_setpathinfo);
8625 call_trans2setfilepathinfo(conn, req, state->call,
8626 &state->param, state->total_param,
8627 &state->data, state->total_data,
8628 state->max_data_return);
8629 END_PROFILE(Trans2_setpathinfo);
8630 break;
8633 case TRANSACT2_FINDNOTIFYFIRST:
8635 START_PROFILE(Trans2_findnotifyfirst);
8636 call_trans2findnotifyfirst(conn, req,
8637 &state->param, state->total_param,
8638 &state->data, state->total_data,
8639 state->max_data_return);
8640 END_PROFILE(Trans2_findnotifyfirst);
8641 break;
8644 case TRANSACT2_FINDNOTIFYNEXT:
8646 START_PROFILE(Trans2_findnotifynext);
8647 call_trans2findnotifynext(conn, req,
8648 &state->param, state->total_param,
8649 &state->data, state->total_data,
8650 state->max_data_return);
8651 END_PROFILE(Trans2_findnotifynext);
8652 break;
8655 case TRANSACT2_MKDIR:
8657 START_PROFILE(Trans2_mkdir);
8658 call_trans2mkdir(conn, req,
8659 &state->param, state->total_param,
8660 &state->data, state->total_data,
8661 state->max_data_return);
8662 END_PROFILE(Trans2_mkdir);
8663 break;
8666 case TRANSACT2_GET_DFS_REFERRAL:
8668 START_PROFILE(Trans2_get_dfs_referral);
8669 call_trans2getdfsreferral(conn, req,
8670 &state->param, state->total_param,
8671 &state->data, state->total_data,
8672 state->max_data_return);
8673 END_PROFILE(Trans2_get_dfs_referral);
8674 break;
8677 case TRANSACT2_IOCTL:
8679 START_PROFILE(Trans2_ioctl);
8680 call_trans2ioctl(conn, req,
8681 &state->param, state->total_param,
8682 &state->data, state->total_data,
8683 state->max_data_return);
8684 END_PROFILE(Trans2_ioctl);
8685 break;
8688 default:
8689 /* Error in request */
8690 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8691 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8695 /****************************************************************************
8696 Reply to a SMBtrans2.
8697 ****************************************************************************/
8699 void reply_trans2(struct smb_request *req)
8701 connection_struct *conn = req->conn;
8702 unsigned int dsoff;
8703 unsigned int dscnt;
8704 unsigned int psoff;
8705 unsigned int pscnt;
8706 unsigned int tran_call;
8707 struct trans_state *state;
8708 NTSTATUS result;
8710 START_PROFILE(SMBtrans2);
8712 if (req->wct < 14) {
8713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8714 END_PROFILE(SMBtrans2);
8715 return;
8718 dsoff = SVAL(req->vwv+12, 0);
8719 dscnt = SVAL(req->vwv+11, 0);
8720 psoff = SVAL(req->vwv+10, 0);
8721 pscnt = SVAL(req->vwv+9, 0);
8722 tran_call = SVAL(req->vwv+14, 0);
8724 result = allow_new_trans(conn->pending_trans, req->mid);
8725 if (!NT_STATUS_IS_OK(result)) {
8726 DEBUG(2, ("Got invalid trans2 request: %s\n",
8727 nt_errstr(result)));
8728 reply_nterror(req, result);
8729 END_PROFILE(SMBtrans2);
8730 return;
8733 if (IS_IPC(conn)) {
8734 switch (tran_call) {
8735 /* List the allowed trans2 calls on IPC$ */
8736 case TRANSACT2_OPEN:
8737 case TRANSACT2_GET_DFS_REFERRAL:
8738 case TRANSACT2_QFILEINFO:
8739 case TRANSACT2_QFSINFO:
8740 case TRANSACT2_SETFSINFO:
8741 break;
8742 default:
8743 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8744 END_PROFILE(SMBtrans2);
8745 return;
8749 if ((state = talloc(conn, struct trans_state)) == NULL) {
8750 DEBUG(0, ("talloc failed\n"));
8751 reply_nterror(req, NT_STATUS_NO_MEMORY);
8752 END_PROFILE(SMBtrans2);
8753 return;
8756 state->cmd = SMBtrans2;
8758 state->mid = req->mid;
8759 state->vuid = req->vuid;
8760 state->setup_count = SVAL(req->vwv+13, 0);
8761 state->setup = NULL;
8762 state->total_param = SVAL(req->vwv+0, 0);
8763 state->param = NULL;
8764 state->total_data = SVAL(req->vwv+1, 0);
8765 state->data = NULL;
8766 state->max_param_return = SVAL(req->vwv+2, 0);
8767 state->max_data_return = SVAL(req->vwv+3, 0);
8768 state->max_setup_return = SVAL(req->vwv+4, 0);
8769 state->close_on_completion = BITSETW(req->vwv+5, 0);
8770 state->one_way = BITSETW(req->vwv+5, 1);
8772 state->call = tran_call;
8774 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8775 is so as a sanity check */
8776 if (state->setup_count != 1) {
8778 * Need to have rc=0 for ioctl to get job id for OS/2.
8779 * Network printing will fail if function is not successful.
8780 * Similar function in reply.c will be used if protocol
8781 * is LANMAN1.0 instead of LM1.2X002.
8782 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8783 * outbuf doesn't have to be set(only job id is used).
8785 if ( (state->setup_count == 4)
8786 && (tran_call == TRANSACT2_IOCTL)
8787 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8788 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8789 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8790 } else {
8791 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8792 DEBUG(2,("Transaction is %d\n",tran_call));
8793 TALLOC_FREE(state);
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 END_PROFILE(SMBtrans2);
8796 return;
8800 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8801 goto bad_param;
8803 if (state->total_data) {
8805 if (trans_oob(state->total_data, 0, dscnt)
8806 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8807 goto bad_param;
8810 /* Can't use talloc here, the core routines do realloc on the
8811 * params and data. */
8812 state->data = (char *)SMB_MALLOC(state->total_data);
8813 if (state->data == NULL) {
8814 DEBUG(0,("reply_trans2: data malloc fail for %u "
8815 "bytes !\n", (unsigned int)state->total_data));
8816 TALLOC_FREE(state);
8817 reply_nterror(req, NT_STATUS_NO_MEMORY);
8818 END_PROFILE(SMBtrans2);
8819 return;
8822 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8825 if (state->total_param) {
8827 if (trans_oob(state->total_param, 0, pscnt)
8828 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8829 goto bad_param;
8832 /* Can't use talloc here, the core routines do realloc on the
8833 * params and data. */
8834 state->param = (char *)SMB_MALLOC(state->total_param);
8835 if (state->param == NULL) {
8836 DEBUG(0,("reply_trans: param malloc fail for %u "
8837 "bytes !\n", (unsigned int)state->total_param));
8838 SAFE_FREE(state->data);
8839 TALLOC_FREE(state);
8840 reply_nterror(req, NT_STATUS_NO_MEMORY);
8841 END_PROFILE(SMBtrans2);
8842 return;
8845 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8848 state->received_data = dscnt;
8849 state->received_param = pscnt;
8851 if ((state->received_param == state->total_param) &&
8852 (state->received_data == state->total_data)) {
8854 handle_trans2(conn, req, state);
8856 SAFE_FREE(state->data);
8857 SAFE_FREE(state->param);
8858 TALLOC_FREE(state);
8859 END_PROFILE(SMBtrans2);
8860 return;
8863 DLIST_ADD(conn->pending_trans, state);
8865 /* We need to send an interim response then receive the rest
8866 of the parameter/data bytes */
8867 reply_outbuf(req, 0, 0);
8868 show_msg((char *)req->outbuf);
8869 END_PROFILE(SMBtrans2);
8870 return;
8872 bad_param:
8874 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8875 SAFE_FREE(state->data);
8876 SAFE_FREE(state->param);
8877 TALLOC_FREE(state);
8878 END_PROFILE(SMBtrans2);
8879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8883 /****************************************************************************
8884 Reply to a SMBtranss2
8885 ****************************************************************************/
8887 void reply_transs2(struct smb_request *req)
8889 connection_struct *conn = req->conn;
8890 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8891 struct trans_state *state;
8893 START_PROFILE(SMBtranss2);
8895 show_msg((const char *)req->inbuf);
8897 if (req->wct < 8) {
8898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8899 END_PROFILE(SMBtranss2);
8900 return;
8903 for (state = conn->pending_trans; state != NULL;
8904 state = state->next) {
8905 if (state->mid == req->mid) {
8906 break;
8910 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8912 END_PROFILE(SMBtranss2);
8913 return;
8916 /* Revise state->total_param and state->total_data in case they have
8917 changed downwards */
8919 if (SVAL(req->vwv+0, 0) < state->total_param)
8920 state->total_param = SVAL(req->vwv+0, 0);
8921 if (SVAL(req->vwv+1, 0) < state->total_data)
8922 state->total_data = SVAL(req->vwv+1, 0);
8924 pcnt = SVAL(req->vwv+2, 0);
8925 poff = SVAL(req->vwv+3, 0);
8926 pdisp = SVAL(req->vwv+4, 0);
8928 dcnt = SVAL(req->vwv+5, 0);
8929 doff = SVAL(req->vwv+6, 0);
8930 ddisp = SVAL(req->vwv+7, 0);
8932 state->received_param += pcnt;
8933 state->received_data += dcnt;
8935 if ((state->received_data > state->total_data) ||
8936 (state->received_param > state->total_param))
8937 goto bad_param;
8939 if (pcnt) {
8940 if (trans_oob(state->total_param, pdisp, pcnt)
8941 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8942 goto bad_param;
8944 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8947 if (dcnt) {
8948 if (trans_oob(state->total_data, ddisp, dcnt)
8949 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8950 goto bad_param;
8952 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8955 if ((state->received_param < state->total_param) ||
8956 (state->received_data < state->total_data)) {
8957 END_PROFILE(SMBtranss2);
8958 return;
8961 handle_trans2(conn, req, state);
8963 DLIST_REMOVE(conn->pending_trans, state);
8964 SAFE_FREE(state->data);
8965 SAFE_FREE(state->param);
8966 TALLOC_FREE(state);
8968 END_PROFILE(SMBtranss2);
8969 return;
8971 bad_param:
8973 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8974 DLIST_REMOVE(conn->pending_trans, state);
8975 SAFE_FREE(state->data);
8976 SAFE_FREE(state->param);
8977 TALLOC_FREE(state);
8978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8979 END_PROFILE(SMBtranss2);
8980 return;