Final part of patchset to fix bug #8556 - ACL permissions ignored when SMBsetatr...
[Samba/id10ts.git] / source3 / smbd / trans2.c
blob024979c20097af2b5418ef5ae24a37d1ccb79d76
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
43 char *pdata,
44 files_struct *fsp,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 The canonical "check access" based on object handle or path function.
54 ********************************************************************/
56 NTSTATUS check_access(connection_struct *conn,
57 files_struct *fsp,
58 const struct smb_filename *smb_fname,
59 uint32_t access_mask)
61 if (fsp) {
62 if (!(fsp->access_mask & access_mask)) {
63 return NT_STATUS_ACCESS_DENIED;
65 } else {
66 NTSTATUS status = smbd_check_access_rights(conn,
67 smb_fname,
68 access_mask);
69 if (!NT_STATUS_IS_OK(status)) {
70 return status;
73 return NT_STATUS_OK;
76 /********************************************************************
77 Roundup a value to the nearest allocation roundup size boundary.
78 Only do this for Windows clients.
79 ********************************************************************/
81 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
83 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
85 /* Only roundup for Windows clients. */
86 enum remote_arch_types ra_type = get_remote_arch();
87 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
88 val = SMB_ROUNDUP(val,rval);
90 return val;
93 /********************************************************************
94 Create a 64 bit FileIndex. If the file is on the same device as
95 the root of the share, just return the 64-bit inode. If it isn't,
96 mangle as we used to do.
97 ********************************************************************/
99 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
101 uint64_t file_index;
102 if (conn->base_share_dev == psbuf->st_ex_dev) {
103 return (uint64_t)psbuf->st_ex_ino;
105 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
106 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
107 return file_index;
110 /****************************************************************************
111 Utility functions for dealing with extended attributes.
112 ****************************************************************************/
114 /****************************************************************************
115 Refuse to allow clients to overwrite our private xattrs.
116 ****************************************************************************/
118 static bool samba_private_attr_name(const char *unix_ea_name)
120 static const char * const prohibited_ea_names[] = {
121 SAMBA_POSIX_INHERITANCE_EA_NAME,
122 SAMBA_XATTR_DOS_ATTRIB,
123 SAMBA_XATTR_MARKER,
124 XATTR_NTACL_NAME,
125 NULL
128 int i;
130 for (i = 0; prohibited_ea_names[i]; i++) {
131 if (strequal( prohibited_ea_names[i], unix_ea_name))
132 return true;
134 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
135 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
136 return true;
138 return false;
141 /****************************************************************************
142 Get one EA value. Fill in a struct ea_struct.
143 ****************************************************************************/
145 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 const char *ea_name, struct ea_struct *pea)
149 /* Get the value of this xattr. Max size is 64k. */
150 size_t attr_size = 256;
151 char *val = NULL;
152 ssize_t sizeret;
154 again:
156 val = talloc_realloc(mem_ctx, val, char, attr_size);
157 if (!val) {
158 return NT_STATUS_NO_MEMORY;
161 if (fsp && fsp->fh->fd != -1) {
162 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
163 } else {
164 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
167 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
168 attr_size = 65536;
169 goto again;
172 if (sizeret == -1) {
173 return map_nt_error_from_unix(errno);
176 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
177 dump_data(10, (uint8 *)val, sizeret);
179 pea->flags = 0;
180 if (strnequal(ea_name, "user.", 5)) {
181 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
182 } else {
183 pea->name = talloc_strdup(mem_ctx, ea_name);
185 if (pea->name == NULL) {
186 TALLOC_FREE(val);
187 return NT_STATUS_NO_MEMORY;
189 pea->value.data = (unsigned char *)val;
190 pea->value.length = (size_t)sizeret;
191 return NT_STATUS_OK;
194 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
195 files_struct *fsp, const char *fname,
196 char ***pnames, size_t *pnum_names)
198 /* Get a list of all xattrs. Max namesize is 64k. */
199 size_t ea_namelist_size = 1024;
200 char *ea_namelist = NULL;
202 char *p;
203 char **names, **tmp;
204 size_t num_names;
205 ssize_t sizeret = -1;
207 if (!lp_ea_support(SNUM(conn))) {
208 if (pnames) {
209 *pnames = NULL;
211 *pnum_names = 0;
212 return NT_STATUS_OK;
216 * TALLOC the result early to get the talloc hierarchy right.
219 names = talloc_array(mem_ctx, char *, 1);
220 if (names == NULL) {
221 DEBUG(0, ("talloc failed\n"));
222 return NT_STATUS_NO_MEMORY;
225 while (ea_namelist_size <= 65536) {
227 ea_namelist = talloc_realloc(
228 names, ea_namelist, char, ea_namelist_size);
229 if (ea_namelist == NULL) {
230 DEBUG(0, ("talloc failed\n"));
231 TALLOC_FREE(names);
232 return NT_STATUS_NO_MEMORY;
235 if (fsp && fsp->fh->fd != -1) {
236 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
237 ea_namelist_size);
238 } else {
239 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
240 ea_namelist_size);
243 if ((sizeret == -1) && (errno == ERANGE)) {
244 ea_namelist_size *= 2;
246 else {
247 break;
251 if (sizeret == -1) {
252 TALLOC_FREE(names);
253 return map_nt_error_from_unix(errno);
256 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
257 (unsigned int)sizeret));
259 if (sizeret == 0) {
260 TALLOC_FREE(names);
261 if (pnames) {
262 *pnames = NULL;
264 *pnum_names = 0;
265 return NT_STATUS_OK;
269 * Ensure the result is 0-terminated
272 if (ea_namelist[sizeret-1] != '\0') {
273 TALLOC_FREE(names);
274 return NT_STATUS_INTERNAL_ERROR;
278 * count the names
280 num_names = 0;
282 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
283 num_names += 1;
286 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
287 if (tmp == NULL) {
288 DEBUG(0, ("talloc failed\n"));
289 TALLOC_FREE(names);
290 return NT_STATUS_NO_MEMORY;
293 names = tmp;
294 num_names = 0;
296 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
297 names[num_names++] = p;
300 if (pnames) {
301 *pnames = names;
302 } else {
303 TALLOC_FREE(names);
305 *pnum_names = num_names;
306 return NT_STATUS_OK;
309 /****************************************************************************
310 Return a linked list of the total EA's. Plus the total size
311 ****************************************************************************/
313 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
314 const char *fname, size_t *pea_total_len)
316 /* Get a list of all xattrs. Max namesize is 64k. */
317 size_t i, num_names;
318 char **names;
319 struct ea_list *ea_list_head = NULL;
320 NTSTATUS status;
322 *pea_total_len = 0;
324 if (!lp_ea_support(SNUM(conn))) {
325 return NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 &names, &num_names);
331 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
332 return NULL;
335 for (i=0; i<num_names; i++) {
336 struct ea_list *listp;
337 fstring dos_ea_name;
339 if (strnequal(names[i], "system.", 7)
340 || samba_private_attr_name(names[i]))
341 continue;
343 listp = talloc(mem_ctx, struct ea_list);
344 if (listp == NULL) {
345 return NULL;
348 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
349 fname, names[i],
350 &listp->ea))) {
351 return NULL;
354 push_ascii_fstring(dos_ea_name, listp->ea.name);
356 *pea_total_len +=
357 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
359 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
360 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
361 (unsigned int)listp->ea.value.length));
363 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
367 /* Add on 4 for total length. */
368 if (*pea_total_len) {
369 *pea_total_len += 4;
372 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
373 (unsigned int)*pea_total_len));
375 return ea_list_head;
378 /****************************************************************************
379 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
380 that was filled.
381 ****************************************************************************/
383 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
384 connection_struct *conn, struct ea_list *ea_list)
386 unsigned int ret_data_size = 4;
387 char *p = pdata;
389 SMB_ASSERT(total_data_size >= 4);
391 if (!lp_ea_support(SNUM(conn))) {
392 SIVAL(pdata,4,0);
393 return 4;
396 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
397 size_t dos_namelen;
398 fstring dos_ea_name;
399 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
400 dos_namelen = strlen(dos_ea_name);
401 if (dos_namelen > 255 || dos_namelen == 0) {
402 break;
404 if (ea_list->ea.value.length > 65535) {
405 break;
407 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
408 break;
411 /* We know we have room. */
412 SCVAL(p,0,ea_list->ea.flags);
413 SCVAL(p,1,dos_namelen);
414 SSVAL(p,2,ea_list->ea.value.length);
415 strlcpy(p+4, dos_ea_name, dos_namelen+1);
416 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
418 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
419 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
422 ret_data_size = PTR_DIFF(p, pdata);
423 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
424 SIVAL(pdata,0,ret_data_size);
425 return ret_data_size;
428 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
429 char *pdata,
430 unsigned int total_data_size,
431 unsigned int *ret_data_size,
432 connection_struct *conn,
433 struct ea_list *ea_list)
435 uint8_t *p = (uint8_t *)pdata;
436 uint8_t *last_start = NULL;
438 *ret_data_size = 0;
440 if (!lp_ea_support(SNUM(conn))) {
441 return NT_STATUS_NO_EAS_ON_FILE;
444 for (; ea_list; ea_list = ea_list->next) {
445 size_t dos_namelen;
446 fstring dos_ea_name;
447 size_t this_size;
449 if (last_start) {
450 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
452 last_start = p;
454 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
455 dos_namelen = strlen(dos_ea_name);
456 if (dos_namelen > 255 || dos_namelen == 0) {
457 return NT_STATUS_INTERNAL_ERROR;
459 if (ea_list->ea.value.length > 65535) {
460 return NT_STATUS_INTERNAL_ERROR;
463 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
465 if (ea_list->next) {
466 size_t pad = 4 - (this_size % 4);
467 this_size += pad;
470 if (this_size > total_data_size) {
471 return NT_STATUS_INFO_LENGTH_MISMATCH;
474 /* We know we have room. */
475 SIVAL(p, 0x00, 0); /* next offset */
476 SCVAL(p, 0x04, ea_list->ea.flags);
477 SCVAL(p, 0x05, dos_namelen);
478 SSVAL(p, 0x06, ea_list->ea.value.length);
479 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
480 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
482 total_data_size -= this_size;
483 p += this_size;
486 *ret_data_size = PTR_DIFF(p, pdata);
487 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
488 return NT_STATUS_OK;
491 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
493 size_t total_ea_len = 0;
494 TALLOC_CTX *mem_ctx = NULL;
496 if (!lp_ea_support(SNUM(conn))) {
497 return 0;
499 mem_ctx = talloc_tos();
500 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
501 return total_ea_len;
504 /****************************************************************************
505 Ensure the EA name is case insensitive by matching any existing EA name.
506 ****************************************************************************/
508 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
510 size_t total_ea_len;
511 TALLOC_CTX *mem_ctx = talloc_tos();
512 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
514 for (; ea_list; ea_list = ea_list->next) {
515 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
516 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
517 &unix_ea_name[5], ea_list->ea.name));
518 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
519 break;
524 /****************************************************************************
525 Set or delete an extended attribute.
526 ****************************************************************************/
528 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
529 const struct smb_filename *smb_fname, struct ea_list *ea_list)
531 NTSTATUS status;
532 char *fname = NULL;
534 if (!lp_ea_support(SNUM(conn))) {
535 return NT_STATUS_EAS_NOT_SUPPORTED;
538 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
539 if (!NT_STATUS_IS_OK(status)) {
540 return status;
543 /* For now setting EAs on streams isn't supported. */
544 fname = smb_fname->base_name;
546 for (;ea_list; ea_list = ea_list->next) {
547 int ret;
548 fstring unix_ea_name;
550 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
551 fstrcat(unix_ea_name, ea_list->ea.name);
553 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
555 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
557 if (samba_private_attr_name(unix_ea_name)) {
558 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
559 return NT_STATUS_ACCESS_DENIED;
562 if (ea_list->ea.value.length == 0) {
563 /* Remove the attribute. */
564 if (fsp && (fsp->fh->fd != -1)) {
565 DEBUG(10,("set_ea: deleting ea name %s on "
566 "file %s by file descriptor.\n",
567 unix_ea_name, fsp_str_dbg(fsp)));
568 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
569 } else {
570 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
571 unix_ea_name, fname));
572 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
574 #ifdef ENOATTR
575 /* Removing a non existent attribute always succeeds. */
576 if (ret == -1 && errno == ENOATTR) {
577 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
578 unix_ea_name));
579 ret = 0;
581 #endif
582 } else {
583 if (fsp && (fsp->fh->fd != -1)) {
584 DEBUG(10,("set_ea: setting ea name %s on file "
585 "%s by file descriptor.\n",
586 unix_ea_name, fsp_str_dbg(fsp)));
587 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
588 ea_list->ea.value.data, ea_list->ea.value.length, 0);
589 } else {
590 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
591 unix_ea_name, fname));
592 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
593 ea_list->ea.value.data, ea_list->ea.value.length, 0);
597 if (ret == -1) {
598 #ifdef ENOTSUP
599 if (errno == ENOTSUP) {
600 return NT_STATUS_EAS_NOT_SUPPORTED;
602 #endif
603 return map_nt_error_from_unix(errno);
607 return NT_STATUS_OK;
609 /****************************************************************************
610 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
611 ****************************************************************************/
613 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
615 struct ea_list *ea_list_head = NULL;
616 size_t converted_size, offset = 0;
618 while (offset + 2 < data_size) {
619 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
620 unsigned int namelen = CVAL(pdata,offset);
622 offset++; /* Go past the namelen byte. */
624 /* integer wrap paranioa. */
625 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
626 (offset > data_size) || (namelen > data_size) ||
627 (offset + namelen >= data_size)) {
628 break;
630 /* Ensure the name is null terminated. */
631 if (pdata[offset + namelen] != '\0') {
632 return NULL;
634 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
635 &converted_size)) {
636 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
637 "failed: %s", strerror(errno)));
639 if (!eal->ea.name) {
640 return NULL;
643 offset += (namelen + 1); /* Go past the name + terminating zero. */
644 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
645 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
648 return ea_list_head;
651 /****************************************************************************
652 Read one EA list entry from the buffer.
653 ****************************************************************************/
655 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
657 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
658 uint16 val_len;
659 unsigned int namelen;
660 size_t converted_size;
662 if (!eal) {
663 return NULL;
666 if (data_size < 6) {
667 return NULL;
670 eal->ea.flags = CVAL(pdata,0);
671 namelen = CVAL(pdata,1);
672 val_len = SVAL(pdata,2);
674 if (4 + namelen + 1 + val_len > data_size) {
675 return NULL;
678 /* Ensure the name is null terminated. */
679 if (pdata[namelen + 4] != '\0') {
680 return NULL;
682 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
683 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
684 strerror(errno)));
686 if (!eal->ea.name) {
687 return NULL;
690 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
691 if (!eal->ea.value.data) {
692 return NULL;
695 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
697 /* Ensure we're null terminated just in case we print the value. */
698 eal->ea.value.data[val_len] = '\0';
699 /* But don't count the null. */
700 eal->ea.value.length--;
702 if (pbytes_used) {
703 *pbytes_used = 4 + namelen + 1 + val_len;
706 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
707 dump_data(10, eal->ea.value.data, eal->ea.value.length);
709 return eal;
712 /****************************************************************************
713 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
718 struct ea_list *ea_list_head = NULL;
719 size_t offset = 0;
720 size_t bytes_used = 0;
722 while (offset < data_size) {
723 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
725 if (!eal) {
726 return NULL;
729 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
730 offset += bytes_used;
733 return ea_list_head;
736 /****************************************************************************
737 Count the total EA size needed.
738 ****************************************************************************/
740 static size_t ea_list_size(struct ea_list *ealist)
742 fstring dos_ea_name;
743 struct ea_list *listp;
744 size_t ret = 0;
746 for (listp = ealist; listp; listp = listp->next) {
747 push_ascii_fstring(dos_ea_name, listp->ea.name);
748 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
750 /* Add on 4 for total length. */
751 if (ret) {
752 ret += 4;
755 return ret;
758 /****************************************************************************
759 Return a union of EA's from a file list and a list of names.
760 The TALLOC context for the two lists *MUST* be identical as we steal
761 memory from one list to add to another. JRA.
762 ****************************************************************************/
764 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
766 struct ea_list *nlistp, *flistp;
768 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
769 for (flistp = file_list; flistp; flistp = flistp->next) {
770 if (strequal(nlistp->ea.name, flistp->ea.name)) {
771 break;
775 if (flistp) {
776 /* Copy the data from this entry. */
777 nlistp->ea.flags = flistp->ea.flags;
778 nlistp->ea.value = flistp->ea.value;
779 } else {
780 /* Null entry. */
781 nlistp->ea.flags = 0;
782 ZERO_STRUCT(nlistp->ea.value);
786 *total_ea_len = ea_list_size(name_list);
787 return name_list;
790 /****************************************************************************
791 Send the required number of replies back.
792 We assume all fields other than the data fields are
793 set correctly for the type of call.
794 HACK ! Always assumes smb_setup field is zero.
795 ****************************************************************************/
797 void send_trans2_replies(connection_struct *conn,
798 struct smb_request *req,
799 const char *params,
800 int paramsize,
801 const char *pdata,
802 int datasize,
803 int max_data_bytes)
805 /* As we are using a protocol > LANMAN1 then the max_send
806 variable must have been set in the sessetupX call.
807 This takes precedence over the max_xmit field in the
808 global struct. These different max_xmit variables should
809 be merged as this is now too confusing */
811 int data_to_send = datasize;
812 int params_to_send = paramsize;
813 int useable_space;
814 const char *pp = params;
815 const char *pd = pdata;
816 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
817 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
818 int data_alignment_offset = 0;
819 bool overflow = False;
820 struct smbd_server_connection *sconn = req->sconn;
821 int max_send = sconn->smb1.sessions.max_send;
823 /* Modify the data_to_send and datasize and set the error if
824 we're trying to send more than max_data_bytes. We still send
825 the part of the packet(s) that fit. Strange, but needed
826 for OS/2. */
828 if (max_data_bytes > 0 && datasize > max_data_bytes) {
829 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
830 max_data_bytes, datasize ));
831 datasize = data_to_send = max_data_bytes;
832 overflow = True;
835 /* If there genuinely are no parameters or data to send just send the empty packet */
837 if(params_to_send == 0 && data_to_send == 0) {
838 reply_outbuf(req, 10, 0);
839 show_msg((char *)req->outbuf);
840 if (!srv_send_smb(sconn,
841 (char *)req->outbuf,
842 true, req->seqnum+1,
843 IS_CONN_ENCRYPTED(conn),
844 &req->pcd)) {
845 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
847 TALLOC_FREE(req->outbuf);
848 return;
851 /* When sending params and data ensure that both are nicely aligned */
852 /* Only do this alignment when there is also data to send - else
853 can cause NT redirector problems. */
855 if (((params_to_send % 4) != 0) && (data_to_send != 0))
856 data_alignment_offset = 4 - (params_to_send % 4);
858 /* Space is bufsize minus Netbios over TCP header minus SMB header */
859 /* The alignment_offset is to align the param bytes on an even byte
860 boundary. NT 4.0 Beta needs this to work correctly. */
862 useable_space = max_send - (smb_size
863 + 2 * 10 /* wct */
864 + alignment_offset
865 + data_alignment_offset);
867 if (useable_space < 0) {
868 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
869 "= %d!!!", useable_space));
870 exit_server_cleanly("send_trans2_replies: Not enough space");
873 while (params_to_send || data_to_send) {
874 /* Calculate whether we will totally or partially fill this packet */
876 total_sent_thistime = params_to_send + data_to_send;
878 /* We can never send more than useable_space */
880 * Note that 'useable_space' does not include the alignment offsets,
881 * but we must include the alignment offsets in the calculation of
882 * the length of the data we send over the wire, as the alignment offsets
883 * are sent here. Fix from Marc_Jacobsen@hp.com.
886 total_sent_thistime = MIN(total_sent_thistime, useable_space);
888 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
889 + data_alignment_offset);
892 * We might have SMBtrans2s in req which was transferred to
893 * the outbuf, fix that.
895 SCVAL(req->outbuf, smb_com, SMBtrans2);
897 /* Set total params and data to be sent */
898 SSVAL(req->outbuf,smb_tprcnt,paramsize);
899 SSVAL(req->outbuf,smb_tdrcnt,datasize);
901 /* Calculate how many parameters and data we can fit into
902 * this packet. Parameters get precedence
905 params_sent_thistime = MIN(params_to_send,useable_space);
906 data_sent_thistime = useable_space - params_sent_thistime;
907 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
909 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
911 /* smb_proff is the offset from the start of the SMB header to the
912 parameter bytes, however the first 4 bytes of outbuf are
913 the Netbios over TCP header. Thus use smb_base() to subtract
914 them from the calculation */
916 SSVAL(req->outbuf,smb_proff,
917 ((smb_buf(req->outbuf)+alignment_offset)
918 - smb_base(req->outbuf)));
920 if(params_sent_thistime == 0)
921 SSVAL(req->outbuf,smb_prdisp,0);
922 else
923 /* Absolute displacement of param bytes sent in this packet */
924 SSVAL(req->outbuf,smb_prdisp,pp - params);
926 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
927 if(data_sent_thistime == 0) {
928 SSVAL(req->outbuf,smb_droff,0);
929 SSVAL(req->outbuf,smb_drdisp, 0);
930 } else {
931 /* The offset of the data bytes is the offset of the
932 parameter bytes plus the number of parameters being sent this time */
933 SSVAL(req->outbuf, smb_droff,
934 ((smb_buf(req->outbuf)+alignment_offset)
935 - smb_base(req->outbuf))
936 + params_sent_thistime + data_alignment_offset);
937 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
940 /* Initialize the padding for alignment */
942 if (alignment_offset != 0) {
943 memset(smb_buf(req->outbuf), 0, alignment_offset);
946 /* Copy the param bytes into the packet */
948 if(params_sent_thistime) {
949 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
950 params_sent_thistime);
953 /* Copy in the data bytes */
954 if(data_sent_thistime) {
955 if (data_alignment_offset != 0) {
956 memset((smb_buf(req->outbuf)+alignment_offset+
957 params_sent_thistime), 0,
958 data_alignment_offset);
960 memcpy(smb_buf(req->outbuf)+alignment_offset
961 +params_sent_thistime+data_alignment_offset,
962 pd,data_sent_thistime);
965 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
966 params_sent_thistime, data_sent_thistime, useable_space));
967 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
968 params_to_send, data_to_send, paramsize, datasize));
970 if (overflow) {
971 error_packet_set((char *)req->outbuf,
972 ERRDOS,ERRbufferoverflow,
973 STATUS_BUFFER_OVERFLOW,
974 __LINE__,__FILE__);
977 /* Send the packet */
978 show_msg((char *)req->outbuf);
979 if (!srv_send_smb(sconn,
980 (char *)req->outbuf,
981 true, req->seqnum+1,
982 IS_CONN_ENCRYPTED(conn),
983 &req->pcd))
984 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
986 TALLOC_FREE(req->outbuf);
988 pp += params_sent_thistime;
989 pd += data_sent_thistime;
991 params_to_send -= params_sent_thistime;
992 data_to_send -= data_sent_thistime;
994 /* Sanity check */
995 if(params_to_send < 0 || data_to_send < 0) {
996 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
997 params_to_send, data_to_send));
998 return;
1002 return;
1005 /****************************************************************************
1006 Reply to a TRANSACT2_OPEN.
1007 ****************************************************************************/
1009 static void call_trans2open(connection_struct *conn,
1010 struct smb_request *req,
1011 char **pparams, int total_params,
1012 char **ppdata, int total_data,
1013 unsigned int max_data_bytes)
1015 struct smb_filename *smb_fname = NULL;
1016 char *params = *pparams;
1017 char *pdata = *ppdata;
1018 int deny_mode;
1019 int32 open_attr;
1020 bool oplock_request;
1021 #if 0
1022 bool return_additional_info;
1023 int16 open_sattr;
1024 time_t open_time;
1025 #endif
1026 int open_ofun;
1027 uint32 open_size;
1028 char *pname;
1029 char *fname = NULL;
1030 SMB_OFF_T size=0;
1031 int fattr=0,mtime=0;
1032 SMB_INO_T inode = 0;
1033 int smb_action = 0;
1034 files_struct *fsp;
1035 struct ea_list *ea_list = NULL;
1036 uint16 flags = 0;
1037 NTSTATUS status;
1038 uint32 access_mask;
1039 uint32 share_mode;
1040 uint32 create_disposition;
1041 uint32 create_options = 0;
1042 uint32_t private_flags = 0;
1043 TALLOC_CTX *ctx = talloc_tos();
1046 * Ensure we have enough parameters to perform the operation.
1049 if (total_params < 29) {
1050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1051 goto out;
1054 flags = SVAL(params, 0);
1055 deny_mode = SVAL(params, 2);
1056 open_attr = SVAL(params,6);
1057 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1058 if (oplock_request) {
1059 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1062 #if 0
1063 return_additional_info = BITSETW(params,0);
1064 open_sattr = SVAL(params, 4);
1065 open_time = make_unix_date3(params+8);
1066 #endif
1067 open_ofun = SVAL(params,12);
1068 open_size = IVAL(params,14);
1069 pname = &params[28];
1071 if (IS_IPC(conn)) {
1072 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1073 goto out;
1076 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1077 total_params - 28, STR_TERMINATE,
1078 &status);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 reply_nterror(req, status);
1081 goto out;
1084 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1085 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1086 (unsigned int)open_ofun, open_size));
1088 status = filename_convert(ctx,
1089 conn,
1090 req->flags2 & FLAGS2_DFS_PATHNAMES,
1091 fname,
1093 NULL,
1094 &smb_fname);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1097 reply_botherror(req,
1098 NT_STATUS_PATH_NOT_COVERED,
1099 ERRSRV, ERRbadpath);
1100 goto out;
1102 reply_nterror(req, status);
1103 goto out;
1106 if (open_ofun == 0) {
1107 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1108 goto out;
1111 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1112 open_ofun,
1113 &access_mask, &share_mode,
1114 &create_disposition,
1115 &create_options,
1116 &private_flags)) {
1117 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1118 goto out;
1121 /* Any data in this call is an EA list. */
1122 if (total_data && (total_data != 4)) {
1123 if (total_data < 10) {
1124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1125 goto out;
1128 if (IVAL(pdata,0) > total_data) {
1129 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1130 IVAL(pdata,0), (unsigned int)total_data));
1131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1132 goto out;
1135 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1136 total_data - 4);
1137 if (!ea_list) {
1138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1139 goto out;
1142 if (!lp_ea_support(SNUM(conn))) {
1143 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1144 goto out;
1148 status = SMB_VFS_CREATE_FILE(
1149 conn, /* conn */
1150 req, /* req */
1151 0, /* root_dir_fid */
1152 smb_fname, /* fname */
1153 access_mask, /* access_mask */
1154 share_mode, /* share_access */
1155 create_disposition, /* create_disposition*/
1156 create_options, /* create_options */
1157 open_attr, /* file_attributes */
1158 oplock_request, /* oplock_request */
1159 open_size, /* allocation_size */
1160 private_flags,
1161 NULL, /* sd */
1162 ea_list, /* ea_list */
1163 &fsp, /* result */
1164 &smb_action); /* psbuf */
1166 if (!NT_STATUS_IS_OK(status)) {
1167 if (open_was_deferred(req->sconn, req->mid)) {
1168 /* We have re-scheduled this call. */
1169 goto out;
1171 reply_openerror(req, status);
1172 goto out;
1175 size = get_file_size_stat(&smb_fname->st);
1176 fattr = dos_mode(conn, smb_fname);
1177 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1178 inode = smb_fname->st.st_ex_ino;
1179 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1180 close_file(req, fsp, ERROR_CLOSE);
1181 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1182 goto out;
1185 /* Realloc the size of parameters and data we will return */
1186 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1187 if(*pparams == NULL ) {
1188 reply_nterror(req, NT_STATUS_NO_MEMORY);
1189 goto out;
1191 params = *pparams;
1193 SSVAL(params,0,fsp->fnum);
1194 SSVAL(params,2,fattr);
1195 srv_put_dos_date2(params,4, mtime);
1196 SIVAL(params,8, (uint32)size);
1197 SSVAL(params,12,deny_mode);
1198 SSVAL(params,14,0); /* open_type - file or directory. */
1199 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1201 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1202 smb_action |= EXTENDED_OPLOCK_GRANTED;
1205 SSVAL(params,18,smb_action);
1208 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1210 SIVAL(params,20,inode);
1211 SSVAL(params,24,0); /* Padding. */
1212 if (flags & 8) {
1213 uint32 ea_size = estimate_ea_size(conn, fsp,
1214 fsp->fsp_name->base_name);
1215 SIVAL(params, 26, ea_size);
1216 } else {
1217 SIVAL(params, 26, 0);
1220 /* Send the required number of replies */
1221 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1222 out:
1223 TALLOC_FREE(smb_fname);
1226 /*********************************************************
1227 Routine to check if a given string matches exactly.
1228 as a special case a mask of "." does NOT match. That
1229 is required for correct wildcard semantics
1230 Case can be significant or not.
1231 **********************************************************/
1233 static bool exact_match(bool has_wild,
1234 bool case_sensitive,
1235 const char *str,
1236 const char *mask)
1238 if (mask[0] == '.' && mask[1] == 0) {
1239 return false;
1242 if (has_wild) {
1243 return false;
1246 if (case_sensitive) {
1247 return strcmp(str,mask)==0;
1248 } else {
1249 return strcasecmp_m(str,mask) == 0;
1253 /****************************************************************************
1254 Return the filetype for UNIX extensions.
1255 ****************************************************************************/
1257 static uint32 unix_filetype(mode_t mode)
1259 if(S_ISREG(mode))
1260 return UNIX_TYPE_FILE;
1261 else if(S_ISDIR(mode))
1262 return UNIX_TYPE_DIR;
1263 #ifdef S_ISLNK
1264 else if(S_ISLNK(mode))
1265 return UNIX_TYPE_SYMLINK;
1266 #endif
1267 #ifdef S_ISCHR
1268 else if(S_ISCHR(mode))
1269 return UNIX_TYPE_CHARDEV;
1270 #endif
1271 #ifdef S_ISBLK
1272 else if(S_ISBLK(mode))
1273 return UNIX_TYPE_BLKDEV;
1274 #endif
1275 #ifdef S_ISFIFO
1276 else if(S_ISFIFO(mode))
1277 return UNIX_TYPE_FIFO;
1278 #endif
1279 #ifdef S_ISSOCK
1280 else if(S_ISSOCK(mode))
1281 return UNIX_TYPE_SOCKET;
1282 #endif
1284 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1285 return UNIX_TYPE_UNKNOWN;
1288 /****************************************************************************
1289 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1290 ****************************************************************************/
1292 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1294 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1295 const SMB_STRUCT_STAT *psbuf,
1296 uint32 perms,
1297 enum perm_type ptype,
1298 mode_t *ret_perms)
1300 mode_t ret = 0;
1302 if (perms == SMB_MODE_NO_CHANGE) {
1303 if (!VALID_STAT(*psbuf)) {
1304 return NT_STATUS_INVALID_PARAMETER;
1305 } else {
1306 *ret_perms = psbuf->st_ex_mode;
1307 return NT_STATUS_OK;
1311 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1312 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1313 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1314 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1315 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1316 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1317 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1318 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1319 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1320 #ifdef S_ISVTX
1321 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1322 #endif
1323 #ifdef S_ISGID
1324 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1325 #endif
1326 #ifdef S_ISUID
1327 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1328 #endif
1330 switch (ptype) {
1331 case PERM_NEW_FILE:
1332 /* Apply mode mask */
1333 ret &= lp_create_mask(SNUM(conn));
1334 /* Add in force bits */
1335 ret |= lp_force_create_mode(SNUM(conn));
1336 break;
1337 case PERM_NEW_DIR:
1338 ret &= lp_dir_mask(SNUM(conn));
1339 /* Add in force bits */
1340 ret |= lp_force_dir_mode(SNUM(conn));
1341 break;
1342 case PERM_EXISTING_FILE:
1343 /* Apply mode mask */
1344 ret &= lp_security_mask(SNUM(conn));
1345 /* Add in force bits */
1346 ret |= lp_force_security_mode(SNUM(conn));
1347 break;
1348 case PERM_EXISTING_DIR:
1349 /* Apply mode mask */
1350 ret &= lp_dir_security_mask(SNUM(conn));
1351 /* Add in force bits */
1352 ret |= lp_force_dir_security_mode(SNUM(conn));
1353 break;
1356 *ret_perms = ret;
1357 return NT_STATUS_OK;
1360 /****************************************************************************
1361 Needed to show the msdfs symlinks as directories. Modifies psbuf
1362 to be a directory if it's a msdfs link.
1363 ****************************************************************************/
1365 static bool check_msdfs_link(connection_struct *conn,
1366 const char *pathname,
1367 SMB_STRUCT_STAT *psbuf)
1369 int saved_errno = errno;
1370 if(lp_host_msdfs() &&
1371 lp_msdfs_root(SNUM(conn)) &&
1372 is_msdfs_link(conn, pathname, psbuf)) {
1374 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1375 "as a directory\n",
1376 pathname));
1377 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1378 errno = saved_errno;
1379 return true;
1381 errno = saved_errno;
1382 return false;
1386 /****************************************************************************
1387 Get a level dependent lanman2 dir entry.
1388 ****************************************************************************/
1390 struct smbd_dirptr_lanman2_state {
1391 connection_struct *conn;
1392 uint32_t info_level;
1393 bool check_mangled_names;
1394 bool has_wild;
1395 bool got_exact_match;
1398 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1399 void *private_data,
1400 const char *dname,
1401 const char *mask,
1402 char **_fname)
1404 struct smbd_dirptr_lanman2_state *state =
1405 (struct smbd_dirptr_lanman2_state *)private_data;
1406 bool ok;
1407 char mangled_name[13]; /* mangled 8.3 name. */
1408 bool got_match;
1409 const char *fname;
1411 /* Mangle fname if it's an illegal name. */
1412 if (mangle_must_mangle(dname, state->conn->params)) {
1413 ok = name_to_8_3(dname, mangled_name,
1414 true, state->conn->params);
1415 if (!ok) {
1416 return false;
1418 fname = mangled_name;
1419 } else {
1420 fname = dname;
1423 got_match = exact_match(state->has_wild,
1424 state->conn->case_sensitive,
1425 fname, mask);
1426 state->got_exact_match = got_match;
1427 if (!got_match) {
1428 got_match = mask_match(fname, mask,
1429 state->conn->case_sensitive);
1432 if(!got_match && state->check_mangled_names &&
1433 !mangle_is_8_3(fname, false, state->conn->params)) {
1435 * It turns out that NT matches wildcards against
1436 * both long *and* short names. This may explain some
1437 * of the wildcard wierdness from old DOS clients
1438 * that some people have been seeing.... JRA.
1440 /* Force the mangling into 8.3. */
1441 ok = name_to_8_3(fname, mangled_name,
1442 false, state->conn->params);
1443 if (!ok) {
1444 return false;
1447 got_match = exact_match(state->has_wild,
1448 state->conn->case_sensitive,
1449 mangled_name, mask);
1450 state->got_exact_match = got_match;
1451 if (!got_match) {
1452 got_match = mask_match(mangled_name, mask,
1453 state->conn->case_sensitive);
1457 if (!got_match) {
1458 return false;
1461 *_fname = talloc_strdup(ctx, fname);
1462 if (*_fname == NULL) {
1463 return false;
1466 return true;
1469 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1470 void *private_data,
1471 struct smb_filename *smb_fname,
1472 uint32_t *_mode)
1474 struct smbd_dirptr_lanman2_state *state =
1475 (struct smbd_dirptr_lanman2_state *)private_data;
1476 bool ms_dfs_link = false;
1477 uint32_t mode = 0;
1479 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1480 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1481 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1482 "Couldn't lstat [%s] (%s)\n",
1483 smb_fname_str_dbg(smb_fname),
1484 strerror(errno)));
1485 return false;
1487 } else if (!VALID_STAT(smb_fname->st) &&
1488 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1489 /* Needed to show the msdfs symlinks as
1490 * directories */
1492 ms_dfs_link = check_msdfs_link(state->conn,
1493 smb_fname->base_name,
1494 &smb_fname->st);
1495 if (!ms_dfs_link) {
1496 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1497 "Couldn't stat [%s] (%s)\n",
1498 smb_fname_str_dbg(smb_fname),
1499 strerror(errno)));
1500 return false;
1504 if (ms_dfs_link) {
1505 mode = dos_mode_msdfs(state->conn, smb_fname);
1506 } else {
1507 mode = dos_mode(state->conn, smb_fname);
1510 *_mode = mode;
1511 return true;
1514 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1515 connection_struct *conn,
1516 uint16_t flags2,
1517 uint32_t info_level,
1518 struct ea_list *name_list,
1519 bool check_mangled_names,
1520 bool requires_resume_key,
1521 uint32_t mode,
1522 const char *fname,
1523 const struct smb_filename *smb_fname,
1524 int space_remaining,
1525 uint8_t align,
1526 bool do_pad,
1527 char *base_data,
1528 char **ppdata,
1529 char *end_data,
1530 bool *out_of_space,
1531 uint64_t *last_entry_off)
1533 char *p, *q, *pdata = *ppdata;
1534 uint32_t reskey=0;
1535 uint64_t file_size = 0;
1536 uint64_t allocation_size = 0;
1537 uint64_t file_index = 0;
1538 uint32_t len;
1539 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1540 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1541 time_t c_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);
1577 c_date = convert_timespec_to_time_t(cdate_ts);
1579 /* align the record */
1580 SMB_ASSERT(align >= 1);
1582 off = (int)PTR_DIFF(pdata, base_data);
1583 pad = (off + (align-1)) & ~(align-1);
1584 pad -= off;
1586 if (pad && pad > space_remaining) {
1587 *out_of_space = true;
1588 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1589 "for padding (wanted %u, had %d)\n",
1590 (unsigned int)pad,
1591 space_remaining ));
1592 return false; /* Not finished - just out of space */
1595 off += pad;
1596 /* initialize padding to 0 */
1597 if (pad) {
1598 memset(pdata, 0, pad);
1600 space_remaining -= pad;
1602 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1603 space_remaining ));
1605 pdata += pad;
1606 p = pdata;
1607 last_entry_ptr = p;
1609 pad = 0;
1610 off = 0;
1612 switch (info_level) {
1613 case SMB_FIND_INFO_STANDARD:
1614 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1615 if(requires_resume_key) {
1616 SIVAL(p,0,reskey);
1617 p += 4;
1619 srv_put_dos_date2(p,0,create_date);
1620 srv_put_dos_date2(p,4,adate);
1621 srv_put_dos_date2(p,8,mdate);
1622 SIVAL(p,12,(uint32)file_size);
1623 SIVAL(p,16,(uint32)allocation_size);
1624 SSVAL(p,20,mode);
1625 p += 23;
1626 nameptr = p;
1627 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1628 p += ucs2_align(base_data, p, 0);
1630 len = srvstr_push(base_data, flags2, p,
1631 fname, PTR_DIFF(end_data, p),
1632 STR_TERMINATE);
1633 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1634 if (len > 2) {
1635 SCVAL(nameptr, -1, len - 2);
1636 } else {
1637 SCVAL(nameptr, -1, 0);
1639 } else {
1640 if (len > 1) {
1641 SCVAL(nameptr, -1, len - 1);
1642 } else {
1643 SCVAL(nameptr, -1, 0);
1646 p += len;
1647 break;
1649 case SMB_FIND_EA_SIZE:
1650 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1651 if (requires_resume_key) {
1652 SIVAL(p,0,reskey);
1653 p += 4;
1655 srv_put_dos_date2(p,0,create_date);
1656 srv_put_dos_date2(p,4,adate);
1657 srv_put_dos_date2(p,8,mdate);
1658 SIVAL(p,12,(uint32)file_size);
1659 SIVAL(p,16,(uint32)allocation_size);
1660 SSVAL(p,20,mode);
1662 unsigned int ea_size = estimate_ea_size(conn, NULL,
1663 smb_fname->base_name);
1664 SIVAL(p,22,ea_size); /* Extended attributes */
1666 p += 27;
1667 nameptr = p - 1;
1668 len = srvstr_push(base_data, flags2,
1669 p, fname, PTR_DIFF(end_data, p),
1670 STR_TERMINATE | STR_NOALIGN);
1671 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1672 if (len > 2) {
1673 len -= 2;
1674 } else {
1675 len = 0;
1677 } else {
1678 if (len > 1) {
1679 len -= 1;
1680 } else {
1681 len = 0;
1684 SCVAL(nameptr,0,len);
1685 p += len;
1686 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1687 break;
1689 case SMB_FIND_EA_LIST:
1691 struct ea_list *file_list = NULL;
1692 size_t ea_len = 0;
1694 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1695 if (!name_list) {
1696 return false;
1698 if (requires_resume_key) {
1699 SIVAL(p,0,reskey);
1700 p += 4;
1702 srv_put_dos_date2(p,0,create_date);
1703 srv_put_dos_date2(p,4,adate);
1704 srv_put_dos_date2(p,8,mdate);
1705 SIVAL(p,12,(uint32)file_size);
1706 SIVAL(p,16,(uint32)allocation_size);
1707 SSVAL(p,20,mode);
1708 p += 22; /* p now points to the EA area. */
1710 file_list = get_ea_list_from_file(ctx, conn, NULL,
1711 smb_fname->base_name,
1712 &ea_len);
1713 name_list = ea_list_union(name_list, file_list, &ea_len);
1715 /* We need to determine if this entry will fit in the space available. */
1716 /* Max string size is 255 bytes. */
1717 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1718 *out_of_space = true;
1719 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1720 "(wanted %u, had %d)\n",
1721 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1722 space_remaining ));
1723 return False; /* Not finished - just out of space */
1726 /* Push the ea_data followed by the name. */
1727 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1728 nameptr = p;
1729 len = srvstr_push(base_data, flags2,
1730 p + 1, fname, PTR_DIFF(end_data, p+1),
1731 STR_TERMINATE | STR_NOALIGN);
1732 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1733 if (len > 2) {
1734 len -= 2;
1735 } else {
1736 len = 0;
1738 } else {
1739 if (len > 1) {
1740 len -= 1;
1741 } else {
1742 len = 0;
1745 SCVAL(nameptr,0,len);
1746 p += len + 1;
1747 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1748 break;
1751 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1753 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1754 p += 4;
1755 SIVAL(p,0,reskey); p += 4;
1756 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1760 SOFF_T(p,0,file_size); p += 8;
1761 SOFF_T(p,0,allocation_size); p += 8;
1762 SIVAL(p,0,mode); p += 4;
1763 q = p; p += 4; /* q is placeholder for name length. */
1765 unsigned int ea_size = estimate_ea_size(conn, NULL,
1766 smb_fname->base_name);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p += 4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 char mangled_name[13]; /* mangled 8.3 name. */
1776 if (!name_to_8_3(fname,mangled_name,True,
1777 conn->params)) {
1778 /* Error - mangle failed ! */
1779 memset(mangled_name,'\0',12);
1781 mangled_name[12] = 0;
1782 len = srvstr_push(base_data, flags2,
1783 p+2, mangled_name, 24,
1784 STR_UPPER|STR_UNICODE);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 2 + 24;
1793 len = srvstr_push(base_data, flags2, p,
1794 fname, PTR_DIFF(end_data, p),
1795 STR_TERMINATE_ASCII);
1796 SIVAL(q,0,len);
1797 p += len;
1799 len = PTR_DIFF(p, pdata);
1800 pad = (len + (align-1)) & ~(align-1);
1802 * offset to the next entry, the caller
1803 * will overwrite it for the last entry
1804 * that's why we always include the padding
1806 SIVAL(pdata,0,pad);
1808 * set padding to zero
1810 if (do_pad) {
1811 memset(p, 0, pad - len);
1812 p = pdata + pad;
1813 } else {
1814 p = pdata + len;
1816 break;
1818 case SMB_FIND_FILE_DIRECTORY_INFO:
1819 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1820 p += 4;
1821 SIVAL(p,0,reskey); p += 4;
1822 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1826 SOFF_T(p,0,file_size); p += 8;
1827 SOFF_T(p,0,allocation_size); p += 8;
1828 SIVAL(p,0,mode); p += 4;
1829 len = srvstr_push(base_data, flags2,
1830 p + 4, fname, PTR_DIFF(end_data, p+4),
1831 STR_TERMINATE_ASCII);
1832 SIVAL(p,0,len);
1833 p += 4 + len;
1835 len = PTR_DIFF(p, pdata);
1836 pad = (len + (align-1)) & ~(align-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1842 SIVAL(pdata,0,pad);
1844 * set padding to zero
1846 if (do_pad) {
1847 memset(p, 0, pad - len);
1848 p = pdata + pad;
1849 } else {
1850 p = pdata + len;
1852 break;
1854 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1856 p += 4;
1857 SIVAL(p,0,reskey); p += 4;
1858 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1862 SOFF_T(p,0,file_size); p += 8;
1863 SOFF_T(p,0,allocation_size); p += 8;
1864 SIVAL(p,0,mode); p += 4;
1865 q = p; p += 4; /* q is placeholder for name length. */
1867 unsigned int ea_size = estimate_ea_size(conn, NULL,
1868 smb_fname->base_name);
1869 SIVAL(p,0,ea_size); /* Extended attributes */
1870 p +=4;
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1875 SIVAL(q, 0, len);
1876 p += len;
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1885 SIVAL(pdata,0,pad);
1887 * set padding to zero
1889 if (do_pad) {
1890 memset(p, 0, pad - len);
1891 p = pdata + pad;
1892 } else {
1893 p = pdata + len;
1895 break;
1897 case SMB_FIND_FILE_NAMES_INFO:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1899 p += 4;
1900 SIVAL(p,0,reskey); p += 4;
1901 p += 4;
1902 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1903 acl on a dir (tridge) */
1904 len = srvstr_push(base_data, flags2, p,
1905 fname, PTR_DIFF(end_data, p),
1906 STR_TERMINATE_ASCII);
1907 SIVAL(p, -4, len);
1908 p += len;
1910 len = PTR_DIFF(p, pdata);
1911 pad = (len + (align-1)) & ~(align-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1917 SIVAL(pdata,0,pad);
1919 * set padding to zero
1921 if (do_pad) {
1922 memset(p, 0, pad - len);
1923 p = pdata + pad;
1924 } else {
1925 p = pdata + len;
1927 break;
1929 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1931 p += 4;
1932 SIVAL(p,0,reskey); p += 4;
1933 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1937 SOFF_T(p,0,file_size); p += 8;
1938 SOFF_T(p,0,allocation_size); p += 8;
1939 SIVAL(p,0,mode); p += 4;
1940 q = p; p += 4; /* q is placeholder for name length. */
1942 unsigned int ea_size = estimate_ea_size(conn, NULL,
1943 smb_fname->base_name);
1944 SIVAL(p,0,ea_size); /* Extended attributes */
1945 p +=4;
1947 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1948 SBVAL(p,0,file_index); p += 8;
1949 len = srvstr_push(base_data, flags2, p,
1950 fname, PTR_DIFF(end_data, p),
1951 STR_TERMINATE_ASCII);
1952 SIVAL(q, 0, len);
1953 p += len;
1955 len = PTR_DIFF(p, pdata);
1956 pad = (len + (align-1)) & ~(align-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1962 SIVAL(pdata,0,pad);
1964 * set padding to zero
1966 if (do_pad) {
1967 memset(p, 0, pad - len);
1968 p = pdata + pad;
1969 } else {
1970 p = pdata + len;
1972 break;
1974 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1976 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1977 p += 4;
1978 SIVAL(p,0,reskey); p += 4;
1979 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1982 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1983 SOFF_T(p,0,file_size); p += 8;
1984 SOFF_T(p,0,allocation_size); p += 8;
1985 SIVAL(p,0,mode); p += 4;
1986 q = p; p += 4; /* q is placeholder for name length */
1988 unsigned int ea_size = estimate_ea_size(conn, NULL,
1989 smb_fname->base_name);
1990 SIVAL(p,0,ea_size); /* Extended attributes */
1991 p +=4;
1993 /* Clear the short name buffer. This is
1994 * IMPORTANT as not doing so will trigger
1995 * a Win2k client bug. JRA.
1997 if (!was_8_3 && check_mangled_names) {
1998 char mangled_name[13]; /* mangled 8.3 name. */
1999 if (!name_to_8_3(fname,mangled_name,True,
2000 conn->params)) {
2001 /* Error - mangle failed ! */
2002 memset(mangled_name,'\0',12);
2004 mangled_name[12] = 0;
2005 len = srvstr_push(base_data, flags2,
2006 p+2, mangled_name, 24,
2007 STR_UPPER|STR_UNICODE);
2008 SSVAL(p, 0, len);
2009 if (len < 24) {
2010 memset(p + 2 + len,'\0',24 - len);
2012 SSVAL(p, 0, len);
2013 } else {
2014 memset(p,'\0',26);
2016 p += 26;
2017 SSVAL(p,0,0); p += 2; /* Reserved ? */
2018 SBVAL(p,0,file_index); p += 8;
2019 len = srvstr_push(base_data, flags2, p,
2020 fname, PTR_DIFF(end_data, p),
2021 STR_TERMINATE_ASCII);
2022 SIVAL(q,0,len);
2023 p += len;
2025 len = PTR_DIFF(p, pdata);
2026 pad = (len + (align-1)) & ~(align-1);
2028 * offset to the next entry, the caller
2029 * will overwrite it for the last entry
2030 * that's why we always include the padding
2032 SIVAL(pdata,0,pad);
2034 * set padding to zero
2036 if (do_pad) {
2037 memset(p, 0, pad - len);
2038 p = pdata + pad;
2039 } else {
2040 p = pdata + len;
2042 break;
2044 /* CIFS UNIX Extension. */
2046 case SMB_FIND_FILE_UNIX:
2047 case SMB_FIND_FILE_UNIX_INFO2:
2048 p+= 4;
2049 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2051 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2053 if (info_level == SMB_FIND_FILE_UNIX) {
2054 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2055 p = store_file_unix_basic(conn, p,
2056 NULL, &smb_fname->st);
2057 len = srvstr_push(base_data, flags2, p,
2058 fname, PTR_DIFF(end_data, p),
2059 STR_TERMINATE);
2060 } else {
2061 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2062 p = store_file_unix_basic_info2(conn, p,
2063 NULL, &smb_fname->st);
2064 nameptr = p;
2065 p += 4;
2066 len = srvstr_push(base_data, flags2, p, fname,
2067 PTR_DIFF(end_data, p), 0);
2068 SIVAL(nameptr, 0, len);
2071 p += len;
2073 len = PTR_DIFF(p, pdata);
2074 pad = (len + (align-1)) & ~(align-1);
2076 * offset to the next entry, the caller
2077 * will overwrite it for the last entry
2078 * that's why we always include the padding
2080 SIVAL(pdata,0,pad);
2082 * set padding to zero
2084 if (do_pad) {
2085 memset(p, 0, pad - len);
2086 p = pdata + pad;
2087 } else {
2088 p = pdata + len;
2090 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2092 break;
2094 default:
2095 return false;
2098 if (PTR_DIFF(p,pdata) > space_remaining) {
2099 *out_of_space = true;
2100 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2101 "(wanted %u, had %d)\n",
2102 (unsigned int)PTR_DIFF(p,pdata),
2103 space_remaining ));
2104 return false; /* Not finished - just out of space */
2107 /* Setup the last entry pointer, as an offset from base_data */
2108 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2109 /* Advance the data pointer to the next slot */
2110 *ppdata = p;
2112 return true;
2115 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2116 connection_struct *conn,
2117 struct dptr_struct *dirptr,
2118 uint16 flags2,
2119 const char *path_mask,
2120 uint32 dirtype,
2121 int info_level,
2122 int requires_resume_key,
2123 bool dont_descend,
2124 bool ask_sharemode,
2125 uint8_t align,
2126 bool do_pad,
2127 char **ppdata,
2128 char *base_data,
2129 char *end_data,
2130 int space_remaining,
2131 bool *out_of_space,
2132 bool *got_exact_match,
2133 int *_last_entry_off,
2134 struct ea_list *name_list)
2136 const char *p;
2137 const char *mask = NULL;
2138 long prev_dirpos = 0;
2139 uint32_t mode = 0;
2140 char *fname = NULL;
2141 struct smb_filename *smb_fname = NULL;
2142 struct smbd_dirptr_lanman2_state state;
2143 bool ok;
2144 uint64_t last_entry_off = 0;
2146 ZERO_STRUCT(state);
2147 state.conn = conn;
2148 state.info_level = info_level;
2149 state.check_mangled_names = lp_manglednames(conn->params);
2150 state.has_wild = dptr_has_wild(dirptr);
2151 state.got_exact_match = false;
2153 *out_of_space = false;
2154 *got_exact_match = false;
2156 p = strrchr_m(path_mask,'/');
2157 if(p != NULL) {
2158 if(p[1] == '\0') {
2159 mask = "*.*";
2160 } else {
2161 mask = p+1;
2163 } else {
2164 mask = path_mask;
2167 ok = smbd_dirptr_get_entry(ctx,
2168 dirptr,
2169 mask,
2170 dirtype,
2171 dont_descend,
2172 ask_sharemode,
2173 smbd_dirptr_lanman2_match_fn,
2174 smbd_dirptr_lanman2_mode_fn,
2175 &state,
2176 &fname,
2177 &smb_fname,
2178 &mode,
2179 &prev_dirpos);
2180 if (!ok) {
2181 return false;
2184 *got_exact_match = state.got_exact_match;
2186 ok = smbd_marshall_dir_entry(ctx,
2187 conn,
2188 flags2,
2189 info_level,
2190 name_list,
2191 state.check_mangled_names,
2192 requires_resume_key,
2193 mode,
2194 fname,
2195 smb_fname,
2196 space_remaining,
2197 align,
2198 do_pad,
2199 base_data,
2200 ppdata,
2201 end_data,
2202 out_of_space,
2203 &last_entry_off);
2204 TALLOC_FREE(fname);
2205 TALLOC_FREE(smb_fname);
2206 if (*out_of_space) {
2207 dptr_SeekDir(dirptr, prev_dirpos);
2208 return false;
2210 if (!ok) {
2211 return false;
2214 *_last_entry_off = last_entry_off;
2215 return true;
2218 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2219 connection_struct *conn,
2220 struct dptr_struct *dirptr,
2221 uint16 flags2,
2222 const char *path_mask,
2223 uint32 dirtype,
2224 int info_level,
2225 bool requires_resume_key,
2226 bool dont_descend,
2227 bool ask_sharemode,
2228 char **ppdata,
2229 char *base_data,
2230 char *end_data,
2231 int space_remaining,
2232 bool *out_of_space,
2233 bool *got_exact_match,
2234 int *last_entry_off,
2235 struct ea_list *name_list)
2237 uint8_t align = 4;
2238 const bool do_pad = true;
2240 if (info_level >= 1 && info_level <= 3) {
2241 /* No alignment on earlier info levels. */
2242 align = 1;
2245 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2246 path_mask, dirtype, info_level,
2247 requires_resume_key, dont_descend, ask_sharemode,
2248 align, do_pad,
2249 ppdata, base_data, end_data,
2250 space_remaining,
2251 out_of_space, got_exact_match,
2252 last_entry_off, name_list);
2255 /****************************************************************************
2256 Reply to a TRANS2_FINDFIRST.
2257 ****************************************************************************/
2259 static void call_trans2findfirst(connection_struct *conn,
2260 struct smb_request *req,
2261 char **pparams, int total_params,
2262 char **ppdata, int total_data,
2263 unsigned int max_data_bytes)
2265 /* We must be careful here that we don't return more than the
2266 allowed number of data bytes. If this means returning fewer than
2267 maxentries then so be it. We assume that the redirector has
2268 enough room for the fixed number of parameter bytes it has
2269 requested. */
2270 struct smb_filename *smb_dname = NULL;
2271 char *params = *pparams;
2272 char *pdata = *ppdata;
2273 char *data_end;
2274 uint32 dirtype;
2275 int maxentries;
2276 uint16 findfirst_flags;
2277 bool close_after_first;
2278 bool close_if_end;
2279 bool requires_resume_key;
2280 int info_level;
2281 char *directory = NULL;
2282 char *mask = NULL;
2283 char *p;
2284 int last_entry_off=0;
2285 int dptr_num = -1;
2286 int numentries = 0;
2287 int i;
2288 bool finished = False;
2289 bool dont_descend = False;
2290 bool out_of_space = False;
2291 int space_remaining;
2292 bool mask_contains_wcard = False;
2293 struct ea_list *ea_list = NULL;
2294 NTSTATUS ntstatus = NT_STATUS_OK;
2295 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2296 TALLOC_CTX *ctx = talloc_tos();
2297 struct dptr_struct *dirptr = NULL;
2298 struct smbd_server_connection *sconn = req->sconn;
2299 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
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 info_level = SVAL(params,6);
2314 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2315 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2316 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2317 info_level, max_data_bytes));
2319 if (!maxentries) {
2320 /* W2K3 seems to treat zero as 1. */
2321 maxentries = 1;
2324 switch (info_level) {
2325 case SMB_FIND_INFO_STANDARD:
2326 case SMB_FIND_EA_SIZE:
2327 case SMB_FIND_EA_LIST:
2328 case SMB_FIND_FILE_DIRECTORY_INFO:
2329 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2330 case SMB_FIND_FILE_NAMES_INFO:
2331 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2332 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2333 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2334 break;
2335 case SMB_FIND_FILE_UNIX:
2336 case SMB_FIND_FILE_UNIX_INFO2:
2337 /* Always use filesystem for UNIX mtime query. */
2338 ask_sharemode = false;
2339 if (!lp_unix_extensions()) {
2340 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2341 goto out;
2343 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2344 break;
2345 default:
2346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2347 goto out;
2350 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2351 params+12, total_params - 12,
2352 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2353 if (!NT_STATUS_IS_OK(ntstatus)) {
2354 reply_nterror(req, ntstatus);
2355 goto out;
2358 ntstatus = filename_convert(ctx, conn,
2359 req->flags2 & FLAGS2_DFS_PATHNAMES,
2360 directory,
2361 ucf_flags,
2362 &mask_contains_wcard,
2363 &smb_dname);
2364 if (!NT_STATUS_IS_OK(ntstatus)) {
2365 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2366 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2367 ERRSRV, ERRbadpath);
2368 goto out;
2370 reply_nterror(req, ntstatus);
2371 goto out;
2374 mask = smb_dname->original_lcomp;
2376 directory = smb_dname->base_name;
2378 p = strrchr_m(directory,'/');
2379 if(p == NULL) {
2380 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2381 if((directory[0] == '.') && (directory[1] == '\0')) {
2382 mask = talloc_strdup(ctx,"*");
2383 if (!mask) {
2384 reply_nterror(req, NT_STATUS_NO_MEMORY);
2385 goto out;
2387 mask_contains_wcard = True;
2389 } else {
2390 *p = 0;
2393 if (p == NULL || p == directory) {
2394 /* Ensure we don't have a directory name of "". */
2395 directory = talloc_strdup(talloc_tos(), ".");
2396 if (!directory) {
2397 reply_nterror(req, NT_STATUS_NO_MEMORY);
2398 goto out;
2402 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2404 if (info_level == SMB_FIND_EA_LIST) {
2405 uint32 ea_size;
2407 if (total_data < 4) {
2408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2409 goto out;
2412 ea_size = IVAL(pdata,0);
2413 if (ea_size != total_data) {
2414 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2415 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2417 goto out;
2420 if (!lp_ea_support(SNUM(conn))) {
2421 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2422 goto out;
2425 /* Pull out the list of names. */
2426 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2427 if (!ea_list) {
2428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2429 goto out;
2433 *ppdata = (char *)SMB_REALLOC(
2434 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2435 if(*ppdata == NULL ) {
2436 reply_nterror(req, NT_STATUS_NO_MEMORY);
2437 goto out;
2439 pdata = *ppdata;
2440 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2442 /* Realloc the params space */
2443 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2444 if (*pparams == NULL) {
2445 reply_nterror(req, NT_STATUS_NO_MEMORY);
2446 goto out;
2448 params = *pparams;
2450 /* Save the wildcard match and attribs we are using on this directory -
2451 needed as lanman2 assumes these are being saved between calls */
2453 ntstatus = dptr_create(conn,
2454 NULL, /* fsp */
2455 directory,
2456 False,
2457 True,
2458 req->smbpid,
2459 mask,
2460 mask_contains_wcard,
2461 dirtype,
2462 &dirptr);
2464 if (!NT_STATUS_IS_OK(ntstatus)) {
2465 reply_nterror(req, ntstatus);
2466 goto out;
2469 dptr_num = dptr_dnum(dirptr);
2470 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2472 /* Initialize per TRANS2_FIND_FIRST operation data */
2473 dptr_init_search_op(dirptr);
2475 /* We don't need to check for VOL here as this is returned by
2476 a different TRANS2 call. */
2478 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2479 directory,lp_dontdescend(SNUM(conn))));
2480 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2481 dont_descend = True;
2483 p = pdata;
2484 space_remaining = max_data_bytes;
2485 out_of_space = False;
2487 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2488 bool got_exact_match = False;
2490 /* this is a heuristic to avoid seeking the dirptr except when
2491 absolutely necessary. It allows for a filename of about 40 chars */
2492 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2493 out_of_space = True;
2494 finished = False;
2495 } else {
2496 finished = !get_lanman2_dir_entry(ctx,
2497 conn,
2498 dirptr,
2499 req->flags2,
2500 mask,dirtype,info_level,
2501 requires_resume_key,dont_descend,
2502 ask_sharemode,
2503 &p,pdata,data_end,
2504 space_remaining, &out_of_space,
2505 &got_exact_match,
2506 &last_entry_off, ea_list);
2509 if (finished && out_of_space)
2510 finished = False;
2512 if (!finished && !out_of_space)
2513 numentries++;
2516 * As an optimisation if we know we aren't looking
2517 * for a wildcard name (ie. the name matches the wildcard exactly)
2518 * then we can finish on any (first) match.
2519 * This speeds up large directory searches. JRA.
2522 if(got_exact_match)
2523 finished = True;
2525 /* Ensure space_remaining never goes -ve. */
2526 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2527 space_remaining = 0;
2528 out_of_space = true;
2529 } else {
2530 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2534 /* Check if we can close the dirptr */
2535 if(close_after_first || (finished && close_if_end)) {
2536 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2537 dptr_close(sconn, &dptr_num);
2541 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2542 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2543 * the protocol level is less than NT1. Tested with smbclient. JRA.
2544 * This should fix the OS/2 client bug #2335.
2547 if(numentries == 0) {
2548 dptr_close(sconn, &dptr_num);
2549 if (get_Protocol() < PROTOCOL_NT1) {
2550 reply_force_doserror(req, ERRDOS, ERRnofiles);
2551 goto out;
2552 } else {
2553 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2554 ERRDOS, ERRbadfile);
2555 goto out;
2559 /* At this point pdata points to numentries directory entries. */
2561 /* Set up the return parameter block */
2562 SSVAL(params,0,dptr_num);
2563 SSVAL(params,2,numentries);
2564 SSVAL(params,4,finished);
2565 SSVAL(params,6,0); /* Never an EA error */
2566 SSVAL(params,8,last_entry_off);
2568 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2569 max_data_bytes);
2571 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2572 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2573 if (!directory) {
2574 reply_nterror(req, NT_STATUS_NO_MEMORY);
2578 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2579 smb_fn_name(req->cmd),
2580 mask, directory, dirtype, numentries ) );
2583 * Force a name mangle here to ensure that the
2584 * mask as an 8.3 name is top of the mangled cache.
2585 * The reasons for this are subtle. Don't remove
2586 * this code unless you know what you are doing
2587 * (see PR#13758). JRA.
2590 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2591 char mangled_name[13];
2592 name_to_8_3(mask, mangled_name, True, conn->params);
2594 out:
2595 TALLOC_FREE(smb_dname);
2596 return;
2599 /****************************************************************************
2600 Reply to a TRANS2_FINDNEXT.
2601 ****************************************************************************/
2603 static void call_trans2findnext(connection_struct *conn,
2604 struct smb_request *req,
2605 char **pparams, int total_params,
2606 char **ppdata, int total_data,
2607 unsigned int max_data_bytes)
2609 /* We must be careful here that we don't return more than the
2610 allowed number of data bytes. If this means returning fewer than
2611 maxentries then so be it. We assume that the redirector has
2612 enough room for the fixed number of parameter bytes it has
2613 requested. */
2614 char *params = *pparams;
2615 char *pdata = *ppdata;
2616 char *data_end;
2617 int dptr_num;
2618 int maxentries;
2619 uint16 info_level;
2620 uint32 resume_key;
2621 uint16 findnext_flags;
2622 bool close_after_request;
2623 bool close_if_end;
2624 bool requires_resume_key;
2625 bool continue_bit;
2626 bool mask_contains_wcard = False;
2627 char *resume_name = NULL;
2628 const char *mask = NULL;
2629 const char *directory = NULL;
2630 char *p = NULL;
2631 uint16 dirtype;
2632 int numentries = 0;
2633 int i, last_entry_off=0;
2634 bool finished = False;
2635 bool dont_descend = False;
2636 bool out_of_space = False;
2637 int space_remaining;
2638 struct ea_list *ea_list = NULL;
2639 NTSTATUS ntstatus = NT_STATUS_OK;
2640 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2641 TALLOC_CTX *ctx = talloc_tos();
2642 struct dptr_struct *dirptr;
2643 struct smbd_server_connection *sconn = req->sconn;
2645 if (total_params < 13) {
2646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2647 return;
2650 dptr_num = SVAL(params,0);
2651 maxentries = SVAL(params,2);
2652 info_level = SVAL(params,4);
2653 resume_key = IVAL(params,6);
2654 findnext_flags = SVAL(params,10);
2655 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2656 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2657 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2658 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2660 if (!continue_bit) {
2661 /* We only need resume_name if continue_bit is zero. */
2662 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2663 params+12,
2664 total_params - 12, STR_TERMINATE, &ntstatus,
2665 &mask_contains_wcard);
2666 if (!NT_STATUS_IS_OK(ntstatus)) {
2667 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2668 complain (it thinks we're asking for the directory above the shared
2669 path or an invalid name). Catch this as the resume name is only compared, never used in
2670 a file access. JRA. */
2671 srvstr_pull_talloc(ctx, params, req->flags2,
2672 &resume_name, params+12,
2673 total_params - 12,
2674 STR_TERMINATE);
2676 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2677 reply_nterror(req, ntstatus);
2678 return;
2683 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2684 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2685 resume_key = %d resume name = %s continue=%d level = %d\n",
2686 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2687 requires_resume_key, resume_key,
2688 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2690 if (!maxentries) {
2691 /* W2K3 seems to treat zero as 1. */
2692 maxentries = 1;
2695 switch (info_level) {
2696 case SMB_FIND_INFO_STANDARD:
2697 case SMB_FIND_EA_SIZE:
2698 case SMB_FIND_EA_LIST:
2699 case SMB_FIND_FILE_DIRECTORY_INFO:
2700 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2701 case SMB_FIND_FILE_NAMES_INFO:
2702 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2703 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2704 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2705 break;
2706 case SMB_FIND_FILE_UNIX:
2707 case SMB_FIND_FILE_UNIX_INFO2:
2708 /* Always use filesystem for UNIX mtime query. */
2709 ask_sharemode = false;
2710 if (!lp_unix_extensions()) {
2711 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2712 return;
2714 break;
2715 default:
2716 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2717 return;
2720 if (info_level == SMB_FIND_EA_LIST) {
2721 uint32 ea_size;
2723 if (total_data < 4) {
2724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2725 return;
2728 ea_size = IVAL(pdata,0);
2729 if (ea_size != total_data) {
2730 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2731 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2733 return;
2736 if (!lp_ea_support(SNUM(conn))) {
2737 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2738 return;
2741 /* Pull out the list of names. */
2742 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2743 if (!ea_list) {
2744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2745 return;
2749 *ppdata = (char *)SMB_REALLOC(
2750 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2751 if(*ppdata == NULL) {
2752 reply_nterror(req, NT_STATUS_NO_MEMORY);
2753 return;
2756 pdata = *ppdata;
2757 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2759 /* Realloc the params space */
2760 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2761 if(*pparams == NULL ) {
2762 reply_nterror(req, NT_STATUS_NO_MEMORY);
2763 return;
2766 params = *pparams;
2768 /* Check that the dptr is valid */
2769 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2770 reply_nterror(req, STATUS_NO_MORE_FILES);
2771 return;
2774 directory = dptr_path(sconn, dptr_num);
2776 /* Get the wildcard mask from the dptr */
2777 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2778 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2779 reply_nterror(req, STATUS_NO_MORE_FILES);
2780 return;
2783 mask = p;
2785 /* Get the attr mask from the dptr */
2786 dirtype = dptr_attr(sconn, dptr_num);
2788 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2789 dptr_num, mask, dirtype,
2790 (long)dirptr,
2791 dptr_TellDir(dirptr)));
2793 /* Initialize per TRANS2_FIND_NEXT operation data */
2794 dptr_init_search_op(dirptr);
2796 /* We don't need to check for VOL here as this is returned by
2797 a different TRANS2 call. */
2799 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2800 directory,lp_dontdescend(SNUM(conn))));
2801 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2802 dont_descend = True;
2804 p = pdata;
2805 space_remaining = max_data_bytes;
2806 out_of_space = False;
2809 * Seek to the correct position. We no longer use the resume key but
2810 * depend on the last file name instead.
2813 if(!continue_bit && resume_name && *resume_name) {
2814 SMB_STRUCT_STAT st;
2816 long current_pos = 0;
2818 * Remember, name_to_8_3 is called by
2819 * get_lanman2_dir_entry(), so the resume name
2820 * could be mangled. Ensure we check the unmangled name.
2823 if (mangle_is_mangled(resume_name, conn->params)) {
2824 char *new_resume_name = NULL;
2825 mangle_lookup_name_from_8_3(ctx,
2826 resume_name,
2827 &new_resume_name,
2828 conn->params);
2829 if (new_resume_name) {
2830 resume_name = new_resume_name;
2835 * Fix for NT redirector problem triggered by resume key indexes
2836 * changing between directory scans. We now return a resume key of 0
2837 * and instead look for the filename to continue from (also given
2838 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2839 * findfirst/findnext (as is usual) then the directory pointer
2840 * should already be at the correct place.
2843 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2844 } /* end if resume_name && !continue_bit */
2846 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2847 bool got_exact_match = False;
2849 /* this is a heuristic to avoid seeking the dirptr except when
2850 absolutely necessary. It allows for a filename of about 40 chars */
2851 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2852 out_of_space = True;
2853 finished = False;
2854 } else {
2855 finished = !get_lanman2_dir_entry(ctx,
2856 conn,
2857 dirptr,
2858 req->flags2,
2859 mask,dirtype,info_level,
2860 requires_resume_key,dont_descend,
2861 ask_sharemode,
2862 &p,pdata,data_end,
2863 space_remaining, &out_of_space,
2864 &got_exact_match,
2865 &last_entry_off, ea_list);
2868 if (finished && out_of_space)
2869 finished = False;
2871 if (!finished && !out_of_space)
2872 numentries++;
2875 * As an optimisation if we know we aren't looking
2876 * for a wildcard name (ie. the name matches the wildcard exactly)
2877 * then we can finish on any (first) match.
2878 * This speeds up large directory searches. JRA.
2881 if(got_exact_match)
2882 finished = True;
2884 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2887 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2888 smb_fn_name(req->cmd),
2889 mask, directory, dirtype, numentries ) );
2891 /* Check if we can close the dirptr */
2892 if(close_after_request || (finished && close_if_end)) {
2893 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2894 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2897 /* Set up the return parameter block */
2898 SSVAL(params,0,numentries);
2899 SSVAL(params,2,finished);
2900 SSVAL(params,4,0); /* Never an EA error */
2901 SSVAL(params,6,last_entry_off);
2903 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2904 max_data_bytes);
2906 return;
2909 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2911 E_md4hash(lp_servicename(SNUM(conn)),objid);
2912 return objid;
2915 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2917 SMB_ASSERT(extended_info != NULL);
2919 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2920 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2921 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2922 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2923 #ifdef SAMBA_VERSION_REVISION
2924 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2925 #endif
2926 extended_info->samba_subversion = 0;
2927 #ifdef SAMBA_VERSION_RC_RELEASE
2928 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2929 #else
2930 #ifdef SAMBA_VERSION_PRE_RELEASE
2931 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2932 #endif
2933 #endif
2934 #ifdef SAMBA_VERSION_VENDOR_PATCH
2935 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2936 #endif
2937 extended_info->samba_gitcommitdate = 0;
2938 #ifdef SAMBA_VERSION_COMMIT_TIME
2939 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2940 #endif
2942 memset(extended_info->samba_version_string, 0,
2943 sizeof(extended_info->samba_version_string));
2945 snprintf (extended_info->samba_version_string,
2946 sizeof(extended_info->samba_version_string),
2947 "%s", samba_version_string());
2950 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2951 TALLOC_CTX *mem_ctx,
2952 uint16_t info_level,
2953 uint16_t flags2,
2954 unsigned int max_data_bytes,
2955 char **ppdata,
2956 int *ret_data_len)
2958 char *pdata, *end_data;
2959 int data_len = 0, len;
2960 const char *vname = volume_label(SNUM(conn));
2961 int snum = SNUM(conn);
2962 char *fstype = lp_fstype(SNUM(conn));
2963 uint32 additional_flags = 0;
2964 struct smb_filename smb_fname_dot;
2965 SMB_STRUCT_STAT st;
2967 if (IS_IPC(conn)) {
2968 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2969 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2970 "info level (0x%x) on IPC$.\n",
2971 (unsigned int)info_level));
2972 return NT_STATUS_ACCESS_DENIED;
2976 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2978 ZERO_STRUCT(smb_fname_dot);
2979 smb_fname_dot.base_name = discard_const_p(char, ".");
2981 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2982 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2983 return map_nt_error_from_unix(errno);
2986 st = smb_fname_dot.st;
2988 *ppdata = (char *)SMB_REALLOC(
2989 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2990 if (*ppdata == NULL) {
2991 return NT_STATUS_NO_MEMORY;
2994 pdata = *ppdata;
2995 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2996 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2998 switch (info_level) {
2999 case SMB_INFO_ALLOCATION:
3001 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3002 data_len = 18;
3003 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3004 return map_nt_error_from_unix(errno);
3007 block_size = lp_block_size(snum);
3008 if (bsize < block_size) {
3009 uint64_t factor = block_size/bsize;
3010 bsize = block_size;
3011 dsize /= factor;
3012 dfree /= factor;
3014 if (bsize > block_size) {
3015 uint64_t factor = bsize/block_size;
3016 bsize = block_size;
3017 dsize *= factor;
3018 dfree *= factor;
3020 bytes_per_sector = 512;
3021 sectors_per_unit = bsize/bytes_per_sector;
3023 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3024 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3025 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3027 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3028 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3029 SIVAL(pdata,l1_cUnit,dsize);
3030 SIVAL(pdata,l1_cUnitAvail,dfree);
3031 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3032 break;
3035 case SMB_INFO_VOLUME:
3036 /* Return volume name */
3038 * Add volume serial number - hash of a combination of
3039 * the called hostname and the service name.
3041 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3043 * Win2k3 and previous mess this up by sending a name length
3044 * one byte short. I believe only older clients (OS/2 Win9x) use
3045 * this call so try fixing this by adding a terminating null to
3046 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3048 len = srvstr_push(
3049 pdata, flags2,
3050 pdata+l2_vol_szVolLabel, vname,
3051 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3052 STR_NOALIGN|STR_TERMINATE);
3053 SCVAL(pdata,l2_vol_cch,len);
3054 data_len = l2_vol_szVolLabel + len;
3055 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3056 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3057 len, vname));
3058 break;
3060 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3061 case SMB_FS_ATTRIBUTE_INFORMATION:
3063 additional_flags = 0;
3064 #if defined(HAVE_SYS_QUOTAS)
3065 additional_flags |= FILE_VOLUME_QUOTAS;
3066 #endif
3068 if(lp_nt_acl_support(SNUM(conn))) {
3069 additional_flags |= FILE_PERSISTENT_ACLS;
3072 /* Capabilities are filled in at connection time through STATVFS call */
3073 additional_flags |= conn->fs_capabilities;
3074 additional_flags |= lp_parm_int(conn->params->service,
3075 "share", "fake_fscaps",
3078 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3079 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3080 additional_flags); /* FS ATTRIBUTES */
3082 SIVAL(pdata,4,255); /* Max filename component length */
3083 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3084 and will think we can't do long filenames */
3085 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3086 PTR_DIFF(end_data, pdata+12),
3087 STR_UNICODE);
3088 SIVAL(pdata,8,len);
3089 data_len = 12 + len;
3090 break;
3092 case SMB_QUERY_FS_LABEL_INFO:
3093 case SMB_FS_LABEL_INFORMATION:
3094 len = srvstr_push(pdata, flags2, pdata+4, vname,
3095 PTR_DIFF(end_data, pdata+4), 0);
3096 data_len = 4 + len;
3097 SIVAL(pdata,0,len);
3098 break;
3100 case SMB_QUERY_FS_VOLUME_INFO:
3101 case SMB_FS_VOLUME_INFORMATION:
3104 * Add volume serial number - hash of a combination of
3105 * the called hostname and the service name.
3107 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3108 (str_checksum(get_local_machine_name())<<16));
3110 /* Max label len is 32 characters. */
3111 len = srvstr_push(pdata, flags2, pdata+18, vname,
3112 PTR_DIFF(end_data, pdata+18),
3113 STR_UNICODE);
3114 SIVAL(pdata,12,len);
3115 data_len = 18+len;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3118 (int)strlen(vname),vname, lp_servicename(snum)));
3119 break;
3121 case SMB_QUERY_FS_SIZE_INFO:
3122 case SMB_FS_SIZE_INFORMATION:
3124 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3125 data_len = 24;
3126 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3127 return map_nt_error_from_unix(errno);
3129 block_size = lp_block_size(snum);
3130 if (bsize < block_size) {
3131 uint64_t factor = block_size/bsize;
3132 bsize = block_size;
3133 dsize /= factor;
3134 dfree /= factor;
3136 if (bsize > block_size) {
3137 uint64_t factor = bsize/block_size;
3138 bsize = block_size;
3139 dsize *= factor;
3140 dfree *= factor;
3142 bytes_per_sector = 512;
3143 sectors_per_unit = bsize/bytes_per_sector;
3144 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3145 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3146 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3147 SBIG_UINT(pdata,0,dsize);
3148 SBIG_UINT(pdata,8,dfree);
3149 SIVAL(pdata,16,sectors_per_unit);
3150 SIVAL(pdata,20,bytes_per_sector);
3151 break;
3154 case SMB_FS_FULL_SIZE_INFORMATION:
3156 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3157 data_len = 32;
3158 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3159 return map_nt_error_from_unix(errno);
3161 block_size = lp_block_size(snum);
3162 if (bsize < block_size) {
3163 uint64_t factor = block_size/bsize;
3164 bsize = block_size;
3165 dsize /= factor;
3166 dfree /= factor;
3168 if (bsize > block_size) {
3169 uint64_t factor = bsize/block_size;
3170 bsize = block_size;
3171 dsize *= factor;
3172 dfree *= factor;
3174 bytes_per_sector = 512;
3175 sectors_per_unit = bsize/bytes_per_sector;
3176 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3177 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3178 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3179 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3180 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3181 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3182 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3183 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3184 break;
3187 case SMB_QUERY_FS_DEVICE_INFO:
3188 case SMB_FS_DEVICE_INFORMATION:
3190 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3192 if (!CAN_WRITE(conn)) {
3193 characteristics |= FILE_READ_ONLY_DEVICE;
3195 data_len = 8;
3196 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3197 SIVAL(pdata,4,characteristics);
3198 break;
3201 #ifdef HAVE_SYS_QUOTAS
3202 case SMB_FS_QUOTA_INFORMATION:
3204 * what we have to send --metze:
3206 * Unknown1: 24 NULL bytes
3207 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3208 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3209 * Quota Flags: 2 byte :
3210 * Unknown3: 6 NULL bytes
3212 * 48 bytes total
3214 * details for Quota Flags:
3216 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3217 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3218 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3219 * 0x0001 Enable Quotas: enable quota for this fs
3223 /* we need to fake up a fsp here,
3224 * because its not send in this call
3226 files_struct fsp;
3227 SMB_NTQUOTA_STRUCT quotas;
3229 ZERO_STRUCT(fsp);
3230 ZERO_STRUCT(quotas);
3232 fsp.conn = conn;
3233 fsp.fnum = -1;
3235 /* access check */
3236 if (get_current_uid(conn) != 0) {
3237 DEBUG(0,("set_user_quota: access_denied "
3238 "service [%s] user [%s]\n",
3239 lp_servicename(SNUM(conn)),
3240 conn->session_info->unix_info->unix_name));
3241 return NT_STATUS_ACCESS_DENIED;
3244 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3245 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3246 return map_nt_error_from_unix(errno);
3249 data_len = 48;
3251 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3252 lp_servicename(SNUM(conn))));
3254 /* Unknown1 24 NULL bytes*/
3255 SBIG_UINT(pdata,0,(uint64_t)0);
3256 SBIG_UINT(pdata,8,(uint64_t)0);
3257 SBIG_UINT(pdata,16,(uint64_t)0);
3259 /* Default Soft Quota 8 bytes */
3260 SBIG_UINT(pdata,24,quotas.softlim);
3262 /* Default Hard Quota 8 bytes */
3263 SBIG_UINT(pdata,32,quotas.hardlim);
3265 /* Quota flag 2 bytes */
3266 SSVAL(pdata,40,quotas.qflags);
3268 /* Unknown3 6 NULL bytes */
3269 SSVAL(pdata,42,0);
3270 SIVAL(pdata,44,0);
3272 break;
3274 #endif /* HAVE_SYS_QUOTAS */
3275 case SMB_FS_OBJECTID_INFORMATION:
3277 unsigned char objid[16];
3278 struct smb_extended_info extended_info;
3279 memcpy(pdata,create_volume_objectid(conn, objid),16);
3280 samba_extended_info_version (&extended_info);
3281 SIVAL(pdata,16,extended_info.samba_magic);
3282 SIVAL(pdata,20,extended_info.samba_version);
3283 SIVAL(pdata,24,extended_info.samba_subversion);
3284 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3285 memcpy(pdata+36,extended_info.samba_version_string,28);
3286 data_len = 64;
3287 break;
3291 * Query the version and capabilities of the CIFS UNIX extensions
3292 * in use.
3295 case SMB_QUERY_CIFS_UNIX_INFO:
3297 bool large_write = lp_min_receive_file_size() &&
3298 !srv_is_signing_active(conn->sconn);
3299 bool large_read = !srv_is_signing_active(conn->sconn);
3300 int encrypt_caps = 0;
3302 if (!lp_unix_extensions()) {
3303 return NT_STATUS_INVALID_LEVEL;
3306 switch (conn->encrypt_level) {
3307 case 0:
3308 encrypt_caps = 0;
3309 break;
3310 case 1:
3311 case Auto:
3312 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3313 break;
3314 case Required:
3315 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3316 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3317 large_write = false;
3318 large_read = false;
3319 break;
3322 data_len = 12;
3323 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3324 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3326 /* We have POSIX ACLs, pathname, encryption,
3327 * large read/write, and locking capability. */
3329 SBIG_UINT(pdata,4,((uint64_t)(
3330 CIFS_UNIX_POSIX_ACLS_CAP|
3331 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3332 CIFS_UNIX_FCNTL_LOCKS_CAP|
3333 CIFS_UNIX_EXTATTR_CAP|
3334 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3335 encrypt_caps|
3336 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3337 (large_write ?
3338 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3339 break;
3342 case SMB_QUERY_POSIX_FS_INFO:
3344 int rc;
3345 vfs_statvfs_struct svfs;
3347 if (!lp_unix_extensions()) {
3348 return NT_STATUS_INVALID_LEVEL;
3351 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3353 if (!rc) {
3354 data_len = 56;
3355 SIVAL(pdata,0,svfs.OptimalTransferSize);
3356 SIVAL(pdata,4,svfs.BlockSize);
3357 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3358 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3359 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3360 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3361 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3362 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3363 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3364 #ifdef EOPNOTSUPP
3365 } else if (rc == EOPNOTSUPP) {
3366 return NT_STATUS_INVALID_LEVEL;
3367 #endif /* EOPNOTSUPP */
3368 } else {
3369 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3370 return NT_STATUS_DOS(ERRSRV, ERRerror);
3372 break;
3375 case SMB_QUERY_POSIX_WHOAMI:
3377 uint32_t flags = 0;
3378 uint32_t sid_bytes;
3379 int i;
3381 if (!lp_unix_extensions()) {
3382 return NT_STATUS_INVALID_LEVEL;
3385 if (max_data_bytes < 40) {
3386 return NT_STATUS_BUFFER_TOO_SMALL;
3389 /* We ARE guest if global_sid_Builtin_Guests is
3390 * in our list of SIDs.
3392 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3393 conn->session_info->security_token)) {
3394 flags |= SMB_WHOAMI_GUEST;
3397 /* We are NOT guest if global_sid_Authenticated_Users
3398 * is in our list of SIDs.
3400 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3401 conn->session_info->security_token)) {
3402 flags &= ~SMB_WHOAMI_GUEST;
3405 /* NOTE: 8 bytes for UID/GID, irrespective of native
3406 * platform size. This matches
3407 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3409 data_len = 4 /* flags */
3410 + 4 /* flag mask */
3411 + 8 /* uid */
3412 + 8 /* gid */
3413 + 4 /* ngroups */
3414 + 4 /* num_sids */
3415 + 4 /* SID bytes */
3416 + 4 /* pad/reserved */
3417 + (conn->session_info->unix_token->ngroups * 8)
3418 /* groups list */
3419 + (conn->session_info->security_token->num_sids *
3420 SID_MAX_SIZE)
3421 /* SID list */;
3423 SIVAL(pdata, 0, flags);
3424 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3425 SBIG_UINT(pdata, 8,
3426 (uint64_t)conn->session_info->unix_token->uid);
3427 SBIG_UINT(pdata, 16,
3428 (uint64_t)conn->session_info->unix_token->gid);
3431 if (data_len >= max_data_bytes) {
3432 /* Potential overflow, skip the GIDs and SIDs. */
3434 SIVAL(pdata, 24, 0); /* num_groups */
3435 SIVAL(pdata, 28, 0); /* num_sids */
3436 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3437 SIVAL(pdata, 36, 0); /* reserved */
3439 data_len = 40;
3440 break;
3443 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3444 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3446 /* We walk the SID list twice, but this call is fairly
3447 * infrequent, and I don't expect that it's performance
3448 * sensitive -- jpeach
3450 for (i = 0, sid_bytes = 0;
3451 i < conn->session_info->security_token->num_sids; ++i) {
3452 sid_bytes += ndr_size_dom_sid(
3453 &conn->session_info->security_token->sids[i],
3457 /* SID list byte count */
3458 SIVAL(pdata, 32, sid_bytes);
3460 /* 4 bytes pad/reserved - must be zero */
3461 SIVAL(pdata, 36, 0);
3462 data_len = 40;
3464 /* GID list */
3465 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3466 SBIG_UINT(pdata, data_len,
3467 (uint64_t)conn->session_info->unix_token->groups[i]);
3468 data_len += 8;
3471 /* SID list */
3472 for (i = 0;
3473 i < conn->session_info->security_token->num_sids; ++i) {
3474 int sid_len = ndr_size_dom_sid(
3475 &conn->session_info->security_token->sids[i],
3478 sid_linearize(pdata + data_len, sid_len,
3479 &conn->session_info->security_token->sids[i]);
3480 data_len += sid_len;
3483 break;
3486 case SMB_MAC_QUERY_FS_INFO:
3488 * Thursby MAC extension... ONLY on NTFS filesystems
3489 * once we do streams then we don't need this
3491 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3492 data_len = 88;
3493 SIVAL(pdata,84,0x100); /* Don't support mac... */
3494 break;
3496 /* drop through */
3497 default:
3498 return NT_STATUS_INVALID_LEVEL;
3501 *ret_data_len = data_len;
3502 return NT_STATUS_OK;
3505 /****************************************************************************
3506 Reply to a TRANS2_QFSINFO (query filesystem info).
3507 ****************************************************************************/
3509 static void call_trans2qfsinfo(connection_struct *conn,
3510 struct smb_request *req,
3511 char **pparams, int total_params,
3512 char **ppdata, int total_data,
3513 unsigned int max_data_bytes)
3515 char *params = *pparams;
3516 uint16_t info_level;
3517 int data_len = 0;
3518 NTSTATUS status;
3520 if (total_params < 2) {
3521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3522 return;
3525 info_level = SVAL(params,0);
3527 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3528 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3529 DEBUG(0,("call_trans2qfsinfo: encryption required "
3530 "and info level 0x%x sent.\n",
3531 (unsigned int)info_level));
3532 exit_server_cleanly("encryption required "
3533 "on connection");
3534 return;
3538 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3540 status = smbd_do_qfsinfo(conn, req,
3541 info_level,
3542 req->flags2,
3543 max_data_bytes,
3544 ppdata, &data_len);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 reply_nterror(req, status);
3547 return;
3550 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3551 max_data_bytes);
3553 DEBUG( 4, ( "%s info_level = %d\n",
3554 smb_fn_name(req->cmd), info_level) );
3556 return;
3559 /****************************************************************************
3560 Reply to a TRANS2_SETFSINFO (set filesystem info).
3561 ****************************************************************************/
3563 static void call_trans2setfsinfo(connection_struct *conn,
3564 struct smb_request *req,
3565 char **pparams, int total_params,
3566 char **ppdata, int total_data,
3567 unsigned int max_data_bytes)
3569 struct smbd_server_connection *sconn = req->sconn;
3570 char *pdata = *ppdata;
3571 char *params = *pparams;
3572 uint16 info_level;
3574 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3576 /* */
3577 if (total_params < 4) {
3578 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3579 total_params));
3580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3581 return;
3584 info_level = SVAL(params,2);
3586 if (IS_IPC(conn)) {
3587 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3588 info_level != SMB_SET_CIFS_UNIX_INFO) {
3589 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3590 "info level (0x%x) on IPC$.\n",
3591 (unsigned int)info_level));
3592 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3593 return;
3597 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3598 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3599 DEBUG(0,("call_trans2setfsinfo: encryption required "
3600 "and info level 0x%x sent.\n",
3601 (unsigned int)info_level));
3602 exit_server_cleanly("encryption required "
3603 "on connection");
3604 return;
3608 switch(info_level) {
3609 case SMB_SET_CIFS_UNIX_INFO:
3610 if (!lp_unix_extensions()) {
3611 reply_nterror(req,
3612 NT_STATUS_INVALID_LEVEL);
3613 return;
3616 /* There should be 12 bytes of capabilities set. */
3617 if (total_data < 8) {
3618 reply_nterror(
3619 req,
3620 NT_STATUS_INVALID_PARAMETER);
3621 return;
3623 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3624 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3625 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3626 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3627 /* Just print these values for now. */
3628 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3629 "major = %u, minor = %u cap_low = 0x%x, "
3630 "cap_high = 0x%xn",
3631 (unsigned int)sconn->
3632 smb1.unix_info.client_major,
3633 (unsigned int)sconn->
3634 smb1.unix_info.client_minor,
3635 (unsigned int)sconn->
3636 smb1.unix_info.client_cap_low,
3637 (unsigned int)sconn->
3638 smb1.unix_info.client_cap_high));
3640 /* Here is where we must switch to posix pathname processing... */
3641 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3642 lp_set_posix_pathnames();
3643 mangle_change_to_posix();
3646 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3647 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3648 /* Client that knows how to do posix locks,
3649 * but not posix open/mkdir operations. Set a
3650 * default type for read/write checks. */
3652 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3655 break;
3657 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3659 NTSTATUS status;
3660 size_t param_len = 0;
3661 size_t data_len = total_data;
3663 if (!lp_unix_extensions()) {
3664 reply_nterror(
3665 req,
3666 NT_STATUS_INVALID_LEVEL);
3667 return;
3670 if (lp_smb_encrypt(SNUM(conn)) == false) {
3671 reply_nterror(
3672 req,
3673 NT_STATUS_NOT_SUPPORTED);
3674 return;
3677 if (req->sconn->smb1.echo_handler.trusted_fde) {
3678 DEBUG( 2,("call_trans2setfsinfo: "
3679 "request transport encryption disabled"
3680 "with 'fork echo handler = yes'\n"));
3681 reply_nterror(
3682 req,
3683 NT_STATUS_NOT_SUPPORTED);
3684 return;
3687 DEBUG( 4,("call_trans2setfsinfo: "
3688 "request transport encryption.\n"));
3690 status = srv_request_encryption_setup(conn,
3691 (unsigned char **)ppdata,
3692 &data_len,
3693 (unsigned char **)pparams,
3694 &param_len);
3696 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3697 !NT_STATUS_IS_OK(status)) {
3698 reply_nterror(req, status);
3699 return;
3702 send_trans2_replies(conn, req,
3703 *pparams,
3704 param_len,
3705 *ppdata,
3706 data_len,
3707 max_data_bytes);
3709 if (NT_STATUS_IS_OK(status)) {
3710 /* Server-side transport
3711 * encryption is now *on*. */
3712 status = srv_encryption_start(conn);
3713 if (!NT_STATUS_IS_OK(status)) {
3714 char *reason = talloc_asprintf(talloc_tos(),
3715 "Failure in setting "
3716 "up encrypted transport: %s",
3717 nt_errstr(status));
3718 exit_server_cleanly(reason);
3721 return;
3724 case SMB_FS_QUOTA_INFORMATION:
3726 files_struct *fsp = NULL;
3727 SMB_NTQUOTA_STRUCT quotas;
3729 ZERO_STRUCT(quotas);
3731 /* access check */
3732 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3733 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3734 lp_servicename(SNUM(conn)),
3735 conn->session_info->unix_info->unix_name));
3736 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3737 return;
3740 /* note: normaly there're 48 bytes,
3741 * but we didn't use the last 6 bytes for now
3742 * --metze
3744 fsp = file_fsp(req, SVAL(params,0));
3746 if (!check_fsp_ntquota_handle(conn, req,
3747 fsp)) {
3748 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3749 reply_nterror(
3750 req, NT_STATUS_INVALID_HANDLE);
3751 return;
3754 if (total_data < 42) {
3755 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3756 total_data));
3757 reply_nterror(
3758 req,
3759 NT_STATUS_INVALID_PARAMETER);
3760 return;
3763 /* unknown_1 24 NULL bytes in pdata*/
3765 /* the soft quotas 8 bytes (uint64_t)*/
3766 quotas.softlim = BVAL(pdata,24);
3768 /* the hard quotas 8 bytes (uint64_t)*/
3769 quotas.hardlim = BVAL(pdata,32);
3771 /* quota_flags 2 bytes **/
3772 quotas.qflags = SVAL(pdata,40);
3774 /* unknown_2 6 NULL bytes follow*/
3776 /* now set the quotas */
3777 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3778 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3779 reply_nterror(req, map_nt_error_from_unix(errno));
3780 return;
3783 break;
3785 default:
3786 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3787 info_level));
3788 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3789 return;
3790 break;
3794 * sending this reply works fine,
3795 * but I'm not sure it's the same
3796 * like windows do...
3797 * --metze
3799 reply_outbuf(req, 10, 0);
3802 #if defined(HAVE_POSIX_ACLS)
3803 /****************************************************************************
3804 Utility function to count the number of entries in a POSIX acl.
3805 ****************************************************************************/
3807 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3809 unsigned int ace_count = 0;
3810 int entry_id = SMB_ACL_FIRST_ENTRY;
3811 SMB_ACL_ENTRY_T entry;
3813 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3814 /* get_next... */
3815 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3816 entry_id = SMB_ACL_NEXT_ENTRY;
3818 ace_count++;
3820 return ace_count;
3823 /****************************************************************************
3824 Utility function to marshall a POSIX acl into wire format.
3825 ****************************************************************************/
3827 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3829 int entry_id = SMB_ACL_FIRST_ENTRY;
3830 SMB_ACL_ENTRY_T entry;
3832 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3833 SMB_ACL_TAG_T tagtype;
3834 SMB_ACL_PERMSET_T permset;
3835 unsigned char perms = 0;
3836 unsigned int own_grp;
3838 /* get_next... */
3839 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3840 entry_id = SMB_ACL_NEXT_ENTRY;
3843 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3844 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3845 return False;
3848 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3849 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3850 return False;
3853 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3854 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3855 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3857 SCVAL(pdata,1,perms);
3859 switch (tagtype) {
3860 case SMB_ACL_USER_OBJ:
3861 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3862 own_grp = (unsigned int)pst->st_ex_uid;
3863 SIVAL(pdata,2,own_grp);
3864 SIVAL(pdata,6,0);
3865 break;
3866 case SMB_ACL_USER:
3868 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3869 if (!puid) {
3870 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3871 return False;
3873 own_grp = (unsigned int)*puid;
3874 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3875 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3876 SIVAL(pdata,2,own_grp);
3877 SIVAL(pdata,6,0);
3878 break;
3880 case SMB_ACL_GROUP_OBJ:
3881 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3882 own_grp = (unsigned int)pst->st_ex_gid;
3883 SIVAL(pdata,2,own_grp);
3884 SIVAL(pdata,6,0);
3885 break;
3886 case SMB_ACL_GROUP:
3888 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3889 if (!pgid) {
3890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3891 return False;
3893 own_grp = (unsigned int)*pgid;
3894 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3895 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3896 SIVAL(pdata,2,own_grp);
3897 SIVAL(pdata,6,0);
3898 break;
3900 case SMB_ACL_MASK:
3901 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3902 SIVAL(pdata,2,0xFFFFFFFF);
3903 SIVAL(pdata,6,0xFFFFFFFF);
3904 break;
3905 case SMB_ACL_OTHER:
3906 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3907 SIVAL(pdata,2,0xFFFFFFFF);
3908 SIVAL(pdata,6,0xFFFFFFFF);
3909 break;
3910 default:
3911 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3912 return False;
3914 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3917 return True;
3919 #endif
3921 /****************************************************************************
3922 Store the FILE_UNIX_BASIC info.
3923 ****************************************************************************/
3925 static char *store_file_unix_basic(connection_struct *conn,
3926 char *pdata,
3927 files_struct *fsp,
3928 const SMB_STRUCT_STAT *psbuf)
3930 uint64_t file_index = get_FileIndex(conn, psbuf);
3932 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3933 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3935 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3936 pdata += 8;
3938 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3939 pdata += 8;
3941 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3942 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3943 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3944 pdata += 24;
3946 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3947 SIVAL(pdata,4,0);
3948 pdata += 8;
3950 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3951 SIVAL(pdata,4,0);
3952 pdata += 8;
3954 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3955 pdata += 4;
3957 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3958 SIVAL(pdata,4,0);
3959 pdata += 8;
3961 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3962 SIVAL(pdata,4,0);
3963 pdata += 8;
3965 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3966 pdata += 8;
3968 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3969 SIVAL(pdata,4,0);
3970 pdata += 8;
3972 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3973 SIVAL(pdata,4,0);
3974 pdata += 8;
3976 return pdata;
3979 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3980 * the chflags(2) (or equivalent) flags.
3982 * XXX: this really should be behind the VFS interface. To do this, we would
3983 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3984 * Each VFS module could then implement its own mapping as appropriate for the
3985 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3987 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3988 info2_flags_map[] =
3990 #ifdef UF_NODUMP
3991 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3992 #endif
3994 #ifdef UF_IMMUTABLE
3995 { UF_IMMUTABLE, EXT_IMMUTABLE },
3996 #endif
3998 #ifdef UF_APPEND
3999 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4000 #endif
4002 #ifdef UF_HIDDEN
4003 { UF_HIDDEN, EXT_HIDDEN },
4004 #endif
4006 /* Do not remove. We need to guarantee that this array has at least one
4007 * entry to build on HP-UX.
4009 { 0, 0 }
4013 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4014 uint32 *smb_fflags, uint32 *smb_fmask)
4016 int i;
4018 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4019 *smb_fmask |= info2_flags_map[i].smb_fflag;
4020 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4021 *smb_fflags |= info2_flags_map[i].smb_fflag;
4026 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4027 const uint32 smb_fflags,
4028 const uint32 smb_fmask,
4029 int *stat_fflags)
4031 uint32 max_fmask = 0;
4032 int i;
4034 *stat_fflags = psbuf->st_ex_flags;
4036 /* For each flags requested in smb_fmask, check the state of the
4037 * corresponding flag in smb_fflags and set or clear the matching
4038 * stat flag.
4041 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4042 max_fmask |= info2_flags_map[i].smb_fflag;
4043 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4044 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4045 *stat_fflags |= info2_flags_map[i].stat_fflag;
4046 } else {
4047 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4052 /* If smb_fmask is asking to set any bits that are not supported by
4053 * our flag mappings, we should fail.
4055 if ((smb_fmask & max_fmask) != smb_fmask) {
4056 return False;
4059 return True;
4063 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4064 * of file flags and birth (create) time.
4066 static char *store_file_unix_basic_info2(connection_struct *conn,
4067 char *pdata,
4068 files_struct *fsp,
4069 const SMB_STRUCT_STAT *psbuf)
4071 uint32 file_flags = 0;
4072 uint32 flags_mask = 0;
4074 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4076 /* Create (birth) time 64 bit */
4077 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4078 pdata += 8;
4080 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4081 SIVAL(pdata, 0, file_flags); /* flags */
4082 SIVAL(pdata, 4, flags_mask); /* mask */
4083 pdata += 8;
4085 return pdata;
4088 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4089 const struct stream_struct *streams,
4090 char *data,
4091 unsigned int max_data_bytes,
4092 unsigned int *data_size)
4094 unsigned int i;
4095 unsigned int ofs = 0;
4097 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4098 unsigned int next_offset;
4099 size_t namelen;
4100 smb_ucs2_t *namebuf;
4102 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4103 streams[i].name, &namelen) ||
4104 namelen <= 2)
4106 return NT_STATUS_INVALID_PARAMETER;
4110 * name_buf is now null-terminated, we need to marshall as not
4111 * terminated
4114 namelen -= 2;
4116 SIVAL(data, ofs+4, namelen);
4117 SOFF_T(data, ofs+8, streams[i].size);
4118 SOFF_T(data, ofs+16, streams[i].alloc_size);
4119 memcpy(data+ofs+24, namebuf, namelen);
4120 TALLOC_FREE(namebuf);
4122 next_offset = ofs + 24 + namelen;
4124 if (i == num_streams-1) {
4125 SIVAL(data, ofs, 0);
4127 else {
4128 unsigned int align = ndr_align_size(next_offset, 8);
4130 memset(data+next_offset, 0, align);
4131 next_offset += align;
4133 SIVAL(data, ofs, next_offset - ofs);
4134 ofs = next_offset;
4137 ofs = next_offset;
4140 *data_size = ofs;
4142 return NT_STATUS_OK;
4145 /****************************************************************************
4146 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4147 ****************************************************************************/
4149 static void call_trans2qpipeinfo(connection_struct *conn,
4150 struct smb_request *req,
4151 unsigned int tran_call,
4152 char **pparams, int total_params,
4153 char **ppdata, int total_data,
4154 unsigned int max_data_bytes)
4156 char *params = *pparams;
4157 char *pdata = *ppdata;
4158 unsigned int data_size = 0;
4159 unsigned int param_size = 2;
4160 uint16 info_level;
4161 files_struct *fsp;
4163 if (!params) {
4164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4165 return;
4168 if (total_params < 4) {
4169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4170 return;
4173 fsp = file_fsp(req, SVAL(params,0));
4174 if (!fsp_is_np(fsp)) {
4175 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4176 return;
4179 info_level = SVAL(params,2);
4181 *pparams = (char *)SMB_REALLOC(*pparams,2);
4182 if (*pparams == NULL) {
4183 reply_nterror(req, NT_STATUS_NO_MEMORY);
4184 return;
4186 params = *pparams;
4187 SSVAL(params,0,0);
4188 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4189 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4190 if (*ppdata == NULL ) {
4191 reply_nterror(req, NT_STATUS_NO_MEMORY);
4192 return;
4194 pdata = *ppdata;
4196 switch (info_level) {
4197 case SMB_FILE_STANDARD_INFORMATION:
4198 memset(pdata,0,24);
4199 SOFF_T(pdata,0,4096LL);
4200 SIVAL(pdata,16,1);
4201 SIVAL(pdata,20,1);
4202 data_size = 24;
4203 break;
4205 default:
4206 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4207 return;
4210 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4211 max_data_bytes);
4213 return;
4216 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4217 TALLOC_CTX *mem_ctx,
4218 uint16_t info_level,
4219 files_struct *fsp,
4220 struct smb_filename *smb_fname,
4221 bool delete_pending,
4222 struct timespec write_time_ts,
4223 struct ea_list *ea_list,
4224 int lock_data_count,
4225 char *lock_data,
4226 uint16_t flags2,
4227 unsigned int max_data_bytes,
4228 char **ppdata,
4229 unsigned int *pdata_size)
4231 char *pdata = *ppdata;
4232 char *dstart, *dend;
4233 unsigned int data_size;
4234 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4235 time_t create_time, mtime, atime, c_time;
4236 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4237 char *p;
4238 char *base_name;
4239 char *dos_fname;
4240 int mode;
4241 int nlink;
4242 NTSTATUS status;
4243 uint64_t file_size = 0;
4244 uint64_t pos = 0;
4245 uint64_t allocation_size = 0;
4246 uint64_t file_index = 0;
4247 uint32_t access_mask = 0;
4249 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4250 return NT_STATUS_INVALID_LEVEL;
4253 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4254 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4255 info_level, max_data_bytes));
4257 mode = dos_mode(conn, smb_fname);
4258 nlink = psbuf->st_ex_nlink;
4260 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4261 nlink = 1;
4264 if ((nlink > 0) && delete_pending) {
4265 nlink -= 1;
4268 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4269 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4270 if (*ppdata == NULL) {
4271 return NT_STATUS_NO_MEMORY;
4273 pdata = *ppdata;
4274 dstart = pdata;
4275 dend = dstart + data_size - 1;
4277 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4278 update_stat_ex_mtime(psbuf, write_time_ts);
4281 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4282 mtime_ts = psbuf->st_ex_mtime;
4283 atime_ts = psbuf->st_ex_atime;
4284 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4286 if (lp_dos_filetime_resolution(SNUM(conn))) {
4287 dos_filetime_timespec(&create_time_ts);
4288 dos_filetime_timespec(&mtime_ts);
4289 dos_filetime_timespec(&atime_ts);
4290 dos_filetime_timespec(&ctime_ts);
4293 create_time = convert_timespec_to_time_t(create_time_ts);
4294 mtime = convert_timespec_to_time_t(mtime_ts);
4295 atime = convert_timespec_to_time_t(atime_ts);
4296 c_time = convert_timespec_to_time_t(ctime_ts);
4298 p = strrchr_m(smb_fname->base_name,'/');
4299 if (!p)
4300 base_name = smb_fname->base_name;
4301 else
4302 base_name = p+1;
4304 /* NT expects the name to be in an exact form of the *full*
4305 filename. See the trans2 torture test */
4306 if (ISDOT(base_name)) {
4307 dos_fname = talloc_strdup(mem_ctx, "\\");
4308 if (!dos_fname) {
4309 return NT_STATUS_NO_MEMORY;
4311 } else {
4312 dos_fname = talloc_asprintf(mem_ctx,
4313 "\\%s",
4314 smb_fname->base_name);
4315 if (!dos_fname) {
4316 return NT_STATUS_NO_MEMORY;
4318 if (is_ntfs_stream_smb_fname(smb_fname)) {
4319 dos_fname = talloc_asprintf(dos_fname, "%s",
4320 smb_fname->stream_name);
4321 if (!dos_fname) {
4322 return NT_STATUS_NO_MEMORY;
4326 string_replace(dos_fname, '/', '\\');
4329 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4331 if (!fsp) {
4332 /* Do we have this path open ? */
4333 files_struct *fsp1;
4334 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4335 fsp1 = file_find_di_first(conn->sconn, fileid);
4336 if (fsp1 && fsp1->initial_allocation_size) {
4337 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4341 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4342 file_size = get_file_size_stat(psbuf);
4345 if (fsp) {
4346 pos = fsp->fh->position_information;
4349 if (fsp) {
4350 access_mask = fsp->access_mask;
4351 } else {
4352 /* GENERIC_EXECUTE mapping from Windows */
4353 access_mask = 0x12019F;
4356 /* This should be an index number - looks like
4357 dev/ino to me :-)
4359 I think this causes us to fail the IFSKIT
4360 BasicFileInformationTest. -tpot */
4361 file_index = get_FileIndex(conn, psbuf);
4363 switch (info_level) {
4364 case SMB_INFO_STANDARD:
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4366 data_size = 22;
4367 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4368 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4369 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4370 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4371 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4372 SSVAL(pdata,l1_attrFile,mode);
4373 break;
4375 case SMB_INFO_QUERY_EA_SIZE:
4377 unsigned int ea_size =
4378 estimate_ea_size(conn, fsp,
4379 smb_fname->base_name);
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4381 data_size = 26;
4382 srv_put_dos_date2(pdata,0,create_time);
4383 srv_put_dos_date2(pdata,4,atime);
4384 srv_put_dos_date2(pdata,8,mtime); /* write time */
4385 SIVAL(pdata,12,(uint32)file_size);
4386 SIVAL(pdata,16,(uint32)allocation_size);
4387 SSVAL(pdata,20,mode);
4388 SIVAL(pdata,22,ea_size);
4389 break;
4392 case SMB_INFO_IS_NAME_VALID:
4393 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4394 if (fsp) {
4395 /* os/2 needs this ? really ?*/
4396 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4398 /* This is only reached for qpathinfo */
4399 data_size = 0;
4400 break;
4402 case SMB_INFO_QUERY_EAS_FROM_LIST:
4404 size_t total_ea_len = 0;
4405 struct ea_list *ea_file_list = NULL;
4407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4409 ea_file_list =
4410 get_ea_list_from_file(mem_ctx, conn, fsp,
4411 smb_fname->base_name,
4412 &total_ea_len);
4413 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4415 if (!ea_list || (total_ea_len > data_size)) {
4416 data_size = 4;
4417 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4418 break;
4421 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4422 break;
4425 case SMB_INFO_QUERY_ALL_EAS:
4427 /* We have data_size bytes to put EA's into. */
4428 size_t total_ea_len = 0;
4430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4432 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4433 smb_fname->base_name,
4434 &total_ea_len);
4435 if (!ea_list || (total_ea_len > data_size)) {
4436 data_size = 4;
4437 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4438 break;
4441 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4442 break;
4445 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4447 /* This is FileFullEaInformation - 0xF which maps to
4448 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4450 /* We have data_size bytes to put EA's into. */
4451 size_t total_ea_len = 0;
4452 struct ea_list *ea_file_list = NULL;
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4456 /*TODO: add filtering and index handling */
4458 ea_file_list =
4459 get_ea_list_from_file(mem_ctx, conn, fsp,
4460 smb_fname->base_name,
4461 &total_ea_len);
4462 if (!ea_file_list) {
4463 return NT_STATUS_NO_EAS_ON_FILE;
4466 status = fill_ea_chained_buffer(mem_ctx,
4467 pdata,
4468 data_size,
4469 &data_size,
4470 conn, ea_file_list);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 return status;
4474 break;
4477 case SMB_FILE_BASIC_INFORMATION:
4478 case SMB_QUERY_FILE_BASIC_INFO:
4480 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4482 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4483 } else {
4484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4485 data_size = 40;
4486 SIVAL(pdata,36,0);
4488 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4489 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4490 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4491 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4492 SIVAL(pdata,32,mode);
4494 DEBUG(5,("SMB_QFBI - "));
4495 DEBUG(5,("create: %s ", ctime(&create_time)));
4496 DEBUG(5,("access: %s ", ctime(&atime)));
4497 DEBUG(5,("write: %s ", ctime(&mtime)));
4498 DEBUG(5,("change: %s ", ctime(&c_time)));
4499 DEBUG(5,("mode: %x\n", mode));
4500 break;
4502 case SMB_FILE_STANDARD_INFORMATION:
4503 case SMB_QUERY_FILE_STANDARD_INFO:
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4506 data_size = 24;
4507 SOFF_T(pdata,0,allocation_size);
4508 SOFF_T(pdata,8,file_size);
4509 SIVAL(pdata,16,nlink);
4510 SCVAL(pdata,20,delete_pending?1:0);
4511 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4512 SSVAL(pdata,22,0); /* Padding. */
4513 break;
4515 case SMB_FILE_EA_INFORMATION:
4516 case SMB_QUERY_FILE_EA_INFO:
4518 unsigned int ea_size =
4519 estimate_ea_size(conn, fsp, smb_fname->base_name);
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4521 data_size = 4;
4522 SIVAL(pdata,0,ea_size);
4523 break;
4526 /* Get the 8.3 name - used if NT SMB was negotiated. */
4527 case SMB_QUERY_FILE_ALT_NAME_INFO:
4528 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4530 int len;
4531 char mangled_name[13];
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4533 if (!name_to_8_3(base_name,mangled_name,
4534 True,conn->params)) {
4535 return NT_STATUS_NO_MEMORY;
4537 len = srvstr_push(dstart, flags2,
4538 pdata+4, mangled_name,
4539 PTR_DIFF(dend, pdata+4),
4540 STR_UNICODE);
4541 data_size = 4 + len;
4542 SIVAL(pdata,0,len);
4543 break;
4546 case SMB_QUERY_FILE_NAME_INFO:
4548 int len;
4550 this must be *exactly* right for ACLs on mapped drives to work
4552 len = srvstr_push(dstart, flags2,
4553 pdata+4, dos_fname,
4554 PTR_DIFF(dend, pdata+4),
4555 STR_UNICODE);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4557 data_size = 4 + len;
4558 SIVAL(pdata,0,len);
4559 break;
4562 case SMB_FILE_ALLOCATION_INFORMATION:
4563 case SMB_QUERY_FILE_ALLOCATION_INFO:
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4565 data_size = 8;
4566 SOFF_T(pdata,0,allocation_size);
4567 break;
4569 case SMB_FILE_END_OF_FILE_INFORMATION:
4570 case SMB_QUERY_FILE_END_OF_FILEINFO:
4571 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4572 data_size = 8;
4573 SOFF_T(pdata,0,file_size);
4574 break;
4576 case SMB_QUERY_FILE_ALL_INFO:
4577 case SMB_FILE_ALL_INFORMATION:
4579 int len;
4580 unsigned int ea_size =
4581 estimate_ea_size(conn, fsp, smb_fname->base_name);
4582 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4583 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4584 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4585 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4586 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4587 SIVAL(pdata,32,mode);
4588 SIVAL(pdata,36,0); /* padding. */
4589 pdata += 40;
4590 SOFF_T(pdata,0,allocation_size);
4591 SOFF_T(pdata,8,file_size);
4592 SIVAL(pdata,16,nlink);
4593 SCVAL(pdata,20,delete_pending);
4594 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4595 SSVAL(pdata,22,0);
4596 pdata += 24;
4597 SIVAL(pdata,0,ea_size);
4598 pdata += 4; /* EA info */
4599 len = srvstr_push(dstart, flags2,
4600 pdata+4, dos_fname,
4601 PTR_DIFF(dend, pdata+4),
4602 STR_UNICODE);
4603 SIVAL(pdata,0,len);
4604 pdata += 4 + len;
4605 data_size = PTR_DIFF(pdata,(*ppdata));
4606 break;
4609 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4611 int len;
4612 unsigned int ea_size =
4613 estimate_ea_size(conn, fsp, smb_fname->base_name);
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4615 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4616 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4617 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4618 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4619 SIVAL(pdata, 0x20, mode);
4620 SIVAL(pdata, 0x24, 0); /* padding. */
4621 SBVAL(pdata, 0x28, allocation_size);
4622 SBVAL(pdata, 0x30, file_size);
4623 SIVAL(pdata, 0x38, nlink);
4624 SCVAL(pdata, 0x3C, delete_pending);
4625 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4626 SSVAL(pdata, 0x3E, 0); /* padding */
4627 SBVAL(pdata, 0x40, file_index);
4628 SIVAL(pdata, 0x48, ea_size);
4629 SIVAL(pdata, 0x4C, access_mask);
4630 SBVAL(pdata, 0x50, pos);
4631 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4632 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4634 pdata += 0x60;
4636 len = srvstr_push(dstart, flags2,
4637 pdata+4, dos_fname,
4638 PTR_DIFF(dend, pdata+4),
4639 STR_UNICODE);
4640 SIVAL(pdata,0,len);
4641 pdata += 4 + len;
4642 data_size = PTR_DIFF(pdata,(*ppdata));
4643 break;
4645 case SMB_FILE_INTERNAL_INFORMATION:
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4648 SBVAL(pdata, 0, file_index);
4649 data_size = 8;
4650 break;
4652 case SMB_FILE_ACCESS_INFORMATION:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4654 SIVAL(pdata, 0, access_mask);
4655 data_size = 4;
4656 break;
4658 case SMB_FILE_NAME_INFORMATION:
4659 /* Pathname with leading '\'. */
4661 size_t byte_len;
4662 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4664 SIVAL(pdata,0,byte_len);
4665 data_size = 4 + byte_len;
4666 break;
4669 case SMB_FILE_DISPOSITION_INFORMATION:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4671 data_size = 1;
4672 SCVAL(pdata,0,delete_pending);
4673 break;
4675 case SMB_FILE_POSITION_INFORMATION:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4677 data_size = 8;
4678 SOFF_T(pdata,0,pos);
4679 break;
4681 case SMB_FILE_MODE_INFORMATION:
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4683 SIVAL(pdata,0,mode);
4684 data_size = 4;
4685 break;
4687 case SMB_FILE_ALIGNMENT_INFORMATION:
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4689 SIVAL(pdata,0,0); /* No alignment needed. */
4690 data_size = 4;
4691 break;
4694 * NT4 server just returns "invalid query" to this - if we try
4695 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4696 * want this. JRA.
4698 /* The first statement above is false - verified using Thursby
4699 * client against NT4 -- gcolley.
4701 case SMB_QUERY_FILE_STREAM_INFO:
4702 case SMB_FILE_STREAM_INFORMATION: {
4703 unsigned int num_streams = 0;
4704 struct stream_struct *streams = NULL;
4706 DEBUG(10,("smbd_do_qfilepathinfo: "
4707 "SMB_FILE_STREAM_INFORMATION\n"));
4709 if (is_ntfs_stream_smb_fname(smb_fname)) {
4710 return NT_STATUS_INVALID_PARAMETER;
4713 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4714 talloc_tos(), &num_streams, &streams);
4716 if (!NT_STATUS_IS_OK(status)) {
4717 DEBUG(10, ("could not get stream info: %s\n",
4718 nt_errstr(status)));
4719 return status;
4722 status = marshall_stream_info(num_streams, streams,
4723 pdata, max_data_bytes,
4724 &data_size);
4726 if (!NT_STATUS_IS_OK(status)) {
4727 DEBUG(10, ("marshall_stream_info failed: %s\n",
4728 nt_errstr(status)));
4729 return status;
4732 TALLOC_FREE(streams);
4734 break;
4736 case SMB_QUERY_COMPRESSION_INFO:
4737 case SMB_FILE_COMPRESSION_INFORMATION:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4739 SOFF_T(pdata,0,file_size);
4740 SIVAL(pdata,8,0); /* ??? */
4741 SIVAL(pdata,12,0); /* ??? */
4742 data_size = 16;
4743 break;
4745 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4746 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4747 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4748 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4749 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4750 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4751 SOFF_T(pdata,32,allocation_size);
4752 SOFF_T(pdata,40,file_size);
4753 SIVAL(pdata,48,mode);
4754 SIVAL(pdata,52,0); /* ??? */
4755 data_size = 56;
4756 break;
4758 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4760 SIVAL(pdata,0,mode);
4761 SIVAL(pdata,4,0);
4762 data_size = 8;
4763 break;
4766 * CIFS UNIX Extensions.
4769 case SMB_QUERY_FILE_UNIX_BASIC:
4771 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4772 data_size = PTR_DIFF(pdata,(*ppdata));
4774 DEBUG(4,("smbd_do_qfilepathinfo: "
4775 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4776 dump_data(4, (uint8_t *)(*ppdata), data_size);
4778 break;
4780 case SMB_QUERY_FILE_UNIX_INFO2:
4782 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4783 data_size = PTR_DIFF(pdata,(*ppdata));
4786 int i;
4787 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4789 for (i=0; i<100; i++)
4790 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4791 DEBUG(4,("\n"));
4794 break;
4796 case SMB_QUERY_FILE_UNIX_LINK:
4798 int len;
4799 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4801 if (!buffer) {
4802 return NT_STATUS_NO_MEMORY;
4805 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4806 #ifdef S_ISLNK
4807 if(!S_ISLNK(psbuf->st_ex_mode)) {
4808 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4810 #else
4811 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4812 #endif
4813 len = SMB_VFS_READLINK(conn,
4814 smb_fname->base_name,
4815 buffer, PATH_MAX);
4816 if (len == -1) {
4817 return map_nt_error_from_unix(errno);
4819 buffer[len] = 0;
4820 len = srvstr_push(dstart, flags2,
4821 pdata, buffer,
4822 PTR_DIFF(dend, pdata),
4823 STR_TERMINATE);
4824 pdata += len;
4825 data_size = PTR_DIFF(pdata,(*ppdata));
4827 break;
4830 #if defined(HAVE_POSIX_ACLS)
4831 case SMB_QUERY_POSIX_ACL:
4833 SMB_ACL_T file_acl = NULL;
4834 SMB_ACL_T def_acl = NULL;
4835 uint16 num_file_acls = 0;
4836 uint16 num_def_acls = 0;
4838 if (fsp && fsp->fh->fd != -1) {
4839 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4840 } else {
4841 file_acl =
4842 SMB_VFS_SYS_ACL_GET_FILE(conn,
4843 smb_fname->base_name,
4844 SMB_ACL_TYPE_ACCESS);
4847 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4848 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4849 "not implemented on "
4850 "filesystem containing %s\n",
4851 smb_fname->base_name));
4852 return NT_STATUS_NOT_IMPLEMENTED;
4855 if (S_ISDIR(psbuf->st_ex_mode)) {
4856 if (fsp && fsp->is_directory) {
4857 def_acl =
4858 SMB_VFS_SYS_ACL_GET_FILE(
4859 conn,
4860 fsp->fsp_name->base_name,
4861 SMB_ACL_TYPE_DEFAULT);
4862 } else {
4863 def_acl =
4864 SMB_VFS_SYS_ACL_GET_FILE(
4865 conn,
4866 smb_fname->base_name,
4867 SMB_ACL_TYPE_DEFAULT);
4869 def_acl = free_empty_sys_acl(conn, def_acl);
4872 num_file_acls = count_acl_entries(conn, file_acl);
4873 num_def_acls = count_acl_entries(conn, def_acl);
4875 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4876 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4877 data_size,
4878 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4879 SMB_POSIX_ACL_HEADER_SIZE) ));
4880 if (file_acl) {
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4883 if (def_acl) {
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4886 return NT_STATUS_BUFFER_TOO_SMALL;
4889 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4890 SSVAL(pdata,2,num_file_acls);
4891 SSVAL(pdata,4,num_def_acls);
4892 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4893 if (file_acl) {
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4896 if (def_acl) {
4897 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4899 return NT_STATUS_INTERNAL_ERROR;
4901 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4902 if (file_acl) {
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4905 if (def_acl) {
4906 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4908 return NT_STATUS_INTERNAL_ERROR;
4911 if (file_acl) {
4912 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4914 if (def_acl) {
4915 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4917 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4918 break;
4920 #endif
4923 case SMB_QUERY_POSIX_LOCK:
4925 uint64_t count;
4926 uint64_t offset;
4927 uint64_t smblctx;
4928 enum brl_type lock_type;
4930 /* We need an open file with a real fd for this. */
4931 if (!fsp || fsp->fh->fd == -1) {
4932 return NT_STATUS_INVALID_LEVEL;
4935 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4936 return NT_STATUS_INVALID_PARAMETER;
4939 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4940 case POSIX_LOCK_TYPE_READ:
4941 lock_type = READ_LOCK;
4942 break;
4943 case POSIX_LOCK_TYPE_WRITE:
4944 lock_type = WRITE_LOCK;
4945 break;
4946 case POSIX_LOCK_TYPE_UNLOCK:
4947 default:
4948 /* There's no point in asking for an unlock... */
4949 return NT_STATUS_INVALID_PARAMETER;
4952 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4953 #if defined(HAVE_LONGLONG)
4954 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4955 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4956 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4957 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4958 #else /* HAVE_LONGLONG */
4959 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4960 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4961 #endif /* HAVE_LONGLONG */
4963 status = query_lock(fsp,
4964 &smblctx,
4965 &count,
4966 &offset,
4967 &lock_type,
4968 POSIX_LOCK);
4970 if (ERROR_WAS_LOCK_DENIED(status)) {
4971 /* Here we need to report who has it locked... */
4972 data_size = POSIX_LOCK_DATA_SIZE;
4974 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4975 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4976 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4977 #if defined(HAVE_LONGLONG)
4978 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4979 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4980 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4981 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4982 #else /* HAVE_LONGLONG */
4983 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4984 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4985 #endif /* HAVE_LONGLONG */
4987 } else if (NT_STATUS_IS_OK(status)) {
4988 /* For success we just return a copy of what we sent
4989 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4990 data_size = POSIX_LOCK_DATA_SIZE;
4991 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4992 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4993 } else {
4994 return status;
4996 break;
4999 default:
5000 return NT_STATUS_INVALID_LEVEL;
5003 *pdata_size = data_size;
5004 return NT_STATUS_OK;
5007 /****************************************************************************
5008 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5009 file name or file id).
5010 ****************************************************************************/
5012 static void call_trans2qfilepathinfo(connection_struct *conn,
5013 struct smb_request *req,
5014 unsigned int tran_call,
5015 char **pparams, int total_params,
5016 char **ppdata, int total_data,
5017 unsigned int max_data_bytes)
5019 char *params = *pparams;
5020 char *pdata = *ppdata;
5021 uint16 info_level;
5022 unsigned int data_size = 0;
5023 unsigned int param_size = 2;
5024 struct smb_filename *smb_fname = NULL;
5025 bool delete_pending = False;
5026 struct timespec write_time_ts;
5027 files_struct *fsp = NULL;
5028 struct file_id fileid;
5029 struct ea_list *ea_list = NULL;
5030 int lock_data_count = 0;
5031 char *lock_data = NULL;
5032 NTSTATUS status = NT_STATUS_OK;
5034 if (!params) {
5035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5036 return;
5039 ZERO_STRUCT(write_time_ts);
5041 if (tran_call == TRANSACT2_QFILEINFO) {
5042 if (total_params < 4) {
5043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5044 return;
5047 if (IS_IPC(conn)) {
5048 call_trans2qpipeinfo(conn, req, tran_call,
5049 pparams, total_params,
5050 ppdata, total_data,
5051 max_data_bytes);
5052 return;
5055 fsp = file_fsp(req, SVAL(params,0));
5056 info_level = SVAL(params,2);
5058 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5060 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5062 return;
5065 /* Initial check for valid fsp ptr. */
5066 if (!check_fsp_open(conn, req, fsp)) {
5067 return;
5070 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5071 &smb_fname);
5072 if (!NT_STATUS_IS_OK(status)) {
5073 reply_nterror(req, status);
5074 return;
5077 if(fsp->fake_file_handle) {
5079 * This is actually for the QUOTA_FAKE_FILE --metze
5082 /* We know this name is ok, it's already passed the checks. */
5084 } else if(fsp->fh->fd == -1) {
5086 * This is actually a QFILEINFO on a directory
5087 * handle (returned from an NT SMB). NT5.0 seems
5088 * to do this call. JRA.
5091 if (INFO_LEVEL_IS_UNIX(info_level)) {
5092 /* Always do lstat for UNIX calls. */
5093 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5094 DEBUG(3,("call_trans2qfilepathinfo: "
5095 "SMB_VFS_LSTAT of %s failed "
5096 "(%s)\n",
5097 smb_fname_str_dbg(smb_fname),
5098 strerror(errno)));
5099 reply_nterror(req,
5100 map_nt_error_from_unix(errno));
5101 return;
5103 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5104 DEBUG(3,("call_trans2qfilepathinfo: "
5105 "SMB_VFS_STAT of %s failed (%s)\n",
5106 smb_fname_str_dbg(smb_fname),
5107 strerror(errno)));
5108 reply_nterror(req,
5109 map_nt_error_from_unix(errno));
5110 return;
5113 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5114 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5115 } else {
5117 * Original code - this is an open file.
5119 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5120 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5121 fsp->fnum, strerror(errno)));
5122 reply_nterror(req,
5123 map_nt_error_from_unix(errno));
5124 return;
5126 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5127 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5130 } else {
5131 uint32_t name_hash;
5132 char *fname = NULL;
5133 uint32_t ucf_flags = 0;
5135 /* qpathinfo */
5136 if (total_params < 7) {
5137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5138 return;
5141 info_level = SVAL(params,0);
5143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5145 if (INFO_LEVEL_IS_UNIX(info_level)) {
5146 if (!lp_unix_extensions()) {
5147 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5148 return;
5150 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5151 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5152 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5153 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5157 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5158 total_params - 6,
5159 STR_TERMINATE, &status);
5160 if (!NT_STATUS_IS_OK(status)) {
5161 reply_nterror(req, status);
5162 return;
5165 status = filename_convert(req,
5166 conn,
5167 req->flags2 & FLAGS2_DFS_PATHNAMES,
5168 fname,
5169 ucf_flags,
5170 NULL,
5171 &smb_fname);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5174 reply_botherror(req,
5175 NT_STATUS_PATH_NOT_COVERED,
5176 ERRSRV, ERRbadpath);
5177 return;
5179 reply_nterror(req, status);
5180 return;
5183 /* If this is a stream, check if there is a delete_pending. */
5184 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5185 && is_ntfs_stream_smb_fname(smb_fname)) {
5186 struct smb_filename *smb_fname_base = NULL;
5188 /* Create an smb_filename with stream_name == NULL. */
5189 status =
5190 create_synthetic_smb_fname(talloc_tos(),
5191 smb_fname->base_name,
5192 NULL, NULL,
5193 &smb_fname_base);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 reply_nterror(req, status);
5196 return;
5199 if (INFO_LEVEL_IS_UNIX(info_level)) {
5200 /* Always do lstat for UNIX calls. */
5201 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "SMB_VFS_LSTAT of %s failed "
5204 "(%s)\n",
5205 smb_fname_str_dbg(smb_fname_base),
5206 strerror(errno)));
5207 TALLOC_FREE(smb_fname_base);
5208 reply_nterror(req,
5209 map_nt_error_from_unix(errno));
5210 return;
5212 } else {
5213 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5214 DEBUG(3,("call_trans2qfilepathinfo: "
5215 "fileinfo of %s failed "
5216 "(%s)\n",
5217 smb_fname_str_dbg(smb_fname_base),
5218 strerror(errno)));
5219 TALLOC_FREE(smb_fname_base);
5220 reply_nterror(req,
5221 map_nt_error_from_unix(errno));
5222 return;
5226 status = file_name_hash(conn,
5227 smb_fname_str_dbg(smb_fname_base),
5228 &name_hash);
5229 if (!NT_STATUS_IS_OK(status)) {
5230 TALLOC_FREE(smb_fname_base);
5231 reply_nterror(req, status);
5232 return;
5235 fileid = vfs_file_id_from_sbuf(conn,
5236 &smb_fname_base->st);
5237 TALLOC_FREE(smb_fname_base);
5238 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5239 if (delete_pending) {
5240 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5241 return;
5245 if (INFO_LEVEL_IS_UNIX(info_level)) {
5246 /* Always do lstat for UNIX calls. */
5247 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "SMB_VFS_LSTAT of %s failed (%s)\n",
5250 smb_fname_str_dbg(smb_fname),
5251 strerror(errno)));
5252 reply_nterror(req,
5253 map_nt_error_from_unix(errno));
5254 return;
5257 } else {
5258 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5259 DEBUG(3,("call_trans2qfilepathinfo: "
5260 "SMB_VFS_STAT of %s failed (%s)\n",
5261 smb_fname_str_dbg(smb_fname),
5262 strerror(errno)));
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),
5271 &name_hash);
5272 if (!NT_STATUS_IS_OK(status)) {
5273 reply_nterror(req, status);
5274 return;
5277 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5278 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5279 if (delete_pending) {
5280 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5281 return;
5285 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5286 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5287 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5289 /* Pull out any data sent here before we realloc. */
5290 switch (info_level) {
5291 case SMB_INFO_QUERY_EAS_FROM_LIST:
5293 /* Pull any EA list from the data portion. */
5294 uint32 ea_size;
5296 if (total_data < 4) {
5297 reply_nterror(
5298 req, NT_STATUS_INVALID_PARAMETER);
5299 return;
5301 ea_size = IVAL(pdata,0);
5303 if (total_data > 0 && ea_size != total_data) {
5304 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5305 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5306 reply_nterror(
5307 req, NT_STATUS_INVALID_PARAMETER);
5308 return;
5311 if (!lp_ea_support(SNUM(conn))) {
5312 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5313 return;
5316 /* Pull out the list of names. */
5317 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5318 if (!ea_list) {
5319 reply_nterror(
5320 req, NT_STATUS_INVALID_PARAMETER);
5321 return;
5323 break;
5326 case SMB_QUERY_POSIX_LOCK:
5328 if (fsp == NULL || fsp->fh->fd == -1) {
5329 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5330 return;
5333 if (total_data != POSIX_LOCK_DATA_SIZE) {
5334 reply_nterror(
5335 req, NT_STATUS_INVALID_PARAMETER);
5336 return;
5339 /* Copy the lock range data. */
5340 lock_data = (char *)talloc_memdup(
5341 req, pdata, total_data);
5342 if (!lock_data) {
5343 reply_nterror(req, NT_STATUS_NO_MEMORY);
5344 return;
5346 lock_data_count = total_data;
5348 default:
5349 break;
5352 *pparams = (char *)SMB_REALLOC(*pparams,2);
5353 if (*pparams == NULL) {
5354 reply_nterror(req, NT_STATUS_NO_MEMORY);
5355 return;
5357 params = *pparams;
5358 SSVAL(params,0,0);
5361 * draft-leach-cifs-v1-spec-02.txt
5362 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5363 * says:
5365 * The requested information is placed in the Data portion of the
5366 * transaction response. For the information levels greater than 0x100,
5367 * the transaction response has 1 parameter word which should be
5368 * ignored by the client.
5370 * However Windows only follows this rule for the IS_NAME_VALID call.
5372 switch (info_level) {
5373 case SMB_INFO_IS_NAME_VALID:
5374 param_size = 0;
5375 break;
5378 if ((info_level & 0xFF00) == 0xFF00) {
5380 * We use levels that start with 0xFF00
5381 * internally to represent SMB2 specific levels
5383 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5384 return;
5387 status = smbd_do_qfilepathinfo(conn, req, info_level,
5388 fsp, smb_fname,
5389 delete_pending, write_time_ts,
5390 ea_list,
5391 lock_data_count, lock_data,
5392 req->flags2, max_data_bytes,
5393 ppdata, &data_size);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 reply_nterror(req, status);
5396 return;
5399 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5400 max_data_bytes);
5402 return;
5405 /****************************************************************************
5406 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5407 code.
5408 ****************************************************************************/
5410 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5411 connection_struct *conn,
5412 struct smb_request *req,
5413 bool overwrite_if_exists,
5414 const struct smb_filename *smb_fname_old,
5415 struct smb_filename *smb_fname_new)
5417 NTSTATUS status = NT_STATUS_OK;
5419 /* source must already exist. */
5420 if (!VALID_STAT(smb_fname_old->st)) {
5421 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5424 if (VALID_STAT(smb_fname_new->st)) {
5425 if (overwrite_if_exists) {
5426 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5427 return NT_STATUS_FILE_IS_A_DIRECTORY;
5429 status = unlink_internals(conn,
5430 req,
5431 FILE_ATTRIBUTE_NORMAL,
5432 smb_fname_new,
5433 false);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 return status;
5437 } else {
5438 /* Disallow if newname already exists. */
5439 return NT_STATUS_OBJECT_NAME_COLLISION;
5443 /* No links from a directory. */
5444 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5445 return NT_STATUS_FILE_IS_A_DIRECTORY;
5448 /* Setting a hardlink to/from a stream isn't currently supported. */
5449 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5450 is_ntfs_stream_smb_fname(smb_fname_new)) {
5451 return NT_STATUS_INVALID_PARAMETER;
5454 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5455 smb_fname_old->base_name, smb_fname_new->base_name));
5457 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5458 smb_fname_new->base_name) != 0) {
5459 status = map_nt_error_from_unix(errno);
5460 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5461 nt_errstr(status), smb_fname_old->base_name,
5462 smb_fname_new->base_name));
5464 return status;
5467 /****************************************************************************
5468 Deal with setting the time from any of the setfilepathinfo functions.
5469 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5470 calling this function.
5471 ****************************************************************************/
5473 NTSTATUS smb_set_file_time(connection_struct *conn,
5474 files_struct *fsp,
5475 const struct smb_filename *smb_fname,
5476 struct smb_file_time *ft,
5477 bool setting_write_time)
5479 struct smb_filename smb_fname_base;
5480 uint32 action =
5481 FILE_NOTIFY_CHANGE_LAST_ACCESS
5482 |FILE_NOTIFY_CHANGE_LAST_WRITE
5483 |FILE_NOTIFY_CHANGE_CREATION;
5485 if (!VALID_STAT(smb_fname->st)) {
5486 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5489 /* get some defaults (no modifications) if any info is zero or -1. */
5490 if (null_timespec(ft->create_time)) {
5491 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5494 if (null_timespec(ft->atime)) {
5495 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5498 if (null_timespec(ft->mtime)) {
5499 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5502 if (!setting_write_time) {
5503 /* ft->mtime comes from change time, not write time. */
5504 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5507 /* Ensure the resolution is the correct for
5508 * what we can store on this filesystem. */
5510 round_timespec(conn->ts_res, &ft->create_time);
5511 round_timespec(conn->ts_res, &ft->ctime);
5512 round_timespec(conn->ts_res, &ft->atime);
5513 round_timespec(conn->ts_res, &ft->mtime);
5515 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5516 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5517 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5518 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5519 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5520 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5521 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5522 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5524 if (setting_write_time) {
5526 * This was a Windows setfileinfo on an open file.
5527 * NT does this a lot. We also need to
5528 * set the time here, as it can be read by
5529 * FindFirst/FindNext and with the patch for bug #2045
5530 * in smbd/fileio.c it ensures that this timestamp is
5531 * kept sticky even after a write. We save the request
5532 * away and will set it on file close and after a write. JRA.
5535 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5536 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5538 if (fsp != NULL) {
5539 if (fsp->base_fsp) {
5540 set_sticky_write_time_fsp(fsp->base_fsp,
5541 ft->mtime);
5542 } else {
5543 set_sticky_write_time_fsp(fsp, ft->mtime);
5545 } else {
5546 set_sticky_write_time_path(
5547 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5548 ft->mtime);
5552 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5554 /* Always call ntimes on the base, even if a stream was passed in. */
5555 smb_fname_base = *smb_fname;
5556 smb_fname_base.stream_name = NULL;
5558 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5559 return map_nt_error_from_unix(errno);
5562 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5563 smb_fname->base_name);
5564 return NT_STATUS_OK;
5567 /****************************************************************************
5568 Deal with setting the dosmode from any of the setfilepathinfo functions.
5569 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5570 done before calling this function.
5571 ****************************************************************************/
5573 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5574 const struct smb_filename *smb_fname,
5575 uint32 dosmode)
5577 struct smb_filename *smb_fname_base = NULL;
5578 NTSTATUS status;
5580 if (!VALID_STAT(smb_fname->st)) {
5581 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5584 /* Always operate on the base_name, even if a stream was passed in. */
5585 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5586 NULL, &smb_fname->st,
5587 &smb_fname_base);
5588 if (!NT_STATUS_IS_OK(status)) {
5589 return status;
5592 if (dosmode) {
5593 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5594 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5595 } else {
5596 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5600 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5602 /* check the mode isn't different, before changing it */
5603 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5604 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5605 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5606 (unsigned int)dosmode));
5608 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5609 false)) {
5610 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5611 "%s failed (%s)\n",
5612 smb_fname_str_dbg(smb_fname_base),
5613 strerror(errno)));
5614 status = map_nt_error_from_unix(errno);
5615 goto out;
5618 status = NT_STATUS_OK;
5619 out:
5620 TALLOC_FREE(smb_fname_base);
5621 return status;
5624 /****************************************************************************
5625 Deal with setting the size from any of the setfilepathinfo functions.
5626 ****************************************************************************/
5628 static NTSTATUS smb_set_file_size(connection_struct *conn,
5629 struct smb_request *req,
5630 files_struct *fsp,
5631 const struct smb_filename *smb_fname,
5632 const SMB_STRUCT_STAT *psbuf,
5633 SMB_OFF_T size,
5634 bool fail_after_createfile)
5636 NTSTATUS status = NT_STATUS_OK;
5637 struct smb_filename *smb_fname_tmp = NULL;
5638 files_struct *new_fsp = NULL;
5640 if (!VALID_STAT(*psbuf)) {
5641 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5644 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5646 if (size == get_file_size_stat(psbuf)) {
5647 return NT_STATUS_OK;
5650 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5651 smb_fname_str_dbg(smb_fname), (double)size));
5653 if (fsp && fsp->fh->fd != -1) {
5654 /* Handle based call. */
5655 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5656 return NT_STATUS_ACCESS_DENIED;
5659 if (vfs_set_filelen(fsp, size) == -1) {
5660 return map_nt_error_from_unix(errno);
5662 trigger_write_time_update_immediate(fsp);
5663 return NT_STATUS_OK;
5666 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 return status;
5671 smb_fname_tmp->st = *psbuf;
5673 status = SMB_VFS_CREATE_FILE(
5674 conn, /* conn */
5675 req, /* req */
5676 0, /* root_dir_fid */
5677 smb_fname_tmp, /* fname */
5678 FILE_WRITE_DATA, /* access_mask */
5679 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5680 FILE_SHARE_DELETE),
5681 FILE_OPEN, /* create_disposition*/
5682 0, /* create_options */
5683 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5684 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5685 0, /* allocation_size */
5686 0, /* private_flags */
5687 NULL, /* sd */
5688 NULL, /* ea_list */
5689 &new_fsp, /* result */
5690 NULL); /* pinfo */
5692 TALLOC_FREE(smb_fname_tmp);
5694 if (!NT_STATUS_IS_OK(status)) {
5695 /* NB. We check for open_was_deferred in the caller. */
5696 return status;
5699 /* See RAW-SFILEINFO-END-OF-FILE */
5700 if (fail_after_createfile) {
5701 close_file(req, new_fsp,NORMAL_CLOSE);
5702 return NT_STATUS_INVALID_LEVEL;
5705 if (vfs_set_filelen(new_fsp, size) == -1) {
5706 status = map_nt_error_from_unix(errno);
5707 close_file(req, new_fsp,NORMAL_CLOSE);
5708 return status;
5711 trigger_write_time_update_immediate(new_fsp);
5712 close_file(req, new_fsp,NORMAL_CLOSE);
5713 return NT_STATUS_OK;
5716 /****************************************************************************
5717 Deal with SMB_INFO_SET_EA.
5718 ****************************************************************************/
5720 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5721 const char *pdata,
5722 int total_data,
5723 files_struct *fsp,
5724 const struct smb_filename *smb_fname)
5726 struct ea_list *ea_list = NULL;
5727 TALLOC_CTX *ctx = NULL;
5728 NTSTATUS status = NT_STATUS_OK;
5730 if (total_data < 10) {
5732 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5733 length. They seem to have no effect. Bug #3212. JRA */
5735 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5736 /* We're done. We only get EA info in this call. */
5737 return NT_STATUS_OK;
5740 return NT_STATUS_INVALID_PARAMETER;
5743 if (IVAL(pdata,0) > total_data) {
5744 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5745 IVAL(pdata,0), (unsigned int)total_data));
5746 return NT_STATUS_INVALID_PARAMETER;
5749 ctx = talloc_tos();
5750 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5751 if (!ea_list) {
5752 return NT_STATUS_INVALID_PARAMETER;
5755 status = set_ea(conn, fsp, smb_fname, ea_list);
5757 return status;
5760 /****************************************************************************
5761 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5765 const char *pdata,
5766 int total_data,
5767 files_struct *fsp)
5769 struct ea_list *ea_list = NULL;
5770 NTSTATUS status;
5772 if (!fsp) {
5773 return NT_STATUS_INVALID_HANDLE;
5776 if (!lp_ea_support(SNUM(conn))) {
5777 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5778 "EA's not supported.\n",
5779 (unsigned int)total_data));
5780 return NT_STATUS_EAS_NOT_SUPPORTED;
5783 if (total_data < 10) {
5784 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5785 "too small.\n",
5786 (unsigned int)total_data));
5787 return NT_STATUS_INVALID_PARAMETER;
5790 ea_list = read_nttrans_ea_list(talloc_tos(),
5791 pdata,
5792 total_data);
5794 if (!ea_list) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5800 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5801 smb_fname_str_dbg(fsp->fsp_name),
5802 nt_errstr(status) ));
5804 return status;
5808 /****************************************************************************
5809 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5810 ****************************************************************************/
5812 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5813 const char *pdata,
5814 int total_data,
5815 files_struct *fsp,
5816 struct smb_filename *smb_fname)
5818 NTSTATUS status = NT_STATUS_OK;
5819 bool delete_on_close;
5820 uint32 dosmode = 0;
5822 if (total_data < 1) {
5823 return NT_STATUS_INVALID_PARAMETER;
5826 if (fsp == NULL) {
5827 return NT_STATUS_INVALID_HANDLE;
5830 delete_on_close = (CVAL(pdata,0) ? True : False);
5831 dosmode = dos_mode(conn, smb_fname);
5833 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5834 "delete_on_close = %u\n",
5835 smb_fname_str_dbg(smb_fname),
5836 (unsigned int)dosmode,
5837 (unsigned int)delete_on_close ));
5839 if (delete_on_close) {
5840 status = can_set_delete_on_close(fsp, dosmode);
5841 if (!NT_STATUS_IS_OK(status)) {
5842 return status;
5846 /* The set is across all open files on this dev/inode pair. */
5847 if (!set_delete_on_close(fsp, delete_on_close,
5848 conn->session_info->unix_token)) {
5849 return NT_STATUS_ACCESS_DENIED;
5851 return NT_STATUS_OK;
5854 /****************************************************************************
5855 Deal with SMB_FILE_POSITION_INFORMATION.
5856 ****************************************************************************/
5858 static NTSTATUS smb_file_position_information(connection_struct *conn,
5859 const char *pdata,
5860 int total_data,
5861 files_struct *fsp)
5863 uint64_t position_information;
5865 if (total_data < 8) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 if (fsp == NULL) {
5870 /* Ignore on pathname based set. */
5871 return NT_STATUS_OK;
5874 position_information = (uint64_t)IVAL(pdata,0);
5875 #ifdef LARGE_SMB_OFF_T
5876 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5877 #else /* LARGE_SMB_OFF_T */
5878 if (IVAL(pdata,4) != 0) {
5879 /* more than 32 bits? */
5880 return NT_STATUS_INVALID_PARAMETER;
5882 #endif /* LARGE_SMB_OFF_T */
5884 DEBUG(10,("smb_file_position_information: Set file position "
5885 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5886 (double)position_information));
5887 fsp->fh->position_information = position_information;
5888 return NT_STATUS_OK;
5891 /****************************************************************************
5892 Deal with SMB_FILE_MODE_INFORMATION.
5893 ****************************************************************************/
5895 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5896 const char *pdata,
5897 int total_data)
5899 uint32 mode;
5901 if (total_data < 4) {
5902 return NT_STATUS_INVALID_PARAMETER;
5904 mode = IVAL(pdata,0);
5905 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5906 return NT_STATUS_INVALID_PARAMETER;
5908 return NT_STATUS_OK;
5911 /****************************************************************************
5912 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5913 ****************************************************************************/
5915 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5916 struct smb_request *req,
5917 const char *pdata,
5918 int total_data,
5919 const struct smb_filename *smb_fname)
5921 char *link_target = NULL;
5922 const char *newname = smb_fname->base_name;
5923 TALLOC_CTX *ctx = talloc_tos();
5925 /* Set a symbolic link. */
5926 /* Don't allow this if follow links is false. */
5928 if (total_data == 0) {
5929 return NT_STATUS_INVALID_PARAMETER;
5932 if (!lp_symlinks(SNUM(conn))) {
5933 return NT_STATUS_ACCESS_DENIED;
5936 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5937 total_data, STR_TERMINATE);
5939 if (!link_target) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5944 newname, link_target ));
5946 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5947 return map_nt_error_from_unix(errno);
5950 return NT_STATUS_OK;
5953 /****************************************************************************
5954 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5955 ****************************************************************************/
5957 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5958 struct smb_request *req,
5959 const char *pdata, int total_data,
5960 struct smb_filename *smb_fname_new)
5962 char *oldname = NULL;
5963 struct smb_filename *smb_fname_old = NULL;
5964 TALLOC_CTX *ctx = talloc_tos();
5965 NTSTATUS status = NT_STATUS_OK;
5967 /* Set a hard link. */
5968 if (total_data == 0) {
5969 return NT_STATUS_INVALID_PARAMETER;
5972 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5973 total_data, STR_TERMINATE, &status);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 return status;
5978 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5979 smb_fname_str_dbg(smb_fname_new), oldname));
5981 status = filename_convert(ctx,
5982 conn,
5983 req->flags2 & FLAGS2_DFS_PATHNAMES,
5984 oldname,
5986 NULL,
5987 &smb_fname_old);
5988 if (!NT_STATUS_IS_OK(status)) {
5989 return status;
5992 return hardlink_internals(ctx, conn, req, false,
5993 smb_fname_old, smb_fname_new);
5996 /****************************************************************************
5997 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5998 ****************************************************************************/
6000 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6001 struct smb_request *req,
6002 const char *pdata,
6003 int total_data,
6004 files_struct *fsp,
6005 struct smb_filename *smb_fname_src)
6007 bool overwrite;
6008 uint32_t len;
6009 char *newname = NULL;
6010 struct smb_filename *smb_fname_dst = NULL;
6011 NTSTATUS status = NT_STATUS_OK;
6012 TALLOC_CTX *ctx = talloc_tos();
6014 if (!fsp) {
6015 return NT_STATUS_INVALID_HANDLE;
6018 if (total_data < 20) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 overwrite = (CVAL(pdata,0) ? True : False);
6023 len = IVAL(pdata,16);
6025 if (len > (total_data - 20) || (len == 0)) {
6026 return NT_STATUS_INVALID_PARAMETER;
6029 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6030 &pdata[20], len, STR_TERMINATE,
6031 &status);
6032 if (!NT_STATUS_IS_OK(status)) {
6033 return status;
6036 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6037 newname));
6039 status = filename_convert(ctx,
6040 conn,
6041 req->flags2 & FLAGS2_DFS_PATHNAMES,
6042 newname,
6043 UCF_SAVE_LCOMP,
6044 NULL,
6045 &smb_fname_dst);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 return status;
6050 if (fsp->base_fsp) {
6051 /* newname must be a stream name. */
6052 if (newname[0] != ':') {
6053 return NT_STATUS_NOT_SUPPORTED;
6056 /* Create an smb_fname to call rename_internals_fsp() with. */
6057 status = create_synthetic_smb_fname(talloc_tos(),
6058 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6059 &smb_fname_dst);
6060 if (!NT_STATUS_IS_OK(status)) {
6061 goto out;
6065 * Set the original last component, since
6066 * rename_internals_fsp() requires it.
6068 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6069 newname);
6070 if (smb_fname_dst->original_lcomp == NULL) {
6071 status = NT_STATUS_NO_MEMORY;
6072 goto out;
6077 DEBUG(10,("smb2_file_rename_information: "
6078 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6079 fsp->fnum, fsp_str_dbg(fsp),
6080 smb_fname_str_dbg(smb_fname_dst)));
6081 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6082 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6083 overwrite);
6085 out:
6086 TALLOC_FREE(smb_fname_dst);
6087 return status;
6090 static NTSTATUS smb_file_link_information(connection_struct *conn,
6091 struct smb_request *req,
6092 const char *pdata,
6093 int total_data,
6094 files_struct *fsp,
6095 struct smb_filename *smb_fname_src)
6097 bool overwrite;
6098 uint32_t len;
6099 char *newname = NULL;
6100 struct smb_filename *smb_fname_dst = NULL;
6101 NTSTATUS status = NT_STATUS_OK;
6102 TALLOC_CTX *ctx = talloc_tos();
6104 if (!fsp) {
6105 return NT_STATUS_INVALID_HANDLE;
6108 if (total_data < 20) {
6109 return NT_STATUS_INVALID_PARAMETER;
6112 overwrite = (CVAL(pdata,0) ? true : false);
6113 len = IVAL(pdata,16);
6115 if (len > (total_data - 20) || (len == 0)) {
6116 return NT_STATUS_INVALID_PARAMETER;
6119 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6120 &pdata[20], len, STR_TERMINATE,
6121 &status);
6122 if (!NT_STATUS_IS_OK(status)) {
6123 return status;
6126 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6127 newname));
6129 status = filename_convert(ctx,
6130 conn,
6131 req->flags2 & FLAGS2_DFS_PATHNAMES,
6132 newname,
6133 UCF_SAVE_LCOMP,
6134 NULL,
6135 &smb_fname_dst);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 return status;
6140 if (fsp->base_fsp) {
6141 /* No stream names. */
6142 return NT_STATUS_NOT_SUPPORTED;
6145 DEBUG(10,("smb_file_link_information: "
6146 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6147 fsp->fnum, fsp_str_dbg(fsp),
6148 smb_fname_str_dbg(smb_fname_dst)));
6149 status = hardlink_internals(ctx,
6150 conn,
6151 req,
6152 overwrite,
6153 fsp->fsp_name,
6154 smb_fname_dst);
6156 TALLOC_FREE(smb_fname_dst);
6157 return status;
6160 /****************************************************************************
6161 Deal with SMB_FILE_RENAME_INFORMATION.
6162 ****************************************************************************/
6164 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6165 struct smb_request *req,
6166 const char *pdata,
6167 int total_data,
6168 files_struct *fsp,
6169 struct smb_filename *smb_fname_src)
6171 bool overwrite;
6172 uint32 root_fid;
6173 uint32 len;
6174 char *newname = NULL;
6175 struct smb_filename *smb_fname_dst = NULL;
6176 bool dest_has_wcard = False;
6177 NTSTATUS status = NT_STATUS_OK;
6178 char *p;
6179 TALLOC_CTX *ctx = talloc_tos();
6181 if (total_data < 13) {
6182 return NT_STATUS_INVALID_PARAMETER;
6185 overwrite = (CVAL(pdata,0) ? True : False);
6186 root_fid = IVAL(pdata,4);
6187 len = IVAL(pdata,8);
6189 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6190 return NT_STATUS_INVALID_PARAMETER;
6193 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6194 len, 0, &status,
6195 &dest_has_wcard);
6196 if (!NT_STATUS_IS_OK(status)) {
6197 return status;
6200 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6201 newname));
6203 status = resolve_dfspath_wcard(ctx, conn,
6204 req->flags2 & FLAGS2_DFS_PATHNAMES,
6205 newname,
6206 true,
6207 &newname,
6208 &dest_has_wcard);
6209 if (!NT_STATUS_IS_OK(status)) {
6210 return status;
6213 /* Check the new name has no '/' characters. */
6214 if (strchr_m(newname, '/')) {
6215 return NT_STATUS_NOT_SUPPORTED;
6218 if (fsp && fsp->base_fsp) {
6219 /* newname must be a stream name. */
6220 if (newname[0] != ':') {
6221 return NT_STATUS_NOT_SUPPORTED;
6224 /* Create an smb_fname to call rename_internals_fsp() with. */
6225 status = create_synthetic_smb_fname(talloc_tos(),
6226 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6227 &smb_fname_dst);
6228 if (!NT_STATUS_IS_OK(status)) {
6229 goto out;
6233 * Set the original last component, since
6234 * rename_internals_fsp() requires it.
6236 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6237 newname);
6238 if (smb_fname_dst->original_lcomp == NULL) {
6239 status = NT_STATUS_NO_MEMORY;
6240 goto out;
6243 } else {
6245 * Build up an smb_fname_dst based on the filename passed in.
6246 * We basically just strip off the last component, and put on
6247 * the newname instead.
6249 char *base_name = NULL;
6251 /* newname must *not* be a stream name. */
6252 if (newname[0] == ':') {
6253 return NT_STATUS_NOT_SUPPORTED;
6257 * Strip off the last component (filename) of the path passed
6258 * in.
6260 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6261 if (!base_name) {
6262 return NT_STATUS_NO_MEMORY;
6264 p = strrchr_m(base_name, '/');
6265 if (p) {
6266 p[1] = '\0';
6267 } else {
6268 base_name = talloc_strdup(ctx, "");
6269 if (!base_name) {
6270 return NT_STATUS_NO_MEMORY;
6273 /* Append the new name. */
6274 base_name = talloc_asprintf_append(base_name,
6275 "%s",
6276 newname);
6277 if (!base_name) {
6278 return NT_STATUS_NO_MEMORY;
6281 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6282 (UCF_SAVE_LCOMP |
6283 (dest_has_wcard ?
6284 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6285 0)));
6287 /* If an error we expect this to be
6288 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6290 if (!NT_STATUS_IS_OK(status)) {
6291 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6292 status)) {
6293 goto out;
6295 /* Create an smb_fname to call rename_internals_fsp() */
6296 status = create_synthetic_smb_fname(ctx,
6297 base_name, NULL,
6298 NULL,
6299 &smb_fname_dst);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 goto out;
6306 if (fsp) {
6307 DEBUG(10,("smb_file_rename_information: "
6308 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6309 fsp->fnum, fsp_str_dbg(fsp),
6310 smb_fname_str_dbg(smb_fname_dst)));
6311 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6312 overwrite);
6313 } else {
6314 DEBUG(10,("smb_file_rename_information: "
6315 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6316 smb_fname_str_dbg(smb_fname_src),
6317 smb_fname_str_dbg(smb_fname_dst)));
6318 status = rename_internals(ctx, conn, req, smb_fname_src,
6319 smb_fname_dst, 0, overwrite, false,
6320 dest_has_wcard,
6321 FILE_WRITE_ATTRIBUTES);
6323 out:
6324 TALLOC_FREE(smb_fname_dst);
6325 return status;
6328 /****************************************************************************
6329 Deal with SMB_SET_POSIX_ACL.
6330 ****************************************************************************/
6332 #if defined(HAVE_POSIX_ACLS)
6333 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6334 const char *pdata,
6335 int total_data,
6336 files_struct *fsp,
6337 const struct smb_filename *smb_fname)
6339 uint16 posix_acl_version;
6340 uint16 num_file_acls;
6341 uint16 num_def_acls;
6342 bool valid_file_acls = True;
6343 bool valid_def_acls = True;
6345 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6346 return NT_STATUS_INVALID_PARAMETER;
6348 posix_acl_version = SVAL(pdata,0);
6349 num_file_acls = SVAL(pdata,2);
6350 num_def_acls = SVAL(pdata,4);
6352 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6353 valid_file_acls = False;
6354 num_file_acls = 0;
6357 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6358 valid_def_acls = False;
6359 num_def_acls = 0;
6362 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6363 return NT_STATUS_INVALID_PARAMETER;
6366 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6367 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6368 return NT_STATUS_INVALID_PARAMETER;
6371 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6372 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6373 (unsigned int)num_file_acls,
6374 (unsigned int)num_def_acls));
6376 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6377 smb_fname->base_name, num_file_acls,
6378 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6379 return map_nt_error_from_unix(errno);
6382 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6383 smb_fname->base_name, &smb_fname->st, num_def_acls,
6384 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6385 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6386 return map_nt_error_from_unix(errno);
6388 return NT_STATUS_OK;
6390 #endif
6392 /****************************************************************************
6393 Deal with SMB_SET_POSIX_LOCK.
6394 ****************************************************************************/
6396 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6397 struct smb_request *req,
6398 const char *pdata,
6399 int total_data,
6400 files_struct *fsp)
6402 uint64_t count;
6403 uint64_t offset;
6404 uint64_t smblctx;
6405 bool blocking_lock = False;
6406 enum brl_type lock_type;
6408 NTSTATUS status = NT_STATUS_OK;
6410 if (fsp == NULL || fsp->fh->fd == -1) {
6411 return NT_STATUS_INVALID_HANDLE;
6414 if (total_data != POSIX_LOCK_DATA_SIZE) {
6415 return NT_STATUS_INVALID_PARAMETER;
6418 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6419 case POSIX_LOCK_TYPE_READ:
6420 lock_type = READ_LOCK;
6421 break;
6422 case POSIX_LOCK_TYPE_WRITE:
6423 /* Return the right POSIX-mappable error code for files opened read-only. */
6424 if (!fsp->can_write) {
6425 return NT_STATUS_INVALID_HANDLE;
6427 lock_type = WRITE_LOCK;
6428 break;
6429 case POSIX_LOCK_TYPE_UNLOCK:
6430 lock_type = UNLOCK_LOCK;
6431 break;
6432 default:
6433 return NT_STATUS_INVALID_PARAMETER;
6436 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6437 blocking_lock = False;
6438 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6439 blocking_lock = True;
6440 } else {
6441 return NT_STATUS_INVALID_PARAMETER;
6444 if (!lp_blocking_locks(SNUM(conn))) {
6445 blocking_lock = False;
6448 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6449 #if defined(HAVE_LONGLONG)
6450 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6451 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6452 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6453 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6454 #else /* HAVE_LONGLONG */
6455 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6456 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6457 #endif /* HAVE_LONGLONG */
6459 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6460 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6461 fsp_str_dbg(fsp),
6462 (unsigned int)lock_type,
6463 (unsigned long long)smblctx,
6464 (double)count,
6465 (double)offset ));
6467 if (lock_type == UNLOCK_LOCK) {
6468 status = do_unlock(req->sconn->msg_ctx,
6469 fsp,
6470 smblctx,
6471 count,
6472 offset,
6473 POSIX_LOCK);
6474 } else {
6475 uint64_t block_smblctx;
6477 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6478 fsp,
6479 smblctx,
6480 count,
6481 offset,
6482 lock_type,
6483 POSIX_LOCK,
6484 blocking_lock,
6485 &status,
6486 &block_smblctx,
6487 NULL);
6489 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6491 * A blocking lock was requested. Package up
6492 * this smb into a queued request and push it
6493 * onto the blocking lock queue.
6495 if(push_blocking_lock_request(br_lck,
6496 req,
6497 fsp,
6498 -1, /* infinite timeout. */
6500 smblctx,
6501 lock_type,
6502 POSIX_LOCK,
6503 offset,
6504 count,
6505 block_smblctx)) {
6506 TALLOC_FREE(br_lck);
6507 return status;
6510 TALLOC_FREE(br_lck);
6513 return status;
6516 /****************************************************************************
6517 Deal with SMB_SET_FILE_BASIC_INFO.
6518 ****************************************************************************/
6520 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6521 const char *pdata,
6522 int total_data,
6523 files_struct *fsp,
6524 const struct smb_filename *smb_fname)
6526 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6527 struct smb_file_time ft;
6528 uint32 dosmode = 0;
6529 NTSTATUS status = NT_STATUS_OK;
6531 ZERO_STRUCT(ft);
6533 if (total_data < 36) {
6534 return NT_STATUS_INVALID_PARAMETER;
6537 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6538 if (!NT_STATUS_IS_OK(status)) {
6539 return status;
6542 /* Set the attributes */
6543 dosmode = IVAL(pdata,32);
6544 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6545 if (!NT_STATUS_IS_OK(status)) {
6546 return status;
6549 /* create time */
6550 ft.create_time = interpret_long_date(pdata);
6552 /* access time */
6553 ft.atime = interpret_long_date(pdata+8);
6555 /* write time. */
6556 ft.mtime = interpret_long_date(pdata+16);
6558 /* change time. */
6559 ft.ctime = interpret_long_date(pdata+24);
6561 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6562 smb_fname_str_dbg(smb_fname)));
6564 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6565 true);
6568 /****************************************************************************
6569 Deal with SMB_INFO_STANDARD.
6570 ****************************************************************************/
6572 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6573 const char *pdata,
6574 int total_data,
6575 files_struct *fsp,
6576 const struct smb_filename *smb_fname)
6578 NTSTATUS status;
6579 struct smb_file_time ft;
6581 ZERO_STRUCT(ft);
6583 if (total_data < 12) {
6584 return NT_STATUS_INVALID_PARAMETER;
6587 /* create time */
6588 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6589 /* access time */
6590 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6591 /* write time */
6592 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6594 DEBUG(10,("smb_set_info_standard: file %s\n",
6595 smb_fname_str_dbg(smb_fname)));
6597 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 return status;
6602 return smb_set_file_time(conn,
6603 fsp,
6604 smb_fname,
6605 &ft,
6606 true);
6609 /****************************************************************************
6610 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6611 ****************************************************************************/
6613 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6614 struct smb_request *req,
6615 const char *pdata,
6616 int total_data,
6617 files_struct *fsp,
6618 struct smb_filename *smb_fname)
6620 uint64_t allocation_size = 0;
6621 NTSTATUS status = NT_STATUS_OK;
6622 files_struct *new_fsp = NULL;
6624 if (!VALID_STAT(smb_fname->st)) {
6625 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6628 if (total_data < 8) {
6629 return NT_STATUS_INVALID_PARAMETER;
6632 allocation_size = (uint64_t)IVAL(pdata,0);
6633 #ifdef LARGE_SMB_OFF_T
6634 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6635 #else /* LARGE_SMB_OFF_T */
6636 if (IVAL(pdata,4) != 0) {
6637 /* more than 32 bits? */
6638 return NT_STATUS_INVALID_PARAMETER;
6640 #endif /* LARGE_SMB_OFF_T */
6642 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6643 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6644 (double)allocation_size));
6646 if (allocation_size) {
6647 allocation_size = smb_roundup(conn, allocation_size);
6650 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6651 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6652 (double)allocation_size));
6654 if (fsp && fsp->fh->fd != -1) {
6655 /* Open file handle. */
6656 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6657 return NT_STATUS_ACCESS_DENIED;
6660 /* Only change if needed. */
6661 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6662 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6663 return map_nt_error_from_unix(errno);
6666 /* But always update the time. */
6668 * This is equivalent to a write. Ensure it's seen immediately
6669 * if there are no pending writes.
6671 trigger_write_time_update_immediate(fsp);
6672 return NT_STATUS_OK;
6675 /* Pathname or stat or directory file. */
6676 status = SMB_VFS_CREATE_FILE(
6677 conn, /* conn */
6678 req, /* req */
6679 0, /* root_dir_fid */
6680 smb_fname, /* fname */
6681 FILE_WRITE_DATA, /* access_mask */
6682 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6683 FILE_SHARE_DELETE),
6684 FILE_OPEN, /* create_disposition*/
6685 0, /* create_options */
6686 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6687 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6688 0, /* allocation_size */
6689 0, /* private_flags */
6690 NULL, /* sd */
6691 NULL, /* ea_list */
6692 &new_fsp, /* result */
6693 NULL); /* pinfo */
6695 if (!NT_STATUS_IS_OK(status)) {
6696 /* NB. We check for open_was_deferred in the caller. */
6697 return status;
6700 /* Only change if needed. */
6701 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6702 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6703 status = map_nt_error_from_unix(errno);
6704 close_file(req, new_fsp, NORMAL_CLOSE);
6705 return status;
6709 /* Changing the allocation size should set the last mod time. */
6711 * This is equivalent to a write. Ensure it's seen immediately
6712 * if there are no pending writes.
6714 trigger_write_time_update_immediate(new_fsp);
6716 close_file(req, new_fsp, NORMAL_CLOSE);
6717 return NT_STATUS_OK;
6720 /****************************************************************************
6721 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6722 ****************************************************************************/
6724 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6725 struct smb_request *req,
6726 const char *pdata,
6727 int total_data,
6728 files_struct *fsp,
6729 const struct smb_filename *smb_fname,
6730 bool fail_after_createfile)
6732 SMB_OFF_T size;
6734 if (total_data < 8) {
6735 return NT_STATUS_INVALID_PARAMETER;
6738 size = IVAL(pdata,0);
6739 #ifdef LARGE_SMB_OFF_T
6740 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6741 #else /* LARGE_SMB_OFF_T */
6742 if (IVAL(pdata,4) != 0) {
6743 /* more than 32 bits? */
6744 return NT_STATUS_INVALID_PARAMETER;
6746 #endif /* LARGE_SMB_OFF_T */
6747 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6748 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6749 (double)size));
6751 return smb_set_file_size(conn, req,
6752 fsp,
6753 smb_fname,
6754 &smb_fname->st,
6755 size,
6756 fail_after_createfile);
6759 /****************************************************************************
6760 Allow a UNIX info mknod.
6761 ****************************************************************************/
6763 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6764 const char *pdata,
6765 int total_data,
6766 const struct smb_filename *smb_fname)
6768 uint32 file_type = IVAL(pdata,56);
6769 #if defined(HAVE_MAKEDEV)
6770 uint32 dev_major = IVAL(pdata,60);
6771 uint32 dev_minor = IVAL(pdata,68);
6772 #endif
6773 SMB_DEV_T dev = (SMB_DEV_T)0;
6774 uint32 raw_unixmode = IVAL(pdata,84);
6775 NTSTATUS status;
6776 mode_t unixmode;
6778 if (total_data < 100) {
6779 return NT_STATUS_INVALID_PARAMETER;
6782 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6783 PERM_NEW_FILE, &unixmode);
6784 if (!NT_STATUS_IS_OK(status)) {
6785 return status;
6788 #if defined(HAVE_MAKEDEV)
6789 dev = makedev(dev_major, dev_minor);
6790 #endif
6792 switch (file_type) {
6793 #if defined(S_IFIFO)
6794 case UNIX_TYPE_FIFO:
6795 unixmode |= S_IFIFO;
6796 break;
6797 #endif
6798 #if defined(S_IFSOCK)
6799 case UNIX_TYPE_SOCKET:
6800 unixmode |= S_IFSOCK;
6801 break;
6802 #endif
6803 #if defined(S_IFCHR)
6804 case UNIX_TYPE_CHARDEV:
6805 unixmode |= S_IFCHR;
6806 break;
6807 #endif
6808 #if defined(S_IFBLK)
6809 case UNIX_TYPE_BLKDEV:
6810 unixmode |= S_IFBLK;
6811 break;
6812 #endif
6813 default:
6814 return NT_STATUS_INVALID_PARAMETER;
6817 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6818 "%.0f mode 0%o for file %s\n", (double)dev,
6819 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6821 /* Ok - do the mknod. */
6822 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6823 return map_nt_error_from_unix(errno);
6826 /* If any of the other "set" calls fail we
6827 * don't want to end up with a half-constructed mknod.
6830 if (lp_inherit_perms(SNUM(conn))) {
6831 char *parent;
6832 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6833 &parent, NULL)) {
6834 return NT_STATUS_NO_MEMORY;
6836 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6837 unixmode);
6838 TALLOC_FREE(parent);
6841 return NT_STATUS_OK;
6844 /****************************************************************************
6845 Deal with SMB_SET_FILE_UNIX_BASIC.
6846 ****************************************************************************/
6848 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6849 struct smb_request *req,
6850 const char *pdata,
6851 int total_data,
6852 files_struct *fsp,
6853 const struct smb_filename *smb_fname)
6855 struct smb_file_time ft;
6856 uint32 raw_unixmode;
6857 mode_t unixmode;
6858 SMB_OFF_T size = 0;
6859 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6860 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6861 NTSTATUS status = NT_STATUS_OK;
6862 bool delete_on_fail = False;
6863 enum perm_type ptype;
6864 files_struct *all_fsps = NULL;
6865 bool modify_mtime = true;
6866 struct file_id id;
6867 struct smb_filename *smb_fname_tmp = NULL;
6868 SMB_STRUCT_STAT sbuf;
6870 ZERO_STRUCT(ft);
6872 if (total_data < 100) {
6873 return NT_STATUS_INVALID_PARAMETER;
6876 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6877 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6878 size=IVAL(pdata,0); /* first 8 Bytes are size */
6879 #ifdef LARGE_SMB_OFF_T
6880 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6881 #else /* LARGE_SMB_OFF_T */
6882 if (IVAL(pdata,4) != 0) {
6883 /* more than 32 bits? */
6884 return NT_STATUS_INVALID_PARAMETER;
6886 #endif /* LARGE_SMB_OFF_T */
6889 ft.atime = interpret_long_date(pdata+24); /* access_time */
6890 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6891 set_owner = (uid_t)IVAL(pdata,40);
6892 set_grp = (gid_t)IVAL(pdata,48);
6893 raw_unixmode = IVAL(pdata,84);
6895 if (VALID_STAT(smb_fname->st)) {
6896 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6897 ptype = PERM_EXISTING_DIR;
6898 } else {
6899 ptype = PERM_EXISTING_FILE;
6901 } else {
6902 ptype = PERM_NEW_FILE;
6905 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6906 ptype, &unixmode);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 return status;
6911 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6912 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6913 smb_fname_str_dbg(smb_fname), (double)size,
6914 (unsigned int)set_owner, (unsigned int)set_grp,
6915 (int)raw_unixmode));
6917 sbuf = smb_fname->st;
6919 if (!VALID_STAT(sbuf)) {
6921 * The only valid use of this is to create character and block
6922 * devices, and named pipes. This is deprecated (IMHO) and
6923 * a new info level should be used for mknod. JRA.
6926 status = smb_unix_mknod(conn,
6927 pdata,
6928 total_data,
6929 smb_fname);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 return status;
6934 status = copy_smb_filename(talloc_tos(), smb_fname,
6935 &smb_fname_tmp);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 return status;
6940 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6941 status = map_nt_error_from_unix(errno);
6942 TALLOC_FREE(smb_fname_tmp);
6943 SMB_VFS_UNLINK(conn, smb_fname);
6944 return status;
6947 sbuf = smb_fname_tmp->st;
6948 smb_fname = smb_fname_tmp;
6950 /* Ensure we don't try and change anything else. */
6951 raw_unixmode = SMB_MODE_NO_CHANGE;
6952 size = get_file_size_stat(&sbuf);
6953 ft.atime = sbuf.st_ex_atime;
6954 ft.mtime = sbuf.st_ex_mtime;
6956 * We continue here as we might want to change the
6957 * owner uid/gid.
6959 delete_on_fail = True;
6962 #if 1
6963 /* Horrible backwards compatibility hack as an old server bug
6964 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6965 * */
6967 if (!size) {
6968 size = get_file_size_stat(&sbuf);
6970 #endif
6972 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 return status;
6978 * Deal with the UNIX specific mode set.
6981 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6983 "setting mode 0%o for file %s\n",
6984 (unsigned int)unixmode,
6985 smb_fname_str_dbg(smb_fname)));
6986 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6987 return map_nt_error_from_unix(errno);
6992 * Deal with the UNIX specific uid set.
6995 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6996 (sbuf.st_ex_uid != set_owner)) {
6997 int ret;
6999 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7000 "changing owner %u for path %s\n",
7001 (unsigned int)set_owner,
7002 smb_fname_str_dbg(smb_fname)));
7004 if (S_ISLNK(sbuf.st_ex_mode)) {
7005 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7006 set_owner, (gid_t)-1);
7007 } else {
7008 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7009 set_owner, (gid_t)-1);
7012 if (ret != 0) {
7013 status = map_nt_error_from_unix(errno);
7014 if (delete_on_fail) {
7015 SMB_VFS_UNLINK(conn, smb_fname);
7017 return status;
7022 * Deal with the UNIX specific gid set.
7025 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7026 (sbuf.st_ex_gid != set_grp)) {
7027 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7028 "changing group %u for file %s\n",
7029 (unsigned int)set_owner,
7030 smb_fname_str_dbg(smb_fname)));
7031 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7032 set_grp) != 0) {
7033 status = map_nt_error_from_unix(errno);
7034 if (delete_on_fail) {
7035 SMB_VFS_UNLINK(conn, smb_fname);
7037 return status;
7041 /* Deal with any size changes. */
7043 status = smb_set_file_size(conn, req,
7044 fsp,
7045 smb_fname,
7046 &sbuf,
7047 size,
7048 false);
7049 if (!NT_STATUS_IS_OK(status)) {
7050 return status;
7053 /* Deal with any time changes. */
7054 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7055 /* No change, don't cancel anything. */
7056 return status;
7059 id = vfs_file_id_from_sbuf(conn, &sbuf);
7060 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7061 all_fsps = file_find_di_next(all_fsps)) {
7063 * We're setting the time explicitly for UNIX.
7064 * Cancel any pending changes over all handles.
7066 all_fsps->update_write_time_on_close = false;
7067 TALLOC_FREE(all_fsps->update_write_time_event);
7071 * Override the "setting_write_time"
7072 * parameter here as it almost does what
7073 * we need. Just remember if we modified
7074 * mtime and send the notify ourselves.
7076 if (null_timespec(ft.mtime)) {
7077 modify_mtime = false;
7080 status = smb_set_file_time(conn,
7081 fsp,
7082 smb_fname,
7083 &ft,
7084 false);
7085 if (modify_mtime) {
7086 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7087 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7089 return status;
7092 /****************************************************************************
7093 Deal with SMB_SET_FILE_UNIX_INFO2.
7094 ****************************************************************************/
7096 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7097 struct smb_request *req,
7098 const char *pdata,
7099 int total_data,
7100 files_struct *fsp,
7101 const struct smb_filename *smb_fname)
7103 NTSTATUS status;
7104 uint32 smb_fflags;
7105 uint32 smb_fmask;
7107 if (total_data < 116) {
7108 return NT_STATUS_INVALID_PARAMETER;
7111 /* Start by setting all the fields that are common between UNIX_BASIC
7112 * and UNIX_INFO2.
7114 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7115 fsp, smb_fname);
7116 if (!NT_STATUS_IS_OK(status)) {
7117 return status;
7120 smb_fflags = IVAL(pdata, 108);
7121 smb_fmask = IVAL(pdata, 112);
7123 /* NB: We should only attempt to alter the file flags if the client
7124 * sends a non-zero mask.
7126 if (smb_fmask != 0) {
7127 int stat_fflags = 0;
7129 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7130 smb_fmask, &stat_fflags)) {
7131 /* Client asked to alter a flag we don't understand. */
7132 return NT_STATUS_INVALID_PARAMETER;
7135 if (fsp && fsp->fh->fd != -1) {
7136 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7137 return NT_STATUS_NOT_SUPPORTED;
7138 } else {
7139 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7140 stat_fflags) != 0) {
7141 return map_nt_error_from_unix(errno);
7146 /* XXX: need to add support for changing the create_time here. You
7147 * can do this for paths on Darwin with setattrlist(2). The right way
7148 * to hook this up is probably by extending the VFS utimes interface.
7151 return NT_STATUS_OK;
7154 /****************************************************************************
7155 Create a directory with POSIX semantics.
7156 ****************************************************************************/
7158 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7159 struct smb_request *req,
7160 char **ppdata,
7161 int total_data,
7162 struct smb_filename *smb_fname,
7163 int *pdata_return_size)
7165 NTSTATUS status = NT_STATUS_OK;
7166 uint32 raw_unixmode = 0;
7167 uint32 mod_unixmode = 0;
7168 mode_t unixmode = (mode_t)0;
7169 files_struct *fsp = NULL;
7170 uint16 info_level_return = 0;
7171 int info;
7172 char *pdata = *ppdata;
7174 if (total_data < 18) {
7175 return NT_STATUS_INVALID_PARAMETER;
7178 raw_unixmode = IVAL(pdata,8);
7179 /* Next 4 bytes are not yet defined. */
7181 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7182 PERM_NEW_DIR, &unixmode);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 return status;
7187 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7189 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7190 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7192 status = SMB_VFS_CREATE_FILE(
7193 conn, /* conn */
7194 req, /* req */
7195 0, /* root_dir_fid */
7196 smb_fname, /* fname */
7197 FILE_READ_ATTRIBUTES, /* access_mask */
7198 FILE_SHARE_NONE, /* share_access */
7199 FILE_CREATE, /* create_disposition*/
7200 FILE_DIRECTORY_FILE, /* create_options */
7201 mod_unixmode, /* file_attributes */
7202 0, /* oplock_request */
7203 0, /* allocation_size */
7204 0, /* private_flags */
7205 NULL, /* sd */
7206 NULL, /* ea_list */
7207 &fsp, /* result */
7208 &info); /* pinfo */
7210 if (NT_STATUS_IS_OK(status)) {
7211 close_file(req, fsp, NORMAL_CLOSE);
7214 info_level_return = SVAL(pdata,16);
7216 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7217 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7218 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7219 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7220 } else {
7221 *pdata_return_size = 12;
7224 /* Realloc the data size */
7225 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7226 if (*ppdata == NULL) {
7227 *pdata_return_size = 0;
7228 return NT_STATUS_NO_MEMORY;
7230 pdata = *ppdata;
7232 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7233 SSVAL(pdata,2,0); /* No fnum. */
7234 SIVAL(pdata,4,info); /* Was directory created. */
7236 switch (info_level_return) {
7237 case SMB_QUERY_FILE_UNIX_BASIC:
7238 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7239 SSVAL(pdata,10,0); /* Padding. */
7240 store_file_unix_basic(conn, pdata + 12, fsp,
7241 &smb_fname->st);
7242 break;
7243 case SMB_QUERY_FILE_UNIX_INFO2:
7244 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7245 SSVAL(pdata,10,0); /* Padding. */
7246 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7247 &smb_fname->st);
7248 break;
7249 default:
7250 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7251 SSVAL(pdata,10,0); /* Padding. */
7252 break;
7255 return status;
7258 /****************************************************************************
7259 Open/Create a file with POSIX semantics.
7260 ****************************************************************************/
7262 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7263 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7265 static NTSTATUS smb_posix_open(connection_struct *conn,
7266 struct smb_request *req,
7267 char **ppdata,
7268 int total_data,
7269 struct smb_filename *smb_fname,
7270 int *pdata_return_size)
7272 bool extended_oplock_granted = False;
7273 char *pdata = *ppdata;
7274 uint32 flags = 0;
7275 uint32 wire_open_mode = 0;
7276 uint32 raw_unixmode = 0;
7277 uint32 mod_unixmode = 0;
7278 uint32 create_disp = 0;
7279 uint32 access_mask = 0;
7280 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7281 NTSTATUS status = NT_STATUS_OK;
7282 mode_t unixmode = (mode_t)0;
7283 files_struct *fsp = NULL;
7284 int oplock_request = 0;
7285 int info = 0;
7286 uint16 info_level_return = 0;
7288 if (total_data < 18) {
7289 return NT_STATUS_INVALID_PARAMETER;
7292 flags = IVAL(pdata,0);
7293 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7294 if (oplock_request) {
7295 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7298 wire_open_mode = IVAL(pdata,4);
7300 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7301 return smb_posix_mkdir(conn, req,
7302 ppdata,
7303 total_data,
7304 smb_fname,
7305 pdata_return_size);
7308 switch (wire_open_mode & SMB_ACCMODE) {
7309 case SMB_O_RDONLY:
7310 access_mask = SMB_O_RDONLY_MAPPING;
7311 break;
7312 case SMB_O_WRONLY:
7313 access_mask = SMB_O_WRONLY_MAPPING;
7314 break;
7315 case SMB_O_RDWR:
7316 access_mask = (SMB_O_RDONLY_MAPPING|
7317 SMB_O_WRONLY_MAPPING);
7318 break;
7319 default:
7320 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7321 (unsigned int)wire_open_mode ));
7322 return NT_STATUS_INVALID_PARAMETER;
7325 wire_open_mode &= ~SMB_ACCMODE;
7327 /* First take care of O_CREAT|O_EXCL interactions. */
7328 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7329 case (SMB_O_CREAT | SMB_O_EXCL):
7330 /* File exists fail. File not exist create. */
7331 create_disp = FILE_CREATE;
7332 break;
7333 case SMB_O_CREAT:
7334 /* File exists open. File not exist create. */
7335 create_disp = FILE_OPEN_IF;
7336 break;
7337 case 0:
7338 /* File exists open. File not exist fail. */
7339 create_disp = FILE_OPEN;
7340 break;
7341 case SMB_O_EXCL:
7342 /* O_EXCL on its own without O_CREAT is undefined. */
7343 default:
7344 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7345 (unsigned int)wire_open_mode ));
7346 return NT_STATUS_INVALID_PARAMETER;
7349 /* Next factor in the effects of O_TRUNC. */
7350 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7352 if (wire_open_mode & SMB_O_TRUNC) {
7353 switch (create_disp) {
7354 case FILE_CREATE:
7355 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7356 /* Leave create_disp alone as
7357 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7359 /* File exists fail. File not exist create. */
7360 break;
7361 case FILE_OPEN_IF:
7362 /* SMB_O_CREAT | SMB_O_TRUNC */
7363 /* File exists overwrite. File not exist create. */
7364 create_disp = FILE_OVERWRITE_IF;
7365 break;
7366 case FILE_OPEN:
7367 /* SMB_O_TRUNC */
7368 /* File exists overwrite. File not exist fail. */
7369 create_disp = FILE_OVERWRITE;
7370 break;
7371 default:
7372 /* Cannot get here. */
7373 smb_panic("smb_posix_open: logic error");
7374 return NT_STATUS_INVALID_PARAMETER;
7378 raw_unixmode = IVAL(pdata,8);
7379 /* Next 4 bytes are not yet defined. */
7381 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7382 (VALID_STAT(smb_fname->st) ?
7383 PERM_EXISTING_FILE : PERM_NEW_FILE),
7384 &unixmode);
7386 if (!NT_STATUS_IS_OK(status)) {
7387 return status;
7390 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7392 if (wire_open_mode & SMB_O_SYNC) {
7393 create_options |= FILE_WRITE_THROUGH;
7395 if (wire_open_mode & SMB_O_APPEND) {
7396 access_mask |= FILE_APPEND_DATA;
7398 if (wire_open_mode & SMB_O_DIRECT) {
7399 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7402 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7403 VALID_STAT_OF_DIR(smb_fname->st)) {
7404 if (access_mask != SMB_O_RDONLY_MAPPING) {
7405 return NT_STATUS_FILE_IS_A_DIRECTORY;
7407 create_options &= ~FILE_NON_DIRECTORY_FILE;
7408 create_options |= FILE_DIRECTORY_FILE;
7411 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7412 smb_fname_str_dbg(smb_fname),
7413 (unsigned int)wire_open_mode,
7414 (unsigned int)unixmode ));
7416 status = SMB_VFS_CREATE_FILE(
7417 conn, /* conn */
7418 req, /* req */
7419 0, /* root_dir_fid */
7420 smb_fname, /* fname */
7421 access_mask, /* access_mask */
7422 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7423 FILE_SHARE_DELETE),
7424 create_disp, /* create_disposition*/
7425 create_options, /* create_options */
7426 mod_unixmode, /* file_attributes */
7427 oplock_request, /* oplock_request */
7428 0, /* allocation_size */
7429 0, /* private_flags */
7430 NULL, /* sd */
7431 NULL, /* ea_list */
7432 &fsp, /* result */
7433 &info); /* pinfo */
7435 if (!NT_STATUS_IS_OK(status)) {
7436 return status;
7439 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7440 extended_oplock_granted = True;
7443 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7444 extended_oplock_granted = True;
7447 info_level_return = SVAL(pdata,16);
7449 /* Allocate the correct return size. */
7451 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7452 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7453 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7454 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7455 } else {
7456 *pdata_return_size = 12;
7459 /* Realloc the data size */
7460 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7461 if (*ppdata == NULL) {
7462 close_file(req, fsp, ERROR_CLOSE);
7463 *pdata_return_size = 0;
7464 return NT_STATUS_NO_MEMORY;
7466 pdata = *ppdata;
7468 if (extended_oplock_granted) {
7469 if (flags & REQUEST_BATCH_OPLOCK) {
7470 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7471 } else {
7472 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7474 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7475 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7476 } else {
7477 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7480 SSVAL(pdata,2,fsp->fnum);
7481 SIVAL(pdata,4,info); /* Was file created etc. */
7483 switch (info_level_return) {
7484 case SMB_QUERY_FILE_UNIX_BASIC:
7485 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7486 SSVAL(pdata,10,0); /* padding. */
7487 store_file_unix_basic(conn, pdata + 12, fsp,
7488 &smb_fname->st);
7489 break;
7490 case SMB_QUERY_FILE_UNIX_INFO2:
7491 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7492 SSVAL(pdata,10,0); /* padding. */
7493 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7494 &smb_fname->st);
7495 break;
7496 default:
7497 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7498 SSVAL(pdata,10,0); /* padding. */
7499 break;
7501 return NT_STATUS_OK;
7504 /****************************************************************************
7505 Delete a file with POSIX semantics.
7506 ****************************************************************************/
7508 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7509 struct smb_request *req,
7510 const char *pdata,
7511 int total_data,
7512 struct smb_filename *smb_fname)
7514 NTSTATUS status = NT_STATUS_OK;
7515 files_struct *fsp = NULL;
7516 uint16 flags = 0;
7517 char del = 1;
7518 int info = 0;
7519 int create_options = 0;
7520 int i;
7521 struct share_mode_lock *lck = NULL;
7523 if (total_data < 2) {
7524 return NT_STATUS_INVALID_PARAMETER;
7527 flags = SVAL(pdata,0);
7529 if (!VALID_STAT(smb_fname->st)) {
7530 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7533 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7534 !VALID_STAT_OF_DIR(smb_fname->st)) {
7535 return NT_STATUS_NOT_A_DIRECTORY;
7538 DEBUG(10,("smb_posix_unlink: %s %s\n",
7539 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7540 smb_fname_str_dbg(smb_fname)));
7542 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7543 create_options |= FILE_DIRECTORY_FILE;
7546 status = SMB_VFS_CREATE_FILE(
7547 conn, /* conn */
7548 req, /* req */
7549 0, /* root_dir_fid */
7550 smb_fname, /* fname */
7551 DELETE_ACCESS, /* access_mask */
7552 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7553 FILE_SHARE_DELETE),
7554 FILE_OPEN, /* create_disposition*/
7555 create_options, /* create_options */
7556 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7557 0, /* oplock_request */
7558 0, /* allocation_size */
7559 0, /* private_flags */
7560 NULL, /* sd */
7561 NULL, /* ea_list */
7562 &fsp, /* result */
7563 &info); /* pinfo */
7565 if (!NT_STATUS_IS_OK(status)) {
7566 return status;
7570 * Don't lie to client. If we can't really delete due to
7571 * non-POSIX opens return SHARING_VIOLATION.
7574 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7575 NULL);
7576 if (lck == NULL) {
7577 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7578 "lock for file %s\n", fsp_str_dbg(fsp)));
7579 close_file(req, fsp, NORMAL_CLOSE);
7580 return NT_STATUS_INVALID_PARAMETER;
7584 * See if others still have the file open. If this is the case, then
7585 * don't delete. If all opens are POSIX delete we can set the delete
7586 * on close disposition.
7588 for (i=0; i<lck->num_share_modes; i++) {
7589 struct share_mode_entry *e = &lck->share_modes[i];
7590 if (is_valid_share_mode_entry(e)) {
7591 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7592 continue;
7594 /* Fail with sharing violation. */
7595 close_file(req, fsp, NORMAL_CLOSE);
7596 TALLOC_FREE(lck);
7597 return NT_STATUS_SHARING_VIOLATION;
7602 * Set the delete on close.
7604 status = smb_set_file_disposition_info(conn,
7605 &del,
7607 fsp,
7608 smb_fname);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 close_file(req, fsp, NORMAL_CLOSE);
7612 TALLOC_FREE(lck);
7613 return status;
7615 TALLOC_FREE(lck);
7616 return close_file(req, fsp, NORMAL_CLOSE);
7619 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7620 struct smb_request *req,
7621 TALLOC_CTX *mem_ctx,
7622 uint16_t info_level,
7623 files_struct *fsp,
7624 struct smb_filename *smb_fname,
7625 char **ppdata, int total_data,
7626 int *ret_data_size)
7628 char *pdata = *ppdata;
7629 NTSTATUS status = NT_STATUS_OK;
7630 int data_return_size = 0;
7632 *ret_data_size = 0;
7634 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7635 return NT_STATUS_INVALID_LEVEL;
7638 if (!CAN_WRITE(conn)) {
7639 /* Allow POSIX opens. The open path will deny
7640 * any non-readonly opens. */
7641 if (info_level != SMB_POSIX_PATH_OPEN) {
7642 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7646 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7647 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7648 fsp ? fsp->fnum : -1, info_level, total_data));
7650 switch (info_level) {
7652 case SMB_INFO_STANDARD:
7654 status = smb_set_info_standard(conn,
7655 pdata,
7656 total_data,
7657 fsp,
7658 smb_fname);
7659 break;
7662 case SMB_INFO_SET_EA:
7664 status = smb_info_set_ea(conn,
7665 pdata,
7666 total_data,
7667 fsp,
7668 smb_fname);
7669 break;
7672 case SMB_SET_FILE_BASIC_INFO:
7673 case SMB_FILE_BASIC_INFORMATION:
7675 status = smb_set_file_basic_info(conn,
7676 pdata,
7677 total_data,
7678 fsp,
7679 smb_fname);
7680 break;
7683 case SMB_FILE_ALLOCATION_INFORMATION:
7684 case SMB_SET_FILE_ALLOCATION_INFO:
7686 status = smb_set_file_allocation_info(conn, req,
7687 pdata,
7688 total_data,
7689 fsp,
7690 smb_fname);
7691 break;
7694 case SMB_FILE_END_OF_FILE_INFORMATION:
7695 case SMB_SET_FILE_END_OF_FILE_INFO:
7698 * XP/Win7 both fail after the createfile with
7699 * SMB_SET_FILE_END_OF_FILE_INFO but not
7700 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7701 * The level is known here, so pass it down
7702 * appropriately.
7704 bool should_fail =
7705 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7707 status = smb_set_file_end_of_file_info(conn, req,
7708 pdata,
7709 total_data,
7710 fsp,
7711 smb_fname,
7712 should_fail);
7713 break;
7716 case SMB_FILE_DISPOSITION_INFORMATION:
7717 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7719 #if 0
7720 /* JRA - We used to just ignore this on a path ?
7721 * Shouldn't this be invalid level on a pathname
7722 * based call ?
7724 if (tran_call != TRANSACT2_SETFILEINFO) {
7725 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7727 #endif
7728 status = smb_set_file_disposition_info(conn,
7729 pdata,
7730 total_data,
7731 fsp,
7732 smb_fname);
7733 break;
7736 case SMB_FILE_POSITION_INFORMATION:
7738 status = smb_file_position_information(conn,
7739 pdata,
7740 total_data,
7741 fsp);
7742 break;
7745 case SMB_FILE_FULL_EA_INFORMATION:
7747 status = smb_set_file_full_ea_info(conn,
7748 pdata,
7749 total_data,
7750 fsp);
7751 break;
7754 /* From tridge Samba4 :
7755 * MODE_INFORMATION in setfileinfo (I have no
7756 * idea what "mode information" on a file is - it takes a value of 0,
7757 * 2, 4 or 6. What could it be?).
7760 case SMB_FILE_MODE_INFORMATION:
7762 status = smb_file_mode_information(conn,
7763 pdata,
7764 total_data);
7765 break;
7769 * CIFS UNIX extensions.
7772 case SMB_SET_FILE_UNIX_BASIC:
7774 status = smb_set_file_unix_basic(conn, req,
7775 pdata,
7776 total_data,
7777 fsp,
7778 smb_fname);
7779 break;
7782 case SMB_SET_FILE_UNIX_INFO2:
7784 status = smb_set_file_unix_info2(conn, req,
7785 pdata,
7786 total_data,
7787 fsp,
7788 smb_fname);
7789 break;
7792 case SMB_SET_FILE_UNIX_LINK:
7794 if (fsp) {
7795 /* We must have a pathname for this. */
7796 return NT_STATUS_INVALID_LEVEL;
7798 status = smb_set_file_unix_link(conn, req, pdata,
7799 total_data, smb_fname);
7800 break;
7803 case SMB_SET_FILE_UNIX_HLINK:
7805 if (fsp) {
7806 /* We must have a pathname for this. */
7807 return NT_STATUS_INVALID_LEVEL;
7809 status = smb_set_file_unix_hlink(conn, req,
7810 pdata, total_data,
7811 smb_fname);
7812 break;
7815 case SMB_FILE_RENAME_INFORMATION:
7817 status = smb_file_rename_information(conn, req,
7818 pdata, total_data,
7819 fsp, smb_fname);
7820 break;
7823 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7825 /* SMB2 rename information. */
7826 status = smb2_file_rename_information(conn, req,
7827 pdata, total_data,
7828 fsp, smb_fname);
7829 break;
7832 case SMB_FILE_LINK_INFORMATION:
7834 status = smb_file_link_information(conn, req,
7835 pdata, total_data,
7836 fsp, smb_fname);
7837 break;
7840 #if defined(HAVE_POSIX_ACLS)
7841 case SMB_SET_POSIX_ACL:
7843 status = smb_set_posix_acl(conn,
7844 pdata,
7845 total_data,
7846 fsp,
7847 smb_fname);
7848 break;
7850 #endif
7852 case SMB_SET_POSIX_LOCK:
7854 if (!fsp) {
7855 return NT_STATUS_INVALID_LEVEL;
7857 status = smb_set_posix_lock(conn, req,
7858 pdata, total_data, fsp);
7859 break;
7862 case SMB_POSIX_PATH_OPEN:
7864 if (fsp) {
7865 /* We must have a pathname for this. */
7866 return NT_STATUS_INVALID_LEVEL;
7869 status = smb_posix_open(conn, req,
7870 ppdata,
7871 total_data,
7872 smb_fname,
7873 &data_return_size);
7874 break;
7877 case SMB_POSIX_PATH_UNLINK:
7879 if (fsp) {
7880 /* We must have a pathname for this. */
7881 return NT_STATUS_INVALID_LEVEL;
7884 status = smb_posix_unlink(conn, req,
7885 pdata,
7886 total_data,
7887 smb_fname);
7888 break;
7891 default:
7892 return NT_STATUS_INVALID_LEVEL;
7895 if (!NT_STATUS_IS_OK(status)) {
7896 return status;
7899 *ret_data_size = data_return_size;
7900 return NT_STATUS_OK;
7903 /****************************************************************************
7904 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7905 ****************************************************************************/
7907 static void call_trans2setfilepathinfo(connection_struct *conn,
7908 struct smb_request *req,
7909 unsigned int tran_call,
7910 char **pparams, int total_params,
7911 char **ppdata, int total_data,
7912 unsigned int max_data_bytes)
7914 char *params = *pparams;
7915 char *pdata = *ppdata;
7916 uint16 info_level;
7917 struct smb_filename *smb_fname = NULL;
7918 files_struct *fsp = NULL;
7919 NTSTATUS status = NT_STATUS_OK;
7920 int data_return_size = 0;
7922 if (!params) {
7923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7924 return;
7927 if (tran_call == TRANSACT2_SETFILEINFO) {
7928 if (total_params < 4) {
7929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930 return;
7933 fsp = file_fsp(req, SVAL(params,0));
7934 /* Basic check for non-null fsp. */
7935 if (!check_fsp_open(conn, req, fsp)) {
7936 return;
7938 info_level = SVAL(params,2);
7940 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7941 &smb_fname);
7942 if (!NT_STATUS_IS_OK(status)) {
7943 reply_nterror(req, status);
7944 return;
7947 if(fsp->fh->fd == -1) {
7949 * This is actually a SETFILEINFO on a directory
7950 * handle (returned from an NT SMB). NT5.0 seems
7951 * to do this call. JRA.
7953 if (INFO_LEVEL_IS_UNIX(info_level)) {
7954 /* Always do lstat for UNIX calls. */
7955 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7956 DEBUG(3,("call_trans2setfilepathinfo: "
7957 "SMB_VFS_LSTAT of %s failed "
7958 "(%s)\n",
7959 smb_fname_str_dbg(smb_fname),
7960 strerror(errno)));
7961 reply_nterror(req, map_nt_error_from_unix(errno));
7962 return;
7964 } else {
7965 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7966 DEBUG(3,("call_trans2setfilepathinfo: "
7967 "fileinfo of %s failed (%s)\n",
7968 smb_fname_str_dbg(smb_fname),
7969 strerror(errno)));
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7971 return;
7974 } else if (fsp->print_file) {
7976 * Doing a DELETE_ON_CLOSE should cancel a print job.
7978 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7979 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7981 DEBUG(3,("call_trans2setfilepathinfo: "
7982 "Cancelling print job (%s)\n",
7983 fsp_str_dbg(fsp)));
7985 SSVAL(params,0,0);
7986 send_trans2_replies(conn, req, params, 2,
7987 *ppdata, 0,
7988 max_data_bytes);
7989 return;
7990 } else {
7991 reply_nterror(req,
7992 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7993 return;
7995 } else {
7997 * Original code - this is an open file.
7999 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8000 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8001 "of fnum %d failed (%s)\n", fsp->fnum,
8002 strerror(errno)));
8003 reply_nterror(req, map_nt_error_from_unix(errno));
8004 return;
8007 } else {
8008 char *fname = NULL;
8010 /* set path info */
8011 if (total_params < 7) {
8012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8013 return;
8016 info_level = SVAL(params,0);
8017 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8018 total_params - 6, STR_TERMINATE,
8019 &status);
8020 if (!NT_STATUS_IS_OK(status)) {
8021 reply_nterror(req, status);
8022 return;
8025 status = filename_convert(req, conn,
8026 req->flags2 & FLAGS2_DFS_PATHNAMES,
8027 fname,
8029 NULL,
8030 &smb_fname);
8031 if (!NT_STATUS_IS_OK(status)) {
8032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8033 reply_botherror(req,
8034 NT_STATUS_PATH_NOT_COVERED,
8035 ERRSRV, ERRbadpath);
8036 return;
8038 reply_nterror(req, status);
8039 return;
8042 if (INFO_LEVEL_IS_UNIX(info_level)) {
8044 * For CIFS UNIX extensions the target name may not exist.
8047 /* Always do lstat for UNIX calls. */
8048 SMB_VFS_LSTAT(conn, smb_fname);
8050 } else if (!VALID_STAT(smb_fname->st) &&
8051 SMB_VFS_STAT(conn, smb_fname)) {
8052 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8053 "%s failed (%s)\n",
8054 smb_fname_str_dbg(smb_fname),
8055 strerror(errno)));
8056 reply_nterror(req, map_nt_error_from_unix(errno));
8057 return;
8061 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8062 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8063 fsp ? fsp->fnum : -1, info_level,total_data));
8065 /* Realloc the parameter size */
8066 *pparams = (char *)SMB_REALLOC(*pparams,2);
8067 if (*pparams == NULL) {
8068 reply_nterror(req, NT_STATUS_NO_MEMORY);
8069 return;
8071 params = *pparams;
8073 SSVAL(params,0,0);
8075 status = smbd_do_setfilepathinfo(conn, req, req,
8076 info_level,
8077 fsp,
8078 smb_fname,
8079 ppdata, total_data,
8080 &data_return_size);
8081 if (!NT_STATUS_IS_OK(status)) {
8082 if (open_was_deferred(req->sconn, req->mid)) {
8083 /* We have re-scheduled this call. */
8084 return;
8086 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8087 /* We have re-scheduled this call. */
8088 return;
8090 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8091 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8092 ERRSRV, ERRbadpath);
8093 return;
8095 if (info_level == SMB_POSIX_PATH_OPEN) {
8096 reply_openerror(req, status);
8097 return;
8100 reply_nterror(req, status);
8101 return;
8104 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8105 max_data_bytes);
8107 return;
8110 /****************************************************************************
8111 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8112 ****************************************************************************/
8114 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8115 char **pparams, int total_params,
8116 char **ppdata, int total_data,
8117 unsigned int max_data_bytes)
8119 struct smb_filename *smb_dname = NULL;
8120 char *params = *pparams;
8121 char *pdata = *ppdata;
8122 char *directory = NULL;
8123 NTSTATUS status = NT_STATUS_OK;
8124 struct ea_list *ea_list = NULL;
8125 TALLOC_CTX *ctx = talloc_tos();
8127 if (!CAN_WRITE(conn)) {
8128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8129 return;
8132 if (total_params < 5) {
8133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8134 return;
8137 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8138 total_params - 4, STR_TERMINATE,
8139 &status);
8140 if (!NT_STATUS_IS_OK(status)) {
8141 reply_nterror(req, status);
8142 return;
8145 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8147 status = filename_convert(ctx,
8148 conn,
8149 req->flags2 & FLAGS2_DFS_PATHNAMES,
8150 directory,
8152 NULL,
8153 &smb_dname);
8155 if (!NT_STATUS_IS_OK(status)) {
8156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8157 reply_botherror(req,
8158 NT_STATUS_PATH_NOT_COVERED,
8159 ERRSRV, ERRbadpath);
8160 return;
8162 reply_nterror(req, status);
8163 return;
8167 * OS/2 workplace shell seems to send SET_EA requests of "null"
8168 * length (4 bytes containing IVAL 4).
8169 * They seem to have no effect. Bug #3212. JRA.
8172 if (total_data && (total_data != 4)) {
8173 /* Any data in this call is an EA list. */
8174 if (total_data < 10) {
8175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8176 goto out;
8179 if (IVAL(pdata,0) > total_data) {
8180 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8181 IVAL(pdata,0), (unsigned int)total_data));
8182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8183 goto out;
8186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8187 total_data - 4);
8188 if (!ea_list) {
8189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8190 goto out;
8193 if (!lp_ea_support(SNUM(conn))) {
8194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8195 goto out;
8198 /* If total_data == 4 Windows doesn't care what values
8199 * are placed in that field, it just ignores them.
8200 * The System i QNTC IBM SMB client puts bad values here,
8201 * so ignore them. */
8203 status = create_directory(conn, req, smb_dname);
8205 if (!NT_STATUS_IS_OK(status)) {
8206 reply_nterror(req, status);
8207 goto out;
8210 /* Try and set any given EA. */
8211 if (ea_list) {
8212 status = set_ea(conn, NULL, smb_dname, ea_list);
8213 if (!NT_STATUS_IS_OK(status)) {
8214 reply_nterror(req, status);
8215 goto out;
8219 /* Realloc the parameter and data sizes */
8220 *pparams = (char *)SMB_REALLOC(*pparams,2);
8221 if(*pparams == NULL) {
8222 reply_nterror(req, NT_STATUS_NO_MEMORY);
8223 goto out;
8225 params = *pparams;
8227 SSVAL(params,0,0);
8229 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8231 out:
8232 TALLOC_FREE(smb_dname);
8233 return;
8236 /****************************************************************************
8237 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8238 We don't actually do this - we just send a null response.
8239 ****************************************************************************/
8241 static void call_trans2findnotifyfirst(connection_struct *conn,
8242 struct smb_request *req,
8243 char **pparams, int total_params,
8244 char **ppdata, int total_data,
8245 unsigned int max_data_bytes)
8247 char *params = *pparams;
8248 uint16 info_level;
8250 if (total_params < 6) {
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8252 return;
8255 info_level = SVAL(params,4);
8256 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8258 switch (info_level) {
8259 case 1:
8260 case 2:
8261 break;
8262 default:
8263 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8264 return;
8267 /* Realloc the parameter and data sizes */
8268 *pparams = (char *)SMB_REALLOC(*pparams,6);
8269 if (*pparams == NULL) {
8270 reply_nterror(req, NT_STATUS_NO_MEMORY);
8271 return;
8273 params = *pparams;
8275 SSVAL(params,0,fnf_handle);
8276 SSVAL(params,2,0); /* No changes */
8277 SSVAL(params,4,0); /* No EA errors */
8279 fnf_handle++;
8281 if(fnf_handle == 0)
8282 fnf_handle = 257;
8284 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8286 return;
8289 /****************************************************************************
8290 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8291 changes). Currently this does nothing.
8292 ****************************************************************************/
8294 static void call_trans2findnotifynext(connection_struct *conn,
8295 struct smb_request *req,
8296 char **pparams, int total_params,
8297 char **ppdata, int total_data,
8298 unsigned int max_data_bytes)
8300 char *params = *pparams;
8302 DEBUG(3,("call_trans2findnotifynext\n"));
8304 /* Realloc the parameter and data sizes */
8305 *pparams = (char *)SMB_REALLOC(*pparams,4);
8306 if (*pparams == NULL) {
8307 reply_nterror(req, NT_STATUS_NO_MEMORY);
8308 return;
8310 params = *pparams;
8312 SSVAL(params,0,0); /* No changes */
8313 SSVAL(params,2,0); /* No EA errors */
8315 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8317 return;
8320 /****************************************************************************
8321 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8322 ****************************************************************************/
8324 static void call_trans2getdfsreferral(connection_struct *conn,
8325 struct smb_request *req,
8326 char **pparams, int total_params,
8327 char **ppdata, int total_data,
8328 unsigned int max_data_bytes)
8330 char *params = *pparams;
8331 char *pathname = NULL;
8332 int reply_size = 0;
8333 int max_referral_level;
8334 NTSTATUS status = NT_STATUS_OK;
8335 TALLOC_CTX *ctx = talloc_tos();
8337 DEBUG(10,("call_trans2getdfsreferral\n"));
8339 if (total_params < 3) {
8340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8341 return;
8344 max_referral_level = SVAL(params,0);
8346 if(!lp_host_msdfs()) {
8347 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8348 return;
8351 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8352 total_params - 2, STR_TERMINATE);
8353 if (!pathname) {
8354 reply_nterror(req, NT_STATUS_NOT_FOUND);
8355 return;
8357 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8358 ppdata,&status)) < 0) {
8359 reply_nterror(req, status);
8360 return;
8363 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8364 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8365 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8367 return;
8370 #define LMCAT_SPL 0x53
8371 #define LMFUNC_GETJOBID 0x60
8373 /****************************************************************************
8374 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8375 ****************************************************************************/
8377 static void call_trans2ioctl(connection_struct *conn,
8378 struct smb_request *req,
8379 char **pparams, int total_params,
8380 char **ppdata, int total_data,
8381 unsigned int max_data_bytes)
8383 char *pdata = *ppdata;
8384 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8386 /* check for an invalid fid before proceeding */
8388 if (!fsp) {
8389 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8390 return;
8393 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8394 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8395 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8396 if (*ppdata == NULL) {
8397 reply_nterror(req, NT_STATUS_NO_MEMORY);
8398 return;
8400 pdata = *ppdata;
8402 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8403 CAN ACCEPT THIS IN UNICODE. JRA. */
8405 /* Job number */
8406 if (fsp->print_file) {
8407 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8408 } else {
8409 SSVAL(pdata, 0, 0);
8411 srvstr_push(pdata, req->flags2, pdata + 2,
8412 lp_netbios_name(), 15,
8413 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8414 srvstr_push(pdata, req->flags2, pdata+18,
8415 lp_servicename(SNUM(conn)), 13,
8416 STR_ASCII|STR_TERMINATE); /* Service name */
8417 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8418 max_data_bytes);
8419 return;
8422 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8423 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8426 /****************************************************************************
8427 Reply to a SMBfindclose (stop trans2 directory search).
8428 ****************************************************************************/
8430 void reply_findclose(struct smb_request *req)
8432 int dptr_num;
8433 struct smbd_server_connection *sconn = req->sconn;
8435 START_PROFILE(SMBfindclose);
8437 if (req->wct < 1) {
8438 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8439 END_PROFILE(SMBfindclose);
8440 return;
8443 dptr_num = SVALS(req->vwv+0, 0);
8445 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8447 dptr_close(sconn, &dptr_num);
8449 reply_outbuf(req, 0, 0);
8451 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8453 END_PROFILE(SMBfindclose);
8454 return;
8457 /****************************************************************************
8458 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8459 ****************************************************************************/
8461 void reply_findnclose(struct smb_request *req)
8463 int dptr_num;
8465 START_PROFILE(SMBfindnclose);
8467 if (req->wct < 1) {
8468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8469 END_PROFILE(SMBfindnclose);
8470 return;
8473 dptr_num = SVAL(req->vwv+0, 0);
8475 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8477 /* We never give out valid handles for a
8478 findnotifyfirst - so any dptr_num is ok here.
8479 Just ignore it. */
8481 reply_outbuf(req, 0, 0);
8483 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8485 END_PROFILE(SMBfindnclose);
8486 return;
8489 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8490 struct trans_state *state)
8492 if (get_Protocol() >= PROTOCOL_NT1) {
8493 req->flags2 |= 0x40; /* IS_LONG_NAME */
8494 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8497 if (conn->encrypt_level == Required && !req->encrypted) {
8498 if (state->call != TRANSACT2_QFSINFO &&
8499 state->call != TRANSACT2_SETFSINFO) {
8500 DEBUG(0,("handle_trans2: encryption required "
8501 "with call 0x%x\n",
8502 (unsigned int)state->call));
8503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8504 return;
8508 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8510 /* Now we must call the relevant TRANS2 function */
8511 switch(state->call) {
8512 case TRANSACT2_OPEN:
8514 START_PROFILE(Trans2_open);
8515 call_trans2open(conn, req,
8516 &state->param, state->total_param,
8517 &state->data, state->total_data,
8518 state->max_data_return);
8519 END_PROFILE(Trans2_open);
8520 break;
8523 case TRANSACT2_FINDFIRST:
8525 START_PROFILE(Trans2_findfirst);
8526 call_trans2findfirst(conn, req,
8527 &state->param, state->total_param,
8528 &state->data, state->total_data,
8529 state->max_data_return);
8530 END_PROFILE(Trans2_findfirst);
8531 break;
8534 case TRANSACT2_FINDNEXT:
8536 START_PROFILE(Trans2_findnext);
8537 call_trans2findnext(conn, req,
8538 &state->param, state->total_param,
8539 &state->data, state->total_data,
8540 state->max_data_return);
8541 END_PROFILE(Trans2_findnext);
8542 break;
8545 case TRANSACT2_QFSINFO:
8547 START_PROFILE(Trans2_qfsinfo);
8548 call_trans2qfsinfo(conn, req,
8549 &state->param, state->total_param,
8550 &state->data, state->total_data,
8551 state->max_data_return);
8552 END_PROFILE(Trans2_qfsinfo);
8553 break;
8556 case TRANSACT2_SETFSINFO:
8558 START_PROFILE(Trans2_setfsinfo);
8559 call_trans2setfsinfo(conn, req,
8560 &state->param, state->total_param,
8561 &state->data, state->total_data,
8562 state->max_data_return);
8563 END_PROFILE(Trans2_setfsinfo);
8564 break;
8567 case TRANSACT2_QPATHINFO:
8568 case TRANSACT2_QFILEINFO:
8570 START_PROFILE(Trans2_qpathinfo);
8571 call_trans2qfilepathinfo(conn, req, state->call,
8572 &state->param, state->total_param,
8573 &state->data, state->total_data,
8574 state->max_data_return);
8575 END_PROFILE(Trans2_qpathinfo);
8576 break;
8579 case TRANSACT2_SETPATHINFO:
8580 case TRANSACT2_SETFILEINFO:
8582 START_PROFILE(Trans2_setpathinfo);
8583 call_trans2setfilepathinfo(conn, req, state->call,
8584 &state->param, state->total_param,
8585 &state->data, state->total_data,
8586 state->max_data_return);
8587 END_PROFILE(Trans2_setpathinfo);
8588 break;
8591 case TRANSACT2_FINDNOTIFYFIRST:
8593 START_PROFILE(Trans2_findnotifyfirst);
8594 call_trans2findnotifyfirst(conn, req,
8595 &state->param, state->total_param,
8596 &state->data, state->total_data,
8597 state->max_data_return);
8598 END_PROFILE(Trans2_findnotifyfirst);
8599 break;
8602 case TRANSACT2_FINDNOTIFYNEXT:
8604 START_PROFILE(Trans2_findnotifynext);
8605 call_trans2findnotifynext(conn, req,
8606 &state->param, state->total_param,
8607 &state->data, state->total_data,
8608 state->max_data_return);
8609 END_PROFILE(Trans2_findnotifynext);
8610 break;
8613 case TRANSACT2_MKDIR:
8615 START_PROFILE(Trans2_mkdir);
8616 call_trans2mkdir(conn, req,
8617 &state->param, state->total_param,
8618 &state->data, state->total_data,
8619 state->max_data_return);
8620 END_PROFILE(Trans2_mkdir);
8621 break;
8624 case TRANSACT2_GET_DFS_REFERRAL:
8626 START_PROFILE(Trans2_get_dfs_referral);
8627 call_trans2getdfsreferral(conn, req,
8628 &state->param, state->total_param,
8629 &state->data, state->total_data,
8630 state->max_data_return);
8631 END_PROFILE(Trans2_get_dfs_referral);
8632 break;
8635 case TRANSACT2_IOCTL:
8637 START_PROFILE(Trans2_ioctl);
8638 call_trans2ioctl(conn, req,
8639 &state->param, state->total_param,
8640 &state->data, state->total_data,
8641 state->max_data_return);
8642 END_PROFILE(Trans2_ioctl);
8643 break;
8646 default:
8647 /* Error in request */
8648 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8649 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8653 /****************************************************************************
8654 Reply to a SMBtrans2.
8655 ****************************************************************************/
8657 void reply_trans2(struct smb_request *req)
8659 connection_struct *conn = req->conn;
8660 unsigned int dsoff;
8661 unsigned int dscnt;
8662 unsigned int psoff;
8663 unsigned int pscnt;
8664 unsigned int tran_call;
8665 struct trans_state *state;
8666 NTSTATUS result;
8668 START_PROFILE(SMBtrans2);
8670 if (req->wct < 14) {
8671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8672 END_PROFILE(SMBtrans2);
8673 return;
8676 dsoff = SVAL(req->vwv+12, 0);
8677 dscnt = SVAL(req->vwv+11, 0);
8678 psoff = SVAL(req->vwv+10, 0);
8679 pscnt = SVAL(req->vwv+9, 0);
8680 tran_call = SVAL(req->vwv+14, 0);
8682 result = allow_new_trans(conn->pending_trans, req->mid);
8683 if (!NT_STATUS_IS_OK(result)) {
8684 DEBUG(2, ("Got invalid trans2 request: %s\n",
8685 nt_errstr(result)));
8686 reply_nterror(req, result);
8687 END_PROFILE(SMBtrans2);
8688 return;
8691 if (IS_IPC(conn)) {
8692 switch (tran_call) {
8693 /* List the allowed trans2 calls on IPC$ */
8694 case TRANSACT2_OPEN:
8695 case TRANSACT2_GET_DFS_REFERRAL:
8696 case TRANSACT2_QFILEINFO:
8697 case TRANSACT2_QFSINFO:
8698 case TRANSACT2_SETFSINFO:
8699 break;
8700 default:
8701 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8702 END_PROFILE(SMBtrans2);
8703 return;
8707 if ((state = talloc(conn, struct trans_state)) == NULL) {
8708 DEBUG(0, ("talloc failed\n"));
8709 reply_nterror(req, NT_STATUS_NO_MEMORY);
8710 END_PROFILE(SMBtrans2);
8711 return;
8714 state->cmd = SMBtrans2;
8716 state->mid = req->mid;
8717 state->vuid = req->vuid;
8718 state->setup_count = SVAL(req->vwv+13, 0);
8719 state->setup = NULL;
8720 state->total_param = SVAL(req->vwv+0, 0);
8721 state->param = NULL;
8722 state->total_data = SVAL(req->vwv+1, 0);
8723 state->data = NULL;
8724 state->max_param_return = SVAL(req->vwv+2, 0);
8725 state->max_data_return = SVAL(req->vwv+3, 0);
8726 state->max_setup_return = SVAL(req->vwv+4, 0);
8727 state->close_on_completion = BITSETW(req->vwv+5, 0);
8728 state->one_way = BITSETW(req->vwv+5, 1);
8730 state->call = tran_call;
8732 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8733 is so as a sanity check */
8734 if (state->setup_count != 1) {
8736 * Need to have rc=0 for ioctl to get job id for OS/2.
8737 * Network printing will fail if function is not successful.
8738 * Similar function in reply.c will be used if protocol
8739 * is LANMAN1.0 instead of LM1.2X002.
8740 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8741 * outbuf doesn't have to be set(only job id is used).
8743 if ( (state->setup_count == 4)
8744 && (tran_call == TRANSACT2_IOCTL)
8745 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8746 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8747 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8748 } else {
8749 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8750 DEBUG(2,("Transaction is %d\n",tran_call));
8751 TALLOC_FREE(state);
8752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8753 END_PROFILE(SMBtrans2);
8754 return;
8758 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8759 goto bad_param;
8761 if (state->total_data) {
8763 if (trans_oob(state->total_data, 0, dscnt)
8764 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8765 goto bad_param;
8768 /* Can't use talloc here, the core routines do realloc on the
8769 * params and data. */
8770 state->data = (char *)SMB_MALLOC(state->total_data);
8771 if (state->data == NULL) {
8772 DEBUG(0,("reply_trans2: data malloc fail for %u "
8773 "bytes !\n", (unsigned int)state->total_data));
8774 TALLOC_FREE(state);
8775 reply_nterror(req, NT_STATUS_NO_MEMORY);
8776 END_PROFILE(SMBtrans2);
8777 return;
8780 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8783 if (state->total_param) {
8785 if (trans_oob(state->total_param, 0, pscnt)
8786 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8787 goto bad_param;
8790 /* Can't use talloc here, the core routines do realloc on the
8791 * params and data. */
8792 state->param = (char *)SMB_MALLOC(state->total_param);
8793 if (state->param == NULL) {
8794 DEBUG(0,("reply_trans: param malloc fail for %u "
8795 "bytes !\n", (unsigned int)state->total_param));
8796 SAFE_FREE(state->data);
8797 TALLOC_FREE(state);
8798 reply_nterror(req, NT_STATUS_NO_MEMORY);
8799 END_PROFILE(SMBtrans2);
8800 return;
8803 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8806 state->received_data = dscnt;
8807 state->received_param = pscnt;
8809 if ((state->received_param == state->total_param) &&
8810 (state->received_data == state->total_data)) {
8812 handle_trans2(conn, req, state);
8814 SAFE_FREE(state->data);
8815 SAFE_FREE(state->param);
8816 TALLOC_FREE(state);
8817 END_PROFILE(SMBtrans2);
8818 return;
8821 DLIST_ADD(conn->pending_trans, state);
8823 /* We need to send an interim response then receive the rest
8824 of the parameter/data bytes */
8825 reply_outbuf(req, 0, 0);
8826 show_msg((char *)req->outbuf);
8827 END_PROFILE(SMBtrans2);
8828 return;
8830 bad_param:
8832 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8833 SAFE_FREE(state->data);
8834 SAFE_FREE(state->param);
8835 TALLOC_FREE(state);
8836 END_PROFILE(SMBtrans2);
8837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8841 /****************************************************************************
8842 Reply to a SMBtranss2
8843 ****************************************************************************/
8845 void reply_transs2(struct smb_request *req)
8847 connection_struct *conn = req->conn;
8848 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8849 struct trans_state *state;
8851 START_PROFILE(SMBtranss2);
8853 show_msg((const char *)req->inbuf);
8855 if (req->wct < 8) {
8856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8857 END_PROFILE(SMBtranss2);
8858 return;
8861 for (state = conn->pending_trans; state != NULL;
8862 state = state->next) {
8863 if (state->mid == req->mid) {
8864 break;
8868 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8870 END_PROFILE(SMBtranss2);
8871 return;
8874 /* Revise state->total_param and state->total_data in case they have
8875 changed downwards */
8877 if (SVAL(req->vwv+0, 0) < state->total_param)
8878 state->total_param = SVAL(req->vwv+0, 0);
8879 if (SVAL(req->vwv+1, 0) < state->total_data)
8880 state->total_data = SVAL(req->vwv+1, 0);
8882 pcnt = SVAL(req->vwv+2, 0);
8883 poff = SVAL(req->vwv+3, 0);
8884 pdisp = SVAL(req->vwv+4, 0);
8886 dcnt = SVAL(req->vwv+5, 0);
8887 doff = SVAL(req->vwv+6, 0);
8888 ddisp = SVAL(req->vwv+7, 0);
8890 state->received_param += pcnt;
8891 state->received_data += dcnt;
8893 if ((state->received_data > state->total_data) ||
8894 (state->received_param > state->total_param))
8895 goto bad_param;
8897 if (pcnt) {
8898 if (trans_oob(state->total_param, pdisp, pcnt)
8899 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8900 goto bad_param;
8902 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8905 if (dcnt) {
8906 if (trans_oob(state->total_data, ddisp, dcnt)
8907 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8908 goto bad_param;
8910 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8913 if ((state->received_param < state->total_param) ||
8914 (state->received_data < state->total_data)) {
8915 END_PROFILE(SMBtranss2);
8916 return;
8919 handle_trans2(conn, req, state);
8921 DLIST_REMOVE(conn->pending_trans, state);
8922 SAFE_FREE(state->data);
8923 SAFE_FREE(state->param);
8924 TALLOC_FREE(state);
8926 END_PROFILE(SMBtranss2);
8927 return;
8929 bad_param:
8931 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8932 DLIST_REMOVE(conn->pending_trans, state);
8933 SAFE_FREE(state->data);
8934 SAFE_FREE(state->param);
8935 TALLOC_FREE(state);
8936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8937 END_PROFILE(SMBtranss2);
8938 return;