s4-libnet: Fix continue_groupinfo_opengroup to check correct state info
[Samba.git] / source3 / smbd / trans2.c
blob63ee76bce9e771186d1c664850c8359173543de2
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 off_t size=0;
1032 int fattr=0,mtime=0;
1033 SMB_INO_T inode = 0;
1034 int smb_action = 0;
1035 files_struct *fsp;
1036 struct ea_list *ea_list = NULL;
1037 uint16 flags = 0;
1038 NTSTATUS status;
1039 uint32 access_mask;
1040 uint32 share_mode;
1041 uint32 create_disposition;
1042 uint32 create_options = 0;
1043 uint32_t private_flags = 0;
1044 TALLOC_CTX *ctx = talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params < 29) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 goto out;
1055 flags = SVAL(params, 0);
1056 deny_mode = SVAL(params, 2);
1057 open_attr = SVAL(params,6);
1058 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1059 if (oplock_request) {
1060 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1063 #if 0
1064 return_additional_info = BITSETW(params,0);
1065 open_sattr = SVAL(params, 4);
1066 open_time = make_unix_date3(params+8);
1067 #endif
1068 open_ofun = SVAL(params,12);
1069 open_size = IVAL(params,14);
1070 pname = &params[28];
1072 if (IS_IPC(conn)) {
1073 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1074 goto out;
1077 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1078 total_params - 28, STR_TERMINATE,
1079 &status);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 reply_nterror(req, status);
1082 goto out;
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1087 (unsigned int)open_ofun, open_size));
1089 status = filename_convert(ctx,
1090 conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092 fname,
1094 NULL,
1095 &smb_fname);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req,
1099 NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 goto out;
1103 reply_nterror(req, status);
1104 goto out;
1107 if (open_ofun == 0) {
1108 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1109 goto out;
1112 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1113 open_ofun,
1114 &access_mask, &share_mode,
1115 &create_disposition,
1116 &create_options,
1117 &private_flags)) {
1118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1119 goto out;
1122 /* Any data in this call is an EA list. */
1123 if (total_data && (total_data != 4)) {
1124 if (total_data < 10) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126 goto out;
1129 if (IVAL(pdata,0) > total_data) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata,0), (unsigned int)total_data));
1132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1133 goto out;
1136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1137 total_data - 4);
1138 if (!ea_list) {
1139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1140 goto out;
1143 if (!lp_ea_support(SNUM(conn))) {
1144 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1145 goto out;
1149 status = SMB_VFS_CREATE_FILE(
1150 conn, /* conn */
1151 req, /* req */
1152 0, /* root_dir_fid */
1153 smb_fname, /* fname */
1154 access_mask, /* access_mask */
1155 share_mode, /* share_access */
1156 create_disposition, /* create_disposition*/
1157 create_options, /* create_options */
1158 open_attr, /* file_attributes */
1159 oplock_request, /* oplock_request */
1160 open_size, /* allocation_size */
1161 private_flags,
1162 NULL, /* sd */
1163 ea_list, /* ea_list */
1164 &fsp, /* result */
1165 &smb_action); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (open_was_deferred(req->sconn, req->mid)) {
1169 /* We have re-scheduled this call. */
1170 goto out;
1172 reply_openerror(req, status);
1173 goto out;
1176 size = get_file_size_stat(&smb_fname->st);
1177 fattr = dos_mode(conn, smb_fname);
1178 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1179 inode = smb_fname->st.st_ex_ino;
1180 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1181 close_file(req, fsp, ERROR_CLOSE);
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1183 goto out;
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1188 if(*pparams == NULL ) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1190 goto out;
1192 params = *pparams;
1194 SSVAL(params,0,fsp->fnum);
1195 SSVAL(params,2,fattr);
1196 srv_put_dos_date2(params,4, mtime);
1197 SIVAL(params,8, (uint32)size);
1198 SSVAL(params,12,deny_mode);
1199 SSVAL(params,14,0); /* open_type - file or directory. */
1200 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1206 SSVAL(params,18,smb_action);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params,20,inode);
1212 SSVAL(params,24,0); /* Padding. */
1213 if (flags & 8) {
1214 uint32 ea_size = estimate_ea_size(conn, fsp,
1215 fsp->fsp_name->base_name);
1216 SIVAL(params, 26, ea_size);
1217 } else {
1218 SIVAL(params, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1223 out:
1224 TALLOC_FREE(smb_fname);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild,
1235 bool case_sensitive,
1236 const char *str,
1237 const char *mask)
1239 if (mask[0] == '.' && mask[1] == 0) {
1240 return false;
1243 if (has_wild) {
1244 return false;
1247 if (case_sensitive) {
1248 return strcmp(str,mask)==0;
1249 } else {
1250 return strcasecmp_m(str,mask) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32 unix_filetype(mode_t mode)
1260 if(S_ISREG(mode))
1261 return UNIX_TYPE_FILE;
1262 else if(S_ISDIR(mode))
1263 return UNIX_TYPE_DIR;
1264 #ifdef S_ISLNK
1265 else if(S_ISLNK(mode))
1266 return UNIX_TYPE_SYMLINK;
1267 #endif
1268 #ifdef S_ISCHR
1269 else if(S_ISCHR(mode))
1270 return UNIX_TYPE_CHARDEV;
1271 #endif
1272 #ifdef S_ISBLK
1273 else if(S_ISBLK(mode))
1274 return UNIX_TYPE_BLKDEV;
1275 #endif
1276 #ifdef S_ISFIFO
1277 else if(S_ISFIFO(mode))
1278 return UNIX_TYPE_FIFO;
1279 #endif
1280 #ifdef S_ISSOCK
1281 else if(S_ISSOCK(mode))
1282 return UNIX_TYPE_SOCKET;
1283 #endif
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1286 return UNIX_TYPE_UNKNOWN;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1295 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1296 const SMB_STRUCT_STAT *psbuf,
1297 uint32 perms,
1298 enum perm_type ptype,
1299 mode_t *ret_perms)
1301 mode_t ret = 0;
1303 if (perms == SMB_MODE_NO_CHANGE) {
1304 if (!VALID_STAT(*psbuf)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1306 } else {
1307 *ret_perms = psbuf->st_ex_mode;
1308 return NT_STATUS_OK;
1312 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1313 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1314 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1315 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1316 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1317 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1318 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1319 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1320 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1321 #ifdef S_ISVTX
1322 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1323 #endif
1324 #ifdef S_ISGID
1325 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1326 #endif
1327 #ifdef S_ISUID
1328 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1329 #endif
1331 switch (ptype) {
1332 case PERM_NEW_FILE:
1333 /* Apply mode mask */
1334 ret &= lp_create_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_create_mode(SNUM(conn));
1337 break;
1338 case PERM_NEW_DIR:
1339 ret &= lp_dir_mask(SNUM(conn));
1340 /* Add in force bits */
1341 ret |= lp_force_dir_mode(SNUM(conn));
1342 break;
1343 case PERM_EXISTING_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_security_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_security_mode(SNUM(conn));
1348 break;
1349 case PERM_EXISTING_DIR:
1350 /* Apply mode mask */
1351 ret &= lp_dir_security_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_security_mode(SNUM(conn));
1354 break;
1357 *ret_perms = ret;
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct *conn,
1367 const char *pathname,
1368 SMB_STRUCT_STAT *psbuf)
1370 int saved_errno = errno;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn)) &&
1373 is_msdfs_link(conn, pathname, psbuf)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1376 "as a directory\n",
1377 pathname));
1378 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1379 errno = saved_errno;
1380 return true;
1382 errno = saved_errno;
1383 return false;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state {
1392 connection_struct *conn;
1393 uint32_t info_level;
1394 bool check_mangled_names;
1395 bool has_wild;
1396 bool got_exact_match;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1400 void *private_data,
1401 const char *dname,
1402 const char *mask,
1403 char **_fname)
1405 struct smbd_dirptr_lanman2_state *state =
1406 (struct smbd_dirptr_lanman2_state *)private_data;
1407 bool ok;
1408 char mangled_name[13]; /* mangled 8.3 name. */
1409 bool got_match;
1410 const char *fname;
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname, state->conn->params)) {
1414 ok = name_to_8_3(dname, mangled_name,
1415 true, state->conn->params);
1416 if (!ok) {
1417 return false;
1419 fname = mangled_name;
1420 } else {
1421 fname = dname;
1424 got_match = exact_match(state->has_wild,
1425 state->conn->case_sensitive,
1426 fname, mask);
1427 state->got_exact_match = got_match;
1428 if (!got_match) {
1429 got_match = mask_match(fname, mask,
1430 state->conn->case_sensitive);
1433 if(!got_match && state->check_mangled_names &&
1434 !mangle_is_8_3(fname, false, state->conn->params)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok = name_to_8_3(fname, mangled_name,
1443 false, state->conn->params);
1444 if (!ok) {
1445 return false;
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1450 mangled_name, mask);
1451 state->got_exact_match = got_match;
1452 if (!got_match) {
1453 got_match = mask_match(mangled_name, mask,
1454 state->conn->case_sensitive);
1458 if (!got_match) {
1459 return false;
1462 *_fname = talloc_strdup(ctx, fname);
1463 if (*_fname == NULL) {
1464 return false;
1467 return true;
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1471 void *private_data,
1472 struct smb_filename *smb_fname,
1473 uint32_t *_mode)
1475 struct smbd_dirptr_lanman2_state *state =
1476 (struct smbd_dirptr_lanman2_state *)private_data;
1477 bool ms_dfs_link = false;
1478 uint32_t mode = 0;
1480 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1481 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname),
1485 strerror(errno)));
1486 return false;
1488 } else if (!VALID_STAT(smb_fname->st) &&
1489 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1490 /* Needed to show the msdfs symlinks as
1491 * directories */
1493 ms_dfs_link = check_msdfs_link(state->conn,
1494 smb_fname->base_name,
1495 &smb_fname->st);
1496 if (!ms_dfs_link) {
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname),
1500 strerror(errno)));
1501 return false;
1505 if (ms_dfs_link) {
1506 mode = dos_mode_msdfs(state->conn, smb_fname);
1507 } else {
1508 mode = dos_mode(state->conn, smb_fname);
1511 *_mode = mode;
1512 return true;
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1516 connection_struct *conn,
1517 uint16_t flags2,
1518 uint32_t info_level,
1519 struct ea_list *name_list,
1520 bool check_mangled_names,
1521 bool requires_resume_key,
1522 uint32_t mode,
1523 const char *fname,
1524 const struct smb_filename *smb_fname,
1525 int space_remaining,
1526 uint8_t align,
1527 bool do_pad,
1528 char *base_data,
1529 char **ppdata,
1530 char *end_data,
1531 bool *out_of_space,
1532 uint64_t *last_entry_off)
1534 char *p, *q, *pdata = *ppdata;
1535 uint32_t reskey=0;
1536 uint64_t file_size = 0;
1537 uint64_t allocation_size = 0;
1538 uint64_t file_index = 0;
1539 uint32_t len;
1540 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1541 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1542 char *nameptr;
1543 char *last_entry_ptr;
1544 bool was_8_3;
1545 int off;
1546 int pad = 0;
1548 *out_of_space = false;
1550 ZERO_STRUCT(mdate_ts);
1551 ZERO_STRUCT(adate_ts);
1552 ZERO_STRUCT(create_date_ts);
1553 ZERO_STRUCT(cdate_ts);
1555 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1556 file_size = get_file_size_stat(&smb_fname->st);
1558 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1560 file_index = get_FileIndex(conn, &smb_fname->st);
1562 mdate_ts = smb_fname->st.st_ex_mtime;
1563 adate_ts = smb_fname->st.st_ex_atime;
1564 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1565 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1567 if (lp_dos_filetime_resolution(SNUM(conn))) {
1568 dos_filetime_timespec(&create_date_ts);
1569 dos_filetime_timespec(&mdate_ts);
1570 dos_filetime_timespec(&adate_ts);
1571 dos_filetime_timespec(&cdate_ts);
1574 create_date = convert_timespec_to_time_t(create_date_ts);
1575 mdate = convert_timespec_to_time_t(mdate_ts);
1576 adate = convert_timespec_to_time_t(adate_ts);
1578 /* align the record */
1579 SMB_ASSERT(align >= 1);
1581 off = (int)PTR_DIFF(pdata, base_data);
1582 pad = (off + (align-1)) & ~(align-1);
1583 pad -= off;
1585 if (pad && pad > space_remaining) {
1586 *out_of_space = true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1589 (unsigned int)pad,
1590 space_remaining ));
1591 return false; /* Not finished - just out of space */
1594 off += pad;
1595 /* initialize padding to 0 */
1596 if (pad) {
1597 memset(pdata, 0, pad);
1599 space_remaining -= pad;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1602 space_remaining ));
1604 pdata += pad;
1605 p = pdata;
1606 last_entry_ptr = p;
1608 pad = 0;
1609 off = 0;
1611 switch (info_level) {
1612 case SMB_FIND_INFO_STANDARD:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1614 if(requires_resume_key) {
1615 SIVAL(p,0,reskey);
1616 p += 4;
1618 srv_put_dos_date2(p,0,create_date);
1619 srv_put_dos_date2(p,4,adate);
1620 srv_put_dos_date2(p,8,mdate);
1621 SIVAL(p,12,(uint32)file_size);
1622 SIVAL(p,16,(uint32)allocation_size);
1623 SSVAL(p,20,mode);
1624 p += 23;
1625 nameptr = p;
1626 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 p += ucs2_align(base_data, p, 0);
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE);
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1633 if (len > 2) {
1634 SCVAL(nameptr, -1, len - 2);
1635 } else {
1636 SCVAL(nameptr, -1, 0);
1638 } else {
1639 if (len > 1) {
1640 SCVAL(nameptr, -1, len - 1);
1641 } else {
1642 SCVAL(nameptr, -1, 0);
1645 p += len;
1646 break;
1648 case SMB_FIND_EA_SIZE:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key) {
1651 SIVAL(p,0,reskey);
1652 p += 4;
1654 srv_put_dos_date2(p,0,create_date);
1655 srv_put_dos_date2(p,4,adate);
1656 srv_put_dos_date2(p,8,mdate);
1657 SIVAL(p,12,(uint32)file_size);
1658 SIVAL(p,16,(uint32)allocation_size);
1659 SSVAL(p,20,mode);
1661 unsigned int ea_size = estimate_ea_size(conn, NULL,
1662 smb_fname->base_name);
1663 SIVAL(p,22,ea_size); /* Extended attributes */
1665 p += 27;
1666 nameptr = p - 1;
1667 len = srvstr_push(base_data, flags2,
1668 p, fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE | STR_NOALIGN);
1670 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1671 if (len > 2) {
1672 len -= 2;
1673 } else {
1674 len = 0;
1676 } else {
1677 if (len > 1) {
1678 len -= 1;
1679 } else {
1680 len = 0;
1683 SCVAL(nameptr,0,len);
1684 p += len;
1685 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1686 break;
1688 case SMB_FIND_EA_LIST:
1690 struct ea_list *file_list = NULL;
1691 size_t ea_len = 0;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1694 if (!name_list) {
1695 return false;
1697 if (requires_resume_key) {
1698 SIVAL(p,0,reskey);
1699 p += 4;
1701 srv_put_dos_date2(p,0,create_date);
1702 srv_put_dos_date2(p,4,adate);
1703 srv_put_dos_date2(p,8,mdate);
1704 SIVAL(p,12,(uint32)file_size);
1705 SIVAL(p,16,(uint32)allocation_size);
1706 SSVAL(p,20,mode);
1707 p += 22; /* p now points to the EA area. */
1709 file_list = get_ea_list_from_file(ctx, conn, NULL,
1710 smb_fname->base_name,
1711 &ea_len);
1712 name_list = ea_list_union(name_list, file_list, &ea_len);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1717 *out_of_space = true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1721 space_remaining ));
1722 return False; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1727 nameptr = p;
1728 len = srvstr_push(base_data, flags2,
1729 p + 1, fname, PTR_DIFF(end_data, p+1),
1730 STR_TERMINATE | STR_NOALIGN);
1731 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1732 if (len > 2) {
1733 len -= 2;
1734 } else {
1735 len = 0;
1737 } else {
1738 if (len > 1) {
1739 len -= 1;
1740 } else {
1741 len = 0;
1744 SCVAL(nameptr,0,len);
1745 p += len + 1;
1746 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1747 break;
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1753 p += 4;
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,mode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL,
1765 smb_fname->base_name);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1767 p += 4;
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 char mangled_name[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 memset(p,'\0',26);
1791 p += 2 + 24;
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1795 SIVAL(q,0,len);
1796 p += len;
1798 len = PTR_DIFF(p, pdata);
1799 pad = (len + (align-1)) & ~(align-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1805 SIVAL(pdata,0,pad);
1807 * set padding to zero
1809 if (do_pad) {
1810 memset(p, 0, pad - len);
1811 p = pdata + pad;
1812 } else {
1813 p = pdata + len;
1815 break;
1817 case SMB_FIND_FILE_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1819 p += 4;
1820 SIVAL(p,0,reskey); p += 4;
1821 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1825 SOFF_T(p,0,file_size); p += 8;
1826 SOFF_T(p,0,allocation_size); p += 8;
1827 SIVAL(p,0,mode); p += 4;
1828 len = srvstr_push(base_data, flags2,
1829 p + 4, fname, PTR_DIFF(end_data, p+4),
1830 STR_TERMINATE_ASCII);
1831 SIVAL(p,0,len);
1832 p += 4 + len;
1834 len = PTR_DIFF(p, pdata);
1835 pad = (len + (align-1)) & ~(align-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1841 SIVAL(pdata,0,pad);
1843 * set padding to zero
1845 if (do_pad) {
1846 memset(p, 0, pad - len);
1847 p = pdata + pad;
1848 } else {
1849 p = pdata + len;
1851 break;
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1855 p += 4;
1856 SIVAL(p,0,reskey); p += 4;
1857 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1861 SOFF_T(p,0,file_size); p += 8;
1862 SOFF_T(p,0,allocation_size); p += 8;
1863 SIVAL(p,0,mode); p += 4;
1864 q = p; p += 4; /* q is placeholder for name length. */
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1867 smb_fname->base_name);
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1869 p +=4;
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1874 SIVAL(q, 0, len);
1875 p += len;
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1884 SIVAL(pdata,0,pad);
1886 * set padding to zero
1888 if (do_pad) {
1889 memset(p, 0, pad - len);
1890 p = pdata + pad;
1891 } else {
1892 p = pdata + len;
1894 break;
1896 case SMB_FIND_FILE_NAMES_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1898 p += 4;
1899 SIVAL(p,0,reskey); p += 4;
1900 p += 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1906 SIVAL(p, -4, len);
1907 p += len;
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1916 SIVAL(pdata,0,pad);
1918 * set padding to zero
1920 if (do_pad) {
1921 memset(p, 0, pad - len);
1922 p = pdata + pad;
1923 } else {
1924 p = pdata + len;
1926 break;
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1930 p += 4;
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 q = p; p += 4; /* q is placeholder for name length. */
1941 unsigned int ea_size = estimate_ea_size(conn, NULL,
1942 smb_fname->base_name);
1943 SIVAL(p,0,ea_size); /* Extended attributes */
1944 p +=4;
1946 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1947 SBVAL(p,0,file_index); p += 8;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q, 0, len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1976 p += 4;
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname->base_name);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1990 p +=4;
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3 && check_mangled_names) {
1997 char mangled_name[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname,mangled_name,True,
1999 conn->params)) {
2000 /* Error - mangle failed ! */
2001 memset(mangled_name,'\0',12);
2003 mangled_name[12] = 0;
2004 len = srvstr_push(base_data, flags2,
2005 p+2, mangled_name, 24,
2006 STR_UPPER|STR_UNICODE);
2007 SSVAL(p, 0, len);
2008 if (len < 24) {
2009 memset(p + 2 + len,'\0',24 - len);
2011 SSVAL(p, 0, len);
2012 } else {
2013 memset(p,'\0',26);
2015 p += 26;
2016 SSVAL(p,0,0); p += 2; /* Reserved ? */
2017 SBVAL(p,0,file_index); p += 8;
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE_ASCII);
2021 SIVAL(q,0,len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX:
2046 case SMB_FIND_FILE_UNIX_INFO2:
2047 p+= 4;
2048 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level == SMB_FIND_FILE_UNIX) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p = store_file_unix_basic(conn, p,
2055 NULL, &smb_fname->st);
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2058 STR_TERMINATE);
2059 } else {
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p = store_file_unix_basic_info2(conn, p,
2062 NULL, &smb_fname->st);
2063 nameptr = p;
2064 p += 4;
2065 len = srvstr_push(base_data, flags2, p, fname,
2066 PTR_DIFF(end_data, p), 0);
2067 SIVAL(nameptr, 0, len);
2070 p += len;
2072 len = PTR_DIFF(p, pdata);
2073 pad = (len + (align-1)) & ~(align-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2079 SIVAL(pdata,0,pad);
2081 * set padding to zero
2083 if (do_pad) {
2084 memset(p, 0, pad - len);
2085 p = pdata + pad;
2086 } else {
2087 p = pdata + len;
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2091 break;
2093 default:
2094 return false;
2097 if (PTR_DIFF(p,pdata) > space_remaining) {
2098 *out_of_space = true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p,pdata),
2102 space_remaining ));
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2108 /* Advance the data pointer to the next slot */
2109 *ppdata = p;
2111 return true;
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2115 connection_struct *conn,
2116 struct dptr_struct *dirptr,
2117 uint16 flags2,
2118 const char *path_mask,
2119 uint32 dirtype,
2120 int info_level,
2121 int requires_resume_key,
2122 bool dont_descend,
2123 bool ask_sharemode,
2124 uint8_t align,
2125 bool do_pad,
2126 char **ppdata,
2127 char *base_data,
2128 char *end_data,
2129 int space_remaining,
2130 bool *out_of_space,
2131 bool *got_exact_match,
2132 int *_last_entry_off,
2133 struct ea_list *name_list)
2135 const char *p;
2136 const char *mask = NULL;
2137 long prev_dirpos = 0;
2138 uint32_t mode = 0;
2139 char *fname = NULL;
2140 struct smb_filename *smb_fname = NULL;
2141 struct smbd_dirptr_lanman2_state state;
2142 bool ok;
2143 uint64_t last_entry_off = 0;
2145 ZERO_STRUCT(state);
2146 state.conn = conn;
2147 state.info_level = info_level;
2148 state.check_mangled_names = lp_manglednames(conn->params);
2149 state.has_wild = dptr_has_wild(dirptr);
2150 state.got_exact_match = false;
2152 *out_of_space = false;
2153 *got_exact_match = false;
2155 p = strrchr_m(path_mask,'/');
2156 if(p != NULL) {
2157 if(p[1] == '\0') {
2158 mask = "*.*";
2159 } else {
2160 mask = p+1;
2162 } else {
2163 mask = path_mask;
2166 ok = smbd_dirptr_get_entry(ctx,
2167 dirptr,
2168 mask,
2169 dirtype,
2170 dont_descend,
2171 ask_sharemode,
2172 smbd_dirptr_lanman2_match_fn,
2173 smbd_dirptr_lanman2_mode_fn,
2174 &state,
2175 &fname,
2176 &smb_fname,
2177 &mode,
2178 &prev_dirpos);
2179 if (!ok) {
2180 return false;
2183 *got_exact_match = state.got_exact_match;
2185 ok = smbd_marshall_dir_entry(ctx,
2186 conn,
2187 flags2,
2188 info_level,
2189 name_list,
2190 state.check_mangled_names,
2191 requires_resume_key,
2192 mode,
2193 fname,
2194 smb_fname,
2195 space_remaining,
2196 align,
2197 do_pad,
2198 base_data,
2199 ppdata,
2200 end_data,
2201 out_of_space,
2202 &last_entry_off);
2203 TALLOC_FREE(fname);
2204 TALLOC_FREE(smb_fname);
2205 if (*out_of_space) {
2206 dptr_SeekDir(dirptr, prev_dirpos);
2207 return false;
2209 if (!ok) {
2210 return false;
2213 *_last_entry_off = last_entry_off;
2214 return true;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2218 connection_struct *conn,
2219 struct dptr_struct *dirptr,
2220 uint16 flags2,
2221 const char *path_mask,
2222 uint32 dirtype,
2223 int info_level,
2224 bool requires_resume_key,
2225 bool dont_descend,
2226 bool ask_sharemode,
2227 char **ppdata,
2228 char *base_data,
2229 char *end_data,
2230 int space_remaining,
2231 bool *out_of_space,
2232 bool *got_exact_match,
2233 int *last_entry_off,
2234 struct ea_list *name_list)
2236 uint8_t align = 4;
2237 const bool do_pad = true;
2239 if (info_level >= 1 && info_level <= 3) {
2240 /* No alignment on earlier info levels. */
2241 align = 1;
2244 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2245 path_mask, dirtype, info_level,
2246 requires_resume_key, dont_descend, ask_sharemode,
2247 align, do_pad,
2248 ppdata, base_data, end_data,
2249 space_remaining,
2250 out_of_space, got_exact_match,
2251 last_entry_off, name_list);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct *conn,
2259 struct smb_request *req,
2260 char **pparams, int total_params,
2261 char **ppdata, int total_data,
2262 unsigned int max_data_bytes)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2268 requested. */
2269 struct smb_filename *smb_dname = NULL;
2270 char *params = *pparams;
2271 char *pdata = *ppdata;
2272 char *data_end;
2273 uint32 dirtype;
2274 int maxentries;
2275 uint16 findfirst_flags;
2276 bool close_after_first;
2277 bool close_if_end;
2278 bool requires_resume_key;
2279 int info_level;
2280 char *directory = NULL;
2281 char *mask = NULL;
2282 char *p;
2283 int last_entry_off=0;
2284 int dptr_num = -1;
2285 int numentries = 0;
2286 int i;
2287 bool finished = False;
2288 bool dont_descend = False;
2289 bool out_of_space = False;
2290 int space_remaining;
2291 bool mask_contains_wcard = False;
2292 struct ea_list *ea_list = NULL;
2293 NTSTATUS ntstatus = NT_STATUS_OK;
2294 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX *ctx = talloc_tos();
2296 struct dptr_struct *dirptr = NULL;
2297 struct smbd_server_connection *sconn = req->sconn;
2298 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2299 bool backup_priv = false;
2301 if (total_params < 13) {
2302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2303 goto out;
2306 dirtype = SVAL(params,0);
2307 maxentries = SVAL(params,2);
2308 findfirst_flags = SVAL(params,4);
2309 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2310 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2311 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2312 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2313 security_token_has_privilege(get_current_nttok(conn),
2314 SEC_PRIV_BACKUP));
2316 info_level = SVAL(params,6);
2318 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2319 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2320 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2321 (int)backup_priv,
2322 info_level, max_data_bytes));
2324 if (!maxentries) {
2325 /* W2K3 seems to treat zero as 1. */
2326 maxentries = 1;
2329 switch (info_level) {
2330 case SMB_FIND_INFO_STANDARD:
2331 case SMB_FIND_EA_SIZE:
2332 case SMB_FIND_EA_LIST:
2333 case SMB_FIND_FILE_DIRECTORY_INFO:
2334 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2335 case SMB_FIND_FILE_NAMES_INFO:
2336 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2337 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2338 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2339 break;
2340 case SMB_FIND_FILE_UNIX:
2341 case SMB_FIND_FILE_UNIX_INFO2:
2342 /* Always use filesystem for UNIX mtime query. */
2343 ask_sharemode = false;
2344 if (!lp_unix_extensions()) {
2345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346 goto out;
2348 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2349 break;
2350 default:
2351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2352 goto out;
2355 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2356 params+12, total_params - 12,
2357 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2358 if (!NT_STATUS_IS_OK(ntstatus)) {
2359 reply_nterror(req, ntstatus);
2360 goto out;
2363 if (backup_priv) {
2364 become_root();
2365 ntstatus = filename_convert_with_privilege(ctx,
2366 conn,
2367 req,
2368 directory,
2369 ucf_flags,
2370 &mask_contains_wcard,
2371 &smb_dname);
2372 } else {
2373 ntstatus = filename_convert(ctx, conn,
2374 req->flags2 & FLAGS2_DFS_PATHNAMES,
2375 directory,
2376 ucf_flags,
2377 &mask_contains_wcard,
2378 &smb_dname);
2381 if (!NT_STATUS_IS_OK(ntstatus)) {
2382 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2383 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2384 ERRSRV, ERRbadpath);
2385 goto out;
2387 reply_nterror(req, ntstatus);
2388 goto out;
2391 mask = smb_dname->original_lcomp;
2393 directory = smb_dname->base_name;
2395 p = strrchr_m(directory,'/');
2396 if(p == NULL) {
2397 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2398 if((directory[0] == '.') && (directory[1] == '\0')) {
2399 mask = talloc_strdup(ctx,"*");
2400 if (!mask) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2402 goto out;
2404 mask_contains_wcard = True;
2406 } else {
2407 *p = 0;
2410 if (p == NULL || p == directory) {
2411 /* Ensure we don't have a directory name of "". */
2412 directory = talloc_strdup(talloc_tos(), ".");
2413 if (!directory) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 goto out;
2419 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2421 if (info_level == SMB_FIND_EA_LIST) {
2422 uint32 ea_size;
2424 if (total_data < 4) {
2425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 goto out;
2429 ea_size = IVAL(pdata,0);
2430 if (ea_size != total_data) {
2431 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2432 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2434 goto out;
2437 if (!lp_ea_support(SNUM(conn))) {
2438 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2439 goto out;
2442 /* Pull out the list of names. */
2443 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2444 if (!ea_list) {
2445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2446 goto out;
2450 *ppdata = (char *)SMB_REALLOC(
2451 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2452 if(*ppdata == NULL ) {
2453 reply_nterror(req, NT_STATUS_NO_MEMORY);
2454 goto out;
2456 pdata = *ppdata;
2457 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2459 /* Realloc the params space */
2460 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2461 if (*pparams == NULL) {
2462 reply_nterror(req, NT_STATUS_NO_MEMORY);
2463 goto out;
2465 params = *pparams;
2467 /* Save the wildcard match and attribs we are using on this directory -
2468 needed as lanman2 assumes these are being saved between calls */
2470 ntstatus = dptr_create(conn,
2471 req,
2472 NULL, /* fsp */
2473 directory,
2474 False,
2475 True,
2476 req->smbpid,
2477 mask,
2478 mask_contains_wcard,
2479 dirtype,
2480 &dirptr);
2482 if (!NT_STATUS_IS_OK(ntstatus)) {
2483 reply_nterror(req, ntstatus);
2484 goto out;
2487 if (backup_priv) {
2488 /* Remember this in case we have
2489 to do a findnext. */
2490 dptr_set_priv(dirptr);
2493 dptr_num = dptr_dnum(dirptr);
2494 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2496 /* Initialize per TRANS2_FIND_FIRST operation data */
2497 dptr_init_search_op(dirptr);
2499 /* We don't need to check for VOL here as this is returned by
2500 a different TRANS2 call. */
2502 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2503 directory,lp_dontdescend(SNUM(conn))));
2504 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2505 dont_descend = True;
2507 p = pdata;
2508 space_remaining = max_data_bytes;
2509 out_of_space = False;
2511 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2512 bool got_exact_match = False;
2514 /* this is a heuristic to avoid seeking the dirptr except when
2515 absolutely necessary. It allows for a filename of about 40 chars */
2516 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2517 out_of_space = True;
2518 finished = False;
2519 } else {
2520 finished = !get_lanman2_dir_entry(ctx,
2521 conn,
2522 dirptr,
2523 req->flags2,
2524 mask,dirtype,info_level,
2525 requires_resume_key,dont_descend,
2526 ask_sharemode,
2527 &p,pdata,data_end,
2528 space_remaining, &out_of_space,
2529 &got_exact_match,
2530 &last_entry_off, ea_list);
2533 if (finished && out_of_space)
2534 finished = False;
2536 if (!finished && !out_of_space)
2537 numentries++;
2540 * As an optimisation if we know we aren't looking
2541 * for a wildcard name (ie. the name matches the wildcard exactly)
2542 * then we can finish on any (first) match.
2543 * This speeds up large directory searches. JRA.
2546 if(got_exact_match)
2547 finished = True;
2549 /* Ensure space_remaining never goes -ve. */
2550 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2551 space_remaining = 0;
2552 out_of_space = true;
2553 } else {
2554 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2558 /* Check if we can close the dirptr */
2559 if(close_after_first || (finished && close_if_end)) {
2560 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2561 dptr_close(sconn, &dptr_num);
2565 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2566 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2567 * the protocol level is less than NT1. Tested with smbclient. JRA.
2568 * This should fix the OS/2 client bug #2335.
2571 if(numentries == 0) {
2572 dptr_close(sconn, &dptr_num);
2573 if (get_Protocol() < PROTOCOL_NT1) {
2574 reply_force_doserror(req, ERRDOS, ERRnofiles);
2575 goto out;
2576 } else {
2577 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2578 ERRDOS, ERRbadfile);
2579 goto out;
2583 /* At this point pdata points to numentries directory entries. */
2585 /* Set up the return parameter block */
2586 SSVAL(params,0,dptr_num);
2587 SSVAL(params,2,numentries);
2588 SSVAL(params,4,finished);
2589 SSVAL(params,6,0); /* Never an EA error */
2590 SSVAL(params,8,last_entry_off);
2592 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2593 max_data_bytes);
2595 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2596 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2597 if (!directory) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2602 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2603 smb_fn_name(req->cmd),
2604 mask, directory, dirtype, numentries ) );
2607 * Force a name mangle here to ensure that the
2608 * mask as an 8.3 name is top of the mangled cache.
2609 * The reasons for this are subtle. Don't remove
2610 * this code unless you know what you are doing
2611 * (see PR#13758). JRA.
2614 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2615 char mangled_name[13];
2616 name_to_8_3(mask, mangled_name, True, conn->params);
2618 out:
2620 if (backup_priv) {
2621 unbecome_root();
2624 TALLOC_FREE(smb_dname);
2625 return;
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDNEXT.
2630 ****************************************************************************/
2632 static void call_trans2findnext(connection_struct *conn,
2633 struct smb_request *req,
2634 char **pparams, int total_params,
2635 char **ppdata, int total_data,
2636 unsigned int max_data_bytes)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2642 requested. */
2643 char *params = *pparams;
2644 char *pdata = *ppdata;
2645 char *data_end;
2646 int dptr_num;
2647 int maxentries;
2648 uint16 info_level;
2649 uint32 resume_key;
2650 uint16 findnext_flags;
2651 bool close_after_request;
2652 bool close_if_end;
2653 bool requires_resume_key;
2654 bool continue_bit;
2655 bool mask_contains_wcard = False;
2656 char *resume_name = NULL;
2657 const char *mask = NULL;
2658 const char *directory = NULL;
2659 char *p = NULL;
2660 uint16 dirtype;
2661 int numentries = 0;
2662 int i, last_entry_off=0;
2663 bool finished = False;
2664 bool dont_descend = False;
2665 bool out_of_space = False;
2666 int space_remaining;
2667 struct ea_list *ea_list = NULL;
2668 NTSTATUS ntstatus = NT_STATUS_OK;
2669 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2670 TALLOC_CTX *ctx = talloc_tos();
2671 struct dptr_struct *dirptr;
2672 struct smbd_server_connection *sconn = req->sconn;
2673 bool backup_priv = false;
2675 if (total_params < 13) {
2676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2677 return;
2680 dptr_num = SVAL(params,0);
2681 maxentries = SVAL(params,2);
2682 info_level = SVAL(params,4);
2683 resume_key = IVAL(params,6);
2684 findnext_flags = SVAL(params,10);
2685 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2686 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2687 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2688 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2690 if (!continue_bit) {
2691 /* We only need resume_name if continue_bit is zero. */
2692 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2693 params+12,
2694 total_params - 12, STR_TERMINATE, &ntstatus,
2695 &mask_contains_wcard);
2696 if (!NT_STATUS_IS_OK(ntstatus)) {
2697 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2698 complain (it thinks we're asking for the directory above the shared
2699 path or an invalid name). Catch this as the resume name is only compared, never used in
2700 a file access. JRA. */
2701 srvstr_pull_talloc(ctx, params, req->flags2,
2702 &resume_name, params+12,
2703 total_params - 12,
2704 STR_TERMINATE);
2706 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2707 reply_nterror(req, ntstatus);
2708 return;
2713 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2714 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2715 resume_key = %d resume name = %s continue=%d level = %d\n",
2716 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2717 requires_resume_key, resume_key,
2718 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2720 if (!maxentries) {
2721 /* W2K3 seems to treat zero as 1. */
2722 maxentries = 1;
2725 switch (info_level) {
2726 case SMB_FIND_INFO_STANDARD:
2727 case SMB_FIND_EA_SIZE:
2728 case SMB_FIND_EA_LIST:
2729 case SMB_FIND_FILE_DIRECTORY_INFO:
2730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2731 case SMB_FIND_FILE_NAMES_INFO:
2732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2733 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2735 break;
2736 case SMB_FIND_FILE_UNIX:
2737 case SMB_FIND_FILE_UNIX_INFO2:
2738 /* Always use filesystem for UNIX mtime query. */
2739 ask_sharemode = false;
2740 if (!lp_unix_extensions()) {
2741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2742 return;
2744 break;
2745 default:
2746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2747 return;
2750 if (info_level == SMB_FIND_EA_LIST) {
2751 uint32 ea_size;
2753 if (total_data < 4) {
2754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2755 return;
2758 ea_size = IVAL(pdata,0);
2759 if (ea_size != total_data) {
2760 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2761 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 return;
2766 if (!lp_ea_support(SNUM(conn))) {
2767 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2768 return;
2771 /* Pull out the list of names. */
2772 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2773 if (!ea_list) {
2774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2775 return;
2779 *ppdata = (char *)SMB_REALLOC(
2780 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2781 if(*ppdata == NULL) {
2782 reply_nterror(req, NT_STATUS_NO_MEMORY);
2783 return;
2786 pdata = *ppdata;
2787 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2789 /* Realloc the params space */
2790 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2791 if(*pparams == NULL ) {
2792 reply_nterror(req, NT_STATUS_NO_MEMORY);
2793 return;
2796 params = *pparams;
2798 /* Check that the dptr is valid */
2799 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2800 reply_nterror(req, STATUS_NO_MORE_FILES);
2801 return;
2804 directory = dptr_path(sconn, dptr_num);
2806 /* Get the wildcard mask from the dptr */
2807 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2808 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2809 reply_nterror(req, STATUS_NO_MORE_FILES);
2810 return;
2813 /* Get the attr mask from the dptr */
2814 dirtype = dptr_attr(sconn, dptr_num);
2816 backup_priv = dptr_get_priv(dirptr);
2818 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2819 "backup_priv = %d\n",
2820 dptr_num, mask, dirtype,
2821 (long)dirptr,
2822 dptr_TellDir(dirptr),
2823 (int)backup_priv));
2825 /* Initialize per TRANS2_FIND_NEXT operation data */
2826 dptr_init_search_op(dirptr);
2828 /* We don't need to check for VOL here as this is returned by
2829 a different TRANS2 call. */
2831 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2832 directory,lp_dontdescend(SNUM(conn))));
2833 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2834 dont_descend = True;
2836 p = pdata;
2837 space_remaining = max_data_bytes;
2838 out_of_space = False;
2840 if (backup_priv) {
2841 become_root();
2845 * Seek to the correct position. We no longer use the resume key but
2846 * depend on the last file name instead.
2849 if(!continue_bit && resume_name && *resume_name) {
2850 SMB_STRUCT_STAT st;
2852 long current_pos = 0;
2854 * Remember, name_to_8_3 is called by
2855 * get_lanman2_dir_entry(), so the resume name
2856 * could be mangled. Ensure we check the unmangled name.
2859 if (mangle_is_mangled(resume_name, conn->params)) {
2860 char *new_resume_name = NULL;
2861 mangle_lookup_name_from_8_3(ctx,
2862 resume_name,
2863 &new_resume_name,
2864 conn->params);
2865 if (new_resume_name) {
2866 resume_name = new_resume_name;
2871 * Fix for NT redirector problem triggered by resume key indexes
2872 * changing between directory scans. We now return a resume key of 0
2873 * and instead look for the filename to continue from (also given
2874 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2875 * findfirst/findnext (as is usual) then the directory pointer
2876 * should already be at the correct place.
2879 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2880 } /* end if resume_name && !continue_bit */
2882 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2883 bool got_exact_match = False;
2885 /* this is a heuristic to avoid seeking the dirptr except when
2886 absolutely necessary. It allows for a filename of about 40 chars */
2887 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2888 out_of_space = True;
2889 finished = False;
2890 } else {
2891 finished = !get_lanman2_dir_entry(ctx,
2892 conn,
2893 dirptr,
2894 req->flags2,
2895 mask,dirtype,info_level,
2896 requires_resume_key,dont_descend,
2897 ask_sharemode,
2898 &p,pdata,data_end,
2899 space_remaining, &out_of_space,
2900 &got_exact_match,
2901 &last_entry_off, ea_list);
2904 if (finished && out_of_space)
2905 finished = False;
2907 if (!finished && !out_of_space)
2908 numentries++;
2911 * As an optimisation if we know we aren't looking
2912 * for a wildcard name (ie. the name matches the wildcard exactly)
2913 * then we can finish on any (first) match.
2914 * This speeds up large directory searches. JRA.
2917 if(got_exact_match)
2918 finished = True;
2920 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2923 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2924 smb_fn_name(req->cmd),
2925 mask, directory, dirtype, numentries ) );
2927 /* Check if we can close the dirptr */
2928 if(close_after_request || (finished && close_if_end)) {
2929 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2930 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2933 if (backup_priv) {
2934 unbecome_root();
2937 /* Set up the return parameter block */
2938 SSVAL(params,0,numentries);
2939 SSVAL(params,2,finished);
2940 SSVAL(params,4,0); /* Never an EA error */
2941 SSVAL(params,6,last_entry_off);
2943 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2944 max_data_bytes);
2946 return;
2949 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2951 E_md4hash(lp_servicename(SNUM(conn)),objid);
2952 return objid;
2955 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2957 SMB_ASSERT(extended_info != NULL);
2959 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2960 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2961 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2962 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2963 #ifdef SAMBA_VERSION_REVISION
2964 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2965 #endif
2966 extended_info->samba_subversion = 0;
2967 #ifdef SAMBA_VERSION_RC_RELEASE
2968 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2969 #else
2970 #ifdef SAMBA_VERSION_PRE_RELEASE
2971 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2972 #endif
2973 #endif
2974 #ifdef SAMBA_VERSION_VENDOR_PATCH
2975 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2976 #endif
2977 extended_info->samba_gitcommitdate = 0;
2978 #ifdef SAMBA_VERSION_COMMIT_TIME
2979 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2980 #endif
2982 memset(extended_info->samba_version_string, 0,
2983 sizeof(extended_info->samba_version_string));
2985 snprintf (extended_info->samba_version_string,
2986 sizeof(extended_info->samba_version_string),
2987 "%s", samba_version_string());
2990 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2991 TALLOC_CTX *mem_ctx,
2992 uint16_t info_level,
2993 uint16_t flags2,
2994 unsigned int max_data_bytes,
2995 char **ppdata,
2996 int *ret_data_len)
2998 char *pdata, *end_data;
2999 int data_len = 0, len;
3000 const char *vname = volume_label(SNUM(conn));
3001 int snum = SNUM(conn);
3002 char *fstype = lp_fstype(SNUM(conn));
3003 uint32 additional_flags = 0;
3004 struct smb_filename smb_fname_dot;
3005 SMB_STRUCT_STAT st;
3007 if (IS_IPC(conn)) {
3008 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3009 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3010 "info level (0x%x) on IPC$.\n",
3011 (unsigned int)info_level));
3012 return NT_STATUS_ACCESS_DENIED;
3016 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3018 ZERO_STRUCT(smb_fname_dot);
3019 smb_fname_dot.base_name = discard_const_p(char, ".");
3021 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3022 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3023 return map_nt_error_from_unix(errno);
3026 st = smb_fname_dot.st;
3028 *ppdata = (char *)SMB_REALLOC(
3029 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3030 if (*ppdata == NULL) {
3031 return NT_STATUS_NO_MEMORY;
3034 pdata = *ppdata;
3035 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3036 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3038 switch (info_level) {
3039 case SMB_INFO_ALLOCATION:
3041 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3042 data_len = 18;
3043 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno);
3047 block_size = lp_block_size(snum);
3048 if (bsize < block_size) {
3049 uint64_t factor = block_size/bsize;
3050 bsize = block_size;
3051 dsize /= factor;
3052 dfree /= factor;
3054 if (bsize > block_size) {
3055 uint64_t factor = bsize/block_size;
3056 bsize = block_size;
3057 dsize *= factor;
3058 dfree *= factor;
3060 bytes_per_sector = 512;
3061 sectors_per_unit = bsize/bytes_per_sector;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3065 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3067 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3068 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3069 SIVAL(pdata,l1_cUnit,dsize);
3070 SIVAL(pdata,l1_cUnitAvail,dfree);
3071 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3072 break;
3075 case SMB_INFO_VOLUME:
3076 /* Return volume name */
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3083 * Win2k3 and previous mess this up by sending a name length
3084 * one byte short. I believe only older clients (OS/2 Win9x) use
3085 * this call so try fixing this by adding a terminating null to
3086 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3088 len = srvstr_push(
3089 pdata, flags2,
3090 pdata+l2_vol_szVolLabel, vname,
3091 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3092 STR_NOALIGN|STR_TERMINATE);
3093 SCVAL(pdata,l2_vol_cch,len);
3094 data_len = l2_vol_szVolLabel + len;
3095 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3096 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3097 len, vname));
3098 break;
3100 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3101 case SMB_FS_ATTRIBUTE_INFORMATION:
3103 additional_flags = 0;
3104 #if defined(HAVE_SYS_QUOTAS)
3105 additional_flags |= FILE_VOLUME_QUOTAS;
3106 #endif
3108 if(lp_nt_acl_support(SNUM(conn))) {
3109 additional_flags |= FILE_PERSISTENT_ACLS;
3112 /* Capabilities are filled in at connection time through STATVFS call */
3113 additional_flags |= conn->fs_capabilities;
3114 additional_flags |= lp_parm_int(conn->params->service,
3115 "share", "fake_fscaps",
3118 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3119 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3120 additional_flags); /* FS ATTRIBUTES */
3122 SIVAL(pdata,4,255); /* Max filename component length */
3123 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3124 and will think we can't do long filenames */
3125 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3126 PTR_DIFF(end_data, pdata+12),
3127 STR_UNICODE);
3128 SIVAL(pdata,8,len);
3129 data_len = 12 + len;
3130 break;
3132 case SMB_QUERY_FS_LABEL_INFO:
3133 case SMB_FS_LABEL_INFORMATION:
3134 len = srvstr_push(pdata, flags2, pdata+4, vname,
3135 PTR_DIFF(end_data, pdata+4), 0);
3136 data_len = 4 + len;
3137 SIVAL(pdata,0,len);
3138 break;
3140 case SMB_QUERY_FS_VOLUME_INFO:
3141 case SMB_FS_VOLUME_INFORMATION:
3144 * Add volume serial number - hash of a combination of
3145 * the called hostname and the service name.
3147 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3148 (str_checksum(get_local_machine_name())<<16));
3150 /* Max label len is 32 characters. */
3151 len = srvstr_push(pdata, flags2, pdata+18, vname,
3152 PTR_DIFF(end_data, pdata+18),
3153 STR_UNICODE);
3154 SIVAL(pdata,12,len);
3155 data_len = 18+len;
3157 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3158 (int)strlen(vname),vname, lp_servicename(snum)));
3159 break;
3161 case SMB_QUERY_FS_SIZE_INFO:
3162 case SMB_FS_SIZE_INFORMATION:
3164 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3165 data_len = 24;
3166 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3167 return map_nt_error_from_unix(errno);
3169 block_size = lp_block_size(snum);
3170 if (bsize < block_size) {
3171 uint64_t factor = block_size/bsize;
3172 bsize = block_size;
3173 dsize /= factor;
3174 dfree /= factor;
3176 if (bsize > block_size) {
3177 uint64_t factor = bsize/block_size;
3178 bsize = block_size;
3179 dsize *= factor;
3180 dfree *= factor;
3182 bytes_per_sector = 512;
3183 sectors_per_unit = bsize/bytes_per_sector;
3184 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3185 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3186 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3187 SBIG_UINT(pdata,0,dsize);
3188 SBIG_UINT(pdata,8,dfree);
3189 SIVAL(pdata,16,sectors_per_unit);
3190 SIVAL(pdata,20,bytes_per_sector);
3191 break;
3194 case SMB_FS_FULL_SIZE_INFORMATION:
3196 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3197 data_len = 32;
3198 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3199 return map_nt_error_from_unix(errno);
3201 block_size = lp_block_size(snum);
3202 if (bsize < block_size) {
3203 uint64_t factor = block_size/bsize;
3204 bsize = block_size;
3205 dsize /= factor;
3206 dfree /= factor;
3208 if (bsize > block_size) {
3209 uint64_t factor = bsize/block_size;
3210 bsize = block_size;
3211 dsize *= factor;
3212 dfree *= factor;
3214 bytes_per_sector = 512;
3215 sectors_per_unit = bsize/bytes_per_sector;
3216 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3217 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3218 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3219 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3220 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3221 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3222 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3223 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3224 break;
3227 case SMB_QUERY_FS_DEVICE_INFO:
3228 case SMB_FS_DEVICE_INFORMATION:
3230 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3232 if (!CAN_WRITE(conn)) {
3233 characteristics |= FILE_READ_ONLY_DEVICE;
3235 data_len = 8;
3236 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3237 SIVAL(pdata,4,characteristics);
3238 break;
3241 #ifdef HAVE_SYS_QUOTAS
3242 case SMB_FS_QUOTA_INFORMATION:
3244 * what we have to send --metze:
3246 * Unknown1: 24 NULL bytes
3247 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3248 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3249 * Quota Flags: 2 byte :
3250 * Unknown3: 6 NULL bytes
3252 * 48 bytes total
3254 * details for Quota Flags:
3256 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3257 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3258 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3259 * 0x0001 Enable Quotas: enable quota for this fs
3263 /* we need to fake up a fsp here,
3264 * because its not send in this call
3266 files_struct fsp;
3267 SMB_NTQUOTA_STRUCT quotas;
3269 ZERO_STRUCT(fsp);
3270 ZERO_STRUCT(quotas);
3272 fsp.conn = conn;
3273 fsp.fnum = -1;
3275 /* access check */
3276 if (get_current_uid(conn) != 0) {
3277 DEBUG(0,("set_user_quota: access_denied "
3278 "service [%s] user [%s]\n",
3279 lp_servicename(SNUM(conn)),
3280 conn->session_info->unix_info->unix_name));
3281 return NT_STATUS_ACCESS_DENIED;
3284 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3285 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3286 return map_nt_error_from_unix(errno);
3289 data_len = 48;
3291 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3292 lp_servicename(SNUM(conn))));
3294 /* Unknown1 24 NULL bytes*/
3295 SBIG_UINT(pdata,0,(uint64_t)0);
3296 SBIG_UINT(pdata,8,(uint64_t)0);
3297 SBIG_UINT(pdata,16,(uint64_t)0);
3299 /* Default Soft Quota 8 bytes */
3300 SBIG_UINT(pdata,24,quotas.softlim);
3302 /* Default Hard Quota 8 bytes */
3303 SBIG_UINT(pdata,32,quotas.hardlim);
3305 /* Quota flag 2 bytes */
3306 SSVAL(pdata,40,quotas.qflags);
3308 /* Unknown3 6 NULL bytes */
3309 SSVAL(pdata,42,0);
3310 SIVAL(pdata,44,0);
3312 break;
3314 #endif /* HAVE_SYS_QUOTAS */
3315 case SMB_FS_OBJECTID_INFORMATION:
3317 unsigned char objid[16];
3318 struct smb_extended_info extended_info;
3319 memcpy(pdata,create_volume_objectid(conn, objid),16);
3320 samba_extended_info_version (&extended_info);
3321 SIVAL(pdata,16,extended_info.samba_magic);
3322 SIVAL(pdata,20,extended_info.samba_version);
3323 SIVAL(pdata,24,extended_info.samba_subversion);
3324 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3325 memcpy(pdata+36,extended_info.samba_version_string,28);
3326 data_len = 64;
3327 break;
3331 * Query the version and capabilities of the CIFS UNIX extensions
3332 * in use.
3335 case SMB_QUERY_CIFS_UNIX_INFO:
3337 bool large_write = lp_min_receive_file_size() &&
3338 !srv_is_signing_active(conn->sconn);
3339 bool large_read = !srv_is_signing_active(conn->sconn);
3340 int encrypt_caps = 0;
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL;
3346 switch (conn->encrypt_level) {
3347 case 0:
3348 encrypt_caps = 0;
3349 break;
3350 case 1:
3351 case Auto:
3352 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3353 break;
3354 case Required:
3355 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3356 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3357 large_write = false;
3358 large_read = false;
3359 break;
3362 data_len = 12;
3363 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3364 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3366 /* We have POSIX ACLs, pathname, encryption,
3367 * large read/write, and locking capability. */
3369 SBIG_UINT(pdata,4,((uint64_t)(
3370 CIFS_UNIX_POSIX_ACLS_CAP|
3371 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3372 CIFS_UNIX_FCNTL_LOCKS_CAP|
3373 CIFS_UNIX_EXTATTR_CAP|
3374 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3375 encrypt_caps|
3376 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3377 (large_write ?
3378 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3379 break;
3382 case SMB_QUERY_POSIX_FS_INFO:
3384 int rc;
3385 vfs_statvfs_struct svfs;
3387 if (!lp_unix_extensions()) {
3388 return NT_STATUS_INVALID_LEVEL;
3391 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3393 if (!rc) {
3394 data_len = 56;
3395 SIVAL(pdata,0,svfs.OptimalTransferSize);
3396 SIVAL(pdata,4,svfs.BlockSize);
3397 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3398 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3399 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3400 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3401 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3402 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3403 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3404 #ifdef EOPNOTSUPP
3405 } else if (rc == EOPNOTSUPP) {
3406 return NT_STATUS_INVALID_LEVEL;
3407 #endif /* EOPNOTSUPP */
3408 } else {
3409 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3410 return NT_STATUS_DOS(ERRSRV, ERRerror);
3412 break;
3415 case SMB_QUERY_POSIX_WHOAMI:
3417 uint32_t flags = 0;
3418 uint32_t sid_bytes;
3419 int i;
3421 if (!lp_unix_extensions()) {
3422 return NT_STATUS_INVALID_LEVEL;
3425 if (max_data_bytes < 40) {
3426 return NT_STATUS_BUFFER_TOO_SMALL;
3429 /* We ARE guest if global_sid_Builtin_Guests is
3430 * in our list of SIDs.
3432 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3433 conn->session_info->security_token)) {
3434 flags |= SMB_WHOAMI_GUEST;
3437 /* We are NOT guest if global_sid_Authenticated_Users
3438 * is in our list of SIDs.
3440 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3441 conn->session_info->security_token)) {
3442 flags &= ~SMB_WHOAMI_GUEST;
3445 /* NOTE: 8 bytes for UID/GID, irrespective of native
3446 * platform size. This matches
3447 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3449 data_len = 4 /* flags */
3450 + 4 /* flag mask */
3451 + 8 /* uid */
3452 + 8 /* gid */
3453 + 4 /* ngroups */
3454 + 4 /* num_sids */
3455 + 4 /* SID bytes */
3456 + 4 /* pad/reserved */
3457 + (conn->session_info->unix_token->ngroups * 8)
3458 /* groups list */
3459 + (conn->session_info->security_token->num_sids *
3460 SID_MAX_SIZE)
3461 /* SID list */;
3463 SIVAL(pdata, 0, flags);
3464 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3465 SBIG_UINT(pdata, 8,
3466 (uint64_t)conn->session_info->unix_token->uid);
3467 SBIG_UINT(pdata, 16,
3468 (uint64_t)conn->session_info->unix_token->gid);
3471 if (data_len >= max_data_bytes) {
3472 /* Potential overflow, skip the GIDs and SIDs. */
3474 SIVAL(pdata, 24, 0); /* num_groups */
3475 SIVAL(pdata, 28, 0); /* num_sids */
3476 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3477 SIVAL(pdata, 36, 0); /* reserved */
3479 data_len = 40;
3480 break;
3483 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3484 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3486 /* We walk the SID list twice, but this call is fairly
3487 * infrequent, and I don't expect that it's performance
3488 * sensitive -- jpeach
3490 for (i = 0, sid_bytes = 0;
3491 i < conn->session_info->security_token->num_sids; ++i) {
3492 sid_bytes += ndr_size_dom_sid(
3493 &conn->session_info->security_token->sids[i],
3497 /* SID list byte count */
3498 SIVAL(pdata, 32, sid_bytes);
3500 /* 4 bytes pad/reserved - must be zero */
3501 SIVAL(pdata, 36, 0);
3502 data_len = 40;
3504 /* GID list */
3505 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3506 SBIG_UINT(pdata, data_len,
3507 (uint64_t)conn->session_info->unix_token->groups[i]);
3508 data_len += 8;
3511 /* SID list */
3512 for (i = 0;
3513 i < conn->session_info->security_token->num_sids; ++i) {
3514 int sid_len = ndr_size_dom_sid(
3515 &conn->session_info->security_token->sids[i],
3518 sid_linearize(pdata + data_len, sid_len,
3519 &conn->session_info->security_token->sids[i]);
3520 data_len += sid_len;
3523 break;
3526 case SMB_MAC_QUERY_FS_INFO:
3528 * Thursby MAC extension... ONLY on NTFS filesystems
3529 * once we do streams then we don't need this
3531 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3532 data_len = 88;
3533 SIVAL(pdata,84,0x100); /* Don't support mac... */
3534 break;
3536 /* drop through */
3537 default:
3538 return NT_STATUS_INVALID_LEVEL;
3541 *ret_data_len = data_len;
3542 return NT_STATUS_OK;
3545 /****************************************************************************
3546 Reply to a TRANS2_QFSINFO (query filesystem info).
3547 ****************************************************************************/
3549 static void call_trans2qfsinfo(connection_struct *conn,
3550 struct smb_request *req,
3551 char **pparams, int total_params,
3552 char **ppdata, int total_data,
3553 unsigned int max_data_bytes)
3555 char *params = *pparams;
3556 uint16_t info_level;
3557 int data_len = 0;
3558 NTSTATUS status;
3560 if (total_params < 2) {
3561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3562 return;
3565 info_level = SVAL(params,0);
3567 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3568 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3569 DEBUG(0,("call_trans2qfsinfo: encryption required "
3570 "and info level 0x%x sent.\n",
3571 (unsigned int)info_level));
3572 exit_server_cleanly("encryption required "
3573 "on connection");
3574 return;
3578 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3580 status = smbd_do_qfsinfo(conn, req,
3581 info_level,
3582 req->flags2,
3583 max_data_bytes,
3584 ppdata, &data_len);
3585 if (!NT_STATUS_IS_OK(status)) {
3586 reply_nterror(req, status);
3587 return;
3590 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3591 max_data_bytes);
3593 DEBUG( 4, ( "%s info_level = %d\n",
3594 smb_fn_name(req->cmd), info_level) );
3596 return;
3599 /****************************************************************************
3600 Reply to a TRANS2_SETFSINFO (set filesystem info).
3601 ****************************************************************************/
3603 static void call_trans2setfsinfo(connection_struct *conn,
3604 struct smb_request *req,
3605 char **pparams, int total_params,
3606 char **ppdata, int total_data,
3607 unsigned int max_data_bytes)
3609 struct smbd_server_connection *sconn = req->sconn;
3610 char *pdata = *ppdata;
3611 char *params = *pparams;
3612 uint16 info_level;
3614 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3616 /* */
3617 if (total_params < 4) {
3618 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3619 total_params));
3620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3621 return;
3624 info_level = SVAL(params,2);
3626 if (IS_IPC(conn)) {
3627 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3628 info_level != SMB_SET_CIFS_UNIX_INFO) {
3629 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3630 "info level (0x%x) on IPC$.\n",
3631 (unsigned int)info_level));
3632 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3633 return;
3637 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3638 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3639 DEBUG(0,("call_trans2setfsinfo: encryption required "
3640 "and info level 0x%x sent.\n",
3641 (unsigned int)info_level));
3642 exit_server_cleanly("encryption required "
3643 "on connection");
3644 return;
3648 switch(info_level) {
3649 case SMB_SET_CIFS_UNIX_INFO:
3650 if (!lp_unix_extensions()) {
3651 DEBUG(2,("call_trans2setfsinfo: "
3652 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3653 "unix extensions off\n"));
3654 reply_nterror(req,
3655 NT_STATUS_INVALID_LEVEL);
3656 return;
3659 /* There should be 12 bytes of capabilities set. */
3660 if (total_data < 12) {
3661 reply_nterror(
3662 req,
3663 NT_STATUS_INVALID_PARAMETER);
3664 return;
3666 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3667 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3668 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3669 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3670 /* Just print these values for now. */
3671 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3672 "major = %u, minor = %u cap_low = 0x%x, "
3673 "cap_high = 0x%xn",
3674 (unsigned int)sconn->
3675 smb1.unix_info.client_major,
3676 (unsigned int)sconn->
3677 smb1.unix_info.client_minor,
3678 (unsigned int)sconn->
3679 smb1.unix_info.client_cap_low,
3680 (unsigned int)sconn->
3681 smb1.unix_info.client_cap_high));
3683 /* Here is where we must switch to posix pathname processing... */
3684 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3685 lp_set_posix_pathnames();
3686 mangle_change_to_posix();
3689 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3690 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3691 /* Client that knows how to do posix locks,
3692 * but not posix open/mkdir operations. Set a
3693 * default type for read/write checks. */
3695 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3698 break;
3700 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3702 NTSTATUS status;
3703 size_t param_len = 0;
3704 size_t data_len = total_data;
3706 if (!lp_unix_extensions()) {
3707 reply_nterror(
3708 req,
3709 NT_STATUS_INVALID_LEVEL);
3710 return;
3713 if (lp_smb_encrypt(SNUM(conn)) == false) {
3714 reply_nterror(
3715 req,
3716 NT_STATUS_NOT_SUPPORTED);
3717 return;
3720 if (req->sconn->smb1.echo_handler.trusted_fde) {
3721 DEBUG( 2,("call_trans2setfsinfo: "
3722 "request transport encryption disabled"
3723 "with 'fork echo handler = yes'\n"));
3724 reply_nterror(
3725 req,
3726 NT_STATUS_NOT_SUPPORTED);
3727 return;
3730 DEBUG( 4,("call_trans2setfsinfo: "
3731 "request transport encryption.\n"));
3733 status = srv_request_encryption_setup(conn,
3734 (unsigned char **)ppdata,
3735 &data_len,
3736 (unsigned char **)pparams,
3737 &param_len);
3739 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3740 !NT_STATUS_IS_OK(status)) {
3741 reply_nterror(req, status);
3742 return;
3745 send_trans2_replies(conn, req,
3746 *pparams,
3747 param_len,
3748 *ppdata,
3749 data_len,
3750 max_data_bytes);
3752 if (NT_STATUS_IS_OK(status)) {
3753 /* Server-side transport
3754 * encryption is now *on*. */
3755 status = srv_encryption_start(conn);
3756 if (!NT_STATUS_IS_OK(status)) {
3757 char *reason = talloc_asprintf(talloc_tos(),
3758 "Failure in setting "
3759 "up encrypted transport: %s",
3760 nt_errstr(status));
3761 exit_server_cleanly(reason);
3764 return;
3767 case SMB_FS_QUOTA_INFORMATION:
3769 files_struct *fsp = NULL;
3770 SMB_NTQUOTA_STRUCT quotas;
3772 ZERO_STRUCT(quotas);
3774 /* access check */
3775 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3776 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3777 lp_servicename(SNUM(conn)),
3778 conn->session_info->unix_info->unix_name));
3779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3780 return;
3783 /* note: normaly there're 48 bytes,
3784 * but we didn't use the last 6 bytes for now
3785 * --metze
3787 fsp = file_fsp(req, SVAL(params,0));
3789 if (!check_fsp_ntquota_handle(conn, req,
3790 fsp)) {
3791 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3792 reply_nterror(
3793 req, NT_STATUS_INVALID_HANDLE);
3794 return;
3797 if (total_data < 42) {
3798 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3799 total_data));
3800 reply_nterror(
3801 req,
3802 NT_STATUS_INVALID_PARAMETER);
3803 return;
3806 /* unknown_1 24 NULL bytes in pdata*/
3808 /* the soft quotas 8 bytes (uint64_t)*/
3809 quotas.softlim = BVAL(pdata,24);
3811 /* the hard quotas 8 bytes (uint64_t)*/
3812 quotas.hardlim = BVAL(pdata,32);
3814 /* quota_flags 2 bytes **/
3815 quotas.qflags = SVAL(pdata,40);
3817 /* unknown_2 6 NULL bytes follow*/
3819 /* now set the quotas */
3820 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3821 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3822 reply_nterror(req, map_nt_error_from_unix(errno));
3823 return;
3826 break;
3828 default:
3829 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3830 info_level));
3831 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3832 return;
3833 break;
3837 * sending this reply works fine,
3838 * but I'm not sure it's the same
3839 * like windows do...
3840 * --metze
3842 reply_outbuf(req, 10, 0);
3845 #if defined(HAVE_POSIX_ACLS)
3846 /****************************************************************************
3847 Utility function to count the number of entries in a POSIX acl.
3848 ****************************************************************************/
3850 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3852 unsigned int ace_count = 0;
3853 int entry_id = SMB_ACL_FIRST_ENTRY;
3854 SMB_ACL_ENTRY_T entry;
3856 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3857 /* get_next... */
3858 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3859 entry_id = SMB_ACL_NEXT_ENTRY;
3861 ace_count++;
3863 return ace_count;
3866 /****************************************************************************
3867 Utility function to marshall a POSIX acl into wire format.
3868 ****************************************************************************/
3870 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3872 int entry_id = SMB_ACL_FIRST_ENTRY;
3873 SMB_ACL_ENTRY_T entry;
3875 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3876 SMB_ACL_TAG_T tagtype;
3877 SMB_ACL_PERMSET_T permset;
3878 unsigned char perms = 0;
3879 unsigned int own_grp;
3881 /* get_next... */
3882 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3883 entry_id = SMB_ACL_NEXT_ENTRY;
3886 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3887 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3888 return False;
3891 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3892 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3893 return False;
3896 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3897 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3898 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3900 SCVAL(pdata,1,perms);
3902 switch (tagtype) {
3903 case SMB_ACL_USER_OBJ:
3904 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3905 own_grp = (unsigned int)pst->st_ex_uid;
3906 SIVAL(pdata,2,own_grp);
3907 SIVAL(pdata,6,0);
3908 break;
3909 case SMB_ACL_USER:
3911 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3912 if (!puid) {
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3914 return False;
3916 own_grp = (unsigned int)*puid;
3917 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3918 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3919 SIVAL(pdata,2,own_grp);
3920 SIVAL(pdata,6,0);
3921 break;
3923 case SMB_ACL_GROUP_OBJ:
3924 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3925 own_grp = (unsigned int)pst->st_ex_gid;
3926 SIVAL(pdata,2,own_grp);
3927 SIVAL(pdata,6,0);
3928 break;
3929 case SMB_ACL_GROUP:
3931 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3932 if (!pgid) {
3933 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3934 return False;
3936 own_grp = (unsigned int)*pgid;
3937 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3938 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3939 SIVAL(pdata,2,own_grp);
3940 SIVAL(pdata,6,0);
3941 break;
3943 case SMB_ACL_MASK:
3944 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3945 SIVAL(pdata,2,0xFFFFFFFF);
3946 SIVAL(pdata,6,0xFFFFFFFF);
3947 break;
3948 case SMB_ACL_OTHER:
3949 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3950 SIVAL(pdata,2,0xFFFFFFFF);
3951 SIVAL(pdata,6,0xFFFFFFFF);
3952 break;
3953 default:
3954 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3955 return False;
3957 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3960 return True;
3962 #endif
3964 /****************************************************************************
3965 Store the FILE_UNIX_BASIC info.
3966 ****************************************************************************/
3968 static char *store_file_unix_basic(connection_struct *conn,
3969 char *pdata,
3970 files_struct *fsp,
3971 const SMB_STRUCT_STAT *psbuf)
3973 uint64_t file_index = get_FileIndex(conn, psbuf);
3975 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3976 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3978 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3979 pdata += 8;
3981 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3982 pdata += 8;
3984 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3985 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3986 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3987 pdata += 24;
3989 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3990 SIVAL(pdata,4,0);
3991 pdata += 8;
3993 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3994 SIVAL(pdata,4,0);
3995 pdata += 8;
3997 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3998 pdata += 4;
4000 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
4001 SIVAL(pdata,4,0);
4002 pdata += 8;
4004 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
4005 SIVAL(pdata,4,0);
4006 pdata += 8;
4008 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4009 pdata += 8;
4011 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4012 SIVAL(pdata,4,0);
4013 pdata += 8;
4015 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4016 SIVAL(pdata,4,0);
4017 pdata += 8;
4019 return pdata;
4022 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4023 * the chflags(2) (or equivalent) flags.
4025 * XXX: this really should be behind the VFS interface. To do this, we would
4026 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4027 * Each VFS module could then implement its own mapping as appropriate for the
4028 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4030 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4031 info2_flags_map[] =
4033 #ifdef UF_NODUMP
4034 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4035 #endif
4037 #ifdef UF_IMMUTABLE
4038 { UF_IMMUTABLE, EXT_IMMUTABLE },
4039 #endif
4041 #ifdef UF_APPEND
4042 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4043 #endif
4045 #ifdef UF_HIDDEN
4046 { UF_HIDDEN, EXT_HIDDEN },
4047 #endif
4049 /* Do not remove. We need to guarantee that this array has at least one
4050 * entry to build on HP-UX.
4052 { 0, 0 }
4056 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4057 uint32 *smb_fflags, uint32 *smb_fmask)
4059 int i;
4061 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4062 *smb_fmask |= info2_flags_map[i].smb_fflag;
4063 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4064 *smb_fflags |= info2_flags_map[i].smb_fflag;
4069 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4070 const uint32 smb_fflags,
4071 const uint32 smb_fmask,
4072 int *stat_fflags)
4074 uint32 max_fmask = 0;
4075 int i;
4077 *stat_fflags = psbuf->st_ex_flags;
4079 /* For each flags requested in smb_fmask, check the state of the
4080 * corresponding flag in smb_fflags and set or clear the matching
4081 * stat flag.
4084 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4085 max_fmask |= info2_flags_map[i].smb_fflag;
4086 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4087 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4088 *stat_fflags |= info2_flags_map[i].stat_fflag;
4089 } else {
4090 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4095 /* If smb_fmask is asking to set any bits that are not supported by
4096 * our flag mappings, we should fail.
4098 if ((smb_fmask & max_fmask) != smb_fmask) {
4099 return False;
4102 return True;
4106 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4107 * of file flags and birth (create) time.
4109 static char *store_file_unix_basic_info2(connection_struct *conn,
4110 char *pdata,
4111 files_struct *fsp,
4112 const SMB_STRUCT_STAT *psbuf)
4114 uint32 file_flags = 0;
4115 uint32 flags_mask = 0;
4117 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4119 /* Create (birth) time 64 bit */
4120 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4121 pdata += 8;
4123 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4124 SIVAL(pdata, 0, file_flags); /* flags */
4125 SIVAL(pdata, 4, flags_mask); /* mask */
4126 pdata += 8;
4128 return pdata;
4131 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4132 const struct stream_struct *streams,
4133 char *data,
4134 unsigned int max_data_bytes,
4135 unsigned int *data_size)
4137 unsigned int i;
4138 unsigned int ofs = 0;
4140 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4141 unsigned int next_offset;
4142 size_t namelen;
4143 smb_ucs2_t *namebuf;
4145 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4146 streams[i].name, &namelen) ||
4147 namelen <= 2)
4149 return NT_STATUS_INVALID_PARAMETER;
4153 * name_buf is now null-terminated, we need to marshall as not
4154 * terminated
4157 namelen -= 2;
4159 SIVAL(data, ofs+4, namelen);
4160 SOFF_T(data, ofs+8, streams[i].size);
4161 SOFF_T(data, ofs+16, streams[i].alloc_size);
4162 memcpy(data+ofs+24, namebuf, namelen);
4163 TALLOC_FREE(namebuf);
4165 next_offset = ofs + 24 + namelen;
4167 if (i == num_streams-1) {
4168 SIVAL(data, ofs, 0);
4170 else {
4171 unsigned int align = ndr_align_size(next_offset, 8);
4173 memset(data+next_offset, 0, align);
4174 next_offset += align;
4176 SIVAL(data, ofs, next_offset - ofs);
4177 ofs = next_offset;
4180 ofs = next_offset;
4183 *data_size = ofs;
4185 return NT_STATUS_OK;
4188 /****************************************************************************
4189 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4190 ****************************************************************************/
4192 static void call_trans2qpipeinfo(connection_struct *conn,
4193 struct smb_request *req,
4194 unsigned int tran_call,
4195 char **pparams, int total_params,
4196 char **ppdata, int total_data,
4197 unsigned int max_data_bytes)
4199 char *params = *pparams;
4200 char *pdata = *ppdata;
4201 unsigned int data_size = 0;
4202 unsigned int param_size = 2;
4203 uint16 info_level;
4204 files_struct *fsp;
4206 if (!params) {
4207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4208 return;
4211 if (total_params < 4) {
4212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4213 return;
4216 fsp = file_fsp(req, SVAL(params,0));
4217 if (!fsp_is_np(fsp)) {
4218 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4219 return;
4222 info_level = SVAL(params,2);
4224 *pparams = (char *)SMB_REALLOC(*pparams,2);
4225 if (*pparams == NULL) {
4226 reply_nterror(req, NT_STATUS_NO_MEMORY);
4227 return;
4229 params = *pparams;
4230 SSVAL(params,0,0);
4231 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4232 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4233 if (*ppdata == NULL ) {
4234 reply_nterror(req, NT_STATUS_NO_MEMORY);
4235 return;
4237 pdata = *ppdata;
4239 switch (info_level) {
4240 case SMB_FILE_STANDARD_INFORMATION:
4241 memset(pdata,0,24);
4242 SOFF_T(pdata,0,4096LL);
4243 SIVAL(pdata,16,1);
4244 SIVAL(pdata,20,1);
4245 data_size = 24;
4246 break;
4248 default:
4249 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4250 return;
4253 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4254 max_data_bytes);
4256 return;
4259 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4260 TALLOC_CTX *mem_ctx,
4261 uint16_t info_level,
4262 files_struct *fsp,
4263 struct smb_filename *smb_fname,
4264 bool delete_pending,
4265 struct timespec write_time_ts,
4266 struct ea_list *ea_list,
4267 int lock_data_count,
4268 char *lock_data,
4269 uint16_t flags2,
4270 unsigned int max_data_bytes,
4271 char **ppdata,
4272 unsigned int *pdata_size)
4274 char *pdata = *ppdata;
4275 char *dstart, *dend;
4276 unsigned int data_size;
4277 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4278 time_t create_time, mtime, atime, c_time;
4279 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4280 char *p;
4281 char *base_name;
4282 char *dos_fname;
4283 int mode;
4284 int nlink;
4285 NTSTATUS status;
4286 uint64_t file_size = 0;
4287 uint64_t pos = 0;
4288 uint64_t allocation_size = 0;
4289 uint64_t file_index = 0;
4290 uint32_t access_mask = 0;
4292 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4293 return NT_STATUS_INVALID_LEVEL;
4296 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4297 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4298 info_level, max_data_bytes));
4300 mode = dos_mode(conn, smb_fname);
4301 nlink = psbuf->st_ex_nlink;
4303 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4304 nlink = 1;
4307 if ((nlink > 0) && delete_pending) {
4308 nlink -= 1;
4311 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4312 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4313 if (*ppdata == NULL) {
4314 return NT_STATUS_NO_MEMORY;
4316 pdata = *ppdata;
4317 dstart = pdata;
4318 dend = dstart + data_size - 1;
4320 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4321 update_stat_ex_mtime(psbuf, write_time_ts);
4324 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4325 mtime_ts = psbuf->st_ex_mtime;
4326 atime_ts = psbuf->st_ex_atime;
4327 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4329 if (lp_dos_filetime_resolution(SNUM(conn))) {
4330 dos_filetime_timespec(&create_time_ts);
4331 dos_filetime_timespec(&mtime_ts);
4332 dos_filetime_timespec(&atime_ts);
4333 dos_filetime_timespec(&ctime_ts);
4336 create_time = convert_timespec_to_time_t(create_time_ts);
4337 mtime = convert_timespec_to_time_t(mtime_ts);
4338 atime = convert_timespec_to_time_t(atime_ts);
4339 c_time = convert_timespec_to_time_t(ctime_ts);
4341 p = strrchr_m(smb_fname->base_name,'/');
4342 if (!p)
4343 base_name = smb_fname->base_name;
4344 else
4345 base_name = p+1;
4347 /* NT expects the name to be in an exact form of the *full*
4348 filename. See the trans2 torture test */
4349 if (ISDOT(base_name)) {
4350 dos_fname = talloc_strdup(mem_ctx, "\\");
4351 if (!dos_fname) {
4352 return NT_STATUS_NO_MEMORY;
4354 } else {
4355 dos_fname = talloc_asprintf(mem_ctx,
4356 "\\%s",
4357 smb_fname->base_name);
4358 if (!dos_fname) {
4359 return NT_STATUS_NO_MEMORY;
4361 if (is_ntfs_stream_smb_fname(smb_fname)) {
4362 dos_fname = talloc_asprintf(dos_fname, "%s",
4363 smb_fname->stream_name);
4364 if (!dos_fname) {
4365 return NT_STATUS_NO_MEMORY;
4369 string_replace(dos_fname, '/', '\\');
4372 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4374 if (!fsp) {
4375 /* Do we have this path open ? */
4376 files_struct *fsp1;
4377 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4378 fsp1 = file_find_di_first(conn->sconn, fileid);
4379 if (fsp1 && fsp1->initial_allocation_size) {
4380 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4384 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4385 file_size = get_file_size_stat(psbuf);
4388 if (fsp) {
4389 pos = fsp->fh->position_information;
4392 if (fsp) {
4393 access_mask = fsp->access_mask;
4394 } else {
4395 /* GENERIC_EXECUTE mapping from Windows */
4396 access_mask = 0x12019F;
4399 /* This should be an index number - looks like
4400 dev/ino to me :-)
4402 I think this causes us to fail the IFSKIT
4403 BasicFileInformationTest. -tpot */
4404 file_index = get_FileIndex(conn, psbuf);
4406 switch (info_level) {
4407 case SMB_INFO_STANDARD:
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4409 data_size = 22;
4410 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4411 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4412 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4413 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4414 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4415 SSVAL(pdata,l1_attrFile,mode);
4416 break;
4418 case SMB_INFO_QUERY_EA_SIZE:
4420 unsigned int ea_size =
4421 estimate_ea_size(conn, fsp,
4422 smb_fname->base_name);
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4424 data_size = 26;
4425 srv_put_dos_date2(pdata,0,create_time);
4426 srv_put_dos_date2(pdata,4,atime);
4427 srv_put_dos_date2(pdata,8,mtime); /* write time */
4428 SIVAL(pdata,12,(uint32)file_size);
4429 SIVAL(pdata,16,(uint32)allocation_size);
4430 SSVAL(pdata,20,mode);
4431 SIVAL(pdata,22,ea_size);
4432 break;
4435 case SMB_INFO_IS_NAME_VALID:
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4437 if (fsp) {
4438 /* os/2 needs this ? really ?*/
4439 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4441 /* This is only reached for qpathinfo */
4442 data_size = 0;
4443 break;
4445 case SMB_INFO_QUERY_EAS_FROM_LIST:
4447 size_t total_ea_len = 0;
4448 struct ea_list *ea_file_list = NULL;
4450 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4452 ea_file_list =
4453 get_ea_list_from_file(mem_ctx, conn, fsp,
4454 smb_fname->base_name,
4455 &total_ea_len);
4456 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4458 if (!ea_list || (total_ea_len > data_size)) {
4459 data_size = 4;
4460 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4461 break;
4464 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4465 break;
4468 case SMB_INFO_QUERY_ALL_EAS:
4470 /* We have data_size bytes to put EA's into. */
4471 size_t total_ea_len = 0;
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4475 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4476 smb_fname->base_name,
4477 &total_ea_len);
4478 if (!ea_list || (total_ea_len > data_size)) {
4479 data_size = 4;
4480 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4481 break;
4484 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4485 break;
4488 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4490 /* This is FileFullEaInformation - 0xF which maps to
4491 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4493 /* We have data_size bytes to put EA's into. */
4494 size_t total_ea_len = 0;
4495 struct ea_list *ea_file_list = NULL;
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4499 /*TODO: add filtering and index handling */
4501 ea_file_list =
4502 get_ea_list_from_file(mem_ctx, conn, fsp,
4503 smb_fname->base_name,
4504 &total_ea_len);
4505 if (!ea_file_list) {
4506 return NT_STATUS_NO_EAS_ON_FILE;
4509 status = fill_ea_chained_buffer(mem_ctx,
4510 pdata,
4511 data_size,
4512 &data_size,
4513 conn, ea_file_list);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 return status;
4517 break;
4520 case SMB_FILE_BASIC_INFORMATION:
4521 case SMB_QUERY_FILE_BASIC_INFO:
4523 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4525 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4526 } else {
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4528 data_size = 40;
4529 SIVAL(pdata,36,0);
4531 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4532 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4533 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4534 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4535 SIVAL(pdata,32,mode);
4537 DEBUG(5,("SMB_QFBI - "));
4538 DEBUG(5,("create: %s ", ctime(&create_time)));
4539 DEBUG(5,("access: %s ", ctime(&atime)));
4540 DEBUG(5,("write: %s ", ctime(&mtime)));
4541 DEBUG(5,("change: %s ", ctime(&c_time)));
4542 DEBUG(5,("mode: %x\n", mode));
4543 break;
4545 case SMB_FILE_STANDARD_INFORMATION:
4546 case SMB_QUERY_FILE_STANDARD_INFO:
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4549 data_size = 24;
4550 SOFF_T(pdata,0,allocation_size);
4551 SOFF_T(pdata,8,file_size);
4552 SIVAL(pdata,16,nlink);
4553 SCVAL(pdata,20,delete_pending?1:0);
4554 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4555 SSVAL(pdata,22,0); /* Padding. */
4556 break;
4558 case SMB_FILE_EA_INFORMATION:
4559 case SMB_QUERY_FILE_EA_INFO:
4561 unsigned int ea_size =
4562 estimate_ea_size(conn, fsp, smb_fname->base_name);
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4564 data_size = 4;
4565 SIVAL(pdata,0,ea_size);
4566 break;
4569 /* Get the 8.3 name - used if NT SMB was negotiated. */
4570 case SMB_QUERY_FILE_ALT_NAME_INFO:
4571 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4573 int len;
4574 char mangled_name[13];
4575 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4576 if (!name_to_8_3(base_name,mangled_name,
4577 True,conn->params)) {
4578 return NT_STATUS_NO_MEMORY;
4580 len = srvstr_push(dstart, flags2,
4581 pdata+4, mangled_name,
4582 PTR_DIFF(dend, pdata+4),
4583 STR_UNICODE);
4584 data_size = 4 + len;
4585 SIVAL(pdata,0,len);
4586 break;
4589 case SMB_QUERY_FILE_NAME_INFO:
4591 int len;
4593 this must be *exactly* right for ACLs on mapped drives to work
4595 len = srvstr_push(dstart, flags2,
4596 pdata+4, dos_fname,
4597 PTR_DIFF(dend, pdata+4),
4598 STR_UNICODE);
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4600 data_size = 4 + len;
4601 SIVAL(pdata,0,len);
4602 break;
4605 case SMB_FILE_ALLOCATION_INFORMATION:
4606 case SMB_QUERY_FILE_ALLOCATION_INFO:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4608 data_size = 8;
4609 SOFF_T(pdata,0,allocation_size);
4610 break;
4612 case SMB_FILE_END_OF_FILE_INFORMATION:
4613 case SMB_QUERY_FILE_END_OF_FILEINFO:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4615 data_size = 8;
4616 SOFF_T(pdata,0,file_size);
4617 break;
4619 case SMB_QUERY_FILE_ALL_INFO:
4620 case SMB_FILE_ALL_INFORMATION:
4622 int len;
4623 unsigned int ea_size =
4624 estimate_ea_size(conn, fsp, smb_fname->base_name);
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4626 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4627 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4628 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4629 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4630 SIVAL(pdata,32,mode);
4631 SIVAL(pdata,36,0); /* padding. */
4632 pdata += 40;
4633 SOFF_T(pdata,0,allocation_size);
4634 SOFF_T(pdata,8,file_size);
4635 SIVAL(pdata,16,nlink);
4636 SCVAL(pdata,20,delete_pending);
4637 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4638 SSVAL(pdata,22,0);
4639 pdata += 24;
4640 SIVAL(pdata,0,ea_size);
4641 pdata += 4; /* EA info */
4642 len = srvstr_push(dstart, flags2,
4643 pdata+4, dos_fname,
4644 PTR_DIFF(dend, pdata+4),
4645 STR_UNICODE);
4646 SIVAL(pdata,0,len);
4647 pdata += 4 + len;
4648 data_size = PTR_DIFF(pdata,(*ppdata));
4649 break;
4652 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4654 int len;
4655 unsigned int ea_size =
4656 estimate_ea_size(conn, fsp, smb_fname->base_name);
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4658 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4659 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4660 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4661 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4662 SIVAL(pdata, 0x20, mode);
4663 SIVAL(pdata, 0x24, 0); /* padding. */
4664 SBVAL(pdata, 0x28, allocation_size);
4665 SBVAL(pdata, 0x30, file_size);
4666 SIVAL(pdata, 0x38, nlink);
4667 SCVAL(pdata, 0x3C, delete_pending);
4668 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4669 SSVAL(pdata, 0x3E, 0); /* padding */
4670 SBVAL(pdata, 0x40, file_index);
4671 SIVAL(pdata, 0x48, ea_size);
4672 SIVAL(pdata, 0x4C, access_mask);
4673 SBVAL(pdata, 0x50, pos);
4674 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4675 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4677 pdata += 0x60;
4679 len = srvstr_push(dstart, flags2,
4680 pdata+4, dos_fname,
4681 PTR_DIFF(dend, pdata+4),
4682 STR_UNICODE);
4683 SIVAL(pdata,0,len);
4684 pdata += 4 + len;
4685 data_size = PTR_DIFF(pdata,(*ppdata));
4686 break;
4688 case SMB_FILE_INTERNAL_INFORMATION:
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4691 SBVAL(pdata, 0, file_index);
4692 data_size = 8;
4693 break;
4695 case SMB_FILE_ACCESS_INFORMATION:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4697 SIVAL(pdata, 0, access_mask);
4698 data_size = 4;
4699 break;
4701 case SMB_FILE_NAME_INFORMATION:
4702 /* Pathname with leading '\'. */
4704 size_t byte_len;
4705 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4707 SIVAL(pdata,0,byte_len);
4708 data_size = 4 + byte_len;
4709 break;
4712 case SMB_FILE_DISPOSITION_INFORMATION:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4714 data_size = 1;
4715 SCVAL(pdata,0,delete_pending);
4716 break;
4718 case SMB_FILE_POSITION_INFORMATION:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4720 data_size = 8;
4721 SOFF_T(pdata,0,pos);
4722 break;
4724 case SMB_FILE_MODE_INFORMATION:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4726 SIVAL(pdata,0,mode);
4727 data_size = 4;
4728 break;
4730 case SMB_FILE_ALIGNMENT_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4732 SIVAL(pdata,0,0); /* No alignment needed. */
4733 data_size = 4;
4734 break;
4737 * NT4 server just returns "invalid query" to this - if we try
4738 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4739 * want this. JRA.
4741 /* The first statement above is false - verified using Thursby
4742 * client against NT4 -- gcolley.
4744 case SMB_QUERY_FILE_STREAM_INFO:
4745 case SMB_FILE_STREAM_INFORMATION: {
4746 unsigned int num_streams = 0;
4747 struct stream_struct *streams = NULL;
4749 DEBUG(10,("smbd_do_qfilepathinfo: "
4750 "SMB_FILE_STREAM_INFORMATION\n"));
4752 if (is_ntfs_stream_smb_fname(smb_fname)) {
4753 return NT_STATUS_INVALID_PARAMETER;
4756 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4757 talloc_tos(), &num_streams, &streams);
4759 if (!NT_STATUS_IS_OK(status)) {
4760 DEBUG(10, ("could not get stream info: %s\n",
4761 nt_errstr(status)));
4762 return status;
4765 status = marshall_stream_info(num_streams, streams,
4766 pdata, max_data_bytes,
4767 &data_size);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 DEBUG(10, ("marshall_stream_info failed: %s\n",
4771 nt_errstr(status)));
4772 return status;
4775 TALLOC_FREE(streams);
4777 break;
4779 case SMB_QUERY_COMPRESSION_INFO:
4780 case SMB_FILE_COMPRESSION_INFORMATION:
4781 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4782 SOFF_T(pdata,0,file_size);
4783 SIVAL(pdata,8,0); /* ??? */
4784 SIVAL(pdata,12,0); /* ??? */
4785 data_size = 16;
4786 break;
4788 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4790 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4791 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4792 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4793 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4794 SOFF_T(pdata,32,allocation_size);
4795 SOFF_T(pdata,40,file_size);
4796 SIVAL(pdata,48,mode);
4797 SIVAL(pdata,52,0); /* ??? */
4798 data_size = 56;
4799 break;
4801 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4803 SIVAL(pdata,0,mode);
4804 SIVAL(pdata,4,0);
4805 data_size = 8;
4806 break;
4809 * CIFS UNIX Extensions.
4812 case SMB_QUERY_FILE_UNIX_BASIC:
4814 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4815 data_size = PTR_DIFF(pdata,(*ppdata));
4817 DEBUG(4,("smbd_do_qfilepathinfo: "
4818 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4819 dump_data(4, (uint8_t *)(*ppdata), data_size);
4821 break;
4823 case SMB_QUERY_FILE_UNIX_INFO2:
4825 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4826 data_size = PTR_DIFF(pdata,(*ppdata));
4829 int i;
4830 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4832 for (i=0; i<100; i++)
4833 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4834 DEBUG(4,("\n"));
4837 break;
4839 case SMB_QUERY_FILE_UNIX_LINK:
4841 int len;
4842 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4844 if (!buffer) {
4845 return NT_STATUS_NO_MEMORY;
4848 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4849 #ifdef S_ISLNK
4850 if(!S_ISLNK(psbuf->st_ex_mode)) {
4851 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4853 #else
4854 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4855 #endif
4856 len = SMB_VFS_READLINK(conn,
4857 smb_fname->base_name,
4858 buffer, PATH_MAX);
4859 if (len == -1) {
4860 return map_nt_error_from_unix(errno);
4862 buffer[len] = 0;
4863 len = srvstr_push(dstart, flags2,
4864 pdata, buffer,
4865 PTR_DIFF(dend, pdata),
4866 STR_TERMINATE);
4867 pdata += len;
4868 data_size = PTR_DIFF(pdata,(*ppdata));
4870 break;
4873 #if defined(HAVE_POSIX_ACLS)
4874 case SMB_QUERY_POSIX_ACL:
4876 SMB_ACL_T file_acl = NULL;
4877 SMB_ACL_T def_acl = NULL;
4878 uint16 num_file_acls = 0;
4879 uint16 num_def_acls = 0;
4881 if (fsp && fsp->fh->fd != -1) {
4882 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4883 } else {
4884 file_acl =
4885 SMB_VFS_SYS_ACL_GET_FILE(conn,
4886 smb_fname->base_name,
4887 SMB_ACL_TYPE_ACCESS);
4890 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4891 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4892 "not implemented on "
4893 "filesystem containing %s\n",
4894 smb_fname->base_name));
4895 return NT_STATUS_NOT_IMPLEMENTED;
4898 if (S_ISDIR(psbuf->st_ex_mode)) {
4899 if (fsp && fsp->is_directory) {
4900 def_acl =
4901 SMB_VFS_SYS_ACL_GET_FILE(
4902 conn,
4903 fsp->fsp_name->base_name,
4904 SMB_ACL_TYPE_DEFAULT);
4905 } else {
4906 def_acl =
4907 SMB_VFS_SYS_ACL_GET_FILE(
4908 conn,
4909 smb_fname->base_name,
4910 SMB_ACL_TYPE_DEFAULT);
4912 def_acl = free_empty_sys_acl(conn, def_acl);
4915 num_file_acls = count_acl_entries(conn, file_acl);
4916 num_def_acls = count_acl_entries(conn, def_acl);
4918 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4919 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4920 data_size,
4921 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4922 SMB_POSIX_ACL_HEADER_SIZE) ));
4923 if (file_acl) {
4924 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4926 if (def_acl) {
4927 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4929 return NT_STATUS_BUFFER_TOO_SMALL;
4932 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4933 SSVAL(pdata,2,num_file_acls);
4934 SSVAL(pdata,4,num_def_acls);
4935 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4936 if (file_acl) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4939 if (def_acl) {
4940 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4942 return NT_STATUS_INTERNAL_ERROR;
4944 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4945 if (file_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4948 if (def_acl) {
4949 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4951 return NT_STATUS_INTERNAL_ERROR;
4954 if (file_acl) {
4955 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4957 if (def_acl) {
4958 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4960 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4961 break;
4963 #endif
4966 case SMB_QUERY_POSIX_LOCK:
4968 uint64_t count;
4969 uint64_t offset;
4970 uint64_t smblctx;
4971 enum brl_type lock_type;
4973 /* We need an open file with a real fd for this. */
4974 if (!fsp || fsp->fh->fd == -1) {
4975 return NT_STATUS_INVALID_LEVEL;
4978 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4979 return NT_STATUS_INVALID_PARAMETER;
4982 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4983 case POSIX_LOCK_TYPE_READ:
4984 lock_type = READ_LOCK;
4985 break;
4986 case POSIX_LOCK_TYPE_WRITE:
4987 lock_type = WRITE_LOCK;
4988 break;
4989 case POSIX_LOCK_TYPE_UNLOCK:
4990 default:
4991 /* There's no point in asking for an unlock... */
4992 return NT_STATUS_INVALID_PARAMETER;
4995 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4996 #if defined(HAVE_LONGLONG)
4997 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4998 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4999 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5000 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5001 #else /* HAVE_LONGLONG */
5002 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5003 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5004 #endif /* HAVE_LONGLONG */
5006 status = query_lock(fsp,
5007 &smblctx,
5008 &count,
5009 &offset,
5010 &lock_type,
5011 POSIX_LOCK);
5013 if (ERROR_WAS_LOCK_DENIED(status)) {
5014 /* Here we need to report who has it locked... */
5015 data_size = POSIX_LOCK_DATA_SIZE;
5017 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5018 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5019 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5020 #if defined(HAVE_LONGLONG)
5021 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5022 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5023 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5024 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5025 #else /* HAVE_LONGLONG */
5026 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5027 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5028 #endif /* HAVE_LONGLONG */
5030 } else if (NT_STATUS_IS_OK(status)) {
5031 /* For success we just return a copy of what we sent
5032 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5033 data_size = POSIX_LOCK_DATA_SIZE;
5034 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5035 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5036 } else {
5037 return status;
5039 break;
5042 default:
5043 return NT_STATUS_INVALID_LEVEL;
5046 *pdata_size = data_size;
5047 return NT_STATUS_OK;
5050 /****************************************************************************
5051 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5052 file name or file id).
5053 ****************************************************************************/
5055 static void call_trans2qfilepathinfo(connection_struct *conn,
5056 struct smb_request *req,
5057 unsigned int tran_call,
5058 char **pparams, int total_params,
5059 char **ppdata, int total_data,
5060 unsigned int max_data_bytes)
5062 char *params = *pparams;
5063 char *pdata = *ppdata;
5064 uint16 info_level;
5065 unsigned int data_size = 0;
5066 unsigned int param_size = 2;
5067 struct smb_filename *smb_fname = NULL;
5068 bool delete_pending = False;
5069 struct timespec write_time_ts;
5070 files_struct *fsp = NULL;
5071 struct file_id fileid;
5072 struct ea_list *ea_list = NULL;
5073 int lock_data_count = 0;
5074 char *lock_data = NULL;
5075 NTSTATUS status = NT_STATUS_OK;
5077 if (!params) {
5078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5079 return;
5082 ZERO_STRUCT(write_time_ts);
5084 if (tran_call == TRANSACT2_QFILEINFO) {
5085 if (total_params < 4) {
5086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5087 return;
5090 if (IS_IPC(conn)) {
5091 call_trans2qpipeinfo(conn, req, tran_call,
5092 pparams, total_params,
5093 ppdata, total_data,
5094 max_data_bytes);
5095 return;
5098 fsp = file_fsp(req, SVAL(params,0));
5099 info_level = SVAL(params,2);
5101 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5103 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5104 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5105 return;
5108 /* Initial check for valid fsp ptr. */
5109 if (!check_fsp_open(conn, req, fsp)) {
5110 return;
5113 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5114 &smb_fname);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 reply_nterror(req, status);
5117 return;
5120 if(fsp->fake_file_handle) {
5122 * This is actually for the QUOTA_FAKE_FILE --metze
5125 /* We know this name is ok, it's already passed the checks. */
5127 } else if(fsp->fh->fd == -1) {
5129 * This is actually a QFILEINFO on a directory
5130 * handle (returned from an NT SMB). NT5.0 seems
5131 * to do this call. JRA.
5134 if (INFO_LEVEL_IS_UNIX(info_level)) {
5135 /* Always do lstat for UNIX calls. */
5136 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5137 DEBUG(3,("call_trans2qfilepathinfo: "
5138 "SMB_VFS_LSTAT of %s failed "
5139 "(%s)\n",
5140 smb_fname_str_dbg(smb_fname),
5141 strerror(errno)));
5142 reply_nterror(req,
5143 map_nt_error_from_unix(errno));
5144 return;
5146 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5147 DEBUG(3,("call_trans2qfilepathinfo: "
5148 "SMB_VFS_STAT of %s failed (%s)\n",
5149 smb_fname_str_dbg(smb_fname),
5150 strerror(errno)));
5151 reply_nterror(req,
5152 map_nt_error_from_unix(errno));
5153 return;
5156 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5157 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5158 } else {
5160 * Original code - this is an open file.
5162 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5163 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5164 fsp->fnum, strerror(errno)));
5165 reply_nterror(req,
5166 map_nt_error_from_unix(errno));
5167 return;
5169 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5170 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5173 } else {
5174 uint32_t name_hash;
5175 char *fname = NULL;
5176 uint32_t ucf_flags = 0;
5178 /* qpathinfo */
5179 if (total_params < 7) {
5180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5181 return;
5184 info_level = SVAL(params,0);
5186 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5188 if (INFO_LEVEL_IS_UNIX(info_level)) {
5189 if (!lp_unix_extensions()) {
5190 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5191 return;
5193 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5194 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5195 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5196 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5200 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5201 total_params - 6,
5202 STR_TERMINATE, &status);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 reply_nterror(req, status);
5205 return;
5208 status = filename_convert(req,
5209 conn,
5210 req->flags2 & FLAGS2_DFS_PATHNAMES,
5211 fname,
5212 ucf_flags,
5213 NULL,
5214 &smb_fname);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5217 reply_botherror(req,
5218 NT_STATUS_PATH_NOT_COVERED,
5219 ERRSRV, ERRbadpath);
5220 return;
5222 reply_nterror(req, status);
5223 return;
5226 /* If this is a stream, check if there is a delete_pending. */
5227 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5228 && is_ntfs_stream_smb_fname(smb_fname)) {
5229 struct smb_filename *smb_fname_base = NULL;
5231 /* Create an smb_filename with stream_name == NULL. */
5232 status =
5233 create_synthetic_smb_fname(talloc_tos(),
5234 smb_fname->base_name,
5235 NULL, NULL,
5236 &smb_fname_base);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 reply_nterror(req, status);
5239 return;
5242 if (INFO_LEVEL_IS_UNIX(info_level)) {
5243 /* Always do lstat for UNIX calls. */
5244 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5245 DEBUG(3,("call_trans2qfilepathinfo: "
5246 "SMB_VFS_LSTAT of %s failed "
5247 "(%s)\n",
5248 smb_fname_str_dbg(smb_fname_base),
5249 strerror(errno)));
5250 TALLOC_FREE(smb_fname_base);
5251 reply_nterror(req,
5252 map_nt_error_from_unix(errno));
5253 return;
5255 } else {
5256 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5257 DEBUG(3,("call_trans2qfilepathinfo: "
5258 "fileinfo of %s failed "
5259 "(%s)\n",
5260 smb_fname_str_dbg(smb_fname_base),
5261 strerror(errno)));
5262 TALLOC_FREE(smb_fname_base);
5263 reply_nterror(req,
5264 map_nt_error_from_unix(errno));
5265 return;
5269 status = file_name_hash(conn,
5270 smb_fname_str_dbg(smb_fname_base),
5271 &name_hash);
5272 if (!NT_STATUS_IS_OK(status)) {
5273 TALLOC_FREE(smb_fname_base);
5274 reply_nterror(req, status);
5275 return;
5278 fileid = vfs_file_id_from_sbuf(conn,
5279 &smb_fname_base->st);
5280 TALLOC_FREE(smb_fname_base);
5281 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5282 if (delete_pending) {
5283 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5284 return;
5288 if (INFO_LEVEL_IS_UNIX(info_level)) {
5289 /* Always do lstat for UNIX calls. */
5290 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5291 DEBUG(3,("call_trans2qfilepathinfo: "
5292 "SMB_VFS_LSTAT of %s failed (%s)\n",
5293 smb_fname_str_dbg(smb_fname),
5294 strerror(errno)));
5295 reply_nterror(req,
5296 map_nt_error_from_unix(errno));
5297 return;
5300 } else {
5301 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5302 DEBUG(3,("call_trans2qfilepathinfo: "
5303 "SMB_VFS_STAT of %s failed (%s)\n",
5304 smb_fname_str_dbg(smb_fname),
5305 strerror(errno)));
5306 reply_nterror(req,
5307 map_nt_error_from_unix(errno));
5308 return;
5312 status = file_name_hash(conn,
5313 smb_fname_str_dbg(smb_fname),
5314 &name_hash);
5315 if (!NT_STATUS_IS_OK(status)) {
5316 reply_nterror(req, status);
5317 return;
5320 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5321 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5322 if (delete_pending) {
5323 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5324 return;
5328 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5329 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5330 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5332 /* Pull out any data sent here before we realloc. */
5333 switch (info_level) {
5334 case SMB_INFO_QUERY_EAS_FROM_LIST:
5336 /* Pull any EA list from the data portion. */
5337 uint32 ea_size;
5339 if (total_data < 4) {
5340 reply_nterror(
5341 req, NT_STATUS_INVALID_PARAMETER);
5342 return;
5344 ea_size = IVAL(pdata,0);
5346 if (total_data > 0 && ea_size != total_data) {
5347 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5348 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5349 reply_nterror(
5350 req, NT_STATUS_INVALID_PARAMETER);
5351 return;
5354 if (!lp_ea_support(SNUM(conn))) {
5355 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5356 return;
5359 /* Pull out the list of names. */
5360 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5361 if (!ea_list) {
5362 reply_nterror(
5363 req, NT_STATUS_INVALID_PARAMETER);
5364 return;
5366 break;
5369 case SMB_QUERY_POSIX_LOCK:
5371 if (fsp == NULL || fsp->fh->fd == -1) {
5372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5373 return;
5376 if (total_data != POSIX_LOCK_DATA_SIZE) {
5377 reply_nterror(
5378 req, NT_STATUS_INVALID_PARAMETER);
5379 return;
5382 /* Copy the lock range data. */
5383 lock_data = (char *)talloc_memdup(
5384 req, pdata, total_data);
5385 if (!lock_data) {
5386 reply_nterror(req, NT_STATUS_NO_MEMORY);
5387 return;
5389 lock_data_count = total_data;
5391 default:
5392 break;
5395 *pparams = (char *)SMB_REALLOC(*pparams,2);
5396 if (*pparams == NULL) {
5397 reply_nterror(req, NT_STATUS_NO_MEMORY);
5398 return;
5400 params = *pparams;
5401 SSVAL(params,0,0);
5404 * draft-leach-cifs-v1-spec-02.txt
5405 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5406 * says:
5408 * The requested information is placed in the Data portion of the
5409 * transaction response. For the information levels greater than 0x100,
5410 * the transaction response has 1 parameter word which should be
5411 * ignored by the client.
5413 * However Windows only follows this rule for the IS_NAME_VALID call.
5415 switch (info_level) {
5416 case SMB_INFO_IS_NAME_VALID:
5417 param_size = 0;
5418 break;
5421 if ((info_level & 0xFF00) == 0xFF00) {
5423 * We use levels that start with 0xFF00
5424 * internally to represent SMB2 specific levels
5426 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5427 return;
5430 status = smbd_do_qfilepathinfo(conn, req, info_level,
5431 fsp, smb_fname,
5432 delete_pending, write_time_ts,
5433 ea_list,
5434 lock_data_count, lock_data,
5435 req->flags2, max_data_bytes,
5436 ppdata, &data_size);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 reply_nterror(req, status);
5439 return;
5442 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5443 max_data_bytes);
5445 return;
5448 /****************************************************************************
5449 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5450 code.
5451 ****************************************************************************/
5453 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5454 connection_struct *conn,
5455 struct smb_request *req,
5456 bool overwrite_if_exists,
5457 const struct smb_filename *smb_fname_old,
5458 struct smb_filename *smb_fname_new)
5460 NTSTATUS status = NT_STATUS_OK;
5462 /* source must already exist. */
5463 if (!VALID_STAT(smb_fname_old->st)) {
5464 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5467 if (VALID_STAT(smb_fname_new->st)) {
5468 if (overwrite_if_exists) {
5469 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5470 return NT_STATUS_FILE_IS_A_DIRECTORY;
5472 status = unlink_internals(conn,
5473 req,
5474 FILE_ATTRIBUTE_NORMAL,
5475 smb_fname_new,
5476 false);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 return status;
5480 } else {
5481 /* Disallow if newname already exists. */
5482 return NT_STATUS_OBJECT_NAME_COLLISION;
5486 /* No links from a directory. */
5487 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5488 return NT_STATUS_FILE_IS_A_DIRECTORY;
5491 /* Setting a hardlink to/from a stream isn't currently supported. */
5492 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5493 is_ntfs_stream_smb_fname(smb_fname_new)) {
5494 return NT_STATUS_INVALID_PARAMETER;
5497 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5498 smb_fname_old->base_name, smb_fname_new->base_name));
5500 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5501 smb_fname_new->base_name) != 0) {
5502 status = map_nt_error_from_unix(errno);
5503 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5504 nt_errstr(status), smb_fname_old->base_name,
5505 smb_fname_new->base_name));
5507 return status;
5510 /****************************************************************************
5511 Deal with setting the time from any of the setfilepathinfo functions.
5512 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5513 calling this function.
5514 ****************************************************************************/
5516 NTSTATUS smb_set_file_time(connection_struct *conn,
5517 files_struct *fsp,
5518 const struct smb_filename *smb_fname,
5519 struct smb_file_time *ft,
5520 bool setting_write_time)
5522 struct smb_filename smb_fname_base;
5523 uint32 action =
5524 FILE_NOTIFY_CHANGE_LAST_ACCESS
5525 |FILE_NOTIFY_CHANGE_LAST_WRITE
5526 |FILE_NOTIFY_CHANGE_CREATION;
5528 if (!VALID_STAT(smb_fname->st)) {
5529 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5532 /* get some defaults (no modifications) if any info is zero or -1. */
5533 if (null_timespec(ft->create_time)) {
5534 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5537 if (null_timespec(ft->atime)) {
5538 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5541 if (null_timespec(ft->mtime)) {
5542 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5545 if (!setting_write_time) {
5546 /* ft->mtime comes from change time, not write time. */
5547 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5550 /* Ensure the resolution is the correct for
5551 * what we can store on this filesystem. */
5553 round_timespec(conn->ts_res, &ft->create_time);
5554 round_timespec(conn->ts_res, &ft->ctime);
5555 round_timespec(conn->ts_res, &ft->atime);
5556 round_timespec(conn->ts_res, &ft->mtime);
5558 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5560 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5561 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5562 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5563 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5564 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5565 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5567 if (setting_write_time) {
5569 * This was a Windows setfileinfo on an open file.
5570 * NT does this a lot. We also need to
5571 * set the time here, as it can be read by
5572 * FindFirst/FindNext and with the patch for bug #2045
5573 * in smbd/fileio.c it ensures that this timestamp is
5574 * kept sticky even after a write. We save the request
5575 * away and will set it on file close and after a write. JRA.
5578 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5579 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5581 if (fsp != NULL) {
5582 if (fsp->base_fsp) {
5583 set_sticky_write_time_fsp(fsp->base_fsp,
5584 ft->mtime);
5585 } else {
5586 set_sticky_write_time_fsp(fsp, ft->mtime);
5588 } else {
5589 set_sticky_write_time_path(
5590 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5591 ft->mtime);
5595 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5597 /* Always call ntimes on the base, even if a stream was passed in. */
5598 smb_fname_base = *smb_fname;
5599 smb_fname_base.stream_name = NULL;
5601 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5602 return map_nt_error_from_unix(errno);
5605 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5606 smb_fname->base_name);
5607 return NT_STATUS_OK;
5610 /****************************************************************************
5611 Deal with setting the dosmode from any of the setfilepathinfo functions.
5612 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5613 done before calling this function.
5614 ****************************************************************************/
5616 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5617 const struct smb_filename *smb_fname,
5618 uint32 dosmode)
5620 struct smb_filename *smb_fname_base = NULL;
5621 NTSTATUS status;
5623 if (!VALID_STAT(smb_fname->st)) {
5624 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5627 /* Always operate on the base_name, even if a stream was passed in. */
5628 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5629 NULL, &smb_fname->st,
5630 &smb_fname_base);
5631 if (!NT_STATUS_IS_OK(status)) {
5632 return status;
5635 if (dosmode) {
5636 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5637 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5638 } else {
5639 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5643 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5645 /* check the mode isn't different, before changing it */
5646 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5647 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5648 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5649 (unsigned int)dosmode));
5651 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5652 false)) {
5653 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5654 "%s failed (%s)\n",
5655 smb_fname_str_dbg(smb_fname_base),
5656 strerror(errno)));
5657 status = map_nt_error_from_unix(errno);
5658 goto out;
5661 status = NT_STATUS_OK;
5662 out:
5663 TALLOC_FREE(smb_fname_base);
5664 return status;
5667 /****************************************************************************
5668 Deal with setting the size from any of the setfilepathinfo functions.
5669 ****************************************************************************/
5671 static NTSTATUS smb_set_file_size(connection_struct *conn,
5672 struct smb_request *req,
5673 files_struct *fsp,
5674 const struct smb_filename *smb_fname,
5675 const SMB_STRUCT_STAT *psbuf,
5676 off_t size,
5677 bool fail_after_createfile)
5679 NTSTATUS status = NT_STATUS_OK;
5680 struct smb_filename *smb_fname_tmp = NULL;
5681 files_struct *new_fsp = NULL;
5683 if (!VALID_STAT(*psbuf)) {
5684 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5687 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5689 if (size == get_file_size_stat(psbuf)) {
5690 return NT_STATUS_OK;
5693 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5694 smb_fname_str_dbg(smb_fname), (double)size));
5696 if (fsp && fsp->fh->fd != -1) {
5697 /* Handle based call. */
5698 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5699 return NT_STATUS_ACCESS_DENIED;
5702 if (vfs_set_filelen(fsp, size) == -1) {
5703 return map_nt_error_from_unix(errno);
5705 trigger_write_time_update_immediate(fsp);
5706 return NT_STATUS_OK;
5709 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 return status;
5714 smb_fname_tmp->st = *psbuf;
5716 status = SMB_VFS_CREATE_FILE(
5717 conn, /* conn */
5718 req, /* req */
5719 0, /* root_dir_fid */
5720 smb_fname_tmp, /* fname */
5721 FILE_WRITE_DATA, /* access_mask */
5722 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5723 FILE_SHARE_DELETE),
5724 FILE_OPEN, /* create_disposition*/
5725 0, /* create_options */
5726 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5727 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5728 0, /* allocation_size */
5729 0, /* private_flags */
5730 NULL, /* sd */
5731 NULL, /* ea_list */
5732 &new_fsp, /* result */
5733 NULL); /* pinfo */
5735 TALLOC_FREE(smb_fname_tmp);
5737 if (!NT_STATUS_IS_OK(status)) {
5738 /* NB. We check for open_was_deferred in the caller. */
5739 return status;
5742 /* See RAW-SFILEINFO-END-OF-FILE */
5743 if (fail_after_createfile) {
5744 close_file(req, new_fsp,NORMAL_CLOSE);
5745 return NT_STATUS_INVALID_LEVEL;
5748 if (vfs_set_filelen(new_fsp, size) == -1) {
5749 status = map_nt_error_from_unix(errno);
5750 close_file(req, new_fsp,NORMAL_CLOSE);
5751 return status;
5754 trigger_write_time_update_immediate(new_fsp);
5755 close_file(req, new_fsp,NORMAL_CLOSE);
5756 return NT_STATUS_OK;
5759 /****************************************************************************
5760 Deal with SMB_INFO_SET_EA.
5761 ****************************************************************************/
5763 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5764 const char *pdata,
5765 int total_data,
5766 files_struct *fsp,
5767 const struct smb_filename *smb_fname)
5769 struct ea_list *ea_list = NULL;
5770 TALLOC_CTX *ctx = NULL;
5771 NTSTATUS status = NT_STATUS_OK;
5773 if (total_data < 10) {
5775 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5776 length. They seem to have no effect. Bug #3212. JRA */
5778 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5779 /* We're done. We only get EA info in this call. */
5780 return NT_STATUS_OK;
5783 return NT_STATUS_INVALID_PARAMETER;
5786 if (IVAL(pdata,0) > total_data) {
5787 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5788 IVAL(pdata,0), (unsigned int)total_data));
5789 return NT_STATUS_INVALID_PARAMETER;
5792 ctx = talloc_tos();
5793 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5794 if (!ea_list) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 status = set_ea(conn, fsp, smb_fname, ea_list);
5800 return status;
5803 /****************************************************************************
5804 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5805 ****************************************************************************/
5807 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5808 const char *pdata,
5809 int total_data,
5810 files_struct *fsp)
5812 struct ea_list *ea_list = NULL;
5813 NTSTATUS status;
5815 if (!fsp) {
5816 return NT_STATUS_INVALID_HANDLE;
5819 if (!lp_ea_support(SNUM(conn))) {
5820 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5821 "EA's not supported.\n",
5822 (unsigned int)total_data));
5823 return NT_STATUS_EAS_NOT_SUPPORTED;
5826 if (total_data < 10) {
5827 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5828 "too small.\n",
5829 (unsigned int)total_data));
5830 return NT_STATUS_INVALID_PARAMETER;
5833 ea_list = read_nttrans_ea_list(talloc_tos(),
5834 pdata,
5835 total_data);
5837 if (!ea_list) {
5838 return NT_STATUS_INVALID_PARAMETER;
5841 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5843 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5844 smb_fname_str_dbg(fsp->fsp_name),
5845 nt_errstr(status) ));
5847 return status;
5851 /****************************************************************************
5852 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5853 ****************************************************************************/
5855 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5856 const char *pdata,
5857 int total_data,
5858 files_struct *fsp,
5859 struct smb_filename *smb_fname)
5861 NTSTATUS status = NT_STATUS_OK;
5862 bool delete_on_close;
5863 uint32 dosmode = 0;
5865 if (total_data < 1) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 if (fsp == NULL) {
5870 return NT_STATUS_INVALID_HANDLE;
5873 delete_on_close = (CVAL(pdata,0) ? True : False);
5874 dosmode = dos_mode(conn, smb_fname);
5876 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5877 "delete_on_close = %u\n",
5878 smb_fname_str_dbg(smb_fname),
5879 (unsigned int)dosmode,
5880 (unsigned int)delete_on_close ));
5882 if (delete_on_close) {
5883 status = can_set_delete_on_close(fsp, dosmode);
5884 if (!NT_STATUS_IS_OK(status)) {
5885 return status;
5889 /* The set is across all open files on this dev/inode pair. */
5890 if (!set_delete_on_close(fsp, delete_on_close,
5891 conn->session_info->security_token,
5892 conn->session_info->unix_token)) {
5893 return NT_STATUS_ACCESS_DENIED;
5895 return NT_STATUS_OK;
5898 /****************************************************************************
5899 Deal with SMB_FILE_POSITION_INFORMATION.
5900 ****************************************************************************/
5902 static NTSTATUS smb_file_position_information(connection_struct *conn,
5903 const char *pdata,
5904 int total_data,
5905 files_struct *fsp)
5907 uint64_t position_information;
5909 if (total_data < 8) {
5910 return NT_STATUS_INVALID_PARAMETER;
5913 if (fsp == NULL) {
5914 /* Ignore on pathname based set. */
5915 return NT_STATUS_OK;
5918 position_information = (uint64_t)IVAL(pdata,0);
5919 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5921 DEBUG(10,("smb_file_position_information: Set file position "
5922 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5923 (double)position_information));
5924 fsp->fh->position_information = position_information;
5925 return NT_STATUS_OK;
5928 /****************************************************************************
5929 Deal with SMB_FILE_MODE_INFORMATION.
5930 ****************************************************************************/
5932 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5933 const char *pdata,
5934 int total_data)
5936 uint32 mode;
5938 if (total_data < 4) {
5939 return NT_STATUS_INVALID_PARAMETER;
5941 mode = IVAL(pdata,0);
5942 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5943 return NT_STATUS_INVALID_PARAMETER;
5945 return NT_STATUS_OK;
5948 /****************************************************************************
5949 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5950 ****************************************************************************/
5952 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5953 struct smb_request *req,
5954 const char *pdata,
5955 int total_data,
5956 const struct smb_filename *smb_fname)
5958 char *link_target = NULL;
5959 const char *newname = smb_fname->base_name;
5960 TALLOC_CTX *ctx = talloc_tos();
5962 /* Set a symbolic link. */
5963 /* Don't allow this if follow links is false. */
5965 if (total_data == 0) {
5966 return NT_STATUS_INVALID_PARAMETER;
5969 if (!lp_symlinks(SNUM(conn))) {
5970 return NT_STATUS_ACCESS_DENIED;
5973 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5974 total_data, STR_TERMINATE);
5976 if (!link_target) {
5977 return NT_STATUS_INVALID_PARAMETER;
5980 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5981 newname, link_target ));
5983 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5984 return map_nt_error_from_unix(errno);
5987 return NT_STATUS_OK;
5990 /****************************************************************************
5991 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5992 ****************************************************************************/
5994 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5995 struct smb_request *req,
5996 const char *pdata, int total_data,
5997 struct smb_filename *smb_fname_new)
5999 char *oldname = NULL;
6000 struct smb_filename *smb_fname_old = NULL;
6001 TALLOC_CTX *ctx = talloc_tos();
6002 NTSTATUS status = NT_STATUS_OK;
6004 /* Set a hard link. */
6005 if (total_data == 0) {
6006 return NT_STATUS_INVALID_PARAMETER;
6009 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6010 total_data, STR_TERMINATE, &status);
6011 if (!NT_STATUS_IS_OK(status)) {
6012 return status;
6015 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6016 smb_fname_str_dbg(smb_fname_new), oldname));
6018 status = filename_convert(ctx,
6019 conn,
6020 req->flags2 & FLAGS2_DFS_PATHNAMES,
6021 oldname,
6023 NULL,
6024 &smb_fname_old);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 return status;
6029 return hardlink_internals(ctx, conn, req, false,
6030 smb_fname_old, smb_fname_new);
6033 /****************************************************************************
6034 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6035 ****************************************************************************/
6037 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6038 struct smb_request *req,
6039 const char *pdata,
6040 int total_data,
6041 files_struct *fsp,
6042 struct smb_filename *smb_fname_src)
6044 bool overwrite;
6045 uint32_t len;
6046 char *newname = NULL;
6047 struct smb_filename *smb_fname_dst = NULL;
6048 NTSTATUS status = NT_STATUS_OK;
6049 TALLOC_CTX *ctx = talloc_tos();
6051 if (!fsp) {
6052 return NT_STATUS_INVALID_HANDLE;
6055 if (total_data < 20) {
6056 return NT_STATUS_INVALID_PARAMETER;
6059 overwrite = (CVAL(pdata,0) ? True : False);
6060 len = IVAL(pdata,16);
6062 if (len > (total_data - 20) || (len == 0)) {
6063 return NT_STATUS_INVALID_PARAMETER;
6066 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6067 &pdata[20], len, STR_TERMINATE,
6068 &status);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 return status;
6073 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6074 newname));
6076 status = filename_convert(ctx,
6077 conn,
6078 req->flags2 & FLAGS2_DFS_PATHNAMES,
6079 newname,
6080 UCF_SAVE_LCOMP,
6081 NULL,
6082 &smb_fname_dst);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 return status;
6087 if (fsp->base_fsp) {
6088 /* newname must be a stream name. */
6089 if (newname[0] != ':') {
6090 return NT_STATUS_NOT_SUPPORTED;
6093 /* Create an smb_fname to call rename_internals_fsp() with. */
6094 status = create_synthetic_smb_fname(talloc_tos(),
6095 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6096 &smb_fname_dst);
6097 if (!NT_STATUS_IS_OK(status)) {
6098 goto out;
6102 * Set the original last component, since
6103 * rename_internals_fsp() requires it.
6105 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6106 newname);
6107 if (smb_fname_dst->original_lcomp == NULL) {
6108 status = NT_STATUS_NO_MEMORY;
6109 goto out;
6114 DEBUG(10,("smb2_file_rename_information: "
6115 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6116 fsp->fnum, fsp_str_dbg(fsp),
6117 smb_fname_str_dbg(smb_fname_dst)));
6118 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6119 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6120 overwrite);
6122 out:
6123 TALLOC_FREE(smb_fname_dst);
6124 return status;
6127 static NTSTATUS smb_file_link_information(connection_struct *conn,
6128 struct smb_request *req,
6129 const char *pdata,
6130 int total_data,
6131 files_struct *fsp,
6132 struct smb_filename *smb_fname_src)
6134 bool overwrite;
6135 uint32_t len;
6136 char *newname = NULL;
6137 struct smb_filename *smb_fname_dst = NULL;
6138 NTSTATUS status = NT_STATUS_OK;
6139 TALLOC_CTX *ctx = talloc_tos();
6141 if (!fsp) {
6142 return NT_STATUS_INVALID_HANDLE;
6145 if (total_data < 20) {
6146 return NT_STATUS_INVALID_PARAMETER;
6149 overwrite = (CVAL(pdata,0) ? true : false);
6150 len = IVAL(pdata,16);
6152 if (len > (total_data - 20) || (len == 0)) {
6153 return NT_STATUS_INVALID_PARAMETER;
6156 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6157 &pdata[20], len, STR_TERMINATE,
6158 &status);
6159 if (!NT_STATUS_IS_OK(status)) {
6160 return status;
6163 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6164 newname));
6166 status = filename_convert(ctx,
6167 conn,
6168 req->flags2 & FLAGS2_DFS_PATHNAMES,
6169 newname,
6170 UCF_SAVE_LCOMP,
6171 NULL,
6172 &smb_fname_dst);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 return status;
6177 if (fsp->base_fsp) {
6178 /* No stream names. */
6179 return NT_STATUS_NOT_SUPPORTED;
6182 DEBUG(10,("smb_file_link_information: "
6183 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6184 fsp->fnum, fsp_str_dbg(fsp),
6185 smb_fname_str_dbg(smb_fname_dst)));
6186 status = hardlink_internals(ctx,
6187 conn,
6188 req,
6189 overwrite,
6190 fsp->fsp_name,
6191 smb_fname_dst);
6193 TALLOC_FREE(smb_fname_dst);
6194 return status;
6197 /****************************************************************************
6198 Deal with SMB_FILE_RENAME_INFORMATION.
6199 ****************************************************************************/
6201 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6202 struct smb_request *req,
6203 const char *pdata,
6204 int total_data,
6205 files_struct *fsp,
6206 struct smb_filename *smb_fname_src)
6208 bool overwrite;
6209 uint32 root_fid;
6210 uint32 len;
6211 char *newname = NULL;
6212 struct smb_filename *smb_fname_dst = NULL;
6213 bool dest_has_wcard = False;
6214 NTSTATUS status = NT_STATUS_OK;
6215 char *p;
6216 TALLOC_CTX *ctx = talloc_tos();
6218 if (total_data < 13) {
6219 return NT_STATUS_INVALID_PARAMETER;
6222 overwrite = (CVAL(pdata,0) ? True : False);
6223 root_fid = IVAL(pdata,4);
6224 len = IVAL(pdata,8);
6226 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6227 return NT_STATUS_INVALID_PARAMETER;
6230 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6231 len, 0, &status,
6232 &dest_has_wcard);
6233 if (!NT_STATUS_IS_OK(status)) {
6234 return status;
6237 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6238 newname));
6240 status = resolve_dfspath_wcard(ctx, conn,
6241 req->flags2 & FLAGS2_DFS_PATHNAMES,
6242 newname,
6243 true,
6244 &newname,
6245 &dest_has_wcard);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 return status;
6250 /* Check the new name has no '/' characters. */
6251 if (strchr_m(newname, '/')) {
6252 return NT_STATUS_NOT_SUPPORTED;
6255 if (fsp && fsp->base_fsp) {
6256 /* newname must be a stream name. */
6257 if (newname[0] != ':') {
6258 return NT_STATUS_NOT_SUPPORTED;
6261 /* Create an smb_fname to call rename_internals_fsp() with. */
6262 status = create_synthetic_smb_fname(talloc_tos(),
6263 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6264 &smb_fname_dst);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 goto out;
6270 * Set the original last component, since
6271 * rename_internals_fsp() requires it.
6273 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6274 newname);
6275 if (smb_fname_dst->original_lcomp == NULL) {
6276 status = NT_STATUS_NO_MEMORY;
6277 goto out;
6280 } else {
6282 * Build up an smb_fname_dst based on the filename passed in.
6283 * We basically just strip off the last component, and put on
6284 * the newname instead.
6286 char *base_name = NULL;
6288 /* newname must *not* be a stream name. */
6289 if (newname[0] == ':') {
6290 return NT_STATUS_NOT_SUPPORTED;
6294 * Strip off the last component (filename) of the path passed
6295 * in.
6297 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6298 if (!base_name) {
6299 return NT_STATUS_NO_MEMORY;
6301 p = strrchr_m(base_name, '/');
6302 if (p) {
6303 p[1] = '\0';
6304 } else {
6305 base_name = talloc_strdup(ctx, "");
6306 if (!base_name) {
6307 return NT_STATUS_NO_MEMORY;
6310 /* Append the new name. */
6311 base_name = talloc_asprintf_append(base_name,
6312 "%s",
6313 newname);
6314 if (!base_name) {
6315 return NT_STATUS_NO_MEMORY;
6318 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6319 (UCF_SAVE_LCOMP |
6320 (dest_has_wcard ?
6321 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6322 0)));
6324 /* If an error we expect this to be
6325 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6327 if (!NT_STATUS_IS_OK(status)) {
6328 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6329 status)) {
6330 goto out;
6332 /* Create an smb_fname to call rename_internals_fsp() */
6333 status = create_synthetic_smb_fname(ctx,
6334 base_name, NULL,
6335 NULL,
6336 &smb_fname_dst);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 goto out;
6343 if (fsp) {
6344 DEBUG(10,("smb_file_rename_information: "
6345 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6346 fsp->fnum, fsp_str_dbg(fsp),
6347 smb_fname_str_dbg(smb_fname_dst)));
6348 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6349 overwrite);
6350 } else {
6351 DEBUG(10,("smb_file_rename_information: "
6352 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6353 smb_fname_str_dbg(smb_fname_src),
6354 smb_fname_str_dbg(smb_fname_dst)));
6355 status = rename_internals(ctx, conn, req, smb_fname_src,
6356 smb_fname_dst, 0, overwrite, false,
6357 dest_has_wcard,
6358 FILE_WRITE_ATTRIBUTES);
6360 out:
6361 TALLOC_FREE(smb_fname_dst);
6362 return status;
6365 /****************************************************************************
6366 Deal with SMB_SET_POSIX_ACL.
6367 ****************************************************************************/
6369 #if defined(HAVE_POSIX_ACLS)
6370 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6371 const char *pdata,
6372 int total_data,
6373 files_struct *fsp,
6374 const struct smb_filename *smb_fname)
6376 uint16 posix_acl_version;
6377 uint16 num_file_acls;
6378 uint16 num_def_acls;
6379 bool valid_file_acls = True;
6380 bool valid_def_acls = True;
6382 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6383 return NT_STATUS_INVALID_PARAMETER;
6385 posix_acl_version = SVAL(pdata,0);
6386 num_file_acls = SVAL(pdata,2);
6387 num_def_acls = SVAL(pdata,4);
6389 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6390 valid_file_acls = False;
6391 num_file_acls = 0;
6394 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6395 valid_def_acls = False;
6396 num_def_acls = 0;
6399 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6400 return NT_STATUS_INVALID_PARAMETER;
6403 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6404 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6405 return NT_STATUS_INVALID_PARAMETER;
6408 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6409 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6410 (unsigned int)num_file_acls,
6411 (unsigned int)num_def_acls));
6413 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6414 smb_fname->base_name, num_file_acls,
6415 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6416 return map_nt_error_from_unix(errno);
6419 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6420 smb_fname->base_name, &smb_fname->st, num_def_acls,
6421 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6422 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6423 return map_nt_error_from_unix(errno);
6425 return NT_STATUS_OK;
6427 #endif
6429 /****************************************************************************
6430 Deal with SMB_SET_POSIX_LOCK.
6431 ****************************************************************************/
6433 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6434 struct smb_request *req,
6435 const char *pdata,
6436 int total_data,
6437 files_struct *fsp)
6439 uint64_t count;
6440 uint64_t offset;
6441 uint64_t smblctx;
6442 bool blocking_lock = False;
6443 enum brl_type lock_type;
6445 NTSTATUS status = NT_STATUS_OK;
6447 if (fsp == NULL || fsp->fh->fd == -1) {
6448 return NT_STATUS_INVALID_HANDLE;
6451 if (total_data != POSIX_LOCK_DATA_SIZE) {
6452 return NT_STATUS_INVALID_PARAMETER;
6455 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6456 case POSIX_LOCK_TYPE_READ:
6457 lock_type = READ_LOCK;
6458 break;
6459 case POSIX_LOCK_TYPE_WRITE:
6460 /* Return the right POSIX-mappable error code for files opened read-only. */
6461 if (!fsp->can_write) {
6462 return NT_STATUS_INVALID_HANDLE;
6464 lock_type = WRITE_LOCK;
6465 break;
6466 case POSIX_LOCK_TYPE_UNLOCK:
6467 lock_type = UNLOCK_LOCK;
6468 break;
6469 default:
6470 return NT_STATUS_INVALID_PARAMETER;
6473 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6474 blocking_lock = False;
6475 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6476 blocking_lock = True;
6477 } else {
6478 return NT_STATUS_INVALID_PARAMETER;
6481 if (!lp_blocking_locks(SNUM(conn))) {
6482 blocking_lock = False;
6485 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6486 #if defined(HAVE_LONGLONG)
6487 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6488 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6489 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6490 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6491 #else /* HAVE_LONGLONG */
6492 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6493 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6494 #endif /* HAVE_LONGLONG */
6496 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6497 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6498 fsp_str_dbg(fsp),
6499 (unsigned int)lock_type,
6500 (unsigned long long)smblctx,
6501 (double)count,
6502 (double)offset ));
6504 if (lock_type == UNLOCK_LOCK) {
6505 status = do_unlock(req->sconn->msg_ctx,
6506 fsp,
6507 smblctx,
6508 count,
6509 offset,
6510 POSIX_LOCK);
6511 } else {
6512 uint64_t block_smblctx;
6514 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6515 fsp,
6516 smblctx,
6517 count,
6518 offset,
6519 lock_type,
6520 POSIX_LOCK,
6521 blocking_lock,
6522 &status,
6523 &block_smblctx,
6524 NULL);
6526 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6528 * A blocking lock was requested. Package up
6529 * this smb into a queued request and push it
6530 * onto the blocking lock queue.
6532 if(push_blocking_lock_request(br_lck,
6533 req,
6534 fsp,
6535 -1, /* infinite timeout. */
6537 smblctx,
6538 lock_type,
6539 POSIX_LOCK,
6540 offset,
6541 count,
6542 block_smblctx)) {
6543 TALLOC_FREE(br_lck);
6544 return status;
6547 TALLOC_FREE(br_lck);
6550 return status;
6553 /****************************************************************************
6554 Deal with SMB_SET_FILE_BASIC_INFO.
6555 ****************************************************************************/
6557 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6558 const char *pdata,
6559 int total_data,
6560 files_struct *fsp,
6561 const struct smb_filename *smb_fname)
6563 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6564 struct smb_file_time ft;
6565 uint32 dosmode = 0;
6566 NTSTATUS status = NT_STATUS_OK;
6568 ZERO_STRUCT(ft);
6570 if (total_data < 36) {
6571 return NT_STATUS_INVALID_PARAMETER;
6574 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6575 if (!NT_STATUS_IS_OK(status)) {
6576 return status;
6579 /* Set the attributes */
6580 dosmode = IVAL(pdata,32);
6581 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6582 if (!NT_STATUS_IS_OK(status)) {
6583 return status;
6586 /* create time */
6587 ft.create_time = interpret_long_date(pdata);
6589 /* access time */
6590 ft.atime = interpret_long_date(pdata+8);
6592 /* write time. */
6593 ft.mtime = interpret_long_date(pdata+16);
6595 /* change time. */
6596 ft.ctime = interpret_long_date(pdata+24);
6598 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6599 smb_fname_str_dbg(smb_fname)));
6601 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6602 true);
6605 /****************************************************************************
6606 Deal with SMB_INFO_STANDARD.
6607 ****************************************************************************/
6609 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6610 const char *pdata,
6611 int total_data,
6612 files_struct *fsp,
6613 const struct smb_filename *smb_fname)
6615 NTSTATUS status;
6616 struct smb_file_time ft;
6618 ZERO_STRUCT(ft);
6620 if (total_data < 12) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 /* create time */
6625 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6626 /* access time */
6627 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6628 /* write time */
6629 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6631 DEBUG(10,("smb_set_info_standard: file %s\n",
6632 smb_fname_str_dbg(smb_fname)));
6634 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6635 if (!NT_STATUS_IS_OK(status)) {
6636 return status;
6639 return smb_set_file_time(conn,
6640 fsp,
6641 smb_fname,
6642 &ft,
6643 true);
6646 /****************************************************************************
6647 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6648 ****************************************************************************/
6650 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6651 struct smb_request *req,
6652 const char *pdata,
6653 int total_data,
6654 files_struct *fsp,
6655 struct smb_filename *smb_fname)
6657 uint64_t allocation_size = 0;
6658 NTSTATUS status = NT_STATUS_OK;
6659 files_struct *new_fsp = NULL;
6661 if (!VALID_STAT(smb_fname->st)) {
6662 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6665 if (total_data < 8) {
6666 return NT_STATUS_INVALID_PARAMETER;
6669 allocation_size = (uint64_t)IVAL(pdata,0);
6670 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6671 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6672 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6673 (double)allocation_size));
6675 if (allocation_size) {
6676 allocation_size = smb_roundup(conn, allocation_size);
6679 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6680 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6681 (double)allocation_size));
6683 if (fsp && fsp->fh->fd != -1) {
6684 /* Open file handle. */
6685 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6686 return NT_STATUS_ACCESS_DENIED;
6689 /* Only change if needed. */
6690 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6691 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6692 return map_nt_error_from_unix(errno);
6695 /* But always update the time. */
6697 * This is equivalent to a write. Ensure it's seen immediately
6698 * if there are no pending writes.
6700 trigger_write_time_update_immediate(fsp);
6701 return NT_STATUS_OK;
6704 /* Pathname or stat or directory file. */
6705 status = SMB_VFS_CREATE_FILE(
6706 conn, /* conn */
6707 req, /* req */
6708 0, /* root_dir_fid */
6709 smb_fname, /* fname */
6710 FILE_WRITE_DATA, /* access_mask */
6711 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6712 FILE_SHARE_DELETE),
6713 FILE_OPEN, /* create_disposition*/
6714 0, /* create_options */
6715 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6716 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6717 0, /* allocation_size */
6718 0, /* private_flags */
6719 NULL, /* sd */
6720 NULL, /* ea_list */
6721 &new_fsp, /* result */
6722 NULL); /* pinfo */
6724 if (!NT_STATUS_IS_OK(status)) {
6725 /* NB. We check for open_was_deferred in the caller. */
6726 return status;
6729 /* Only change if needed. */
6730 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6731 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6732 status = map_nt_error_from_unix(errno);
6733 close_file(req, new_fsp, NORMAL_CLOSE);
6734 return status;
6738 /* Changing the allocation size should set the last mod time. */
6740 * This is equivalent to a write. Ensure it's seen immediately
6741 * if there are no pending writes.
6743 trigger_write_time_update_immediate(new_fsp);
6745 close_file(req, new_fsp, NORMAL_CLOSE);
6746 return NT_STATUS_OK;
6749 /****************************************************************************
6750 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6751 ****************************************************************************/
6753 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6754 struct smb_request *req,
6755 const char *pdata,
6756 int total_data,
6757 files_struct *fsp,
6758 const struct smb_filename *smb_fname,
6759 bool fail_after_createfile)
6761 off_t size;
6763 if (total_data < 8) {
6764 return NT_STATUS_INVALID_PARAMETER;
6767 size = IVAL(pdata,0);
6768 size |= (((off_t)IVAL(pdata,4)) << 32);
6769 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6770 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6771 (double)size));
6773 return smb_set_file_size(conn, req,
6774 fsp,
6775 smb_fname,
6776 &smb_fname->st,
6777 size,
6778 fail_after_createfile);
6781 /****************************************************************************
6782 Allow a UNIX info mknod.
6783 ****************************************************************************/
6785 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6786 const char *pdata,
6787 int total_data,
6788 const struct smb_filename *smb_fname)
6790 uint32 file_type = IVAL(pdata,56);
6791 #if defined(HAVE_MAKEDEV)
6792 uint32 dev_major = IVAL(pdata,60);
6793 uint32 dev_minor = IVAL(pdata,68);
6794 #endif
6795 SMB_DEV_T dev = (SMB_DEV_T)0;
6796 uint32 raw_unixmode = IVAL(pdata,84);
6797 NTSTATUS status;
6798 mode_t unixmode;
6800 if (total_data < 100) {
6801 return NT_STATUS_INVALID_PARAMETER;
6804 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6805 PERM_NEW_FILE, &unixmode);
6806 if (!NT_STATUS_IS_OK(status)) {
6807 return status;
6810 #if defined(HAVE_MAKEDEV)
6811 dev = makedev(dev_major, dev_minor);
6812 #endif
6814 switch (file_type) {
6815 #if defined(S_IFIFO)
6816 case UNIX_TYPE_FIFO:
6817 unixmode |= S_IFIFO;
6818 break;
6819 #endif
6820 #if defined(S_IFSOCK)
6821 case UNIX_TYPE_SOCKET:
6822 unixmode |= S_IFSOCK;
6823 break;
6824 #endif
6825 #if defined(S_IFCHR)
6826 case UNIX_TYPE_CHARDEV:
6827 unixmode |= S_IFCHR;
6828 break;
6829 #endif
6830 #if defined(S_IFBLK)
6831 case UNIX_TYPE_BLKDEV:
6832 unixmode |= S_IFBLK;
6833 break;
6834 #endif
6835 default:
6836 return NT_STATUS_INVALID_PARAMETER;
6839 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6840 "%.0f mode 0%o for file %s\n", (double)dev,
6841 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6843 /* Ok - do the mknod. */
6844 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6845 return map_nt_error_from_unix(errno);
6848 /* If any of the other "set" calls fail we
6849 * don't want to end up with a half-constructed mknod.
6852 if (lp_inherit_perms(SNUM(conn))) {
6853 char *parent;
6854 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6855 &parent, NULL)) {
6856 return NT_STATUS_NO_MEMORY;
6858 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6859 unixmode);
6860 TALLOC_FREE(parent);
6863 return NT_STATUS_OK;
6866 /****************************************************************************
6867 Deal with SMB_SET_FILE_UNIX_BASIC.
6868 ****************************************************************************/
6870 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6871 struct smb_request *req,
6872 const char *pdata,
6873 int total_data,
6874 files_struct *fsp,
6875 const struct smb_filename *smb_fname)
6877 struct smb_file_time ft;
6878 uint32 raw_unixmode;
6879 mode_t unixmode;
6880 off_t size = 0;
6881 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6882 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6883 NTSTATUS status = NT_STATUS_OK;
6884 bool delete_on_fail = False;
6885 enum perm_type ptype;
6886 files_struct *all_fsps = NULL;
6887 bool modify_mtime = true;
6888 struct file_id id;
6889 struct smb_filename *smb_fname_tmp = NULL;
6890 SMB_STRUCT_STAT sbuf;
6892 ZERO_STRUCT(ft);
6894 if (total_data < 100) {
6895 return NT_STATUS_INVALID_PARAMETER;
6898 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6899 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6900 size=IVAL(pdata,0); /* first 8 Bytes are size */
6901 size |= (((off_t)IVAL(pdata,4)) << 32);
6904 ft.atime = interpret_long_date(pdata+24); /* access_time */
6905 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6906 set_owner = (uid_t)IVAL(pdata,40);
6907 set_grp = (gid_t)IVAL(pdata,48);
6908 raw_unixmode = IVAL(pdata,84);
6910 if (VALID_STAT(smb_fname->st)) {
6911 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6912 ptype = PERM_EXISTING_DIR;
6913 } else {
6914 ptype = PERM_EXISTING_FILE;
6916 } else {
6917 ptype = PERM_NEW_FILE;
6920 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6921 ptype, &unixmode);
6922 if (!NT_STATUS_IS_OK(status)) {
6923 return status;
6926 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6927 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6928 smb_fname_str_dbg(smb_fname), (double)size,
6929 (unsigned int)set_owner, (unsigned int)set_grp,
6930 (int)raw_unixmode));
6932 sbuf = smb_fname->st;
6934 if (!VALID_STAT(sbuf)) {
6936 * The only valid use of this is to create character and block
6937 * devices, and named pipes. This is deprecated (IMHO) and
6938 * a new info level should be used for mknod. JRA.
6941 status = smb_unix_mknod(conn,
6942 pdata,
6943 total_data,
6944 smb_fname);
6945 if (!NT_STATUS_IS_OK(status)) {
6946 return status;
6949 status = copy_smb_filename(talloc_tos(), smb_fname,
6950 &smb_fname_tmp);
6951 if (!NT_STATUS_IS_OK(status)) {
6952 return status;
6955 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6956 status = map_nt_error_from_unix(errno);
6957 TALLOC_FREE(smb_fname_tmp);
6958 SMB_VFS_UNLINK(conn, smb_fname);
6959 return status;
6962 sbuf = smb_fname_tmp->st;
6963 smb_fname = smb_fname_tmp;
6965 /* Ensure we don't try and change anything else. */
6966 raw_unixmode = SMB_MODE_NO_CHANGE;
6967 size = get_file_size_stat(&sbuf);
6968 ft.atime = sbuf.st_ex_atime;
6969 ft.mtime = sbuf.st_ex_mtime;
6971 * We continue here as we might want to change the
6972 * owner uid/gid.
6974 delete_on_fail = True;
6977 #if 1
6978 /* Horrible backwards compatibility hack as an old server bug
6979 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6980 * */
6982 if (!size) {
6983 size = get_file_size_stat(&sbuf);
6985 #endif
6988 * Deal with the UNIX specific mode set.
6991 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6992 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6993 "setting mode 0%o for file %s\n",
6994 (unsigned int)unixmode,
6995 smb_fname_str_dbg(smb_fname)));
6996 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6997 return map_nt_error_from_unix(errno);
7002 * Deal with the UNIX specific uid set.
7005 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7006 (sbuf.st_ex_uid != set_owner)) {
7007 int ret;
7009 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7010 "changing owner %u for path %s\n",
7011 (unsigned int)set_owner,
7012 smb_fname_str_dbg(smb_fname)));
7014 if (S_ISLNK(sbuf.st_ex_mode)) {
7015 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7016 set_owner, (gid_t)-1);
7017 } else {
7018 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7019 set_owner, (gid_t)-1);
7022 if (ret != 0) {
7023 status = map_nt_error_from_unix(errno);
7024 if (delete_on_fail) {
7025 SMB_VFS_UNLINK(conn, smb_fname);
7027 return status;
7032 * Deal with the UNIX specific gid set.
7035 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7036 (sbuf.st_ex_gid != set_grp)) {
7037 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7038 "changing group %u for file %s\n",
7039 (unsigned int)set_owner,
7040 smb_fname_str_dbg(smb_fname)));
7041 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7042 set_grp) != 0) {
7043 status = map_nt_error_from_unix(errno);
7044 if (delete_on_fail) {
7045 SMB_VFS_UNLINK(conn, smb_fname);
7047 return status;
7051 /* Deal with any size changes. */
7053 status = smb_set_file_size(conn, req,
7054 fsp,
7055 smb_fname,
7056 &sbuf,
7057 size,
7058 false);
7059 if (!NT_STATUS_IS_OK(status)) {
7060 return status;
7063 /* Deal with any time changes. */
7064 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7065 /* No change, don't cancel anything. */
7066 return status;
7069 id = vfs_file_id_from_sbuf(conn, &sbuf);
7070 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7071 all_fsps = file_find_di_next(all_fsps)) {
7073 * We're setting the time explicitly for UNIX.
7074 * Cancel any pending changes over all handles.
7076 all_fsps->update_write_time_on_close = false;
7077 TALLOC_FREE(all_fsps->update_write_time_event);
7081 * Override the "setting_write_time"
7082 * parameter here as it almost does what
7083 * we need. Just remember if we modified
7084 * mtime and send the notify ourselves.
7086 if (null_timespec(ft.mtime)) {
7087 modify_mtime = false;
7090 status = smb_set_file_time(conn,
7091 fsp,
7092 smb_fname,
7093 &ft,
7094 false);
7095 if (modify_mtime) {
7096 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7097 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7099 return status;
7102 /****************************************************************************
7103 Deal with SMB_SET_FILE_UNIX_INFO2.
7104 ****************************************************************************/
7106 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7107 struct smb_request *req,
7108 const char *pdata,
7109 int total_data,
7110 files_struct *fsp,
7111 const struct smb_filename *smb_fname)
7113 NTSTATUS status;
7114 uint32 smb_fflags;
7115 uint32 smb_fmask;
7117 if (total_data < 116) {
7118 return NT_STATUS_INVALID_PARAMETER;
7121 /* Start by setting all the fields that are common between UNIX_BASIC
7122 * and UNIX_INFO2.
7124 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7125 fsp, smb_fname);
7126 if (!NT_STATUS_IS_OK(status)) {
7127 return status;
7130 smb_fflags = IVAL(pdata, 108);
7131 smb_fmask = IVAL(pdata, 112);
7133 /* NB: We should only attempt to alter the file flags if the client
7134 * sends a non-zero mask.
7136 if (smb_fmask != 0) {
7137 int stat_fflags = 0;
7139 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7140 smb_fmask, &stat_fflags)) {
7141 /* Client asked to alter a flag we don't understand. */
7142 return NT_STATUS_INVALID_PARAMETER;
7145 if (fsp && fsp->fh->fd != -1) {
7146 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7147 return NT_STATUS_NOT_SUPPORTED;
7148 } else {
7149 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7150 stat_fflags) != 0) {
7151 return map_nt_error_from_unix(errno);
7156 /* XXX: need to add support for changing the create_time here. You
7157 * can do this for paths on Darwin with setattrlist(2). The right way
7158 * to hook this up is probably by extending the VFS utimes interface.
7161 return NT_STATUS_OK;
7164 /****************************************************************************
7165 Create a directory with POSIX semantics.
7166 ****************************************************************************/
7168 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7169 struct smb_request *req,
7170 char **ppdata,
7171 int total_data,
7172 struct smb_filename *smb_fname,
7173 int *pdata_return_size)
7175 NTSTATUS status = NT_STATUS_OK;
7176 uint32 raw_unixmode = 0;
7177 uint32 mod_unixmode = 0;
7178 mode_t unixmode = (mode_t)0;
7179 files_struct *fsp = NULL;
7180 uint16 info_level_return = 0;
7181 int info;
7182 char *pdata = *ppdata;
7184 if (total_data < 18) {
7185 return NT_STATUS_INVALID_PARAMETER;
7188 raw_unixmode = IVAL(pdata,8);
7189 /* Next 4 bytes are not yet defined. */
7191 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7192 PERM_NEW_DIR, &unixmode);
7193 if (!NT_STATUS_IS_OK(status)) {
7194 return status;
7197 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7199 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7200 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7202 status = SMB_VFS_CREATE_FILE(
7203 conn, /* conn */
7204 req, /* req */
7205 0, /* root_dir_fid */
7206 smb_fname, /* fname */
7207 FILE_READ_ATTRIBUTES, /* access_mask */
7208 FILE_SHARE_NONE, /* share_access */
7209 FILE_CREATE, /* create_disposition*/
7210 FILE_DIRECTORY_FILE, /* create_options */
7211 mod_unixmode, /* file_attributes */
7212 0, /* oplock_request */
7213 0, /* allocation_size */
7214 0, /* private_flags */
7215 NULL, /* sd */
7216 NULL, /* ea_list */
7217 &fsp, /* result */
7218 &info); /* pinfo */
7220 if (NT_STATUS_IS_OK(status)) {
7221 close_file(req, fsp, NORMAL_CLOSE);
7224 info_level_return = SVAL(pdata,16);
7226 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7227 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7228 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7229 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7230 } else {
7231 *pdata_return_size = 12;
7234 /* Realloc the data size */
7235 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7236 if (*ppdata == NULL) {
7237 *pdata_return_size = 0;
7238 return NT_STATUS_NO_MEMORY;
7240 pdata = *ppdata;
7242 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7243 SSVAL(pdata,2,0); /* No fnum. */
7244 SIVAL(pdata,4,info); /* Was directory created. */
7246 switch (info_level_return) {
7247 case SMB_QUERY_FILE_UNIX_BASIC:
7248 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7249 SSVAL(pdata,10,0); /* Padding. */
7250 store_file_unix_basic(conn, pdata + 12, fsp,
7251 &smb_fname->st);
7252 break;
7253 case SMB_QUERY_FILE_UNIX_INFO2:
7254 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7255 SSVAL(pdata,10,0); /* Padding. */
7256 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7257 &smb_fname->st);
7258 break;
7259 default:
7260 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7261 SSVAL(pdata,10,0); /* Padding. */
7262 break;
7265 return status;
7268 /****************************************************************************
7269 Open/Create a file with POSIX semantics.
7270 ****************************************************************************/
7272 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7273 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7275 static NTSTATUS smb_posix_open(connection_struct *conn,
7276 struct smb_request *req,
7277 char **ppdata,
7278 int total_data,
7279 struct smb_filename *smb_fname,
7280 int *pdata_return_size)
7282 bool extended_oplock_granted = False;
7283 char *pdata = *ppdata;
7284 uint32 flags = 0;
7285 uint32 wire_open_mode = 0;
7286 uint32 raw_unixmode = 0;
7287 uint32 mod_unixmode = 0;
7288 uint32 create_disp = 0;
7289 uint32 access_mask = 0;
7290 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7291 NTSTATUS status = NT_STATUS_OK;
7292 mode_t unixmode = (mode_t)0;
7293 files_struct *fsp = NULL;
7294 int oplock_request = 0;
7295 int info = 0;
7296 uint16 info_level_return = 0;
7298 if (total_data < 18) {
7299 return NT_STATUS_INVALID_PARAMETER;
7302 flags = IVAL(pdata,0);
7303 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7304 if (oplock_request) {
7305 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7308 wire_open_mode = IVAL(pdata,4);
7310 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7311 return smb_posix_mkdir(conn, req,
7312 ppdata,
7313 total_data,
7314 smb_fname,
7315 pdata_return_size);
7318 switch (wire_open_mode & SMB_ACCMODE) {
7319 case SMB_O_RDONLY:
7320 access_mask = SMB_O_RDONLY_MAPPING;
7321 break;
7322 case SMB_O_WRONLY:
7323 access_mask = SMB_O_WRONLY_MAPPING;
7324 break;
7325 case SMB_O_RDWR:
7326 access_mask = (SMB_O_RDONLY_MAPPING|
7327 SMB_O_WRONLY_MAPPING);
7328 break;
7329 default:
7330 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7331 (unsigned int)wire_open_mode ));
7332 return NT_STATUS_INVALID_PARAMETER;
7335 wire_open_mode &= ~SMB_ACCMODE;
7337 /* First take care of O_CREAT|O_EXCL interactions. */
7338 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7339 case (SMB_O_CREAT | SMB_O_EXCL):
7340 /* File exists fail. File not exist create. */
7341 create_disp = FILE_CREATE;
7342 break;
7343 case SMB_O_CREAT:
7344 /* File exists open. File not exist create. */
7345 create_disp = FILE_OPEN_IF;
7346 break;
7347 case 0:
7348 /* File exists open. File not exist fail. */
7349 create_disp = FILE_OPEN;
7350 break;
7351 case SMB_O_EXCL:
7352 /* O_EXCL on its own without O_CREAT is undefined. */
7353 default:
7354 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7355 (unsigned int)wire_open_mode ));
7356 return NT_STATUS_INVALID_PARAMETER;
7359 /* Next factor in the effects of O_TRUNC. */
7360 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7362 if (wire_open_mode & SMB_O_TRUNC) {
7363 switch (create_disp) {
7364 case FILE_CREATE:
7365 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7366 /* Leave create_disp alone as
7367 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7369 /* File exists fail. File not exist create. */
7370 break;
7371 case FILE_OPEN_IF:
7372 /* SMB_O_CREAT | SMB_O_TRUNC */
7373 /* File exists overwrite. File not exist create. */
7374 create_disp = FILE_OVERWRITE_IF;
7375 break;
7376 case FILE_OPEN:
7377 /* SMB_O_TRUNC */
7378 /* File exists overwrite. File not exist fail. */
7379 create_disp = FILE_OVERWRITE;
7380 break;
7381 default:
7382 /* Cannot get here. */
7383 smb_panic("smb_posix_open: logic error");
7384 return NT_STATUS_INVALID_PARAMETER;
7388 raw_unixmode = IVAL(pdata,8);
7389 /* Next 4 bytes are not yet defined. */
7391 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7392 (VALID_STAT(smb_fname->st) ?
7393 PERM_EXISTING_FILE : PERM_NEW_FILE),
7394 &unixmode);
7396 if (!NT_STATUS_IS_OK(status)) {
7397 return status;
7400 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7402 if (wire_open_mode & SMB_O_SYNC) {
7403 create_options |= FILE_WRITE_THROUGH;
7405 if (wire_open_mode & SMB_O_APPEND) {
7406 access_mask |= FILE_APPEND_DATA;
7408 if (wire_open_mode & SMB_O_DIRECT) {
7409 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7412 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7413 VALID_STAT_OF_DIR(smb_fname->st)) {
7414 if (access_mask != SMB_O_RDONLY_MAPPING) {
7415 return NT_STATUS_FILE_IS_A_DIRECTORY;
7417 create_options &= ~FILE_NON_DIRECTORY_FILE;
7418 create_options |= FILE_DIRECTORY_FILE;
7421 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7422 smb_fname_str_dbg(smb_fname),
7423 (unsigned int)wire_open_mode,
7424 (unsigned int)unixmode ));
7426 status = SMB_VFS_CREATE_FILE(
7427 conn, /* conn */
7428 req, /* req */
7429 0, /* root_dir_fid */
7430 smb_fname, /* fname */
7431 access_mask, /* access_mask */
7432 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7433 FILE_SHARE_DELETE),
7434 create_disp, /* create_disposition*/
7435 create_options, /* create_options */
7436 mod_unixmode, /* file_attributes */
7437 oplock_request, /* oplock_request */
7438 0, /* allocation_size */
7439 0, /* private_flags */
7440 NULL, /* sd */
7441 NULL, /* ea_list */
7442 &fsp, /* result */
7443 &info); /* pinfo */
7445 if (!NT_STATUS_IS_OK(status)) {
7446 return status;
7449 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7450 extended_oplock_granted = True;
7453 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7454 extended_oplock_granted = True;
7457 info_level_return = SVAL(pdata,16);
7459 /* Allocate the correct return size. */
7461 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7462 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7463 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7464 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7465 } else {
7466 *pdata_return_size = 12;
7469 /* Realloc the data size */
7470 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7471 if (*ppdata == NULL) {
7472 close_file(req, fsp, ERROR_CLOSE);
7473 *pdata_return_size = 0;
7474 return NT_STATUS_NO_MEMORY;
7476 pdata = *ppdata;
7478 if (extended_oplock_granted) {
7479 if (flags & REQUEST_BATCH_OPLOCK) {
7480 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7481 } else {
7482 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7484 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7485 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7486 } else {
7487 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7490 SSVAL(pdata,2,fsp->fnum);
7491 SIVAL(pdata,4,info); /* Was file created etc. */
7493 switch (info_level_return) {
7494 case SMB_QUERY_FILE_UNIX_BASIC:
7495 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7496 SSVAL(pdata,10,0); /* padding. */
7497 store_file_unix_basic(conn, pdata + 12, fsp,
7498 &smb_fname->st);
7499 break;
7500 case SMB_QUERY_FILE_UNIX_INFO2:
7501 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7502 SSVAL(pdata,10,0); /* padding. */
7503 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7504 &smb_fname->st);
7505 break;
7506 default:
7507 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7508 SSVAL(pdata,10,0); /* padding. */
7509 break;
7511 return NT_STATUS_OK;
7514 /****************************************************************************
7515 Delete a file with POSIX semantics.
7516 ****************************************************************************/
7518 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7519 struct smb_request *req,
7520 const char *pdata,
7521 int total_data,
7522 struct smb_filename *smb_fname)
7524 NTSTATUS status = NT_STATUS_OK;
7525 files_struct *fsp = NULL;
7526 uint16 flags = 0;
7527 char del = 1;
7528 int info = 0;
7529 int create_options = 0;
7530 int i;
7531 struct share_mode_lock *lck = NULL;
7533 if (total_data < 2) {
7534 return NT_STATUS_INVALID_PARAMETER;
7537 flags = SVAL(pdata,0);
7539 if (!VALID_STAT(smb_fname->st)) {
7540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7543 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7544 !VALID_STAT_OF_DIR(smb_fname->st)) {
7545 return NT_STATUS_NOT_A_DIRECTORY;
7548 DEBUG(10,("smb_posix_unlink: %s %s\n",
7549 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7550 smb_fname_str_dbg(smb_fname)));
7552 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7553 create_options |= FILE_DIRECTORY_FILE;
7556 status = SMB_VFS_CREATE_FILE(
7557 conn, /* conn */
7558 req, /* req */
7559 0, /* root_dir_fid */
7560 smb_fname, /* fname */
7561 DELETE_ACCESS, /* access_mask */
7562 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7563 FILE_SHARE_DELETE),
7564 FILE_OPEN, /* create_disposition*/
7565 create_options, /* create_options */
7566 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7567 0, /* oplock_request */
7568 0, /* allocation_size */
7569 0, /* private_flags */
7570 NULL, /* sd */
7571 NULL, /* ea_list */
7572 &fsp, /* result */
7573 &info); /* pinfo */
7575 if (!NT_STATUS_IS_OK(status)) {
7576 return status;
7580 * Don't lie to client. If we can't really delete due to
7581 * non-POSIX opens return SHARING_VIOLATION.
7584 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7585 if (lck == NULL) {
7586 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7587 "lock for file %s\n", fsp_str_dbg(fsp)));
7588 close_file(req, fsp, NORMAL_CLOSE);
7589 return NT_STATUS_INVALID_PARAMETER;
7593 * See if others still have the file open. If this is the case, then
7594 * don't delete. If all opens are POSIX delete we can set the delete
7595 * on close disposition.
7597 for (i=0; i<lck->data->num_share_modes; i++) {
7598 struct share_mode_entry *e = &lck->data->share_modes[i];
7599 if (is_valid_share_mode_entry(e)) {
7600 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7601 continue;
7603 /* Fail with sharing violation. */
7604 close_file(req, fsp, NORMAL_CLOSE);
7605 TALLOC_FREE(lck);
7606 return NT_STATUS_SHARING_VIOLATION;
7611 * Set the delete on close.
7613 status = smb_set_file_disposition_info(conn,
7614 &del,
7616 fsp,
7617 smb_fname);
7619 if (!NT_STATUS_IS_OK(status)) {
7620 close_file(req, fsp, NORMAL_CLOSE);
7621 TALLOC_FREE(lck);
7622 return status;
7624 TALLOC_FREE(lck);
7625 return close_file(req, fsp, NORMAL_CLOSE);
7628 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7629 struct smb_request *req,
7630 TALLOC_CTX *mem_ctx,
7631 uint16_t info_level,
7632 files_struct *fsp,
7633 struct smb_filename *smb_fname,
7634 char **ppdata, int total_data,
7635 int *ret_data_size)
7637 char *pdata = *ppdata;
7638 NTSTATUS status = NT_STATUS_OK;
7639 int data_return_size = 0;
7641 *ret_data_size = 0;
7643 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7644 return NT_STATUS_INVALID_LEVEL;
7647 if (!CAN_WRITE(conn)) {
7648 /* Allow POSIX opens. The open path will deny
7649 * any non-readonly opens. */
7650 if (info_level != SMB_POSIX_PATH_OPEN) {
7651 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7655 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7656 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7657 fsp ? fsp->fnum : -1, info_level, total_data));
7659 switch (info_level) {
7661 case SMB_INFO_STANDARD:
7663 status = smb_set_info_standard(conn,
7664 pdata,
7665 total_data,
7666 fsp,
7667 smb_fname);
7668 break;
7671 case SMB_INFO_SET_EA:
7673 status = smb_info_set_ea(conn,
7674 pdata,
7675 total_data,
7676 fsp,
7677 smb_fname);
7678 break;
7681 case SMB_SET_FILE_BASIC_INFO:
7682 case SMB_FILE_BASIC_INFORMATION:
7684 status = smb_set_file_basic_info(conn,
7685 pdata,
7686 total_data,
7687 fsp,
7688 smb_fname);
7689 break;
7692 case SMB_FILE_ALLOCATION_INFORMATION:
7693 case SMB_SET_FILE_ALLOCATION_INFO:
7695 status = smb_set_file_allocation_info(conn, req,
7696 pdata,
7697 total_data,
7698 fsp,
7699 smb_fname);
7700 break;
7703 case SMB_FILE_END_OF_FILE_INFORMATION:
7704 case SMB_SET_FILE_END_OF_FILE_INFO:
7707 * XP/Win7 both fail after the createfile with
7708 * SMB_SET_FILE_END_OF_FILE_INFO but not
7709 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7710 * The level is known here, so pass it down
7711 * appropriately.
7713 bool should_fail =
7714 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7716 status = smb_set_file_end_of_file_info(conn, req,
7717 pdata,
7718 total_data,
7719 fsp,
7720 smb_fname,
7721 should_fail);
7722 break;
7725 case SMB_FILE_DISPOSITION_INFORMATION:
7726 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7728 #if 0
7729 /* JRA - We used to just ignore this on a path ?
7730 * Shouldn't this be invalid level on a pathname
7731 * based call ?
7733 if (tran_call != TRANSACT2_SETFILEINFO) {
7734 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7736 #endif
7737 status = smb_set_file_disposition_info(conn,
7738 pdata,
7739 total_data,
7740 fsp,
7741 smb_fname);
7742 break;
7745 case SMB_FILE_POSITION_INFORMATION:
7747 status = smb_file_position_information(conn,
7748 pdata,
7749 total_data,
7750 fsp);
7751 break;
7754 case SMB_FILE_FULL_EA_INFORMATION:
7756 status = smb_set_file_full_ea_info(conn,
7757 pdata,
7758 total_data,
7759 fsp);
7760 break;
7763 /* From tridge Samba4 :
7764 * MODE_INFORMATION in setfileinfo (I have no
7765 * idea what "mode information" on a file is - it takes a value of 0,
7766 * 2, 4 or 6. What could it be?).
7769 case SMB_FILE_MODE_INFORMATION:
7771 status = smb_file_mode_information(conn,
7772 pdata,
7773 total_data);
7774 break;
7778 * CIFS UNIX extensions.
7781 case SMB_SET_FILE_UNIX_BASIC:
7783 status = smb_set_file_unix_basic(conn, req,
7784 pdata,
7785 total_data,
7786 fsp,
7787 smb_fname);
7788 break;
7791 case SMB_SET_FILE_UNIX_INFO2:
7793 status = smb_set_file_unix_info2(conn, req,
7794 pdata,
7795 total_data,
7796 fsp,
7797 smb_fname);
7798 break;
7801 case SMB_SET_FILE_UNIX_LINK:
7803 if (fsp) {
7804 /* We must have a pathname for this. */
7805 return NT_STATUS_INVALID_LEVEL;
7807 status = smb_set_file_unix_link(conn, req, pdata,
7808 total_data, smb_fname);
7809 break;
7812 case SMB_SET_FILE_UNIX_HLINK:
7814 if (fsp) {
7815 /* We must have a pathname for this. */
7816 return NT_STATUS_INVALID_LEVEL;
7818 status = smb_set_file_unix_hlink(conn, req,
7819 pdata, total_data,
7820 smb_fname);
7821 break;
7824 case SMB_FILE_RENAME_INFORMATION:
7826 status = smb_file_rename_information(conn, req,
7827 pdata, total_data,
7828 fsp, smb_fname);
7829 break;
7832 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7834 /* SMB2 rename information. */
7835 status = smb2_file_rename_information(conn, req,
7836 pdata, total_data,
7837 fsp, smb_fname);
7838 break;
7841 case SMB_FILE_LINK_INFORMATION:
7843 status = smb_file_link_information(conn, req,
7844 pdata, total_data,
7845 fsp, smb_fname);
7846 break;
7849 #if defined(HAVE_POSIX_ACLS)
7850 case SMB_SET_POSIX_ACL:
7852 status = smb_set_posix_acl(conn,
7853 pdata,
7854 total_data,
7855 fsp,
7856 smb_fname);
7857 break;
7859 #endif
7861 case SMB_SET_POSIX_LOCK:
7863 if (!fsp) {
7864 return NT_STATUS_INVALID_LEVEL;
7866 status = smb_set_posix_lock(conn, req,
7867 pdata, total_data, fsp);
7868 break;
7871 case SMB_POSIX_PATH_OPEN:
7873 if (fsp) {
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL;
7878 status = smb_posix_open(conn, req,
7879 ppdata,
7880 total_data,
7881 smb_fname,
7882 &data_return_size);
7883 break;
7886 case SMB_POSIX_PATH_UNLINK:
7888 if (fsp) {
7889 /* We must have a pathname for this. */
7890 return NT_STATUS_INVALID_LEVEL;
7893 status = smb_posix_unlink(conn, req,
7894 pdata,
7895 total_data,
7896 smb_fname);
7897 break;
7900 default:
7901 return NT_STATUS_INVALID_LEVEL;
7904 if (!NT_STATUS_IS_OK(status)) {
7905 return status;
7908 *ret_data_size = data_return_size;
7909 return NT_STATUS_OK;
7912 /****************************************************************************
7913 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7914 ****************************************************************************/
7916 static void call_trans2setfilepathinfo(connection_struct *conn,
7917 struct smb_request *req,
7918 unsigned int tran_call,
7919 char **pparams, int total_params,
7920 char **ppdata, int total_data,
7921 unsigned int max_data_bytes)
7923 char *params = *pparams;
7924 char *pdata = *ppdata;
7925 uint16 info_level;
7926 struct smb_filename *smb_fname = NULL;
7927 files_struct *fsp = NULL;
7928 NTSTATUS status = NT_STATUS_OK;
7929 int data_return_size = 0;
7931 if (!params) {
7932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7933 return;
7936 if (tran_call == TRANSACT2_SETFILEINFO) {
7937 if (total_params < 4) {
7938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7939 return;
7942 fsp = file_fsp(req, SVAL(params,0));
7943 /* Basic check for non-null fsp. */
7944 if (!check_fsp_open(conn, req, fsp)) {
7945 return;
7947 info_level = SVAL(params,2);
7949 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7950 &smb_fname);
7951 if (!NT_STATUS_IS_OK(status)) {
7952 reply_nterror(req, status);
7953 return;
7956 if(fsp->fh->fd == -1) {
7958 * This is actually a SETFILEINFO on a directory
7959 * handle (returned from an NT SMB). NT5.0 seems
7960 * to do this call. JRA.
7962 if (INFO_LEVEL_IS_UNIX(info_level)) {
7963 /* Always do lstat for UNIX calls. */
7964 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7965 DEBUG(3,("call_trans2setfilepathinfo: "
7966 "SMB_VFS_LSTAT of %s failed "
7967 "(%s)\n",
7968 smb_fname_str_dbg(smb_fname),
7969 strerror(errno)));
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7971 return;
7973 } else {
7974 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7975 DEBUG(3,("call_trans2setfilepathinfo: "
7976 "fileinfo of %s failed (%s)\n",
7977 smb_fname_str_dbg(smb_fname),
7978 strerror(errno)));
7979 reply_nterror(req, map_nt_error_from_unix(errno));
7980 return;
7983 } else if (fsp->print_file) {
7985 * Doing a DELETE_ON_CLOSE should cancel a print job.
7987 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7988 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7990 DEBUG(3,("call_trans2setfilepathinfo: "
7991 "Cancelling print job (%s)\n",
7992 fsp_str_dbg(fsp)));
7994 SSVAL(params,0,0);
7995 send_trans2_replies(conn, req, params, 2,
7996 *ppdata, 0,
7997 max_data_bytes);
7998 return;
7999 } else {
8000 reply_nterror(req,
8001 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8002 return;
8004 } else {
8006 * Original code - this is an open file.
8008 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8009 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8010 "of fnum %d failed (%s)\n", fsp->fnum,
8011 strerror(errno)));
8012 reply_nterror(req, map_nt_error_from_unix(errno));
8013 return;
8016 } else {
8017 char *fname = NULL;
8018 uint32_t ucf_flags = 0;
8020 /* set path info */
8021 if (total_params < 7) {
8022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8023 return;
8026 info_level = SVAL(params,0);
8027 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8028 total_params - 6, STR_TERMINATE,
8029 &status);
8030 if (!NT_STATUS_IS_OK(status)) {
8031 reply_nterror(req, status);
8032 return;
8035 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8036 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8037 info_level == SMB_FILE_RENAME_INFORMATION ||
8038 info_level == SMB_POSIX_PATH_UNLINK) {
8039 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8042 status = filename_convert(req, conn,
8043 req->flags2 & FLAGS2_DFS_PATHNAMES,
8044 fname,
8045 ucf_flags,
8046 NULL,
8047 &smb_fname);
8048 if (!NT_STATUS_IS_OK(status)) {
8049 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8050 reply_botherror(req,
8051 NT_STATUS_PATH_NOT_COVERED,
8052 ERRSRV, ERRbadpath);
8053 return;
8055 reply_nterror(req, status);
8056 return;
8059 if (INFO_LEVEL_IS_UNIX(info_level)) {
8061 * For CIFS UNIX extensions the target name may not exist.
8064 /* Always do lstat for UNIX calls. */
8065 SMB_VFS_LSTAT(conn, smb_fname);
8067 } else if (!VALID_STAT(smb_fname->st) &&
8068 SMB_VFS_STAT(conn, smb_fname)) {
8069 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8070 "%s failed (%s)\n",
8071 smb_fname_str_dbg(smb_fname),
8072 strerror(errno)));
8073 reply_nterror(req, map_nt_error_from_unix(errno));
8074 return;
8078 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8079 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8080 fsp ? fsp->fnum : -1, info_level,total_data));
8082 /* Realloc the parameter size */
8083 *pparams = (char *)SMB_REALLOC(*pparams,2);
8084 if (*pparams == NULL) {
8085 reply_nterror(req, NT_STATUS_NO_MEMORY);
8086 return;
8088 params = *pparams;
8090 SSVAL(params,0,0);
8092 status = smbd_do_setfilepathinfo(conn, req, req,
8093 info_level,
8094 fsp,
8095 smb_fname,
8096 ppdata, total_data,
8097 &data_return_size);
8098 if (!NT_STATUS_IS_OK(status)) {
8099 if (open_was_deferred(req->sconn, req->mid)) {
8100 /* We have re-scheduled this call. */
8101 return;
8103 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8104 /* We have re-scheduled this call. */
8105 return;
8107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8108 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8109 ERRSRV, ERRbadpath);
8110 return;
8112 if (info_level == SMB_POSIX_PATH_OPEN) {
8113 reply_openerror(req, status);
8114 return;
8117 reply_nterror(req, status);
8118 return;
8121 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8122 max_data_bytes);
8124 return;
8127 /****************************************************************************
8128 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8129 ****************************************************************************/
8131 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8132 char **pparams, int total_params,
8133 char **ppdata, int total_data,
8134 unsigned int max_data_bytes)
8136 struct smb_filename *smb_dname = NULL;
8137 char *params = *pparams;
8138 char *pdata = *ppdata;
8139 char *directory = NULL;
8140 NTSTATUS status = NT_STATUS_OK;
8141 struct ea_list *ea_list = NULL;
8142 TALLOC_CTX *ctx = talloc_tos();
8144 if (!CAN_WRITE(conn)) {
8145 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8146 return;
8149 if (total_params < 5) {
8150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8151 return;
8154 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8155 total_params - 4, STR_TERMINATE,
8156 &status);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 reply_nterror(req, status);
8159 return;
8162 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8164 status = filename_convert(ctx,
8165 conn,
8166 req->flags2 & FLAGS2_DFS_PATHNAMES,
8167 directory,
8169 NULL,
8170 &smb_dname);
8172 if (!NT_STATUS_IS_OK(status)) {
8173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8174 reply_botherror(req,
8175 NT_STATUS_PATH_NOT_COVERED,
8176 ERRSRV, ERRbadpath);
8177 return;
8179 reply_nterror(req, status);
8180 return;
8184 * OS/2 workplace shell seems to send SET_EA requests of "null"
8185 * length (4 bytes containing IVAL 4).
8186 * They seem to have no effect. Bug #3212. JRA.
8189 if (total_data && (total_data != 4)) {
8190 /* Any data in this call is an EA list. */
8191 if (total_data < 10) {
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 goto out;
8196 if (IVAL(pdata,0) > total_data) {
8197 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8198 IVAL(pdata,0), (unsigned int)total_data));
8199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8200 goto out;
8203 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8204 total_data - 4);
8205 if (!ea_list) {
8206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8207 goto out;
8210 if (!lp_ea_support(SNUM(conn))) {
8211 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8212 goto out;
8215 /* If total_data == 4 Windows doesn't care what values
8216 * are placed in that field, it just ignores them.
8217 * The System i QNTC IBM SMB client puts bad values here,
8218 * so ignore them. */
8220 status = create_directory(conn, req, smb_dname);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 reply_nterror(req, status);
8224 goto out;
8227 /* Try and set any given EA. */
8228 if (ea_list) {
8229 status = set_ea(conn, NULL, smb_dname, ea_list);
8230 if (!NT_STATUS_IS_OK(status)) {
8231 reply_nterror(req, status);
8232 goto out;
8236 /* Realloc the parameter and data sizes */
8237 *pparams = (char *)SMB_REALLOC(*pparams,2);
8238 if(*pparams == NULL) {
8239 reply_nterror(req, NT_STATUS_NO_MEMORY);
8240 goto out;
8242 params = *pparams;
8244 SSVAL(params,0,0);
8246 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8248 out:
8249 TALLOC_FREE(smb_dname);
8250 return;
8253 /****************************************************************************
8254 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8255 We don't actually do this - we just send a null response.
8256 ****************************************************************************/
8258 static void call_trans2findnotifyfirst(connection_struct *conn,
8259 struct smb_request *req,
8260 char **pparams, int total_params,
8261 char **ppdata, int total_data,
8262 unsigned int max_data_bytes)
8264 char *params = *pparams;
8265 uint16 info_level;
8267 if (total_params < 6) {
8268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8269 return;
8272 info_level = SVAL(params,4);
8273 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8275 switch (info_level) {
8276 case 1:
8277 case 2:
8278 break;
8279 default:
8280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8281 return;
8284 /* Realloc the parameter and data sizes */
8285 *pparams = (char *)SMB_REALLOC(*pparams,6);
8286 if (*pparams == NULL) {
8287 reply_nterror(req, NT_STATUS_NO_MEMORY);
8288 return;
8290 params = *pparams;
8292 SSVAL(params,0,fnf_handle);
8293 SSVAL(params,2,0); /* No changes */
8294 SSVAL(params,4,0); /* No EA errors */
8296 fnf_handle++;
8298 if(fnf_handle == 0)
8299 fnf_handle = 257;
8301 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8303 return;
8306 /****************************************************************************
8307 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8308 changes). Currently this does nothing.
8309 ****************************************************************************/
8311 static void call_trans2findnotifynext(connection_struct *conn,
8312 struct smb_request *req,
8313 char **pparams, int total_params,
8314 char **ppdata, int total_data,
8315 unsigned int max_data_bytes)
8317 char *params = *pparams;
8319 DEBUG(3,("call_trans2findnotifynext\n"));
8321 /* Realloc the parameter and data sizes */
8322 *pparams = (char *)SMB_REALLOC(*pparams,4);
8323 if (*pparams == NULL) {
8324 reply_nterror(req, NT_STATUS_NO_MEMORY);
8325 return;
8327 params = *pparams;
8329 SSVAL(params,0,0); /* No changes */
8330 SSVAL(params,2,0); /* No EA errors */
8332 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8334 return;
8337 /****************************************************************************
8338 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8339 ****************************************************************************/
8341 static void call_trans2getdfsreferral(connection_struct *conn,
8342 struct smb_request *req,
8343 char **pparams, int total_params,
8344 char **ppdata, int total_data,
8345 unsigned int max_data_bytes)
8347 char *params = *pparams;
8348 char *pathname = NULL;
8349 int reply_size = 0;
8350 int max_referral_level;
8351 NTSTATUS status = NT_STATUS_OK;
8352 TALLOC_CTX *ctx = talloc_tos();
8354 DEBUG(10,("call_trans2getdfsreferral\n"));
8356 if (total_params < 3) {
8357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 return;
8361 max_referral_level = SVAL(params,0);
8363 if(!lp_host_msdfs()) {
8364 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8365 return;
8368 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8369 total_params - 2, STR_TERMINATE);
8370 if (!pathname) {
8371 reply_nterror(req, NT_STATUS_NOT_FOUND);
8372 return;
8374 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8375 ppdata,&status)) < 0) {
8376 reply_nterror(req, status);
8377 return;
8380 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8381 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8382 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8384 return;
8387 #define LMCAT_SPL 0x53
8388 #define LMFUNC_GETJOBID 0x60
8390 /****************************************************************************
8391 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8392 ****************************************************************************/
8394 static void call_trans2ioctl(connection_struct *conn,
8395 struct smb_request *req,
8396 char **pparams, int total_params,
8397 char **ppdata, int total_data,
8398 unsigned int max_data_bytes)
8400 char *pdata = *ppdata;
8401 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8403 /* check for an invalid fid before proceeding */
8405 if (!fsp) {
8406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8407 return;
8410 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8411 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8412 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8413 if (*ppdata == NULL) {
8414 reply_nterror(req, NT_STATUS_NO_MEMORY);
8415 return;
8417 pdata = *ppdata;
8419 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8420 CAN ACCEPT THIS IN UNICODE. JRA. */
8422 /* Job number */
8423 if (fsp->print_file) {
8424 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8425 } else {
8426 SSVAL(pdata, 0, 0);
8428 srvstr_push(pdata, req->flags2, pdata + 2,
8429 lp_netbios_name(), 15,
8430 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8431 srvstr_push(pdata, req->flags2, pdata+18,
8432 lp_servicename(SNUM(conn)), 13,
8433 STR_ASCII|STR_TERMINATE); /* Service name */
8434 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8435 max_data_bytes);
8436 return;
8439 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8440 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8443 /****************************************************************************
8444 Reply to a SMBfindclose (stop trans2 directory search).
8445 ****************************************************************************/
8447 void reply_findclose(struct smb_request *req)
8449 int dptr_num;
8450 struct smbd_server_connection *sconn = req->sconn;
8452 START_PROFILE(SMBfindclose);
8454 if (req->wct < 1) {
8455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8456 END_PROFILE(SMBfindclose);
8457 return;
8460 dptr_num = SVALS(req->vwv+0, 0);
8462 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8464 dptr_close(sconn, &dptr_num);
8466 reply_outbuf(req, 0, 0);
8468 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8470 END_PROFILE(SMBfindclose);
8471 return;
8474 /****************************************************************************
8475 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8476 ****************************************************************************/
8478 void reply_findnclose(struct smb_request *req)
8480 int dptr_num;
8482 START_PROFILE(SMBfindnclose);
8484 if (req->wct < 1) {
8485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8486 END_PROFILE(SMBfindnclose);
8487 return;
8490 dptr_num = SVAL(req->vwv+0, 0);
8492 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8494 /* We never give out valid handles for a
8495 findnotifyfirst - so any dptr_num is ok here.
8496 Just ignore it. */
8498 reply_outbuf(req, 0, 0);
8500 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8502 END_PROFILE(SMBfindnclose);
8503 return;
8506 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8507 struct trans_state *state)
8509 if (get_Protocol() >= PROTOCOL_NT1) {
8510 req->flags2 |= 0x40; /* IS_LONG_NAME */
8511 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8514 if (conn->encrypt_level == Required && !req->encrypted) {
8515 if (state->call != TRANSACT2_QFSINFO &&
8516 state->call != TRANSACT2_SETFSINFO) {
8517 DEBUG(0,("handle_trans2: encryption required "
8518 "with call 0x%x\n",
8519 (unsigned int)state->call));
8520 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8521 return;
8525 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8527 /* Now we must call the relevant TRANS2 function */
8528 switch(state->call) {
8529 case TRANSACT2_OPEN:
8531 START_PROFILE(Trans2_open);
8532 call_trans2open(conn, req,
8533 &state->param, state->total_param,
8534 &state->data, state->total_data,
8535 state->max_data_return);
8536 END_PROFILE(Trans2_open);
8537 break;
8540 case TRANSACT2_FINDFIRST:
8542 START_PROFILE(Trans2_findfirst);
8543 call_trans2findfirst(conn, req,
8544 &state->param, state->total_param,
8545 &state->data, state->total_data,
8546 state->max_data_return);
8547 END_PROFILE(Trans2_findfirst);
8548 break;
8551 case TRANSACT2_FINDNEXT:
8553 START_PROFILE(Trans2_findnext);
8554 call_trans2findnext(conn, req,
8555 &state->param, state->total_param,
8556 &state->data, state->total_data,
8557 state->max_data_return);
8558 END_PROFILE(Trans2_findnext);
8559 break;
8562 case TRANSACT2_QFSINFO:
8564 START_PROFILE(Trans2_qfsinfo);
8565 call_trans2qfsinfo(conn, req,
8566 &state->param, state->total_param,
8567 &state->data, state->total_data,
8568 state->max_data_return);
8569 END_PROFILE(Trans2_qfsinfo);
8570 break;
8573 case TRANSACT2_SETFSINFO:
8575 START_PROFILE(Trans2_setfsinfo);
8576 call_trans2setfsinfo(conn, req,
8577 &state->param, state->total_param,
8578 &state->data, state->total_data,
8579 state->max_data_return);
8580 END_PROFILE(Trans2_setfsinfo);
8581 break;
8584 case TRANSACT2_QPATHINFO:
8585 case TRANSACT2_QFILEINFO:
8587 START_PROFILE(Trans2_qpathinfo);
8588 call_trans2qfilepathinfo(conn, req, state->call,
8589 &state->param, state->total_param,
8590 &state->data, state->total_data,
8591 state->max_data_return);
8592 END_PROFILE(Trans2_qpathinfo);
8593 break;
8596 case TRANSACT2_SETPATHINFO:
8597 case TRANSACT2_SETFILEINFO:
8599 START_PROFILE(Trans2_setpathinfo);
8600 call_trans2setfilepathinfo(conn, req, state->call,
8601 &state->param, state->total_param,
8602 &state->data, state->total_data,
8603 state->max_data_return);
8604 END_PROFILE(Trans2_setpathinfo);
8605 break;
8608 case TRANSACT2_FINDNOTIFYFIRST:
8610 START_PROFILE(Trans2_findnotifyfirst);
8611 call_trans2findnotifyfirst(conn, req,
8612 &state->param, state->total_param,
8613 &state->data, state->total_data,
8614 state->max_data_return);
8615 END_PROFILE(Trans2_findnotifyfirst);
8616 break;
8619 case TRANSACT2_FINDNOTIFYNEXT:
8621 START_PROFILE(Trans2_findnotifynext);
8622 call_trans2findnotifynext(conn, req,
8623 &state->param, state->total_param,
8624 &state->data, state->total_data,
8625 state->max_data_return);
8626 END_PROFILE(Trans2_findnotifynext);
8627 break;
8630 case TRANSACT2_MKDIR:
8632 START_PROFILE(Trans2_mkdir);
8633 call_trans2mkdir(conn, req,
8634 &state->param, state->total_param,
8635 &state->data, state->total_data,
8636 state->max_data_return);
8637 END_PROFILE(Trans2_mkdir);
8638 break;
8641 case TRANSACT2_GET_DFS_REFERRAL:
8643 START_PROFILE(Trans2_get_dfs_referral);
8644 call_trans2getdfsreferral(conn, req,
8645 &state->param, state->total_param,
8646 &state->data, state->total_data,
8647 state->max_data_return);
8648 END_PROFILE(Trans2_get_dfs_referral);
8649 break;
8652 case TRANSACT2_IOCTL:
8654 START_PROFILE(Trans2_ioctl);
8655 call_trans2ioctl(conn, req,
8656 &state->param, state->total_param,
8657 &state->data, state->total_data,
8658 state->max_data_return);
8659 END_PROFILE(Trans2_ioctl);
8660 break;
8663 default:
8664 /* Error in request */
8665 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8666 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8670 /****************************************************************************
8671 Reply to a SMBtrans2.
8672 ****************************************************************************/
8674 void reply_trans2(struct smb_request *req)
8676 connection_struct *conn = req->conn;
8677 unsigned int dsoff;
8678 unsigned int dscnt;
8679 unsigned int psoff;
8680 unsigned int pscnt;
8681 unsigned int tran_call;
8682 struct trans_state *state;
8683 NTSTATUS result;
8685 START_PROFILE(SMBtrans2);
8687 if (req->wct < 14) {
8688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8689 END_PROFILE(SMBtrans2);
8690 return;
8693 dsoff = SVAL(req->vwv+12, 0);
8694 dscnt = SVAL(req->vwv+11, 0);
8695 psoff = SVAL(req->vwv+10, 0);
8696 pscnt = SVAL(req->vwv+9, 0);
8697 tran_call = SVAL(req->vwv+14, 0);
8699 result = allow_new_trans(conn->pending_trans, req->mid);
8700 if (!NT_STATUS_IS_OK(result)) {
8701 DEBUG(2, ("Got invalid trans2 request: %s\n",
8702 nt_errstr(result)));
8703 reply_nterror(req, result);
8704 END_PROFILE(SMBtrans2);
8705 return;
8708 if (IS_IPC(conn)) {
8709 switch (tran_call) {
8710 /* List the allowed trans2 calls on IPC$ */
8711 case TRANSACT2_OPEN:
8712 case TRANSACT2_GET_DFS_REFERRAL:
8713 case TRANSACT2_QFILEINFO:
8714 case TRANSACT2_QFSINFO:
8715 case TRANSACT2_SETFSINFO:
8716 break;
8717 default:
8718 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8719 END_PROFILE(SMBtrans2);
8720 return;
8724 if ((state = talloc(conn, struct trans_state)) == NULL) {
8725 DEBUG(0, ("talloc failed\n"));
8726 reply_nterror(req, NT_STATUS_NO_MEMORY);
8727 END_PROFILE(SMBtrans2);
8728 return;
8731 state->cmd = SMBtrans2;
8733 state->mid = req->mid;
8734 state->vuid = req->vuid;
8735 state->setup_count = SVAL(req->vwv+13, 0);
8736 state->setup = NULL;
8737 state->total_param = SVAL(req->vwv+0, 0);
8738 state->param = NULL;
8739 state->total_data = SVAL(req->vwv+1, 0);
8740 state->data = NULL;
8741 state->max_param_return = SVAL(req->vwv+2, 0);
8742 state->max_data_return = SVAL(req->vwv+3, 0);
8743 state->max_setup_return = SVAL(req->vwv+4, 0);
8744 state->close_on_completion = BITSETW(req->vwv+5, 0);
8745 state->one_way = BITSETW(req->vwv+5, 1);
8747 state->call = tran_call;
8749 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8750 is so as a sanity check */
8751 if (state->setup_count != 1) {
8753 * Need to have rc=0 for ioctl to get job id for OS/2.
8754 * Network printing will fail if function is not successful.
8755 * Similar function in reply.c will be used if protocol
8756 * is LANMAN1.0 instead of LM1.2X002.
8757 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8758 * outbuf doesn't have to be set(only job id is used).
8760 if ( (state->setup_count == 4)
8761 && (tran_call == TRANSACT2_IOCTL)
8762 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8763 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8764 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8765 } else {
8766 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8767 DEBUG(2,("Transaction is %d\n",tran_call));
8768 TALLOC_FREE(state);
8769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8770 END_PROFILE(SMBtrans2);
8771 return;
8775 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8776 goto bad_param;
8778 if (state->total_data) {
8780 if (trans_oob(state->total_data, 0, dscnt)
8781 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8782 goto bad_param;
8785 /* Can't use talloc here, the core routines do realloc on the
8786 * params and data. */
8787 state->data = (char *)SMB_MALLOC(state->total_data);
8788 if (state->data == NULL) {
8789 DEBUG(0,("reply_trans2: data malloc fail for %u "
8790 "bytes !\n", (unsigned int)state->total_data));
8791 TALLOC_FREE(state);
8792 reply_nterror(req, NT_STATUS_NO_MEMORY);
8793 END_PROFILE(SMBtrans2);
8794 return;
8797 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8800 if (state->total_param) {
8802 if (trans_oob(state->total_param, 0, pscnt)
8803 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8804 goto bad_param;
8807 /* Can't use talloc here, the core routines do realloc on the
8808 * params and data. */
8809 state->param = (char *)SMB_MALLOC(state->total_param);
8810 if (state->param == NULL) {
8811 DEBUG(0,("reply_trans: param malloc fail for %u "
8812 "bytes !\n", (unsigned int)state->total_param));
8813 SAFE_FREE(state->data);
8814 TALLOC_FREE(state);
8815 reply_nterror(req, NT_STATUS_NO_MEMORY);
8816 END_PROFILE(SMBtrans2);
8817 return;
8820 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8823 state->received_data = dscnt;
8824 state->received_param = pscnt;
8826 if ((state->received_param == state->total_param) &&
8827 (state->received_data == state->total_data)) {
8829 handle_trans2(conn, req, state);
8831 SAFE_FREE(state->data);
8832 SAFE_FREE(state->param);
8833 TALLOC_FREE(state);
8834 END_PROFILE(SMBtrans2);
8835 return;
8838 DLIST_ADD(conn->pending_trans, state);
8840 /* We need to send an interim response then receive the rest
8841 of the parameter/data bytes */
8842 reply_outbuf(req, 0, 0);
8843 show_msg((char *)req->outbuf);
8844 END_PROFILE(SMBtrans2);
8845 return;
8847 bad_param:
8849 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8850 SAFE_FREE(state->data);
8851 SAFE_FREE(state->param);
8852 TALLOC_FREE(state);
8853 END_PROFILE(SMBtrans2);
8854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8858 /****************************************************************************
8859 Reply to a SMBtranss2
8860 ****************************************************************************/
8862 void reply_transs2(struct smb_request *req)
8864 connection_struct *conn = req->conn;
8865 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8866 struct trans_state *state;
8868 START_PROFILE(SMBtranss2);
8870 show_msg((const char *)req->inbuf);
8872 if (req->wct < 8) {
8873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8874 END_PROFILE(SMBtranss2);
8875 return;
8878 for (state = conn->pending_trans; state != NULL;
8879 state = state->next) {
8880 if (state->mid == req->mid) {
8881 break;
8885 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8887 END_PROFILE(SMBtranss2);
8888 return;
8891 /* Revise state->total_param and state->total_data in case they have
8892 changed downwards */
8894 if (SVAL(req->vwv+0, 0) < state->total_param)
8895 state->total_param = SVAL(req->vwv+0, 0);
8896 if (SVAL(req->vwv+1, 0) < state->total_data)
8897 state->total_data = SVAL(req->vwv+1, 0);
8899 pcnt = SVAL(req->vwv+2, 0);
8900 poff = SVAL(req->vwv+3, 0);
8901 pdisp = SVAL(req->vwv+4, 0);
8903 dcnt = SVAL(req->vwv+5, 0);
8904 doff = SVAL(req->vwv+6, 0);
8905 ddisp = SVAL(req->vwv+7, 0);
8907 state->received_param += pcnt;
8908 state->received_data += dcnt;
8910 if ((state->received_data > state->total_data) ||
8911 (state->received_param > state->total_param))
8912 goto bad_param;
8914 if (pcnt) {
8915 if (trans_oob(state->total_param, pdisp, pcnt)
8916 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8917 goto bad_param;
8919 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8922 if (dcnt) {
8923 if (trans_oob(state->total_data, ddisp, dcnt)
8924 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8925 goto bad_param;
8927 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8930 if ((state->received_param < state->total_param) ||
8931 (state->received_data < state->total_data)) {
8932 END_PROFILE(SMBtranss2);
8933 return;
8936 handle_trans2(conn, req, state);
8938 DLIST_REMOVE(conn->pending_trans, state);
8939 SAFE_FREE(state->data);
8940 SAFE_FREE(state->param);
8941 TALLOC_FREE(state);
8943 END_PROFILE(SMBtranss2);
8944 return;
8946 bad_param:
8948 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8949 DLIST_REMOVE(conn->pending_trans, state);
8950 SAFE_FREE(state->data);
8951 SAFE_FREE(state->param);
8952 TALLOC_FREE(state);
8953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8954 END_PROFILE(SMBtranss2);
8955 return;