s3: Put an indirection layer into share_mode_lock
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobba6bcbbb9e288cfac6f3684844bd0f09b4bcae29
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 time_t c_date = (time_t)0;
1543 char *nameptr;
1544 char *last_entry_ptr;
1545 bool was_8_3;
1546 int off;
1547 int pad = 0;
1549 *out_of_space = false;
1551 ZERO_STRUCT(mdate_ts);
1552 ZERO_STRUCT(adate_ts);
1553 ZERO_STRUCT(create_date_ts);
1554 ZERO_STRUCT(cdate_ts);
1556 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1557 file_size = get_file_size_stat(&smb_fname->st);
1559 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1561 file_index = get_FileIndex(conn, &smb_fname->st);
1563 mdate_ts = smb_fname->st.st_ex_mtime;
1564 adate_ts = smb_fname->st.st_ex_atime;
1565 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1566 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1568 if (lp_dos_filetime_resolution(SNUM(conn))) {
1569 dos_filetime_timespec(&create_date_ts);
1570 dos_filetime_timespec(&mdate_ts);
1571 dos_filetime_timespec(&adate_ts);
1572 dos_filetime_timespec(&cdate_ts);
1575 create_date = convert_timespec_to_time_t(create_date_ts);
1576 mdate = convert_timespec_to_time_t(mdate_ts);
1577 adate = convert_timespec_to_time_t(adate_ts);
1578 c_date = convert_timespec_to_time_t(cdate_ts);
1580 /* align the record */
1581 SMB_ASSERT(align >= 1);
1583 off = (int)PTR_DIFF(pdata, base_data);
1584 pad = (off + (align-1)) & ~(align-1);
1585 pad -= off;
1587 if (pad && pad > space_remaining) {
1588 *out_of_space = true;
1589 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1590 "for padding (wanted %u, had %d)\n",
1591 (unsigned int)pad,
1592 space_remaining ));
1593 return false; /* Not finished - just out of space */
1596 off += pad;
1597 /* initialize padding to 0 */
1598 if (pad) {
1599 memset(pdata, 0, pad);
1601 space_remaining -= pad;
1603 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1604 space_remaining ));
1606 pdata += pad;
1607 p = pdata;
1608 last_entry_ptr = p;
1610 pad = 0;
1611 off = 0;
1613 switch (info_level) {
1614 case SMB_FIND_INFO_STANDARD:
1615 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1616 if(requires_resume_key) {
1617 SIVAL(p,0,reskey);
1618 p += 4;
1620 srv_put_dos_date2(p,0,create_date);
1621 srv_put_dos_date2(p,4,adate);
1622 srv_put_dos_date2(p,8,mdate);
1623 SIVAL(p,12,(uint32)file_size);
1624 SIVAL(p,16,(uint32)allocation_size);
1625 SSVAL(p,20,mode);
1626 p += 23;
1627 nameptr = p;
1628 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1629 p += ucs2_align(base_data, p, 0);
1631 len = srvstr_push(base_data, flags2, p,
1632 fname, PTR_DIFF(end_data, p),
1633 STR_TERMINATE);
1634 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1635 if (len > 2) {
1636 SCVAL(nameptr, -1, len - 2);
1637 } else {
1638 SCVAL(nameptr, -1, 0);
1640 } else {
1641 if (len > 1) {
1642 SCVAL(nameptr, -1, len - 1);
1643 } else {
1644 SCVAL(nameptr, -1, 0);
1647 p += len;
1648 break;
1650 case SMB_FIND_EA_SIZE:
1651 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1652 if (requires_resume_key) {
1653 SIVAL(p,0,reskey);
1654 p += 4;
1656 srv_put_dos_date2(p,0,create_date);
1657 srv_put_dos_date2(p,4,adate);
1658 srv_put_dos_date2(p,8,mdate);
1659 SIVAL(p,12,(uint32)file_size);
1660 SIVAL(p,16,(uint32)allocation_size);
1661 SSVAL(p,20,mode);
1663 unsigned int ea_size = estimate_ea_size(conn, NULL,
1664 smb_fname->base_name);
1665 SIVAL(p,22,ea_size); /* Extended attributes */
1667 p += 27;
1668 nameptr = p - 1;
1669 len = srvstr_push(base_data, flags2,
1670 p, fname, PTR_DIFF(end_data, p),
1671 STR_TERMINATE | STR_NOALIGN);
1672 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1673 if (len > 2) {
1674 len -= 2;
1675 } else {
1676 len = 0;
1678 } else {
1679 if (len > 1) {
1680 len -= 1;
1681 } else {
1682 len = 0;
1685 SCVAL(nameptr,0,len);
1686 p += len;
1687 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1688 break;
1690 case SMB_FIND_EA_LIST:
1692 struct ea_list *file_list = NULL;
1693 size_t ea_len = 0;
1695 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1696 if (!name_list) {
1697 return false;
1699 if (requires_resume_key) {
1700 SIVAL(p,0,reskey);
1701 p += 4;
1703 srv_put_dos_date2(p,0,create_date);
1704 srv_put_dos_date2(p,4,adate);
1705 srv_put_dos_date2(p,8,mdate);
1706 SIVAL(p,12,(uint32)file_size);
1707 SIVAL(p,16,(uint32)allocation_size);
1708 SSVAL(p,20,mode);
1709 p += 22; /* p now points to the EA area. */
1711 file_list = get_ea_list_from_file(ctx, conn, NULL,
1712 smb_fname->base_name,
1713 &ea_len);
1714 name_list = ea_list_union(name_list, file_list, &ea_len);
1716 /* We need to determine if this entry will fit in the space available. */
1717 /* Max string size is 255 bytes. */
1718 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1719 *out_of_space = true;
1720 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1721 "(wanted %u, had %d)\n",
1722 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1723 space_remaining ));
1724 return False; /* Not finished - just out of space */
1727 /* Push the ea_data followed by the name. */
1728 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1729 nameptr = p;
1730 len = srvstr_push(base_data, flags2,
1731 p + 1, fname, PTR_DIFF(end_data, p+1),
1732 STR_TERMINATE | STR_NOALIGN);
1733 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1734 if (len > 2) {
1735 len -= 2;
1736 } else {
1737 len = 0;
1739 } else {
1740 if (len > 1) {
1741 len -= 1;
1742 } else {
1743 len = 0;
1746 SCVAL(nameptr,0,len);
1747 p += len + 1;
1748 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1749 break;
1752 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1760 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,mode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length. */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL,
1767 smb_fname->base_name);
1768 SIVAL(p,0,ea_size); /* Extended attributes */
1769 p += 4;
1771 /* Clear the short name buffer. This is
1772 * IMPORTANT as not doing so will trigger
1773 * a Win2k client bug. JRA.
1775 if (!was_8_3 && check_mangled_names) {
1776 char mangled_name[13]; /* mangled 8.3 name. */
1777 if (!name_to_8_3(fname,mangled_name,True,
1778 conn->params)) {
1779 /* Error - mangle failed ! */
1780 memset(mangled_name,'\0',12);
1782 mangled_name[12] = 0;
1783 len = srvstr_push(base_data, flags2,
1784 p+2, mangled_name, 24,
1785 STR_UPPER|STR_UNICODE);
1786 if (len < 24) {
1787 memset(p + 2 + len,'\0',24 - len);
1789 SSVAL(p, 0, len);
1790 } else {
1791 memset(p,'\0',26);
1793 p += 2 + 24;
1794 len = srvstr_push(base_data, flags2, p,
1795 fname, PTR_DIFF(end_data, p),
1796 STR_TERMINATE_ASCII);
1797 SIVAL(q,0,len);
1798 p += len;
1800 len = PTR_DIFF(p, pdata);
1801 pad = (len + (align-1)) & ~(align-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1807 SIVAL(pdata,0,pad);
1809 * set padding to zero
1811 if (do_pad) {
1812 memset(p, 0, pad - len);
1813 p = pdata + pad;
1814 } else {
1815 p = pdata + len;
1817 break;
1819 case SMB_FIND_FILE_DIRECTORY_INFO:
1820 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1821 p += 4;
1822 SIVAL(p,0,reskey); p += 4;
1823 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1827 SOFF_T(p,0,file_size); p += 8;
1828 SOFF_T(p,0,allocation_size); p += 8;
1829 SIVAL(p,0,mode); p += 4;
1830 len = srvstr_push(base_data, flags2,
1831 p + 4, fname, PTR_DIFF(end_data, p+4),
1832 STR_TERMINATE_ASCII);
1833 SIVAL(p,0,len);
1834 p += 4 + len;
1836 len = PTR_DIFF(p, pdata);
1837 pad = (len + (align-1)) & ~(align-1);
1839 * offset to the next entry, the caller
1840 * will overwrite it for the last entry
1841 * that's why we always include the padding
1843 SIVAL(pdata,0,pad);
1845 * set padding to zero
1847 if (do_pad) {
1848 memset(p, 0, pad - len);
1849 p = pdata + pad;
1850 } else {
1851 p = pdata + len;
1853 break;
1855 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1856 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1857 p += 4;
1858 SIVAL(p,0,reskey); p += 4;
1859 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1863 SOFF_T(p,0,file_size); p += 8;
1864 SOFF_T(p,0,allocation_size); p += 8;
1865 SIVAL(p,0,mode); p += 4;
1866 q = p; p += 4; /* q is placeholder for name length. */
1868 unsigned int ea_size = estimate_ea_size(conn, NULL,
1869 smb_fname->base_name);
1870 SIVAL(p,0,ea_size); /* Extended attributes */
1871 p +=4;
1873 len = srvstr_push(base_data, flags2, p,
1874 fname, PTR_DIFF(end_data, p),
1875 STR_TERMINATE_ASCII);
1876 SIVAL(q, 0, len);
1877 p += len;
1879 len = PTR_DIFF(p, pdata);
1880 pad = (len + (align-1)) & ~(align-1);
1882 * offset to the next entry, the caller
1883 * will overwrite it for the last entry
1884 * that's why we always include the padding
1886 SIVAL(pdata,0,pad);
1888 * set padding to zero
1890 if (do_pad) {
1891 memset(p, 0, pad - len);
1892 p = pdata + pad;
1893 } else {
1894 p = pdata + len;
1896 break;
1898 case SMB_FIND_FILE_NAMES_INFO:
1899 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1900 p += 4;
1901 SIVAL(p,0,reskey); p += 4;
1902 p += 4;
1903 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1904 acl on a dir (tridge) */
1905 len = srvstr_push(base_data, flags2, p,
1906 fname, PTR_DIFF(end_data, p),
1907 STR_TERMINATE_ASCII);
1908 SIVAL(p, -4, len);
1909 p += len;
1911 len = PTR_DIFF(p, pdata);
1912 pad = (len + (align-1)) & ~(align-1);
1914 * offset to the next entry, the caller
1915 * will overwrite it for the last entry
1916 * that's why we always include the padding
1918 SIVAL(pdata,0,pad);
1920 * set padding to zero
1922 if (do_pad) {
1923 memset(p, 0, pad - len);
1924 p = pdata + pad;
1925 } else {
1926 p = pdata + len;
1928 break;
1930 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1931 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1932 p += 4;
1933 SIVAL(p,0,reskey); p += 4;
1934 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1937 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1938 SOFF_T(p,0,file_size); p += 8;
1939 SOFF_T(p,0,allocation_size); p += 8;
1940 SIVAL(p,0,mode); p += 4;
1941 q = p; p += 4; /* q is placeholder for name length. */
1943 unsigned int ea_size = estimate_ea_size(conn, NULL,
1944 smb_fname->base_name);
1945 SIVAL(p,0,ea_size); /* Extended attributes */
1946 p +=4;
1948 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1949 SBVAL(p,0,file_index); p += 8;
1950 len = srvstr_push(base_data, flags2, p,
1951 fname, PTR_DIFF(end_data, p),
1952 STR_TERMINATE_ASCII);
1953 SIVAL(q, 0, len);
1954 p += len;
1956 len = PTR_DIFF(p, pdata);
1957 pad = (len + (align-1)) & ~(align-1);
1959 * offset to the next entry, the caller
1960 * will overwrite it for the last entry
1961 * that's why we always include the padding
1963 SIVAL(pdata,0,pad);
1965 * set padding to zero
1967 if (do_pad) {
1968 memset(p, 0, pad - len);
1969 p = pdata + pad;
1970 } else {
1971 p = pdata + len;
1973 break;
1975 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1976 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1977 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1978 p += 4;
1979 SIVAL(p,0,reskey); p += 4;
1980 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1982 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1983 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1984 SOFF_T(p,0,file_size); p += 8;
1985 SOFF_T(p,0,allocation_size); p += 8;
1986 SIVAL(p,0,mode); p += 4;
1987 q = p; p += 4; /* q is placeholder for name length */
1989 unsigned int ea_size = estimate_ea_size(conn, NULL,
1990 smb_fname->base_name);
1991 SIVAL(p,0,ea_size); /* Extended attributes */
1992 p +=4;
1994 /* Clear the short name buffer. This is
1995 * IMPORTANT as not doing so will trigger
1996 * a Win2k client bug. JRA.
1998 if (!was_8_3 && check_mangled_names) {
1999 char mangled_name[13]; /* mangled 8.3 name. */
2000 if (!name_to_8_3(fname,mangled_name,True,
2001 conn->params)) {
2002 /* Error - mangle failed ! */
2003 memset(mangled_name,'\0',12);
2005 mangled_name[12] = 0;
2006 len = srvstr_push(base_data, flags2,
2007 p+2, mangled_name, 24,
2008 STR_UPPER|STR_UNICODE);
2009 SSVAL(p, 0, len);
2010 if (len < 24) {
2011 memset(p + 2 + len,'\0',24 - len);
2013 SSVAL(p, 0, len);
2014 } else {
2015 memset(p,'\0',26);
2017 p += 26;
2018 SSVAL(p,0,0); p += 2; /* Reserved ? */
2019 SBVAL(p,0,file_index); p += 8;
2020 len = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2022 STR_TERMINATE_ASCII);
2023 SIVAL(q,0,len);
2024 p += len;
2026 len = PTR_DIFF(p, pdata);
2027 pad = (len + (align-1)) & ~(align-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2033 SIVAL(pdata,0,pad);
2035 * set padding to zero
2037 if (do_pad) {
2038 memset(p, 0, pad - len);
2039 p = pdata + pad;
2040 } else {
2041 p = pdata + len;
2043 break;
2045 /* CIFS UNIX Extension. */
2047 case SMB_FIND_FILE_UNIX:
2048 case SMB_FIND_FILE_UNIX_INFO2:
2049 p+= 4;
2050 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2052 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2054 if (info_level == SMB_FIND_FILE_UNIX) {
2055 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2056 p = store_file_unix_basic(conn, p,
2057 NULL, &smb_fname->st);
2058 len = srvstr_push(base_data, flags2, p,
2059 fname, PTR_DIFF(end_data, p),
2060 STR_TERMINATE);
2061 } else {
2062 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2063 p = store_file_unix_basic_info2(conn, p,
2064 NULL, &smb_fname->st);
2065 nameptr = p;
2066 p += 4;
2067 len = srvstr_push(base_data, flags2, p, fname,
2068 PTR_DIFF(end_data, p), 0);
2069 SIVAL(nameptr, 0, len);
2072 p += len;
2074 len = PTR_DIFF(p, pdata);
2075 pad = (len + (align-1)) & ~(align-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2081 SIVAL(pdata,0,pad);
2083 * set padding to zero
2085 if (do_pad) {
2086 memset(p, 0, pad - len);
2087 p = pdata + pad;
2088 } else {
2089 p = pdata + len;
2091 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2093 break;
2095 default:
2096 return false;
2099 if (PTR_DIFF(p,pdata) > space_remaining) {
2100 *out_of_space = true;
2101 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2102 "(wanted %u, had %d)\n",
2103 (unsigned int)PTR_DIFF(p,pdata),
2104 space_remaining ));
2105 return false; /* Not finished - just out of space */
2108 /* Setup the last entry pointer, as an offset from base_data */
2109 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2110 /* Advance the data pointer to the next slot */
2111 *ppdata = p;
2113 return true;
2116 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2117 connection_struct *conn,
2118 struct dptr_struct *dirptr,
2119 uint16 flags2,
2120 const char *path_mask,
2121 uint32 dirtype,
2122 int info_level,
2123 int requires_resume_key,
2124 bool dont_descend,
2125 bool ask_sharemode,
2126 uint8_t align,
2127 bool do_pad,
2128 char **ppdata,
2129 char *base_data,
2130 char *end_data,
2131 int space_remaining,
2132 bool *out_of_space,
2133 bool *got_exact_match,
2134 int *_last_entry_off,
2135 struct ea_list *name_list)
2137 const char *p;
2138 const char *mask = NULL;
2139 long prev_dirpos = 0;
2140 uint32_t mode = 0;
2141 char *fname = NULL;
2142 struct smb_filename *smb_fname = NULL;
2143 struct smbd_dirptr_lanman2_state state;
2144 bool ok;
2145 uint64_t last_entry_off = 0;
2147 ZERO_STRUCT(state);
2148 state.conn = conn;
2149 state.info_level = info_level;
2150 state.check_mangled_names = lp_manglednames(conn->params);
2151 state.has_wild = dptr_has_wild(dirptr);
2152 state.got_exact_match = false;
2154 *out_of_space = false;
2155 *got_exact_match = false;
2157 p = strrchr_m(path_mask,'/');
2158 if(p != NULL) {
2159 if(p[1] == '\0') {
2160 mask = "*.*";
2161 } else {
2162 mask = p+1;
2164 } else {
2165 mask = path_mask;
2168 ok = smbd_dirptr_get_entry(ctx,
2169 dirptr,
2170 mask,
2171 dirtype,
2172 dont_descend,
2173 ask_sharemode,
2174 smbd_dirptr_lanman2_match_fn,
2175 smbd_dirptr_lanman2_mode_fn,
2176 &state,
2177 &fname,
2178 &smb_fname,
2179 &mode,
2180 &prev_dirpos);
2181 if (!ok) {
2182 return false;
2185 *got_exact_match = state.got_exact_match;
2187 ok = smbd_marshall_dir_entry(ctx,
2188 conn,
2189 flags2,
2190 info_level,
2191 name_list,
2192 state.check_mangled_names,
2193 requires_resume_key,
2194 mode,
2195 fname,
2196 smb_fname,
2197 space_remaining,
2198 align,
2199 do_pad,
2200 base_data,
2201 ppdata,
2202 end_data,
2203 out_of_space,
2204 &last_entry_off);
2205 TALLOC_FREE(fname);
2206 TALLOC_FREE(smb_fname);
2207 if (*out_of_space) {
2208 dptr_SeekDir(dirptr, prev_dirpos);
2209 return false;
2211 if (!ok) {
2212 return false;
2215 *_last_entry_off = last_entry_off;
2216 return true;
2219 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2220 connection_struct *conn,
2221 struct dptr_struct *dirptr,
2222 uint16 flags2,
2223 const char *path_mask,
2224 uint32 dirtype,
2225 int info_level,
2226 bool requires_resume_key,
2227 bool dont_descend,
2228 bool ask_sharemode,
2229 char **ppdata,
2230 char *base_data,
2231 char *end_data,
2232 int space_remaining,
2233 bool *out_of_space,
2234 bool *got_exact_match,
2235 int *last_entry_off,
2236 struct ea_list *name_list)
2238 uint8_t align = 4;
2239 const bool do_pad = true;
2241 if (info_level >= 1 && info_level <= 3) {
2242 /* No alignment on earlier info levels. */
2243 align = 1;
2246 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2247 path_mask, dirtype, info_level,
2248 requires_resume_key, dont_descend, ask_sharemode,
2249 align, do_pad,
2250 ppdata, base_data, end_data,
2251 space_remaining,
2252 out_of_space, got_exact_match,
2253 last_entry_off, name_list);
2256 /****************************************************************************
2257 Reply to a TRANS2_FINDFIRST.
2258 ****************************************************************************/
2260 static void call_trans2findfirst(connection_struct *conn,
2261 struct smb_request *req,
2262 char **pparams, int total_params,
2263 char **ppdata, int total_data,
2264 unsigned int max_data_bytes)
2266 /* We must be careful here that we don't return more than the
2267 allowed number of data bytes. If this means returning fewer than
2268 maxentries then so be it. We assume that the redirector has
2269 enough room for the fixed number of parameter bytes it has
2270 requested. */
2271 struct smb_filename *smb_dname = NULL;
2272 char *params = *pparams;
2273 char *pdata = *ppdata;
2274 char *data_end;
2275 uint32 dirtype;
2276 int maxentries;
2277 uint16 findfirst_flags;
2278 bool close_after_first;
2279 bool close_if_end;
2280 bool requires_resume_key;
2281 int info_level;
2282 char *directory = NULL;
2283 char *mask = NULL;
2284 char *p;
2285 int last_entry_off=0;
2286 int dptr_num = -1;
2287 int numentries = 0;
2288 int i;
2289 bool finished = False;
2290 bool dont_descend = False;
2291 bool out_of_space = False;
2292 int space_remaining;
2293 bool mask_contains_wcard = False;
2294 struct ea_list *ea_list = NULL;
2295 NTSTATUS ntstatus = NT_STATUS_OK;
2296 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2297 TALLOC_CTX *ctx = talloc_tos();
2298 struct dptr_struct *dirptr = NULL;
2299 struct smbd_server_connection *sconn = req->sconn;
2300 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2302 if (total_params < 13) {
2303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2304 goto out;
2307 dirtype = SVAL(params,0);
2308 maxentries = SVAL(params,2);
2309 findfirst_flags = SVAL(params,4);
2310 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2311 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2312 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2313 info_level = SVAL(params,6);
2315 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2316 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2317 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2318 info_level, max_data_bytes));
2320 if (!maxentries) {
2321 /* W2K3 seems to treat zero as 1. */
2322 maxentries = 1;
2325 switch (info_level) {
2326 case SMB_FIND_INFO_STANDARD:
2327 case SMB_FIND_EA_SIZE:
2328 case SMB_FIND_EA_LIST:
2329 case SMB_FIND_FILE_DIRECTORY_INFO:
2330 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2331 case SMB_FIND_FILE_NAMES_INFO:
2332 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2333 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2334 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2335 break;
2336 case SMB_FIND_FILE_UNIX:
2337 case SMB_FIND_FILE_UNIX_INFO2:
2338 /* Always use filesystem for UNIX mtime query. */
2339 ask_sharemode = false;
2340 if (!lp_unix_extensions()) {
2341 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2342 goto out;
2344 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2345 break;
2346 default:
2347 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2348 goto out;
2351 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2352 params+12, total_params - 12,
2353 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2354 if (!NT_STATUS_IS_OK(ntstatus)) {
2355 reply_nterror(req, ntstatus);
2356 goto out;
2359 ntstatus = filename_convert(ctx, conn,
2360 req->flags2 & FLAGS2_DFS_PATHNAMES,
2361 directory,
2362 ucf_flags,
2363 &mask_contains_wcard,
2364 &smb_dname);
2365 if (!NT_STATUS_IS_OK(ntstatus)) {
2366 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2367 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2368 ERRSRV, ERRbadpath);
2369 goto out;
2371 reply_nterror(req, ntstatus);
2372 goto out;
2375 mask = smb_dname->original_lcomp;
2377 directory = smb_dname->base_name;
2379 p = strrchr_m(directory,'/');
2380 if(p == NULL) {
2381 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2382 if((directory[0] == '.') && (directory[1] == '\0')) {
2383 mask = talloc_strdup(ctx,"*");
2384 if (!mask) {
2385 reply_nterror(req, NT_STATUS_NO_MEMORY);
2386 goto out;
2388 mask_contains_wcard = True;
2390 } else {
2391 *p = 0;
2394 if (p == NULL || p == directory) {
2395 /* Ensure we don't have a directory name of "". */
2396 directory = talloc_strdup(talloc_tos(), ".");
2397 if (!directory) {
2398 reply_nterror(req, NT_STATUS_NO_MEMORY);
2399 goto out;
2403 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2405 if (info_level == SMB_FIND_EA_LIST) {
2406 uint32 ea_size;
2408 if (total_data < 4) {
2409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2410 goto out;
2413 ea_size = IVAL(pdata,0);
2414 if (ea_size != total_data) {
2415 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2416 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2418 goto out;
2421 if (!lp_ea_support(SNUM(conn))) {
2422 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2423 goto out;
2426 /* Pull out the list of names. */
2427 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2428 if (!ea_list) {
2429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2430 goto out;
2434 *ppdata = (char *)SMB_REALLOC(
2435 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2436 if(*ppdata == NULL ) {
2437 reply_nterror(req, NT_STATUS_NO_MEMORY);
2438 goto out;
2440 pdata = *ppdata;
2441 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2443 /* Realloc the params space */
2444 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2445 if (*pparams == NULL) {
2446 reply_nterror(req, NT_STATUS_NO_MEMORY);
2447 goto out;
2449 params = *pparams;
2451 /* Save the wildcard match and attribs we are using on this directory -
2452 needed as lanman2 assumes these are being saved between calls */
2454 ntstatus = dptr_create(conn,
2455 NULL, /* fsp */
2456 directory,
2457 False,
2458 True,
2459 req->smbpid,
2460 mask,
2461 mask_contains_wcard,
2462 dirtype,
2463 &dirptr);
2465 if (!NT_STATUS_IS_OK(ntstatus)) {
2466 reply_nterror(req, ntstatus);
2467 goto out;
2470 dptr_num = dptr_dnum(dirptr);
2471 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2473 /* Initialize per TRANS2_FIND_FIRST operation data */
2474 dptr_init_search_op(dirptr);
2476 /* We don't need to check for VOL here as this is returned by
2477 a different TRANS2 call. */
2479 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2480 directory,lp_dontdescend(SNUM(conn))));
2481 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2482 dont_descend = True;
2484 p = pdata;
2485 space_remaining = max_data_bytes;
2486 out_of_space = False;
2488 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2489 bool got_exact_match = False;
2491 /* this is a heuristic to avoid seeking the dirptr except when
2492 absolutely necessary. It allows for a filename of about 40 chars */
2493 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2494 out_of_space = True;
2495 finished = False;
2496 } else {
2497 finished = !get_lanman2_dir_entry(ctx,
2498 conn,
2499 dirptr,
2500 req->flags2,
2501 mask,dirtype,info_level,
2502 requires_resume_key,dont_descend,
2503 ask_sharemode,
2504 &p,pdata,data_end,
2505 space_remaining, &out_of_space,
2506 &got_exact_match,
2507 &last_entry_off, ea_list);
2510 if (finished && out_of_space)
2511 finished = False;
2513 if (!finished && !out_of_space)
2514 numentries++;
2517 * As an optimisation if we know we aren't looking
2518 * for a wildcard name (ie. the name matches the wildcard exactly)
2519 * then we can finish on any (first) match.
2520 * This speeds up large directory searches. JRA.
2523 if(got_exact_match)
2524 finished = True;
2526 /* Ensure space_remaining never goes -ve. */
2527 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2528 space_remaining = 0;
2529 out_of_space = true;
2530 } else {
2531 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2535 /* Check if we can close the dirptr */
2536 if(close_after_first || (finished && close_if_end)) {
2537 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2538 dptr_close(sconn, &dptr_num);
2542 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2543 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2544 * the protocol level is less than NT1. Tested with smbclient. JRA.
2545 * This should fix the OS/2 client bug #2335.
2548 if(numentries == 0) {
2549 dptr_close(sconn, &dptr_num);
2550 if (get_Protocol() < PROTOCOL_NT1) {
2551 reply_force_doserror(req, ERRDOS, ERRnofiles);
2552 goto out;
2553 } else {
2554 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2555 ERRDOS, ERRbadfile);
2556 goto out;
2560 /* At this point pdata points to numentries directory entries. */
2562 /* Set up the return parameter block */
2563 SSVAL(params,0,dptr_num);
2564 SSVAL(params,2,numentries);
2565 SSVAL(params,4,finished);
2566 SSVAL(params,6,0); /* Never an EA error */
2567 SSVAL(params,8,last_entry_off);
2569 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2570 max_data_bytes);
2572 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2573 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2574 if (!directory) {
2575 reply_nterror(req, NT_STATUS_NO_MEMORY);
2579 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2580 smb_fn_name(req->cmd),
2581 mask, directory, dirtype, numentries ) );
2584 * Force a name mangle here to ensure that the
2585 * mask as an 8.3 name is top of the mangled cache.
2586 * The reasons for this are subtle. Don't remove
2587 * this code unless you know what you are doing
2588 * (see PR#13758). JRA.
2591 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2592 char mangled_name[13];
2593 name_to_8_3(mask, mangled_name, True, conn->params);
2595 out:
2596 TALLOC_FREE(smb_dname);
2597 return;
2600 /****************************************************************************
2601 Reply to a TRANS2_FINDNEXT.
2602 ****************************************************************************/
2604 static void call_trans2findnext(connection_struct *conn,
2605 struct smb_request *req,
2606 char **pparams, int total_params,
2607 char **ppdata, int total_data,
2608 unsigned int max_data_bytes)
2610 /* We must be careful here that we don't return more than the
2611 allowed number of data bytes. If this means returning fewer than
2612 maxentries then so be it. We assume that the redirector has
2613 enough room for the fixed number of parameter bytes it has
2614 requested. */
2615 char *params = *pparams;
2616 char *pdata = *ppdata;
2617 char *data_end;
2618 int dptr_num;
2619 int maxentries;
2620 uint16 info_level;
2621 uint32 resume_key;
2622 uint16 findnext_flags;
2623 bool close_after_request;
2624 bool close_if_end;
2625 bool requires_resume_key;
2626 bool continue_bit;
2627 bool mask_contains_wcard = False;
2628 char *resume_name = NULL;
2629 const char *mask = NULL;
2630 const char *directory = NULL;
2631 char *p = NULL;
2632 uint16 dirtype;
2633 int numentries = 0;
2634 int i, last_entry_off=0;
2635 bool finished = False;
2636 bool dont_descend = False;
2637 bool out_of_space = False;
2638 int space_remaining;
2639 struct ea_list *ea_list = NULL;
2640 NTSTATUS ntstatus = NT_STATUS_OK;
2641 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2642 TALLOC_CTX *ctx = talloc_tos();
2643 struct dptr_struct *dirptr;
2644 struct smbd_server_connection *sconn = req->sconn;
2646 if (total_params < 13) {
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 return;
2651 dptr_num = SVAL(params,0);
2652 maxentries = SVAL(params,2);
2653 info_level = SVAL(params,4);
2654 resume_key = IVAL(params,6);
2655 findnext_flags = SVAL(params,10);
2656 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2657 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2658 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2659 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2661 if (!continue_bit) {
2662 /* We only need resume_name if continue_bit is zero. */
2663 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2664 params+12,
2665 total_params - 12, STR_TERMINATE, &ntstatus,
2666 &mask_contains_wcard);
2667 if (!NT_STATUS_IS_OK(ntstatus)) {
2668 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2669 complain (it thinks we're asking for the directory above the shared
2670 path or an invalid name). Catch this as the resume name is only compared, never used in
2671 a file access. JRA. */
2672 srvstr_pull_talloc(ctx, params, req->flags2,
2673 &resume_name, params+12,
2674 total_params - 12,
2675 STR_TERMINATE);
2677 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2678 reply_nterror(req, ntstatus);
2679 return;
2684 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2685 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2686 resume_key = %d resume name = %s continue=%d level = %d\n",
2687 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2688 requires_resume_key, resume_key,
2689 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2691 if (!maxentries) {
2692 /* W2K3 seems to treat zero as 1. */
2693 maxentries = 1;
2696 switch (info_level) {
2697 case SMB_FIND_INFO_STANDARD:
2698 case SMB_FIND_EA_SIZE:
2699 case SMB_FIND_EA_LIST:
2700 case SMB_FIND_FILE_DIRECTORY_INFO:
2701 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2702 case SMB_FIND_FILE_NAMES_INFO:
2703 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2704 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2705 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2706 break;
2707 case SMB_FIND_FILE_UNIX:
2708 case SMB_FIND_FILE_UNIX_INFO2:
2709 /* Always use filesystem for UNIX mtime query. */
2710 ask_sharemode = false;
2711 if (!lp_unix_extensions()) {
2712 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2713 return;
2715 break;
2716 default:
2717 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2718 return;
2721 if (info_level == SMB_FIND_EA_LIST) {
2722 uint32 ea_size;
2724 if (total_data < 4) {
2725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2726 return;
2729 ea_size = IVAL(pdata,0);
2730 if (ea_size != total_data) {
2731 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2732 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2734 return;
2737 if (!lp_ea_support(SNUM(conn))) {
2738 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2739 return;
2742 /* Pull out the list of names. */
2743 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2744 if (!ea_list) {
2745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2746 return;
2750 *ppdata = (char *)SMB_REALLOC(
2751 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2752 if(*ppdata == NULL) {
2753 reply_nterror(req, NT_STATUS_NO_MEMORY);
2754 return;
2757 pdata = *ppdata;
2758 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2760 /* Realloc the params space */
2761 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2762 if(*pparams == NULL ) {
2763 reply_nterror(req, NT_STATUS_NO_MEMORY);
2764 return;
2767 params = *pparams;
2769 /* Check that the dptr is valid */
2770 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2771 reply_nterror(req, STATUS_NO_MORE_FILES);
2772 return;
2775 directory = dptr_path(sconn, dptr_num);
2777 /* Get the wildcard mask from the dptr */
2778 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2779 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2780 reply_nterror(req, STATUS_NO_MORE_FILES);
2781 return;
2784 mask = p;
2786 /* Get the attr mask from the dptr */
2787 dirtype = dptr_attr(sconn, dptr_num);
2789 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2790 dptr_num, mask, dirtype,
2791 (long)dirptr,
2792 dptr_TellDir(dirptr)));
2794 /* Initialize per TRANS2_FIND_NEXT operation data */
2795 dptr_init_search_op(dirptr);
2797 /* We don't need to check for VOL here as this is returned by
2798 a different TRANS2 call. */
2800 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2801 directory,lp_dontdescend(SNUM(conn))));
2802 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2803 dont_descend = True;
2805 p = pdata;
2806 space_remaining = max_data_bytes;
2807 out_of_space = False;
2810 * Seek to the correct position. We no longer use the resume key but
2811 * depend on the last file name instead.
2814 if(!continue_bit && resume_name && *resume_name) {
2815 SMB_STRUCT_STAT st;
2817 long current_pos = 0;
2819 * Remember, name_to_8_3 is called by
2820 * get_lanman2_dir_entry(), so the resume name
2821 * could be mangled. Ensure we check the unmangled name.
2824 if (mangle_is_mangled(resume_name, conn->params)) {
2825 char *new_resume_name = NULL;
2826 mangle_lookup_name_from_8_3(ctx,
2827 resume_name,
2828 &new_resume_name,
2829 conn->params);
2830 if (new_resume_name) {
2831 resume_name = new_resume_name;
2836 * Fix for NT redirector problem triggered by resume key indexes
2837 * changing between directory scans. We now return a resume key of 0
2838 * and instead look for the filename to continue from (also given
2839 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2840 * findfirst/findnext (as is usual) then the directory pointer
2841 * should already be at the correct place.
2844 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2845 } /* end if resume_name && !continue_bit */
2847 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2848 bool got_exact_match = False;
2850 /* this is a heuristic to avoid seeking the dirptr except when
2851 absolutely necessary. It allows for a filename of about 40 chars */
2852 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2853 out_of_space = True;
2854 finished = False;
2855 } else {
2856 finished = !get_lanman2_dir_entry(ctx,
2857 conn,
2858 dirptr,
2859 req->flags2,
2860 mask,dirtype,info_level,
2861 requires_resume_key,dont_descend,
2862 ask_sharemode,
2863 &p,pdata,data_end,
2864 space_remaining, &out_of_space,
2865 &got_exact_match,
2866 &last_entry_off, ea_list);
2869 if (finished && out_of_space)
2870 finished = False;
2872 if (!finished && !out_of_space)
2873 numentries++;
2876 * As an optimisation if we know we aren't looking
2877 * for a wildcard name (ie. the name matches the wildcard exactly)
2878 * then we can finish on any (first) match.
2879 * This speeds up large directory searches. JRA.
2882 if(got_exact_match)
2883 finished = True;
2885 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2888 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2889 smb_fn_name(req->cmd),
2890 mask, directory, dirtype, numentries ) );
2892 /* Check if we can close the dirptr */
2893 if(close_after_request || (finished && close_if_end)) {
2894 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2895 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2898 /* Set up the return parameter block */
2899 SSVAL(params,0,numentries);
2900 SSVAL(params,2,finished);
2901 SSVAL(params,4,0); /* Never an EA error */
2902 SSVAL(params,6,last_entry_off);
2904 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2905 max_data_bytes);
2907 return;
2910 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2912 E_md4hash(lp_servicename(SNUM(conn)),objid);
2913 return objid;
2916 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2918 SMB_ASSERT(extended_info != NULL);
2920 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2921 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2922 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2923 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2924 #ifdef SAMBA_VERSION_REVISION
2925 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2926 #endif
2927 extended_info->samba_subversion = 0;
2928 #ifdef SAMBA_VERSION_RC_RELEASE
2929 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2930 #else
2931 #ifdef SAMBA_VERSION_PRE_RELEASE
2932 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2933 #endif
2934 #endif
2935 #ifdef SAMBA_VERSION_VENDOR_PATCH
2936 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2937 #endif
2938 extended_info->samba_gitcommitdate = 0;
2939 #ifdef SAMBA_VERSION_COMMIT_TIME
2940 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2941 #endif
2943 memset(extended_info->samba_version_string, 0,
2944 sizeof(extended_info->samba_version_string));
2946 snprintf (extended_info->samba_version_string,
2947 sizeof(extended_info->samba_version_string),
2948 "%s", samba_version_string());
2951 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2952 TALLOC_CTX *mem_ctx,
2953 uint16_t info_level,
2954 uint16_t flags2,
2955 unsigned int max_data_bytes,
2956 char **ppdata,
2957 int *ret_data_len)
2959 char *pdata, *end_data;
2960 int data_len = 0, len;
2961 const char *vname = volume_label(SNUM(conn));
2962 int snum = SNUM(conn);
2963 char *fstype = lp_fstype(SNUM(conn));
2964 uint32 additional_flags = 0;
2965 struct smb_filename smb_fname_dot;
2966 SMB_STRUCT_STAT st;
2968 if (IS_IPC(conn)) {
2969 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2970 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2971 "info level (0x%x) on IPC$.\n",
2972 (unsigned int)info_level));
2973 return NT_STATUS_ACCESS_DENIED;
2977 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2979 ZERO_STRUCT(smb_fname_dot);
2980 smb_fname_dot.base_name = discard_const_p(char, ".");
2982 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2983 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2984 return map_nt_error_from_unix(errno);
2987 st = smb_fname_dot.st;
2989 *ppdata = (char *)SMB_REALLOC(
2990 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2991 if (*ppdata == NULL) {
2992 return NT_STATUS_NO_MEMORY;
2995 pdata = *ppdata;
2996 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2997 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2999 switch (info_level) {
3000 case SMB_INFO_ALLOCATION:
3002 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3003 data_len = 18;
3004 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3005 return map_nt_error_from_unix(errno);
3008 block_size = lp_block_size(snum);
3009 if (bsize < block_size) {
3010 uint64_t factor = block_size/bsize;
3011 bsize = block_size;
3012 dsize /= factor;
3013 dfree /= factor;
3015 if (bsize > block_size) {
3016 uint64_t factor = bsize/block_size;
3017 bsize = block_size;
3018 dsize *= factor;
3019 dfree *= factor;
3021 bytes_per_sector = 512;
3022 sectors_per_unit = bsize/bytes_per_sector;
3024 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3025 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3026 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3028 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3029 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3030 SIVAL(pdata,l1_cUnit,dsize);
3031 SIVAL(pdata,l1_cUnitAvail,dfree);
3032 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3033 break;
3036 case SMB_INFO_VOLUME:
3037 /* Return volume name */
3039 * Add volume serial number - hash of a combination of
3040 * the called hostname and the service name.
3042 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3044 * Win2k3 and previous mess this up by sending a name length
3045 * one byte short. I believe only older clients (OS/2 Win9x) use
3046 * this call so try fixing this by adding a terminating null to
3047 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3049 len = srvstr_push(
3050 pdata, flags2,
3051 pdata+l2_vol_szVolLabel, vname,
3052 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3053 STR_NOALIGN|STR_TERMINATE);
3054 SCVAL(pdata,l2_vol_cch,len);
3055 data_len = l2_vol_szVolLabel + len;
3056 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3057 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3058 len, vname));
3059 break;
3061 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3062 case SMB_FS_ATTRIBUTE_INFORMATION:
3064 additional_flags = 0;
3065 #if defined(HAVE_SYS_QUOTAS)
3066 additional_flags |= FILE_VOLUME_QUOTAS;
3067 #endif
3069 if(lp_nt_acl_support(SNUM(conn))) {
3070 additional_flags |= FILE_PERSISTENT_ACLS;
3073 /* Capabilities are filled in at connection time through STATVFS call */
3074 additional_flags |= conn->fs_capabilities;
3075 additional_flags |= lp_parm_int(conn->params->service,
3076 "share", "fake_fscaps",
3079 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3080 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3081 additional_flags); /* FS ATTRIBUTES */
3083 SIVAL(pdata,4,255); /* Max filename component length */
3084 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3085 and will think we can't do long filenames */
3086 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3087 PTR_DIFF(end_data, pdata+12),
3088 STR_UNICODE);
3089 SIVAL(pdata,8,len);
3090 data_len = 12 + len;
3091 break;
3093 case SMB_QUERY_FS_LABEL_INFO:
3094 case SMB_FS_LABEL_INFORMATION:
3095 len = srvstr_push(pdata, flags2, pdata+4, vname,
3096 PTR_DIFF(end_data, pdata+4), 0);
3097 data_len = 4 + len;
3098 SIVAL(pdata,0,len);
3099 break;
3101 case SMB_QUERY_FS_VOLUME_INFO:
3102 case SMB_FS_VOLUME_INFORMATION:
3105 * Add volume serial number - hash of a combination of
3106 * the called hostname and the service name.
3108 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3109 (str_checksum(get_local_machine_name())<<16));
3111 /* Max label len is 32 characters. */
3112 len = srvstr_push(pdata, flags2, pdata+18, vname,
3113 PTR_DIFF(end_data, pdata+18),
3114 STR_UNICODE);
3115 SIVAL(pdata,12,len);
3116 data_len = 18+len;
3118 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3119 (int)strlen(vname),vname, lp_servicename(snum)));
3120 break;
3122 case SMB_QUERY_FS_SIZE_INFO:
3123 case SMB_FS_SIZE_INFORMATION:
3125 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3126 data_len = 24;
3127 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3128 return map_nt_error_from_unix(errno);
3130 block_size = lp_block_size(snum);
3131 if (bsize < block_size) {
3132 uint64_t factor = block_size/bsize;
3133 bsize = block_size;
3134 dsize /= factor;
3135 dfree /= factor;
3137 if (bsize > block_size) {
3138 uint64_t factor = bsize/block_size;
3139 bsize = block_size;
3140 dsize *= factor;
3141 dfree *= factor;
3143 bytes_per_sector = 512;
3144 sectors_per_unit = bsize/bytes_per_sector;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3147 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3148 SBIG_UINT(pdata,0,dsize);
3149 SBIG_UINT(pdata,8,dfree);
3150 SIVAL(pdata,16,sectors_per_unit);
3151 SIVAL(pdata,20,bytes_per_sector);
3152 break;
3155 case SMB_FS_FULL_SIZE_INFORMATION:
3157 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3158 data_len = 32;
3159 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3160 return map_nt_error_from_unix(errno);
3162 block_size = lp_block_size(snum);
3163 if (bsize < block_size) {
3164 uint64_t factor = block_size/bsize;
3165 bsize = block_size;
3166 dsize /= factor;
3167 dfree /= factor;
3169 if (bsize > block_size) {
3170 uint64_t factor = bsize/block_size;
3171 bsize = block_size;
3172 dsize *= factor;
3173 dfree *= factor;
3175 bytes_per_sector = 512;
3176 sectors_per_unit = bsize/bytes_per_sector;
3177 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3178 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3179 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3180 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3181 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3182 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3183 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3184 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3185 break;
3188 case SMB_QUERY_FS_DEVICE_INFO:
3189 case SMB_FS_DEVICE_INFORMATION:
3191 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3193 if (!CAN_WRITE(conn)) {
3194 characteristics |= FILE_READ_ONLY_DEVICE;
3196 data_len = 8;
3197 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3198 SIVAL(pdata,4,characteristics);
3199 break;
3202 #ifdef HAVE_SYS_QUOTAS
3203 case SMB_FS_QUOTA_INFORMATION:
3205 * what we have to send --metze:
3207 * Unknown1: 24 NULL bytes
3208 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3209 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3210 * Quota Flags: 2 byte :
3211 * Unknown3: 6 NULL bytes
3213 * 48 bytes total
3215 * details for Quota Flags:
3217 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3218 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3219 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3220 * 0x0001 Enable Quotas: enable quota for this fs
3224 /* we need to fake up a fsp here,
3225 * because its not send in this call
3227 files_struct fsp;
3228 SMB_NTQUOTA_STRUCT quotas;
3230 ZERO_STRUCT(fsp);
3231 ZERO_STRUCT(quotas);
3233 fsp.conn = conn;
3234 fsp.fnum = -1;
3236 /* access check */
3237 if (get_current_uid(conn) != 0) {
3238 DEBUG(0,("set_user_quota: access_denied "
3239 "service [%s] user [%s]\n",
3240 lp_servicename(SNUM(conn)),
3241 conn->session_info->unix_info->unix_name));
3242 return NT_STATUS_ACCESS_DENIED;
3245 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3246 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3247 return map_nt_error_from_unix(errno);
3250 data_len = 48;
3252 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3253 lp_servicename(SNUM(conn))));
3255 /* Unknown1 24 NULL bytes*/
3256 SBIG_UINT(pdata,0,(uint64_t)0);
3257 SBIG_UINT(pdata,8,(uint64_t)0);
3258 SBIG_UINT(pdata,16,(uint64_t)0);
3260 /* Default Soft Quota 8 bytes */
3261 SBIG_UINT(pdata,24,quotas.softlim);
3263 /* Default Hard Quota 8 bytes */
3264 SBIG_UINT(pdata,32,quotas.hardlim);
3266 /* Quota flag 2 bytes */
3267 SSVAL(pdata,40,quotas.qflags);
3269 /* Unknown3 6 NULL bytes */
3270 SSVAL(pdata,42,0);
3271 SIVAL(pdata,44,0);
3273 break;
3275 #endif /* HAVE_SYS_QUOTAS */
3276 case SMB_FS_OBJECTID_INFORMATION:
3278 unsigned char objid[16];
3279 struct smb_extended_info extended_info;
3280 memcpy(pdata,create_volume_objectid(conn, objid),16);
3281 samba_extended_info_version (&extended_info);
3282 SIVAL(pdata,16,extended_info.samba_magic);
3283 SIVAL(pdata,20,extended_info.samba_version);
3284 SIVAL(pdata,24,extended_info.samba_subversion);
3285 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3286 memcpy(pdata+36,extended_info.samba_version_string,28);
3287 data_len = 64;
3288 break;
3292 * Query the version and capabilities of the CIFS UNIX extensions
3293 * in use.
3296 case SMB_QUERY_CIFS_UNIX_INFO:
3298 bool large_write = lp_min_receive_file_size() &&
3299 !srv_is_signing_active(conn->sconn);
3300 bool large_read = !srv_is_signing_active(conn->sconn);
3301 int encrypt_caps = 0;
3303 if (!lp_unix_extensions()) {
3304 return NT_STATUS_INVALID_LEVEL;
3307 switch (conn->encrypt_level) {
3308 case 0:
3309 encrypt_caps = 0;
3310 break;
3311 case 1:
3312 case Auto:
3313 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3314 break;
3315 case Required:
3316 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3317 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3318 large_write = false;
3319 large_read = false;
3320 break;
3323 data_len = 12;
3324 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3325 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3327 /* We have POSIX ACLs, pathname, encryption,
3328 * large read/write, and locking capability. */
3330 SBIG_UINT(pdata,4,((uint64_t)(
3331 CIFS_UNIX_POSIX_ACLS_CAP|
3332 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3333 CIFS_UNIX_FCNTL_LOCKS_CAP|
3334 CIFS_UNIX_EXTATTR_CAP|
3335 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3336 encrypt_caps|
3337 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3338 (large_write ?
3339 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3340 break;
3343 case SMB_QUERY_POSIX_FS_INFO:
3345 int rc;
3346 vfs_statvfs_struct svfs;
3348 if (!lp_unix_extensions()) {
3349 return NT_STATUS_INVALID_LEVEL;
3352 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3354 if (!rc) {
3355 data_len = 56;
3356 SIVAL(pdata,0,svfs.OptimalTransferSize);
3357 SIVAL(pdata,4,svfs.BlockSize);
3358 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3359 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3360 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3361 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3362 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3363 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3364 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3365 #ifdef EOPNOTSUPP
3366 } else if (rc == EOPNOTSUPP) {
3367 return NT_STATUS_INVALID_LEVEL;
3368 #endif /* EOPNOTSUPP */
3369 } else {
3370 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3371 return NT_STATUS_DOS(ERRSRV, ERRerror);
3373 break;
3376 case SMB_QUERY_POSIX_WHOAMI:
3378 uint32_t flags = 0;
3379 uint32_t sid_bytes;
3380 int i;
3382 if (!lp_unix_extensions()) {
3383 return NT_STATUS_INVALID_LEVEL;
3386 if (max_data_bytes < 40) {
3387 return NT_STATUS_BUFFER_TOO_SMALL;
3390 /* We ARE guest if global_sid_Builtin_Guests is
3391 * in our list of SIDs.
3393 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3394 conn->session_info->security_token)) {
3395 flags |= SMB_WHOAMI_GUEST;
3398 /* We are NOT guest if global_sid_Authenticated_Users
3399 * is in our list of SIDs.
3401 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3402 conn->session_info->security_token)) {
3403 flags &= ~SMB_WHOAMI_GUEST;
3406 /* NOTE: 8 bytes for UID/GID, irrespective of native
3407 * platform size. This matches
3408 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3410 data_len = 4 /* flags */
3411 + 4 /* flag mask */
3412 + 8 /* uid */
3413 + 8 /* gid */
3414 + 4 /* ngroups */
3415 + 4 /* num_sids */
3416 + 4 /* SID bytes */
3417 + 4 /* pad/reserved */
3418 + (conn->session_info->unix_token->ngroups * 8)
3419 /* groups list */
3420 + (conn->session_info->security_token->num_sids *
3421 SID_MAX_SIZE)
3422 /* SID list */;
3424 SIVAL(pdata, 0, flags);
3425 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3426 SBIG_UINT(pdata, 8,
3427 (uint64_t)conn->session_info->unix_token->uid);
3428 SBIG_UINT(pdata, 16,
3429 (uint64_t)conn->session_info->unix_token->gid);
3432 if (data_len >= max_data_bytes) {
3433 /* Potential overflow, skip the GIDs and SIDs. */
3435 SIVAL(pdata, 24, 0); /* num_groups */
3436 SIVAL(pdata, 28, 0); /* num_sids */
3437 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3438 SIVAL(pdata, 36, 0); /* reserved */
3440 data_len = 40;
3441 break;
3444 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3445 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3447 /* We walk the SID list twice, but this call is fairly
3448 * infrequent, and I don't expect that it's performance
3449 * sensitive -- jpeach
3451 for (i = 0, sid_bytes = 0;
3452 i < conn->session_info->security_token->num_sids; ++i) {
3453 sid_bytes += ndr_size_dom_sid(
3454 &conn->session_info->security_token->sids[i],
3458 /* SID list byte count */
3459 SIVAL(pdata, 32, sid_bytes);
3461 /* 4 bytes pad/reserved - must be zero */
3462 SIVAL(pdata, 36, 0);
3463 data_len = 40;
3465 /* GID list */
3466 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3467 SBIG_UINT(pdata, data_len,
3468 (uint64_t)conn->session_info->unix_token->groups[i]);
3469 data_len += 8;
3472 /* SID list */
3473 for (i = 0;
3474 i < conn->session_info->security_token->num_sids; ++i) {
3475 int sid_len = ndr_size_dom_sid(
3476 &conn->session_info->security_token->sids[i],
3479 sid_linearize(pdata + data_len, sid_len,
3480 &conn->session_info->security_token->sids[i]);
3481 data_len += sid_len;
3484 break;
3487 case SMB_MAC_QUERY_FS_INFO:
3489 * Thursby MAC extension... ONLY on NTFS filesystems
3490 * once we do streams then we don't need this
3492 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3493 data_len = 88;
3494 SIVAL(pdata,84,0x100); /* Don't support mac... */
3495 break;
3497 /* drop through */
3498 default:
3499 return NT_STATUS_INVALID_LEVEL;
3502 *ret_data_len = data_len;
3503 return NT_STATUS_OK;
3506 /****************************************************************************
3507 Reply to a TRANS2_QFSINFO (query filesystem info).
3508 ****************************************************************************/
3510 static void call_trans2qfsinfo(connection_struct *conn,
3511 struct smb_request *req,
3512 char **pparams, int total_params,
3513 char **ppdata, int total_data,
3514 unsigned int max_data_bytes)
3516 char *params = *pparams;
3517 uint16_t info_level;
3518 int data_len = 0;
3519 NTSTATUS status;
3521 if (total_params < 2) {
3522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3523 return;
3526 info_level = SVAL(params,0);
3528 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3529 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3530 DEBUG(0,("call_trans2qfsinfo: encryption required "
3531 "and info level 0x%x sent.\n",
3532 (unsigned int)info_level));
3533 exit_server_cleanly("encryption required "
3534 "on connection");
3535 return;
3539 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3541 status = smbd_do_qfsinfo(conn, req,
3542 info_level,
3543 req->flags2,
3544 max_data_bytes,
3545 ppdata, &data_len);
3546 if (!NT_STATUS_IS_OK(status)) {
3547 reply_nterror(req, status);
3548 return;
3551 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3552 max_data_bytes);
3554 DEBUG( 4, ( "%s info_level = %d\n",
3555 smb_fn_name(req->cmd), info_level) );
3557 return;
3560 /****************************************************************************
3561 Reply to a TRANS2_SETFSINFO (set filesystem info).
3562 ****************************************************************************/
3564 static void call_trans2setfsinfo(connection_struct *conn,
3565 struct smb_request *req,
3566 char **pparams, int total_params,
3567 char **ppdata, int total_data,
3568 unsigned int max_data_bytes)
3570 struct smbd_server_connection *sconn = req->sconn;
3571 char *pdata = *ppdata;
3572 char *params = *pparams;
3573 uint16 info_level;
3575 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3577 /* */
3578 if (total_params < 4) {
3579 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3580 total_params));
3581 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3582 return;
3585 info_level = SVAL(params,2);
3587 if (IS_IPC(conn)) {
3588 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3589 info_level != SMB_SET_CIFS_UNIX_INFO) {
3590 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3591 "info level (0x%x) on IPC$.\n",
3592 (unsigned int)info_level));
3593 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3594 return;
3598 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3599 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3600 DEBUG(0,("call_trans2setfsinfo: encryption required "
3601 "and info level 0x%x sent.\n",
3602 (unsigned int)info_level));
3603 exit_server_cleanly("encryption required "
3604 "on connection");
3605 return;
3609 switch(info_level) {
3610 case SMB_SET_CIFS_UNIX_INFO:
3611 if (!lp_unix_extensions()) {
3612 reply_nterror(req,
3613 NT_STATUS_INVALID_LEVEL);
3614 return;
3617 /* There should be 12 bytes of capabilities set. */
3618 if (total_data < 8) {
3619 reply_nterror(
3620 req,
3621 NT_STATUS_INVALID_PARAMETER);
3622 return;
3624 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3625 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3626 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3627 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3628 /* Just print these values for now. */
3629 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3630 "major = %u, minor = %u cap_low = 0x%x, "
3631 "cap_high = 0x%xn",
3632 (unsigned int)sconn->
3633 smb1.unix_info.client_major,
3634 (unsigned int)sconn->
3635 smb1.unix_info.client_minor,
3636 (unsigned int)sconn->
3637 smb1.unix_info.client_cap_low,
3638 (unsigned int)sconn->
3639 smb1.unix_info.client_cap_high));
3641 /* Here is where we must switch to posix pathname processing... */
3642 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3643 lp_set_posix_pathnames();
3644 mangle_change_to_posix();
3647 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3648 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3649 /* Client that knows how to do posix locks,
3650 * but not posix open/mkdir operations. Set a
3651 * default type for read/write checks. */
3653 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3656 break;
3658 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3660 NTSTATUS status;
3661 size_t param_len = 0;
3662 size_t data_len = total_data;
3664 if (!lp_unix_extensions()) {
3665 reply_nterror(
3666 req,
3667 NT_STATUS_INVALID_LEVEL);
3668 return;
3671 if (lp_smb_encrypt(SNUM(conn)) == false) {
3672 reply_nterror(
3673 req,
3674 NT_STATUS_NOT_SUPPORTED);
3675 return;
3678 if (req->sconn->smb1.echo_handler.trusted_fde) {
3679 DEBUG( 2,("call_trans2setfsinfo: "
3680 "request transport encryption disabled"
3681 "with 'fork echo handler = yes'\n"));
3682 reply_nterror(
3683 req,
3684 NT_STATUS_NOT_SUPPORTED);
3685 return;
3688 DEBUG( 4,("call_trans2setfsinfo: "
3689 "request transport encryption.\n"));
3691 status = srv_request_encryption_setup(conn,
3692 (unsigned char **)ppdata,
3693 &data_len,
3694 (unsigned char **)pparams,
3695 &param_len);
3697 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3698 !NT_STATUS_IS_OK(status)) {
3699 reply_nterror(req, status);
3700 return;
3703 send_trans2_replies(conn, req,
3704 *pparams,
3705 param_len,
3706 *ppdata,
3707 data_len,
3708 max_data_bytes);
3710 if (NT_STATUS_IS_OK(status)) {
3711 /* Server-side transport
3712 * encryption is now *on*. */
3713 status = srv_encryption_start(conn);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 char *reason = talloc_asprintf(talloc_tos(),
3716 "Failure in setting "
3717 "up encrypted transport: %s",
3718 nt_errstr(status));
3719 exit_server_cleanly(reason);
3722 return;
3725 case SMB_FS_QUOTA_INFORMATION:
3727 files_struct *fsp = NULL;
3728 SMB_NTQUOTA_STRUCT quotas;
3730 ZERO_STRUCT(quotas);
3732 /* access check */
3733 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3734 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3735 lp_servicename(SNUM(conn)),
3736 conn->session_info->unix_info->unix_name));
3737 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3738 return;
3741 /* note: normaly there're 48 bytes,
3742 * but we didn't use the last 6 bytes for now
3743 * --metze
3745 fsp = file_fsp(req, SVAL(params,0));
3747 if (!check_fsp_ntquota_handle(conn, req,
3748 fsp)) {
3749 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3750 reply_nterror(
3751 req, NT_STATUS_INVALID_HANDLE);
3752 return;
3755 if (total_data < 42) {
3756 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3757 total_data));
3758 reply_nterror(
3759 req,
3760 NT_STATUS_INVALID_PARAMETER);
3761 return;
3764 /* unknown_1 24 NULL bytes in pdata*/
3766 /* the soft quotas 8 bytes (uint64_t)*/
3767 quotas.softlim = BVAL(pdata,24);
3769 /* the hard quotas 8 bytes (uint64_t)*/
3770 quotas.hardlim = BVAL(pdata,32);
3772 /* quota_flags 2 bytes **/
3773 quotas.qflags = SVAL(pdata,40);
3775 /* unknown_2 6 NULL bytes follow*/
3777 /* now set the quotas */
3778 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3779 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3780 reply_nterror(req, map_nt_error_from_unix(errno));
3781 return;
3784 break;
3786 default:
3787 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3788 info_level));
3789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3790 return;
3791 break;
3795 * sending this reply works fine,
3796 * but I'm not sure it's the same
3797 * like windows do...
3798 * --metze
3800 reply_outbuf(req, 10, 0);
3803 #if defined(HAVE_POSIX_ACLS)
3804 /****************************************************************************
3805 Utility function to count the number of entries in a POSIX acl.
3806 ****************************************************************************/
3808 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3810 unsigned int ace_count = 0;
3811 int entry_id = SMB_ACL_FIRST_ENTRY;
3812 SMB_ACL_ENTRY_T entry;
3814 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3815 /* get_next... */
3816 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3817 entry_id = SMB_ACL_NEXT_ENTRY;
3819 ace_count++;
3821 return ace_count;
3824 /****************************************************************************
3825 Utility function to marshall a POSIX acl into wire format.
3826 ****************************************************************************/
3828 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3830 int entry_id = SMB_ACL_FIRST_ENTRY;
3831 SMB_ACL_ENTRY_T entry;
3833 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3834 SMB_ACL_TAG_T tagtype;
3835 SMB_ACL_PERMSET_T permset;
3836 unsigned char perms = 0;
3837 unsigned int own_grp;
3839 /* get_next... */
3840 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3841 entry_id = SMB_ACL_NEXT_ENTRY;
3844 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3845 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3846 return False;
3849 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3850 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3851 return False;
3854 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3855 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3856 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3858 SCVAL(pdata,1,perms);
3860 switch (tagtype) {
3861 case SMB_ACL_USER_OBJ:
3862 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3863 own_grp = (unsigned int)pst->st_ex_uid;
3864 SIVAL(pdata,2,own_grp);
3865 SIVAL(pdata,6,0);
3866 break;
3867 case SMB_ACL_USER:
3869 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3870 if (!puid) {
3871 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3872 return False;
3874 own_grp = (unsigned int)*puid;
3875 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3876 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3877 SIVAL(pdata,2,own_grp);
3878 SIVAL(pdata,6,0);
3879 break;
3881 case SMB_ACL_GROUP_OBJ:
3882 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3883 own_grp = (unsigned int)pst->st_ex_gid;
3884 SIVAL(pdata,2,own_grp);
3885 SIVAL(pdata,6,0);
3886 break;
3887 case SMB_ACL_GROUP:
3889 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3890 if (!pgid) {
3891 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3892 return False;
3894 own_grp = (unsigned int)*pgid;
3895 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3896 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3897 SIVAL(pdata,2,own_grp);
3898 SIVAL(pdata,6,0);
3899 break;
3901 case SMB_ACL_MASK:
3902 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3903 SIVAL(pdata,2,0xFFFFFFFF);
3904 SIVAL(pdata,6,0xFFFFFFFF);
3905 break;
3906 case SMB_ACL_OTHER:
3907 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3908 SIVAL(pdata,2,0xFFFFFFFF);
3909 SIVAL(pdata,6,0xFFFFFFFF);
3910 break;
3911 default:
3912 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3913 return False;
3915 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3918 return True;
3920 #endif
3922 /****************************************************************************
3923 Store the FILE_UNIX_BASIC info.
3924 ****************************************************************************/
3926 static char *store_file_unix_basic(connection_struct *conn,
3927 char *pdata,
3928 files_struct *fsp,
3929 const SMB_STRUCT_STAT *psbuf)
3931 uint64_t file_index = get_FileIndex(conn, psbuf);
3933 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3934 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3936 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3937 pdata += 8;
3939 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3940 pdata += 8;
3942 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3943 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3944 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3945 pdata += 24;
3947 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3948 SIVAL(pdata,4,0);
3949 pdata += 8;
3951 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3952 SIVAL(pdata,4,0);
3953 pdata += 8;
3955 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3956 pdata += 4;
3958 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3959 SIVAL(pdata,4,0);
3960 pdata += 8;
3962 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3963 SIVAL(pdata,4,0);
3964 pdata += 8;
3966 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3967 pdata += 8;
3969 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3970 SIVAL(pdata,4,0);
3971 pdata += 8;
3973 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3974 SIVAL(pdata,4,0);
3975 pdata += 8;
3977 return pdata;
3980 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3981 * the chflags(2) (or equivalent) flags.
3983 * XXX: this really should be behind the VFS interface. To do this, we would
3984 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3985 * Each VFS module could then implement its own mapping as appropriate for the
3986 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3988 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3989 info2_flags_map[] =
3991 #ifdef UF_NODUMP
3992 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3993 #endif
3995 #ifdef UF_IMMUTABLE
3996 { UF_IMMUTABLE, EXT_IMMUTABLE },
3997 #endif
3999 #ifdef UF_APPEND
4000 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4001 #endif
4003 #ifdef UF_HIDDEN
4004 { UF_HIDDEN, EXT_HIDDEN },
4005 #endif
4007 /* Do not remove. We need to guarantee that this array has at least one
4008 * entry to build on HP-UX.
4010 { 0, 0 }
4014 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4015 uint32 *smb_fflags, uint32 *smb_fmask)
4017 int i;
4019 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4020 *smb_fmask |= info2_flags_map[i].smb_fflag;
4021 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4022 *smb_fflags |= info2_flags_map[i].smb_fflag;
4027 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4028 const uint32 smb_fflags,
4029 const uint32 smb_fmask,
4030 int *stat_fflags)
4032 uint32 max_fmask = 0;
4033 int i;
4035 *stat_fflags = psbuf->st_ex_flags;
4037 /* For each flags requested in smb_fmask, check the state of the
4038 * corresponding flag in smb_fflags and set or clear the matching
4039 * stat flag.
4042 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4043 max_fmask |= info2_flags_map[i].smb_fflag;
4044 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4045 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4046 *stat_fflags |= info2_flags_map[i].stat_fflag;
4047 } else {
4048 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4053 /* If smb_fmask is asking to set any bits that are not supported by
4054 * our flag mappings, we should fail.
4056 if ((smb_fmask & max_fmask) != smb_fmask) {
4057 return False;
4060 return True;
4064 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4065 * of file flags and birth (create) time.
4067 static char *store_file_unix_basic_info2(connection_struct *conn,
4068 char *pdata,
4069 files_struct *fsp,
4070 const SMB_STRUCT_STAT *psbuf)
4072 uint32 file_flags = 0;
4073 uint32 flags_mask = 0;
4075 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4077 /* Create (birth) time 64 bit */
4078 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4079 pdata += 8;
4081 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4082 SIVAL(pdata, 0, file_flags); /* flags */
4083 SIVAL(pdata, 4, flags_mask); /* mask */
4084 pdata += 8;
4086 return pdata;
4089 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4090 const struct stream_struct *streams,
4091 char *data,
4092 unsigned int max_data_bytes,
4093 unsigned int *data_size)
4095 unsigned int i;
4096 unsigned int ofs = 0;
4098 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4099 unsigned int next_offset;
4100 size_t namelen;
4101 smb_ucs2_t *namebuf;
4103 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4104 streams[i].name, &namelen) ||
4105 namelen <= 2)
4107 return NT_STATUS_INVALID_PARAMETER;
4111 * name_buf is now null-terminated, we need to marshall as not
4112 * terminated
4115 namelen -= 2;
4117 SIVAL(data, ofs+4, namelen);
4118 SOFF_T(data, ofs+8, streams[i].size);
4119 SOFF_T(data, ofs+16, streams[i].alloc_size);
4120 memcpy(data+ofs+24, namebuf, namelen);
4121 TALLOC_FREE(namebuf);
4123 next_offset = ofs + 24 + namelen;
4125 if (i == num_streams-1) {
4126 SIVAL(data, ofs, 0);
4128 else {
4129 unsigned int align = ndr_align_size(next_offset, 8);
4131 memset(data+next_offset, 0, align);
4132 next_offset += align;
4134 SIVAL(data, ofs, next_offset - ofs);
4135 ofs = next_offset;
4138 ofs = next_offset;
4141 *data_size = ofs;
4143 return NT_STATUS_OK;
4146 /****************************************************************************
4147 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4148 ****************************************************************************/
4150 static void call_trans2qpipeinfo(connection_struct *conn,
4151 struct smb_request *req,
4152 unsigned int tran_call,
4153 char **pparams, int total_params,
4154 char **ppdata, int total_data,
4155 unsigned int max_data_bytes)
4157 char *params = *pparams;
4158 char *pdata = *ppdata;
4159 unsigned int data_size = 0;
4160 unsigned int param_size = 2;
4161 uint16 info_level;
4162 files_struct *fsp;
4164 if (!params) {
4165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4166 return;
4169 if (total_params < 4) {
4170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4171 return;
4174 fsp = file_fsp(req, SVAL(params,0));
4175 if (!fsp_is_np(fsp)) {
4176 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4177 return;
4180 info_level = SVAL(params,2);
4182 *pparams = (char *)SMB_REALLOC(*pparams,2);
4183 if (*pparams == NULL) {
4184 reply_nterror(req, NT_STATUS_NO_MEMORY);
4185 return;
4187 params = *pparams;
4188 SSVAL(params,0,0);
4189 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4190 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4191 if (*ppdata == NULL ) {
4192 reply_nterror(req, NT_STATUS_NO_MEMORY);
4193 return;
4195 pdata = *ppdata;
4197 switch (info_level) {
4198 case SMB_FILE_STANDARD_INFORMATION:
4199 memset(pdata,0,24);
4200 SOFF_T(pdata,0,4096LL);
4201 SIVAL(pdata,16,1);
4202 SIVAL(pdata,20,1);
4203 data_size = 24;
4204 break;
4206 default:
4207 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4208 return;
4211 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4212 max_data_bytes);
4214 return;
4217 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4218 TALLOC_CTX *mem_ctx,
4219 uint16_t info_level,
4220 files_struct *fsp,
4221 struct smb_filename *smb_fname,
4222 bool delete_pending,
4223 struct timespec write_time_ts,
4224 struct ea_list *ea_list,
4225 int lock_data_count,
4226 char *lock_data,
4227 uint16_t flags2,
4228 unsigned int max_data_bytes,
4229 char **ppdata,
4230 unsigned int *pdata_size)
4232 char *pdata = *ppdata;
4233 char *dstart, *dend;
4234 unsigned int data_size;
4235 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4236 time_t create_time, mtime, atime, c_time;
4237 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4238 char *p;
4239 char *base_name;
4240 char *dos_fname;
4241 int mode;
4242 int nlink;
4243 NTSTATUS status;
4244 uint64_t file_size = 0;
4245 uint64_t pos = 0;
4246 uint64_t allocation_size = 0;
4247 uint64_t file_index = 0;
4248 uint32_t access_mask = 0;
4250 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4251 return NT_STATUS_INVALID_LEVEL;
4254 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4255 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4256 info_level, max_data_bytes));
4258 mode = dos_mode(conn, smb_fname);
4259 nlink = psbuf->st_ex_nlink;
4261 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4262 nlink = 1;
4265 if ((nlink > 0) && delete_pending) {
4266 nlink -= 1;
4269 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4270 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4271 if (*ppdata == NULL) {
4272 return NT_STATUS_NO_MEMORY;
4274 pdata = *ppdata;
4275 dstart = pdata;
4276 dend = dstart + data_size - 1;
4278 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4279 update_stat_ex_mtime(psbuf, write_time_ts);
4282 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4283 mtime_ts = psbuf->st_ex_mtime;
4284 atime_ts = psbuf->st_ex_atime;
4285 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4287 if (lp_dos_filetime_resolution(SNUM(conn))) {
4288 dos_filetime_timespec(&create_time_ts);
4289 dos_filetime_timespec(&mtime_ts);
4290 dos_filetime_timespec(&atime_ts);
4291 dos_filetime_timespec(&ctime_ts);
4294 create_time = convert_timespec_to_time_t(create_time_ts);
4295 mtime = convert_timespec_to_time_t(mtime_ts);
4296 atime = convert_timespec_to_time_t(atime_ts);
4297 c_time = convert_timespec_to_time_t(ctime_ts);
4299 p = strrchr_m(smb_fname->base_name,'/');
4300 if (!p)
4301 base_name = smb_fname->base_name;
4302 else
4303 base_name = p+1;
4305 /* NT expects the name to be in an exact form of the *full*
4306 filename. See the trans2 torture test */
4307 if (ISDOT(base_name)) {
4308 dos_fname = talloc_strdup(mem_ctx, "\\");
4309 if (!dos_fname) {
4310 return NT_STATUS_NO_MEMORY;
4312 } else {
4313 dos_fname = talloc_asprintf(mem_ctx,
4314 "\\%s",
4315 smb_fname->base_name);
4316 if (!dos_fname) {
4317 return NT_STATUS_NO_MEMORY;
4319 if (is_ntfs_stream_smb_fname(smb_fname)) {
4320 dos_fname = talloc_asprintf(dos_fname, "%s",
4321 smb_fname->stream_name);
4322 if (!dos_fname) {
4323 return NT_STATUS_NO_MEMORY;
4327 string_replace(dos_fname, '/', '\\');
4330 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4332 if (!fsp) {
4333 /* Do we have this path open ? */
4334 files_struct *fsp1;
4335 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4336 fsp1 = file_find_di_first(conn->sconn, fileid);
4337 if (fsp1 && fsp1->initial_allocation_size) {
4338 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4342 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4343 file_size = get_file_size_stat(psbuf);
4346 if (fsp) {
4347 pos = fsp->fh->position_information;
4350 if (fsp) {
4351 access_mask = fsp->access_mask;
4352 } else {
4353 /* GENERIC_EXECUTE mapping from Windows */
4354 access_mask = 0x12019F;
4357 /* This should be an index number - looks like
4358 dev/ino to me :-)
4360 I think this causes us to fail the IFSKIT
4361 BasicFileInformationTest. -tpot */
4362 file_index = get_FileIndex(conn, psbuf);
4364 switch (info_level) {
4365 case SMB_INFO_STANDARD:
4366 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4367 data_size = 22;
4368 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4369 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4370 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4371 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4372 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4373 SSVAL(pdata,l1_attrFile,mode);
4374 break;
4376 case SMB_INFO_QUERY_EA_SIZE:
4378 unsigned int ea_size =
4379 estimate_ea_size(conn, fsp,
4380 smb_fname->base_name);
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4382 data_size = 26;
4383 srv_put_dos_date2(pdata,0,create_time);
4384 srv_put_dos_date2(pdata,4,atime);
4385 srv_put_dos_date2(pdata,8,mtime); /* write time */
4386 SIVAL(pdata,12,(uint32)file_size);
4387 SIVAL(pdata,16,(uint32)allocation_size);
4388 SSVAL(pdata,20,mode);
4389 SIVAL(pdata,22,ea_size);
4390 break;
4393 case SMB_INFO_IS_NAME_VALID:
4394 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4395 if (fsp) {
4396 /* os/2 needs this ? really ?*/
4397 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4399 /* This is only reached for qpathinfo */
4400 data_size = 0;
4401 break;
4403 case SMB_INFO_QUERY_EAS_FROM_LIST:
4405 size_t total_ea_len = 0;
4406 struct ea_list *ea_file_list = NULL;
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4410 ea_file_list =
4411 get_ea_list_from_file(mem_ctx, conn, fsp,
4412 smb_fname->base_name,
4413 &total_ea_len);
4414 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4416 if (!ea_list || (total_ea_len > data_size)) {
4417 data_size = 4;
4418 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4419 break;
4422 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4423 break;
4426 case SMB_INFO_QUERY_ALL_EAS:
4428 /* We have data_size bytes to put EA's into. */
4429 size_t total_ea_len = 0;
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4433 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4434 smb_fname->base_name,
4435 &total_ea_len);
4436 if (!ea_list || (total_ea_len > data_size)) {
4437 data_size = 4;
4438 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4439 break;
4442 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4443 break;
4446 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4448 /* This is FileFullEaInformation - 0xF which maps to
4449 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4451 /* We have data_size bytes to put EA's into. */
4452 size_t total_ea_len = 0;
4453 struct ea_list *ea_file_list = NULL;
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4457 /*TODO: add filtering and index handling */
4459 ea_file_list =
4460 get_ea_list_from_file(mem_ctx, conn, fsp,
4461 smb_fname->base_name,
4462 &total_ea_len);
4463 if (!ea_file_list) {
4464 return NT_STATUS_NO_EAS_ON_FILE;
4467 status = fill_ea_chained_buffer(mem_ctx,
4468 pdata,
4469 data_size,
4470 &data_size,
4471 conn, ea_file_list);
4472 if (!NT_STATUS_IS_OK(status)) {
4473 return status;
4475 break;
4478 case SMB_FILE_BASIC_INFORMATION:
4479 case SMB_QUERY_FILE_BASIC_INFO:
4481 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4483 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4484 } else {
4485 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4486 data_size = 40;
4487 SIVAL(pdata,36,0);
4489 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4490 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4491 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4492 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4493 SIVAL(pdata,32,mode);
4495 DEBUG(5,("SMB_QFBI - "));
4496 DEBUG(5,("create: %s ", ctime(&create_time)));
4497 DEBUG(5,("access: %s ", ctime(&atime)));
4498 DEBUG(5,("write: %s ", ctime(&mtime)));
4499 DEBUG(5,("change: %s ", ctime(&c_time)));
4500 DEBUG(5,("mode: %x\n", mode));
4501 break;
4503 case SMB_FILE_STANDARD_INFORMATION:
4504 case SMB_QUERY_FILE_STANDARD_INFO:
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4507 data_size = 24;
4508 SOFF_T(pdata,0,allocation_size);
4509 SOFF_T(pdata,8,file_size);
4510 SIVAL(pdata,16,nlink);
4511 SCVAL(pdata,20,delete_pending?1:0);
4512 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4513 SSVAL(pdata,22,0); /* Padding. */
4514 break;
4516 case SMB_FILE_EA_INFORMATION:
4517 case SMB_QUERY_FILE_EA_INFO:
4519 unsigned int ea_size =
4520 estimate_ea_size(conn, fsp, smb_fname->base_name);
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4522 data_size = 4;
4523 SIVAL(pdata,0,ea_size);
4524 break;
4527 /* Get the 8.3 name - used if NT SMB was negotiated. */
4528 case SMB_QUERY_FILE_ALT_NAME_INFO:
4529 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4531 int len;
4532 char mangled_name[13];
4533 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4534 if (!name_to_8_3(base_name,mangled_name,
4535 True,conn->params)) {
4536 return NT_STATUS_NO_MEMORY;
4538 len = srvstr_push(dstart, flags2,
4539 pdata+4, mangled_name,
4540 PTR_DIFF(dend, pdata+4),
4541 STR_UNICODE);
4542 data_size = 4 + len;
4543 SIVAL(pdata,0,len);
4544 break;
4547 case SMB_QUERY_FILE_NAME_INFO:
4549 int len;
4551 this must be *exactly* right for ACLs on mapped drives to work
4553 len = srvstr_push(dstart, flags2,
4554 pdata+4, dos_fname,
4555 PTR_DIFF(dend, pdata+4),
4556 STR_UNICODE);
4557 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4558 data_size = 4 + len;
4559 SIVAL(pdata,0,len);
4560 break;
4563 case SMB_FILE_ALLOCATION_INFORMATION:
4564 case SMB_QUERY_FILE_ALLOCATION_INFO:
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4566 data_size = 8;
4567 SOFF_T(pdata,0,allocation_size);
4568 break;
4570 case SMB_FILE_END_OF_FILE_INFORMATION:
4571 case SMB_QUERY_FILE_END_OF_FILEINFO:
4572 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4573 data_size = 8;
4574 SOFF_T(pdata,0,file_size);
4575 break;
4577 case SMB_QUERY_FILE_ALL_INFO:
4578 case SMB_FILE_ALL_INFORMATION:
4580 int len;
4581 unsigned int ea_size =
4582 estimate_ea_size(conn, fsp, smb_fname->base_name);
4583 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4584 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4585 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4586 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4587 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4588 SIVAL(pdata,32,mode);
4589 SIVAL(pdata,36,0); /* padding. */
4590 pdata += 40;
4591 SOFF_T(pdata,0,allocation_size);
4592 SOFF_T(pdata,8,file_size);
4593 SIVAL(pdata,16,nlink);
4594 SCVAL(pdata,20,delete_pending);
4595 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4596 SSVAL(pdata,22,0);
4597 pdata += 24;
4598 SIVAL(pdata,0,ea_size);
4599 pdata += 4; /* EA info */
4600 len = srvstr_push(dstart, flags2,
4601 pdata+4, dos_fname,
4602 PTR_DIFF(dend, pdata+4),
4603 STR_UNICODE);
4604 SIVAL(pdata,0,len);
4605 pdata += 4 + len;
4606 data_size = PTR_DIFF(pdata,(*ppdata));
4607 break;
4610 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4612 int len;
4613 unsigned int ea_size =
4614 estimate_ea_size(conn, fsp, smb_fname->base_name);
4615 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4616 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4617 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4618 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4619 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4620 SIVAL(pdata, 0x20, mode);
4621 SIVAL(pdata, 0x24, 0); /* padding. */
4622 SBVAL(pdata, 0x28, allocation_size);
4623 SBVAL(pdata, 0x30, file_size);
4624 SIVAL(pdata, 0x38, nlink);
4625 SCVAL(pdata, 0x3C, delete_pending);
4626 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4627 SSVAL(pdata, 0x3E, 0); /* padding */
4628 SBVAL(pdata, 0x40, file_index);
4629 SIVAL(pdata, 0x48, ea_size);
4630 SIVAL(pdata, 0x4C, access_mask);
4631 SBVAL(pdata, 0x50, pos);
4632 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4633 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4635 pdata += 0x60;
4637 len = srvstr_push(dstart, flags2,
4638 pdata+4, dos_fname,
4639 PTR_DIFF(dend, pdata+4),
4640 STR_UNICODE);
4641 SIVAL(pdata,0,len);
4642 pdata += 4 + len;
4643 data_size = PTR_DIFF(pdata,(*ppdata));
4644 break;
4646 case SMB_FILE_INTERNAL_INFORMATION:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4649 SBVAL(pdata, 0, file_index);
4650 data_size = 8;
4651 break;
4653 case SMB_FILE_ACCESS_INFORMATION:
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4655 SIVAL(pdata, 0, access_mask);
4656 data_size = 4;
4657 break;
4659 case SMB_FILE_NAME_INFORMATION:
4660 /* Pathname with leading '\'. */
4662 size_t byte_len;
4663 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4665 SIVAL(pdata,0,byte_len);
4666 data_size = 4 + byte_len;
4667 break;
4670 case SMB_FILE_DISPOSITION_INFORMATION:
4671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4672 data_size = 1;
4673 SCVAL(pdata,0,delete_pending);
4674 break;
4676 case SMB_FILE_POSITION_INFORMATION:
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4678 data_size = 8;
4679 SOFF_T(pdata,0,pos);
4680 break;
4682 case SMB_FILE_MODE_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4684 SIVAL(pdata,0,mode);
4685 data_size = 4;
4686 break;
4688 case SMB_FILE_ALIGNMENT_INFORMATION:
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4690 SIVAL(pdata,0,0); /* No alignment needed. */
4691 data_size = 4;
4692 break;
4695 * NT4 server just returns "invalid query" to this - if we try
4696 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4697 * want this. JRA.
4699 /* The first statement above is false - verified using Thursby
4700 * client against NT4 -- gcolley.
4702 case SMB_QUERY_FILE_STREAM_INFO:
4703 case SMB_FILE_STREAM_INFORMATION: {
4704 unsigned int num_streams = 0;
4705 struct stream_struct *streams = NULL;
4707 DEBUG(10,("smbd_do_qfilepathinfo: "
4708 "SMB_FILE_STREAM_INFORMATION\n"));
4710 if (is_ntfs_stream_smb_fname(smb_fname)) {
4711 return NT_STATUS_INVALID_PARAMETER;
4714 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4715 talloc_tos(), &num_streams, &streams);
4717 if (!NT_STATUS_IS_OK(status)) {
4718 DEBUG(10, ("could not get stream info: %s\n",
4719 nt_errstr(status)));
4720 return status;
4723 status = marshall_stream_info(num_streams, streams,
4724 pdata, max_data_bytes,
4725 &data_size);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 DEBUG(10, ("marshall_stream_info failed: %s\n",
4729 nt_errstr(status)));
4730 return status;
4733 TALLOC_FREE(streams);
4735 break;
4737 case SMB_QUERY_COMPRESSION_INFO:
4738 case SMB_FILE_COMPRESSION_INFORMATION:
4739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4740 SOFF_T(pdata,0,file_size);
4741 SIVAL(pdata,8,0); /* ??? */
4742 SIVAL(pdata,12,0); /* ??? */
4743 data_size = 16;
4744 break;
4746 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4748 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4749 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4750 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4751 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4752 SOFF_T(pdata,32,allocation_size);
4753 SOFF_T(pdata,40,file_size);
4754 SIVAL(pdata,48,mode);
4755 SIVAL(pdata,52,0); /* ??? */
4756 data_size = 56;
4757 break;
4759 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4761 SIVAL(pdata,0,mode);
4762 SIVAL(pdata,4,0);
4763 data_size = 8;
4764 break;
4767 * CIFS UNIX Extensions.
4770 case SMB_QUERY_FILE_UNIX_BASIC:
4772 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4773 data_size = PTR_DIFF(pdata,(*ppdata));
4775 DEBUG(4,("smbd_do_qfilepathinfo: "
4776 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4777 dump_data(4, (uint8_t *)(*ppdata), data_size);
4779 break;
4781 case SMB_QUERY_FILE_UNIX_INFO2:
4783 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4784 data_size = PTR_DIFF(pdata,(*ppdata));
4787 int i;
4788 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4790 for (i=0; i<100; i++)
4791 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4792 DEBUG(4,("\n"));
4795 break;
4797 case SMB_QUERY_FILE_UNIX_LINK:
4799 int len;
4800 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4802 if (!buffer) {
4803 return NT_STATUS_NO_MEMORY;
4806 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4807 #ifdef S_ISLNK
4808 if(!S_ISLNK(psbuf->st_ex_mode)) {
4809 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4811 #else
4812 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4813 #endif
4814 len = SMB_VFS_READLINK(conn,
4815 smb_fname->base_name,
4816 buffer, PATH_MAX);
4817 if (len == -1) {
4818 return map_nt_error_from_unix(errno);
4820 buffer[len] = 0;
4821 len = srvstr_push(dstart, flags2,
4822 pdata, buffer,
4823 PTR_DIFF(dend, pdata),
4824 STR_TERMINATE);
4825 pdata += len;
4826 data_size = PTR_DIFF(pdata,(*ppdata));
4828 break;
4831 #if defined(HAVE_POSIX_ACLS)
4832 case SMB_QUERY_POSIX_ACL:
4834 SMB_ACL_T file_acl = NULL;
4835 SMB_ACL_T def_acl = NULL;
4836 uint16 num_file_acls = 0;
4837 uint16 num_def_acls = 0;
4839 if (fsp && fsp->fh->fd != -1) {
4840 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4841 } else {
4842 file_acl =
4843 SMB_VFS_SYS_ACL_GET_FILE(conn,
4844 smb_fname->base_name,
4845 SMB_ACL_TYPE_ACCESS);
4848 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4849 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4850 "not implemented on "
4851 "filesystem containing %s\n",
4852 smb_fname->base_name));
4853 return NT_STATUS_NOT_IMPLEMENTED;
4856 if (S_ISDIR(psbuf->st_ex_mode)) {
4857 if (fsp && fsp->is_directory) {
4858 def_acl =
4859 SMB_VFS_SYS_ACL_GET_FILE(
4860 conn,
4861 fsp->fsp_name->base_name,
4862 SMB_ACL_TYPE_DEFAULT);
4863 } else {
4864 def_acl =
4865 SMB_VFS_SYS_ACL_GET_FILE(
4866 conn,
4867 smb_fname->base_name,
4868 SMB_ACL_TYPE_DEFAULT);
4870 def_acl = free_empty_sys_acl(conn, def_acl);
4873 num_file_acls = count_acl_entries(conn, file_acl);
4874 num_def_acls = count_acl_entries(conn, def_acl);
4876 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4877 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4878 data_size,
4879 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4880 SMB_POSIX_ACL_HEADER_SIZE) ));
4881 if (file_acl) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4884 if (def_acl) {
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4887 return NT_STATUS_BUFFER_TOO_SMALL;
4890 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4891 SSVAL(pdata,2,num_file_acls);
4892 SSVAL(pdata,4,num_def_acls);
4893 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4894 if (file_acl) {
4895 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4897 if (def_acl) {
4898 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4900 return NT_STATUS_INTERNAL_ERROR;
4902 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4903 if (file_acl) {
4904 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4906 if (def_acl) {
4907 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4909 return NT_STATUS_INTERNAL_ERROR;
4912 if (file_acl) {
4913 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4915 if (def_acl) {
4916 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4918 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4919 break;
4921 #endif
4924 case SMB_QUERY_POSIX_LOCK:
4926 uint64_t count;
4927 uint64_t offset;
4928 uint64_t smblctx;
4929 enum brl_type lock_type;
4931 /* We need an open file with a real fd for this. */
4932 if (!fsp || fsp->fh->fd == -1) {
4933 return NT_STATUS_INVALID_LEVEL;
4936 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4937 return NT_STATUS_INVALID_PARAMETER;
4940 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4941 case POSIX_LOCK_TYPE_READ:
4942 lock_type = READ_LOCK;
4943 break;
4944 case POSIX_LOCK_TYPE_WRITE:
4945 lock_type = WRITE_LOCK;
4946 break;
4947 case POSIX_LOCK_TYPE_UNLOCK:
4948 default:
4949 /* There's no point in asking for an unlock... */
4950 return NT_STATUS_INVALID_PARAMETER;
4953 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4954 #if defined(HAVE_LONGLONG)
4955 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4956 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4957 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4958 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4959 #else /* HAVE_LONGLONG */
4960 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4961 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4962 #endif /* HAVE_LONGLONG */
4964 status = query_lock(fsp,
4965 &smblctx,
4966 &count,
4967 &offset,
4968 &lock_type,
4969 POSIX_LOCK);
4971 if (ERROR_WAS_LOCK_DENIED(status)) {
4972 /* Here we need to report who has it locked... */
4973 data_size = POSIX_LOCK_DATA_SIZE;
4975 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4976 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4977 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4978 #if defined(HAVE_LONGLONG)
4979 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4980 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4981 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4982 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4983 #else /* HAVE_LONGLONG */
4984 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4985 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4986 #endif /* HAVE_LONGLONG */
4988 } else if (NT_STATUS_IS_OK(status)) {
4989 /* For success we just return a copy of what we sent
4990 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4991 data_size = POSIX_LOCK_DATA_SIZE;
4992 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4993 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4994 } else {
4995 return status;
4997 break;
5000 default:
5001 return NT_STATUS_INVALID_LEVEL;
5004 *pdata_size = data_size;
5005 return NT_STATUS_OK;
5008 /****************************************************************************
5009 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5010 file name or file id).
5011 ****************************************************************************/
5013 static void call_trans2qfilepathinfo(connection_struct *conn,
5014 struct smb_request *req,
5015 unsigned int tran_call,
5016 char **pparams, int total_params,
5017 char **ppdata, int total_data,
5018 unsigned int max_data_bytes)
5020 char *params = *pparams;
5021 char *pdata = *ppdata;
5022 uint16 info_level;
5023 unsigned int data_size = 0;
5024 unsigned int param_size = 2;
5025 struct smb_filename *smb_fname = NULL;
5026 bool delete_pending = False;
5027 struct timespec write_time_ts;
5028 files_struct *fsp = NULL;
5029 struct file_id fileid;
5030 struct ea_list *ea_list = NULL;
5031 int lock_data_count = 0;
5032 char *lock_data = NULL;
5033 NTSTATUS status = NT_STATUS_OK;
5035 if (!params) {
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5037 return;
5040 ZERO_STRUCT(write_time_ts);
5042 if (tran_call == TRANSACT2_QFILEINFO) {
5043 if (total_params < 4) {
5044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5045 return;
5048 if (IS_IPC(conn)) {
5049 call_trans2qpipeinfo(conn, req, tran_call,
5050 pparams, total_params,
5051 ppdata, total_data,
5052 max_data_bytes);
5053 return;
5056 fsp = file_fsp(req, SVAL(params,0));
5057 info_level = SVAL(params,2);
5059 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5061 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5062 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5063 return;
5066 /* Initial check for valid fsp ptr. */
5067 if (!check_fsp_open(conn, req, fsp)) {
5068 return;
5071 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5072 &smb_fname);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 reply_nterror(req, status);
5075 return;
5078 if(fsp->fake_file_handle) {
5080 * This is actually for the QUOTA_FAKE_FILE --metze
5083 /* We know this name is ok, it's already passed the checks. */
5085 } else if(fsp->fh->fd == -1) {
5087 * This is actually a QFILEINFO on a directory
5088 * handle (returned from an NT SMB). NT5.0 seems
5089 * to do this call. JRA.
5092 if (INFO_LEVEL_IS_UNIX(info_level)) {
5093 /* Always do lstat for UNIX calls. */
5094 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5095 DEBUG(3,("call_trans2qfilepathinfo: "
5096 "SMB_VFS_LSTAT of %s failed "
5097 "(%s)\n",
5098 smb_fname_str_dbg(smb_fname),
5099 strerror(errno)));
5100 reply_nterror(req,
5101 map_nt_error_from_unix(errno));
5102 return;
5104 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5105 DEBUG(3,("call_trans2qfilepathinfo: "
5106 "SMB_VFS_STAT of %s failed (%s)\n",
5107 smb_fname_str_dbg(smb_fname),
5108 strerror(errno)));
5109 reply_nterror(req,
5110 map_nt_error_from_unix(errno));
5111 return;
5114 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5115 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5116 } else {
5118 * Original code - this is an open file.
5120 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5121 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5122 fsp->fnum, strerror(errno)));
5123 reply_nterror(req,
5124 map_nt_error_from_unix(errno));
5125 return;
5127 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5128 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5131 } else {
5132 uint32_t name_hash;
5133 char *fname = NULL;
5134 uint32_t ucf_flags = 0;
5136 /* qpathinfo */
5137 if (total_params < 7) {
5138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5139 return;
5142 info_level = SVAL(params,0);
5144 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5146 if (INFO_LEVEL_IS_UNIX(info_level)) {
5147 if (!lp_unix_extensions()) {
5148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5149 return;
5151 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5152 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5153 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5154 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5158 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5159 total_params - 6,
5160 STR_TERMINATE, &status);
5161 if (!NT_STATUS_IS_OK(status)) {
5162 reply_nterror(req, status);
5163 return;
5166 status = filename_convert(req,
5167 conn,
5168 req->flags2 & FLAGS2_DFS_PATHNAMES,
5169 fname,
5170 ucf_flags,
5171 NULL,
5172 &smb_fname);
5173 if (!NT_STATUS_IS_OK(status)) {
5174 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5175 reply_botherror(req,
5176 NT_STATUS_PATH_NOT_COVERED,
5177 ERRSRV, ERRbadpath);
5178 return;
5180 reply_nterror(req, status);
5181 return;
5184 /* If this is a stream, check if there is a delete_pending. */
5185 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5186 && is_ntfs_stream_smb_fname(smb_fname)) {
5187 struct smb_filename *smb_fname_base = NULL;
5189 /* Create an smb_filename with stream_name == NULL. */
5190 status =
5191 create_synthetic_smb_fname(talloc_tos(),
5192 smb_fname->base_name,
5193 NULL, NULL,
5194 &smb_fname_base);
5195 if (!NT_STATUS_IS_OK(status)) {
5196 reply_nterror(req, status);
5197 return;
5200 if (INFO_LEVEL_IS_UNIX(info_level)) {
5201 /* Always do lstat for UNIX calls. */
5202 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "SMB_VFS_LSTAT of %s failed "
5205 "(%s)\n",
5206 smb_fname_str_dbg(smb_fname_base),
5207 strerror(errno)));
5208 TALLOC_FREE(smb_fname_base);
5209 reply_nterror(req,
5210 map_nt_error_from_unix(errno));
5211 return;
5213 } else {
5214 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5215 DEBUG(3,("call_trans2qfilepathinfo: "
5216 "fileinfo of %s failed "
5217 "(%s)\n",
5218 smb_fname_str_dbg(smb_fname_base),
5219 strerror(errno)));
5220 TALLOC_FREE(smb_fname_base);
5221 reply_nterror(req,
5222 map_nt_error_from_unix(errno));
5223 return;
5227 status = file_name_hash(conn,
5228 smb_fname_str_dbg(smb_fname_base),
5229 &name_hash);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 TALLOC_FREE(smb_fname_base);
5232 reply_nterror(req, status);
5233 return;
5236 fileid = vfs_file_id_from_sbuf(conn,
5237 &smb_fname_base->st);
5238 TALLOC_FREE(smb_fname_base);
5239 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5240 if (delete_pending) {
5241 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5242 return;
5246 if (INFO_LEVEL_IS_UNIX(info_level)) {
5247 /* Always do lstat for UNIX calls. */
5248 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5249 DEBUG(3,("call_trans2qfilepathinfo: "
5250 "SMB_VFS_LSTAT of %s failed (%s)\n",
5251 smb_fname_str_dbg(smb_fname),
5252 strerror(errno)));
5253 reply_nterror(req,
5254 map_nt_error_from_unix(errno));
5255 return;
5258 } else {
5259 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5260 DEBUG(3,("call_trans2qfilepathinfo: "
5261 "SMB_VFS_STAT of %s failed (%s)\n",
5262 smb_fname_str_dbg(smb_fname),
5263 strerror(errno)));
5264 reply_nterror(req,
5265 map_nt_error_from_unix(errno));
5266 return;
5270 status = file_name_hash(conn,
5271 smb_fname_str_dbg(smb_fname),
5272 &name_hash);
5273 if (!NT_STATUS_IS_OK(status)) {
5274 reply_nterror(req, status);
5275 return;
5278 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5279 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5280 if (delete_pending) {
5281 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5282 return;
5286 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5287 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5288 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5290 /* Pull out any data sent here before we realloc. */
5291 switch (info_level) {
5292 case SMB_INFO_QUERY_EAS_FROM_LIST:
5294 /* Pull any EA list from the data portion. */
5295 uint32 ea_size;
5297 if (total_data < 4) {
5298 reply_nterror(
5299 req, NT_STATUS_INVALID_PARAMETER);
5300 return;
5302 ea_size = IVAL(pdata,0);
5304 if (total_data > 0 && ea_size != total_data) {
5305 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5306 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5307 reply_nterror(
5308 req, NT_STATUS_INVALID_PARAMETER);
5309 return;
5312 if (!lp_ea_support(SNUM(conn))) {
5313 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5314 return;
5317 /* Pull out the list of names. */
5318 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5319 if (!ea_list) {
5320 reply_nterror(
5321 req, NT_STATUS_INVALID_PARAMETER);
5322 return;
5324 break;
5327 case SMB_QUERY_POSIX_LOCK:
5329 if (fsp == NULL || fsp->fh->fd == -1) {
5330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5331 return;
5334 if (total_data != POSIX_LOCK_DATA_SIZE) {
5335 reply_nterror(
5336 req, NT_STATUS_INVALID_PARAMETER);
5337 return;
5340 /* Copy the lock range data. */
5341 lock_data = (char *)talloc_memdup(
5342 req, pdata, total_data);
5343 if (!lock_data) {
5344 reply_nterror(req, NT_STATUS_NO_MEMORY);
5345 return;
5347 lock_data_count = total_data;
5349 default:
5350 break;
5353 *pparams = (char *)SMB_REALLOC(*pparams,2);
5354 if (*pparams == NULL) {
5355 reply_nterror(req, NT_STATUS_NO_MEMORY);
5356 return;
5358 params = *pparams;
5359 SSVAL(params,0,0);
5362 * draft-leach-cifs-v1-spec-02.txt
5363 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5364 * says:
5366 * The requested information is placed in the Data portion of the
5367 * transaction response. For the information levels greater than 0x100,
5368 * the transaction response has 1 parameter word which should be
5369 * ignored by the client.
5371 * However Windows only follows this rule for the IS_NAME_VALID call.
5373 switch (info_level) {
5374 case SMB_INFO_IS_NAME_VALID:
5375 param_size = 0;
5376 break;
5379 if ((info_level & 0xFF00) == 0xFF00) {
5381 * We use levels that start with 0xFF00
5382 * internally to represent SMB2 specific levels
5384 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5385 return;
5388 status = smbd_do_qfilepathinfo(conn, req, info_level,
5389 fsp, smb_fname,
5390 delete_pending, write_time_ts,
5391 ea_list,
5392 lock_data_count, lock_data,
5393 req->flags2, max_data_bytes,
5394 ppdata, &data_size);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 reply_nterror(req, status);
5397 return;
5400 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5401 max_data_bytes);
5403 return;
5406 /****************************************************************************
5407 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5408 code.
5409 ****************************************************************************/
5411 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5412 connection_struct *conn,
5413 struct smb_request *req,
5414 bool overwrite_if_exists,
5415 const struct smb_filename *smb_fname_old,
5416 struct smb_filename *smb_fname_new)
5418 NTSTATUS status = NT_STATUS_OK;
5420 /* source must already exist. */
5421 if (!VALID_STAT(smb_fname_old->st)) {
5422 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5425 if (VALID_STAT(smb_fname_new->st)) {
5426 if (overwrite_if_exists) {
5427 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5428 return NT_STATUS_FILE_IS_A_DIRECTORY;
5430 status = unlink_internals(conn,
5431 req,
5432 FILE_ATTRIBUTE_NORMAL,
5433 smb_fname_new,
5434 false);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 return status;
5438 } else {
5439 /* Disallow if newname already exists. */
5440 return NT_STATUS_OBJECT_NAME_COLLISION;
5444 /* No links from a directory. */
5445 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5446 return NT_STATUS_FILE_IS_A_DIRECTORY;
5449 /* Setting a hardlink to/from a stream isn't currently supported. */
5450 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5451 is_ntfs_stream_smb_fname(smb_fname_new)) {
5452 return NT_STATUS_INVALID_PARAMETER;
5455 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5456 smb_fname_old->base_name, smb_fname_new->base_name));
5458 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5459 smb_fname_new->base_name) != 0) {
5460 status = map_nt_error_from_unix(errno);
5461 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5462 nt_errstr(status), smb_fname_old->base_name,
5463 smb_fname_new->base_name));
5465 return status;
5468 /****************************************************************************
5469 Deal with setting the time from any of the setfilepathinfo functions.
5470 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5471 calling this function.
5472 ****************************************************************************/
5474 NTSTATUS smb_set_file_time(connection_struct *conn,
5475 files_struct *fsp,
5476 const struct smb_filename *smb_fname,
5477 struct smb_file_time *ft,
5478 bool setting_write_time)
5480 struct smb_filename smb_fname_base;
5481 uint32 action =
5482 FILE_NOTIFY_CHANGE_LAST_ACCESS
5483 |FILE_NOTIFY_CHANGE_LAST_WRITE
5484 |FILE_NOTIFY_CHANGE_CREATION;
5486 if (!VALID_STAT(smb_fname->st)) {
5487 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5490 /* get some defaults (no modifications) if any info is zero or -1. */
5491 if (null_timespec(ft->create_time)) {
5492 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5495 if (null_timespec(ft->atime)) {
5496 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5499 if (null_timespec(ft->mtime)) {
5500 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5503 if (!setting_write_time) {
5504 /* ft->mtime comes from change time, not write time. */
5505 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5508 /* Ensure the resolution is the correct for
5509 * what we can store on this filesystem. */
5511 round_timespec(conn->ts_res, &ft->create_time);
5512 round_timespec(conn->ts_res, &ft->ctime);
5513 round_timespec(conn->ts_res, &ft->atime);
5514 round_timespec(conn->ts_res, &ft->mtime);
5516 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5517 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5518 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5519 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5520 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5521 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5522 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5523 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5525 if (setting_write_time) {
5527 * This was a Windows setfileinfo on an open file.
5528 * NT does this a lot. We also need to
5529 * set the time here, as it can be read by
5530 * FindFirst/FindNext and with the patch for bug #2045
5531 * in smbd/fileio.c it ensures that this timestamp is
5532 * kept sticky even after a write. We save the request
5533 * away and will set it on file close and after a write. JRA.
5536 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5537 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5539 if (fsp != NULL) {
5540 if (fsp->base_fsp) {
5541 set_sticky_write_time_fsp(fsp->base_fsp,
5542 ft->mtime);
5543 } else {
5544 set_sticky_write_time_fsp(fsp, ft->mtime);
5546 } else {
5547 set_sticky_write_time_path(
5548 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5549 ft->mtime);
5553 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5555 /* Always call ntimes on the base, even if a stream was passed in. */
5556 smb_fname_base = *smb_fname;
5557 smb_fname_base.stream_name = NULL;
5559 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5560 return map_nt_error_from_unix(errno);
5563 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5564 smb_fname->base_name);
5565 return NT_STATUS_OK;
5568 /****************************************************************************
5569 Deal with setting the dosmode from any of the setfilepathinfo functions.
5570 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5571 done before calling this function.
5572 ****************************************************************************/
5574 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5575 const struct smb_filename *smb_fname,
5576 uint32 dosmode)
5578 struct smb_filename *smb_fname_base = NULL;
5579 NTSTATUS status;
5581 if (!VALID_STAT(smb_fname->st)) {
5582 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5585 /* Always operate on the base_name, even if a stream was passed in. */
5586 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5587 NULL, &smb_fname->st,
5588 &smb_fname_base);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 return status;
5593 if (dosmode) {
5594 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5595 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5596 } else {
5597 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5601 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5603 /* check the mode isn't different, before changing it */
5604 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5605 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5606 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5607 (unsigned int)dosmode));
5609 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5610 false)) {
5611 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5612 "%s failed (%s)\n",
5613 smb_fname_str_dbg(smb_fname_base),
5614 strerror(errno)));
5615 status = map_nt_error_from_unix(errno);
5616 goto out;
5619 status = NT_STATUS_OK;
5620 out:
5621 TALLOC_FREE(smb_fname_base);
5622 return status;
5625 /****************************************************************************
5626 Deal with setting the size from any of the setfilepathinfo functions.
5627 ****************************************************************************/
5629 static NTSTATUS smb_set_file_size(connection_struct *conn,
5630 struct smb_request *req,
5631 files_struct *fsp,
5632 const struct smb_filename *smb_fname,
5633 const SMB_STRUCT_STAT *psbuf,
5634 SMB_OFF_T size,
5635 bool fail_after_createfile)
5637 NTSTATUS status = NT_STATUS_OK;
5638 struct smb_filename *smb_fname_tmp = NULL;
5639 files_struct *new_fsp = NULL;
5641 if (!VALID_STAT(*psbuf)) {
5642 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5645 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5647 if (size == get_file_size_stat(psbuf)) {
5648 return NT_STATUS_OK;
5651 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5652 smb_fname_str_dbg(smb_fname), (double)size));
5654 if (fsp && fsp->fh->fd != -1) {
5655 /* Handle based call. */
5656 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5657 return NT_STATUS_ACCESS_DENIED;
5660 if (vfs_set_filelen(fsp, size) == -1) {
5661 return map_nt_error_from_unix(errno);
5663 trigger_write_time_update_immediate(fsp);
5664 return NT_STATUS_OK;
5667 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 return status;
5672 smb_fname_tmp->st = *psbuf;
5674 status = SMB_VFS_CREATE_FILE(
5675 conn, /* conn */
5676 req, /* req */
5677 0, /* root_dir_fid */
5678 smb_fname_tmp, /* fname */
5679 FILE_WRITE_DATA, /* access_mask */
5680 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5681 FILE_SHARE_DELETE),
5682 FILE_OPEN, /* create_disposition*/
5683 0, /* create_options */
5684 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5685 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5686 0, /* allocation_size */
5687 0, /* private_flags */
5688 NULL, /* sd */
5689 NULL, /* ea_list */
5690 &new_fsp, /* result */
5691 NULL); /* pinfo */
5693 TALLOC_FREE(smb_fname_tmp);
5695 if (!NT_STATUS_IS_OK(status)) {
5696 /* NB. We check for open_was_deferred in the caller. */
5697 return status;
5700 /* See RAW-SFILEINFO-END-OF-FILE */
5701 if (fail_after_createfile) {
5702 close_file(req, new_fsp,NORMAL_CLOSE);
5703 return NT_STATUS_INVALID_LEVEL;
5706 if (vfs_set_filelen(new_fsp, size) == -1) {
5707 status = map_nt_error_from_unix(errno);
5708 close_file(req, new_fsp,NORMAL_CLOSE);
5709 return status;
5712 trigger_write_time_update_immediate(new_fsp);
5713 close_file(req, new_fsp,NORMAL_CLOSE);
5714 return NT_STATUS_OK;
5717 /****************************************************************************
5718 Deal with SMB_INFO_SET_EA.
5719 ****************************************************************************/
5721 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5722 const char *pdata,
5723 int total_data,
5724 files_struct *fsp,
5725 const struct smb_filename *smb_fname)
5727 struct ea_list *ea_list = NULL;
5728 TALLOC_CTX *ctx = NULL;
5729 NTSTATUS status = NT_STATUS_OK;
5731 if (total_data < 10) {
5733 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5734 length. They seem to have no effect. Bug #3212. JRA */
5736 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5737 /* We're done. We only get EA info in this call. */
5738 return NT_STATUS_OK;
5741 return NT_STATUS_INVALID_PARAMETER;
5744 if (IVAL(pdata,0) > total_data) {
5745 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5746 IVAL(pdata,0), (unsigned int)total_data));
5747 return NT_STATUS_INVALID_PARAMETER;
5750 ctx = talloc_tos();
5751 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5752 if (!ea_list) {
5753 return NT_STATUS_INVALID_PARAMETER;
5756 status = set_ea(conn, fsp, smb_fname, ea_list);
5758 return status;
5761 /****************************************************************************
5762 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5763 ****************************************************************************/
5765 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5766 const char *pdata,
5767 int total_data,
5768 files_struct *fsp)
5770 struct ea_list *ea_list = NULL;
5771 NTSTATUS status;
5773 if (!fsp) {
5774 return NT_STATUS_INVALID_HANDLE;
5777 if (!lp_ea_support(SNUM(conn))) {
5778 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5779 "EA's not supported.\n",
5780 (unsigned int)total_data));
5781 return NT_STATUS_EAS_NOT_SUPPORTED;
5784 if (total_data < 10) {
5785 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5786 "too small.\n",
5787 (unsigned int)total_data));
5788 return NT_STATUS_INVALID_PARAMETER;
5791 ea_list = read_nttrans_ea_list(talloc_tos(),
5792 pdata,
5793 total_data);
5795 if (!ea_list) {
5796 return NT_STATUS_INVALID_PARAMETER;
5799 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5801 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5802 smb_fname_str_dbg(fsp->fsp_name),
5803 nt_errstr(status) ));
5805 return status;
5809 /****************************************************************************
5810 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5811 ****************************************************************************/
5813 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5814 const char *pdata,
5815 int total_data,
5816 files_struct *fsp,
5817 struct smb_filename *smb_fname)
5819 NTSTATUS status = NT_STATUS_OK;
5820 bool delete_on_close;
5821 uint32 dosmode = 0;
5823 if (total_data < 1) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 if (fsp == NULL) {
5828 return NT_STATUS_INVALID_HANDLE;
5831 delete_on_close = (CVAL(pdata,0) ? True : False);
5832 dosmode = dos_mode(conn, smb_fname);
5834 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5835 "delete_on_close = %u\n",
5836 smb_fname_str_dbg(smb_fname),
5837 (unsigned int)dosmode,
5838 (unsigned int)delete_on_close ));
5840 if (delete_on_close) {
5841 status = can_set_delete_on_close(fsp, dosmode);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 return status;
5847 /* The set is across all open files on this dev/inode pair. */
5848 if (!set_delete_on_close(fsp, delete_on_close,
5849 conn->session_info->unix_token)) {
5850 return NT_STATUS_ACCESS_DENIED;
5852 return NT_STATUS_OK;
5855 /****************************************************************************
5856 Deal with SMB_FILE_POSITION_INFORMATION.
5857 ****************************************************************************/
5859 static NTSTATUS smb_file_position_information(connection_struct *conn,
5860 const char *pdata,
5861 int total_data,
5862 files_struct *fsp)
5864 uint64_t position_information;
5866 if (total_data < 8) {
5867 return NT_STATUS_INVALID_PARAMETER;
5870 if (fsp == NULL) {
5871 /* Ignore on pathname based set. */
5872 return NT_STATUS_OK;
5875 position_information = (uint64_t)IVAL(pdata,0);
5876 #ifdef LARGE_SMB_OFF_T
5877 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5878 #else /* LARGE_SMB_OFF_T */
5879 if (IVAL(pdata,4) != 0) {
5880 /* more than 32 bits? */
5881 return NT_STATUS_INVALID_PARAMETER;
5883 #endif /* LARGE_SMB_OFF_T */
5885 DEBUG(10,("smb_file_position_information: Set file position "
5886 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5887 (double)position_information));
5888 fsp->fh->position_information = position_information;
5889 return NT_STATUS_OK;
5892 /****************************************************************************
5893 Deal with SMB_FILE_MODE_INFORMATION.
5894 ****************************************************************************/
5896 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5897 const char *pdata,
5898 int total_data)
5900 uint32 mode;
5902 if (total_data < 4) {
5903 return NT_STATUS_INVALID_PARAMETER;
5905 mode = IVAL(pdata,0);
5906 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5907 return NT_STATUS_INVALID_PARAMETER;
5909 return NT_STATUS_OK;
5912 /****************************************************************************
5913 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5914 ****************************************************************************/
5916 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5917 struct smb_request *req,
5918 const char *pdata,
5919 int total_data,
5920 const struct smb_filename *smb_fname)
5922 char *link_target = NULL;
5923 const char *newname = smb_fname->base_name;
5924 TALLOC_CTX *ctx = talloc_tos();
5926 /* Set a symbolic link. */
5927 /* Don't allow this if follow links is false. */
5929 if (total_data == 0) {
5930 return NT_STATUS_INVALID_PARAMETER;
5933 if (!lp_symlinks(SNUM(conn))) {
5934 return NT_STATUS_ACCESS_DENIED;
5937 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5938 total_data, STR_TERMINATE);
5940 if (!link_target) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5945 newname, link_target ));
5947 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5948 return map_nt_error_from_unix(errno);
5951 return NT_STATUS_OK;
5954 /****************************************************************************
5955 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5956 ****************************************************************************/
5958 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5959 struct smb_request *req,
5960 const char *pdata, int total_data,
5961 struct smb_filename *smb_fname_new)
5963 char *oldname = NULL;
5964 struct smb_filename *smb_fname_old = NULL;
5965 TALLOC_CTX *ctx = talloc_tos();
5966 NTSTATUS status = NT_STATUS_OK;
5968 /* Set a hard link. */
5969 if (total_data == 0) {
5970 return NT_STATUS_INVALID_PARAMETER;
5973 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5974 total_data, STR_TERMINATE, &status);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 return status;
5979 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5980 smb_fname_str_dbg(smb_fname_new), oldname));
5982 status = filename_convert(ctx,
5983 conn,
5984 req->flags2 & FLAGS2_DFS_PATHNAMES,
5985 oldname,
5987 NULL,
5988 &smb_fname_old);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 return status;
5993 return hardlink_internals(ctx, conn, req, false,
5994 smb_fname_old, smb_fname_new);
5997 /****************************************************************************
5998 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5999 ****************************************************************************/
6001 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6002 struct smb_request *req,
6003 const char *pdata,
6004 int total_data,
6005 files_struct *fsp,
6006 struct smb_filename *smb_fname_src)
6008 bool overwrite;
6009 uint32_t len;
6010 char *newname = NULL;
6011 struct smb_filename *smb_fname_dst = NULL;
6012 NTSTATUS status = NT_STATUS_OK;
6013 TALLOC_CTX *ctx = talloc_tos();
6015 if (!fsp) {
6016 return NT_STATUS_INVALID_HANDLE;
6019 if (total_data < 20) {
6020 return NT_STATUS_INVALID_PARAMETER;
6023 overwrite = (CVAL(pdata,0) ? True : False);
6024 len = IVAL(pdata,16);
6026 if (len > (total_data - 20) || (len == 0)) {
6027 return NT_STATUS_INVALID_PARAMETER;
6030 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6031 &pdata[20], len, STR_TERMINATE,
6032 &status);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 return status;
6037 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6038 newname));
6040 status = filename_convert(ctx,
6041 conn,
6042 req->flags2 & FLAGS2_DFS_PATHNAMES,
6043 newname,
6044 UCF_SAVE_LCOMP,
6045 NULL,
6046 &smb_fname_dst);
6047 if (!NT_STATUS_IS_OK(status)) {
6048 return status;
6051 if (fsp->base_fsp) {
6052 /* newname must be a stream name. */
6053 if (newname[0] != ':') {
6054 return NT_STATUS_NOT_SUPPORTED;
6057 /* Create an smb_fname to call rename_internals_fsp() with. */
6058 status = create_synthetic_smb_fname(talloc_tos(),
6059 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6060 &smb_fname_dst);
6061 if (!NT_STATUS_IS_OK(status)) {
6062 goto out;
6066 * Set the original last component, since
6067 * rename_internals_fsp() requires it.
6069 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6070 newname);
6071 if (smb_fname_dst->original_lcomp == NULL) {
6072 status = NT_STATUS_NO_MEMORY;
6073 goto out;
6078 DEBUG(10,("smb2_file_rename_information: "
6079 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6080 fsp->fnum, fsp_str_dbg(fsp),
6081 smb_fname_str_dbg(smb_fname_dst)));
6082 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6083 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6084 overwrite);
6086 out:
6087 TALLOC_FREE(smb_fname_dst);
6088 return status;
6091 static NTSTATUS smb_file_link_information(connection_struct *conn,
6092 struct smb_request *req,
6093 const char *pdata,
6094 int total_data,
6095 files_struct *fsp,
6096 struct smb_filename *smb_fname_src)
6098 bool overwrite;
6099 uint32_t len;
6100 char *newname = NULL;
6101 struct smb_filename *smb_fname_dst = NULL;
6102 NTSTATUS status = NT_STATUS_OK;
6103 TALLOC_CTX *ctx = talloc_tos();
6105 if (!fsp) {
6106 return NT_STATUS_INVALID_HANDLE;
6109 if (total_data < 20) {
6110 return NT_STATUS_INVALID_PARAMETER;
6113 overwrite = (CVAL(pdata,0) ? true : false);
6114 len = IVAL(pdata,16);
6116 if (len > (total_data - 20) || (len == 0)) {
6117 return NT_STATUS_INVALID_PARAMETER;
6120 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6121 &pdata[20], len, STR_TERMINATE,
6122 &status);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 return status;
6127 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6128 newname));
6130 status = filename_convert(ctx,
6131 conn,
6132 req->flags2 & FLAGS2_DFS_PATHNAMES,
6133 newname,
6134 UCF_SAVE_LCOMP,
6135 NULL,
6136 &smb_fname_dst);
6137 if (!NT_STATUS_IS_OK(status)) {
6138 return status;
6141 if (fsp->base_fsp) {
6142 /* No stream names. */
6143 return NT_STATUS_NOT_SUPPORTED;
6146 DEBUG(10,("smb_file_link_information: "
6147 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6148 fsp->fnum, fsp_str_dbg(fsp),
6149 smb_fname_str_dbg(smb_fname_dst)));
6150 status = hardlink_internals(ctx,
6151 conn,
6152 req,
6153 overwrite,
6154 fsp->fsp_name,
6155 smb_fname_dst);
6157 TALLOC_FREE(smb_fname_dst);
6158 return status;
6161 /****************************************************************************
6162 Deal with SMB_FILE_RENAME_INFORMATION.
6163 ****************************************************************************/
6165 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6166 struct smb_request *req,
6167 const char *pdata,
6168 int total_data,
6169 files_struct *fsp,
6170 struct smb_filename *smb_fname_src)
6172 bool overwrite;
6173 uint32 root_fid;
6174 uint32 len;
6175 char *newname = NULL;
6176 struct smb_filename *smb_fname_dst = NULL;
6177 bool dest_has_wcard = False;
6178 NTSTATUS status = NT_STATUS_OK;
6179 char *p;
6180 TALLOC_CTX *ctx = talloc_tos();
6182 if (total_data < 13) {
6183 return NT_STATUS_INVALID_PARAMETER;
6186 overwrite = (CVAL(pdata,0) ? True : False);
6187 root_fid = IVAL(pdata,4);
6188 len = IVAL(pdata,8);
6190 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6191 return NT_STATUS_INVALID_PARAMETER;
6194 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6195 len, 0, &status,
6196 &dest_has_wcard);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 return status;
6201 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6202 newname));
6204 status = resolve_dfspath_wcard(ctx, conn,
6205 req->flags2 & FLAGS2_DFS_PATHNAMES,
6206 newname,
6207 true,
6208 &newname,
6209 &dest_has_wcard);
6210 if (!NT_STATUS_IS_OK(status)) {
6211 return status;
6214 /* Check the new name has no '/' characters. */
6215 if (strchr_m(newname, '/')) {
6216 return NT_STATUS_NOT_SUPPORTED;
6219 if (fsp && fsp->base_fsp) {
6220 /* newname must be a stream name. */
6221 if (newname[0] != ':') {
6222 return NT_STATUS_NOT_SUPPORTED;
6225 /* Create an smb_fname to call rename_internals_fsp() with. */
6226 status = create_synthetic_smb_fname(talloc_tos(),
6227 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6228 &smb_fname_dst);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 goto out;
6234 * Set the original last component, since
6235 * rename_internals_fsp() requires it.
6237 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6238 newname);
6239 if (smb_fname_dst->original_lcomp == NULL) {
6240 status = NT_STATUS_NO_MEMORY;
6241 goto out;
6244 } else {
6246 * Build up an smb_fname_dst based on the filename passed in.
6247 * We basically just strip off the last component, and put on
6248 * the newname instead.
6250 char *base_name = NULL;
6252 /* newname must *not* be a stream name. */
6253 if (newname[0] == ':') {
6254 return NT_STATUS_NOT_SUPPORTED;
6258 * Strip off the last component (filename) of the path passed
6259 * in.
6261 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6262 if (!base_name) {
6263 return NT_STATUS_NO_MEMORY;
6265 p = strrchr_m(base_name, '/');
6266 if (p) {
6267 p[1] = '\0';
6268 } else {
6269 base_name = talloc_strdup(ctx, "");
6270 if (!base_name) {
6271 return NT_STATUS_NO_MEMORY;
6274 /* Append the new name. */
6275 base_name = talloc_asprintf_append(base_name,
6276 "%s",
6277 newname);
6278 if (!base_name) {
6279 return NT_STATUS_NO_MEMORY;
6282 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6283 (UCF_SAVE_LCOMP |
6284 (dest_has_wcard ?
6285 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6286 0)));
6288 /* If an error we expect this to be
6289 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6291 if (!NT_STATUS_IS_OK(status)) {
6292 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6293 status)) {
6294 goto out;
6296 /* Create an smb_fname to call rename_internals_fsp() */
6297 status = create_synthetic_smb_fname(ctx,
6298 base_name, NULL,
6299 NULL,
6300 &smb_fname_dst);
6301 if (!NT_STATUS_IS_OK(status)) {
6302 goto out;
6307 if (fsp) {
6308 DEBUG(10,("smb_file_rename_information: "
6309 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6310 fsp->fnum, fsp_str_dbg(fsp),
6311 smb_fname_str_dbg(smb_fname_dst)));
6312 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6313 overwrite);
6314 } else {
6315 DEBUG(10,("smb_file_rename_information: "
6316 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6317 smb_fname_str_dbg(smb_fname_src),
6318 smb_fname_str_dbg(smb_fname_dst)));
6319 status = rename_internals(ctx, conn, req, smb_fname_src,
6320 smb_fname_dst, 0, overwrite, false,
6321 dest_has_wcard,
6322 FILE_WRITE_ATTRIBUTES);
6324 out:
6325 TALLOC_FREE(smb_fname_dst);
6326 return status;
6329 /****************************************************************************
6330 Deal with SMB_SET_POSIX_ACL.
6331 ****************************************************************************/
6333 #if defined(HAVE_POSIX_ACLS)
6334 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6335 const char *pdata,
6336 int total_data,
6337 files_struct *fsp,
6338 const struct smb_filename *smb_fname)
6340 uint16 posix_acl_version;
6341 uint16 num_file_acls;
6342 uint16 num_def_acls;
6343 bool valid_file_acls = True;
6344 bool valid_def_acls = True;
6346 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6347 return NT_STATUS_INVALID_PARAMETER;
6349 posix_acl_version = SVAL(pdata,0);
6350 num_file_acls = SVAL(pdata,2);
6351 num_def_acls = SVAL(pdata,4);
6353 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6354 valid_file_acls = False;
6355 num_file_acls = 0;
6358 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6359 valid_def_acls = False;
6360 num_def_acls = 0;
6363 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6364 return NT_STATUS_INVALID_PARAMETER;
6367 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6368 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6369 return NT_STATUS_INVALID_PARAMETER;
6372 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6373 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6374 (unsigned int)num_file_acls,
6375 (unsigned int)num_def_acls));
6377 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6378 smb_fname->base_name, num_file_acls,
6379 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6380 return map_nt_error_from_unix(errno);
6383 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6384 smb_fname->base_name, &smb_fname->st, num_def_acls,
6385 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6386 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6387 return map_nt_error_from_unix(errno);
6389 return NT_STATUS_OK;
6391 #endif
6393 /****************************************************************************
6394 Deal with SMB_SET_POSIX_LOCK.
6395 ****************************************************************************/
6397 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6398 struct smb_request *req,
6399 const char *pdata,
6400 int total_data,
6401 files_struct *fsp)
6403 uint64_t count;
6404 uint64_t offset;
6405 uint64_t smblctx;
6406 bool blocking_lock = False;
6407 enum brl_type lock_type;
6409 NTSTATUS status = NT_STATUS_OK;
6411 if (fsp == NULL || fsp->fh->fd == -1) {
6412 return NT_STATUS_INVALID_HANDLE;
6415 if (total_data != POSIX_LOCK_DATA_SIZE) {
6416 return NT_STATUS_INVALID_PARAMETER;
6419 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6420 case POSIX_LOCK_TYPE_READ:
6421 lock_type = READ_LOCK;
6422 break;
6423 case POSIX_LOCK_TYPE_WRITE:
6424 /* Return the right POSIX-mappable error code for files opened read-only. */
6425 if (!fsp->can_write) {
6426 return NT_STATUS_INVALID_HANDLE;
6428 lock_type = WRITE_LOCK;
6429 break;
6430 case POSIX_LOCK_TYPE_UNLOCK:
6431 lock_type = UNLOCK_LOCK;
6432 break;
6433 default:
6434 return NT_STATUS_INVALID_PARAMETER;
6437 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6438 blocking_lock = False;
6439 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6440 blocking_lock = True;
6441 } else {
6442 return NT_STATUS_INVALID_PARAMETER;
6445 if (!lp_blocking_locks(SNUM(conn))) {
6446 blocking_lock = False;
6449 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6450 #if defined(HAVE_LONGLONG)
6451 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6452 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6453 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6454 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6455 #else /* HAVE_LONGLONG */
6456 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6457 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6458 #endif /* HAVE_LONGLONG */
6460 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6461 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6462 fsp_str_dbg(fsp),
6463 (unsigned int)lock_type,
6464 (unsigned long long)smblctx,
6465 (double)count,
6466 (double)offset ));
6468 if (lock_type == UNLOCK_LOCK) {
6469 status = do_unlock(req->sconn->msg_ctx,
6470 fsp,
6471 smblctx,
6472 count,
6473 offset,
6474 POSIX_LOCK);
6475 } else {
6476 uint64_t block_smblctx;
6478 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6479 fsp,
6480 smblctx,
6481 count,
6482 offset,
6483 lock_type,
6484 POSIX_LOCK,
6485 blocking_lock,
6486 &status,
6487 &block_smblctx,
6488 NULL);
6490 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6492 * A blocking lock was requested. Package up
6493 * this smb into a queued request and push it
6494 * onto the blocking lock queue.
6496 if(push_blocking_lock_request(br_lck,
6497 req,
6498 fsp,
6499 -1, /* infinite timeout. */
6501 smblctx,
6502 lock_type,
6503 POSIX_LOCK,
6504 offset,
6505 count,
6506 block_smblctx)) {
6507 TALLOC_FREE(br_lck);
6508 return status;
6511 TALLOC_FREE(br_lck);
6514 return status;
6517 /****************************************************************************
6518 Deal with SMB_SET_FILE_BASIC_INFO.
6519 ****************************************************************************/
6521 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6522 const char *pdata,
6523 int total_data,
6524 files_struct *fsp,
6525 const struct smb_filename *smb_fname)
6527 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6528 struct smb_file_time ft;
6529 uint32 dosmode = 0;
6530 NTSTATUS status = NT_STATUS_OK;
6532 ZERO_STRUCT(ft);
6534 if (total_data < 36) {
6535 return NT_STATUS_INVALID_PARAMETER;
6538 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 return status;
6543 /* Set the attributes */
6544 dosmode = IVAL(pdata,32);
6545 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6546 if (!NT_STATUS_IS_OK(status)) {
6547 return status;
6550 /* create time */
6551 ft.create_time = interpret_long_date(pdata);
6553 /* access time */
6554 ft.atime = interpret_long_date(pdata+8);
6556 /* write time. */
6557 ft.mtime = interpret_long_date(pdata+16);
6559 /* change time. */
6560 ft.ctime = interpret_long_date(pdata+24);
6562 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6563 smb_fname_str_dbg(smb_fname)));
6565 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6566 true);
6569 /****************************************************************************
6570 Deal with SMB_INFO_STANDARD.
6571 ****************************************************************************/
6573 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6574 const char *pdata,
6575 int total_data,
6576 files_struct *fsp,
6577 const struct smb_filename *smb_fname)
6579 NTSTATUS status;
6580 struct smb_file_time ft;
6582 ZERO_STRUCT(ft);
6584 if (total_data < 12) {
6585 return NT_STATUS_INVALID_PARAMETER;
6588 /* create time */
6589 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6590 /* access time */
6591 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6592 /* write time */
6593 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6595 DEBUG(10,("smb_set_info_standard: file %s\n",
6596 smb_fname_str_dbg(smb_fname)));
6598 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 return status;
6603 return smb_set_file_time(conn,
6604 fsp,
6605 smb_fname,
6606 &ft,
6607 true);
6610 /****************************************************************************
6611 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6612 ****************************************************************************/
6614 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6615 struct smb_request *req,
6616 const char *pdata,
6617 int total_data,
6618 files_struct *fsp,
6619 struct smb_filename *smb_fname)
6621 uint64_t allocation_size = 0;
6622 NTSTATUS status = NT_STATUS_OK;
6623 files_struct *new_fsp = NULL;
6625 if (!VALID_STAT(smb_fname->st)) {
6626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6629 if (total_data < 8) {
6630 return NT_STATUS_INVALID_PARAMETER;
6633 allocation_size = (uint64_t)IVAL(pdata,0);
6634 #ifdef LARGE_SMB_OFF_T
6635 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6636 #else /* LARGE_SMB_OFF_T */
6637 if (IVAL(pdata,4) != 0) {
6638 /* more than 32 bits? */
6639 return NT_STATUS_INVALID_PARAMETER;
6641 #endif /* LARGE_SMB_OFF_T */
6643 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6644 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6645 (double)allocation_size));
6647 if (allocation_size) {
6648 allocation_size = smb_roundup(conn, allocation_size);
6651 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6652 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6653 (double)allocation_size));
6655 if (fsp && fsp->fh->fd != -1) {
6656 /* Open file handle. */
6657 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6658 return NT_STATUS_ACCESS_DENIED;
6661 /* Only change if needed. */
6662 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6663 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6664 return map_nt_error_from_unix(errno);
6667 /* But always update the time. */
6669 * This is equivalent to a write. Ensure it's seen immediately
6670 * if there are no pending writes.
6672 trigger_write_time_update_immediate(fsp);
6673 return NT_STATUS_OK;
6676 /* Pathname or stat or directory file. */
6677 status = SMB_VFS_CREATE_FILE(
6678 conn, /* conn */
6679 req, /* req */
6680 0, /* root_dir_fid */
6681 smb_fname, /* fname */
6682 FILE_WRITE_DATA, /* access_mask */
6683 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6684 FILE_SHARE_DELETE),
6685 FILE_OPEN, /* create_disposition*/
6686 0, /* create_options */
6687 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6688 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6689 0, /* allocation_size */
6690 0, /* private_flags */
6691 NULL, /* sd */
6692 NULL, /* ea_list */
6693 &new_fsp, /* result */
6694 NULL); /* pinfo */
6696 if (!NT_STATUS_IS_OK(status)) {
6697 /* NB. We check for open_was_deferred in the caller. */
6698 return status;
6701 /* Only change if needed. */
6702 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6703 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6704 status = map_nt_error_from_unix(errno);
6705 close_file(req, new_fsp, NORMAL_CLOSE);
6706 return status;
6710 /* Changing the allocation size should set the last mod time. */
6712 * This is equivalent to a write. Ensure it's seen immediately
6713 * if there are no pending writes.
6715 trigger_write_time_update_immediate(new_fsp);
6717 close_file(req, new_fsp, NORMAL_CLOSE);
6718 return NT_STATUS_OK;
6721 /****************************************************************************
6722 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6723 ****************************************************************************/
6725 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6726 struct smb_request *req,
6727 const char *pdata,
6728 int total_data,
6729 files_struct *fsp,
6730 const struct smb_filename *smb_fname,
6731 bool fail_after_createfile)
6733 SMB_OFF_T size;
6735 if (total_data < 8) {
6736 return NT_STATUS_INVALID_PARAMETER;
6739 size = IVAL(pdata,0);
6740 #ifdef LARGE_SMB_OFF_T
6741 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6742 #else /* LARGE_SMB_OFF_T */
6743 if (IVAL(pdata,4) != 0) {
6744 /* more than 32 bits? */
6745 return NT_STATUS_INVALID_PARAMETER;
6747 #endif /* LARGE_SMB_OFF_T */
6748 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6749 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6750 (double)size));
6752 return smb_set_file_size(conn, req,
6753 fsp,
6754 smb_fname,
6755 &smb_fname->st,
6756 size,
6757 fail_after_createfile);
6760 /****************************************************************************
6761 Allow a UNIX info mknod.
6762 ****************************************************************************/
6764 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6765 const char *pdata,
6766 int total_data,
6767 const struct smb_filename *smb_fname)
6769 uint32 file_type = IVAL(pdata,56);
6770 #if defined(HAVE_MAKEDEV)
6771 uint32 dev_major = IVAL(pdata,60);
6772 uint32 dev_minor = IVAL(pdata,68);
6773 #endif
6774 SMB_DEV_T dev = (SMB_DEV_T)0;
6775 uint32 raw_unixmode = IVAL(pdata,84);
6776 NTSTATUS status;
6777 mode_t unixmode;
6779 if (total_data < 100) {
6780 return NT_STATUS_INVALID_PARAMETER;
6783 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6784 PERM_NEW_FILE, &unixmode);
6785 if (!NT_STATUS_IS_OK(status)) {
6786 return status;
6789 #if defined(HAVE_MAKEDEV)
6790 dev = makedev(dev_major, dev_minor);
6791 #endif
6793 switch (file_type) {
6794 #if defined(S_IFIFO)
6795 case UNIX_TYPE_FIFO:
6796 unixmode |= S_IFIFO;
6797 break;
6798 #endif
6799 #if defined(S_IFSOCK)
6800 case UNIX_TYPE_SOCKET:
6801 unixmode |= S_IFSOCK;
6802 break;
6803 #endif
6804 #if defined(S_IFCHR)
6805 case UNIX_TYPE_CHARDEV:
6806 unixmode |= S_IFCHR;
6807 break;
6808 #endif
6809 #if defined(S_IFBLK)
6810 case UNIX_TYPE_BLKDEV:
6811 unixmode |= S_IFBLK;
6812 break;
6813 #endif
6814 default:
6815 return NT_STATUS_INVALID_PARAMETER;
6818 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6819 "%.0f mode 0%o for file %s\n", (double)dev,
6820 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6822 /* Ok - do the mknod. */
6823 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6824 return map_nt_error_from_unix(errno);
6827 /* If any of the other "set" calls fail we
6828 * don't want to end up with a half-constructed mknod.
6831 if (lp_inherit_perms(SNUM(conn))) {
6832 char *parent;
6833 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6834 &parent, NULL)) {
6835 return NT_STATUS_NO_MEMORY;
6837 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6838 unixmode);
6839 TALLOC_FREE(parent);
6842 return NT_STATUS_OK;
6845 /****************************************************************************
6846 Deal with SMB_SET_FILE_UNIX_BASIC.
6847 ****************************************************************************/
6849 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6850 struct smb_request *req,
6851 const char *pdata,
6852 int total_data,
6853 files_struct *fsp,
6854 const struct smb_filename *smb_fname)
6856 struct smb_file_time ft;
6857 uint32 raw_unixmode;
6858 mode_t unixmode;
6859 SMB_OFF_T size = 0;
6860 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6861 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6862 NTSTATUS status = NT_STATUS_OK;
6863 bool delete_on_fail = False;
6864 enum perm_type ptype;
6865 files_struct *all_fsps = NULL;
6866 bool modify_mtime = true;
6867 struct file_id id;
6868 struct smb_filename *smb_fname_tmp = NULL;
6869 SMB_STRUCT_STAT sbuf;
6871 ZERO_STRUCT(ft);
6873 if (total_data < 100) {
6874 return NT_STATUS_INVALID_PARAMETER;
6877 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6878 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6879 size=IVAL(pdata,0); /* first 8 Bytes are size */
6880 #ifdef LARGE_SMB_OFF_T
6881 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6882 #else /* LARGE_SMB_OFF_T */
6883 if (IVAL(pdata,4) != 0) {
6884 /* more than 32 bits? */
6885 return NT_STATUS_INVALID_PARAMETER;
6887 #endif /* LARGE_SMB_OFF_T */
6890 ft.atime = interpret_long_date(pdata+24); /* access_time */
6891 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6892 set_owner = (uid_t)IVAL(pdata,40);
6893 set_grp = (gid_t)IVAL(pdata,48);
6894 raw_unixmode = IVAL(pdata,84);
6896 if (VALID_STAT(smb_fname->st)) {
6897 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6898 ptype = PERM_EXISTING_DIR;
6899 } else {
6900 ptype = PERM_EXISTING_FILE;
6902 } else {
6903 ptype = PERM_NEW_FILE;
6906 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6907 ptype, &unixmode);
6908 if (!NT_STATUS_IS_OK(status)) {
6909 return status;
6912 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6913 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6914 smb_fname_str_dbg(smb_fname), (double)size,
6915 (unsigned int)set_owner, (unsigned int)set_grp,
6916 (int)raw_unixmode));
6918 sbuf = smb_fname->st;
6920 if (!VALID_STAT(sbuf)) {
6922 * The only valid use of this is to create character and block
6923 * devices, and named pipes. This is deprecated (IMHO) and
6924 * a new info level should be used for mknod. JRA.
6927 status = smb_unix_mknod(conn,
6928 pdata,
6929 total_data,
6930 smb_fname);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 return status;
6935 status = copy_smb_filename(talloc_tos(), smb_fname,
6936 &smb_fname_tmp);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 return status;
6941 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6942 status = map_nt_error_from_unix(errno);
6943 TALLOC_FREE(smb_fname_tmp);
6944 SMB_VFS_UNLINK(conn, smb_fname);
6945 return status;
6948 sbuf = smb_fname_tmp->st;
6949 smb_fname = smb_fname_tmp;
6951 /* Ensure we don't try and change anything else. */
6952 raw_unixmode = SMB_MODE_NO_CHANGE;
6953 size = get_file_size_stat(&sbuf);
6954 ft.atime = sbuf.st_ex_atime;
6955 ft.mtime = sbuf.st_ex_mtime;
6957 * We continue here as we might want to change the
6958 * owner uid/gid.
6960 delete_on_fail = True;
6963 #if 1
6964 /* Horrible backwards compatibility hack as an old server bug
6965 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6966 * */
6968 if (!size) {
6969 size = get_file_size_stat(&sbuf);
6971 #endif
6973 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6974 if (!NT_STATUS_IS_OK(status)) {
6975 return status;
6979 * Deal with the UNIX specific mode set.
6982 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6983 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6984 "setting mode 0%o for file %s\n",
6985 (unsigned int)unixmode,
6986 smb_fname_str_dbg(smb_fname)));
6987 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6988 return map_nt_error_from_unix(errno);
6993 * Deal with the UNIX specific uid set.
6996 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6997 (sbuf.st_ex_uid != set_owner)) {
6998 int ret;
7000 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7001 "changing owner %u for path %s\n",
7002 (unsigned int)set_owner,
7003 smb_fname_str_dbg(smb_fname)));
7005 if (S_ISLNK(sbuf.st_ex_mode)) {
7006 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7007 set_owner, (gid_t)-1);
7008 } else {
7009 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7010 set_owner, (gid_t)-1);
7013 if (ret != 0) {
7014 status = map_nt_error_from_unix(errno);
7015 if (delete_on_fail) {
7016 SMB_VFS_UNLINK(conn, smb_fname);
7018 return status;
7023 * Deal with the UNIX specific gid set.
7026 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7027 (sbuf.st_ex_gid != set_grp)) {
7028 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7029 "changing group %u for file %s\n",
7030 (unsigned int)set_owner,
7031 smb_fname_str_dbg(smb_fname)));
7032 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7033 set_grp) != 0) {
7034 status = map_nt_error_from_unix(errno);
7035 if (delete_on_fail) {
7036 SMB_VFS_UNLINK(conn, smb_fname);
7038 return status;
7042 /* Deal with any size changes. */
7044 status = smb_set_file_size(conn, req,
7045 fsp,
7046 smb_fname,
7047 &sbuf,
7048 size,
7049 false);
7050 if (!NT_STATUS_IS_OK(status)) {
7051 return status;
7054 /* Deal with any time changes. */
7055 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7056 /* No change, don't cancel anything. */
7057 return status;
7060 id = vfs_file_id_from_sbuf(conn, &sbuf);
7061 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7062 all_fsps = file_find_di_next(all_fsps)) {
7064 * We're setting the time explicitly for UNIX.
7065 * Cancel any pending changes over all handles.
7067 all_fsps->update_write_time_on_close = false;
7068 TALLOC_FREE(all_fsps->update_write_time_event);
7072 * Override the "setting_write_time"
7073 * parameter here as it almost does what
7074 * we need. Just remember if we modified
7075 * mtime and send the notify ourselves.
7077 if (null_timespec(ft.mtime)) {
7078 modify_mtime = false;
7081 status = smb_set_file_time(conn,
7082 fsp,
7083 smb_fname,
7084 &ft,
7085 false);
7086 if (modify_mtime) {
7087 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7088 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7090 return status;
7093 /****************************************************************************
7094 Deal with SMB_SET_FILE_UNIX_INFO2.
7095 ****************************************************************************/
7097 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7098 struct smb_request *req,
7099 const char *pdata,
7100 int total_data,
7101 files_struct *fsp,
7102 const struct smb_filename *smb_fname)
7104 NTSTATUS status;
7105 uint32 smb_fflags;
7106 uint32 smb_fmask;
7108 if (total_data < 116) {
7109 return NT_STATUS_INVALID_PARAMETER;
7112 /* Start by setting all the fields that are common between UNIX_BASIC
7113 * and UNIX_INFO2.
7115 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7116 fsp, smb_fname);
7117 if (!NT_STATUS_IS_OK(status)) {
7118 return status;
7121 smb_fflags = IVAL(pdata, 108);
7122 smb_fmask = IVAL(pdata, 112);
7124 /* NB: We should only attempt to alter the file flags if the client
7125 * sends a non-zero mask.
7127 if (smb_fmask != 0) {
7128 int stat_fflags = 0;
7130 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7131 smb_fmask, &stat_fflags)) {
7132 /* Client asked to alter a flag we don't understand. */
7133 return NT_STATUS_INVALID_PARAMETER;
7136 if (fsp && fsp->fh->fd != -1) {
7137 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7138 return NT_STATUS_NOT_SUPPORTED;
7139 } else {
7140 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7141 stat_fflags) != 0) {
7142 return map_nt_error_from_unix(errno);
7147 /* XXX: need to add support for changing the create_time here. You
7148 * can do this for paths on Darwin with setattrlist(2). The right way
7149 * to hook this up is probably by extending the VFS utimes interface.
7152 return NT_STATUS_OK;
7155 /****************************************************************************
7156 Create a directory with POSIX semantics.
7157 ****************************************************************************/
7159 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7160 struct smb_request *req,
7161 char **ppdata,
7162 int total_data,
7163 struct smb_filename *smb_fname,
7164 int *pdata_return_size)
7166 NTSTATUS status = NT_STATUS_OK;
7167 uint32 raw_unixmode = 0;
7168 uint32 mod_unixmode = 0;
7169 mode_t unixmode = (mode_t)0;
7170 files_struct *fsp = NULL;
7171 uint16 info_level_return = 0;
7172 int info;
7173 char *pdata = *ppdata;
7175 if (total_data < 18) {
7176 return NT_STATUS_INVALID_PARAMETER;
7179 raw_unixmode = IVAL(pdata,8);
7180 /* Next 4 bytes are not yet defined. */
7182 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7183 PERM_NEW_DIR, &unixmode);
7184 if (!NT_STATUS_IS_OK(status)) {
7185 return status;
7188 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7190 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7191 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7193 status = SMB_VFS_CREATE_FILE(
7194 conn, /* conn */
7195 req, /* req */
7196 0, /* root_dir_fid */
7197 smb_fname, /* fname */
7198 FILE_READ_ATTRIBUTES, /* access_mask */
7199 FILE_SHARE_NONE, /* share_access */
7200 FILE_CREATE, /* create_disposition*/
7201 FILE_DIRECTORY_FILE, /* create_options */
7202 mod_unixmode, /* file_attributes */
7203 0, /* oplock_request */
7204 0, /* allocation_size */
7205 0, /* private_flags */
7206 NULL, /* sd */
7207 NULL, /* ea_list */
7208 &fsp, /* result */
7209 &info); /* pinfo */
7211 if (NT_STATUS_IS_OK(status)) {
7212 close_file(req, fsp, NORMAL_CLOSE);
7215 info_level_return = SVAL(pdata,16);
7217 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7218 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7219 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7220 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7221 } else {
7222 *pdata_return_size = 12;
7225 /* Realloc the data size */
7226 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7227 if (*ppdata == NULL) {
7228 *pdata_return_size = 0;
7229 return NT_STATUS_NO_MEMORY;
7231 pdata = *ppdata;
7233 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7234 SSVAL(pdata,2,0); /* No fnum. */
7235 SIVAL(pdata,4,info); /* Was directory created. */
7237 switch (info_level_return) {
7238 case SMB_QUERY_FILE_UNIX_BASIC:
7239 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7240 SSVAL(pdata,10,0); /* Padding. */
7241 store_file_unix_basic(conn, pdata + 12, fsp,
7242 &smb_fname->st);
7243 break;
7244 case SMB_QUERY_FILE_UNIX_INFO2:
7245 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7246 SSVAL(pdata,10,0); /* Padding. */
7247 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7248 &smb_fname->st);
7249 break;
7250 default:
7251 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7252 SSVAL(pdata,10,0); /* Padding. */
7253 break;
7256 return status;
7259 /****************************************************************************
7260 Open/Create a file with POSIX semantics.
7261 ****************************************************************************/
7263 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7264 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7266 static NTSTATUS smb_posix_open(connection_struct *conn,
7267 struct smb_request *req,
7268 char **ppdata,
7269 int total_data,
7270 struct smb_filename *smb_fname,
7271 int *pdata_return_size)
7273 bool extended_oplock_granted = False;
7274 char *pdata = *ppdata;
7275 uint32 flags = 0;
7276 uint32 wire_open_mode = 0;
7277 uint32 raw_unixmode = 0;
7278 uint32 mod_unixmode = 0;
7279 uint32 create_disp = 0;
7280 uint32 access_mask = 0;
7281 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7282 NTSTATUS status = NT_STATUS_OK;
7283 mode_t unixmode = (mode_t)0;
7284 files_struct *fsp = NULL;
7285 int oplock_request = 0;
7286 int info = 0;
7287 uint16 info_level_return = 0;
7289 if (total_data < 18) {
7290 return NT_STATUS_INVALID_PARAMETER;
7293 flags = IVAL(pdata,0);
7294 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7295 if (oplock_request) {
7296 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7299 wire_open_mode = IVAL(pdata,4);
7301 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7302 return smb_posix_mkdir(conn, req,
7303 ppdata,
7304 total_data,
7305 smb_fname,
7306 pdata_return_size);
7309 switch (wire_open_mode & SMB_ACCMODE) {
7310 case SMB_O_RDONLY:
7311 access_mask = SMB_O_RDONLY_MAPPING;
7312 break;
7313 case SMB_O_WRONLY:
7314 access_mask = SMB_O_WRONLY_MAPPING;
7315 break;
7316 case SMB_O_RDWR:
7317 access_mask = (SMB_O_RDONLY_MAPPING|
7318 SMB_O_WRONLY_MAPPING);
7319 break;
7320 default:
7321 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7322 (unsigned int)wire_open_mode ));
7323 return NT_STATUS_INVALID_PARAMETER;
7326 wire_open_mode &= ~SMB_ACCMODE;
7328 /* First take care of O_CREAT|O_EXCL interactions. */
7329 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7330 case (SMB_O_CREAT | SMB_O_EXCL):
7331 /* File exists fail. File not exist create. */
7332 create_disp = FILE_CREATE;
7333 break;
7334 case SMB_O_CREAT:
7335 /* File exists open. File not exist create. */
7336 create_disp = FILE_OPEN_IF;
7337 break;
7338 case 0:
7339 /* File exists open. File not exist fail. */
7340 create_disp = FILE_OPEN;
7341 break;
7342 case SMB_O_EXCL:
7343 /* O_EXCL on its own without O_CREAT is undefined. */
7344 default:
7345 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7346 (unsigned int)wire_open_mode ));
7347 return NT_STATUS_INVALID_PARAMETER;
7350 /* Next factor in the effects of O_TRUNC. */
7351 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7353 if (wire_open_mode & SMB_O_TRUNC) {
7354 switch (create_disp) {
7355 case FILE_CREATE:
7356 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7357 /* Leave create_disp alone as
7358 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7360 /* File exists fail. File not exist create. */
7361 break;
7362 case FILE_OPEN_IF:
7363 /* SMB_O_CREAT | SMB_O_TRUNC */
7364 /* File exists overwrite. File not exist create. */
7365 create_disp = FILE_OVERWRITE_IF;
7366 break;
7367 case FILE_OPEN:
7368 /* SMB_O_TRUNC */
7369 /* File exists overwrite. File not exist fail. */
7370 create_disp = FILE_OVERWRITE;
7371 break;
7372 default:
7373 /* Cannot get here. */
7374 smb_panic("smb_posix_open: logic error");
7375 return NT_STATUS_INVALID_PARAMETER;
7379 raw_unixmode = IVAL(pdata,8);
7380 /* Next 4 bytes are not yet defined. */
7382 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7383 (VALID_STAT(smb_fname->st) ?
7384 PERM_EXISTING_FILE : PERM_NEW_FILE),
7385 &unixmode);
7387 if (!NT_STATUS_IS_OK(status)) {
7388 return status;
7391 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7393 if (wire_open_mode & SMB_O_SYNC) {
7394 create_options |= FILE_WRITE_THROUGH;
7396 if (wire_open_mode & SMB_O_APPEND) {
7397 access_mask |= FILE_APPEND_DATA;
7399 if (wire_open_mode & SMB_O_DIRECT) {
7400 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7403 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7404 VALID_STAT_OF_DIR(smb_fname->st)) {
7405 if (access_mask != SMB_O_RDONLY_MAPPING) {
7406 return NT_STATUS_FILE_IS_A_DIRECTORY;
7408 create_options &= ~FILE_NON_DIRECTORY_FILE;
7409 create_options |= FILE_DIRECTORY_FILE;
7412 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7413 smb_fname_str_dbg(smb_fname),
7414 (unsigned int)wire_open_mode,
7415 (unsigned int)unixmode ));
7417 status = SMB_VFS_CREATE_FILE(
7418 conn, /* conn */
7419 req, /* req */
7420 0, /* root_dir_fid */
7421 smb_fname, /* fname */
7422 access_mask, /* access_mask */
7423 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7424 FILE_SHARE_DELETE),
7425 create_disp, /* create_disposition*/
7426 create_options, /* create_options */
7427 mod_unixmode, /* file_attributes */
7428 oplock_request, /* oplock_request */
7429 0, /* allocation_size */
7430 0, /* private_flags */
7431 NULL, /* sd */
7432 NULL, /* ea_list */
7433 &fsp, /* result */
7434 &info); /* pinfo */
7436 if (!NT_STATUS_IS_OK(status)) {
7437 return status;
7440 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7441 extended_oplock_granted = True;
7444 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7445 extended_oplock_granted = True;
7448 info_level_return = SVAL(pdata,16);
7450 /* Allocate the correct return size. */
7452 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7453 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7454 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7455 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7456 } else {
7457 *pdata_return_size = 12;
7460 /* Realloc the data size */
7461 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7462 if (*ppdata == NULL) {
7463 close_file(req, fsp, ERROR_CLOSE);
7464 *pdata_return_size = 0;
7465 return NT_STATUS_NO_MEMORY;
7467 pdata = *ppdata;
7469 if (extended_oplock_granted) {
7470 if (flags & REQUEST_BATCH_OPLOCK) {
7471 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7472 } else {
7473 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7475 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7476 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7477 } else {
7478 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7481 SSVAL(pdata,2,fsp->fnum);
7482 SIVAL(pdata,4,info); /* Was file created etc. */
7484 switch (info_level_return) {
7485 case SMB_QUERY_FILE_UNIX_BASIC:
7486 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7487 SSVAL(pdata,10,0); /* padding. */
7488 store_file_unix_basic(conn, pdata + 12, fsp,
7489 &smb_fname->st);
7490 break;
7491 case SMB_QUERY_FILE_UNIX_INFO2:
7492 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7493 SSVAL(pdata,10,0); /* padding. */
7494 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7495 &smb_fname->st);
7496 break;
7497 default:
7498 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7499 SSVAL(pdata,10,0); /* padding. */
7500 break;
7502 return NT_STATUS_OK;
7505 /****************************************************************************
7506 Delete a file with POSIX semantics.
7507 ****************************************************************************/
7509 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7510 struct smb_request *req,
7511 const char *pdata,
7512 int total_data,
7513 struct smb_filename *smb_fname)
7515 NTSTATUS status = NT_STATUS_OK;
7516 files_struct *fsp = NULL;
7517 uint16 flags = 0;
7518 char del = 1;
7519 int info = 0;
7520 int create_options = 0;
7521 int i;
7522 struct share_mode_lock *lck = NULL;
7524 if (total_data < 2) {
7525 return NT_STATUS_INVALID_PARAMETER;
7528 flags = SVAL(pdata,0);
7530 if (!VALID_STAT(smb_fname->st)) {
7531 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7534 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7535 !VALID_STAT_OF_DIR(smb_fname->st)) {
7536 return NT_STATUS_NOT_A_DIRECTORY;
7539 DEBUG(10,("smb_posix_unlink: %s %s\n",
7540 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7541 smb_fname_str_dbg(smb_fname)));
7543 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7544 create_options |= FILE_DIRECTORY_FILE;
7547 status = SMB_VFS_CREATE_FILE(
7548 conn, /* conn */
7549 req, /* req */
7550 0, /* root_dir_fid */
7551 smb_fname, /* fname */
7552 DELETE_ACCESS, /* access_mask */
7553 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7554 FILE_SHARE_DELETE),
7555 FILE_OPEN, /* create_disposition*/
7556 create_options, /* create_options */
7557 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7558 0, /* oplock_request */
7559 0, /* allocation_size */
7560 0, /* private_flags */
7561 NULL, /* sd */
7562 NULL, /* ea_list */
7563 &fsp, /* result */
7564 &info); /* pinfo */
7566 if (!NT_STATUS_IS_OK(status)) {
7567 return status;
7571 * Don't lie to client. If we can't really delete due to
7572 * non-POSIX opens return SHARING_VIOLATION.
7575 lck = get_share_mode_lock(talloc_tos(), fsp->file_id);
7576 if (lck == NULL) {
7577 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7578 "lock for file %s\n", fsp_str_dbg(fsp)));
7579 close_file(req, fsp, NORMAL_CLOSE);
7580 return NT_STATUS_INVALID_PARAMETER;
7584 * See if others still have the file open. If this is the case, then
7585 * don't delete. If all opens are POSIX delete we can set the delete
7586 * on close disposition.
7588 for (i=0; i<lck->data->num_share_modes; i++) {
7589 struct share_mode_entry *e = &lck->data->share_modes[i];
7590 if (is_valid_share_mode_entry(e)) {
7591 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7592 continue;
7594 /* Fail with sharing violation. */
7595 close_file(req, fsp, NORMAL_CLOSE);
7596 TALLOC_FREE(lck);
7597 return NT_STATUS_SHARING_VIOLATION;
7602 * Set the delete on close.
7604 status = smb_set_file_disposition_info(conn,
7605 &del,
7607 fsp,
7608 smb_fname);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 close_file(req, fsp, NORMAL_CLOSE);
7612 TALLOC_FREE(lck);
7613 return status;
7615 TALLOC_FREE(lck);
7616 return close_file(req, fsp, NORMAL_CLOSE);
7619 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7620 struct smb_request *req,
7621 TALLOC_CTX *mem_ctx,
7622 uint16_t info_level,
7623 files_struct *fsp,
7624 struct smb_filename *smb_fname,
7625 char **ppdata, int total_data,
7626 int *ret_data_size)
7628 char *pdata = *ppdata;
7629 NTSTATUS status = NT_STATUS_OK;
7630 int data_return_size = 0;
7632 *ret_data_size = 0;
7634 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7635 return NT_STATUS_INVALID_LEVEL;
7638 if (!CAN_WRITE(conn)) {
7639 /* Allow POSIX opens. The open path will deny
7640 * any non-readonly opens. */
7641 if (info_level != SMB_POSIX_PATH_OPEN) {
7642 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7646 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7647 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7648 fsp ? fsp->fnum : -1, info_level, total_data));
7650 switch (info_level) {
7652 case SMB_INFO_STANDARD:
7654 status = smb_set_info_standard(conn,
7655 pdata,
7656 total_data,
7657 fsp,
7658 smb_fname);
7659 break;
7662 case SMB_INFO_SET_EA:
7664 status = smb_info_set_ea(conn,
7665 pdata,
7666 total_data,
7667 fsp,
7668 smb_fname);
7669 break;
7672 case SMB_SET_FILE_BASIC_INFO:
7673 case SMB_FILE_BASIC_INFORMATION:
7675 status = smb_set_file_basic_info(conn,
7676 pdata,
7677 total_data,
7678 fsp,
7679 smb_fname);
7680 break;
7683 case SMB_FILE_ALLOCATION_INFORMATION:
7684 case SMB_SET_FILE_ALLOCATION_INFO:
7686 status = smb_set_file_allocation_info(conn, req,
7687 pdata,
7688 total_data,
7689 fsp,
7690 smb_fname);
7691 break;
7694 case SMB_FILE_END_OF_FILE_INFORMATION:
7695 case SMB_SET_FILE_END_OF_FILE_INFO:
7698 * XP/Win7 both fail after the createfile with
7699 * SMB_SET_FILE_END_OF_FILE_INFO but not
7700 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7701 * The level is known here, so pass it down
7702 * appropriately.
7704 bool should_fail =
7705 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7707 status = smb_set_file_end_of_file_info(conn, req,
7708 pdata,
7709 total_data,
7710 fsp,
7711 smb_fname,
7712 should_fail);
7713 break;
7716 case SMB_FILE_DISPOSITION_INFORMATION:
7717 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7719 #if 0
7720 /* JRA - We used to just ignore this on a path ?
7721 * Shouldn't this be invalid level on a pathname
7722 * based call ?
7724 if (tran_call != TRANSACT2_SETFILEINFO) {
7725 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7727 #endif
7728 status = smb_set_file_disposition_info(conn,
7729 pdata,
7730 total_data,
7731 fsp,
7732 smb_fname);
7733 break;
7736 case SMB_FILE_POSITION_INFORMATION:
7738 status = smb_file_position_information(conn,
7739 pdata,
7740 total_data,
7741 fsp);
7742 break;
7745 case SMB_FILE_FULL_EA_INFORMATION:
7747 status = smb_set_file_full_ea_info(conn,
7748 pdata,
7749 total_data,
7750 fsp);
7751 break;
7754 /* From tridge Samba4 :
7755 * MODE_INFORMATION in setfileinfo (I have no
7756 * idea what "mode information" on a file is - it takes a value of 0,
7757 * 2, 4 or 6. What could it be?).
7760 case SMB_FILE_MODE_INFORMATION:
7762 status = smb_file_mode_information(conn,
7763 pdata,
7764 total_data);
7765 break;
7769 * CIFS UNIX extensions.
7772 case SMB_SET_FILE_UNIX_BASIC:
7774 status = smb_set_file_unix_basic(conn, req,
7775 pdata,
7776 total_data,
7777 fsp,
7778 smb_fname);
7779 break;
7782 case SMB_SET_FILE_UNIX_INFO2:
7784 status = smb_set_file_unix_info2(conn, req,
7785 pdata,
7786 total_data,
7787 fsp,
7788 smb_fname);
7789 break;
7792 case SMB_SET_FILE_UNIX_LINK:
7794 if (fsp) {
7795 /* We must have a pathname for this. */
7796 return NT_STATUS_INVALID_LEVEL;
7798 status = smb_set_file_unix_link(conn, req, pdata,
7799 total_data, smb_fname);
7800 break;
7803 case SMB_SET_FILE_UNIX_HLINK:
7805 if (fsp) {
7806 /* We must have a pathname for this. */
7807 return NT_STATUS_INVALID_LEVEL;
7809 status = smb_set_file_unix_hlink(conn, req,
7810 pdata, total_data,
7811 smb_fname);
7812 break;
7815 case SMB_FILE_RENAME_INFORMATION:
7817 status = smb_file_rename_information(conn, req,
7818 pdata, total_data,
7819 fsp, smb_fname);
7820 break;
7823 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7825 /* SMB2 rename information. */
7826 status = smb2_file_rename_information(conn, req,
7827 pdata, total_data,
7828 fsp, smb_fname);
7829 break;
7832 case SMB_FILE_LINK_INFORMATION:
7834 status = smb_file_link_information(conn, req,
7835 pdata, total_data,
7836 fsp, smb_fname);
7837 break;
7840 #if defined(HAVE_POSIX_ACLS)
7841 case SMB_SET_POSIX_ACL:
7843 status = smb_set_posix_acl(conn,
7844 pdata,
7845 total_data,
7846 fsp,
7847 smb_fname);
7848 break;
7850 #endif
7852 case SMB_SET_POSIX_LOCK:
7854 if (!fsp) {
7855 return NT_STATUS_INVALID_LEVEL;
7857 status = smb_set_posix_lock(conn, req,
7858 pdata, total_data, fsp);
7859 break;
7862 case SMB_POSIX_PATH_OPEN:
7864 if (fsp) {
7865 /* We must have a pathname for this. */
7866 return NT_STATUS_INVALID_LEVEL;
7869 status = smb_posix_open(conn, req,
7870 ppdata,
7871 total_data,
7872 smb_fname,
7873 &data_return_size);
7874 break;
7877 case SMB_POSIX_PATH_UNLINK:
7879 if (fsp) {
7880 /* We must have a pathname for this. */
7881 return NT_STATUS_INVALID_LEVEL;
7884 status = smb_posix_unlink(conn, req,
7885 pdata,
7886 total_data,
7887 smb_fname);
7888 break;
7891 default:
7892 return NT_STATUS_INVALID_LEVEL;
7895 if (!NT_STATUS_IS_OK(status)) {
7896 return status;
7899 *ret_data_size = data_return_size;
7900 return NT_STATUS_OK;
7903 /****************************************************************************
7904 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7905 ****************************************************************************/
7907 static void call_trans2setfilepathinfo(connection_struct *conn,
7908 struct smb_request *req,
7909 unsigned int tran_call,
7910 char **pparams, int total_params,
7911 char **ppdata, int total_data,
7912 unsigned int max_data_bytes)
7914 char *params = *pparams;
7915 char *pdata = *ppdata;
7916 uint16 info_level;
7917 struct smb_filename *smb_fname = NULL;
7918 files_struct *fsp = NULL;
7919 NTSTATUS status = NT_STATUS_OK;
7920 int data_return_size = 0;
7922 if (!params) {
7923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7924 return;
7927 if (tran_call == TRANSACT2_SETFILEINFO) {
7928 if (total_params < 4) {
7929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930 return;
7933 fsp = file_fsp(req, SVAL(params,0));
7934 /* Basic check for non-null fsp. */
7935 if (!check_fsp_open(conn, req, fsp)) {
7936 return;
7938 info_level = SVAL(params,2);
7940 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7941 &smb_fname);
7942 if (!NT_STATUS_IS_OK(status)) {
7943 reply_nterror(req, status);
7944 return;
7947 if(fsp->fh->fd == -1) {
7949 * This is actually a SETFILEINFO on a directory
7950 * handle (returned from an NT SMB). NT5.0 seems
7951 * to do this call. JRA.
7953 if (INFO_LEVEL_IS_UNIX(info_level)) {
7954 /* Always do lstat for UNIX calls. */
7955 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7956 DEBUG(3,("call_trans2setfilepathinfo: "
7957 "SMB_VFS_LSTAT of %s failed "
7958 "(%s)\n",
7959 smb_fname_str_dbg(smb_fname),
7960 strerror(errno)));
7961 reply_nterror(req, map_nt_error_from_unix(errno));
7962 return;
7964 } else {
7965 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7966 DEBUG(3,("call_trans2setfilepathinfo: "
7967 "fileinfo of %s failed (%s)\n",
7968 smb_fname_str_dbg(smb_fname),
7969 strerror(errno)));
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7971 return;
7974 } else if (fsp->print_file) {
7976 * Doing a DELETE_ON_CLOSE should cancel a print job.
7978 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7979 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7981 DEBUG(3,("call_trans2setfilepathinfo: "
7982 "Cancelling print job (%s)\n",
7983 fsp_str_dbg(fsp)));
7985 SSVAL(params,0,0);
7986 send_trans2_replies(conn, req, params, 2,
7987 *ppdata, 0,
7988 max_data_bytes);
7989 return;
7990 } else {
7991 reply_nterror(req,
7992 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7993 return;
7995 } else {
7997 * Original code - this is an open file.
7999 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8000 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8001 "of fnum %d failed (%s)\n", fsp->fnum,
8002 strerror(errno)));
8003 reply_nterror(req, map_nt_error_from_unix(errno));
8004 return;
8007 } else {
8008 char *fname = NULL;
8009 uint32_t ucf_flags = 0;
8011 /* set path info */
8012 if (total_params < 7) {
8013 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8014 return;
8017 info_level = SVAL(params,0);
8018 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8019 total_params - 6, STR_TERMINATE,
8020 &status);
8021 if (!NT_STATUS_IS_OK(status)) {
8022 reply_nterror(req, status);
8023 return;
8026 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8027 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8028 info_level == SMB_FILE_RENAME_INFORMATION ||
8029 info_level == SMB_POSIX_PATH_UNLINK) {
8030 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8033 status = filename_convert(req, conn,
8034 req->flags2 & FLAGS2_DFS_PATHNAMES,
8035 fname,
8036 ucf_flags,
8037 NULL,
8038 &smb_fname);
8039 if (!NT_STATUS_IS_OK(status)) {
8040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8041 reply_botherror(req,
8042 NT_STATUS_PATH_NOT_COVERED,
8043 ERRSRV, ERRbadpath);
8044 return;
8046 reply_nterror(req, status);
8047 return;
8050 if (INFO_LEVEL_IS_UNIX(info_level)) {
8052 * For CIFS UNIX extensions the target name may not exist.
8055 /* Always do lstat for UNIX calls. */
8056 SMB_VFS_LSTAT(conn, smb_fname);
8058 } else if (!VALID_STAT(smb_fname->st) &&
8059 SMB_VFS_STAT(conn, smb_fname)) {
8060 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8061 "%s failed (%s)\n",
8062 smb_fname_str_dbg(smb_fname),
8063 strerror(errno)));
8064 reply_nterror(req, map_nt_error_from_unix(errno));
8065 return;
8069 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8070 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8071 fsp ? fsp->fnum : -1, info_level,total_data));
8073 /* Realloc the parameter size */
8074 *pparams = (char *)SMB_REALLOC(*pparams,2);
8075 if (*pparams == NULL) {
8076 reply_nterror(req, NT_STATUS_NO_MEMORY);
8077 return;
8079 params = *pparams;
8081 SSVAL(params,0,0);
8083 status = smbd_do_setfilepathinfo(conn, req, req,
8084 info_level,
8085 fsp,
8086 smb_fname,
8087 ppdata, total_data,
8088 &data_return_size);
8089 if (!NT_STATUS_IS_OK(status)) {
8090 if (open_was_deferred(req->sconn, req->mid)) {
8091 /* We have re-scheduled this call. */
8092 return;
8094 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8095 /* We have re-scheduled this call. */
8096 return;
8098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8100 ERRSRV, ERRbadpath);
8101 return;
8103 if (info_level == SMB_POSIX_PATH_OPEN) {
8104 reply_openerror(req, status);
8105 return;
8108 reply_nterror(req, status);
8109 return;
8112 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8113 max_data_bytes);
8115 return;
8118 /****************************************************************************
8119 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8120 ****************************************************************************/
8122 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8123 char **pparams, int total_params,
8124 char **ppdata, int total_data,
8125 unsigned int max_data_bytes)
8127 struct smb_filename *smb_dname = NULL;
8128 char *params = *pparams;
8129 char *pdata = *ppdata;
8130 char *directory = NULL;
8131 NTSTATUS status = NT_STATUS_OK;
8132 struct ea_list *ea_list = NULL;
8133 TALLOC_CTX *ctx = talloc_tos();
8135 if (!CAN_WRITE(conn)) {
8136 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8137 return;
8140 if (total_params < 5) {
8141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8142 return;
8145 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8146 total_params - 4, STR_TERMINATE,
8147 &status);
8148 if (!NT_STATUS_IS_OK(status)) {
8149 reply_nterror(req, status);
8150 return;
8153 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8155 status = filename_convert(ctx,
8156 conn,
8157 req->flags2 & FLAGS2_DFS_PATHNAMES,
8158 directory,
8160 NULL,
8161 &smb_dname);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8165 reply_botherror(req,
8166 NT_STATUS_PATH_NOT_COVERED,
8167 ERRSRV, ERRbadpath);
8168 return;
8170 reply_nterror(req, status);
8171 return;
8175 * OS/2 workplace shell seems to send SET_EA requests of "null"
8176 * length (4 bytes containing IVAL 4).
8177 * They seem to have no effect. Bug #3212. JRA.
8180 if (total_data && (total_data != 4)) {
8181 /* Any data in this call is an EA list. */
8182 if (total_data < 10) {
8183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8184 goto out;
8187 if (IVAL(pdata,0) > total_data) {
8188 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8189 IVAL(pdata,0), (unsigned int)total_data));
8190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8191 goto out;
8194 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8195 total_data - 4);
8196 if (!ea_list) {
8197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8198 goto out;
8201 if (!lp_ea_support(SNUM(conn))) {
8202 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8203 goto out;
8206 /* If total_data == 4 Windows doesn't care what values
8207 * are placed in that field, it just ignores them.
8208 * The System i QNTC IBM SMB client puts bad values here,
8209 * so ignore them. */
8211 status = create_directory(conn, req, smb_dname);
8213 if (!NT_STATUS_IS_OK(status)) {
8214 reply_nterror(req, status);
8215 goto out;
8218 /* Try and set any given EA. */
8219 if (ea_list) {
8220 status = set_ea(conn, NULL, smb_dname, ea_list);
8221 if (!NT_STATUS_IS_OK(status)) {
8222 reply_nterror(req, status);
8223 goto out;
8227 /* Realloc the parameter and data sizes */
8228 *pparams = (char *)SMB_REALLOC(*pparams,2);
8229 if(*pparams == NULL) {
8230 reply_nterror(req, NT_STATUS_NO_MEMORY);
8231 goto out;
8233 params = *pparams;
8235 SSVAL(params,0,0);
8237 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8239 out:
8240 TALLOC_FREE(smb_dname);
8241 return;
8244 /****************************************************************************
8245 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8246 We don't actually do this - we just send a null response.
8247 ****************************************************************************/
8249 static void call_trans2findnotifyfirst(connection_struct *conn,
8250 struct smb_request *req,
8251 char **pparams, int total_params,
8252 char **ppdata, int total_data,
8253 unsigned int max_data_bytes)
8255 char *params = *pparams;
8256 uint16 info_level;
8258 if (total_params < 6) {
8259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8260 return;
8263 info_level = SVAL(params,4);
8264 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8266 switch (info_level) {
8267 case 1:
8268 case 2:
8269 break;
8270 default:
8271 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8272 return;
8275 /* Realloc the parameter and data sizes */
8276 *pparams = (char *)SMB_REALLOC(*pparams,6);
8277 if (*pparams == NULL) {
8278 reply_nterror(req, NT_STATUS_NO_MEMORY);
8279 return;
8281 params = *pparams;
8283 SSVAL(params,0,fnf_handle);
8284 SSVAL(params,2,0); /* No changes */
8285 SSVAL(params,4,0); /* No EA errors */
8287 fnf_handle++;
8289 if(fnf_handle == 0)
8290 fnf_handle = 257;
8292 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8294 return;
8297 /****************************************************************************
8298 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8299 changes). Currently this does nothing.
8300 ****************************************************************************/
8302 static void call_trans2findnotifynext(connection_struct *conn,
8303 struct smb_request *req,
8304 char **pparams, int total_params,
8305 char **ppdata, int total_data,
8306 unsigned int max_data_bytes)
8308 char *params = *pparams;
8310 DEBUG(3,("call_trans2findnotifynext\n"));
8312 /* Realloc the parameter and data sizes */
8313 *pparams = (char *)SMB_REALLOC(*pparams,4);
8314 if (*pparams == NULL) {
8315 reply_nterror(req, NT_STATUS_NO_MEMORY);
8316 return;
8318 params = *pparams;
8320 SSVAL(params,0,0); /* No changes */
8321 SSVAL(params,2,0); /* No EA errors */
8323 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8325 return;
8328 /****************************************************************************
8329 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8330 ****************************************************************************/
8332 static void call_trans2getdfsreferral(connection_struct *conn,
8333 struct smb_request *req,
8334 char **pparams, int total_params,
8335 char **ppdata, int total_data,
8336 unsigned int max_data_bytes)
8338 char *params = *pparams;
8339 char *pathname = NULL;
8340 int reply_size = 0;
8341 int max_referral_level;
8342 NTSTATUS status = NT_STATUS_OK;
8343 TALLOC_CTX *ctx = talloc_tos();
8345 DEBUG(10,("call_trans2getdfsreferral\n"));
8347 if (total_params < 3) {
8348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8349 return;
8352 max_referral_level = SVAL(params,0);
8354 if(!lp_host_msdfs()) {
8355 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8356 return;
8359 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8360 total_params - 2, STR_TERMINATE);
8361 if (!pathname) {
8362 reply_nterror(req, NT_STATUS_NOT_FOUND);
8363 return;
8365 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8366 ppdata,&status)) < 0) {
8367 reply_nterror(req, status);
8368 return;
8371 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8372 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8373 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8375 return;
8378 #define LMCAT_SPL 0x53
8379 #define LMFUNC_GETJOBID 0x60
8381 /****************************************************************************
8382 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8383 ****************************************************************************/
8385 static void call_trans2ioctl(connection_struct *conn,
8386 struct smb_request *req,
8387 char **pparams, int total_params,
8388 char **ppdata, int total_data,
8389 unsigned int max_data_bytes)
8391 char *pdata = *ppdata;
8392 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8394 /* check for an invalid fid before proceeding */
8396 if (!fsp) {
8397 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8398 return;
8401 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8402 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8403 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8404 if (*ppdata == NULL) {
8405 reply_nterror(req, NT_STATUS_NO_MEMORY);
8406 return;
8408 pdata = *ppdata;
8410 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8411 CAN ACCEPT THIS IN UNICODE. JRA. */
8413 /* Job number */
8414 if (fsp->print_file) {
8415 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8416 } else {
8417 SSVAL(pdata, 0, 0);
8419 srvstr_push(pdata, req->flags2, pdata + 2,
8420 lp_netbios_name(), 15,
8421 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8422 srvstr_push(pdata, req->flags2, pdata+18,
8423 lp_servicename(SNUM(conn)), 13,
8424 STR_ASCII|STR_TERMINATE); /* Service name */
8425 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8426 max_data_bytes);
8427 return;
8430 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8431 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8434 /****************************************************************************
8435 Reply to a SMBfindclose (stop trans2 directory search).
8436 ****************************************************************************/
8438 void reply_findclose(struct smb_request *req)
8440 int dptr_num;
8441 struct smbd_server_connection *sconn = req->sconn;
8443 START_PROFILE(SMBfindclose);
8445 if (req->wct < 1) {
8446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8447 END_PROFILE(SMBfindclose);
8448 return;
8451 dptr_num = SVALS(req->vwv+0, 0);
8453 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8455 dptr_close(sconn, &dptr_num);
8457 reply_outbuf(req, 0, 0);
8459 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8461 END_PROFILE(SMBfindclose);
8462 return;
8465 /****************************************************************************
8466 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8467 ****************************************************************************/
8469 void reply_findnclose(struct smb_request *req)
8471 int dptr_num;
8473 START_PROFILE(SMBfindnclose);
8475 if (req->wct < 1) {
8476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8477 END_PROFILE(SMBfindnclose);
8478 return;
8481 dptr_num = SVAL(req->vwv+0, 0);
8483 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8485 /* We never give out valid handles for a
8486 findnotifyfirst - so any dptr_num is ok here.
8487 Just ignore it. */
8489 reply_outbuf(req, 0, 0);
8491 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8493 END_PROFILE(SMBfindnclose);
8494 return;
8497 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8498 struct trans_state *state)
8500 if (get_Protocol() >= PROTOCOL_NT1) {
8501 req->flags2 |= 0x40; /* IS_LONG_NAME */
8502 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8505 if (conn->encrypt_level == Required && !req->encrypted) {
8506 if (state->call != TRANSACT2_QFSINFO &&
8507 state->call != TRANSACT2_SETFSINFO) {
8508 DEBUG(0,("handle_trans2: encryption required "
8509 "with call 0x%x\n",
8510 (unsigned int)state->call));
8511 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8512 return;
8516 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8518 /* Now we must call the relevant TRANS2 function */
8519 switch(state->call) {
8520 case TRANSACT2_OPEN:
8522 START_PROFILE(Trans2_open);
8523 call_trans2open(conn, req,
8524 &state->param, state->total_param,
8525 &state->data, state->total_data,
8526 state->max_data_return);
8527 END_PROFILE(Trans2_open);
8528 break;
8531 case TRANSACT2_FINDFIRST:
8533 START_PROFILE(Trans2_findfirst);
8534 call_trans2findfirst(conn, req,
8535 &state->param, state->total_param,
8536 &state->data, state->total_data,
8537 state->max_data_return);
8538 END_PROFILE(Trans2_findfirst);
8539 break;
8542 case TRANSACT2_FINDNEXT:
8544 START_PROFILE(Trans2_findnext);
8545 call_trans2findnext(conn, req,
8546 &state->param, state->total_param,
8547 &state->data, state->total_data,
8548 state->max_data_return);
8549 END_PROFILE(Trans2_findnext);
8550 break;
8553 case TRANSACT2_QFSINFO:
8555 START_PROFILE(Trans2_qfsinfo);
8556 call_trans2qfsinfo(conn, req,
8557 &state->param, state->total_param,
8558 &state->data, state->total_data,
8559 state->max_data_return);
8560 END_PROFILE(Trans2_qfsinfo);
8561 break;
8564 case TRANSACT2_SETFSINFO:
8566 START_PROFILE(Trans2_setfsinfo);
8567 call_trans2setfsinfo(conn, req,
8568 &state->param, state->total_param,
8569 &state->data, state->total_data,
8570 state->max_data_return);
8571 END_PROFILE(Trans2_setfsinfo);
8572 break;
8575 case TRANSACT2_QPATHINFO:
8576 case TRANSACT2_QFILEINFO:
8578 START_PROFILE(Trans2_qpathinfo);
8579 call_trans2qfilepathinfo(conn, req, state->call,
8580 &state->param, state->total_param,
8581 &state->data, state->total_data,
8582 state->max_data_return);
8583 END_PROFILE(Trans2_qpathinfo);
8584 break;
8587 case TRANSACT2_SETPATHINFO:
8588 case TRANSACT2_SETFILEINFO:
8590 START_PROFILE(Trans2_setpathinfo);
8591 call_trans2setfilepathinfo(conn, req, state->call,
8592 &state->param, state->total_param,
8593 &state->data, state->total_data,
8594 state->max_data_return);
8595 END_PROFILE(Trans2_setpathinfo);
8596 break;
8599 case TRANSACT2_FINDNOTIFYFIRST:
8601 START_PROFILE(Trans2_findnotifyfirst);
8602 call_trans2findnotifyfirst(conn, req,
8603 &state->param, state->total_param,
8604 &state->data, state->total_data,
8605 state->max_data_return);
8606 END_PROFILE(Trans2_findnotifyfirst);
8607 break;
8610 case TRANSACT2_FINDNOTIFYNEXT:
8612 START_PROFILE(Trans2_findnotifynext);
8613 call_trans2findnotifynext(conn, req,
8614 &state->param, state->total_param,
8615 &state->data, state->total_data,
8616 state->max_data_return);
8617 END_PROFILE(Trans2_findnotifynext);
8618 break;
8621 case TRANSACT2_MKDIR:
8623 START_PROFILE(Trans2_mkdir);
8624 call_trans2mkdir(conn, req,
8625 &state->param, state->total_param,
8626 &state->data, state->total_data,
8627 state->max_data_return);
8628 END_PROFILE(Trans2_mkdir);
8629 break;
8632 case TRANSACT2_GET_DFS_REFERRAL:
8634 START_PROFILE(Trans2_get_dfs_referral);
8635 call_trans2getdfsreferral(conn, req,
8636 &state->param, state->total_param,
8637 &state->data, state->total_data,
8638 state->max_data_return);
8639 END_PROFILE(Trans2_get_dfs_referral);
8640 break;
8643 case TRANSACT2_IOCTL:
8645 START_PROFILE(Trans2_ioctl);
8646 call_trans2ioctl(conn, req,
8647 &state->param, state->total_param,
8648 &state->data, state->total_data,
8649 state->max_data_return);
8650 END_PROFILE(Trans2_ioctl);
8651 break;
8654 default:
8655 /* Error in request */
8656 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8657 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8661 /****************************************************************************
8662 Reply to a SMBtrans2.
8663 ****************************************************************************/
8665 void reply_trans2(struct smb_request *req)
8667 connection_struct *conn = req->conn;
8668 unsigned int dsoff;
8669 unsigned int dscnt;
8670 unsigned int psoff;
8671 unsigned int pscnt;
8672 unsigned int tran_call;
8673 struct trans_state *state;
8674 NTSTATUS result;
8676 START_PROFILE(SMBtrans2);
8678 if (req->wct < 14) {
8679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8680 END_PROFILE(SMBtrans2);
8681 return;
8684 dsoff = SVAL(req->vwv+12, 0);
8685 dscnt = SVAL(req->vwv+11, 0);
8686 psoff = SVAL(req->vwv+10, 0);
8687 pscnt = SVAL(req->vwv+9, 0);
8688 tran_call = SVAL(req->vwv+14, 0);
8690 result = allow_new_trans(conn->pending_trans, req->mid);
8691 if (!NT_STATUS_IS_OK(result)) {
8692 DEBUG(2, ("Got invalid trans2 request: %s\n",
8693 nt_errstr(result)));
8694 reply_nterror(req, result);
8695 END_PROFILE(SMBtrans2);
8696 return;
8699 if (IS_IPC(conn)) {
8700 switch (tran_call) {
8701 /* List the allowed trans2 calls on IPC$ */
8702 case TRANSACT2_OPEN:
8703 case TRANSACT2_GET_DFS_REFERRAL:
8704 case TRANSACT2_QFILEINFO:
8705 case TRANSACT2_QFSINFO:
8706 case TRANSACT2_SETFSINFO:
8707 break;
8708 default:
8709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8710 END_PROFILE(SMBtrans2);
8711 return;
8715 if ((state = talloc(conn, struct trans_state)) == NULL) {
8716 DEBUG(0, ("talloc failed\n"));
8717 reply_nterror(req, NT_STATUS_NO_MEMORY);
8718 END_PROFILE(SMBtrans2);
8719 return;
8722 state->cmd = SMBtrans2;
8724 state->mid = req->mid;
8725 state->vuid = req->vuid;
8726 state->setup_count = SVAL(req->vwv+13, 0);
8727 state->setup = NULL;
8728 state->total_param = SVAL(req->vwv+0, 0);
8729 state->param = NULL;
8730 state->total_data = SVAL(req->vwv+1, 0);
8731 state->data = NULL;
8732 state->max_param_return = SVAL(req->vwv+2, 0);
8733 state->max_data_return = SVAL(req->vwv+3, 0);
8734 state->max_setup_return = SVAL(req->vwv+4, 0);
8735 state->close_on_completion = BITSETW(req->vwv+5, 0);
8736 state->one_way = BITSETW(req->vwv+5, 1);
8738 state->call = tran_call;
8740 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8741 is so as a sanity check */
8742 if (state->setup_count != 1) {
8744 * Need to have rc=0 for ioctl to get job id for OS/2.
8745 * Network printing will fail if function is not successful.
8746 * Similar function in reply.c will be used if protocol
8747 * is LANMAN1.0 instead of LM1.2X002.
8748 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8749 * outbuf doesn't have to be set(only job id is used).
8751 if ( (state->setup_count == 4)
8752 && (tran_call == TRANSACT2_IOCTL)
8753 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8754 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8755 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8756 } else {
8757 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8758 DEBUG(2,("Transaction is %d\n",tran_call));
8759 TALLOC_FREE(state);
8760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8761 END_PROFILE(SMBtrans2);
8762 return;
8766 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8767 goto bad_param;
8769 if (state->total_data) {
8771 if (trans_oob(state->total_data, 0, dscnt)
8772 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8773 goto bad_param;
8776 /* Can't use talloc here, the core routines do realloc on the
8777 * params and data. */
8778 state->data = (char *)SMB_MALLOC(state->total_data);
8779 if (state->data == NULL) {
8780 DEBUG(0,("reply_trans2: data malloc fail for %u "
8781 "bytes !\n", (unsigned int)state->total_data));
8782 TALLOC_FREE(state);
8783 reply_nterror(req, NT_STATUS_NO_MEMORY);
8784 END_PROFILE(SMBtrans2);
8785 return;
8788 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8791 if (state->total_param) {
8793 if (trans_oob(state->total_param, 0, pscnt)
8794 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8795 goto bad_param;
8798 /* Can't use talloc here, the core routines do realloc on the
8799 * params and data. */
8800 state->param = (char *)SMB_MALLOC(state->total_param);
8801 if (state->param == NULL) {
8802 DEBUG(0,("reply_trans: param malloc fail for %u "
8803 "bytes !\n", (unsigned int)state->total_param));
8804 SAFE_FREE(state->data);
8805 TALLOC_FREE(state);
8806 reply_nterror(req, NT_STATUS_NO_MEMORY);
8807 END_PROFILE(SMBtrans2);
8808 return;
8811 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8814 state->received_data = dscnt;
8815 state->received_param = pscnt;
8817 if ((state->received_param == state->total_param) &&
8818 (state->received_data == state->total_data)) {
8820 handle_trans2(conn, req, state);
8822 SAFE_FREE(state->data);
8823 SAFE_FREE(state->param);
8824 TALLOC_FREE(state);
8825 END_PROFILE(SMBtrans2);
8826 return;
8829 DLIST_ADD(conn->pending_trans, state);
8831 /* We need to send an interim response then receive the rest
8832 of the parameter/data bytes */
8833 reply_outbuf(req, 0, 0);
8834 show_msg((char *)req->outbuf);
8835 END_PROFILE(SMBtrans2);
8836 return;
8838 bad_param:
8840 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8841 SAFE_FREE(state->data);
8842 SAFE_FREE(state->param);
8843 TALLOC_FREE(state);
8844 END_PROFILE(SMBtrans2);
8845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8849 /****************************************************************************
8850 Reply to a SMBtranss2
8851 ****************************************************************************/
8853 void reply_transs2(struct smb_request *req)
8855 connection_struct *conn = req->conn;
8856 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8857 struct trans_state *state;
8859 START_PROFILE(SMBtranss2);
8861 show_msg((const char *)req->inbuf);
8863 if (req->wct < 8) {
8864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8865 END_PROFILE(SMBtranss2);
8866 return;
8869 for (state = conn->pending_trans; state != NULL;
8870 state = state->next) {
8871 if (state->mid == req->mid) {
8872 break;
8876 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8878 END_PROFILE(SMBtranss2);
8879 return;
8882 /* Revise state->total_param and state->total_data in case they have
8883 changed downwards */
8885 if (SVAL(req->vwv+0, 0) < state->total_param)
8886 state->total_param = SVAL(req->vwv+0, 0);
8887 if (SVAL(req->vwv+1, 0) < state->total_data)
8888 state->total_data = SVAL(req->vwv+1, 0);
8890 pcnt = SVAL(req->vwv+2, 0);
8891 poff = SVAL(req->vwv+3, 0);
8892 pdisp = SVAL(req->vwv+4, 0);
8894 dcnt = SVAL(req->vwv+5, 0);
8895 doff = SVAL(req->vwv+6, 0);
8896 ddisp = SVAL(req->vwv+7, 0);
8898 state->received_param += pcnt;
8899 state->received_data += dcnt;
8901 if ((state->received_data > state->total_data) ||
8902 (state->received_param > state->total_param))
8903 goto bad_param;
8905 if (pcnt) {
8906 if (trans_oob(state->total_param, pdisp, pcnt)
8907 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8908 goto bad_param;
8910 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8913 if (dcnt) {
8914 if (trans_oob(state->total_data, ddisp, dcnt)
8915 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8916 goto bad_param;
8918 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8921 if ((state->received_param < state->total_param) ||
8922 (state->received_data < state->total_data)) {
8923 END_PROFILE(SMBtranss2);
8924 return;
8927 handle_trans2(conn, req, state);
8929 DLIST_REMOVE(conn->pending_trans, state);
8930 SAFE_FREE(state->data);
8931 SAFE_FREE(state->param);
8932 TALLOC_FREE(state);
8934 END_PROFILE(SMBtranss2);
8935 return;
8937 bad_param:
8939 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8940 DLIST_REMOVE(conn->pending_trans, state);
8941 SAFE_FREE(state->data);
8942 SAFE_FREE(state->param);
8943 TALLOC_FREE(state);
8944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8945 END_PROFILE(SMBtranss2);
8946 return;