s3:smbd/trans2: make use of BVAL() and remove ugly LARGE_SMB_OFF_T ifdef's
[Samba.git] / source3 / smbd / trans2.c
blob830504c6570bed870d1eb6b2ea59412a8e149009
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"
39 #define DIR_ENTRY_SAFETY_MARGIN 4096
41 static char *store_file_unix_basic(connection_struct *conn,
42 char *pdata,
43 files_struct *fsp,
44 const SMB_STRUCT_STAT *psbuf);
46 static char *store_file_unix_basic_info2(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 /********************************************************************
52 Roundup a value to the nearest allocation roundup size boundary.
53 Only do this for Windows clients.
54 ********************************************************************/
56 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
58 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
60 /* Only roundup for Windows clients. */
61 enum remote_arch_types ra_type = get_remote_arch();
62 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
63 val = SMB_ROUNDUP(val,rval);
65 return val;
68 /********************************************************************
69 Create a 64 bit FileIndex. If the file is on the same device as
70 the root of the share, just return the 64-bit inode. If it isn't,
71 mangle as we used to do.
72 ********************************************************************/
74 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
76 uint64_t file_index;
77 if (conn->base_share_dev == psbuf->st_ex_dev) {
78 return (uint64_t)psbuf->st_ex_ino;
80 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
81 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
82 return file_index;
85 /****************************************************************************
86 Utility functions for dealing with extended attributes.
87 ****************************************************************************/
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static bool samba_private_attr_name(const char *unix_ea_name)
95 static const char * const prohibited_ea_names[] = {
96 SAMBA_POSIX_INHERITANCE_EA_NAME,
97 SAMBA_XATTR_DOS_ATTRIB,
98 SAMBA_XATTR_MARKER,
99 XATTR_NTACL_NAME,
100 NULL
103 int i;
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
107 return true;
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
111 return true;
113 return false;
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
126 char *val = NULL;
127 ssize_t sizeret;
129 again:
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (!val) {
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 } else {
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
143 attr_size = 65536;
144 goto again;
147 if (sizeret == -1) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
154 pea->flags = 0;
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 } else {
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
161 TALLOC_FREE(val);
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
166 return NT_STATUS_OK;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
177 char *p;
178 char **names, **tmp;
179 size_t num_names;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
183 if (pnames) {
184 *pnames = NULL;
186 *pnum_names = 0;
187 return NT_STATUS_OK;
191 * TALLOC the result early to get the talloc hierarchy right.
194 names = TALLOC_ARRAY(mem_ctx, char *, 1);
195 if (names == NULL) {
196 DEBUG(0, ("talloc failed\n"));
197 return NT_STATUS_NO_MEMORY;
200 while (ea_namelist_size <= 65536) {
202 ea_namelist = TALLOC_REALLOC_ARRAY(
203 names, ea_namelist, char, ea_namelist_size);
204 if (ea_namelist == NULL) {
205 DEBUG(0, ("talloc failed\n"));
206 TALLOC_FREE(names);
207 return NT_STATUS_NO_MEMORY;
210 if (fsp && fsp->fh->fd != -1) {
211 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
212 ea_namelist_size);
213 } else {
214 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
215 ea_namelist_size);
218 if ((sizeret == -1) && (errno == ERANGE)) {
219 ea_namelist_size *= 2;
221 else {
222 break;
226 if (sizeret == -1) {
227 TALLOC_FREE(names);
228 return map_nt_error_from_unix(errno);
231 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
232 (unsigned int)sizeret));
234 if (sizeret == 0) {
235 TALLOC_FREE(names);
236 if (pnames) {
237 *pnames = NULL;
239 *pnum_names = 0;
240 return NT_STATUS_OK;
244 * Ensure the result is 0-terminated
247 if (ea_namelist[sizeret-1] != '\0') {
248 TALLOC_FREE(names);
249 return NT_STATUS_INTERNAL_ERROR;
253 * count the names
255 num_names = 0;
257 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
258 num_names += 1;
261 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
262 if (tmp == NULL) {
263 DEBUG(0, ("talloc failed\n"));
264 TALLOC_FREE(names);
265 return NT_STATUS_NO_MEMORY;
268 names = tmp;
269 num_names = 0;
271 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
272 names[num_names++] = p;
275 if (pnames) {
276 *pnames = names;
277 } else {
278 TALLOC_FREE(names);
280 *pnum_names = num_names;
281 return NT_STATUS_OK;
284 /****************************************************************************
285 Return a linked list of the total EA's. Plus the total size
286 ****************************************************************************/
288 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
289 const char *fname, size_t *pea_total_len)
291 /* Get a list of all xattrs. Max namesize is 64k. */
292 size_t i, num_names;
293 char **names;
294 struct ea_list *ea_list_head = NULL;
295 NTSTATUS status;
297 *pea_total_len = 0;
299 if (!lp_ea_support(SNUM(conn))) {
300 return NULL;
303 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
304 &names, &num_names);
306 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
307 return NULL;
310 for (i=0; i<num_names; i++) {
311 struct ea_list *listp;
312 fstring dos_ea_name;
314 if (strnequal(names[i], "system.", 7)
315 || samba_private_attr_name(names[i]))
316 continue;
318 listp = TALLOC_P(mem_ctx, struct ea_list);
319 if (listp == NULL) {
320 return NULL;
323 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
324 fname, names[i],
325 &listp->ea))) {
326 return NULL;
329 push_ascii_fstring(dos_ea_name, listp->ea.name);
331 *pea_total_len +=
332 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
334 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
335 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
336 (unsigned int)listp->ea.value.length));
338 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
342 /* Add on 4 for total length. */
343 if (*pea_total_len) {
344 *pea_total_len += 4;
347 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
348 (unsigned int)*pea_total_len));
350 return ea_list_head;
353 /****************************************************************************
354 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
355 that was filled.
356 ****************************************************************************/
358 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
359 connection_struct *conn, struct ea_list *ea_list)
361 unsigned int ret_data_size = 4;
362 char *p = pdata;
364 SMB_ASSERT(total_data_size >= 4);
366 if (!lp_ea_support(SNUM(conn))) {
367 SIVAL(pdata,4,0);
368 return 4;
371 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
372 size_t dos_namelen;
373 fstring dos_ea_name;
374 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
375 dos_namelen = strlen(dos_ea_name);
376 if (dos_namelen > 255 || dos_namelen == 0) {
377 break;
379 if (ea_list->ea.value.length > 65535) {
380 break;
382 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
383 break;
386 /* We know we have room. */
387 SCVAL(p,0,ea_list->ea.flags);
388 SCVAL(p,1,dos_namelen);
389 SSVAL(p,2,ea_list->ea.value.length);
390 fstrcpy(p+4, dos_ea_name);
391 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
393 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
394 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
397 ret_data_size = PTR_DIFF(p, pdata);
398 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
399 SIVAL(pdata,0,ret_data_size);
400 return ret_data_size;
403 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
404 char *pdata,
405 unsigned int total_data_size,
406 unsigned int *ret_data_size,
407 connection_struct *conn,
408 struct ea_list *ea_list)
410 uint8_t *p = (uint8_t *)pdata;
411 uint8_t *last_start = NULL;
413 *ret_data_size = 0;
415 if (!lp_ea_support(SNUM(conn))) {
416 return NT_STATUS_NO_EAS_ON_FILE;
419 for (; ea_list; ea_list = ea_list->next) {
420 size_t dos_namelen;
421 fstring dos_ea_name;
422 size_t this_size;
424 if (last_start) {
425 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
427 last_start = p;
429 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
430 dos_namelen = strlen(dos_ea_name);
431 if (dos_namelen > 255 || dos_namelen == 0) {
432 return NT_STATUS_INTERNAL_ERROR;
434 if (ea_list->ea.value.length > 65535) {
435 return NT_STATUS_INTERNAL_ERROR;
438 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
440 if (ea_list->next) {
441 size_t pad = 4 - (this_size % 4);
442 this_size += pad;
445 if (this_size > total_data_size) {
446 return NT_STATUS_INFO_LENGTH_MISMATCH;
449 /* We know we have room. */
450 SIVAL(p, 0x00, 0); /* next offset */
451 SCVAL(p, 0x04, ea_list->ea.flags);
452 SCVAL(p, 0x05, dos_namelen);
453 SSVAL(p, 0x06, ea_list->ea.value.length);
454 fstrcpy((char *)(p+0x08), dos_ea_name);
455 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
457 total_data_size -= this_size;
458 p += this_size;
461 *ret_data_size = PTR_DIFF(p, pdata);
462 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
463 return NT_STATUS_OK;
466 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
468 size_t total_ea_len = 0;
469 TALLOC_CTX *mem_ctx = NULL;
471 if (!lp_ea_support(SNUM(conn))) {
472 return 0;
474 mem_ctx = talloc_tos();
475 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
476 return total_ea_len;
479 /****************************************************************************
480 Ensure the EA name is case insensitive by matching any existing EA name.
481 ****************************************************************************/
483 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
485 size_t total_ea_len;
486 TALLOC_CTX *mem_ctx = talloc_tos();
487 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
489 for (; ea_list; ea_list = ea_list->next) {
490 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
491 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
492 &unix_ea_name[5], ea_list->ea.name));
493 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
494 break;
499 /****************************************************************************
500 Set or delete an extended attribute.
501 ****************************************************************************/
503 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
504 const struct smb_filename *smb_fname, struct ea_list *ea_list)
506 char *fname = NULL;
508 if (!lp_ea_support(SNUM(conn))) {
509 return NT_STATUS_EAS_NOT_SUPPORTED;
512 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
513 return NT_STATUS_ACCESS_DENIED;
516 /* For now setting EAs on streams isn't supported. */
517 fname = smb_fname->base_name;
519 for (;ea_list; ea_list = ea_list->next) {
520 int ret;
521 fstring unix_ea_name;
523 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
524 fstrcat(unix_ea_name, ea_list->ea.name);
526 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
528 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
530 if (samba_private_attr_name(unix_ea_name)) {
531 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
532 return NT_STATUS_ACCESS_DENIED;
535 if (ea_list->ea.value.length == 0) {
536 /* Remove the attribute. */
537 if (fsp && (fsp->fh->fd != -1)) {
538 DEBUG(10,("set_ea: deleting ea name %s on "
539 "file %s by file descriptor.\n",
540 unix_ea_name, fsp_str_dbg(fsp)));
541 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
542 } else {
543 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
544 unix_ea_name, fname));
545 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
547 #ifdef ENOATTR
548 /* Removing a non existent attribute always succeeds. */
549 if (ret == -1 && errno == ENOATTR) {
550 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
551 unix_ea_name));
552 ret = 0;
554 #endif
555 } else {
556 if (fsp && (fsp->fh->fd != -1)) {
557 DEBUG(10,("set_ea: setting ea name %s on file "
558 "%s by file descriptor.\n",
559 unix_ea_name, fsp_str_dbg(fsp)));
560 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
561 ea_list->ea.value.data, ea_list->ea.value.length, 0);
562 } else {
563 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
564 unix_ea_name, fname));
565 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
566 ea_list->ea.value.data, ea_list->ea.value.length, 0);
570 if (ret == -1) {
571 #ifdef ENOTSUP
572 if (errno == ENOTSUP) {
573 return NT_STATUS_EAS_NOT_SUPPORTED;
575 #endif
576 return map_nt_error_from_unix(errno);
580 return NT_STATUS_OK;
582 /****************************************************************************
583 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
584 ****************************************************************************/
586 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
588 struct ea_list *ea_list_head = NULL;
589 size_t converted_size, offset = 0;
591 while (offset + 2 < data_size) {
592 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
593 unsigned int namelen = CVAL(pdata,offset);
595 offset++; /* Go past the namelen byte. */
597 /* integer wrap paranioa. */
598 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
599 (offset > data_size) || (namelen > data_size) ||
600 (offset + namelen >= data_size)) {
601 break;
603 /* Ensure the name is null terminated. */
604 if (pdata[offset + namelen] != '\0') {
605 return NULL;
607 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
608 &converted_size)) {
609 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
610 "failed: %s", strerror(errno)));
612 if (!eal->ea.name) {
613 return NULL;
616 offset += (namelen + 1); /* Go past the name + terminating zero. */
617 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
618 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
621 return ea_list_head;
624 /****************************************************************************
625 Read one EA list entry from the buffer.
626 ****************************************************************************/
628 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
630 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
631 uint16 val_len;
632 unsigned int namelen;
633 size_t converted_size;
635 if (!eal) {
636 return NULL;
639 if (data_size < 6) {
640 return NULL;
643 eal->ea.flags = CVAL(pdata,0);
644 namelen = CVAL(pdata,1);
645 val_len = SVAL(pdata,2);
647 if (4 + namelen + 1 + val_len > data_size) {
648 return NULL;
651 /* Ensure the name is null terminated. */
652 if (pdata[namelen + 4] != '\0') {
653 return NULL;
655 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
656 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
657 strerror(errno)));
659 if (!eal->ea.name) {
660 return NULL;
663 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
664 if (!eal->ea.value.data) {
665 return NULL;
668 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
670 /* Ensure we're null terminated just in case we print the value. */
671 eal->ea.value.data[val_len] = '\0';
672 /* But don't count the null. */
673 eal->ea.value.length--;
675 if (pbytes_used) {
676 *pbytes_used = 4 + namelen + 1 + val_len;
679 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
680 dump_data(10, eal->ea.value.data, eal->ea.value.length);
682 return eal;
685 /****************************************************************************
686 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
687 ****************************************************************************/
689 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
691 struct ea_list *ea_list_head = NULL;
692 size_t offset = 0;
693 size_t bytes_used = 0;
695 while (offset < data_size) {
696 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
698 if (!eal) {
699 return NULL;
702 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
703 offset += bytes_used;
706 return ea_list_head;
709 /****************************************************************************
710 Count the total EA size needed.
711 ****************************************************************************/
713 static size_t ea_list_size(struct ea_list *ealist)
715 fstring dos_ea_name;
716 struct ea_list *listp;
717 size_t ret = 0;
719 for (listp = ealist; listp; listp = listp->next) {
720 push_ascii_fstring(dos_ea_name, listp->ea.name);
721 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
723 /* Add on 4 for total length. */
724 if (ret) {
725 ret += 4;
728 return ret;
731 /****************************************************************************
732 Return a union of EA's from a file list and a list of names.
733 The TALLOC context for the two lists *MUST* be identical as we steal
734 memory from one list to add to another. JRA.
735 ****************************************************************************/
737 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
739 struct ea_list *nlistp, *flistp;
741 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
742 for (flistp = file_list; flistp; flistp = flistp->next) {
743 if (strequal(nlistp->ea.name, flistp->ea.name)) {
744 break;
748 if (flistp) {
749 /* Copy the data from this entry. */
750 nlistp->ea.flags = flistp->ea.flags;
751 nlistp->ea.value = flistp->ea.value;
752 } else {
753 /* Null entry. */
754 nlistp->ea.flags = 0;
755 ZERO_STRUCT(nlistp->ea.value);
759 *total_ea_len = ea_list_size(name_list);
760 return name_list;
763 /****************************************************************************
764 Send the required number of replies back.
765 We assume all fields other than the data fields are
766 set correctly for the type of call.
767 HACK ! Always assumes smb_setup field is zero.
768 ****************************************************************************/
770 void send_trans2_replies(connection_struct *conn,
771 struct smb_request *req,
772 const char *params,
773 int paramsize,
774 const char *pdata,
775 int datasize,
776 int max_data_bytes)
778 /* As we are using a protocol > LANMAN1 then the max_send
779 variable must have been set in the sessetupX call.
780 This takes precedence over the max_xmit field in the
781 global struct. These different max_xmit variables should
782 be merged as this is now too confusing */
784 int data_to_send = datasize;
785 int params_to_send = paramsize;
786 int useable_space;
787 const char *pp = params;
788 const char *pd = pdata;
789 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
790 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
791 int data_alignment_offset = 0;
792 bool overflow = False;
793 struct smbd_server_connection *sconn = req->sconn;
794 int max_send = sconn->smb1.sessions.max_send;
796 /* Modify the data_to_send and datasize and set the error if
797 we're trying to send more than max_data_bytes. We still send
798 the part of the packet(s) that fit. Strange, but needed
799 for OS/2. */
801 if (max_data_bytes > 0 && datasize > max_data_bytes) {
802 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
803 max_data_bytes, datasize ));
804 datasize = data_to_send = max_data_bytes;
805 overflow = True;
808 /* If there genuinely are no parameters or data to send just send the empty packet */
810 if(params_to_send == 0 && data_to_send == 0) {
811 reply_outbuf(req, 10, 0);
812 show_msg((char *)req->outbuf);
813 if (!srv_send_smb(sconn,
814 (char *)req->outbuf,
815 true, req->seqnum+1,
816 IS_CONN_ENCRYPTED(conn),
817 &req->pcd)) {
818 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
820 TALLOC_FREE(req->outbuf);
821 return;
824 /* When sending params and data ensure that both are nicely aligned */
825 /* Only do this alignment when there is also data to send - else
826 can cause NT redirector problems. */
828 if (((params_to_send % 4) != 0) && (data_to_send != 0))
829 data_alignment_offset = 4 - (params_to_send % 4);
831 /* Space is bufsize minus Netbios over TCP header minus SMB header */
832 /* The alignment_offset is to align the param bytes on an even byte
833 boundary. NT 4.0 Beta needs this to work correctly. */
835 useable_space = max_send - (smb_size
836 + 2 * 10 /* wct */
837 + alignment_offset
838 + data_alignment_offset);
840 if (useable_space < 0) {
841 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
842 "= %d!!!", useable_space));
843 exit_server_cleanly("send_trans2_replies: Not enough space");
846 while (params_to_send || data_to_send) {
847 /* Calculate whether we will totally or partially fill this packet */
849 total_sent_thistime = params_to_send + data_to_send;
851 /* We can never send more than useable_space */
853 * Note that 'useable_space' does not include the alignment offsets,
854 * but we must include the alignment offsets in the calculation of
855 * the length of the data we send over the wire, as the alignment offsets
856 * are sent here. Fix from Marc_Jacobsen@hp.com.
859 total_sent_thistime = MIN(total_sent_thistime, useable_space);
861 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
862 + data_alignment_offset);
865 * We might have SMBtrans2s in req which was transferred to
866 * the outbuf, fix that.
868 SCVAL(req->outbuf, smb_com, SMBtrans2);
870 /* Set total params and data to be sent */
871 SSVAL(req->outbuf,smb_tprcnt,paramsize);
872 SSVAL(req->outbuf,smb_tdrcnt,datasize);
874 /* Calculate how many parameters and data we can fit into
875 * this packet. Parameters get precedence
878 params_sent_thistime = MIN(params_to_send,useable_space);
879 data_sent_thistime = useable_space - params_sent_thistime;
880 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
882 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
884 /* smb_proff is the offset from the start of the SMB header to the
885 parameter bytes, however the first 4 bytes of outbuf are
886 the Netbios over TCP header. Thus use smb_base() to subtract
887 them from the calculation */
889 SSVAL(req->outbuf,smb_proff,
890 ((smb_buf(req->outbuf)+alignment_offset)
891 - smb_base(req->outbuf)));
893 if(params_sent_thistime == 0)
894 SSVAL(req->outbuf,smb_prdisp,0);
895 else
896 /* Absolute displacement of param bytes sent in this packet */
897 SSVAL(req->outbuf,smb_prdisp,pp - params);
899 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
900 if(data_sent_thistime == 0) {
901 SSVAL(req->outbuf,smb_droff,0);
902 SSVAL(req->outbuf,smb_drdisp, 0);
903 } else {
904 /* The offset of the data bytes is the offset of the
905 parameter bytes plus the number of parameters being sent this time */
906 SSVAL(req->outbuf, smb_droff,
907 ((smb_buf(req->outbuf)+alignment_offset)
908 - smb_base(req->outbuf))
909 + params_sent_thistime + data_alignment_offset);
910 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
913 /* Initialize the padding for alignment */
915 if (alignment_offset != 0) {
916 memset(smb_buf(req->outbuf), 0, alignment_offset);
919 /* Copy the param bytes into the packet */
921 if(params_sent_thistime) {
922 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
923 params_sent_thistime);
926 /* Copy in the data bytes */
927 if(data_sent_thistime) {
928 if (data_alignment_offset != 0) {
929 memset((smb_buf(req->outbuf)+alignment_offset+
930 params_sent_thistime), 0,
931 data_alignment_offset);
933 memcpy(smb_buf(req->outbuf)+alignment_offset
934 +params_sent_thistime+data_alignment_offset,
935 pd,data_sent_thistime);
938 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
939 params_sent_thistime, data_sent_thistime, useable_space));
940 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
941 params_to_send, data_to_send, paramsize, datasize));
943 if (overflow) {
944 error_packet_set((char *)req->outbuf,
945 ERRDOS,ERRbufferoverflow,
946 STATUS_BUFFER_OVERFLOW,
947 __LINE__,__FILE__);
950 /* Send the packet */
951 show_msg((char *)req->outbuf);
952 if (!srv_send_smb(sconn,
953 (char *)req->outbuf,
954 true, req->seqnum+1,
955 IS_CONN_ENCRYPTED(conn),
956 &req->pcd))
957 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
959 TALLOC_FREE(req->outbuf);
961 pp += params_sent_thistime;
962 pd += data_sent_thistime;
964 params_to_send -= params_sent_thistime;
965 data_to_send -= data_sent_thistime;
967 /* Sanity check */
968 if(params_to_send < 0 || data_to_send < 0) {
969 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
970 params_to_send, data_to_send));
971 return;
975 return;
978 /****************************************************************************
979 Reply to a TRANSACT2_OPEN.
980 ****************************************************************************/
982 static void call_trans2open(connection_struct *conn,
983 struct smb_request *req,
984 char **pparams, int total_params,
985 char **ppdata, int total_data,
986 unsigned int max_data_bytes)
988 struct smb_filename *smb_fname = NULL;
989 char *params = *pparams;
990 char *pdata = *ppdata;
991 int deny_mode;
992 int32 open_attr;
993 bool oplock_request;
994 #if 0
995 bool return_additional_info;
996 int16 open_sattr;
997 time_t open_time;
998 #endif
999 int open_ofun;
1000 uint32 open_size;
1001 char *pname;
1002 char *fname = NULL;
1003 SMB_OFF_T size=0;
1004 int fattr=0,mtime=0;
1005 SMB_INO_T inode = 0;
1006 int smb_action = 0;
1007 files_struct *fsp;
1008 struct ea_list *ea_list = NULL;
1009 uint16 flags = 0;
1010 NTSTATUS status;
1011 uint32 access_mask;
1012 uint32 share_mode;
1013 uint32 create_disposition;
1014 uint32 create_options = 0;
1015 uint32_t private_flags = 0;
1016 TALLOC_CTX *ctx = talloc_tos();
1019 * Ensure we have enough parameters to perform the operation.
1022 if (total_params < 29) {
1023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1024 goto out;
1027 flags = SVAL(params, 0);
1028 deny_mode = SVAL(params, 2);
1029 open_attr = SVAL(params,6);
1030 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1031 if (oplock_request) {
1032 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1035 #if 0
1036 return_additional_info = BITSETW(params,0);
1037 open_sattr = SVAL(params, 4);
1038 open_time = make_unix_date3(params+8);
1039 #endif
1040 open_ofun = SVAL(params,12);
1041 open_size = IVAL(params,14);
1042 pname = &params[28];
1044 if (IS_IPC(conn)) {
1045 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1046 goto out;
1049 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1050 total_params - 28, STR_TERMINATE,
1051 &status);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 reply_nterror(req, status);
1054 goto out;
1057 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1058 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1059 (unsigned int)open_ofun, open_size));
1061 status = filename_convert(ctx,
1062 conn,
1063 req->flags2 & FLAGS2_DFS_PATHNAMES,
1064 fname,
1066 NULL,
1067 &smb_fname);
1068 if (!NT_STATUS_IS_OK(status)) {
1069 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1070 reply_botherror(req,
1071 NT_STATUS_PATH_NOT_COVERED,
1072 ERRSRV, ERRbadpath);
1073 goto out;
1075 reply_nterror(req, status);
1076 goto out;
1079 if (open_ofun == 0) {
1080 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1081 goto out;
1084 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1085 &access_mask, &share_mode,
1086 &create_disposition,
1087 &create_options,
1088 &private_flags)) {
1089 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1090 goto out;
1093 /* Any data in this call is an EA list. */
1094 if (total_data && (total_data != 4)) {
1095 if (total_data < 10) {
1096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1097 goto out;
1100 if (IVAL(pdata,0) > total_data) {
1101 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1102 IVAL(pdata,0), (unsigned int)total_data));
1103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1104 goto out;
1107 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1108 total_data - 4);
1109 if (!ea_list) {
1110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1111 goto out;
1114 if (!lp_ea_support(SNUM(conn))) {
1115 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1116 goto out;
1120 status = SMB_VFS_CREATE_FILE(
1121 conn, /* conn */
1122 req, /* req */
1123 0, /* root_dir_fid */
1124 smb_fname, /* fname */
1125 access_mask, /* access_mask */
1126 share_mode, /* share_access */
1127 create_disposition, /* create_disposition*/
1128 create_options, /* create_options */
1129 open_attr, /* file_attributes */
1130 oplock_request, /* oplock_request */
1131 open_size, /* allocation_size */
1132 private_flags,
1133 NULL, /* sd */
1134 ea_list, /* ea_list */
1135 &fsp, /* result */
1136 &smb_action); /* psbuf */
1138 if (!NT_STATUS_IS_OK(status)) {
1139 if (open_was_deferred(req->mid)) {
1140 /* We have re-scheduled this call. */
1141 goto out;
1143 reply_openerror(req, status);
1144 goto out;
1147 size = get_file_size_stat(&smb_fname->st);
1148 fattr = dos_mode(conn, smb_fname);
1149 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1150 inode = smb_fname->st.st_ex_ino;
1151 if (fattr & aDIR) {
1152 close_file(req, fsp, ERROR_CLOSE);
1153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1154 goto out;
1157 /* Realloc the size of parameters and data we will return */
1158 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1159 if(*pparams == NULL ) {
1160 reply_nterror(req, NT_STATUS_NO_MEMORY);
1161 goto out;
1163 params = *pparams;
1165 SSVAL(params,0,fsp->fnum);
1166 SSVAL(params,2,fattr);
1167 srv_put_dos_date2(params,4, mtime);
1168 SIVAL(params,8, (uint32)size);
1169 SSVAL(params,12,deny_mode);
1170 SSVAL(params,14,0); /* open_type - file or directory. */
1171 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1173 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1174 smb_action |= EXTENDED_OPLOCK_GRANTED;
1177 SSVAL(params,18,smb_action);
1180 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1182 SIVAL(params,20,inode);
1183 SSVAL(params,24,0); /* Padding. */
1184 if (flags & 8) {
1185 uint32 ea_size = estimate_ea_size(conn, fsp,
1186 fsp->fsp_name->base_name);
1187 SIVAL(params, 26, ea_size);
1188 } else {
1189 SIVAL(params, 26, 0);
1192 /* Send the required number of replies */
1193 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1194 out:
1195 TALLOC_FREE(smb_fname);
1198 /*********************************************************
1199 Routine to check if a given string matches exactly.
1200 as a special case a mask of "." does NOT match. That
1201 is required for correct wildcard semantics
1202 Case can be significant or not.
1203 **********************************************************/
1205 static bool exact_match(bool has_wild,
1206 bool case_sensitive,
1207 const char *str,
1208 const char *mask)
1210 if (mask[0] == '.' && mask[1] == 0) {
1211 return false;
1214 if (has_wild) {
1215 return false;
1218 if (case_sensitive) {
1219 return strcmp(str,mask)==0;
1220 } else {
1221 return StrCaseCmp(str,mask) == 0;
1225 /****************************************************************************
1226 Return the filetype for UNIX extensions.
1227 ****************************************************************************/
1229 static uint32 unix_filetype(mode_t mode)
1231 if(S_ISREG(mode))
1232 return UNIX_TYPE_FILE;
1233 else if(S_ISDIR(mode))
1234 return UNIX_TYPE_DIR;
1235 #ifdef S_ISLNK
1236 else if(S_ISLNK(mode))
1237 return UNIX_TYPE_SYMLINK;
1238 #endif
1239 #ifdef S_ISCHR
1240 else if(S_ISCHR(mode))
1241 return UNIX_TYPE_CHARDEV;
1242 #endif
1243 #ifdef S_ISBLK
1244 else if(S_ISBLK(mode))
1245 return UNIX_TYPE_BLKDEV;
1246 #endif
1247 #ifdef S_ISFIFO
1248 else if(S_ISFIFO(mode))
1249 return UNIX_TYPE_FIFO;
1250 #endif
1251 #ifdef S_ISSOCK
1252 else if(S_ISSOCK(mode))
1253 return UNIX_TYPE_SOCKET;
1254 #endif
1256 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1257 return UNIX_TYPE_UNKNOWN;
1260 /****************************************************************************
1261 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1262 ****************************************************************************/
1264 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1266 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1267 const SMB_STRUCT_STAT *psbuf,
1268 uint32 perms,
1269 enum perm_type ptype,
1270 mode_t *ret_perms)
1272 mode_t ret = 0;
1274 if (perms == SMB_MODE_NO_CHANGE) {
1275 if (!VALID_STAT(*psbuf)) {
1276 return NT_STATUS_INVALID_PARAMETER;
1277 } else {
1278 *ret_perms = psbuf->st_ex_mode;
1279 return NT_STATUS_OK;
1283 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1284 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1285 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1286 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1287 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1288 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1289 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1290 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1291 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1292 #ifdef S_ISVTX
1293 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1294 #endif
1295 #ifdef S_ISGID
1296 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1297 #endif
1298 #ifdef S_ISUID
1299 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1300 #endif
1302 switch (ptype) {
1303 case PERM_NEW_FILE:
1304 /* Apply mode mask */
1305 ret &= lp_create_mask(SNUM(conn));
1306 /* Add in force bits */
1307 ret |= lp_force_create_mode(SNUM(conn));
1308 break;
1309 case PERM_NEW_DIR:
1310 ret &= lp_dir_mask(SNUM(conn));
1311 /* Add in force bits */
1312 ret |= lp_force_dir_mode(SNUM(conn));
1313 break;
1314 case PERM_EXISTING_FILE:
1315 /* Apply mode mask */
1316 ret &= lp_security_mask(SNUM(conn));
1317 /* Add in force bits */
1318 ret |= lp_force_security_mode(SNUM(conn));
1319 break;
1320 case PERM_EXISTING_DIR:
1321 /* Apply mode mask */
1322 ret &= lp_dir_security_mask(SNUM(conn));
1323 /* Add in force bits */
1324 ret |= lp_force_dir_security_mode(SNUM(conn));
1325 break;
1328 *ret_perms = ret;
1329 return NT_STATUS_OK;
1332 /****************************************************************************
1333 Needed to show the msdfs symlinks as directories. Modifies psbuf
1334 to be a directory if it's a msdfs link.
1335 ****************************************************************************/
1337 static bool check_msdfs_link(connection_struct *conn,
1338 const char *pathname,
1339 SMB_STRUCT_STAT *psbuf)
1341 int saved_errno = errno;
1342 if(lp_host_msdfs() &&
1343 lp_msdfs_root(SNUM(conn)) &&
1344 is_msdfs_link(conn, pathname, psbuf)) {
1346 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1347 "as a directory\n",
1348 pathname));
1349 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1350 errno = saved_errno;
1351 return true;
1353 errno = saved_errno;
1354 return false;
1358 /****************************************************************************
1359 Get a level dependent lanman2 dir entry.
1360 ****************************************************************************/
1362 struct smbd_dirptr_lanman2_state {
1363 connection_struct *conn;
1364 uint32_t info_level;
1365 bool check_mangled_names;
1366 bool has_wild;
1367 bool got_exact_match;
1370 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1371 void *private_data,
1372 const char *dname,
1373 const char *mask,
1374 char **_fname)
1376 struct smbd_dirptr_lanman2_state *state =
1377 (struct smbd_dirptr_lanman2_state *)private_data;
1378 bool ok;
1379 char mangled_name[13]; /* mangled 8.3 name. */
1380 bool got_match;
1381 const char *fname;
1383 /* Mangle fname if it's an illegal name. */
1384 if (mangle_must_mangle(dname, state->conn->params)) {
1385 ok = name_to_8_3(dname, mangled_name,
1386 true, state->conn->params);
1387 if (!ok) {
1388 return false;
1390 fname = mangled_name;
1391 } else {
1392 fname = dname;
1395 got_match = exact_match(state->has_wild,
1396 state->conn->case_sensitive,
1397 fname, mask);
1398 state->got_exact_match = got_match;
1399 if (!got_match) {
1400 got_match = mask_match(fname, mask,
1401 state->conn->case_sensitive);
1404 if(!got_match && state->check_mangled_names &&
1405 !mangle_is_8_3(fname, false, state->conn->params)) {
1407 * It turns out that NT matches wildcards against
1408 * both long *and* short names. This may explain some
1409 * of the wildcard wierdness from old DOS clients
1410 * that some people have been seeing.... JRA.
1412 /* Force the mangling into 8.3. */
1413 ok = name_to_8_3(fname, mangled_name,
1414 false, state->conn->params);
1415 if (!ok) {
1416 return false;
1419 got_match = exact_match(state->has_wild,
1420 state->conn->case_sensitive,
1421 mangled_name, mask);
1422 state->got_exact_match = got_match;
1423 if (!got_match) {
1424 got_match = mask_match(mangled_name, mask,
1425 state->conn->case_sensitive);
1429 if (!got_match) {
1430 return false;
1433 *_fname = talloc_strdup(ctx, fname);
1434 if (*_fname == NULL) {
1435 return false;
1438 return true;
1441 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1442 void *private_data,
1443 struct smb_filename *smb_fname,
1444 uint32_t *_mode)
1446 struct smbd_dirptr_lanman2_state *state =
1447 (struct smbd_dirptr_lanman2_state *)private_data;
1448 bool ms_dfs_link = false;
1449 uint32_t mode = 0;
1451 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1452 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1453 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1454 "Couldn't lstat [%s] (%s)\n",
1455 smb_fname_str_dbg(smb_fname),
1456 strerror(errno)));
1457 return false;
1459 } else if (!VALID_STAT(smb_fname->st) &&
1460 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1461 /* Needed to show the msdfs symlinks as
1462 * directories */
1464 ms_dfs_link = check_msdfs_link(state->conn,
1465 smb_fname->base_name,
1466 &smb_fname->st);
1467 if (!ms_dfs_link) {
1468 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1469 "Couldn't stat [%s] (%s)\n",
1470 smb_fname_str_dbg(smb_fname),
1471 strerror(errno)));
1472 return false;
1476 if (ms_dfs_link) {
1477 mode = dos_mode_msdfs(state->conn, smb_fname);
1478 } else {
1479 mode = dos_mode(state->conn, smb_fname);
1482 *_mode = mode;
1483 return true;
1486 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1487 connection_struct *conn,
1488 uint16_t flags2,
1489 uint32_t info_level,
1490 struct ea_list *name_list,
1491 bool check_mangled_names,
1492 bool requires_resume_key,
1493 uint32_t mode,
1494 const char *fname,
1495 const struct smb_filename *smb_fname,
1496 int space_remaining,
1497 uint8_t align,
1498 bool do_pad,
1499 char *base_data,
1500 char **ppdata,
1501 char *end_data,
1502 bool *out_of_space,
1503 uint64_t *last_entry_off)
1505 char *p, *q, *pdata = *ppdata;
1506 uint32_t reskey=0;
1507 uint64_t file_size = 0;
1508 uint64_t allocation_size = 0;
1509 uint64_t file_index = 0;
1510 uint32_t len;
1511 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1512 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1513 time_t c_date = (time_t)0;
1514 char *nameptr;
1515 char *last_entry_ptr;
1516 bool was_8_3;
1517 int off;
1518 int pad = 0;
1520 *out_of_space = false;
1522 ZERO_STRUCT(mdate_ts);
1523 ZERO_STRUCT(adate_ts);
1524 ZERO_STRUCT(create_date_ts);
1525 ZERO_STRUCT(cdate_ts);
1527 if (!(mode & aDIR)) {
1528 file_size = get_file_size_stat(&smb_fname->st);
1530 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1532 file_index = get_FileIndex(conn, &smb_fname->st);
1534 mdate_ts = smb_fname->st.st_ex_mtime;
1535 adate_ts = smb_fname->st.st_ex_atime;
1536 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1537 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1539 if (lp_dos_filetime_resolution(SNUM(conn))) {
1540 dos_filetime_timespec(&create_date_ts);
1541 dos_filetime_timespec(&mdate_ts);
1542 dos_filetime_timespec(&adate_ts);
1543 dos_filetime_timespec(&cdate_ts);
1546 create_date = convert_timespec_to_time_t(create_date_ts);
1547 mdate = convert_timespec_to_time_t(mdate_ts);
1548 adate = convert_timespec_to_time_t(adate_ts);
1549 c_date = convert_timespec_to_time_t(cdate_ts);
1551 /* align the record */
1552 SMB_ASSERT(align >= 1);
1554 off = (int)PTR_DIFF(pdata, base_data);
1555 pad = (off + (align-1)) & ~(align-1);
1556 pad -= off;
1558 if (pad && pad > space_remaining) {
1559 *out_of_space = true;
1560 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1561 "for padding (wanted %u, had %d)\n",
1562 (unsigned int)pad,
1563 space_remaining ));
1564 return false; /* Not finished - just out of space */
1567 off += pad;
1568 /* initialize padding to 0 */
1569 if (pad) {
1570 memset(pdata, 0, pad);
1572 space_remaining -= pad;
1574 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1575 space_remaining ));
1577 pdata += pad;
1578 p = pdata;
1579 last_entry_ptr = p;
1581 pad = 0;
1582 off = 0;
1584 switch (info_level) {
1585 case SMB_FIND_INFO_STANDARD:
1586 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1587 if(requires_resume_key) {
1588 SIVAL(p,0,reskey);
1589 p += 4;
1591 srv_put_dos_date2(p,0,create_date);
1592 srv_put_dos_date2(p,4,adate);
1593 srv_put_dos_date2(p,8,mdate);
1594 SIVAL(p,12,(uint32)file_size);
1595 SIVAL(p,16,(uint32)allocation_size);
1596 SSVAL(p,20,mode);
1597 p += 23;
1598 nameptr = p;
1599 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1600 p += ucs2_align(base_data, p, 0);
1602 len = srvstr_push(base_data, flags2, p,
1603 fname, PTR_DIFF(end_data, p),
1604 STR_TERMINATE);
1605 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 if (len > 2) {
1607 SCVAL(nameptr, -1, len - 2);
1608 } else {
1609 SCVAL(nameptr, -1, 0);
1611 } else {
1612 if (len > 1) {
1613 SCVAL(nameptr, -1, len - 1);
1614 } else {
1615 SCVAL(nameptr, -1, 0);
1618 p += len;
1619 break;
1621 case SMB_FIND_EA_SIZE:
1622 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1623 if (requires_resume_key) {
1624 SIVAL(p,0,reskey);
1625 p += 4;
1627 srv_put_dos_date2(p,0,create_date);
1628 srv_put_dos_date2(p,4,adate);
1629 srv_put_dos_date2(p,8,mdate);
1630 SIVAL(p,12,(uint32)file_size);
1631 SIVAL(p,16,(uint32)allocation_size);
1632 SSVAL(p,20,mode);
1634 unsigned int ea_size = estimate_ea_size(conn, NULL,
1635 smb_fname->base_name);
1636 SIVAL(p,22,ea_size); /* Extended attributes */
1638 p += 27;
1639 nameptr = p - 1;
1640 len = srvstr_push(base_data, flags2,
1641 p, fname, PTR_DIFF(end_data, p),
1642 STR_TERMINATE | STR_NOALIGN);
1643 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1644 if (len > 2) {
1645 len -= 2;
1646 } else {
1647 len = 0;
1649 } else {
1650 if (len > 1) {
1651 len -= 1;
1652 } else {
1653 len = 0;
1656 SCVAL(nameptr,0,len);
1657 p += len;
1658 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1659 break;
1661 case SMB_FIND_EA_LIST:
1663 struct ea_list *file_list = NULL;
1664 size_t ea_len = 0;
1666 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1667 if (!name_list) {
1668 return false;
1670 if (requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 22; /* p now points to the EA area. */
1682 file_list = get_ea_list_from_file(ctx, conn, NULL,
1683 smb_fname->base_name,
1684 &ea_len);
1685 name_list = ea_list_union(name_list, file_list, &ea_len);
1687 /* We need to determine if this entry will fit in the space available. */
1688 /* Max string size is 255 bytes. */
1689 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1690 *out_of_space = true;
1691 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1692 "(wanted %u, had %d)\n",
1693 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1694 space_remaining ));
1695 return False; /* Not finished - just out of space */
1698 /* Push the ea_data followed by the name. */
1699 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1700 nameptr = p;
1701 len = srvstr_push(base_data, flags2,
1702 p + 1, fname, PTR_DIFF(end_data, p+1),
1703 STR_TERMINATE | STR_NOALIGN);
1704 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1705 if (len > 2) {
1706 len -= 2;
1707 } else {
1708 len = 0;
1710 } else {
1711 if (len > 1) {
1712 len -= 1;
1713 } else {
1714 len = 0;
1717 SCVAL(nameptr,0,len);
1718 p += len + 1;
1719 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1720 break;
1723 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1724 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1725 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1726 p += 4;
1727 SIVAL(p,0,reskey); p += 4;
1728 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1729 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1730 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1732 SOFF_T(p,0,file_size); p += 8;
1733 SOFF_T(p,0,allocation_size); p += 8;
1734 SIVAL(p,0,mode); p += 4;
1735 q = p; p += 4; /* q is placeholder for name length. */
1737 unsigned int ea_size = estimate_ea_size(conn, NULL,
1738 smb_fname->base_name);
1739 SIVAL(p,0,ea_size); /* Extended attributes */
1740 p += 4;
1742 /* Clear the short name buffer. This is
1743 * IMPORTANT as not doing so will trigger
1744 * a Win2k client bug. JRA.
1746 if (!was_8_3 && check_mangled_names) {
1747 char mangled_name[13]; /* mangled 8.3 name. */
1748 if (!name_to_8_3(fname,mangled_name,True,
1749 conn->params)) {
1750 /* Error - mangle failed ! */
1751 memset(mangled_name,'\0',12);
1753 mangled_name[12] = 0;
1754 len = srvstr_push(base_data, flags2,
1755 p+2, mangled_name, 24,
1756 STR_UPPER|STR_UNICODE);
1757 if (len < 24) {
1758 memset(p + 2 + len,'\0',24 - len);
1760 SSVAL(p, 0, len);
1761 } else {
1762 memset(p,'\0',26);
1764 p += 2 + 24;
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1768 SIVAL(q,0,len);
1769 p += len;
1771 len = PTR_DIFF(p, pdata);
1772 pad = (len + (align-1)) & ~(align-1);
1774 * offset to the next entry, the caller
1775 * will overwrite it for the last entry
1776 * that's why we always include the padding
1778 SIVAL(pdata,0,pad);
1780 * set padding to zero
1782 if (do_pad) {
1783 memset(p, 0, pad - len);
1784 p = pdata + pad;
1785 } else {
1786 p = pdata + len;
1788 break;
1790 case SMB_FIND_FILE_DIRECTORY_INFO:
1791 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1792 p += 4;
1793 SIVAL(p,0,reskey); p += 4;
1794 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1798 SOFF_T(p,0,file_size); p += 8;
1799 SOFF_T(p,0,allocation_size); p += 8;
1800 SIVAL(p,0,mode); p += 4;
1801 len = srvstr_push(base_data, flags2,
1802 p + 4, fname, PTR_DIFF(end_data, p+4),
1803 STR_TERMINATE_ASCII);
1804 SIVAL(p,0,len);
1805 p += 4 + len;
1807 len = PTR_DIFF(p, pdata);
1808 pad = (len + (align-1)) & ~(align-1);
1810 * offset to the next entry, the caller
1811 * will overwrite it for the last entry
1812 * that's why we always include the padding
1814 SIVAL(pdata,0,pad);
1816 * set padding to zero
1818 if (do_pad) {
1819 memset(p, 0, pad - len);
1820 p = pdata + pad;
1821 } else {
1822 p = pdata + len;
1824 break;
1826 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1827 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1828 p += 4;
1829 SIVAL(p,0,reskey); p += 4;
1830 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1831 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1832 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1834 SOFF_T(p,0,file_size); p += 8;
1835 SOFF_T(p,0,allocation_size); p += 8;
1836 SIVAL(p,0,mode); p += 4;
1837 q = p; p += 4; /* q is placeholder for name length. */
1839 unsigned int ea_size = estimate_ea_size(conn, NULL,
1840 smb_fname->base_name);
1841 SIVAL(p,0,ea_size); /* Extended attributes */
1842 p +=4;
1844 len = srvstr_push(base_data, flags2, p,
1845 fname, PTR_DIFF(end_data, p),
1846 STR_TERMINATE_ASCII);
1847 SIVAL(q, 0, len);
1848 p += len;
1850 len = PTR_DIFF(p, pdata);
1851 pad = (len + (align-1)) & ~(align-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1857 SIVAL(pdata,0,pad);
1859 * set padding to zero
1861 if (do_pad) {
1862 memset(p, 0, pad - len);
1863 p = pdata + pad;
1864 } else {
1865 p = pdata + len;
1867 break;
1869 case SMB_FIND_FILE_NAMES_INFO:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1871 p += 4;
1872 SIVAL(p,0,reskey); p += 4;
1873 p += 4;
1874 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1875 acl on a dir (tridge) */
1876 len = srvstr_push(base_data, flags2, p,
1877 fname, PTR_DIFF(end_data, p),
1878 STR_TERMINATE_ASCII);
1879 SIVAL(p, -4, len);
1880 p += len;
1882 len = PTR_DIFF(p, pdata);
1883 pad = (len + (align-1)) & ~(align-1);
1885 * offset to the next entry, the caller
1886 * will overwrite it for the last entry
1887 * that's why we always include the padding
1889 SIVAL(pdata,0,pad);
1891 * set padding to zero
1893 if (do_pad) {
1894 memset(p, 0, pad - len);
1895 p = pdata + pad;
1896 } else {
1897 p = pdata + len;
1899 break;
1901 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1902 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1903 p += 4;
1904 SIVAL(p,0,reskey); p += 4;
1905 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1909 SOFF_T(p,0,file_size); p += 8;
1910 SOFF_T(p,0,allocation_size); p += 8;
1911 SIVAL(p,0,mode); p += 4;
1912 q = p; p += 4; /* q is placeholder for name length. */
1914 unsigned int ea_size = estimate_ea_size(conn, NULL,
1915 smb_fname->base_name);
1916 SIVAL(p,0,ea_size); /* Extended attributes */
1917 p +=4;
1919 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1920 SBVAL(p,0,file_index); p += 8;
1921 len = srvstr_push(base_data, flags2, p,
1922 fname, PTR_DIFF(end_data, p),
1923 STR_TERMINATE_ASCII);
1924 SIVAL(q, 0, len);
1925 p += len;
1927 len = PTR_DIFF(p, pdata);
1928 pad = (len + (align-1)) & ~(align-1);
1930 * offset to the next entry, the caller
1931 * will overwrite it for the last entry
1932 * that's why we always include the padding
1934 SIVAL(pdata,0,pad);
1936 * set padding to zero
1938 if (do_pad) {
1939 memset(p, 0, pad - len);
1940 p = pdata + pad;
1941 } else {
1942 p = pdata + len;
1944 break;
1946 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1947 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1948 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1949 p += 4;
1950 SIVAL(p,0,reskey); p += 4;
1951 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1952 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1953 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1955 SOFF_T(p,0,file_size); p += 8;
1956 SOFF_T(p,0,allocation_size); p += 8;
1957 SIVAL(p,0,mode); p += 4;
1958 q = p; p += 4; /* q is placeholder for name length */
1960 unsigned int ea_size = estimate_ea_size(conn, NULL,
1961 smb_fname->base_name);
1962 SIVAL(p,0,ea_size); /* Extended attributes */
1963 p +=4;
1965 /* Clear the short name buffer. This is
1966 * IMPORTANT as not doing so will trigger
1967 * a Win2k client bug. JRA.
1969 if (!was_8_3 && check_mangled_names) {
1970 char mangled_name[13]; /* mangled 8.3 name. */
1971 if (!name_to_8_3(fname,mangled_name,True,
1972 conn->params)) {
1973 /* Error - mangle failed ! */
1974 memset(mangled_name,'\0',12);
1976 mangled_name[12] = 0;
1977 len = srvstr_push(base_data, flags2,
1978 p+2, mangled_name, 24,
1979 STR_UPPER|STR_UNICODE);
1980 SSVAL(p, 0, len);
1981 if (len < 24) {
1982 memset(p + 2 + len,'\0',24 - len);
1984 SSVAL(p, 0, len);
1985 } else {
1986 memset(p,'\0',26);
1988 p += 26;
1989 SSVAL(p,0,0); p += 2; /* Reserved ? */
1990 SBVAL(p,0,file_index); p += 8;
1991 len = srvstr_push(base_data, flags2, p,
1992 fname, PTR_DIFF(end_data, p),
1993 STR_TERMINATE_ASCII);
1994 SIVAL(q,0,len);
1995 p += len;
1997 len = PTR_DIFF(p, pdata);
1998 pad = (len + (align-1)) & ~(align-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2004 SIVAL(pdata,0,pad);
2006 * set padding to zero
2008 if (do_pad) {
2009 memset(p, 0, pad - len);
2010 p = pdata + pad;
2011 } else {
2012 p = pdata + len;
2014 break;
2016 /* CIFS UNIX Extension. */
2018 case SMB_FIND_FILE_UNIX:
2019 case SMB_FIND_FILE_UNIX_INFO2:
2020 p+= 4;
2021 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2023 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2025 if (info_level == SMB_FIND_FILE_UNIX) {
2026 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2027 p = store_file_unix_basic(conn, p,
2028 NULL, &smb_fname->st);
2029 len = srvstr_push(base_data, flags2, p,
2030 fname, PTR_DIFF(end_data, p),
2031 STR_TERMINATE);
2032 } else {
2033 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2034 p = store_file_unix_basic_info2(conn, p,
2035 NULL, &smb_fname->st);
2036 nameptr = p;
2037 p += 4;
2038 len = srvstr_push(base_data, flags2, p, fname,
2039 PTR_DIFF(end_data, p), 0);
2040 SIVAL(nameptr, 0, len);
2043 p += len;
2045 len = PTR_DIFF(p, pdata);
2046 pad = (len + (align-1)) & ~(align-1);
2048 * offset to the next entry, the caller
2049 * will overwrite it for the last entry
2050 * that's why we always include the padding
2052 SIVAL(pdata,0,pad);
2054 * set padding to zero
2056 if (do_pad) {
2057 memset(p, 0, pad - len);
2058 p = pdata + pad;
2059 } else {
2060 p = pdata + len;
2062 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2064 break;
2066 default:
2067 return false;
2070 if (PTR_DIFF(p,pdata) > space_remaining) {
2071 *out_of_space = true;
2072 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2073 "(wanted %u, had %d)\n",
2074 (unsigned int)PTR_DIFF(p,pdata),
2075 space_remaining ));
2076 return false; /* Not finished - just out of space */
2079 /* Setup the last entry pointer, as an offset from base_data */
2080 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2081 /* Advance the data pointer to the next slot */
2082 *ppdata = p;
2084 return true;
2087 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2088 connection_struct *conn,
2089 struct dptr_struct *dirptr,
2090 uint16 flags2,
2091 const char *path_mask,
2092 uint32 dirtype,
2093 int info_level,
2094 int requires_resume_key,
2095 bool dont_descend,
2096 bool ask_sharemode,
2097 uint8_t align,
2098 bool do_pad,
2099 char **ppdata,
2100 char *base_data,
2101 char *end_data,
2102 int space_remaining,
2103 bool *out_of_space,
2104 bool *got_exact_match,
2105 int *_last_entry_off,
2106 struct ea_list *name_list)
2108 const char *p;
2109 const char *mask = NULL;
2110 long prev_dirpos = 0;
2111 uint32_t mode = 0;
2112 char *fname = NULL;
2113 struct smb_filename *smb_fname = NULL;
2114 struct smbd_dirptr_lanman2_state state;
2115 bool ok;
2116 uint64_t last_entry_off = 0;
2118 ZERO_STRUCT(state);
2119 state.conn = conn;
2120 state.info_level = info_level;
2121 state.check_mangled_names = lp_manglednames(conn->params);
2122 state.has_wild = dptr_has_wild(dirptr);
2123 state.got_exact_match = false;
2125 *out_of_space = false;
2126 *got_exact_match = false;
2128 p = strrchr_m(path_mask,'/');
2129 if(p != NULL) {
2130 if(p[1] == '\0') {
2131 mask = "*.*";
2132 } else {
2133 mask = p+1;
2135 } else {
2136 mask = path_mask;
2139 ok = smbd_dirptr_get_entry(ctx,
2140 dirptr,
2141 mask,
2142 dirtype,
2143 dont_descend,
2144 ask_sharemode,
2145 smbd_dirptr_lanman2_match_fn,
2146 smbd_dirptr_lanman2_mode_fn,
2147 &state,
2148 &fname,
2149 &smb_fname,
2150 &mode,
2151 &prev_dirpos);
2152 if (!ok) {
2153 return false;
2156 *got_exact_match = state.got_exact_match;
2158 ok = smbd_marshall_dir_entry(ctx,
2159 conn,
2160 flags2,
2161 info_level,
2162 name_list,
2163 state.check_mangled_names,
2164 requires_resume_key,
2165 mode,
2166 fname,
2167 smb_fname,
2168 space_remaining,
2169 align,
2170 do_pad,
2171 base_data,
2172 ppdata,
2173 end_data,
2174 out_of_space,
2175 &last_entry_off);
2176 TALLOC_FREE(fname);
2177 TALLOC_FREE(smb_fname);
2178 if (*out_of_space) {
2179 dptr_SeekDir(dirptr, prev_dirpos);
2180 return false;
2182 if (!ok) {
2183 return false;
2186 *_last_entry_off = last_entry_off;
2187 return true;
2190 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2191 connection_struct *conn,
2192 struct dptr_struct *dirptr,
2193 uint16 flags2,
2194 const char *path_mask,
2195 uint32 dirtype,
2196 int info_level,
2197 bool requires_resume_key,
2198 bool dont_descend,
2199 bool ask_sharemode,
2200 char **ppdata,
2201 char *base_data,
2202 char *end_data,
2203 int space_remaining,
2204 bool *out_of_space,
2205 bool *got_exact_match,
2206 int *last_entry_off,
2207 struct ea_list *name_list)
2209 uint8_t align = 4;
2210 const bool do_pad = true;
2212 if (info_level >= 1 && info_level <= 3) {
2213 /* No alignment on earlier info levels. */
2214 align = 1;
2217 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2218 path_mask, dirtype, info_level,
2219 requires_resume_key, dont_descend, ask_sharemode,
2220 align, do_pad,
2221 ppdata, base_data, end_data,
2222 space_remaining,
2223 out_of_space, got_exact_match,
2224 last_entry_off, name_list);
2227 /****************************************************************************
2228 Reply to a TRANS2_FINDFIRST.
2229 ****************************************************************************/
2231 static void call_trans2findfirst(connection_struct *conn,
2232 struct smb_request *req,
2233 char **pparams, int total_params,
2234 char **ppdata, int total_data,
2235 unsigned int max_data_bytes)
2237 /* We must be careful here that we don't return more than the
2238 allowed number of data bytes. If this means returning fewer than
2239 maxentries then so be it. We assume that the redirector has
2240 enough room for the fixed number of parameter bytes it has
2241 requested. */
2242 struct smb_filename *smb_dname = NULL;
2243 char *params = *pparams;
2244 char *pdata = *ppdata;
2245 char *data_end;
2246 uint32 dirtype;
2247 int maxentries;
2248 uint16 findfirst_flags;
2249 bool close_after_first;
2250 bool close_if_end;
2251 bool requires_resume_key;
2252 int info_level;
2253 char *directory = NULL;
2254 char *mask = NULL;
2255 char *p;
2256 int last_entry_off=0;
2257 int dptr_num = -1;
2258 int numentries = 0;
2259 int i;
2260 bool finished = False;
2261 bool dont_descend = False;
2262 bool out_of_space = False;
2263 int space_remaining;
2264 bool mask_contains_wcard = False;
2265 struct ea_list *ea_list = NULL;
2266 NTSTATUS ntstatus = NT_STATUS_OK;
2267 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2268 TALLOC_CTX *ctx = talloc_tos();
2269 struct dptr_struct *dirptr = NULL;
2270 struct smbd_server_connection *sconn = req->sconn;
2272 if (total_params < 13) {
2273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2274 goto out;
2277 dirtype = SVAL(params,0);
2278 maxentries = SVAL(params,2);
2279 findfirst_flags = SVAL(params,4);
2280 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2281 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2282 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2283 info_level = SVAL(params,6);
2285 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2286 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2287 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2288 info_level, max_data_bytes));
2290 if (!maxentries) {
2291 /* W2K3 seems to treat zero as 1. */
2292 maxentries = 1;
2295 switch (info_level) {
2296 case SMB_FIND_INFO_STANDARD:
2297 case SMB_FIND_EA_SIZE:
2298 case SMB_FIND_EA_LIST:
2299 case SMB_FIND_FILE_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2301 case SMB_FIND_FILE_NAMES_INFO:
2302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2303 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2304 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2305 break;
2306 case SMB_FIND_FILE_UNIX:
2307 case SMB_FIND_FILE_UNIX_INFO2:
2308 /* Always use filesystem for UNIX mtime query. */
2309 ask_sharemode = false;
2310 if (!lp_unix_extensions()) {
2311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2312 goto out;
2314 break;
2315 default:
2316 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2317 goto out;
2320 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2321 params+12, total_params - 12,
2322 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2323 if (!NT_STATUS_IS_OK(ntstatus)) {
2324 reply_nterror(req, ntstatus);
2325 goto out;
2328 ntstatus = filename_convert(ctx, conn,
2329 req->flags2 & FLAGS2_DFS_PATHNAMES,
2330 directory,
2331 (UCF_SAVE_LCOMP |
2332 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2333 &mask_contains_wcard,
2334 &smb_dname);
2335 if (!NT_STATUS_IS_OK(ntstatus)) {
2336 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2337 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2338 ERRSRV, ERRbadpath);
2339 goto out;
2341 reply_nterror(req, ntstatus);
2342 goto out;
2345 mask = smb_dname->original_lcomp;
2347 directory = smb_dname->base_name;
2349 p = strrchr_m(directory,'/');
2350 if(p == NULL) {
2351 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2352 if((directory[0] == '.') && (directory[1] == '\0')) {
2353 mask = talloc_strdup(ctx,"*");
2354 if (!mask) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 goto out;
2358 mask_contains_wcard = True;
2360 } else {
2361 *p = 0;
2364 if (p == NULL || p == directory) {
2365 /* Ensure we don't have a directory name of "". */
2366 directory = talloc_strdup(talloc_tos(), ".");
2367 if (!directory) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 goto out;
2373 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2375 if (info_level == SMB_FIND_EA_LIST) {
2376 uint32 ea_size;
2378 if (total_data < 4) {
2379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2380 goto out;
2383 ea_size = IVAL(pdata,0);
2384 if (ea_size != total_data) {
2385 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2386 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2388 goto out;
2391 if (!lp_ea_support(SNUM(conn))) {
2392 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2393 goto out;
2396 /* Pull out the list of names. */
2397 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2398 if (!ea_list) {
2399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2400 goto out;
2404 *ppdata = (char *)SMB_REALLOC(
2405 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2406 if(*ppdata == NULL ) {
2407 reply_nterror(req, NT_STATUS_NO_MEMORY);
2408 goto out;
2410 pdata = *ppdata;
2411 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2413 /* Realloc the params space */
2414 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2415 if (*pparams == NULL) {
2416 reply_nterror(req, NT_STATUS_NO_MEMORY);
2417 goto out;
2419 params = *pparams;
2421 /* Save the wildcard match and attribs we are using on this directory -
2422 needed as lanman2 assumes these are being saved between calls */
2424 ntstatus = dptr_create(conn,
2425 NULL, /* fsp */
2426 directory,
2427 False,
2428 True,
2429 req->smbpid,
2430 mask,
2431 mask_contains_wcard,
2432 dirtype,
2433 &dirptr);
2435 if (!NT_STATUS_IS_OK(ntstatus)) {
2436 reply_nterror(req, ntstatus);
2437 goto out;
2440 dptr_num = dptr_dnum(dirptr);
2441 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2443 /* Initialize per TRANS2_FIND_FIRST operation data */
2444 dptr_init_search_op(dirptr);
2446 /* We don't need to check for VOL here as this is returned by
2447 a different TRANS2 call. */
2449 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2450 directory,lp_dontdescend(SNUM(conn))));
2451 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2452 dont_descend = True;
2454 p = pdata;
2455 space_remaining = max_data_bytes;
2456 out_of_space = False;
2458 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2459 bool got_exact_match = False;
2461 /* this is a heuristic to avoid seeking the dirptr except when
2462 absolutely necessary. It allows for a filename of about 40 chars */
2463 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2464 out_of_space = True;
2465 finished = False;
2466 } else {
2467 finished = !get_lanman2_dir_entry(ctx,
2468 conn,
2469 dirptr,
2470 req->flags2,
2471 mask,dirtype,info_level,
2472 requires_resume_key,dont_descend,
2473 ask_sharemode,
2474 &p,pdata,data_end,
2475 space_remaining, &out_of_space,
2476 &got_exact_match,
2477 &last_entry_off, ea_list);
2480 if (finished && out_of_space)
2481 finished = False;
2483 if (!finished && !out_of_space)
2484 numentries++;
2487 * As an optimisation if we know we aren't looking
2488 * for a wildcard name (ie. the name matches the wildcard exactly)
2489 * then we can finish on any (first) match.
2490 * This speeds up large directory searches. JRA.
2493 if(got_exact_match)
2494 finished = True;
2496 /* Ensure space_remaining never goes -ve. */
2497 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2498 space_remaining = 0;
2499 out_of_space = true;
2500 } else {
2501 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2505 /* Check if we can close the dirptr */
2506 if(close_after_first || (finished && close_if_end)) {
2507 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2508 dptr_close(sconn, &dptr_num);
2512 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2513 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2514 * the protocol level is less than NT1. Tested with smbclient. JRA.
2515 * This should fix the OS/2 client bug #2335.
2518 if(numentries == 0) {
2519 dptr_close(sconn, &dptr_num);
2520 if (get_Protocol() < PROTOCOL_NT1) {
2521 reply_force_doserror(req, ERRDOS, ERRnofiles);
2522 goto out;
2523 } else {
2524 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2525 ERRDOS, ERRbadfile);
2526 goto out;
2530 /* At this point pdata points to numentries directory entries. */
2532 /* Set up the return parameter block */
2533 SSVAL(params,0,dptr_num);
2534 SSVAL(params,2,numentries);
2535 SSVAL(params,4,finished);
2536 SSVAL(params,6,0); /* Never an EA error */
2537 SSVAL(params,8,last_entry_off);
2539 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2540 max_data_bytes);
2542 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2543 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2544 if (!directory) {
2545 reply_nterror(req, NT_STATUS_NO_MEMORY);
2549 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2550 smb_fn_name(req->cmd),
2551 mask, directory, dirtype, numentries ) );
2554 * Force a name mangle here to ensure that the
2555 * mask as an 8.3 name is top of the mangled cache.
2556 * The reasons for this are subtle. Don't remove
2557 * this code unless you know what you are doing
2558 * (see PR#13758). JRA.
2561 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2562 char mangled_name[13];
2563 name_to_8_3(mask, mangled_name, True, conn->params);
2565 out:
2566 TALLOC_FREE(smb_dname);
2567 return;
2570 /****************************************************************************
2571 Reply to a TRANS2_FINDNEXT.
2572 ****************************************************************************/
2574 static void call_trans2findnext(connection_struct *conn,
2575 struct smb_request *req,
2576 char **pparams, int total_params,
2577 char **ppdata, int total_data,
2578 unsigned int max_data_bytes)
2580 /* We must be careful here that we don't return more than the
2581 allowed number of data bytes. If this means returning fewer than
2582 maxentries then so be it. We assume that the redirector has
2583 enough room for the fixed number of parameter bytes it has
2584 requested. */
2585 char *params = *pparams;
2586 char *pdata = *ppdata;
2587 char *data_end;
2588 int dptr_num;
2589 int maxentries;
2590 uint16 info_level;
2591 uint32 resume_key;
2592 uint16 findnext_flags;
2593 bool close_after_request;
2594 bool close_if_end;
2595 bool requires_resume_key;
2596 bool continue_bit;
2597 bool mask_contains_wcard = False;
2598 char *resume_name = NULL;
2599 const char *mask = NULL;
2600 const char *directory = NULL;
2601 char *p = NULL;
2602 uint16 dirtype;
2603 int numentries = 0;
2604 int i, last_entry_off=0;
2605 bool finished = False;
2606 bool dont_descend = False;
2607 bool out_of_space = False;
2608 int space_remaining;
2609 struct ea_list *ea_list = NULL;
2610 NTSTATUS ntstatus = NT_STATUS_OK;
2611 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2612 TALLOC_CTX *ctx = talloc_tos();
2613 struct dptr_struct *dirptr;
2614 struct smbd_server_connection *sconn = req->sconn;
2616 if (total_params < 13) {
2617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2618 return;
2621 dptr_num = SVAL(params,0);
2622 maxentries = SVAL(params,2);
2623 info_level = SVAL(params,4);
2624 resume_key = IVAL(params,6);
2625 findnext_flags = SVAL(params,10);
2626 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2627 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2628 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2629 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2631 if (!continue_bit) {
2632 /* We only need resume_name if continue_bit is zero. */
2633 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2634 params+12,
2635 total_params - 12, STR_TERMINATE, &ntstatus,
2636 &mask_contains_wcard);
2637 if (!NT_STATUS_IS_OK(ntstatus)) {
2638 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2639 complain (it thinks we're asking for the directory above the shared
2640 path or an invalid name). Catch this as the resume name is only compared, never used in
2641 a file access. JRA. */
2642 srvstr_pull_talloc(ctx, params, req->flags2,
2643 &resume_name, params+12,
2644 total_params - 12,
2645 STR_TERMINATE);
2647 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2648 reply_nterror(req, ntstatus);
2649 return;
2654 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2655 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2656 resume_key = %d resume name = %s continue=%d level = %d\n",
2657 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2658 requires_resume_key, resume_key,
2659 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2661 if (!maxentries) {
2662 /* W2K3 seems to treat zero as 1. */
2663 maxentries = 1;
2666 switch (info_level) {
2667 case SMB_FIND_INFO_STANDARD:
2668 case SMB_FIND_EA_SIZE:
2669 case SMB_FIND_EA_LIST:
2670 case SMB_FIND_FILE_DIRECTORY_INFO:
2671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2672 case SMB_FIND_FILE_NAMES_INFO:
2673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2674 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2675 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2676 break;
2677 case SMB_FIND_FILE_UNIX:
2678 case SMB_FIND_FILE_UNIX_INFO2:
2679 /* Always use filesystem for UNIX mtime query. */
2680 ask_sharemode = false;
2681 if (!lp_unix_extensions()) {
2682 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2683 return;
2685 break;
2686 default:
2687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2688 return;
2691 if (info_level == SMB_FIND_EA_LIST) {
2692 uint32 ea_size;
2694 if (total_data < 4) {
2695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2696 return;
2699 ea_size = IVAL(pdata,0);
2700 if (ea_size != total_data) {
2701 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2702 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2704 return;
2707 if (!lp_ea_support(SNUM(conn))) {
2708 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2709 return;
2712 /* Pull out the list of names. */
2713 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2714 if (!ea_list) {
2715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2716 return;
2720 *ppdata = (char *)SMB_REALLOC(
2721 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2722 if(*ppdata == NULL) {
2723 reply_nterror(req, NT_STATUS_NO_MEMORY);
2724 return;
2727 pdata = *ppdata;
2728 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2730 /* Realloc the params space */
2731 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2732 if(*pparams == NULL ) {
2733 reply_nterror(req, NT_STATUS_NO_MEMORY);
2734 return;
2737 params = *pparams;
2739 /* Check that the dptr is valid */
2740 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2741 reply_nterror(req, STATUS_NO_MORE_FILES);
2742 return;
2745 directory = dptr_path(sconn, dptr_num);
2747 /* Get the wildcard mask from the dptr */
2748 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2749 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2750 reply_nterror(req, STATUS_NO_MORE_FILES);
2751 return;
2754 mask = p;
2756 /* Get the attr mask from the dptr */
2757 dirtype = dptr_attr(sconn, dptr_num);
2759 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2760 dptr_num, mask, dirtype,
2761 (long)dirptr,
2762 dptr_TellDir(dirptr)));
2764 /* Initialize per TRANS2_FIND_NEXT operation data */
2765 dptr_init_search_op(dirptr);
2767 /* We don't need to check for VOL here as this is returned by
2768 a different TRANS2 call. */
2770 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2771 directory,lp_dontdescend(SNUM(conn))));
2772 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2773 dont_descend = True;
2775 p = pdata;
2776 space_remaining = max_data_bytes;
2777 out_of_space = False;
2780 * Seek to the correct position. We no longer use the resume key but
2781 * depend on the last file name instead.
2784 if(!continue_bit && resume_name && *resume_name) {
2785 SMB_STRUCT_STAT st;
2787 long current_pos = 0;
2789 * Remember, name_to_8_3 is called by
2790 * get_lanman2_dir_entry(), so the resume name
2791 * could be mangled. Ensure we check the unmangled name.
2794 if (mangle_is_mangled(resume_name, conn->params)) {
2795 char *new_resume_name = NULL;
2796 mangle_lookup_name_from_8_3(ctx,
2797 resume_name,
2798 &new_resume_name,
2799 conn->params);
2800 if (new_resume_name) {
2801 resume_name = new_resume_name;
2806 * Fix for NT redirector problem triggered by resume key indexes
2807 * changing between directory scans. We now return a resume key of 0
2808 * and instead look for the filename to continue from (also given
2809 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2810 * findfirst/findnext (as is usual) then the directory pointer
2811 * should already be at the correct place.
2814 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2815 } /* end if resume_name && !continue_bit */
2817 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2818 bool got_exact_match = False;
2820 /* this is a heuristic to avoid seeking the dirptr except when
2821 absolutely necessary. It allows for a filename of about 40 chars */
2822 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2823 out_of_space = True;
2824 finished = False;
2825 } else {
2826 finished = !get_lanman2_dir_entry(ctx,
2827 conn,
2828 dirptr,
2829 req->flags2,
2830 mask,dirtype,info_level,
2831 requires_resume_key,dont_descend,
2832 ask_sharemode,
2833 &p,pdata,data_end,
2834 space_remaining, &out_of_space,
2835 &got_exact_match,
2836 &last_entry_off, ea_list);
2839 if (finished && out_of_space)
2840 finished = False;
2842 if (!finished && !out_of_space)
2843 numentries++;
2846 * As an optimisation if we know we aren't looking
2847 * for a wildcard name (ie. the name matches the wildcard exactly)
2848 * then we can finish on any (first) match.
2849 * This speeds up large directory searches. JRA.
2852 if(got_exact_match)
2853 finished = True;
2855 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2858 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2859 smb_fn_name(req->cmd),
2860 mask, directory, dirtype, numentries ) );
2862 /* Check if we can close the dirptr */
2863 if(close_after_request || (finished && close_if_end)) {
2864 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2865 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2868 /* Set up the return parameter block */
2869 SSVAL(params,0,numentries);
2870 SSVAL(params,2,finished);
2871 SSVAL(params,4,0); /* Never an EA error */
2872 SSVAL(params,6,last_entry_off);
2874 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2875 max_data_bytes);
2877 return;
2880 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2882 E_md4hash(lp_servicename(SNUM(conn)),objid);
2883 return objid;
2886 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2888 SMB_ASSERT(extended_info != NULL);
2890 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2891 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2892 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2893 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2894 #ifdef SAMBA_VERSION_REVISION
2895 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2896 #endif
2897 extended_info->samba_subversion = 0;
2898 #ifdef SAMBA_VERSION_RC_RELEASE
2899 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2900 #else
2901 #ifdef SAMBA_VERSION_PRE_RELEASE
2902 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2903 #endif
2904 #endif
2905 #ifdef SAMBA_VERSION_VENDOR_PATCH
2906 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2907 #endif
2908 extended_info->samba_gitcommitdate = 0;
2909 #ifdef SAMBA_VERSION_COMMIT_TIME
2910 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2911 #endif
2913 memset(extended_info->samba_version_string, 0,
2914 sizeof(extended_info->samba_version_string));
2916 snprintf (extended_info->samba_version_string,
2917 sizeof(extended_info->samba_version_string),
2918 "%s", samba_version_string());
2921 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2922 TALLOC_CTX *mem_ctx,
2923 uint16_t info_level,
2924 uint16_t flags2,
2925 unsigned int max_data_bytes,
2926 char **ppdata,
2927 int *ret_data_len)
2929 char *pdata, *end_data;
2930 int data_len = 0, len;
2931 const char *vname = volume_label(SNUM(conn));
2932 int snum = SNUM(conn);
2933 char *fstype = lp_fstype(SNUM(conn));
2934 uint32 additional_flags = 0;
2935 struct smb_filename smb_fname_dot;
2936 SMB_STRUCT_STAT st;
2938 if (IS_IPC(conn)) {
2939 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2940 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2941 "info level (0x%x) on IPC$.\n",
2942 (unsigned int)info_level));
2943 return NT_STATUS_ACCESS_DENIED;
2947 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2949 ZERO_STRUCT(smb_fname_dot);
2950 smb_fname_dot.base_name = discard_const_p(char, ".");
2952 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2953 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2954 return map_nt_error_from_unix(errno);
2957 st = smb_fname_dot.st;
2959 *ppdata = (char *)SMB_REALLOC(
2960 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2961 if (*ppdata == NULL) {
2962 return NT_STATUS_NO_MEMORY;
2965 pdata = *ppdata;
2966 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2967 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2969 switch (info_level) {
2970 case SMB_INFO_ALLOCATION:
2972 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2973 data_len = 18;
2974 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2975 return map_nt_error_from_unix(errno);
2978 block_size = lp_block_size(snum);
2979 if (bsize < block_size) {
2980 uint64_t factor = block_size/bsize;
2981 bsize = block_size;
2982 dsize /= factor;
2983 dfree /= factor;
2985 if (bsize > block_size) {
2986 uint64_t factor = bsize/block_size;
2987 bsize = block_size;
2988 dsize *= factor;
2989 dfree *= factor;
2991 bytes_per_sector = 512;
2992 sectors_per_unit = bsize/bytes_per_sector;
2994 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2995 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2996 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2998 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2999 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3000 SIVAL(pdata,l1_cUnit,dsize);
3001 SIVAL(pdata,l1_cUnitAvail,dfree);
3002 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3003 break;
3006 case SMB_INFO_VOLUME:
3007 /* Return volume name */
3009 * Add volume serial number - hash of a combination of
3010 * the called hostname and the service name.
3012 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3014 * Win2k3 and previous mess this up by sending a name length
3015 * one byte short. I believe only older clients (OS/2 Win9x) use
3016 * this call so try fixing this by adding a terminating null to
3017 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3019 len = srvstr_push(
3020 pdata, flags2,
3021 pdata+l2_vol_szVolLabel, vname,
3022 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3023 STR_NOALIGN|STR_TERMINATE);
3024 SCVAL(pdata,l2_vol_cch,len);
3025 data_len = l2_vol_szVolLabel + len;
3026 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3027 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3028 len, vname));
3029 break;
3031 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3032 case SMB_FS_ATTRIBUTE_INFORMATION:
3034 additional_flags = 0;
3035 #if defined(HAVE_SYS_QUOTAS)
3036 additional_flags |= FILE_VOLUME_QUOTAS;
3037 #endif
3039 if(lp_nt_acl_support(SNUM(conn))) {
3040 additional_flags |= FILE_PERSISTENT_ACLS;
3043 /* Capabilities are filled in at connection time through STATVFS call */
3044 additional_flags |= conn->fs_capabilities;
3045 additional_flags |= lp_parm_int(conn->params->service,
3046 "share", "fake_fscaps",
3049 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3050 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3051 additional_flags); /* FS ATTRIBUTES */
3053 SIVAL(pdata,4,255); /* Max filename component length */
3054 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3055 and will think we can't do long filenames */
3056 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3057 PTR_DIFF(end_data, pdata+12),
3058 STR_UNICODE);
3059 SIVAL(pdata,8,len);
3060 data_len = 12 + len;
3061 break;
3063 case SMB_QUERY_FS_LABEL_INFO:
3064 case SMB_FS_LABEL_INFORMATION:
3065 len = srvstr_push(pdata, flags2, pdata+4, vname,
3066 PTR_DIFF(end_data, pdata+4), 0);
3067 data_len = 4 + len;
3068 SIVAL(pdata,0,len);
3069 break;
3071 case SMB_QUERY_FS_VOLUME_INFO:
3072 case SMB_FS_VOLUME_INFORMATION:
3075 * Add volume serial number - hash of a combination of
3076 * the called hostname and the service name.
3078 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3079 (str_checksum(get_local_machine_name())<<16));
3081 /* Max label len is 32 characters. */
3082 len = srvstr_push(pdata, flags2, pdata+18, vname,
3083 PTR_DIFF(end_data, pdata+18),
3084 STR_UNICODE);
3085 SIVAL(pdata,12,len);
3086 data_len = 18+len;
3088 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3089 (int)strlen(vname),vname, lp_servicename(snum)));
3090 break;
3092 case SMB_QUERY_FS_SIZE_INFO:
3093 case SMB_FS_SIZE_INFORMATION:
3095 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3096 data_len = 24;
3097 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3098 return map_nt_error_from_unix(errno);
3100 block_size = lp_block_size(snum);
3101 if (bsize < block_size) {
3102 uint64_t factor = block_size/bsize;
3103 bsize = block_size;
3104 dsize /= factor;
3105 dfree /= factor;
3107 if (bsize > block_size) {
3108 uint64_t factor = bsize/block_size;
3109 bsize = block_size;
3110 dsize *= factor;
3111 dfree *= factor;
3113 bytes_per_sector = 512;
3114 sectors_per_unit = bsize/bytes_per_sector;
3115 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3116 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3117 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3118 SBIG_UINT(pdata,0,dsize);
3119 SBIG_UINT(pdata,8,dfree);
3120 SIVAL(pdata,16,sectors_per_unit);
3121 SIVAL(pdata,20,bytes_per_sector);
3122 break;
3125 case SMB_FS_FULL_SIZE_INFORMATION:
3127 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3128 data_len = 32;
3129 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3130 return map_nt_error_from_unix(errno);
3132 block_size = lp_block_size(snum);
3133 if (bsize < block_size) {
3134 uint64_t factor = block_size/bsize;
3135 bsize = block_size;
3136 dsize /= factor;
3137 dfree /= factor;
3139 if (bsize > block_size) {
3140 uint64_t factor = bsize/block_size;
3141 bsize = block_size;
3142 dsize *= factor;
3143 dfree *= factor;
3145 bytes_per_sector = 512;
3146 sectors_per_unit = bsize/bytes_per_sector;
3147 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3148 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3149 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3150 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3151 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3152 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3153 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3154 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3155 break;
3158 case SMB_QUERY_FS_DEVICE_INFO:
3159 case SMB_FS_DEVICE_INFORMATION:
3161 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3163 if (!CAN_WRITE(conn)) {
3164 characteristics |= FILE_READ_ONLY_DEVICE;
3166 data_len = 8;
3167 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3168 SIVAL(pdata,4,characteristics);
3169 break;
3172 #ifdef HAVE_SYS_QUOTAS
3173 case SMB_FS_QUOTA_INFORMATION:
3175 * what we have to send --metze:
3177 * Unknown1: 24 NULL bytes
3178 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3179 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3180 * Quota Flags: 2 byte :
3181 * Unknown3: 6 NULL bytes
3183 * 48 bytes total
3185 * details for Quota Flags:
3187 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3188 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3189 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3190 * 0x0001 Enable Quotas: enable quota for this fs
3194 /* we need to fake up a fsp here,
3195 * because its not send in this call
3197 files_struct fsp;
3198 SMB_NTQUOTA_STRUCT quotas;
3200 ZERO_STRUCT(fsp);
3201 ZERO_STRUCT(quotas);
3203 fsp.conn = conn;
3204 fsp.fnum = -1;
3206 /* access check */
3207 if (get_current_uid(conn) != 0) {
3208 DEBUG(0,("set_user_quota: access_denied "
3209 "service [%s] user [%s]\n",
3210 lp_servicename(SNUM(conn)),
3211 conn->session_info->unix_name));
3212 return NT_STATUS_ACCESS_DENIED;
3215 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3216 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3217 return map_nt_error_from_unix(errno);
3220 data_len = 48;
3222 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3223 lp_servicename(SNUM(conn))));
3225 /* Unknown1 24 NULL bytes*/
3226 SBIG_UINT(pdata,0,(uint64_t)0);
3227 SBIG_UINT(pdata,8,(uint64_t)0);
3228 SBIG_UINT(pdata,16,(uint64_t)0);
3230 /* Default Soft Quota 8 bytes */
3231 SBIG_UINT(pdata,24,quotas.softlim);
3233 /* Default Hard Quota 8 bytes */
3234 SBIG_UINT(pdata,32,quotas.hardlim);
3236 /* Quota flag 2 bytes */
3237 SSVAL(pdata,40,quotas.qflags);
3239 /* Unknown3 6 NULL bytes */
3240 SSVAL(pdata,42,0);
3241 SIVAL(pdata,44,0);
3243 break;
3245 #endif /* HAVE_SYS_QUOTAS */
3246 case SMB_FS_OBJECTID_INFORMATION:
3248 unsigned char objid[16];
3249 struct smb_extended_info extended_info;
3250 memcpy(pdata,create_volume_objectid(conn, objid),16);
3251 samba_extended_info_version (&extended_info);
3252 SIVAL(pdata,16,extended_info.samba_magic);
3253 SIVAL(pdata,20,extended_info.samba_version);
3254 SIVAL(pdata,24,extended_info.samba_subversion);
3255 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3256 memcpy(pdata+36,extended_info.samba_version_string,28);
3257 data_len = 64;
3258 break;
3262 * Query the version and capabilities of the CIFS UNIX extensions
3263 * in use.
3266 case SMB_QUERY_CIFS_UNIX_INFO:
3268 bool large_write = lp_min_receive_file_size() &&
3269 !srv_is_signing_active(conn->sconn);
3270 bool large_read = !srv_is_signing_active(conn->sconn);
3271 int encrypt_caps = 0;
3273 if (!lp_unix_extensions()) {
3274 return NT_STATUS_INVALID_LEVEL;
3277 switch (conn->encrypt_level) {
3278 case 0:
3279 encrypt_caps = 0;
3280 break;
3281 case 1:
3282 case Auto:
3283 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3284 break;
3285 case Required:
3286 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3287 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3288 large_write = false;
3289 large_read = false;
3290 break;
3293 data_len = 12;
3294 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3295 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3297 /* We have POSIX ACLs, pathname, encryption,
3298 * large read/write, and locking capability. */
3300 SBIG_UINT(pdata,4,((uint64_t)(
3301 CIFS_UNIX_POSIX_ACLS_CAP|
3302 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3303 CIFS_UNIX_FCNTL_LOCKS_CAP|
3304 CIFS_UNIX_EXTATTR_CAP|
3305 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3306 encrypt_caps|
3307 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3308 (large_write ?
3309 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3310 break;
3313 case SMB_QUERY_POSIX_FS_INFO:
3315 int rc;
3316 vfs_statvfs_struct svfs;
3318 if (!lp_unix_extensions()) {
3319 return NT_STATUS_INVALID_LEVEL;
3322 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3324 if (!rc) {
3325 data_len = 56;
3326 SIVAL(pdata,0,svfs.OptimalTransferSize);
3327 SIVAL(pdata,4,svfs.BlockSize);
3328 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3329 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3330 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3331 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3332 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3333 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3334 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3335 #ifdef EOPNOTSUPP
3336 } else if (rc == EOPNOTSUPP) {
3337 return NT_STATUS_INVALID_LEVEL;
3338 #endif /* EOPNOTSUPP */
3339 } else {
3340 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3341 return NT_STATUS_DOS(ERRSRV, ERRerror);
3343 break;
3346 case SMB_QUERY_POSIX_WHOAMI:
3348 uint32_t flags = 0;
3349 uint32_t sid_bytes;
3350 int i;
3352 if (!lp_unix_extensions()) {
3353 return NT_STATUS_INVALID_LEVEL;
3356 if (max_data_bytes < 40) {
3357 return NT_STATUS_BUFFER_TOO_SMALL;
3360 /* We ARE guest if global_sid_Builtin_Guests is
3361 * in our list of SIDs.
3363 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3364 conn->session_info->security_token)) {
3365 flags |= SMB_WHOAMI_GUEST;
3368 /* We are NOT guest if global_sid_Authenticated_Users
3369 * is in our list of SIDs.
3371 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3372 conn->session_info->security_token)) {
3373 flags &= ~SMB_WHOAMI_GUEST;
3376 /* NOTE: 8 bytes for UID/GID, irrespective of native
3377 * platform size. This matches
3378 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3380 data_len = 4 /* flags */
3381 + 4 /* flag mask */
3382 + 8 /* uid */
3383 + 8 /* gid */
3384 + 4 /* ngroups */
3385 + 4 /* num_sids */
3386 + 4 /* SID bytes */
3387 + 4 /* pad/reserved */
3388 + (conn->session_info->utok.ngroups * 8)
3389 /* groups list */
3390 + (conn->session_info->security_token->num_sids *
3391 SID_MAX_SIZE)
3392 /* SID list */;
3394 SIVAL(pdata, 0, flags);
3395 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3396 SBIG_UINT(pdata, 8,
3397 (uint64_t)conn->session_info->utok.uid);
3398 SBIG_UINT(pdata, 16,
3399 (uint64_t)conn->session_info->utok.gid);
3402 if (data_len >= max_data_bytes) {
3403 /* Potential overflow, skip the GIDs and SIDs. */
3405 SIVAL(pdata, 24, 0); /* num_groups */
3406 SIVAL(pdata, 28, 0); /* num_sids */
3407 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3408 SIVAL(pdata, 36, 0); /* reserved */
3410 data_len = 40;
3411 break;
3414 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3415 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3417 /* We walk the SID list twice, but this call is fairly
3418 * infrequent, and I don't expect that it's performance
3419 * sensitive -- jpeach
3421 for (i = 0, sid_bytes = 0;
3422 i < conn->session_info->security_token->num_sids; ++i) {
3423 sid_bytes += ndr_size_dom_sid(
3424 &conn->session_info->security_token->sids[i],
3428 /* SID list byte count */
3429 SIVAL(pdata, 32, sid_bytes);
3431 /* 4 bytes pad/reserved - must be zero */
3432 SIVAL(pdata, 36, 0);
3433 data_len = 40;
3435 /* GID list */
3436 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3437 SBIG_UINT(pdata, data_len,
3438 (uint64_t)conn->session_info->utok.groups[i]);
3439 data_len += 8;
3442 /* SID list */
3443 for (i = 0;
3444 i < conn->session_info->security_token->num_sids; ++i) {
3445 int sid_len = ndr_size_dom_sid(
3446 &conn->session_info->security_token->sids[i],
3449 sid_linearize(pdata + data_len, sid_len,
3450 &conn->session_info->security_token->sids[i]);
3451 data_len += sid_len;
3454 break;
3457 case SMB_MAC_QUERY_FS_INFO:
3459 * Thursby MAC extension... ONLY on NTFS filesystems
3460 * once we do streams then we don't need this
3462 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3463 data_len = 88;
3464 SIVAL(pdata,84,0x100); /* Don't support mac... */
3465 break;
3467 /* drop through */
3468 default:
3469 return NT_STATUS_INVALID_LEVEL;
3472 *ret_data_len = data_len;
3473 return NT_STATUS_OK;
3476 /****************************************************************************
3477 Reply to a TRANS2_QFSINFO (query filesystem info).
3478 ****************************************************************************/
3480 static void call_trans2qfsinfo(connection_struct *conn,
3481 struct smb_request *req,
3482 char **pparams, int total_params,
3483 char **ppdata, int total_data,
3484 unsigned int max_data_bytes)
3486 char *params = *pparams;
3487 uint16_t info_level;
3488 int data_len = 0;
3489 NTSTATUS status;
3491 if (total_params < 2) {
3492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3493 return;
3496 info_level = SVAL(params,0);
3498 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3499 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3500 DEBUG(0,("call_trans2qfsinfo: encryption required "
3501 "and info level 0x%x sent.\n",
3502 (unsigned int)info_level));
3503 exit_server_cleanly("encryption required "
3504 "on connection");
3505 return;
3509 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3511 status = smbd_do_qfsinfo(conn, req,
3512 info_level,
3513 req->flags2,
3514 max_data_bytes,
3515 ppdata, &data_len);
3516 if (!NT_STATUS_IS_OK(status)) {
3517 reply_nterror(req, status);
3518 return;
3521 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3522 max_data_bytes);
3524 DEBUG( 4, ( "%s info_level = %d\n",
3525 smb_fn_name(req->cmd), info_level) );
3527 return;
3530 /****************************************************************************
3531 Reply to a TRANS2_SETFSINFO (set filesystem info).
3532 ****************************************************************************/
3534 static void call_trans2setfsinfo(connection_struct *conn,
3535 struct smb_request *req,
3536 char **pparams, int total_params,
3537 char **ppdata, int total_data,
3538 unsigned int max_data_bytes)
3540 char *pdata = *ppdata;
3541 char *params = *pparams;
3542 uint16 info_level;
3544 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3546 /* */
3547 if (total_params < 4) {
3548 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3549 total_params));
3550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3551 return;
3554 info_level = SVAL(params,2);
3556 if (IS_IPC(conn)) {
3557 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3558 info_level != SMB_SET_CIFS_UNIX_INFO) {
3559 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3560 "info level (0x%x) on IPC$.\n",
3561 (unsigned int)info_level));
3562 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3563 return;
3567 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3568 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3569 DEBUG(0,("call_trans2setfsinfo: encryption required "
3570 "and info level 0x%x sent.\n",
3571 (unsigned int)info_level));
3572 exit_server_cleanly("encryption required "
3573 "on connection");
3574 return;
3578 switch(info_level) {
3579 case SMB_SET_CIFS_UNIX_INFO:
3581 uint16 client_unix_major;
3582 uint16 client_unix_minor;
3583 uint32 client_unix_cap_low;
3584 uint32 client_unix_cap_high;
3586 if (!lp_unix_extensions()) {
3587 reply_nterror(req,
3588 NT_STATUS_INVALID_LEVEL);
3589 return;
3592 /* There should be 12 bytes of capabilities set. */
3593 if (total_data < 8) {
3594 reply_nterror(
3595 req,
3596 NT_STATUS_INVALID_PARAMETER);
3597 return;
3599 client_unix_major = SVAL(pdata,0);
3600 client_unix_minor = SVAL(pdata,2);
3601 client_unix_cap_low = IVAL(pdata,4);
3602 client_unix_cap_high = IVAL(pdata,8);
3603 /* Just print these values for now. */
3604 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3605 cap_low = 0x%x, cap_high = 0x%x\n",
3606 (unsigned int)client_unix_major,
3607 (unsigned int)client_unix_minor,
3608 (unsigned int)client_unix_cap_low,
3609 (unsigned int)client_unix_cap_high ));
3611 /* Here is where we must switch to posix pathname processing... */
3612 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3613 lp_set_posix_pathnames();
3614 mangle_change_to_posix();
3617 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3618 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3619 /* Client that knows how to do posix locks,
3620 * but not posix open/mkdir operations. Set a
3621 * default type for read/write checks. */
3623 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3626 break;
3629 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3631 NTSTATUS status;
3632 size_t param_len = 0;
3633 size_t data_len = total_data;
3635 if (!lp_unix_extensions()) {
3636 reply_nterror(
3637 req,
3638 NT_STATUS_INVALID_LEVEL);
3639 return;
3642 if (lp_smb_encrypt(SNUM(conn)) == false) {
3643 reply_nterror(
3644 req,
3645 NT_STATUS_NOT_SUPPORTED);
3646 return;
3649 if (req->sconn->smb1.echo_handler.trusted_fde) {
3650 DEBUG( 2,("call_trans2setfsinfo: "
3651 "request transport encryption disabled"
3652 "with 'fork echo handler = yes'\n"));
3653 reply_nterror(
3654 req,
3655 NT_STATUS_NOT_SUPPORTED);
3656 return;
3659 DEBUG( 4,("call_trans2setfsinfo: "
3660 "request transport encryption.\n"));
3662 status = srv_request_encryption_setup(conn,
3663 (unsigned char **)ppdata,
3664 &data_len,
3665 (unsigned char **)pparams,
3666 &param_len);
3668 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3669 !NT_STATUS_IS_OK(status)) {
3670 reply_nterror(req, status);
3671 return;
3674 send_trans2_replies(conn, req,
3675 *pparams,
3676 param_len,
3677 *ppdata,
3678 data_len,
3679 max_data_bytes);
3681 if (NT_STATUS_IS_OK(status)) {
3682 /* Server-side transport
3683 * encryption is now *on*. */
3684 status = srv_encryption_start(conn);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 exit_server_cleanly(
3687 "Failure in setting "
3688 "up encrypted transport");
3691 return;
3694 case SMB_FS_QUOTA_INFORMATION:
3696 files_struct *fsp = NULL;
3697 SMB_NTQUOTA_STRUCT quotas;
3699 ZERO_STRUCT(quotas);
3701 /* access check */
3702 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3703 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3704 lp_servicename(SNUM(conn)),
3705 conn->session_info->unix_name));
3706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3707 return;
3710 /* note: normaly there're 48 bytes,
3711 * but we didn't use the last 6 bytes for now
3712 * --metze
3714 fsp = file_fsp(req, SVAL(params,0));
3716 if (!check_fsp_ntquota_handle(conn, req,
3717 fsp)) {
3718 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3719 reply_nterror(
3720 req, NT_STATUS_INVALID_HANDLE);
3721 return;
3724 if (total_data < 42) {
3725 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3726 total_data));
3727 reply_nterror(
3728 req,
3729 NT_STATUS_INVALID_PARAMETER);
3730 return;
3733 /* unknown_1 24 NULL bytes in pdata*/
3735 /* the soft quotas 8 bytes (uint64_t)*/
3736 quotas.softlim = BVAL(pdata,24);
3738 /* the hard quotas 8 bytes (uint64_t)*/
3739 quotas.hardlim = BVAL(pdata,32);
3741 /* quota_flags 2 bytes **/
3742 quotas.qflags = SVAL(pdata,40);
3744 /* unknown_2 6 NULL bytes follow*/
3746 /* now set the quotas */
3747 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3748 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3749 reply_nterror(req, map_nt_error_from_unix(errno));
3750 return;
3753 break;
3755 default:
3756 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3757 info_level));
3758 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3759 return;
3760 break;
3764 * sending this reply works fine,
3765 * but I'm not sure it's the same
3766 * like windows do...
3767 * --metze
3769 reply_outbuf(req, 10, 0);
3772 #if defined(HAVE_POSIX_ACLS)
3773 /****************************************************************************
3774 Utility function to count the number of entries in a POSIX acl.
3775 ****************************************************************************/
3777 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3779 unsigned int ace_count = 0;
3780 int entry_id = SMB_ACL_FIRST_ENTRY;
3781 SMB_ACL_ENTRY_T entry;
3783 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3784 /* get_next... */
3785 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3786 entry_id = SMB_ACL_NEXT_ENTRY;
3788 ace_count++;
3790 return ace_count;
3793 /****************************************************************************
3794 Utility function to marshall a POSIX acl into wire format.
3795 ****************************************************************************/
3797 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3799 int entry_id = SMB_ACL_FIRST_ENTRY;
3800 SMB_ACL_ENTRY_T entry;
3802 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3803 SMB_ACL_TAG_T tagtype;
3804 SMB_ACL_PERMSET_T permset;
3805 unsigned char perms = 0;
3806 unsigned int own_grp;
3808 /* get_next... */
3809 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3810 entry_id = SMB_ACL_NEXT_ENTRY;
3813 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3814 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3815 return False;
3818 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3819 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3820 return False;
3823 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3824 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3825 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3827 SCVAL(pdata,1,perms);
3829 switch (tagtype) {
3830 case SMB_ACL_USER_OBJ:
3831 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3832 own_grp = (unsigned int)pst->st_ex_uid;
3833 SIVAL(pdata,2,own_grp);
3834 SIVAL(pdata,6,0);
3835 break;
3836 case SMB_ACL_USER:
3838 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3839 if (!puid) {
3840 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3841 return False;
3843 own_grp = (unsigned int)*puid;
3844 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3845 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3846 SIVAL(pdata,2,own_grp);
3847 SIVAL(pdata,6,0);
3848 break;
3850 case SMB_ACL_GROUP_OBJ:
3851 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3852 own_grp = (unsigned int)pst->st_ex_gid;
3853 SIVAL(pdata,2,own_grp);
3854 SIVAL(pdata,6,0);
3855 break;
3856 case SMB_ACL_GROUP:
3858 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3859 if (!pgid) {
3860 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3861 return False;
3863 own_grp = (unsigned int)*pgid;
3864 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3865 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3866 SIVAL(pdata,2,own_grp);
3867 SIVAL(pdata,6,0);
3868 break;
3870 case SMB_ACL_MASK:
3871 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3872 SIVAL(pdata,2,0xFFFFFFFF);
3873 SIVAL(pdata,6,0xFFFFFFFF);
3874 break;
3875 case SMB_ACL_OTHER:
3876 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3877 SIVAL(pdata,2,0xFFFFFFFF);
3878 SIVAL(pdata,6,0xFFFFFFFF);
3879 break;
3880 default:
3881 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3882 return False;
3884 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3887 return True;
3889 #endif
3891 /****************************************************************************
3892 Store the FILE_UNIX_BASIC info.
3893 ****************************************************************************/
3895 static char *store_file_unix_basic(connection_struct *conn,
3896 char *pdata,
3897 files_struct *fsp,
3898 const SMB_STRUCT_STAT *psbuf)
3900 uint64_t file_index = get_FileIndex(conn, psbuf);
3902 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3903 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3905 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3906 pdata += 8;
3908 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3909 pdata += 8;
3911 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3912 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3913 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3914 pdata += 24;
3916 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3917 SIVAL(pdata,4,0);
3918 pdata += 8;
3920 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3921 SIVAL(pdata,4,0);
3922 pdata += 8;
3924 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3925 pdata += 4;
3927 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3928 SIVAL(pdata,4,0);
3929 pdata += 8;
3931 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3932 SIVAL(pdata,4,0);
3933 pdata += 8;
3935 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3936 pdata += 8;
3938 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3939 SIVAL(pdata,4,0);
3940 pdata += 8;
3942 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3943 SIVAL(pdata,4,0);
3944 pdata += 8;
3946 return pdata;
3949 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3950 * the chflags(2) (or equivalent) flags.
3952 * XXX: this really should be behind the VFS interface. To do this, we would
3953 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3954 * Each VFS module could then implement its own mapping as appropriate for the
3955 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3957 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3958 info2_flags_map[] =
3960 #ifdef UF_NODUMP
3961 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3962 #endif
3964 #ifdef UF_IMMUTABLE
3965 { UF_IMMUTABLE, EXT_IMMUTABLE },
3966 #endif
3968 #ifdef UF_APPEND
3969 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3970 #endif
3972 #ifdef UF_HIDDEN
3973 { UF_HIDDEN, EXT_HIDDEN },
3974 #endif
3976 /* Do not remove. We need to guarantee that this array has at least one
3977 * entry to build on HP-UX.
3979 { 0, 0 }
3983 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3984 uint32 *smb_fflags, uint32 *smb_fmask)
3986 int i;
3988 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3989 *smb_fmask |= info2_flags_map[i].smb_fflag;
3990 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3991 *smb_fflags |= info2_flags_map[i].smb_fflag;
3996 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3997 const uint32 smb_fflags,
3998 const uint32 smb_fmask,
3999 int *stat_fflags)
4001 uint32 max_fmask = 0;
4002 int i;
4004 *stat_fflags = psbuf->st_ex_flags;
4006 /* For each flags requested in smb_fmask, check the state of the
4007 * corresponding flag in smb_fflags and set or clear the matching
4008 * stat flag.
4011 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4012 max_fmask |= info2_flags_map[i].smb_fflag;
4013 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4014 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4015 *stat_fflags |= info2_flags_map[i].stat_fflag;
4016 } else {
4017 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4022 /* If smb_fmask is asking to set any bits that are not supported by
4023 * our flag mappings, we should fail.
4025 if ((smb_fmask & max_fmask) != smb_fmask) {
4026 return False;
4029 return True;
4033 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4034 * of file flags and birth (create) time.
4036 static char *store_file_unix_basic_info2(connection_struct *conn,
4037 char *pdata,
4038 files_struct *fsp,
4039 const SMB_STRUCT_STAT *psbuf)
4041 uint32 file_flags = 0;
4042 uint32 flags_mask = 0;
4044 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4046 /* Create (birth) time 64 bit */
4047 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4048 pdata += 8;
4050 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4051 SIVAL(pdata, 0, file_flags); /* flags */
4052 SIVAL(pdata, 4, flags_mask); /* mask */
4053 pdata += 8;
4055 return pdata;
4058 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4059 const struct stream_struct *streams,
4060 char *data,
4061 unsigned int max_data_bytes,
4062 unsigned int *data_size)
4064 unsigned int i;
4065 unsigned int ofs = 0;
4067 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4068 unsigned int next_offset;
4069 size_t namelen;
4070 smb_ucs2_t *namebuf;
4072 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4073 streams[i].name, &namelen) ||
4074 namelen <= 2)
4076 return NT_STATUS_INVALID_PARAMETER;
4080 * name_buf is now null-terminated, we need to marshall as not
4081 * terminated
4084 namelen -= 2;
4086 SIVAL(data, ofs+4, namelen);
4087 SOFF_T(data, ofs+8, streams[i].size);
4088 SOFF_T(data, ofs+16, streams[i].alloc_size);
4089 memcpy(data+ofs+24, namebuf, namelen);
4090 TALLOC_FREE(namebuf);
4092 next_offset = ofs + 24 + namelen;
4094 if (i == num_streams-1) {
4095 SIVAL(data, ofs, 0);
4097 else {
4098 unsigned int align = ndr_align_size(next_offset, 8);
4100 memset(data+next_offset, 0, align);
4101 next_offset += align;
4103 SIVAL(data, ofs, next_offset - ofs);
4104 ofs = next_offset;
4107 ofs = next_offset;
4110 *data_size = ofs;
4112 return NT_STATUS_OK;
4115 /****************************************************************************
4116 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4117 ****************************************************************************/
4119 static void call_trans2qpipeinfo(connection_struct *conn,
4120 struct smb_request *req,
4121 unsigned int tran_call,
4122 char **pparams, int total_params,
4123 char **ppdata, int total_data,
4124 unsigned int max_data_bytes)
4126 char *params = *pparams;
4127 char *pdata = *ppdata;
4128 unsigned int data_size = 0;
4129 unsigned int param_size = 2;
4130 uint16 info_level;
4131 files_struct *fsp;
4133 if (!params) {
4134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4135 return;
4138 if (total_params < 4) {
4139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4140 return;
4143 fsp = file_fsp(req, SVAL(params,0));
4144 if (!fsp_is_np(fsp)) {
4145 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4146 return;
4149 info_level = SVAL(params,2);
4151 *pparams = (char *)SMB_REALLOC(*pparams,2);
4152 if (*pparams == NULL) {
4153 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154 return;
4156 params = *pparams;
4157 SSVAL(params,0,0);
4158 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4159 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4160 if (*ppdata == NULL ) {
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 return;
4164 pdata = *ppdata;
4166 switch (info_level) {
4167 case SMB_FILE_STANDARD_INFORMATION:
4168 memset(pdata,0,24);
4169 SOFF_T(pdata,0,4096LL);
4170 SIVAL(pdata,16,1);
4171 SIVAL(pdata,20,1);
4172 data_size = 24;
4173 break;
4175 default:
4176 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4177 return;
4180 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4181 max_data_bytes);
4183 return;
4186 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4187 TALLOC_CTX *mem_ctx,
4188 uint16_t info_level,
4189 files_struct *fsp,
4190 struct smb_filename *smb_fname,
4191 bool delete_pending,
4192 struct timespec write_time_ts,
4193 struct ea_list *ea_list,
4194 int lock_data_count,
4195 char *lock_data,
4196 uint16_t flags2,
4197 unsigned int max_data_bytes,
4198 char **ppdata,
4199 unsigned int *pdata_size)
4201 char *pdata = *ppdata;
4202 char *dstart, *dend;
4203 unsigned int data_size;
4204 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4205 time_t create_time, mtime, atime, c_time;
4206 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4207 char *p;
4208 char *base_name;
4209 char *dos_fname;
4210 int mode;
4211 int nlink;
4212 NTSTATUS status;
4213 uint64_t file_size = 0;
4214 uint64_t pos = 0;
4215 uint64_t allocation_size = 0;
4216 uint64_t file_index = 0;
4217 uint32_t access_mask = 0;
4219 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4220 return NT_STATUS_INVALID_LEVEL;
4223 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4224 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4225 info_level, max_data_bytes));
4227 mode = dos_mode(conn, smb_fname);
4228 nlink = psbuf->st_ex_nlink;
4230 if (nlink && (mode&aDIR)) {
4231 nlink = 1;
4234 if ((nlink > 0) && delete_pending) {
4235 nlink -= 1;
4238 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4239 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4240 if (*ppdata == NULL) {
4241 return NT_STATUS_NO_MEMORY;
4243 pdata = *ppdata;
4244 dstart = pdata;
4245 dend = dstart + data_size - 1;
4247 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4248 update_stat_ex_mtime(psbuf, write_time_ts);
4251 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4252 mtime_ts = psbuf->st_ex_mtime;
4253 atime_ts = psbuf->st_ex_atime;
4254 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4256 if (lp_dos_filetime_resolution(SNUM(conn))) {
4257 dos_filetime_timespec(&create_time_ts);
4258 dos_filetime_timespec(&mtime_ts);
4259 dos_filetime_timespec(&atime_ts);
4260 dos_filetime_timespec(&ctime_ts);
4263 create_time = convert_timespec_to_time_t(create_time_ts);
4264 mtime = convert_timespec_to_time_t(mtime_ts);
4265 atime = convert_timespec_to_time_t(atime_ts);
4266 c_time = convert_timespec_to_time_t(ctime_ts);
4268 p = strrchr_m(smb_fname->base_name,'/');
4269 if (!p)
4270 base_name = smb_fname->base_name;
4271 else
4272 base_name = p+1;
4274 /* NT expects the name to be in an exact form of the *full*
4275 filename. See the trans2 torture test */
4276 if (ISDOT(base_name)) {
4277 dos_fname = talloc_strdup(mem_ctx, "\\");
4278 if (!dos_fname) {
4279 return NT_STATUS_NO_MEMORY;
4281 } else {
4282 dos_fname = talloc_asprintf(mem_ctx,
4283 "\\%s",
4284 smb_fname->base_name);
4285 if (!dos_fname) {
4286 return NT_STATUS_NO_MEMORY;
4288 if (is_ntfs_stream_smb_fname(smb_fname)) {
4289 dos_fname = talloc_asprintf(dos_fname, "%s",
4290 smb_fname->stream_name);
4291 if (!dos_fname) {
4292 return NT_STATUS_NO_MEMORY;
4296 string_replace(dos_fname, '/', '\\');
4299 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4301 if (!fsp) {
4302 /* Do we have this path open ? */
4303 files_struct *fsp1;
4304 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4305 fsp1 = file_find_di_first(conn->sconn, fileid);
4306 if (fsp1 && fsp1->initial_allocation_size) {
4307 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4311 if (!(mode & aDIR)) {
4312 file_size = get_file_size_stat(psbuf);
4315 if (fsp) {
4316 pos = fsp->fh->position_information;
4319 if (fsp) {
4320 access_mask = fsp->access_mask;
4321 } else {
4322 /* GENERIC_EXECUTE mapping from Windows */
4323 access_mask = 0x12019F;
4326 /* This should be an index number - looks like
4327 dev/ino to me :-)
4329 I think this causes us to fail the IFSKIT
4330 BasicFileInformationTest. -tpot */
4331 file_index = get_FileIndex(conn, psbuf);
4333 switch (info_level) {
4334 case SMB_INFO_STANDARD:
4335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4336 data_size = 22;
4337 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4338 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4339 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4340 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4341 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4342 SSVAL(pdata,l1_attrFile,mode);
4343 break;
4345 case SMB_INFO_QUERY_EA_SIZE:
4347 unsigned int ea_size =
4348 estimate_ea_size(conn, fsp,
4349 smb_fname->base_name);
4350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4351 data_size = 26;
4352 srv_put_dos_date2(pdata,0,create_time);
4353 srv_put_dos_date2(pdata,4,atime);
4354 srv_put_dos_date2(pdata,8,mtime); /* write time */
4355 SIVAL(pdata,12,(uint32)file_size);
4356 SIVAL(pdata,16,(uint32)allocation_size);
4357 SSVAL(pdata,20,mode);
4358 SIVAL(pdata,22,ea_size);
4359 break;
4362 case SMB_INFO_IS_NAME_VALID:
4363 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4364 if (fsp) {
4365 /* os/2 needs this ? really ?*/
4366 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4368 /* This is only reached for qpathinfo */
4369 data_size = 0;
4370 break;
4372 case SMB_INFO_QUERY_EAS_FROM_LIST:
4374 size_t total_ea_len = 0;
4375 struct ea_list *ea_file_list = NULL;
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4379 ea_file_list =
4380 get_ea_list_from_file(mem_ctx, conn, fsp,
4381 smb_fname->base_name,
4382 &total_ea_len);
4383 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4385 if (!ea_list || (total_ea_len > data_size)) {
4386 data_size = 4;
4387 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4388 break;
4391 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4392 break;
4395 case SMB_INFO_QUERY_ALL_EAS:
4397 /* We have data_size bytes to put EA's into. */
4398 size_t total_ea_len = 0;
4400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4402 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4403 smb_fname->base_name,
4404 &total_ea_len);
4405 if (!ea_list || (total_ea_len > data_size)) {
4406 data_size = 4;
4407 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4408 break;
4411 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4412 break;
4415 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4417 /* This is FileFullEaInformation - 0xF which maps to
4418 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4420 /* We have data_size bytes to put EA's into. */
4421 size_t total_ea_len = 0;
4422 struct ea_list *ea_file_list = NULL;
4424 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4426 /*TODO: add filtering and index handling */
4428 ea_file_list =
4429 get_ea_list_from_file(mem_ctx, conn, fsp,
4430 smb_fname->base_name,
4431 &total_ea_len);
4432 if (!ea_file_list) {
4433 return NT_STATUS_NO_EAS_ON_FILE;
4436 status = fill_ea_chained_buffer(mem_ctx,
4437 pdata,
4438 data_size,
4439 &data_size,
4440 conn, ea_file_list);
4441 if (!NT_STATUS_IS_OK(status)) {
4442 return status;
4444 break;
4447 case SMB_FILE_BASIC_INFORMATION:
4448 case SMB_QUERY_FILE_BASIC_INFO:
4450 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4452 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4453 } else {
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4455 data_size = 40;
4456 SIVAL(pdata,36,0);
4458 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4459 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4460 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4461 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4462 SIVAL(pdata,32,mode);
4464 DEBUG(5,("SMB_QFBI - "));
4465 DEBUG(5,("create: %s ", ctime(&create_time)));
4466 DEBUG(5,("access: %s ", ctime(&atime)));
4467 DEBUG(5,("write: %s ", ctime(&mtime)));
4468 DEBUG(5,("change: %s ", ctime(&c_time)));
4469 DEBUG(5,("mode: %x\n", mode));
4470 break;
4472 case SMB_FILE_STANDARD_INFORMATION:
4473 case SMB_QUERY_FILE_STANDARD_INFO:
4475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4476 data_size = 24;
4477 SOFF_T(pdata,0,allocation_size);
4478 SOFF_T(pdata,8,file_size);
4479 SIVAL(pdata,16,nlink);
4480 SCVAL(pdata,20,delete_pending?1:0);
4481 SCVAL(pdata,21,(mode&aDIR)?1:0);
4482 SSVAL(pdata,22,0); /* Padding. */
4483 break;
4485 case SMB_FILE_EA_INFORMATION:
4486 case SMB_QUERY_FILE_EA_INFO:
4488 unsigned int ea_size =
4489 estimate_ea_size(conn, fsp, smb_fname->base_name);
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4491 data_size = 4;
4492 SIVAL(pdata,0,ea_size);
4493 break;
4496 /* Get the 8.3 name - used if NT SMB was negotiated. */
4497 case SMB_QUERY_FILE_ALT_NAME_INFO:
4498 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4500 int len;
4501 char mangled_name[13];
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4503 if (!name_to_8_3(base_name,mangled_name,
4504 True,conn->params)) {
4505 return NT_STATUS_NO_MEMORY;
4507 len = srvstr_push(dstart, flags2,
4508 pdata+4, mangled_name,
4509 PTR_DIFF(dend, pdata+4),
4510 STR_UNICODE);
4511 data_size = 4 + len;
4512 SIVAL(pdata,0,len);
4513 break;
4516 case SMB_QUERY_FILE_NAME_INFO:
4518 int len;
4520 this must be *exactly* right for ACLs on mapped drives to work
4522 len = srvstr_push(dstart, flags2,
4523 pdata+4, dos_fname,
4524 PTR_DIFF(dend, pdata+4),
4525 STR_UNICODE);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4527 data_size = 4 + len;
4528 SIVAL(pdata,0,len);
4529 break;
4532 case SMB_FILE_ALLOCATION_INFORMATION:
4533 case SMB_QUERY_FILE_ALLOCATION_INFO:
4534 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4535 data_size = 8;
4536 SOFF_T(pdata,0,allocation_size);
4537 break;
4539 case SMB_FILE_END_OF_FILE_INFORMATION:
4540 case SMB_QUERY_FILE_END_OF_FILEINFO:
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4542 data_size = 8;
4543 SOFF_T(pdata,0,file_size);
4544 break;
4546 case SMB_QUERY_FILE_ALL_INFO:
4547 case SMB_FILE_ALL_INFORMATION:
4549 int len;
4550 unsigned int ea_size =
4551 estimate_ea_size(conn, fsp, smb_fname->base_name);
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4553 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4554 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4555 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4556 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4557 SIVAL(pdata,32,mode);
4558 SIVAL(pdata,36,0); /* padding. */
4559 pdata += 40;
4560 SOFF_T(pdata,0,allocation_size);
4561 SOFF_T(pdata,8,file_size);
4562 SIVAL(pdata,16,nlink);
4563 SCVAL(pdata,20,delete_pending);
4564 SCVAL(pdata,21,(mode&aDIR)?1:0);
4565 SSVAL(pdata,22,0);
4566 pdata += 24;
4567 SIVAL(pdata,0,ea_size);
4568 pdata += 4; /* EA info */
4569 len = srvstr_push(dstart, flags2,
4570 pdata+4, dos_fname,
4571 PTR_DIFF(dend, pdata+4),
4572 STR_UNICODE);
4573 SIVAL(pdata,0,len);
4574 pdata += 4 + len;
4575 data_size = PTR_DIFF(pdata,(*ppdata));
4576 break;
4579 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4581 int len;
4582 unsigned int ea_size =
4583 estimate_ea_size(conn, fsp, smb_fname->base_name);
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4585 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4586 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4587 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4588 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4589 SIVAL(pdata, 0x20, mode);
4590 SIVAL(pdata, 0x24, 0); /* padding. */
4591 SBVAL(pdata, 0x28, allocation_size);
4592 SBVAL(pdata, 0x30, file_size);
4593 SIVAL(pdata, 0x38, nlink);
4594 SCVAL(pdata, 0x3C, delete_pending);
4595 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4596 SSVAL(pdata, 0x3E, 0); /* padding */
4597 SBVAL(pdata, 0x40, file_index);
4598 SIVAL(pdata, 0x48, ea_size);
4599 SIVAL(pdata, 0x4C, access_mask);
4600 SBVAL(pdata, 0x50, pos);
4601 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4602 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4604 pdata += 0x60;
4606 len = srvstr_push(dstart, flags2,
4607 pdata+4, dos_fname,
4608 PTR_DIFF(dend, pdata+4),
4609 STR_UNICODE);
4610 SIVAL(pdata,0,len);
4611 pdata += 4 + len;
4612 data_size = PTR_DIFF(pdata,(*ppdata));
4613 break;
4615 case SMB_FILE_INTERNAL_INFORMATION:
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4618 SBVAL(pdata, 0, file_index);
4619 data_size = 8;
4620 break;
4622 case SMB_FILE_ACCESS_INFORMATION:
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4624 SIVAL(pdata, 0, access_mask);
4625 data_size = 4;
4626 break;
4628 case SMB_FILE_NAME_INFORMATION:
4629 /* Pathname with leading '\'. */
4631 size_t byte_len;
4632 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4634 SIVAL(pdata,0,byte_len);
4635 data_size = 4 + byte_len;
4636 break;
4639 case SMB_FILE_DISPOSITION_INFORMATION:
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4641 data_size = 1;
4642 SCVAL(pdata,0,delete_pending);
4643 break;
4645 case SMB_FILE_POSITION_INFORMATION:
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4647 data_size = 8;
4648 SOFF_T(pdata,0,pos);
4649 break;
4651 case SMB_FILE_MODE_INFORMATION:
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4653 SIVAL(pdata,0,mode);
4654 data_size = 4;
4655 break;
4657 case SMB_FILE_ALIGNMENT_INFORMATION:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4659 SIVAL(pdata,0,0); /* No alignment needed. */
4660 data_size = 4;
4661 break;
4664 * NT4 server just returns "invalid query" to this - if we try
4665 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4666 * want this. JRA.
4668 /* The first statement above is false - verified using Thursby
4669 * client against NT4 -- gcolley.
4671 case SMB_QUERY_FILE_STREAM_INFO:
4672 case SMB_FILE_STREAM_INFORMATION: {
4673 unsigned int num_streams;
4674 struct stream_struct *streams;
4676 DEBUG(10,("smbd_do_qfilepathinfo: "
4677 "SMB_FILE_STREAM_INFORMATION\n"));
4679 if (is_ntfs_stream_smb_fname(smb_fname)) {
4680 return NT_STATUS_INVALID_PARAMETER;
4683 status = SMB_VFS_STREAMINFO(
4684 conn, fsp, smb_fname->base_name, talloc_tos(),
4685 &num_streams, &streams);
4687 if (!NT_STATUS_IS_OK(status)) {
4688 DEBUG(10, ("could not get stream info: %s\n",
4689 nt_errstr(status)));
4690 return status;
4693 status = marshall_stream_info(num_streams, streams,
4694 pdata, max_data_bytes,
4695 &data_size);
4697 if (!NT_STATUS_IS_OK(status)) {
4698 DEBUG(10, ("marshall_stream_info failed: %s\n",
4699 nt_errstr(status)));
4700 return status;
4703 TALLOC_FREE(streams);
4705 break;
4707 case SMB_QUERY_COMPRESSION_INFO:
4708 case SMB_FILE_COMPRESSION_INFORMATION:
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4710 SOFF_T(pdata,0,file_size);
4711 SIVAL(pdata,8,0); /* ??? */
4712 SIVAL(pdata,12,0); /* ??? */
4713 data_size = 16;
4714 break;
4716 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4718 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4719 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4721 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4722 SOFF_T(pdata,32,allocation_size);
4723 SOFF_T(pdata,40,file_size);
4724 SIVAL(pdata,48,mode);
4725 SIVAL(pdata,52,0); /* ??? */
4726 data_size = 56;
4727 break;
4729 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4731 SIVAL(pdata,0,mode);
4732 SIVAL(pdata,4,0);
4733 data_size = 8;
4734 break;
4737 * CIFS UNIX Extensions.
4740 case SMB_QUERY_FILE_UNIX_BASIC:
4742 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4743 data_size = PTR_DIFF(pdata,(*ppdata));
4745 DEBUG(4,("smbd_do_qfilepathinfo: "
4746 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4747 dump_data(4, (uint8_t *)(*ppdata), data_size);
4749 break;
4751 case SMB_QUERY_FILE_UNIX_INFO2:
4753 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4754 data_size = PTR_DIFF(pdata,(*ppdata));
4757 int i;
4758 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4760 for (i=0; i<100; i++)
4761 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4762 DEBUG(4,("\n"));
4765 break;
4767 case SMB_QUERY_FILE_UNIX_LINK:
4769 int len;
4770 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4772 if (!buffer) {
4773 return NT_STATUS_NO_MEMORY;
4776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4777 #ifdef S_ISLNK
4778 if(!S_ISLNK(psbuf->st_ex_mode)) {
4779 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4781 #else
4782 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4783 #endif
4784 len = SMB_VFS_READLINK(conn,
4785 smb_fname->base_name,
4786 buffer, PATH_MAX);
4787 if (len == -1) {
4788 return map_nt_error_from_unix(errno);
4790 buffer[len] = 0;
4791 len = srvstr_push(dstart, flags2,
4792 pdata, buffer,
4793 PTR_DIFF(dend, pdata),
4794 STR_TERMINATE);
4795 pdata += len;
4796 data_size = PTR_DIFF(pdata,(*ppdata));
4798 break;
4801 #if defined(HAVE_POSIX_ACLS)
4802 case SMB_QUERY_POSIX_ACL:
4804 SMB_ACL_T file_acl = NULL;
4805 SMB_ACL_T def_acl = NULL;
4806 uint16 num_file_acls = 0;
4807 uint16 num_def_acls = 0;
4809 if (fsp && fsp->fh->fd != -1) {
4810 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4811 } else {
4812 file_acl =
4813 SMB_VFS_SYS_ACL_GET_FILE(conn,
4814 smb_fname->base_name,
4815 SMB_ACL_TYPE_ACCESS);
4818 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4819 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4820 "not implemented on "
4821 "filesystem containing %s\n",
4822 smb_fname->base_name));
4823 return NT_STATUS_NOT_IMPLEMENTED;
4826 if (S_ISDIR(psbuf->st_ex_mode)) {
4827 if (fsp && fsp->is_directory) {
4828 def_acl =
4829 SMB_VFS_SYS_ACL_GET_FILE(
4830 conn,
4831 fsp->fsp_name->base_name,
4832 SMB_ACL_TYPE_DEFAULT);
4833 } else {
4834 def_acl =
4835 SMB_VFS_SYS_ACL_GET_FILE(
4836 conn,
4837 smb_fname->base_name,
4838 SMB_ACL_TYPE_DEFAULT);
4840 def_acl = free_empty_sys_acl(conn, def_acl);
4843 num_file_acls = count_acl_entries(conn, file_acl);
4844 num_def_acls = count_acl_entries(conn, def_acl);
4846 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4847 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4848 data_size,
4849 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4850 SMB_POSIX_ACL_HEADER_SIZE) ));
4851 if (file_acl) {
4852 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4854 if (def_acl) {
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4857 return NT_STATUS_BUFFER_TOO_SMALL;
4860 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4861 SSVAL(pdata,2,num_file_acls);
4862 SSVAL(pdata,4,num_def_acls);
4863 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4864 if (file_acl) {
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4867 if (def_acl) {
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4870 return NT_STATUS_INTERNAL_ERROR;
4872 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4873 if (file_acl) {
4874 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4876 if (def_acl) {
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4879 return NT_STATUS_INTERNAL_ERROR;
4882 if (file_acl) {
4883 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4885 if (def_acl) {
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4888 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4889 break;
4891 #endif
4894 case SMB_QUERY_POSIX_LOCK:
4896 uint64_t count;
4897 uint64_t offset;
4898 uint64_t smblctx;
4899 enum brl_type lock_type;
4901 /* We need an open file with a real fd for this. */
4902 if (!fsp || fsp->fh->fd == -1) {
4903 return NT_STATUS_INVALID_LEVEL;
4906 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4907 return NT_STATUS_INVALID_PARAMETER;
4910 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4911 case POSIX_LOCK_TYPE_READ:
4912 lock_type = READ_LOCK;
4913 break;
4914 case POSIX_LOCK_TYPE_WRITE:
4915 lock_type = WRITE_LOCK;
4916 break;
4917 case POSIX_LOCK_TYPE_UNLOCK:
4918 default:
4919 /* There's no point in asking for an unlock... */
4920 return NT_STATUS_INVALID_PARAMETER;
4923 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4924 #if defined(HAVE_LONGLONG)
4925 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4926 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4927 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4928 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4929 #else /* HAVE_LONGLONG */
4930 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4931 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4932 #endif /* HAVE_LONGLONG */
4934 status = query_lock(fsp,
4935 &smblctx,
4936 &count,
4937 &offset,
4938 &lock_type,
4939 POSIX_LOCK);
4941 if (ERROR_WAS_LOCK_DENIED(status)) {
4942 /* Here we need to report who has it locked... */
4943 data_size = POSIX_LOCK_DATA_SIZE;
4945 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4946 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4947 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4948 #if defined(HAVE_LONGLONG)
4949 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4950 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4951 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4952 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4953 #else /* HAVE_LONGLONG */
4954 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4955 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4956 #endif /* HAVE_LONGLONG */
4958 } else if (NT_STATUS_IS_OK(status)) {
4959 /* For success we just return a copy of what we sent
4960 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4961 data_size = POSIX_LOCK_DATA_SIZE;
4962 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4963 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4964 } else {
4965 return status;
4967 break;
4970 default:
4971 return NT_STATUS_INVALID_LEVEL;
4974 *pdata_size = data_size;
4975 return NT_STATUS_OK;
4978 /****************************************************************************
4979 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4980 file name or file id).
4981 ****************************************************************************/
4983 static void call_trans2qfilepathinfo(connection_struct *conn,
4984 struct smb_request *req,
4985 unsigned int tran_call,
4986 char **pparams, int total_params,
4987 char **ppdata, int total_data,
4988 unsigned int max_data_bytes)
4990 char *params = *pparams;
4991 char *pdata = *ppdata;
4992 uint16 info_level;
4993 unsigned int data_size = 0;
4994 unsigned int param_size = 2;
4995 struct smb_filename *smb_fname = NULL;
4996 bool delete_pending = False;
4997 struct timespec write_time_ts;
4998 files_struct *fsp = NULL;
4999 struct file_id fileid;
5000 struct ea_list *ea_list = NULL;
5001 int lock_data_count = 0;
5002 char *lock_data = NULL;
5003 NTSTATUS status = NT_STATUS_OK;
5005 if (!params) {
5006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5007 return;
5010 ZERO_STRUCT(write_time_ts);
5012 if (tran_call == TRANSACT2_QFILEINFO) {
5013 if (total_params < 4) {
5014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5015 return;
5018 if (IS_IPC(conn)) {
5019 call_trans2qpipeinfo(conn, req, tran_call,
5020 pparams, total_params,
5021 ppdata, total_data,
5022 max_data_bytes);
5023 return;
5026 fsp = file_fsp(req, SVAL(params,0));
5027 info_level = SVAL(params,2);
5029 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5031 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5032 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5033 return;
5036 /* Initial check for valid fsp ptr. */
5037 if (!check_fsp_open(conn, req, fsp)) {
5038 return;
5041 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5042 &smb_fname);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 reply_nterror(req, status);
5045 return;
5048 if(fsp->fake_file_handle) {
5050 * This is actually for the QUOTA_FAKE_FILE --metze
5053 /* We know this name is ok, it's already passed the checks. */
5055 } else if(fsp->fh->fd == -1) {
5057 * This is actually a QFILEINFO on a directory
5058 * handle (returned from an NT SMB). NT5.0 seems
5059 * to do this call. JRA.
5062 if (INFO_LEVEL_IS_UNIX(info_level)) {
5063 /* Always do lstat for UNIX calls. */
5064 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5065 DEBUG(3,("call_trans2qfilepathinfo: "
5066 "SMB_VFS_LSTAT of %s failed "
5067 "(%s)\n",
5068 smb_fname_str_dbg(smb_fname),
5069 strerror(errno)));
5070 reply_nterror(req,
5071 map_nt_error_from_unix(errno));
5072 return;
5074 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5075 DEBUG(3,("call_trans2qfilepathinfo: "
5076 "SMB_VFS_STAT of %s failed (%s)\n",
5077 smb_fname_str_dbg(smb_fname),
5078 strerror(errno)));
5079 reply_nterror(req,
5080 map_nt_error_from_unix(errno));
5081 return;
5084 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5085 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5086 } else {
5088 * Original code - this is an open file.
5090 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5091 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5092 fsp->fnum, strerror(errno)));
5093 reply_nterror(req,
5094 map_nt_error_from_unix(errno));
5095 return;
5097 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5098 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5101 } else {
5102 uint32_t name_hash;
5103 char *fname = NULL;
5105 /* qpathinfo */
5106 if (total_params < 7) {
5107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5108 return;
5111 info_level = SVAL(params,0);
5113 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5115 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5117 return;
5120 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5121 total_params - 6,
5122 STR_TERMINATE, &status);
5123 if (!NT_STATUS_IS_OK(status)) {
5124 reply_nterror(req, status);
5125 return;
5128 status = filename_convert(req,
5129 conn,
5130 req->flags2 & FLAGS2_DFS_PATHNAMES,
5131 fname,
5133 NULL,
5134 &smb_fname);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5137 reply_botherror(req,
5138 NT_STATUS_PATH_NOT_COVERED,
5139 ERRSRV, ERRbadpath);
5140 return;
5142 reply_nterror(req, status);
5143 return;
5146 /* If this is a stream, check if there is a delete_pending. */
5147 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5148 && is_ntfs_stream_smb_fname(smb_fname)) {
5149 struct smb_filename *smb_fname_base = NULL;
5151 /* Create an smb_filename with stream_name == NULL. */
5152 status =
5153 create_synthetic_smb_fname(talloc_tos(),
5154 smb_fname->base_name,
5155 NULL, NULL,
5156 &smb_fname_base);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5159 return;
5162 if (INFO_LEVEL_IS_UNIX(info_level)) {
5163 /* Always do lstat for UNIX calls. */
5164 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5165 DEBUG(3,("call_trans2qfilepathinfo: "
5166 "SMB_VFS_LSTAT of %s failed "
5167 "(%s)\n",
5168 smb_fname_str_dbg(smb_fname_base),
5169 strerror(errno)));
5170 TALLOC_FREE(smb_fname_base);
5171 reply_nterror(req,
5172 map_nt_error_from_unix(errno));
5173 return;
5175 } else {
5176 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5177 DEBUG(3,("call_trans2qfilepathinfo: "
5178 "fileinfo of %s failed "
5179 "(%s)\n",
5180 smb_fname_str_dbg(smb_fname_base),
5181 strerror(errno)));
5182 TALLOC_FREE(smb_fname_base);
5183 reply_nterror(req,
5184 map_nt_error_from_unix(errno));
5185 return;
5189 status = file_name_hash(conn,
5190 smb_fname_str_dbg(smb_fname_base),
5191 &name_hash);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 TALLOC_FREE(smb_fname_base);
5194 reply_nterror(req, status);
5195 return;
5198 fileid = vfs_file_id_from_sbuf(conn,
5199 &smb_fname_base->st);
5200 TALLOC_FREE(smb_fname_base);
5201 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5202 if (delete_pending) {
5203 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5204 return;
5208 if (INFO_LEVEL_IS_UNIX(info_level)) {
5209 /* Always do lstat for UNIX calls. */
5210 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5211 DEBUG(3,("call_trans2qfilepathinfo: "
5212 "SMB_VFS_LSTAT of %s failed (%s)\n",
5213 smb_fname_str_dbg(smb_fname),
5214 strerror(errno)));
5215 reply_nterror(req,
5216 map_nt_error_from_unix(errno));
5217 return;
5220 } else {
5221 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_STAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname),
5225 strerror(errno)));
5226 reply_nterror(req,
5227 map_nt_error_from_unix(errno));
5228 return;
5232 status = file_name_hash(conn,
5233 smb_fname_str_dbg(smb_fname),
5234 &name_hash);
5235 if (!NT_STATUS_IS_OK(status)) {
5236 reply_nterror(req, status);
5237 return;
5240 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5241 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5242 if (delete_pending) {
5243 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5244 return;
5248 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5249 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5250 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5252 /* Pull out any data sent here before we realloc. */
5253 switch (info_level) {
5254 case SMB_INFO_QUERY_EAS_FROM_LIST:
5256 /* Pull any EA list from the data portion. */
5257 uint32 ea_size;
5259 if (total_data < 4) {
5260 reply_nterror(
5261 req, NT_STATUS_INVALID_PARAMETER);
5262 return;
5264 ea_size = IVAL(pdata,0);
5266 if (total_data > 0 && ea_size != total_data) {
5267 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5268 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5269 reply_nterror(
5270 req, NT_STATUS_INVALID_PARAMETER);
5271 return;
5274 if (!lp_ea_support(SNUM(conn))) {
5275 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5276 return;
5279 /* Pull out the list of names. */
5280 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5281 if (!ea_list) {
5282 reply_nterror(
5283 req, NT_STATUS_INVALID_PARAMETER);
5284 return;
5286 break;
5289 case SMB_QUERY_POSIX_LOCK:
5291 if (fsp == NULL || fsp->fh->fd == -1) {
5292 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5293 return;
5296 if (total_data != POSIX_LOCK_DATA_SIZE) {
5297 reply_nterror(
5298 req, NT_STATUS_INVALID_PARAMETER);
5299 return;
5302 /* Copy the lock range data. */
5303 lock_data = (char *)TALLOC_MEMDUP(
5304 req, pdata, total_data);
5305 if (!lock_data) {
5306 reply_nterror(req, NT_STATUS_NO_MEMORY);
5307 return;
5309 lock_data_count = total_data;
5311 default:
5312 break;
5315 *pparams = (char *)SMB_REALLOC(*pparams,2);
5316 if (*pparams == NULL) {
5317 reply_nterror(req, NT_STATUS_NO_MEMORY);
5318 return;
5320 params = *pparams;
5321 SSVAL(params,0,0);
5324 * draft-leach-cifs-v1-spec-02.txt
5325 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5326 * says:
5328 * The requested information is placed in the Data portion of the
5329 * transaction response. For the information levels greater than 0x100,
5330 * the transaction response has 1 parameter word which should be
5331 * ignored by the client.
5333 * However Windows only follows this rule for the IS_NAME_VALID call.
5335 switch (info_level) {
5336 case SMB_INFO_IS_NAME_VALID:
5337 param_size = 0;
5338 break;
5341 if ((info_level & 0xFF00) == 0xFF00) {
5343 * We use levels that start with 0xFF00
5344 * internally to represent SMB2 specific levels
5346 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5347 return;
5350 status = smbd_do_qfilepathinfo(conn, req, info_level,
5351 fsp, smb_fname,
5352 delete_pending, write_time_ts,
5353 ea_list,
5354 lock_data_count, lock_data,
5355 req->flags2, max_data_bytes,
5356 ppdata, &data_size);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 reply_nterror(req, status);
5359 return;
5362 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5363 max_data_bytes);
5365 return;
5368 /****************************************************************************
5369 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5370 code.
5371 ****************************************************************************/
5373 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5374 connection_struct *conn,
5375 struct smb_request *req,
5376 bool overwrite_if_exists,
5377 const struct smb_filename *smb_fname_old,
5378 struct smb_filename *smb_fname_new)
5380 NTSTATUS status = NT_STATUS_OK;
5382 /* source must already exist. */
5383 if (!VALID_STAT(smb_fname_old->st)) {
5384 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5387 if (VALID_STAT(smb_fname_new->st)) {
5388 if (overwrite_if_exists) {
5389 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5390 return NT_STATUS_FILE_IS_A_DIRECTORY;
5392 status = unlink_internals(conn,
5393 req,
5394 FILE_ATTRIBUTE_NORMAL,
5395 smb_fname_new,
5396 false);
5397 if (!NT_STATUS_IS_OK(status)) {
5398 return status;
5400 } else {
5401 /* Disallow if newname already exists. */
5402 return NT_STATUS_OBJECT_NAME_COLLISION;
5406 /* No links from a directory. */
5407 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5408 return NT_STATUS_FILE_IS_A_DIRECTORY;
5411 /* Setting a hardlink to/from a stream isn't currently supported. */
5412 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5413 is_ntfs_stream_smb_fname(smb_fname_new)) {
5414 return NT_STATUS_INVALID_PARAMETER;
5417 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5418 smb_fname_old->base_name, smb_fname_new->base_name));
5420 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5421 smb_fname_new->base_name) != 0) {
5422 status = map_nt_error_from_unix(errno);
5423 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5424 nt_errstr(status), smb_fname_old->base_name,
5425 smb_fname_new->base_name));
5427 return status;
5430 /****************************************************************************
5431 Deal with setting the time from any of the setfilepathinfo functions.
5432 ****************************************************************************/
5434 NTSTATUS smb_set_file_time(connection_struct *conn,
5435 files_struct *fsp,
5436 const struct smb_filename *smb_fname,
5437 struct smb_file_time *ft,
5438 bool setting_write_time)
5440 struct smb_filename smb_fname_base;
5441 uint32 action =
5442 FILE_NOTIFY_CHANGE_LAST_ACCESS
5443 |FILE_NOTIFY_CHANGE_LAST_WRITE
5444 |FILE_NOTIFY_CHANGE_CREATION;
5446 if (!VALID_STAT(smb_fname->st)) {
5447 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5450 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5451 return NT_STATUS_ACCESS_DENIED;
5454 /* get some defaults (no modifications) if any info is zero or -1. */
5455 if (null_timespec(ft->create_time)) {
5456 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5459 if (null_timespec(ft->atime)) {
5460 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5463 if (null_timespec(ft->mtime)) {
5464 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5467 if (!setting_write_time) {
5468 /* ft->mtime comes from change time, not write time. */
5469 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5472 /* Ensure the resolution is the correct for
5473 * what we can store on this filesystem. */
5475 round_timespec(conn->ts_res, &ft->create_time);
5476 round_timespec(conn->ts_res, &ft->ctime);
5477 round_timespec(conn->ts_res, &ft->atime);
5478 round_timespec(conn->ts_res, &ft->mtime);
5480 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5482 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5484 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5486 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5487 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5489 if (setting_write_time) {
5491 * This was a Windows setfileinfo on an open file.
5492 * NT does this a lot. We also need to
5493 * set the time here, as it can be read by
5494 * FindFirst/FindNext and with the patch for bug #2045
5495 * in smbd/fileio.c it ensures that this timestamp is
5496 * kept sticky even after a write. We save the request
5497 * away and will set it on file close and after a write. JRA.
5500 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5501 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5503 if (fsp != NULL) {
5504 if (fsp->base_fsp) {
5505 set_sticky_write_time_fsp(fsp->base_fsp,
5506 ft->mtime);
5507 } else {
5508 set_sticky_write_time_fsp(fsp, ft->mtime);
5510 } else {
5511 set_sticky_write_time_path(
5512 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5513 ft->mtime);
5517 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5519 /* Always call ntimes on the base, even if a stream was passed in. */
5520 smb_fname_base = *smb_fname;
5521 smb_fname_base.stream_name = NULL;
5523 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5524 return map_nt_error_from_unix(errno);
5527 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5528 smb_fname->base_name);
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Deal with setting the dosmode from any of the setfilepathinfo functions.
5534 ****************************************************************************/
5536 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5537 const struct smb_filename *smb_fname,
5538 uint32 dosmode)
5540 struct smb_filename *smb_fname_base = NULL;
5541 NTSTATUS status;
5543 if (!VALID_STAT(smb_fname->st)) {
5544 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5547 /* Always operate on the base_name, even if a stream was passed in. */
5548 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5549 NULL, &smb_fname->st,
5550 &smb_fname_base);
5551 if (!NT_STATUS_IS_OK(status)) {
5552 return status;
5555 if (dosmode) {
5556 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5557 dosmode |= aDIR;
5558 } else {
5559 dosmode &= ~aDIR;
5563 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5565 /* check the mode isn't different, before changing it */
5566 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5567 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5568 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5569 (unsigned int)dosmode));
5571 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5572 false)) {
5573 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5574 "%s failed (%s)\n",
5575 smb_fname_str_dbg(smb_fname_base),
5576 strerror(errno)));
5577 status = map_nt_error_from_unix(errno);
5578 goto out;
5581 status = NT_STATUS_OK;
5582 out:
5583 TALLOC_FREE(smb_fname_base);
5584 return status;
5587 /****************************************************************************
5588 Deal with setting the size from any of the setfilepathinfo functions.
5589 ****************************************************************************/
5591 static NTSTATUS smb_set_file_size(connection_struct *conn,
5592 struct smb_request *req,
5593 files_struct *fsp,
5594 const struct smb_filename *smb_fname,
5595 const SMB_STRUCT_STAT *psbuf,
5596 SMB_OFF_T size,
5597 bool fail_after_createfile)
5599 NTSTATUS status = NT_STATUS_OK;
5600 struct smb_filename *smb_fname_tmp = NULL;
5601 files_struct *new_fsp = NULL;
5603 if (!VALID_STAT(*psbuf)) {
5604 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5607 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5608 return NT_STATUS_ACCESS_DENIED;
5611 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5613 if (size == get_file_size_stat(psbuf)) {
5614 return NT_STATUS_OK;
5617 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5618 smb_fname_str_dbg(smb_fname), (double)size));
5620 if (fsp && fsp->fh->fd != -1) {
5621 /* Handle based call. */
5622 if (vfs_set_filelen(fsp, size) == -1) {
5623 return map_nt_error_from_unix(errno);
5625 trigger_write_time_update_immediate(fsp);
5626 return NT_STATUS_OK;
5629 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 return status;
5634 smb_fname_tmp->st = *psbuf;
5636 status = SMB_VFS_CREATE_FILE(
5637 conn, /* conn */
5638 req, /* req */
5639 0, /* root_dir_fid */
5640 smb_fname_tmp, /* fname */
5641 FILE_WRITE_DATA, /* access_mask */
5642 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5643 FILE_SHARE_DELETE),
5644 FILE_OPEN, /* create_disposition*/
5645 0, /* create_options */
5646 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5647 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5648 0, /* allocation_size */
5649 0, /* private_flags */
5650 NULL, /* sd */
5651 NULL, /* ea_list */
5652 &new_fsp, /* result */
5653 NULL); /* pinfo */
5655 TALLOC_FREE(smb_fname_tmp);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 /* NB. We check for open_was_deferred in the caller. */
5659 return status;
5662 /* See RAW-SFILEINFO-END-OF-FILE */
5663 if (fail_after_createfile) {
5664 close_file(req, new_fsp,NORMAL_CLOSE);
5665 return NT_STATUS_INVALID_LEVEL;
5668 if (vfs_set_filelen(new_fsp, size) == -1) {
5669 status = map_nt_error_from_unix(errno);
5670 close_file(req, new_fsp,NORMAL_CLOSE);
5671 return status;
5674 trigger_write_time_update_immediate(new_fsp);
5675 close_file(req, new_fsp,NORMAL_CLOSE);
5676 return NT_STATUS_OK;
5679 /****************************************************************************
5680 Deal with SMB_INFO_SET_EA.
5681 ****************************************************************************/
5683 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5684 const char *pdata,
5685 int total_data,
5686 files_struct *fsp,
5687 const struct smb_filename *smb_fname)
5689 struct ea_list *ea_list = NULL;
5690 TALLOC_CTX *ctx = NULL;
5691 NTSTATUS status = NT_STATUS_OK;
5693 if (total_data < 10) {
5695 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5696 length. They seem to have no effect. Bug #3212. JRA */
5698 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5699 /* We're done. We only get EA info in this call. */
5700 return NT_STATUS_OK;
5703 return NT_STATUS_INVALID_PARAMETER;
5706 if (IVAL(pdata,0) > total_data) {
5707 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5708 IVAL(pdata,0), (unsigned int)total_data));
5709 return NT_STATUS_INVALID_PARAMETER;
5712 ctx = talloc_tos();
5713 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5714 if (!ea_list) {
5715 return NT_STATUS_INVALID_PARAMETER;
5718 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5719 return NT_STATUS_ACCESS_DENIED;
5722 status = set_ea(conn, fsp, smb_fname, ea_list);
5724 return status;
5727 /****************************************************************************
5728 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5729 ****************************************************************************/
5731 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5732 const char *pdata,
5733 int total_data,
5734 files_struct *fsp)
5736 struct ea_list *ea_list = NULL;
5737 NTSTATUS status;
5739 if (!fsp) {
5740 return NT_STATUS_INVALID_HANDLE;
5743 if (!lp_ea_support(SNUM(conn))) {
5744 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5745 "EA's not supported.\n",
5746 (unsigned int)total_data));
5747 return NT_STATUS_EAS_NOT_SUPPORTED;
5750 if (total_data < 10) {
5751 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5752 "too small.\n",
5753 (unsigned int)total_data));
5754 return NT_STATUS_INVALID_PARAMETER;
5757 ea_list = read_nttrans_ea_list(talloc_tos(),
5758 pdata,
5759 total_data);
5761 if (!ea_list) {
5762 return NT_STATUS_INVALID_PARAMETER;
5765 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5766 return NT_STATUS_ACCESS_DENIED;
5769 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5771 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5772 smb_fname_str_dbg(fsp->fsp_name),
5773 nt_errstr(status) ));
5775 return status;
5779 /****************************************************************************
5780 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5781 ****************************************************************************/
5783 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5784 const char *pdata,
5785 int total_data,
5786 files_struct *fsp,
5787 struct smb_filename *smb_fname)
5789 NTSTATUS status = NT_STATUS_OK;
5790 bool delete_on_close;
5791 uint32 dosmode = 0;
5793 if (total_data < 1) {
5794 return NT_STATUS_INVALID_PARAMETER;
5797 if (fsp == NULL) {
5798 return NT_STATUS_INVALID_HANDLE;
5801 delete_on_close = (CVAL(pdata,0) ? True : False);
5802 dosmode = dos_mode(conn, smb_fname);
5804 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5805 "delete_on_close = %u\n",
5806 smb_fname_str_dbg(smb_fname),
5807 (unsigned int)dosmode,
5808 (unsigned int)delete_on_close ));
5810 if (delete_on_close) {
5811 status = can_set_delete_on_close(fsp, dosmode);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 return status;
5817 /* The set is across all open files on this dev/inode pair. */
5818 if (!set_delete_on_close(fsp, delete_on_close,
5819 &conn->session_info->utok)) {
5820 return NT_STATUS_ACCESS_DENIED;
5822 return NT_STATUS_OK;
5825 /****************************************************************************
5826 Deal with SMB_FILE_POSITION_INFORMATION.
5827 ****************************************************************************/
5829 static NTSTATUS smb_file_position_information(connection_struct *conn,
5830 const char *pdata,
5831 int total_data,
5832 files_struct *fsp)
5834 uint64_t position_information;
5836 if (total_data < 8) {
5837 return NT_STATUS_INVALID_PARAMETER;
5840 if (fsp == NULL) {
5841 /* Ignore on pathname based set. */
5842 return NT_STATUS_OK;
5845 position_information = (uint64_t)IVAL(pdata,0);
5846 #ifdef LARGE_SMB_OFF_T
5847 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5848 #else /* LARGE_SMB_OFF_T */
5849 if (IVAL(pdata,4) != 0) {
5850 /* more than 32 bits? */
5851 return NT_STATUS_INVALID_PARAMETER;
5853 #endif /* LARGE_SMB_OFF_T */
5855 DEBUG(10,("smb_file_position_information: Set file position "
5856 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5857 (double)position_information));
5858 fsp->fh->position_information = position_information;
5859 return NT_STATUS_OK;
5862 /****************************************************************************
5863 Deal with SMB_FILE_MODE_INFORMATION.
5864 ****************************************************************************/
5866 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5867 const char *pdata,
5868 int total_data)
5870 uint32 mode;
5872 if (total_data < 4) {
5873 return NT_STATUS_INVALID_PARAMETER;
5875 mode = IVAL(pdata,0);
5876 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5877 return NT_STATUS_INVALID_PARAMETER;
5879 return NT_STATUS_OK;
5882 /****************************************************************************
5883 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5884 ****************************************************************************/
5886 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5887 struct smb_request *req,
5888 const char *pdata,
5889 int total_data,
5890 const struct smb_filename *smb_fname)
5892 char *link_target = NULL;
5893 const char *newname = smb_fname->base_name;
5894 TALLOC_CTX *ctx = talloc_tos();
5896 /* Set a symbolic link. */
5897 /* Don't allow this if follow links is false. */
5899 if (total_data == 0) {
5900 return NT_STATUS_INVALID_PARAMETER;
5903 if (!lp_symlinks(SNUM(conn))) {
5904 return NT_STATUS_ACCESS_DENIED;
5907 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5908 total_data, STR_TERMINATE);
5910 if (!link_target) {
5911 return NT_STATUS_INVALID_PARAMETER;
5914 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5915 newname, link_target ));
5917 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5918 return map_nt_error_from_unix(errno);
5921 return NT_STATUS_OK;
5924 /****************************************************************************
5925 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5926 ****************************************************************************/
5928 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5929 struct smb_request *req,
5930 const char *pdata, int total_data,
5931 struct smb_filename *smb_fname_new)
5933 char *oldname = NULL;
5934 struct smb_filename *smb_fname_old = NULL;
5935 TALLOC_CTX *ctx = talloc_tos();
5936 NTSTATUS status = NT_STATUS_OK;
5938 /* Set a hard link. */
5939 if (total_data == 0) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5944 total_data, STR_TERMINATE, &status);
5945 if (!NT_STATUS_IS_OK(status)) {
5946 return status;
5949 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5950 smb_fname_str_dbg(smb_fname_new), oldname));
5952 status = filename_convert(ctx,
5953 conn,
5954 req->flags2 & FLAGS2_DFS_PATHNAMES,
5955 oldname,
5957 NULL,
5958 &smb_fname_old);
5959 if (!NT_STATUS_IS_OK(status)) {
5960 return status;
5963 return hardlink_internals(ctx, conn, req, false,
5964 smb_fname_old, smb_fname_new);
5967 /****************************************************************************
5968 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5969 ****************************************************************************/
5971 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5972 struct smb_request *req,
5973 const char *pdata,
5974 int total_data,
5975 files_struct *fsp,
5976 struct smb_filename *smb_fname_src)
5978 bool overwrite;
5979 uint32_t len;
5980 char *newname = NULL;
5981 struct smb_filename *smb_fname_dst = NULL;
5982 NTSTATUS status = NT_STATUS_OK;
5983 TALLOC_CTX *ctx = talloc_tos();
5985 if (!fsp) {
5986 return NT_STATUS_INVALID_HANDLE;
5989 if (total_data < 20) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 overwrite = (CVAL(pdata,0) ? True : False);
5994 len = IVAL(pdata,16);
5996 if (len > (total_data - 20) || (len == 0)) {
5997 return NT_STATUS_INVALID_PARAMETER;
6000 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6001 &pdata[20], len, STR_TERMINATE,
6002 &status);
6003 if (!NT_STATUS_IS_OK(status)) {
6004 return status;
6007 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6008 newname));
6010 status = filename_convert(ctx,
6011 conn,
6012 req->flags2 & FLAGS2_DFS_PATHNAMES,
6013 newname,
6014 UCF_SAVE_LCOMP,
6015 NULL,
6016 &smb_fname_dst);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 return status;
6021 if (fsp->base_fsp) {
6022 /* newname must be a stream name. */
6023 if (newname[0] != ':') {
6024 return NT_STATUS_NOT_SUPPORTED;
6027 /* Create an smb_fname to call rename_internals_fsp() with. */
6028 status = create_synthetic_smb_fname(talloc_tos(),
6029 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6030 &smb_fname_dst);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 goto out;
6036 * Set the original last component, since
6037 * rename_internals_fsp() requires it.
6039 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6040 newname);
6041 if (smb_fname_dst->original_lcomp == NULL) {
6042 status = NT_STATUS_NO_MEMORY;
6043 goto out;
6048 DEBUG(10,("smb2_file_rename_information: "
6049 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6050 fsp->fnum, fsp_str_dbg(fsp),
6051 smb_fname_str_dbg(smb_fname_dst)));
6052 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6053 overwrite);
6055 out:
6056 TALLOC_FREE(smb_fname_dst);
6057 return status;
6060 static NTSTATUS smb_file_link_information(connection_struct *conn,
6061 struct smb_request *req,
6062 const char *pdata,
6063 int total_data,
6064 files_struct *fsp,
6065 struct smb_filename *smb_fname_src)
6067 bool overwrite;
6068 uint32_t len;
6069 char *newname = NULL;
6070 struct smb_filename *smb_fname_dst = NULL;
6071 NTSTATUS status = NT_STATUS_OK;
6072 TALLOC_CTX *ctx = talloc_tos();
6074 if (!fsp) {
6075 return NT_STATUS_INVALID_HANDLE;
6078 if (total_data < 20) {
6079 return NT_STATUS_INVALID_PARAMETER;
6082 overwrite = (CVAL(pdata,0) ? true : false);
6083 len = IVAL(pdata,16);
6085 if (len > (total_data - 20) || (len == 0)) {
6086 return NT_STATUS_INVALID_PARAMETER;
6089 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6090 &pdata[20], len, STR_TERMINATE,
6091 &status);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 return status;
6096 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6097 newname));
6099 status = filename_convert(ctx,
6100 conn,
6101 req->flags2 & FLAGS2_DFS_PATHNAMES,
6102 newname,
6103 UCF_SAVE_LCOMP,
6104 NULL,
6105 &smb_fname_dst);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 return status;
6110 if (fsp->base_fsp) {
6111 /* No stream names. */
6112 return NT_STATUS_NOT_SUPPORTED;
6115 DEBUG(10,("smb_file_link_information: "
6116 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6117 fsp->fnum, fsp_str_dbg(fsp),
6118 smb_fname_str_dbg(smb_fname_dst)));
6119 status = hardlink_internals(ctx,
6120 conn,
6121 req,
6122 overwrite,
6123 fsp->fsp_name,
6124 smb_fname_dst);
6126 TALLOC_FREE(smb_fname_dst);
6127 return status;
6130 /****************************************************************************
6131 Deal with SMB_FILE_RENAME_INFORMATION.
6132 ****************************************************************************/
6134 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6135 struct smb_request *req,
6136 const char *pdata,
6137 int total_data,
6138 files_struct *fsp,
6139 struct smb_filename *smb_fname_src)
6141 bool overwrite;
6142 uint32 root_fid;
6143 uint32 len;
6144 char *newname = NULL;
6145 struct smb_filename *smb_fname_dst = NULL;
6146 bool dest_has_wcard = False;
6147 NTSTATUS status = NT_STATUS_OK;
6148 char *p;
6149 TALLOC_CTX *ctx = talloc_tos();
6151 if (total_data < 13) {
6152 return NT_STATUS_INVALID_PARAMETER;
6155 overwrite = (CVAL(pdata,0) ? True : False);
6156 root_fid = IVAL(pdata,4);
6157 len = IVAL(pdata,8);
6159 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6160 return NT_STATUS_INVALID_PARAMETER;
6163 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6164 len, 0, &status,
6165 &dest_has_wcard);
6166 if (!NT_STATUS_IS_OK(status)) {
6167 return status;
6170 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6171 newname));
6173 status = resolve_dfspath_wcard(ctx, conn,
6174 req->flags2 & FLAGS2_DFS_PATHNAMES,
6175 newname,
6176 true,
6177 &newname,
6178 &dest_has_wcard);
6179 if (!NT_STATUS_IS_OK(status)) {
6180 return status;
6183 /* Check the new name has no '/' characters. */
6184 if (strchr_m(newname, '/')) {
6185 return NT_STATUS_NOT_SUPPORTED;
6188 if (fsp && fsp->base_fsp) {
6189 /* newname must be a stream name. */
6190 if (newname[0] != ':') {
6191 return NT_STATUS_NOT_SUPPORTED;
6194 /* Create an smb_fname to call rename_internals_fsp() with. */
6195 status = create_synthetic_smb_fname(talloc_tos(),
6196 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6197 &smb_fname_dst);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 goto out;
6203 * Set the original last component, since
6204 * rename_internals_fsp() requires it.
6206 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6207 newname);
6208 if (smb_fname_dst->original_lcomp == NULL) {
6209 status = NT_STATUS_NO_MEMORY;
6210 goto out;
6213 } else {
6215 * Build up an smb_fname_dst based on the filename passed in.
6216 * We basically just strip off the last component, and put on
6217 * the newname instead.
6219 char *base_name = NULL;
6221 /* newname must *not* be a stream name. */
6222 if (newname[0] == ':') {
6223 return NT_STATUS_NOT_SUPPORTED;
6227 * Strip off the last component (filename) of the path passed
6228 * in.
6230 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6231 if (!base_name) {
6232 return NT_STATUS_NO_MEMORY;
6234 p = strrchr_m(base_name, '/');
6235 if (p) {
6236 p[1] = '\0';
6237 } else {
6238 base_name = talloc_strdup(ctx, "");
6239 if (!base_name) {
6240 return NT_STATUS_NO_MEMORY;
6243 /* Append the new name. */
6244 base_name = talloc_asprintf_append(base_name,
6245 "%s",
6246 newname);
6247 if (!base_name) {
6248 return NT_STATUS_NO_MEMORY;
6251 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6252 (UCF_SAVE_LCOMP |
6253 (dest_has_wcard ?
6254 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6255 0)));
6257 /* If an error we expect this to be
6258 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6260 if (!NT_STATUS_IS_OK(status)) {
6261 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6262 status)) {
6263 goto out;
6265 /* Create an smb_fname to call rename_internals_fsp() */
6266 status = create_synthetic_smb_fname(ctx,
6267 base_name, NULL,
6268 NULL,
6269 &smb_fname_dst);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 goto out;
6276 if (fsp) {
6277 DEBUG(10,("smb_file_rename_information: "
6278 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6279 fsp->fnum, fsp_str_dbg(fsp),
6280 smb_fname_str_dbg(smb_fname_dst)));
6281 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6282 overwrite);
6283 } else {
6284 DEBUG(10,("smb_file_rename_information: "
6285 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6286 smb_fname_str_dbg(smb_fname_src),
6287 smb_fname_str_dbg(smb_fname_dst)));
6288 status = rename_internals(ctx, conn, req, smb_fname_src,
6289 smb_fname_dst, 0, overwrite, false,
6290 dest_has_wcard,
6291 FILE_WRITE_ATTRIBUTES);
6293 out:
6294 TALLOC_FREE(smb_fname_dst);
6295 return status;
6298 /****************************************************************************
6299 Deal with SMB_SET_POSIX_ACL.
6300 ****************************************************************************/
6302 #if defined(HAVE_POSIX_ACLS)
6303 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6304 const char *pdata,
6305 int total_data,
6306 files_struct *fsp,
6307 const struct smb_filename *smb_fname)
6309 uint16 posix_acl_version;
6310 uint16 num_file_acls;
6311 uint16 num_def_acls;
6312 bool valid_file_acls = True;
6313 bool valid_def_acls = True;
6315 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6316 return NT_STATUS_INVALID_PARAMETER;
6318 posix_acl_version = SVAL(pdata,0);
6319 num_file_acls = SVAL(pdata,2);
6320 num_def_acls = SVAL(pdata,4);
6322 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6323 valid_file_acls = False;
6324 num_file_acls = 0;
6327 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6328 valid_def_acls = False;
6329 num_def_acls = 0;
6332 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6337 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6338 return NT_STATUS_INVALID_PARAMETER;
6341 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6342 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6343 (unsigned int)num_file_acls,
6344 (unsigned int)num_def_acls));
6346 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6347 smb_fname->base_name, num_file_acls,
6348 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6349 return map_nt_error_from_unix(errno);
6352 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6353 smb_fname->base_name, &smb_fname->st, num_def_acls,
6354 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6355 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6356 return map_nt_error_from_unix(errno);
6358 return NT_STATUS_OK;
6360 #endif
6362 /****************************************************************************
6363 Deal with SMB_SET_POSIX_LOCK.
6364 ****************************************************************************/
6366 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6367 struct smb_request *req,
6368 const char *pdata,
6369 int total_data,
6370 files_struct *fsp)
6372 uint64_t count;
6373 uint64_t offset;
6374 uint64_t smblctx;
6375 bool blocking_lock = False;
6376 enum brl_type lock_type;
6378 NTSTATUS status = NT_STATUS_OK;
6380 if (fsp == NULL || fsp->fh->fd == -1) {
6381 return NT_STATUS_INVALID_HANDLE;
6384 if (total_data != POSIX_LOCK_DATA_SIZE) {
6385 return NT_STATUS_INVALID_PARAMETER;
6388 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6389 case POSIX_LOCK_TYPE_READ:
6390 lock_type = READ_LOCK;
6391 break;
6392 case POSIX_LOCK_TYPE_WRITE:
6393 /* Return the right POSIX-mappable error code for files opened read-only. */
6394 if (!fsp->can_write) {
6395 return NT_STATUS_INVALID_HANDLE;
6397 lock_type = WRITE_LOCK;
6398 break;
6399 case POSIX_LOCK_TYPE_UNLOCK:
6400 lock_type = UNLOCK_LOCK;
6401 break;
6402 default:
6403 return NT_STATUS_INVALID_PARAMETER;
6406 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6407 blocking_lock = False;
6408 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6409 blocking_lock = True;
6410 } else {
6411 return NT_STATUS_INVALID_PARAMETER;
6414 if (!lp_blocking_locks(SNUM(conn))) {
6415 blocking_lock = False;
6418 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6419 #if defined(HAVE_LONGLONG)
6420 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6421 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6422 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6423 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6424 #else /* HAVE_LONGLONG */
6425 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6426 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6427 #endif /* HAVE_LONGLONG */
6429 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6430 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6431 fsp_str_dbg(fsp),
6432 (unsigned int)lock_type,
6433 (unsigned long long)smblctx,
6434 (double)count,
6435 (double)offset ));
6437 if (lock_type == UNLOCK_LOCK) {
6438 status = do_unlock(req->sconn->msg_ctx,
6439 fsp,
6440 smblctx,
6441 count,
6442 offset,
6443 POSIX_LOCK);
6444 } else {
6445 uint64_t block_smblctx;
6447 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6448 fsp,
6449 smblctx,
6450 count,
6451 offset,
6452 lock_type,
6453 POSIX_LOCK,
6454 blocking_lock,
6455 &status,
6456 &block_smblctx,
6457 NULL);
6459 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6461 * A blocking lock was requested. Package up
6462 * this smb into a queued request and push it
6463 * onto the blocking lock queue.
6465 if(push_blocking_lock_request(br_lck,
6466 req,
6467 fsp,
6468 -1, /* infinite timeout. */
6470 smblctx,
6471 lock_type,
6472 POSIX_LOCK,
6473 offset,
6474 count,
6475 block_smblctx)) {
6476 TALLOC_FREE(br_lck);
6477 return status;
6480 TALLOC_FREE(br_lck);
6483 return status;
6486 /****************************************************************************
6487 Deal with SMB_SET_FILE_BASIC_INFO.
6488 ****************************************************************************/
6490 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6491 const char *pdata,
6492 int total_data,
6493 files_struct *fsp,
6494 const struct smb_filename *smb_fname)
6496 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6497 struct smb_file_time ft;
6498 uint32 dosmode = 0;
6499 NTSTATUS status = NT_STATUS_OK;
6501 ZERO_STRUCT(ft);
6503 if (total_data < 36) {
6504 return NT_STATUS_INVALID_PARAMETER;
6507 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6508 return NT_STATUS_ACCESS_DENIED;
6511 /* Set the attributes */
6512 dosmode = IVAL(pdata,32);
6513 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6514 if (!NT_STATUS_IS_OK(status)) {
6515 return status;
6518 /* create time */
6519 ft.create_time = interpret_long_date(pdata);
6521 /* access time */
6522 ft.atime = interpret_long_date(pdata+8);
6524 /* write time. */
6525 ft.mtime = interpret_long_date(pdata+16);
6527 /* change time. */
6528 ft.ctime = interpret_long_date(pdata+24);
6530 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6531 smb_fname_str_dbg(smb_fname)));
6533 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6534 true);
6537 /****************************************************************************
6538 Deal with SMB_INFO_STANDARD.
6539 ****************************************************************************/
6541 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6542 const char *pdata,
6543 int total_data,
6544 files_struct *fsp,
6545 const struct smb_filename *smb_fname)
6547 struct smb_file_time ft;
6549 ZERO_STRUCT(ft);
6551 if (total_data < 12) {
6552 return NT_STATUS_INVALID_PARAMETER;
6555 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6556 return NT_STATUS_ACCESS_DENIED;
6559 /* create time */
6560 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6561 /* access time */
6562 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6563 /* write time */
6564 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6566 DEBUG(10,("smb_set_info_standard: file %s\n",
6567 smb_fname_str_dbg(smb_fname)));
6569 return smb_set_file_time(conn,
6570 fsp,
6571 smb_fname,
6572 &ft,
6573 true);
6576 /****************************************************************************
6577 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6578 ****************************************************************************/
6580 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6581 struct smb_request *req,
6582 const char *pdata,
6583 int total_data,
6584 files_struct *fsp,
6585 struct smb_filename *smb_fname)
6587 uint64_t allocation_size = 0;
6588 NTSTATUS status = NT_STATUS_OK;
6589 files_struct *new_fsp = NULL;
6591 if (!VALID_STAT(smb_fname->st)) {
6592 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6595 if (total_data < 8) {
6596 return NT_STATUS_INVALID_PARAMETER;
6599 allocation_size = (uint64_t)IVAL(pdata,0);
6600 #ifdef LARGE_SMB_OFF_T
6601 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6602 #else /* LARGE_SMB_OFF_T */
6603 if (IVAL(pdata,4) != 0) {
6604 /* more than 32 bits? */
6605 return NT_STATUS_INVALID_PARAMETER;
6607 #endif /* LARGE_SMB_OFF_T */
6609 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6610 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6611 (double)allocation_size));
6613 if (allocation_size) {
6614 allocation_size = smb_roundup(conn, allocation_size);
6617 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6618 return NT_STATUS_ACCESS_DENIED;
6621 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6622 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6623 (double)allocation_size));
6625 if (fsp && fsp->fh->fd != -1) {
6626 /* Open file handle. */
6627 /* Only change if needed. */
6628 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6629 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6630 return map_nt_error_from_unix(errno);
6633 /* But always update the time. */
6635 * This is equivalent to a write. Ensure it's seen immediately
6636 * if there are no pending writes.
6638 trigger_write_time_update_immediate(fsp);
6639 return NT_STATUS_OK;
6642 /* Pathname or stat or directory file. */
6643 status = SMB_VFS_CREATE_FILE(
6644 conn, /* conn */
6645 req, /* req */
6646 0, /* root_dir_fid */
6647 smb_fname, /* fname */
6648 FILE_WRITE_DATA, /* access_mask */
6649 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6650 FILE_SHARE_DELETE),
6651 FILE_OPEN, /* create_disposition*/
6652 0, /* create_options */
6653 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6654 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6655 0, /* allocation_size */
6656 0, /* private_flags */
6657 NULL, /* sd */
6658 NULL, /* ea_list */
6659 &new_fsp, /* result */
6660 NULL); /* pinfo */
6662 if (!NT_STATUS_IS_OK(status)) {
6663 /* NB. We check for open_was_deferred in the caller. */
6664 return status;
6667 /* Only change if needed. */
6668 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6669 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6670 status = map_nt_error_from_unix(errno);
6671 close_file(req, new_fsp, NORMAL_CLOSE);
6672 return status;
6676 /* Changing the allocation size should set the last mod time. */
6678 * This is equivalent to a write. Ensure it's seen immediately
6679 * if there are no pending writes.
6681 trigger_write_time_update_immediate(new_fsp);
6683 close_file(req, new_fsp, NORMAL_CLOSE);
6684 return NT_STATUS_OK;
6687 /****************************************************************************
6688 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6689 ****************************************************************************/
6691 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6692 struct smb_request *req,
6693 const char *pdata,
6694 int total_data,
6695 files_struct *fsp,
6696 const struct smb_filename *smb_fname,
6697 bool fail_after_createfile)
6699 SMB_OFF_T size;
6701 if (total_data < 8) {
6702 return NT_STATUS_INVALID_PARAMETER;
6705 size = IVAL(pdata,0);
6706 #ifdef LARGE_SMB_OFF_T
6707 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6708 #else /* LARGE_SMB_OFF_T */
6709 if (IVAL(pdata,4) != 0) {
6710 /* more than 32 bits? */
6711 return NT_STATUS_INVALID_PARAMETER;
6713 #endif /* LARGE_SMB_OFF_T */
6714 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6715 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6716 (double)size));
6718 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6719 return NT_STATUS_ACCESS_DENIED;
6722 return smb_set_file_size(conn, req,
6723 fsp,
6724 smb_fname,
6725 &smb_fname->st,
6726 size,
6727 fail_after_createfile);
6730 /****************************************************************************
6731 Allow a UNIX info mknod.
6732 ****************************************************************************/
6734 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6735 const char *pdata,
6736 int total_data,
6737 const struct smb_filename *smb_fname)
6739 uint32 file_type = IVAL(pdata,56);
6740 #if defined(HAVE_MAKEDEV)
6741 uint32 dev_major = IVAL(pdata,60);
6742 uint32 dev_minor = IVAL(pdata,68);
6743 #endif
6744 SMB_DEV_T dev = (SMB_DEV_T)0;
6745 uint32 raw_unixmode = IVAL(pdata,84);
6746 NTSTATUS status;
6747 mode_t unixmode;
6749 if (total_data < 100) {
6750 return NT_STATUS_INVALID_PARAMETER;
6753 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6754 PERM_NEW_FILE, &unixmode);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 return status;
6759 #if defined(HAVE_MAKEDEV)
6760 dev = makedev(dev_major, dev_minor);
6761 #endif
6763 switch (file_type) {
6764 #if defined(S_IFIFO)
6765 case UNIX_TYPE_FIFO:
6766 unixmode |= S_IFIFO;
6767 break;
6768 #endif
6769 #if defined(S_IFSOCK)
6770 case UNIX_TYPE_SOCKET:
6771 unixmode |= S_IFSOCK;
6772 break;
6773 #endif
6774 #if defined(S_IFCHR)
6775 case UNIX_TYPE_CHARDEV:
6776 unixmode |= S_IFCHR;
6777 break;
6778 #endif
6779 #if defined(S_IFBLK)
6780 case UNIX_TYPE_BLKDEV:
6781 unixmode |= S_IFBLK;
6782 break;
6783 #endif
6784 default:
6785 return NT_STATUS_INVALID_PARAMETER;
6788 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6789 "%.0f mode 0%o for file %s\n", (double)dev,
6790 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6792 /* Ok - do the mknod. */
6793 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6794 return map_nt_error_from_unix(errno);
6797 /* If any of the other "set" calls fail we
6798 * don't want to end up with a half-constructed mknod.
6801 if (lp_inherit_perms(SNUM(conn))) {
6802 char *parent;
6803 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6804 &parent, NULL)) {
6805 return NT_STATUS_NO_MEMORY;
6807 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6808 unixmode);
6809 TALLOC_FREE(parent);
6812 return NT_STATUS_OK;
6815 /****************************************************************************
6816 Deal with SMB_SET_FILE_UNIX_BASIC.
6817 ****************************************************************************/
6819 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6820 struct smb_request *req,
6821 const char *pdata,
6822 int total_data,
6823 files_struct *fsp,
6824 const struct smb_filename *smb_fname)
6826 struct smb_file_time ft;
6827 uint32 raw_unixmode;
6828 mode_t unixmode;
6829 SMB_OFF_T size = 0;
6830 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6831 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6832 NTSTATUS status = NT_STATUS_OK;
6833 bool delete_on_fail = False;
6834 enum perm_type ptype;
6835 files_struct *all_fsps = NULL;
6836 bool modify_mtime = true;
6837 struct file_id id;
6838 struct smb_filename *smb_fname_tmp = NULL;
6839 SMB_STRUCT_STAT sbuf;
6841 ZERO_STRUCT(ft);
6843 if (total_data < 100) {
6844 return NT_STATUS_INVALID_PARAMETER;
6847 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6848 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6849 size=IVAL(pdata,0); /* first 8 Bytes are size */
6850 #ifdef LARGE_SMB_OFF_T
6851 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6852 #else /* LARGE_SMB_OFF_T */
6853 if (IVAL(pdata,4) != 0) {
6854 /* more than 32 bits? */
6855 return NT_STATUS_INVALID_PARAMETER;
6857 #endif /* LARGE_SMB_OFF_T */
6860 ft.atime = interpret_long_date(pdata+24); /* access_time */
6861 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6862 set_owner = (uid_t)IVAL(pdata,40);
6863 set_grp = (gid_t)IVAL(pdata,48);
6864 raw_unixmode = IVAL(pdata,84);
6866 if (VALID_STAT(smb_fname->st)) {
6867 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6868 ptype = PERM_EXISTING_DIR;
6869 } else {
6870 ptype = PERM_EXISTING_FILE;
6872 } else {
6873 ptype = PERM_NEW_FILE;
6876 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6877 ptype, &unixmode);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 return status;
6882 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6883 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6884 smb_fname_str_dbg(smb_fname), (double)size,
6885 (unsigned int)set_owner, (unsigned int)set_grp,
6886 (int)raw_unixmode));
6888 sbuf = smb_fname->st;
6890 if (!VALID_STAT(sbuf)) {
6892 * The only valid use of this is to create character and block
6893 * devices, and named pipes. This is deprecated (IMHO) and
6894 * a new info level should be used for mknod. JRA.
6897 status = smb_unix_mknod(conn,
6898 pdata,
6899 total_data,
6900 smb_fname);
6901 if (!NT_STATUS_IS_OK(status)) {
6902 return status;
6905 status = copy_smb_filename(talloc_tos(), smb_fname,
6906 &smb_fname_tmp);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 return status;
6911 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6912 status = map_nt_error_from_unix(errno);
6913 TALLOC_FREE(smb_fname_tmp);
6914 SMB_VFS_UNLINK(conn, smb_fname);
6915 return status;
6918 sbuf = smb_fname_tmp->st;
6919 smb_fname = smb_fname_tmp;
6921 /* Ensure we don't try and change anything else. */
6922 raw_unixmode = SMB_MODE_NO_CHANGE;
6923 size = get_file_size_stat(&sbuf);
6924 ft.atime = sbuf.st_ex_atime;
6925 ft.mtime = sbuf.st_ex_mtime;
6927 * We continue here as we might want to change the
6928 * owner uid/gid.
6930 delete_on_fail = True;
6933 #if 1
6934 /* Horrible backwards compatibility hack as an old server bug
6935 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6936 * */
6938 if (!size) {
6939 size = get_file_size_stat(&sbuf);
6941 #endif
6944 * Deal with the UNIX specific mode set.
6947 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6948 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6949 "setting mode 0%o for file %s\n",
6950 (unsigned int)unixmode,
6951 smb_fname_str_dbg(smb_fname)));
6952 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6953 return map_nt_error_from_unix(errno);
6958 * Deal with the UNIX specific uid set.
6961 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6962 (sbuf.st_ex_uid != set_owner)) {
6963 int ret;
6965 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6966 "changing owner %u for path %s\n",
6967 (unsigned int)set_owner,
6968 smb_fname_str_dbg(smb_fname)));
6970 if (S_ISLNK(sbuf.st_ex_mode)) {
6971 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6972 set_owner, (gid_t)-1);
6973 } else {
6974 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6975 set_owner, (gid_t)-1);
6978 if (ret != 0) {
6979 status = map_nt_error_from_unix(errno);
6980 if (delete_on_fail) {
6981 SMB_VFS_UNLINK(conn, smb_fname);
6983 return status;
6988 * Deal with the UNIX specific gid set.
6991 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6992 (sbuf.st_ex_gid != set_grp)) {
6993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6994 "changing group %u for file %s\n",
6995 (unsigned int)set_owner,
6996 smb_fname_str_dbg(smb_fname)));
6997 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6998 set_grp) != 0) {
6999 status = map_nt_error_from_unix(errno);
7000 if (delete_on_fail) {
7001 SMB_VFS_UNLINK(conn, smb_fname);
7003 return status;
7007 /* Deal with any size changes. */
7009 status = smb_set_file_size(conn, req,
7010 fsp,
7011 smb_fname,
7012 &sbuf,
7013 size,
7014 false);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 return status;
7019 /* Deal with any time changes. */
7020 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7021 /* No change, don't cancel anything. */
7022 return status;
7025 id = vfs_file_id_from_sbuf(conn, &sbuf);
7026 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7027 all_fsps = file_find_di_next(all_fsps)) {
7029 * We're setting the time explicitly for UNIX.
7030 * Cancel any pending changes over all handles.
7032 all_fsps->update_write_time_on_close = false;
7033 TALLOC_FREE(all_fsps->update_write_time_event);
7037 * Override the "setting_write_time"
7038 * parameter here as it almost does what
7039 * we need. Just remember if we modified
7040 * mtime and send the notify ourselves.
7042 if (null_timespec(ft.mtime)) {
7043 modify_mtime = false;
7046 status = smb_set_file_time(conn,
7047 fsp,
7048 smb_fname,
7049 &ft,
7050 false);
7051 if (modify_mtime) {
7052 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7053 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7055 return status;
7058 /****************************************************************************
7059 Deal with SMB_SET_FILE_UNIX_INFO2.
7060 ****************************************************************************/
7062 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7063 struct smb_request *req,
7064 const char *pdata,
7065 int total_data,
7066 files_struct *fsp,
7067 const struct smb_filename *smb_fname)
7069 NTSTATUS status;
7070 uint32 smb_fflags;
7071 uint32 smb_fmask;
7073 if (total_data < 116) {
7074 return NT_STATUS_INVALID_PARAMETER;
7077 /* Start by setting all the fields that are common between UNIX_BASIC
7078 * and UNIX_INFO2.
7080 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7081 fsp, smb_fname);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 return status;
7086 smb_fflags = IVAL(pdata, 108);
7087 smb_fmask = IVAL(pdata, 112);
7089 /* NB: We should only attempt to alter the file flags if the client
7090 * sends a non-zero mask.
7092 if (smb_fmask != 0) {
7093 int stat_fflags = 0;
7095 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7096 smb_fmask, &stat_fflags)) {
7097 /* Client asked to alter a flag we don't understand. */
7098 return NT_STATUS_INVALID_PARAMETER;
7101 if (fsp && fsp->fh->fd != -1) {
7102 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7103 return NT_STATUS_NOT_SUPPORTED;
7104 } else {
7105 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7106 stat_fflags) != 0) {
7107 return map_nt_error_from_unix(errno);
7112 /* XXX: need to add support for changing the create_time here. You
7113 * can do this for paths on Darwin with setattrlist(2). The right way
7114 * to hook this up is probably by extending the VFS utimes interface.
7117 return NT_STATUS_OK;
7120 /****************************************************************************
7121 Create a directory with POSIX semantics.
7122 ****************************************************************************/
7124 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7125 struct smb_request *req,
7126 char **ppdata,
7127 int total_data,
7128 struct smb_filename *smb_fname,
7129 int *pdata_return_size)
7131 NTSTATUS status = NT_STATUS_OK;
7132 uint32 raw_unixmode = 0;
7133 uint32 mod_unixmode = 0;
7134 mode_t unixmode = (mode_t)0;
7135 files_struct *fsp = NULL;
7136 uint16 info_level_return = 0;
7137 int info;
7138 char *pdata = *ppdata;
7140 if (total_data < 18) {
7141 return NT_STATUS_INVALID_PARAMETER;
7144 raw_unixmode = IVAL(pdata,8);
7145 /* Next 4 bytes are not yet defined. */
7147 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7148 PERM_NEW_DIR, &unixmode);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 return status;
7153 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7155 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7156 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7158 status = SMB_VFS_CREATE_FILE(
7159 conn, /* conn */
7160 req, /* req */
7161 0, /* root_dir_fid */
7162 smb_fname, /* fname */
7163 FILE_READ_ATTRIBUTES, /* access_mask */
7164 FILE_SHARE_NONE, /* share_access */
7165 FILE_CREATE, /* create_disposition*/
7166 FILE_DIRECTORY_FILE, /* create_options */
7167 mod_unixmode, /* file_attributes */
7168 0, /* oplock_request */
7169 0, /* allocation_size */
7170 0, /* private_flags */
7171 NULL, /* sd */
7172 NULL, /* ea_list */
7173 &fsp, /* result */
7174 &info); /* pinfo */
7176 if (NT_STATUS_IS_OK(status)) {
7177 close_file(req, fsp, NORMAL_CLOSE);
7180 info_level_return = SVAL(pdata,16);
7182 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7183 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7184 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7185 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7186 } else {
7187 *pdata_return_size = 12;
7190 /* Realloc the data size */
7191 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7192 if (*ppdata == NULL) {
7193 *pdata_return_size = 0;
7194 return NT_STATUS_NO_MEMORY;
7196 pdata = *ppdata;
7198 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7199 SSVAL(pdata,2,0); /* No fnum. */
7200 SIVAL(pdata,4,info); /* Was directory created. */
7202 switch (info_level_return) {
7203 case SMB_QUERY_FILE_UNIX_BASIC:
7204 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7205 SSVAL(pdata,10,0); /* Padding. */
7206 store_file_unix_basic(conn, pdata + 12, fsp,
7207 &smb_fname->st);
7208 break;
7209 case SMB_QUERY_FILE_UNIX_INFO2:
7210 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7211 SSVAL(pdata,10,0); /* Padding. */
7212 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7213 &smb_fname->st);
7214 break;
7215 default:
7216 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7217 SSVAL(pdata,10,0); /* Padding. */
7218 break;
7221 return status;
7224 /****************************************************************************
7225 Open/Create a file with POSIX semantics.
7226 ****************************************************************************/
7228 static NTSTATUS smb_posix_open(connection_struct *conn,
7229 struct smb_request *req,
7230 char **ppdata,
7231 int total_data,
7232 struct smb_filename *smb_fname,
7233 int *pdata_return_size)
7235 bool extended_oplock_granted = False;
7236 char *pdata = *ppdata;
7237 uint32 flags = 0;
7238 uint32 wire_open_mode = 0;
7239 uint32 raw_unixmode = 0;
7240 uint32 mod_unixmode = 0;
7241 uint32 create_disp = 0;
7242 uint32 access_mask = 0;
7243 uint32 create_options = 0;
7244 NTSTATUS status = NT_STATUS_OK;
7245 mode_t unixmode = (mode_t)0;
7246 files_struct *fsp = NULL;
7247 int oplock_request = 0;
7248 int info = 0;
7249 uint16 info_level_return = 0;
7251 if (total_data < 18) {
7252 return NT_STATUS_INVALID_PARAMETER;
7255 flags = IVAL(pdata,0);
7256 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7257 if (oplock_request) {
7258 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7261 wire_open_mode = IVAL(pdata,4);
7263 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7264 return smb_posix_mkdir(conn, req,
7265 ppdata,
7266 total_data,
7267 smb_fname,
7268 pdata_return_size);
7271 switch (wire_open_mode & SMB_ACCMODE) {
7272 case SMB_O_RDONLY:
7273 access_mask = FILE_READ_DATA;
7274 break;
7275 case SMB_O_WRONLY:
7276 access_mask = FILE_WRITE_DATA;
7277 break;
7278 case SMB_O_RDWR:
7279 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7280 break;
7281 default:
7282 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7283 (unsigned int)wire_open_mode ));
7284 return NT_STATUS_INVALID_PARAMETER;
7287 wire_open_mode &= ~SMB_ACCMODE;
7289 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7290 create_disp = FILE_CREATE;
7291 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7292 create_disp = FILE_OVERWRITE_IF;
7293 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7294 create_disp = FILE_OPEN_IF;
7295 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7296 create_disp = FILE_OPEN;
7297 } else {
7298 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7299 (unsigned int)wire_open_mode ));
7300 return NT_STATUS_INVALID_PARAMETER;
7303 raw_unixmode = IVAL(pdata,8);
7304 /* Next 4 bytes are not yet defined. */
7306 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7307 (VALID_STAT(smb_fname->st) ?
7308 PERM_EXISTING_FILE : PERM_NEW_FILE),
7309 &unixmode);
7311 if (!NT_STATUS_IS_OK(status)) {
7312 return status;
7315 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7317 if (wire_open_mode & SMB_O_SYNC) {
7318 create_options |= FILE_WRITE_THROUGH;
7320 if (wire_open_mode & SMB_O_APPEND) {
7321 access_mask |= FILE_APPEND_DATA;
7323 if (wire_open_mode & SMB_O_DIRECT) {
7324 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7327 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7328 smb_fname_str_dbg(smb_fname),
7329 (unsigned int)wire_open_mode,
7330 (unsigned int)unixmode ));
7332 status = SMB_VFS_CREATE_FILE(
7333 conn, /* conn */
7334 req, /* req */
7335 0, /* root_dir_fid */
7336 smb_fname, /* fname */
7337 access_mask, /* access_mask */
7338 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7339 FILE_SHARE_DELETE),
7340 create_disp, /* create_disposition*/
7341 FILE_NON_DIRECTORY_FILE, /* create_options */
7342 mod_unixmode, /* file_attributes */
7343 oplock_request, /* oplock_request */
7344 0, /* allocation_size */
7345 0, /* private_flags */
7346 NULL, /* sd */
7347 NULL, /* ea_list */
7348 &fsp, /* result */
7349 &info); /* pinfo */
7351 if (!NT_STATUS_IS_OK(status)) {
7352 return status;
7355 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7356 extended_oplock_granted = True;
7359 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7360 extended_oplock_granted = True;
7363 info_level_return = SVAL(pdata,16);
7365 /* Allocate the correct return size. */
7367 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7368 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7369 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7370 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7371 } else {
7372 *pdata_return_size = 12;
7375 /* Realloc the data size */
7376 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7377 if (*ppdata == NULL) {
7378 close_file(req, fsp, ERROR_CLOSE);
7379 *pdata_return_size = 0;
7380 return NT_STATUS_NO_MEMORY;
7382 pdata = *ppdata;
7384 if (extended_oplock_granted) {
7385 if (flags & REQUEST_BATCH_OPLOCK) {
7386 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7387 } else {
7388 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7390 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7391 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7392 } else {
7393 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7396 SSVAL(pdata,2,fsp->fnum);
7397 SIVAL(pdata,4,info); /* Was file created etc. */
7399 switch (info_level_return) {
7400 case SMB_QUERY_FILE_UNIX_BASIC:
7401 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7402 SSVAL(pdata,10,0); /* padding. */
7403 store_file_unix_basic(conn, pdata + 12, fsp,
7404 &smb_fname->st);
7405 break;
7406 case SMB_QUERY_FILE_UNIX_INFO2:
7407 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7408 SSVAL(pdata,10,0); /* padding. */
7409 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7410 &smb_fname->st);
7411 break;
7412 default:
7413 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7414 SSVAL(pdata,10,0); /* padding. */
7415 break;
7417 return NT_STATUS_OK;
7420 /****************************************************************************
7421 Delete a file with POSIX semantics.
7422 ****************************************************************************/
7424 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7425 struct smb_request *req,
7426 const char *pdata,
7427 int total_data,
7428 struct smb_filename *smb_fname)
7430 NTSTATUS status = NT_STATUS_OK;
7431 files_struct *fsp = NULL;
7432 uint16 flags = 0;
7433 char del = 1;
7434 int info = 0;
7435 int create_options = 0;
7436 int i;
7437 struct share_mode_lock *lck = NULL;
7439 if (total_data < 2) {
7440 return NT_STATUS_INVALID_PARAMETER;
7443 flags = SVAL(pdata,0);
7445 if (!VALID_STAT(smb_fname->st)) {
7446 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7449 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7450 !VALID_STAT_OF_DIR(smb_fname->st)) {
7451 return NT_STATUS_NOT_A_DIRECTORY;
7454 DEBUG(10,("smb_posix_unlink: %s %s\n",
7455 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7456 smb_fname_str_dbg(smb_fname)));
7458 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7459 create_options |= FILE_DIRECTORY_FILE;
7462 status = SMB_VFS_CREATE_FILE(
7463 conn, /* conn */
7464 req, /* req */
7465 0, /* root_dir_fid */
7466 smb_fname, /* fname */
7467 DELETE_ACCESS, /* access_mask */
7468 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7469 FILE_SHARE_DELETE),
7470 FILE_OPEN, /* create_disposition*/
7471 create_options, /* create_options */
7472 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7473 0, /* oplock_request */
7474 0, /* allocation_size */
7475 0, /* private_flags */
7476 NULL, /* sd */
7477 NULL, /* ea_list */
7478 &fsp, /* result */
7479 &info); /* pinfo */
7481 if (!NT_STATUS_IS_OK(status)) {
7482 return status;
7486 * Don't lie to client. If we can't really delete due to
7487 * non-POSIX opens return SHARING_VIOLATION.
7490 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7491 NULL);
7492 if (lck == NULL) {
7493 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7494 "lock for file %s\n", fsp_str_dbg(fsp)));
7495 close_file(req, fsp, NORMAL_CLOSE);
7496 return NT_STATUS_INVALID_PARAMETER;
7500 * See if others still have the file open. If this is the case, then
7501 * don't delete. If all opens are POSIX delete we can set the delete
7502 * on close disposition.
7504 for (i=0; i<lck->num_share_modes; i++) {
7505 struct share_mode_entry *e = &lck->share_modes[i];
7506 if (is_valid_share_mode_entry(e)) {
7507 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7508 continue;
7510 /* Fail with sharing violation. */
7511 close_file(req, fsp, NORMAL_CLOSE);
7512 TALLOC_FREE(lck);
7513 return NT_STATUS_SHARING_VIOLATION;
7518 * Set the delete on close.
7520 status = smb_set_file_disposition_info(conn,
7521 &del,
7523 fsp,
7524 smb_fname);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 close_file(req, fsp, NORMAL_CLOSE);
7528 TALLOC_FREE(lck);
7529 return status;
7531 TALLOC_FREE(lck);
7532 return close_file(req, fsp, NORMAL_CLOSE);
7535 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7536 struct smb_request *req,
7537 TALLOC_CTX *mem_ctx,
7538 uint16_t info_level,
7539 files_struct *fsp,
7540 struct smb_filename *smb_fname,
7541 char **ppdata, int total_data,
7542 int *ret_data_size)
7544 char *pdata = *ppdata;
7545 NTSTATUS status = NT_STATUS_OK;
7546 int data_return_size = 0;
7548 *ret_data_size = 0;
7550 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7551 return NT_STATUS_INVALID_LEVEL;
7554 if (!CAN_WRITE(conn)) {
7555 /* Allow POSIX opens. The open path will deny
7556 * any non-readonly opens. */
7557 if (info_level != SMB_POSIX_PATH_OPEN) {
7558 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7562 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7563 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7564 fsp ? fsp->fnum : -1, info_level, total_data));
7566 switch (info_level) {
7568 case SMB_INFO_STANDARD:
7570 status = smb_set_info_standard(conn,
7571 pdata,
7572 total_data,
7573 fsp,
7574 smb_fname);
7575 break;
7578 case SMB_INFO_SET_EA:
7580 status = smb_info_set_ea(conn,
7581 pdata,
7582 total_data,
7583 fsp,
7584 smb_fname);
7585 break;
7588 case SMB_SET_FILE_BASIC_INFO:
7589 case SMB_FILE_BASIC_INFORMATION:
7591 status = smb_set_file_basic_info(conn,
7592 pdata,
7593 total_data,
7594 fsp,
7595 smb_fname);
7596 break;
7599 case SMB_FILE_ALLOCATION_INFORMATION:
7600 case SMB_SET_FILE_ALLOCATION_INFO:
7602 status = smb_set_file_allocation_info(conn, req,
7603 pdata,
7604 total_data,
7605 fsp,
7606 smb_fname);
7607 break;
7610 case SMB_FILE_END_OF_FILE_INFORMATION:
7611 case SMB_SET_FILE_END_OF_FILE_INFO:
7614 * XP/Win7 both fail after the createfile with
7615 * SMB_SET_FILE_END_OF_FILE_INFO but not
7616 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7617 * The level is known here, so pass it down
7618 * appropriately.
7620 bool should_fail =
7621 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7623 status = smb_set_file_end_of_file_info(conn, req,
7624 pdata,
7625 total_data,
7626 fsp,
7627 smb_fname,
7628 should_fail);
7629 break;
7632 case SMB_FILE_DISPOSITION_INFORMATION:
7633 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7635 #if 0
7636 /* JRA - We used to just ignore this on a path ?
7637 * Shouldn't this be invalid level on a pathname
7638 * based call ?
7640 if (tran_call != TRANSACT2_SETFILEINFO) {
7641 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7643 #endif
7644 status = smb_set_file_disposition_info(conn,
7645 pdata,
7646 total_data,
7647 fsp,
7648 smb_fname);
7649 break;
7652 case SMB_FILE_POSITION_INFORMATION:
7654 status = smb_file_position_information(conn,
7655 pdata,
7656 total_data,
7657 fsp);
7658 break;
7661 case SMB_FILE_FULL_EA_INFORMATION:
7663 status = smb_set_file_full_ea_info(conn,
7664 pdata,
7665 total_data,
7666 fsp);
7667 break;
7670 /* From tridge Samba4 :
7671 * MODE_INFORMATION in setfileinfo (I have no
7672 * idea what "mode information" on a file is - it takes a value of 0,
7673 * 2, 4 or 6. What could it be?).
7676 case SMB_FILE_MODE_INFORMATION:
7678 status = smb_file_mode_information(conn,
7679 pdata,
7680 total_data);
7681 break;
7685 * CIFS UNIX extensions.
7688 case SMB_SET_FILE_UNIX_BASIC:
7690 status = smb_set_file_unix_basic(conn, req,
7691 pdata,
7692 total_data,
7693 fsp,
7694 smb_fname);
7695 break;
7698 case SMB_SET_FILE_UNIX_INFO2:
7700 status = smb_set_file_unix_info2(conn, req,
7701 pdata,
7702 total_data,
7703 fsp,
7704 smb_fname);
7705 break;
7708 case SMB_SET_FILE_UNIX_LINK:
7710 if (fsp) {
7711 /* We must have a pathname for this. */
7712 return NT_STATUS_INVALID_LEVEL;
7714 status = smb_set_file_unix_link(conn, req, pdata,
7715 total_data, smb_fname);
7716 break;
7719 case SMB_SET_FILE_UNIX_HLINK:
7721 if (fsp) {
7722 /* We must have a pathname for this. */
7723 return NT_STATUS_INVALID_LEVEL;
7725 status = smb_set_file_unix_hlink(conn, req,
7726 pdata, total_data,
7727 smb_fname);
7728 break;
7731 case SMB_FILE_RENAME_INFORMATION:
7733 status = smb_file_rename_information(conn, req,
7734 pdata, total_data,
7735 fsp, smb_fname);
7736 break;
7739 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7741 /* SMB2 rename information. */
7742 status = smb2_file_rename_information(conn, req,
7743 pdata, total_data,
7744 fsp, smb_fname);
7745 break;
7748 case SMB_FILE_LINK_INFORMATION:
7750 status = smb_file_link_information(conn, req,
7751 pdata, total_data,
7752 fsp, smb_fname);
7753 break;
7756 #if defined(HAVE_POSIX_ACLS)
7757 case SMB_SET_POSIX_ACL:
7759 status = smb_set_posix_acl(conn,
7760 pdata,
7761 total_data,
7762 fsp,
7763 smb_fname);
7764 break;
7766 #endif
7768 case SMB_SET_POSIX_LOCK:
7770 if (!fsp) {
7771 return NT_STATUS_INVALID_LEVEL;
7773 status = smb_set_posix_lock(conn, req,
7774 pdata, total_data, fsp);
7775 break;
7778 case SMB_POSIX_PATH_OPEN:
7780 if (fsp) {
7781 /* We must have a pathname for this. */
7782 return NT_STATUS_INVALID_LEVEL;
7785 status = smb_posix_open(conn, req,
7786 ppdata,
7787 total_data,
7788 smb_fname,
7789 &data_return_size);
7790 break;
7793 case SMB_POSIX_PATH_UNLINK:
7795 if (fsp) {
7796 /* We must have a pathname for this. */
7797 return NT_STATUS_INVALID_LEVEL;
7800 status = smb_posix_unlink(conn, req,
7801 pdata,
7802 total_data,
7803 smb_fname);
7804 break;
7807 default:
7808 return NT_STATUS_INVALID_LEVEL;
7811 if (!NT_STATUS_IS_OK(status)) {
7812 return status;
7815 *ret_data_size = data_return_size;
7816 return NT_STATUS_OK;
7819 /****************************************************************************
7820 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7821 ****************************************************************************/
7823 static void call_trans2setfilepathinfo(connection_struct *conn,
7824 struct smb_request *req,
7825 unsigned int tran_call,
7826 char **pparams, int total_params,
7827 char **ppdata, int total_data,
7828 unsigned int max_data_bytes)
7830 char *params = *pparams;
7831 char *pdata = *ppdata;
7832 uint16 info_level;
7833 struct smb_filename *smb_fname = NULL;
7834 files_struct *fsp = NULL;
7835 NTSTATUS status = NT_STATUS_OK;
7836 int data_return_size = 0;
7838 if (!params) {
7839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7840 return;
7843 if (tran_call == TRANSACT2_SETFILEINFO) {
7844 if (total_params < 4) {
7845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7846 return;
7849 fsp = file_fsp(req, SVAL(params,0));
7850 /* Basic check for non-null fsp. */
7851 if (!check_fsp_open(conn, req, fsp)) {
7852 return;
7854 info_level = SVAL(params,2);
7856 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7857 &smb_fname);
7858 if (!NT_STATUS_IS_OK(status)) {
7859 reply_nterror(req, status);
7860 return;
7863 if(fsp->fh->fd == -1) {
7865 * This is actually a SETFILEINFO on a directory
7866 * handle (returned from an NT SMB). NT5.0 seems
7867 * to do this call. JRA.
7869 if (INFO_LEVEL_IS_UNIX(info_level)) {
7870 /* Always do lstat for UNIX calls. */
7871 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7872 DEBUG(3,("call_trans2setfilepathinfo: "
7873 "SMB_VFS_LSTAT of %s failed "
7874 "(%s)\n",
7875 smb_fname_str_dbg(smb_fname),
7876 strerror(errno)));
7877 reply_nterror(req, map_nt_error_from_unix(errno));
7878 return;
7880 } else {
7881 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7882 DEBUG(3,("call_trans2setfilepathinfo: "
7883 "fileinfo of %s failed (%s)\n",
7884 smb_fname_str_dbg(smb_fname),
7885 strerror(errno)));
7886 reply_nterror(req, map_nt_error_from_unix(errno));
7887 return;
7890 } else if (fsp->print_file) {
7892 * Doing a DELETE_ON_CLOSE should cancel a print job.
7894 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7895 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7897 DEBUG(3,("call_trans2setfilepathinfo: "
7898 "Cancelling print job (%s)\n",
7899 fsp_str_dbg(fsp)));
7901 SSVAL(params,0,0);
7902 send_trans2_replies(conn, req, params, 2,
7903 *ppdata, 0,
7904 max_data_bytes);
7905 return;
7906 } else {
7907 reply_nterror(req,
7908 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7909 return;
7911 } else {
7913 * Original code - this is an open file.
7915 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7916 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7917 "of fnum %d failed (%s)\n", fsp->fnum,
7918 strerror(errno)));
7919 reply_nterror(req, map_nt_error_from_unix(errno));
7920 return;
7923 } else {
7924 char *fname = NULL;
7926 /* set path info */
7927 if (total_params < 7) {
7928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7929 return;
7932 info_level = SVAL(params,0);
7933 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7934 total_params - 6, STR_TERMINATE,
7935 &status);
7936 if (!NT_STATUS_IS_OK(status)) {
7937 reply_nterror(req, status);
7938 return;
7941 status = filename_convert(req, conn,
7942 req->flags2 & FLAGS2_DFS_PATHNAMES,
7943 fname,
7945 NULL,
7946 &smb_fname);
7947 if (!NT_STATUS_IS_OK(status)) {
7948 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7949 reply_botherror(req,
7950 NT_STATUS_PATH_NOT_COVERED,
7951 ERRSRV, ERRbadpath);
7952 return;
7954 reply_nterror(req, status);
7955 return;
7958 if (INFO_LEVEL_IS_UNIX(info_level)) {
7960 * For CIFS UNIX extensions the target name may not exist.
7963 /* Always do lstat for UNIX calls. */
7964 SMB_VFS_LSTAT(conn, smb_fname);
7966 } else if (!VALID_STAT(smb_fname->st) &&
7967 SMB_VFS_STAT(conn, smb_fname)) {
7968 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7969 "%s failed (%s)\n",
7970 smb_fname_str_dbg(smb_fname),
7971 strerror(errno)));
7972 reply_nterror(req, map_nt_error_from_unix(errno));
7973 return;
7977 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7978 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7979 fsp ? fsp->fnum : -1, info_level,total_data));
7981 /* Realloc the parameter size */
7982 *pparams = (char *)SMB_REALLOC(*pparams,2);
7983 if (*pparams == NULL) {
7984 reply_nterror(req, NT_STATUS_NO_MEMORY);
7985 return;
7987 params = *pparams;
7989 SSVAL(params,0,0);
7991 status = smbd_do_setfilepathinfo(conn, req, req,
7992 info_level,
7993 fsp,
7994 smb_fname,
7995 ppdata, total_data,
7996 &data_return_size);
7997 if (!NT_STATUS_IS_OK(status)) {
7998 if (open_was_deferred(req->mid)) {
7999 /* We have re-scheduled this call. */
8000 return;
8002 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8003 /* We have re-scheduled this call. */
8004 return;
8006 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8007 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8008 ERRSRV, ERRbadpath);
8009 return;
8011 if (info_level == SMB_POSIX_PATH_OPEN) {
8012 reply_openerror(req, status);
8013 return;
8016 reply_nterror(req, status);
8017 return;
8020 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8021 max_data_bytes);
8023 return;
8026 /****************************************************************************
8027 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8028 ****************************************************************************/
8030 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8031 char **pparams, int total_params,
8032 char **ppdata, int total_data,
8033 unsigned int max_data_bytes)
8035 struct smb_filename *smb_dname = NULL;
8036 char *params = *pparams;
8037 char *pdata = *ppdata;
8038 char *directory = NULL;
8039 NTSTATUS status = NT_STATUS_OK;
8040 struct ea_list *ea_list = NULL;
8041 TALLOC_CTX *ctx = talloc_tos();
8043 if (!CAN_WRITE(conn)) {
8044 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8045 return;
8048 if (total_params < 5) {
8049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8050 return;
8053 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8054 total_params - 4, STR_TERMINATE,
8055 &status);
8056 if (!NT_STATUS_IS_OK(status)) {
8057 reply_nterror(req, status);
8058 return;
8061 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8063 status = filename_convert(ctx,
8064 conn,
8065 req->flags2 & FLAGS2_DFS_PATHNAMES,
8066 directory,
8068 NULL,
8069 &smb_dname);
8071 if (!NT_STATUS_IS_OK(status)) {
8072 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8073 reply_botherror(req,
8074 NT_STATUS_PATH_NOT_COVERED,
8075 ERRSRV, ERRbadpath);
8076 return;
8078 reply_nterror(req, status);
8079 return;
8083 * OS/2 workplace shell seems to send SET_EA requests of "null"
8084 * length (4 bytes containing IVAL 4).
8085 * They seem to have no effect. Bug #3212. JRA.
8088 if (total_data && (total_data != 4)) {
8089 /* Any data in this call is an EA list. */
8090 if (total_data < 10) {
8091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8092 goto out;
8095 if (IVAL(pdata,0) > total_data) {
8096 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8097 IVAL(pdata,0), (unsigned int)total_data));
8098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8099 goto out;
8102 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8103 total_data - 4);
8104 if (!ea_list) {
8105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8106 goto out;
8109 if (!lp_ea_support(SNUM(conn))) {
8110 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8111 goto out;
8114 /* If total_data == 4 Windows doesn't care what values
8115 * are placed in that field, it just ignores them.
8116 * The System i QNTC IBM SMB client puts bad values here,
8117 * so ignore them. */
8119 status = create_directory(conn, req, smb_dname);
8121 if (!NT_STATUS_IS_OK(status)) {
8122 reply_nterror(req, status);
8123 goto out;
8126 /* Try and set any given EA. */
8127 if (ea_list) {
8128 status = set_ea(conn, NULL, smb_dname, ea_list);
8129 if (!NT_STATUS_IS_OK(status)) {
8130 reply_nterror(req, status);
8131 goto out;
8135 /* Realloc the parameter and data sizes */
8136 *pparams = (char *)SMB_REALLOC(*pparams,2);
8137 if(*pparams == NULL) {
8138 reply_nterror(req, NT_STATUS_NO_MEMORY);
8139 goto out;
8141 params = *pparams;
8143 SSVAL(params,0,0);
8145 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8147 out:
8148 TALLOC_FREE(smb_dname);
8149 return;
8152 /****************************************************************************
8153 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8154 We don't actually do this - we just send a null response.
8155 ****************************************************************************/
8157 static void call_trans2findnotifyfirst(connection_struct *conn,
8158 struct smb_request *req,
8159 char **pparams, int total_params,
8160 char **ppdata, int total_data,
8161 unsigned int max_data_bytes)
8163 char *params = *pparams;
8164 uint16 info_level;
8166 if (total_params < 6) {
8167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8168 return;
8171 info_level = SVAL(params,4);
8172 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8174 switch (info_level) {
8175 case 1:
8176 case 2:
8177 break;
8178 default:
8179 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8180 return;
8183 /* Realloc the parameter and data sizes */
8184 *pparams = (char *)SMB_REALLOC(*pparams,6);
8185 if (*pparams == NULL) {
8186 reply_nterror(req, NT_STATUS_NO_MEMORY);
8187 return;
8189 params = *pparams;
8191 SSVAL(params,0,fnf_handle);
8192 SSVAL(params,2,0); /* No changes */
8193 SSVAL(params,4,0); /* No EA errors */
8195 fnf_handle++;
8197 if(fnf_handle == 0)
8198 fnf_handle = 257;
8200 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8202 return;
8205 /****************************************************************************
8206 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8207 changes). Currently this does nothing.
8208 ****************************************************************************/
8210 static void call_trans2findnotifynext(connection_struct *conn,
8211 struct smb_request *req,
8212 char **pparams, int total_params,
8213 char **ppdata, int total_data,
8214 unsigned int max_data_bytes)
8216 char *params = *pparams;
8218 DEBUG(3,("call_trans2findnotifynext\n"));
8220 /* Realloc the parameter and data sizes */
8221 *pparams = (char *)SMB_REALLOC(*pparams,4);
8222 if (*pparams == NULL) {
8223 reply_nterror(req, NT_STATUS_NO_MEMORY);
8224 return;
8226 params = *pparams;
8228 SSVAL(params,0,0); /* No changes */
8229 SSVAL(params,2,0); /* No EA errors */
8231 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8233 return;
8236 /****************************************************************************
8237 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8238 ****************************************************************************/
8240 static void call_trans2getdfsreferral(connection_struct *conn,
8241 struct smb_request *req,
8242 char **pparams, int total_params,
8243 char **ppdata, int total_data,
8244 unsigned int max_data_bytes)
8246 char *params = *pparams;
8247 char *pathname = NULL;
8248 int reply_size = 0;
8249 int max_referral_level;
8250 NTSTATUS status = NT_STATUS_OK;
8251 TALLOC_CTX *ctx = talloc_tos();
8253 DEBUG(10,("call_trans2getdfsreferral\n"));
8255 if (total_params < 3) {
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 return;
8260 max_referral_level = SVAL(params,0);
8262 if(!lp_host_msdfs()) {
8263 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8264 return;
8267 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8268 total_params - 2, STR_TERMINATE);
8269 if (!pathname) {
8270 reply_nterror(req, NT_STATUS_NOT_FOUND);
8271 return;
8273 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8274 ppdata,&status)) < 0) {
8275 reply_nterror(req, status);
8276 return;
8279 SSVAL(req->inbuf, smb_flg2,
8280 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8281 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8283 return;
8286 #define LMCAT_SPL 0x53
8287 #define LMFUNC_GETJOBID 0x60
8289 /****************************************************************************
8290 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8291 ****************************************************************************/
8293 static void call_trans2ioctl(connection_struct *conn,
8294 struct smb_request *req,
8295 char **pparams, int total_params,
8296 char **ppdata, int total_data,
8297 unsigned int max_data_bytes)
8299 char *pdata = *ppdata;
8300 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8302 /* check for an invalid fid before proceeding */
8304 if (!fsp) {
8305 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8306 return;
8309 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8310 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8311 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8312 if (*ppdata == NULL) {
8313 reply_nterror(req, NT_STATUS_NO_MEMORY);
8314 return;
8316 pdata = *ppdata;
8318 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8319 CAN ACCEPT THIS IN UNICODE. JRA. */
8321 /* Job number */
8322 if (fsp->print_file) {
8323 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8324 } else {
8325 SSVAL(pdata, 0, 0);
8327 srvstr_push(pdata, req->flags2, pdata + 2,
8328 global_myname(), 15,
8329 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8330 srvstr_push(pdata, req->flags2, pdata+18,
8331 lp_servicename(SNUM(conn)), 13,
8332 STR_ASCII|STR_TERMINATE); /* Service name */
8333 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8334 max_data_bytes);
8335 return;
8338 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8339 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8342 /****************************************************************************
8343 Reply to a SMBfindclose (stop trans2 directory search).
8344 ****************************************************************************/
8346 void reply_findclose(struct smb_request *req)
8348 int dptr_num;
8349 struct smbd_server_connection *sconn = req->sconn;
8351 START_PROFILE(SMBfindclose);
8353 if (req->wct < 1) {
8354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8355 END_PROFILE(SMBfindclose);
8356 return;
8359 dptr_num = SVALS(req->vwv+0, 0);
8361 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8363 dptr_close(sconn, &dptr_num);
8365 reply_outbuf(req, 0, 0);
8367 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8369 END_PROFILE(SMBfindclose);
8370 return;
8373 /****************************************************************************
8374 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8375 ****************************************************************************/
8377 void reply_findnclose(struct smb_request *req)
8379 int dptr_num;
8381 START_PROFILE(SMBfindnclose);
8383 if (req->wct < 1) {
8384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8385 END_PROFILE(SMBfindnclose);
8386 return;
8389 dptr_num = SVAL(req->vwv+0, 0);
8391 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8393 /* We never give out valid handles for a
8394 findnotifyfirst - so any dptr_num is ok here.
8395 Just ignore it. */
8397 reply_outbuf(req, 0, 0);
8399 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8401 END_PROFILE(SMBfindnclose);
8402 return;
8405 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8406 struct trans_state *state)
8408 if (get_Protocol() >= PROTOCOL_NT1) {
8409 req->flags2 |= 0x40; /* IS_LONG_NAME */
8410 SSVAL(req->inbuf,smb_flg2,req->flags2);
8413 if (conn->encrypt_level == Required && !req->encrypted) {
8414 if (state->call != TRANSACT2_QFSINFO &&
8415 state->call != TRANSACT2_SETFSINFO) {
8416 DEBUG(0,("handle_trans2: encryption required "
8417 "with call 0x%x\n",
8418 (unsigned int)state->call));
8419 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8420 return;
8424 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8426 /* Now we must call the relevant TRANS2 function */
8427 switch(state->call) {
8428 case TRANSACT2_OPEN:
8430 START_PROFILE(Trans2_open);
8431 call_trans2open(conn, req,
8432 &state->param, state->total_param,
8433 &state->data, state->total_data,
8434 state->max_data_return);
8435 END_PROFILE(Trans2_open);
8436 break;
8439 case TRANSACT2_FINDFIRST:
8441 START_PROFILE(Trans2_findfirst);
8442 call_trans2findfirst(conn, req,
8443 &state->param, state->total_param,
8444 &state->data, state->total_data,
8445 state->max_data_return);
8446 END_PROFILE(Trans2_findfirst);
8447 break;
8450 case TRANSACT2_FINDNEXT:
8452 START_PROFILE(Trans2_findnext);
8453 call_trans2findnext(conn, req,
8454 &state->param, state->total_param,
8455 &state->data, state->total_data,
8456 state->max_data_return);
8457 END_PROFILE(Trans2_findnext);
8458 break;
8461 case TRANSACT2_QFSINFO:
8463 START_PROFILE(Trans2_qfsinfo);
8464 call_trans2qfsinfo(conn, req,
8465 &state->param, state->total_param,
8466 &state->data, state->total_data,
8467 state->max_data_return);
8468 END_PROFILE(Trans2_qfsinfo);
8469 break;
8472 case TRANSACT2_SETFSINFO:
8474 START_PROFILE(Trans2_setfsinfo);
8475 call_trans2setfsinfo(conn, req,
8476 &state->param, state->total_param,
8477 &state->data, state->total_data,
8478 state->max_data_return);
8479 END_PROFILE(Trans2_setfsinfo);
8480 break;
8483 case TRANSACT2_QPATHINFO:
8484 case TRANSACT2_QFILEINFO:
8486 START_PROFILE(Trans2_qpathinfo);
8487 call_trans2qfilepathinfo(conn, req, state->call,
8488 &state->param, state->total_param,
8489 &state->data, state->total_data,
8490 state->max_data_return);
8491 END_PROFILE(Trans2_qpathinfo);
8492 break;
8495 case TRANSACT2_SETPATHINFO:
8496 case TRANSACT2_SETFILEINFO:
8498 START_PROFILE(Trans2_setpathinfo);
8499 call_trans2setfilepathinfo(conn, req, state->call,
8500 &state->param, state->total_param,
8501 &state->data, state->total_data,
8502 state->max_data_return);
8503 END_PROFILE(Trans2_setpathinfo);
8504 break;
8507 case TRANSACT2_FINDNOTIFYFIRST:
8509 START_PROFILE(Trans2_findnotifyfirst);
8510 call_trans2findnotifyfirst(conn, req,
8511 &state->param, state->total_param,
8512 &state->data, state->total_data,
8513 state->max_data_return);
8514 END_PROFILE(Trans2_findnotifyfirst);
8515 break;
8518 case TRANSACT2_FINDNOTIFYNEXT:
8520 START_PROFILE(Trans2_findnotifynext);
8521 call_trans2findnotifynext(conn, req,
8522 &state->param, state->total_param,
8523 &state->data, state->total_data,
8524 state->max_data_return);
8525 END_PROFILE(Trans2_findnotifynext);
8526 break;
8529 case TRANSACT2_MKDIR:
8531 START_PROFILE(Trans2_mkdir);
8532 call_trans2mkdir(conn, req,
8533 &state->param, state->total_param,
8534 &state->data, state->total_data,
8535 state->max_data_return);
8536 END_PROFILE(Trans2_mkdir);
8537 break;
8540 case TRANSACT2_GET_DFS_REFERRAL:
8542 START_PROFILE(Trans2_get_dfs_referral);
8543 call_trans2getdfsreferral(conn, req,
8544 &state->param, state->total_param,
8545 &state->data, state->total_data,
8546 state->max_data_return);
8547 END_PROFILE(Trans2_get_dfs_referral);
8548 break;
8551 case TRANSACT2_IOCTL:
8553 START_PROFILE(Trans2_ioctl);
8554 call_trans2ioctl(conn, req,
8555 &state->param, state->total_param,
8556 &state->data, state->total_data,
8557 state->max_data_return);
8558 END_PROFILE(Trans2_ioctl);
8559 break;
8562 default:
8563 /* Error in request */
8564 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8565 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8569 /****************************************************************************
8570 Reply to a SMBtrans2.
8571 ****************************************************************************/
8573 void reply_trans2(struct smb_request *req)
8575 connection_struct *conn = req->conn;
8576 unsigned int dsoff;
8577 unsigned int dscnt;
8578 unsigned int psoff;
8579 unsigned int pscnt;
8580 unsigned int tran_call;
8581 struct trans_state *state;
8582 NTSTATUS result;
8584 START_PROFILE(SMBtrans2);
8586 if (req->wct < 14) {
8587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8588 END_PROFILE(SMBtrans2);
8589 return;
8592 dsoff = SVAL(req->vwv+12, 0);
8593 dscnt = SVAL(req->vwv+11, 0);
8594 psoff = SVAL(req->vwv+10, 0);
8595 pscnt = SVAL(req->vwv+9, 0);
8596 tran_call = SVAL(req->vwv+14, 0);
8598 result = allow_new_trans(conn->pending_trans, req->mid);
8599 if (!NT_STATUS_IS_OK(result)) {
8600 DEBUG(2, ("Got invalid trans2 request: %s\n",
8601 nt_errstr(result)));
8602 reply_nterror(req, result);
8603 END_PROFILE(SMBtrans2);
8604 return;
8607 if (IS_IPC(conn)) {
8608 switch (tran_call) {
8609 /* List the allowed trans2 calls on IPC$ */
8610 case TRANSACT2_OPEN:
8611 case TRANSACT2_GET_DFS_REFERRAL:
8612 case TRANSACT2_QFILEINFO:
8613 case TRANSACT2_QFSINFO:
8614 case TRANSACT2_SETFSINFO:
8615 break;
8616 default:
8617 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8618 END_PROFILE(SMBtrans2);
8619 return;
8623 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8624 DEBUG(0, ("talloc failed\n"));
8625 reply_nterror(req, NT_STATUS_NO_MEMORY);
8626 END_PROFILE(SMBtrans2);
8627 return;
8630 state->cmd = SMBtrans2;
8632 state->mid = req->mid;
8633 state->vuid = req->vuid;
8634 state->setup_count = SVAL(req->vwv+13, 0);
8635 state->setup = NULL;
8636 state->total_param = SVAL(req->vwv+0, 0);
8637 state->param = NULL;
8638 state->total_data = SVAL(req->vwv+1, 0);
8639 state->data = NULL;
8640 state->max_param_return = SVAL(req->vwv+2, 0);
8641 state->max_data_return = SVAL(req->vwv+3, 0);
8642 state->max_setup_return = SVAL(req->vwv+4, 0);
8643 state->close_on_completion = BITSETW(req->vwv+5, 0);
8644 state->one_way = BITSETW(req->vwv+5, 1);
8646 state->call = tran_call;
8648 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8649 is so as a sanity check */
8650 if (state->setup_count != 1) {
8652 * Need to have rc=0 for ioctl to get job id for OS/2.
8653 * Network printing will fail if function is not successful.
8654 * Similar function in reply.c will be used if protocol
8655 * is LANMAN1.0 instead of LM1.2X002.
8656 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8657 * outbuf doesn't have to be set(only job id is used).
8659 if ( (state->setup_count == 4)
8660 && (tran_call == TRANSACT2_IOCTL)
8661 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8662 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8663 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8664 } else {
8665 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8666 DEBUG(2,("Transaction is %d\n",tran_call));
8667 TALLOC_FREE(state);
8668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8669 END_PROFILE(SMBtrans2);
8670 return;
8674 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8675 goto bad_param;
8677 if (state->total_data) {
8679 if (trans_oob(state->total_data, 0, dscnt)
8680 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8681 goto bad_param;
8684 /* Can't use talloc here, the core routines do realloc on the
8685 * params and data. */
8686 state->data = (char *)SMB_MALLOC(state->total_data);
8687 if (state->data == NULL) {
8688 DEBUG(0,("reply_trans2: data malloc fail for %u "
8689 "bytes !\n", (unsigned int)state->total_data));
8690 TALLOC_FREE(state);
8691 reply_nterror(req, NT_STATUS_NO_MEMORY);
8692 END_PROFILE(SMBtrans2);
8693 return;
8696 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8699 if (state->total_param) {
8701 if (trans_oob(state->total_param, 0, pscnt)
8702 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8703 goto bad_param;
8706 /* Can't use talloc here, the core routines do realloc on the
8707 * params and data. */
8708 state->param = (char *)SMB_MALLOC(state->total_param);
8709 if (state->param == NULL) {
8710 DEBUG(0,("reply_trans: param malloc fail for %u "
8711 "bytes !\n", (unsigned int)state->total_param));
8712 SAFE_FREE(state->data);
8713 TALLOC_FREE(state);
8714 reply_nterror(req, NT_STATUS_NO_MEMORY);
8715 END_PROFILE(SMBtrans2);
8716 return;
8719 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8722 state->received_data = dscnt;
8723 state->received_param = pscnt;
8725 if ((state->received_param == state->total_param) &&
8726 (state->received_data == state->total_data)) {
8728 handle_trans2(conn, req, state);
8730 SAFE_FREE(state->data);
8731 SAFE_FREE(state->param);
8732 TALLOC_FREE(state);
8733 END_PROFILE(SMBtrans2);
8734 return;
8737 DLIST_ADD(conn->pending_trans, state);
8739 /* We need to send an interim response then receive the rest
8740 of the parameter/data bytes */
8741 reply_outbuf(req, 0, 0);
8742 show_msg((char *)req->outbuf);
8743 END_PROFILE(SMBtrans2);
8744 return;
8746 bad_param:
8748 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8749 SAFE_FREE(state->data);
8750 SAFE_FREE(state->param);
8751 TALLOC_FREE(state);
8752 END_PROFILE(SMBtrans2);
8753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8757 /****************************************************************************
8758 Reply to a SMBtranss2
8759 ****************************************************************************/
8761 void reply_transs2(struct smb_request *req)
8763 connection_struct *conn = req->conn;
8764 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8765 struct trans_state *state;
8767 START_PROFILE(SMBtranss2);
8769 show_msg((char *)req->inbuf);
8771 if (req->wct < 8) {
8772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8773 END_PROFILE(SMBtranss2);
8774 return;
8777 for (state = conn->pending_trans; state != NULL;
8778 state = state->next) {
8779 if (state->mid == req->mid) {
8780 break;
8784 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8786 END_PROFILE(SMBtranss2);
8787 return;
8790 /* Revise state->total_param and state->total_data in case they have
8791 changed downwards */
8793 if (SVAL(req->vwv+0, 0) < state->total_param)
8794 state->total_param = SVAL(req->vwv+0, 0);
8795 if (SVAL(req->vwv+1, 0) < state->total_data)
8796 state->total_data = SVAL(req->vwv+1, 0);
8798 pcnt = SVAL(req->vwv+2, 0);
8799 poff = SVAL(req->vwv+3, 0);
8800 pdisp = SVAL(req->vwv+4, 0);
8802 dcnt = SVAL(req->vwv+5, 0);
8803 doff = SVAL(req->vwv+6, 0);
8804 ddisp = SVAL(req->vwv+7, 0);
8806 state->received_param += pcnt;
8807 state->received_data += dcnt;
8809 if ((state->received_data > state->total_data) ||
8810 (state->received_param > state->total_param))
8811 goto bad_param;
8813 if (pcnt) {
8814 if (trans_oob(state->total_param, pdisp, pcnt)
8815 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8816 goto bad_param;
8818 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8821 if (dcnt) {
8822 if (trans_oob(state->total_data, ddisp, dcnt)
8823 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8824 goto bad_param;
8826 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8829 if ((state->received_param < state->total_param) ||
8830 (state->received_data < state->total_data)) {
8831 END_PROFILE(SMBtranss2);
8832 return;
8835 handle_trans2(conn, req, state);
8837 DLIST_REMOVE(conn->pending_trans, state);
8838 SAFE_FREE(state->data);
8839 SAFE_FREE(state->param);
8840 TALLOC_FREE(state);
8842 END_PROFILE(SMBtranss2);
8843 return;
8845 bad_param:
8847 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8848 DLIST_REMOVE(conn->pending_trans, state);
8849 SAFE_FREE(state->data);
8850 SAFE_FREE(state->param);
8851 TALLOC_FREE(state);
8852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8853 END_PROFILE(SMBtranss2);
8854 return;