Change estimate_ea_size() to correctly estimate the EA size over SMB2.
[Samba.git] / source3 / smbd / trans2.c
blob304664932261c7bf55e6515bfdca5e74248925cf
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
39 #include "libsmb/libsmb.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 Roundup a value to the nearest allocation roundup size boundary.
55 Only do this for Windows clients.
56 ********************************************************************/
58 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
60 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
62 /* Only roundup for Windows clients. */
63 enum remote_arch_types ra_type = get_remote_arch();
64 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
65 val = SMB_ROUNDUP(val,rval);
67 return val;
70 /********************************************************************
71 Create a 64 bit FileIndex. If the file is on the same device as
72 the root of the share, just return the 64-bit inode. If it isn't,
73 mangle as we used to do.
74 ********************************************************************/
76 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 uint64_t file_index;
79 if (conn->base_share_dev == psbuf->st_ex_dev) {
80 return (uint64_t)psbuf->st_ex_ino;
82 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
83 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
84 return file_index;
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char * const prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 SAMBA_XATTR_MARKER,
101 XATTR_NTACL_NAME,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return true;
111 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
112 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
113 return true;
115 return false;
118 /****************************************************************************
119 Get one EA value. Fill in a struct ea_struct.
120 ****************************************************************************/
122 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
123 files_struct *fsp, const char *fname,
124 const char *ea_name, struct ea_struct *pea)
126 /* Get the value of this xattr. Max size is 64k. */
127 size_t attr_size = 256;
128 char *val = NULL;
129 ssize_t sizeret;
131 again:
133 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (!val) {
135 return NT_STATUS_NO_MEMORY;
138 if (fsp && fsp->fh->fd != -1) {
139 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 } else {
141 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
144 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
145 attr_size = 65536;
146 goto again;
149 if (sizeret == -1) {
150 return map_nt_error_from_unix(errno);
153 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
154 dump_data(10, (uint8 *)val, sizeret);
156 pea->flags = 0;
157 if (strnequal(ea_name, "user.", 5)) {
158 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 } else {
160 pea->name = talloc_strdup(mem_ctx, ea_name);
162 if (pea->name == NULL) {
163 TALLOC_FREE(val);
164 return NT_STATUS_NO_MEMORY;
166 pea->value.data = (unsigned char *)val;
167 pea->value.length = (size_t)sizeret;
168 return NT_STATUS_OK;
171 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
172 files_struct *fsp, const char *fname,
173 char ***pnames, size_t *pnum_names)
175 /* Get a list of all xattrs. Max namesize is 64k. */
176 size_t ea_namelist_size = 1024;
177 char *ea_namelist = NULL;
179 char *p;
180 char **names, **tmp;
181 size_t num_names;
182 ssize_t sizeret = -1;
184 if (!lp_ea_support(SNUM(conn))) {
185 if (pnames) {
186 *pnames = NULL;
188 *pnum_names = 0;
189 return NT_STATUS_OK;
193 * TALLOC the result early to get the talloc hierarchy right.
196 names = TALLOC_ARRAY(mem_ctx, char *, 1);
197 if (names == NULL) {
198 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY;
202 while (ea_namelist_size <= 65536) {
204 ea_namelist = TALLOC_REALLOC_ARRAY(
205 names, ea_namelist, char, ea_namelist_size);
206 if (ea_namelist == NULL) {
207 DEBUG(0, ("talloc failed\n"));
208 TALLOC_FREE(names);
209 return NT_STATUS_NO_MEMORY;
212 if (fsp && fsp->fh->fd != -1) {
213 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
214 ea_namelist_size);
215 } else {
216 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 ea_namelist_size);
220 if ((sizeret == -1) && (errno == ERANGE)) {
221 ea_namelist_size *= 2;
223 else {
224 break;
228 if (sizeret == -1) {
229 TALLOC_FREE(names);
230 return map_nt_error_from_unix(errno);
233 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
234 (unsigned int)sizeret));
236 if (sizeret == 0) {
237 TALLOC_FREE(names);
238 if (pnames) {
239 *pnames = NULL;
241 *pnum_names = 0;
242 return NT_STATUS_OK;
246 * Ensure the result is 0-terminated
249 if (ea_namelist[sizeret-1] != '\0') {
250 TALLOC_FREE(names);
251 return NT_STATUS_INTERNAL_ERROR;
255 * count the names
257 num_names = 0;
259 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
260 num_names += 1;
263 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
264 if (tmp == NULL) {
265 DEBUG(0, ("talloc failed\n"));
266 TALLOC_FREE(names);
267 return NT_STATUS_NO_MEMORY;
270 names = tmp;
271 num_names = 0;
273 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
274 names[num_names++] = p;
277 if (pnames) {
278 *pnames = names;
279 } else {
280 TALLOC_FREE(names);
282 *pnum_names = num_names;
283 return NT_STATUS_OK;
286 /****************************************************************************
287 Return a linked list of the total EA's. Plus the total size
288 ****************************************************************************/
290 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
291 const char *fname, size_t *pea_total_len)
293 /* Get a list of all xattrs. Max namesize is 64k. */
294 size_t i, num_names;
295 char **names;
296 struct ea_list *ea_list_head = NULL;
297 NTSTATUS status;
299 *pea_total_len = 0;
301 if (!lp_ea_support(SNUM(conn))) {
302 return NULL;
305 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
306 &names, &num_names);
308 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
309 return NULL;
312 for (i=0; i<num_names; i++) {
313 struct ea_list *listp;
314 fstring dos_ea_name;
316 if (strnequal(names[i], "system.", 7)
317 || samba_private_attr_name(names[i]))
318 continue;
320 listp = TALLOC_P(mem_ctx, struct ea_list);
321 if (listp == NULL) {
322 return NULL;
325 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
326 fname, names[i],
327 &listp->ea))) {
328 return NULL;
331 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 *pea_total_len +=
334 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
336 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
337 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
338 (unsigned int)listp->ea.value.length));
340 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
344 /* Add on 4 for total length. */
345 if (*pea_total_len) {
346 *pea_total_len += 4;
349 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
350 (unsigned int)*pea_total_len));
352 return ea_list_head;
355 /****************************************************************************
356 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 that was filled.
358 ****************************************************************************/
360 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
361 connection_struct *conn, struct ea_list *ea_list)
363 unsigned int ret_data_size = 4;
364 char *p = pdata;
366 SMB_ASSERT(total_data_size >= 4);
368 if (!lp_ea_support(SNUM(conn))) {
369 SIVAL(pdata,4,0);
370 return 4;
373 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
374 size_t dos_namelen;
375 fstring dos_ea_name;
376 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
377 dos_namelen = strlen(dos_ea_name);
378 if (dos_namelen > 255 || dos_namelen == 0) {
379 break;
381 if (ea_list->ea.value.length > 65535) {
382 break;
384 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
385 break;
388 /* We know we have room. */
389 SCVAL(p,0,ea_list->ea.flags);
390 SCVAL(p,1,dos_namelen);
391 SSVAL(p,2,ea_list->ea.value.length);
392 fstrcpy(p+4, dos_ea_name);
393 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
395 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
396 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
399 ret_data_size = PTR_DIFF(p, pdata);
400 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
401 SIVAL(pdata,0,ret_data_size);
402 return ret_data_size;
405 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 char *pdata,
407 unsigned int total_data_size,
408 unsigned int *ret_data_size,
409 connection_struct *conn,
410 struct ea_list *ea_list)
412 uint8_t *p = (uint8_t *)pdata;
413 uint8_t *last_start = NULL;
414 bool store_data = (pdata != NULL);
416 *ret_data_size = 0;
418 if (!lp_ea_support(SNUM(conn))) {
419 return NT_STATUS_NO_EAS_ON_FILE;
422 for (; ea_list; ea_list = ea_list->next) {
423 size_t dos_namelen;
424 fstring dos_ea_name;
425 size_t this_size;
427 if (last_start && store_data) {
428 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
430 last_start = p;
432 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
433 dos_namelen = strlen(dos_ea_name);
434 if (dos_namelen > 255 || dos_namelen == 0) {
435 return NT_STATUS_INTERNAL_ERROR;
437 if (ea_list->ea.value.length > 65535) {
438 return NT_STATUS_INTERNAL_ERROR;
441 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
443 if (ea_list->next) {
444 size_t pad = 4 - (this_size % 4);
445 this_size += pad;
448 if (this_size > total_data_size) {
449 return NT_STATUS_INFO_LENGTH_MISMATCH;
452 /* We know we have room. */
453 if (store_data) {
454 SIVAL(p, 0x00, 0); /* next offset */
455 SCVAL(p, 0x04, ea_list->ea.flags);
456 SCVAL(p, 0x05, dos_namelen);
457 SSVAL(p, 0x06, ea_list->ea.value.length);
458 fstrcpy((char *)(p+0x08), dos_ea_name);
459 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
462 total_data_size -= this_size;
463 p += this_size;
466 *ret_data_size = PTR_DIFF(p, pdata);
467 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
468 return NT_STATUS_OK;
471 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
473 size_t total_ea_len = 0;
474 struct ea_list *ea_list = NULL;
475 TALLOC_CTX *mem_ctx = NULL;
477 if (!lp_ea_support(SNUM(conn))) {
478 return 0;
480 mem_ctx = talloc_tos();
481 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
482 if (ea_list == NULL) {
483 return 0;
485 if(conn->sconn->using_smb2) {
486 NTSTATUS status;
487 unsigned int ret_data_size;
489 * We're going to be using fill_ea_chained_buffer() to
490 * marshall EA's - this size is significantly larger
491 * than the SMB1 buffer. Re-calculate the size without
492 * marshalling.
494 status = fill_ea_chained_buffer(mem_ctx,
495 NULL,
496 65535,
497 &ret_data_size,
498 conn,
499 ea_list);
500 if (!NT_STATUS_IS_OK(status)) {
501 ret_data_size = 0;
503 total_ea_len = ret_data_size;
506 return total_ea_len;
509 /****************************************************************************
510 Ensure the EA name is case insensitive by matching any existing EA name.
511 ****************************************************************************/
513 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
515 size_t total_ea_len;
516 TALLOC_CTX *mem_ctx = talloc_tos();
517 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
519 for (; ea_list; ea_list = ea_list->next) {
520 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
521 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
522 &unix_ea_name[5], ea_list->ea.name));
523 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
524 break;
529 /****************************************************************************
530 Set or delete an extended attribute.
531 ****************************************************************************/
533 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
534 const struct smb_filename *smb_fname, struct ea_list *ea_list)
536 char *fname = NULL;
538 if (!lp_ea_support(SNUM(conn))) {
539 return NT_STATUS_EAS_NOT_SUPPORTED;
542 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
543 return NT_STATUS_ACCESS_DENIED;
546 /* For now setting EAs on streams isn't supported. */
547 fname = smb_fname->base_name;
549 for (;ea_list; ea_list = ea_list->next) {
550 int ret;
551 fstring unix_ea_name;
553 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
554 fstrcat(unix_ea_name, ea_list->ea.name);
556 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
558 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
560 if (samba_private_attr_name(unix_ea_name)) {
561 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
562 return NT_STATUS_ACCESS_DENIED;
565 if (ea_list->ea.value.length == 0) {
566 /* Remove the attribute. */
567 if (fsp && (fsp->fh->fd != -1)) {
568 DEBUG(10,("set_ea: deleting ea name %s on "
569 "file %s by file descriptor.\n",
570 unix_ea_name, fsp_str_dbg(fsp)));
571 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
572 } else {
573 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
574 unix_ea_name, fname));
575 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
577 #ifdef ENOATTR
578 /* Removing a non existent attribute always succeeds. */
579 if (ret == -1 && errno == ENOATTR) {
580 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
581 unix_ea_name));
582 ret = 0;
584 #endif
585 } else {
586 if (fsp && (fsp->fh->fd != -1)) {
587 DEBUG(10,("set_ea: setting ea name %s on file "
588 "%s by file descriptor.\n",
589 unix_ea_name, fsp_str_dbg(fsp)));
590 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
591 ea_list->ea.value.data, ea_list->ea.value.length, 0);
592 } else {
593 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
594 unix_ea_name, fname));
595 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
596 ea_list->ea.value.data, ea_list->ea.value.length, 0);
600 if (ret == -1) {
601 #ifdef ENOTSUP
602 if (errno == ENOTSUP) {
603 return NT_STATUS_EAS_NOT_SUPPORTED;
605 #endif
606 return map_nt_error_from_unix(errno);
610 return NT_STATUS_OK;
612 /****************************************************************************
613 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
614 ****************************************************************************/
616 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
618 struct ea_list *ea_list_head = NULL;
619 size_t converted_size, offset = 0;
621 while (offset + 2 < data_size) {
622 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
623 unsigned int namelen = CVAL(pdata,offset);
625 offset++; /* Go past the namelen byte. */
627 /* integer wrap paranioa. */
628 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
629 (offset > data_size) || (namelen > data_size) ||
630 (offset + namelen >= data_size)) {
631 break;
633 /* Ensure the name is null terminated. */
634 if (pdata[offset + namelen] != '\0') {
635 return NULL;
637 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
638 &converted_size)) {
639 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
640 "failed: %s", strerror(errno)));
642 if (!eal->ea.name) {
643 return NULL;
646 offset += (namelen + 1); /* Go past the name + terminating zero. */
647 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
648 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
651 return ea_list_head;
654 /****************************************************************************
655 Read one EA list entry from the buffer.
656 ****************************************************************************/
658 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
660 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
661 uint16 val_len;
662 unsigned int namelen;
663 size_t converted_size;
665 if (!eal) {
666 return NULL;
669 if (data_size < 6) {
670 return NULL;
673 eal->ea.flags = CVAL(pdata,0);
674 namelen = CVAL(pdata,1);
675 val_len = SVAL(pdata,2);
677 if (4 + namelen + 1 + val_len > data_size) {
678 return NULL;
681 /* Ensure the name is null terminated. */
682 if (pdata[namelen + 4] != '\0') {
683 return NULL;
685 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
686 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
687 strerror(errno)));
689 if (!eal->ea.name) {
690 return NULL;
693 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
694 if (!eal->ea.value.data) {
695 return NULL;
698 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
700 /* Ensure we're null terminated just in case we print the value. */
701 eal->ea.value.data[val_len] = '\0';
702 /* But don't count the null. */
703 eal->ea.value.length--;
705 if (pbytes_used) {
706 *pbytes_used = 4 + namelen + 1 + val_len;
709 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
710 dump_data(10, eal->ea.value.data, eal->ea.value.length);
712 return eal;
715 /****************************************************************************
716 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
717 ****************************************************************************/
719 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
721 struct ea_list *ea_list_head = NULL;
722 size_t offset = 0;
723 size_t bytes_used = 0;
725 while (offset < data_size) {
726 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
728 if (!eal) {
729 return NULL;
732 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
733 offset += bytes_used;
736 return ea_list_head;
739 /****************************************************************************
740 Count the total EA size needed.
741 ****************************************************************************/
743 static size_t ea_list_size(struct ea_list *ealist)
745 fstring dos_ea_name;
746 struct ea_list *listp;
747 size_t ret = 0;
749 for (listp = ealist; listp; listp = listp->next) {
750 push_ascii_fstring(dos_ea_name, listp->ea.name);
751 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
753 /* Add on 4 for total length. */
754 if (ret) {
755 ret += 4;
758 return ret;
761 /****************************************************************************
762 Return a union of EA's from a file list and a list of names.
763 The TALLOC context for the two lists *MUST* be identical as we steal
764 memory from one list to add to another. JRA.
765 ****************************************************************************/
767 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
769 struct ea_list *nlistp, *flistp;
771 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
772 for (flistp = file_list; flistp; flistp = flistp->next) {
773 if (strequal(nlistp->ea.name, flistp->ea.name)) {
774 break;
778 if (flistp) {
779 /* Copy the data from this entry. */
780 nlistp->ea.flags = flistp->ea.flags;
781 nlistp->ea.value = flistp->ea.value;
782 } else {
783 /* Null entry. */
784 nlistp->ea.flags = 0;
785 ZERO_STRUCT(nlistp->ea.value);
789 *total_ea_len = ea_list_size(name_list);
790 return name_list;
793 /****************************************************************************
794 Send the required number of replies back.
795 We assume all fields other than the data fields are
796 set correctly for the type of call.
797 HACK ! Always assumes smb_setup field is zero.
798 ****************************************************************************/
800 void send_trans2_replies(connection_struct *conn,
801 struct smb_request *req,
802 const char *params,
803 int paramsize,
804 const char *pdata,
805 int datasize,
806 int max_data_bytes)
808 /* As we are using a protocol > LANMAN1 then the max_send
809 variable must have been set in the sessetupX call.
810 This takes precedence over the max_xmit field in the
811 global struct. These different max_xmit variables should
812 be merged as this is now too confusing */
814 int data_to_send = datasize;
815 int params_to_send = paramsize;
816 int useable_space;
817 const char *pp = params;
818 const char *pd = pdata;
819 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
820 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
821 int data_alignment_offset = 0;
822 bool overflow = False;
823 struct smbd_server_connection *sconn = req->sconn;
824 int max_send = sconn->smb1.sessions.max_send;
826 /* Modify the data_to_send and datasize and set the error if
827 we're trying to send more than max_data_bytes. We still send
828 the part of the packet(s) that fit. Strange, but needed
829 for OS/2. */
831 if (max_data_bytes > 0 && datasize > max_data_bytes) {
832 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
833 max_data_bytes, datasize ));
834 datasize = data_to_send = max_data_bytes;
835 overflow = True;
838 /* If there genuinely are no parameters or data to send just send the empty packet */
840 if(params_to_send == 0 && data_to_send == 0) {
841 reply_outbuf(req, 10, 0);
842 show_msg((char *)req->outbuf);
843 if (!srv_send_smb(sconn,
844 (char *)req->outbuf,
845 true, req->seqnum+1,
846 IS_CONN_ENCRYPTED(conn),
847 &req->pcd)) {
848 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
850 TALLOC_FREE(req->outbuf);
851 return;
854 /* When sending params and data ensure that both are nicely aligned */
855 /* Only do this alignment when there is also data to send - else
856 can cause NT redirector problems. */
858 if (((params_to_send % 4) != 0) && (data_to_send != 0))
859 data_alignment_offset = 4 - (params_to_send % 4);
861 /* Space is bufsize minus Netbios over TCP header minus SMB header */
862 /* The alignment_offset is to align the param bytes on an even byte
863 boundary. NT 4.0 Beta needs this to work correctly. */
865 useable_space = max_send - (smb_size
866 + 2 * 10 /* wct */
867 + alignment_offset
868 + data_alignment_offset);
870 if (useable_space < 0) {
871 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
872 "= %d!!!", useable_space));
873 exit_server_cleanly("send_trans2_replies: Not enough space");
876 while (params_to_send || data_to_send) {
877 /* Calculate whether we will totally or partially fill this packet */
879 total_sent_thistime = params_to_send + data_to_send;
881 /* We can never send more than useable_space */
883 * Note that 'useable_space' does not include the alignment offsets,
884 * but we must include the alignment offsets in the calculation of
885 * the length of the data we send over the wire, as the alignment offsets
886 * are sent here. Fix from Marc_Jacobsen@hp.com.
889 total_sent_thistime = MIN(total_sent_thistime, useable_space);
891 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
892 + data_alignment_offset);
894 /* Set total params and data to be sent */
895 SSVAL(req->outbuf,smb_tprcnt,paramsize);
896 SSVAL(req->outbuf,smb_tdrcnt,datasize);
898 /* Calculate how many parameters and data we can fit into
899 * this packet. Parameters get precedence
902 params_sent_thistime = MIN(params_to_send,useable_space);
903 data_sent_thistime = useable_space - params_sent_thistime;
904 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
906 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
908 /* smb_proff is the offset from the start of the SMB header to the
909 parameter bytes, however the first 4 bytes of outbuf are
910 the Netbios over TCP header. Thus use smb_base() to subtract
911 them from the calculation */
913 SSVAL(req->outbuf,smb_proff,
914 ((smb_buf(req->outbuf)+alignment_offset)
915 - smb_base(req->outbuf)));
917 if(params_sent_thistime == 0)
918 SSVAL(req->outbuf,smb_prdisp,0);
919 else
920 /* Absolute displacement of param bytes sent in this packet */
921 SSVAL(req->outbuf,smb_prdisp,pp - params);
923 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
924 if(data_sent_thistime == 0) {
925 SSVAL(req->outbuf,smb_droff,0);
926 SSVAL(req->outbuf,smb_drdisp, 0);
927 } else {
928 /* The offset of the data bytes is the offset of the
929 parameter bytes plus the number of parameters being sent this time */
930 SSVAL(req->outbuf, smb_droff,
931 ((smb_buf(req->outbuf)+alignment_offset)
932 - smb_base(req->outbuf))
933 + params_sent_thistime + data_alignment_offset);
934 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
937 /* Initialize the padding for alignment */
939 if (alignment_offset != 0) {
940 memset(smb_buf(req->outbuf), 0, alignment_offset);
943 /* Copy the param bytes into the packet */
945 if(params_sent_thistime) {
946 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
947 params_sent_thistime);
950 /* Copy in the data bytes */
951 if(data_sent_thistime) {
952 if (data_alignment_offset != 0) {
953 memset((smb_buf(req->outbuf)+alignment_offset+
954 params_sent_thistime), 0,
955 data_alignment_offset);
957 memcpy(smb_buf(req->outbuf)+alignment_offset
958 +params_sent_thistime+data_alignment_offset,
959 pd,data_sent_thistime);
962 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
963 params_sent_thistime, data_sent_thistime, useable_space));
964 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
965 params_to_send, data_to_send, paramsize, datasize));
967 if (overflow) {
968 error_packet_set((char *)req->outbuf,
969 ERRDOS,ERRbufferoverflow,
970 STATUS_BUFFER_OVERFLOW,
971 __LINE__,__FILE__);
974 /* Send the packet */
975 show_msg((char *)req->outbuf);
976 if (!srv_send_smb(sconn,
977 (char *)req->outbuf,
978 true, req->seqnum+1,
979 IS_CONN_ENCRYPTED(conn),
980 &req->pcd))
981 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
983 TALLOC_FREE(req->outbuf);
985 pp += params_sent_thistime;
986 pd += data_sent_thistime;
988 params_to_send -= params_sent_thistime;
989 data_to_send -= data_sent_thistime;
991 /* Sanity check */
992 if(params_to_send < 0 || data_to_send < 0) {
993 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
994 params_to_send, data_to_send));
995 return;
999 return;
1002 /****************************************************************************
1003 Reply to a TRANSACT2_OPEN.
1004 ****************************************************************************/
1006 static void call_trans2open(connection_struct *conn,
1007 struct smb_request *req,
1008 char **pparams, int total_params,
1009 char **ppdata, int total_data,
1010 unsigned int max_data_bytes)
1012 struct smb_filename *smb_fname = NULL;
1013 char *params = *pparams;
1014 char *pdata = *ppdata;
1015 int deny_mode;
1016 int32 open_attr;
1017 bool oplock_request;
1018 #if 0
1019 bool return_additional_info;
1020 int16 open_sattr;
1021 time_t open_time;
1022 #endif
1023 int open_ofun;
1024 uint32 open_size;
1025 char *pname;
1026 char *fname = NULL;
1027 SMB_OFF_T size=0;
1028 int fattr=0,mtime=0;
1029 SMB_INO_T inode = 0;
1030 int smb_action = 0;
1031 files_struct *fsp;
1032 struct ea_list *ea_list = NULL;
1033 uint16 flags = 0;
1034 NTSTATUS status;
1035 uint32 access_mask;
1036 uint32 share_mode;
1037 uint32 create_disposition;
1038 uint32 create_options = 0;
1039 uint32_t private_flags = 0;
1040 TALLOC_CTX *ctx = talloc_tos();
1043 * Ensure we have enough parameters to perform the operation.
1046 if (total_params < 29) {
1047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1048 goto out;
1051 flags = SVAL(params, 0);
1052 deny_mode = SVAL(params, 2);
1053 open_attr = SVAL(params,6);
1054 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1055 if (oplock_request) {
1056 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1059 #if 0
1060 return_additional_info = BITSETW(params,0);
1061 open_sattr = SVAL(params, 4);
1062 open_time = make_unix_date3(params+8);
1063 #endif
1064 open_ofun = SVAL(params,12);
1065 open_size = IVAL(params,14);
1066 pname = &params[28];
1068 if (IS_IPC(conn)) {
1069 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1070 goto out;
1073 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1074 total_params - 28, STR_TERMINATE,
1075 &status);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 reply_nterror(req, status);
1078 goto out;
1081 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1082 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1083 (unsigned int)open_ofun, open_size));
1085 status = filename_convert(ctx,
1086 conn,
1087 req->flags2 & FLAGS2_DFS_PATHNAMES,
1088 fname,
1090 NULL,
1091 &smb_fname);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1094 reply_botherror(req,
1095 NT_STATUS_PATH_NOT_COVERED,
1096 ERRSRV, ERRbadpath);
1097 goto out;
1099 reply_nterror(req, status);
1100 goto out;
1103 if (open_ofun == 0) {
1104 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1105 goto out;
1108 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1109 open_ofun,
1110 &access_mask, &share_mode,
1111 &create_disposition,
1112 &create_options,
1113 &private_flags)) {
1114 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1115 goto out;
1118 /* Any data in this call is an EA list. */
1119 if (total_data && (total_data != 4)) {
1120 if (total_data < 10) {
1121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1122 goto out;
1125 if (IVAL(pdata,0) > total_data) {
1126 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1127 IVAL(pdata,0), (unsigned int)total_data));
1128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1129 goto out;
1132 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1133 total_data - 4);
1134 if (!ea_list) {
1135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1136 goto out;
1139 if (!lp_ea_support(SNUM(conn))) {
1140 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1141 goto out;
1145 status = SMB_VFS_CREATE_FILE(
1146 conn, /* conn */
1147 req, /* req */
1148 0, /* root_dir_fid */
1149 smb_fname, /* fname */
1150 access_mask, /* access_mask */
1151 share_mode, /* share_access */
1152 create_disposition, /* create_disposition*/
1153 create_options, /* create_options */
1154 open_attr, /* file_attributes */
1155 oplock_request, /* oplock_request */
1156 open_size, /* allocation_size */
1157 private_flags,
1158 NULL, /* sd */
1159 ea_list, /* ea_list */
1160 &fsp, /* result */
1161 &smb_action); /* psbuf */
1163 if (!NT_STATUS_IS_OK(status)) {
1164 if (open_was_deferred(req->mid)) {
1165 /* We have re-scheduled this call. */
1166 goto out;
1168 reply_openerror(req, status);
1169 goto out;
1172 size = get_file_size_stat(&smb_fname->st);
1173 fattr = dos_mode(conn, smb_fname);
1174 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1175 inode = smb_fname->st.st_ex_ino;
1176 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1177 close_file(req, fsp, ERROR_CLOSE);
1178 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1179 goto out;
1182 /* Realloc the size of parameters and data we will return */
1183 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1184 if(*pparams == NULL ) {
1185 reply_nterror(req, NT_STATUS_NO_MEMORY);
1186 goto out;
1188 params = *pparams;
1190 SSVAL(params,0,fsp->fnum);
1191 SSVAL(params,2,fattr);
1192 srv_put_dos_date2(params,4, mtime);
1193 SIVAL(params,8, (uint32)size);
1194 SSVAL(params,12,deny_mode);
1195 SSVAL(params,14,0); /* open_type - file or directory. */
1196 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1198 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1199 smb_action |= EXTENDED_OPLOCK_GRANTED;
1202 SSVAL(params,18,smb_action);
1205 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1207 SIVAL(params,20,inode);
1208 SSVAL(params,24,0); /* Padding. */
1209 if (flags & 8) {
1210 uint32 ea_size = estimate_ea_size(conn, fsp,
1211 fsp->fsp_name->base_name);
1212 SIVAL(params, 26, ea_size);
1213 } else {
1214 SIVAL(params, 26, 0);
1217 /* Send the required number of replies */
1218 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1219 out:
1220 TALLOC_FREE(smb_fname);
1223 /*********************************************************
1224 Routine to check if a given string matches exactly.
1225 as a special case a mask of "." does NOT match. That
1226 is required for correct wildcard semantics
1227 Case can be significant or not.
1228 **********************************************************/
1230 static bool exact_match(bool has_wild,
1231 bool case_sensitive,
1232 const char *str,
1233 const char *mask)
1235 if (mask[0] == '.' && mask[1] == 0) {
1236 return false;
1239 if (has_wild) {
1240 return false;
1243 if (case_sensitive) {
1244 return strcmp(str,mask)==0;
1245 } else {
1246 return StrCaseCmp(str,mask) == 0;
1250 /****************************************************************************
1251 Return the filetype for UNIX extensions.
1252 ****************************************************************************/
1254 static uint32 unix_filetype(mode_t mode)
1256 if(S_ISREG(mode))
1257 return UNIX_TYPE_FILE;
1258 else if(S_ISDIR(mode))
1259 return UNIX_TYPE_DIR;
1260 #ifdef S_ISLNK
1261 else if(S_ISLNK(mode))
1262 return UNIX_TYPE_SYMLINK;
1263 #endif
1264 #ifdef S_ISCHR
1265 else if(S_ISCHR(mode))
1266 return UNIX_TYPE_CHARDEV;
1267 #endif
1268 #ifdef S_ISBLK
1269 else if(S_ISBLK(mode))
1270 return UNIX_TYPE_BLKDEV;
1271 #endif
1272 #ifdef S_ISFIFO
1273 else if(S_ISFIFO(mode))
1274 return UNIX_TYPE_FIFO;
1275 #endif
1276 #ifdef S_ISSOCK
1277 else if(S_ISSOCK(mode))
1278 return UNIX_TYPE_SOCKET;
1279 #endif
1281 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1282 return UNIX_TYPE_UNKNOWN;
1285 /****************************************************************************
1286 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1287 ****************************************************************************/
1289 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1291 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1292 const SMB_STRUCT_STAT *psbuf,
1293 uint32 perms,
1294 enum perm_type ptype,
1295 mode_t *ret_perms)
1297 mode_t ret = 0;
1299 if (perms == SMB_MODE_NO_CHANGE) {
1300 if (!VALID_STAT(*psbuf)) {
1301 return NT_STATUS_INVALID_PARAMETER;
1302 } else {
1303 *ret_perms = psbuf->st_ex_mode;
1304 return NT_STATUS_OK;
1308 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1309 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1310 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1311 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1312 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1313 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1314 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1315 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1316 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1317 #ifdef S_ISVTX
1318 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1319 #endif
1320 #ifdef S_ISGID
1321 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1322 #endif
1323 #ifdef S_ISUID
1324 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1325 #endif
1327 switch (ptype) {
1328 case PERM_NEW_FILE:
1329 /* Apply mode mask */
1330 ret &= lp_create_mask(SNUM(conn));
1331 /* Add in force bits */
1332 ret |= lp_force_create_mode(SNUM(conn));
1333 break;
1334 case PERM_NEW_DIR:
1335 ret &= lp_dir_mask(SNUM(conn));
1336 /* Add in force bits */
1337 ret |= lp_force_dir_mode(SNUM(conn));
1338 break;
1339 case PERM_EXISTING_FILE:
1340 /* Apply mode mask */
1341 ret &= lp_security_mask(SNUM(conn));
1342 /* Add in force bits */
1343 ret |= lp_force_security_mode(SNUM(conn));
1344 break;
1345 case PERM_EXISTING_DIR:
1346 /* Apply mode mask */
1347 ret &= lp_dir_security_mask(SNUM(conn));
1348 /* Add in force bits */
1349 ret |= lp_force_dir_security_mode(SNUM(conn));
1350 break;
1353 *ret_perms = ret;
1354 return NT_STATUS_OK;
1357 /****************************************************************************
1358 Needed to show the msdfs symlinks as directories. Modifies psbuf
1359 to be a directory if it's a msdfs link.
1360 ****************************************************************************/
1362 static bool check_msdfs_link(connection_struct *conn,
1363 const char *pathname,
1364 SMB_STRUCT_STAT *psbuf)
1366 int saved_errno = errno;
1367 if(lp_host_msdfs() &&
1368 lp_msdfs_root(SNUM(conn)) &&
1369 is_msdfs_link(conn, pathname, psbuf)) {
1371 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1372 "as a directory\n",
1373 pathname));
1374 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1375 errno = saved_errno;
1376 return true;
1378 errno = saved_errno;
1379 return false;
1383 /****************************************************************************
1384 Get a level dependent lanman2 dir entry.
1385 ****************************************************************************/
1387 struct smbd_dirptr_lanman2_state {
1388 connection_struct *conn;
1389 uint32_t info_level;
1390 bool check_mangled_names;
1391 bool has_wild;
1392 bool got_exact_match;
1395 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1396 void *private_data,
1397 const char *dname,
1398 const char *mask,
1399 char **_fname)
1401 struct smbd_dirptr_lanman2_state *state =
1402 (struct smbd_dirptr_lanman2_state *)private_data;
1403 bool ok;
1404 char mangled_name[13]; /* mangled 8.3 name. */
1405 bool got_match;
1406 const char *fname;
1408 /* Mangle fname if it's an illegal name. */
1409 if (mangle_must_mangle(dname, state->conn->params)) {
1410 ok = name_to_8_3(dname, mangled_name,
1411 true, state->conn->params);
1412 if (!ok) {
1413 return false;
1415 fname = mangled_name;
1416 } else {
1417 fname = dname;
1420 got_match = exact_match(state->has_wild,
1421 state->conn->case_sensitive,
1422 fname, mask);
1423 state->got_exact_match = got_match;
1424 if (!got_match) {
1425 got_match = mask_match(fname, mask,
1426 state->conn->case_sensitive);
1429 if(!got_match && state->check_mangled_names &&
1430 !mangle_is_8_3(fname, false, state->conn->params)) {
1432 * It turns out that NT matches wildcards against
1433 * both long *and* short names. This may explain some
1434 * of the wildcard wierdness from old DOS clients
1435 * that some people have been seeing.... JRA.
1437 /* Force the mangling into 8.3. */
1438 ok = name_to_8_3(fname, mangled_name,
1439 false, state->conn->params);
1440 if (!ok) {
1441 return false;
1444 got_match = exact_match(state->has_wild,
1445 state->conn->case_sensitive,
1446 mangled_name, mask);
1447 state->got_exact_match = got_match;
1448 if (!got_match) {
1449 got_match = mask_match(mangled_name, mask,
1450 state->conn->case_sensitive);
1454 if (!got_match) {
1455 return false;
1458 *_fname = talloc_strdup(ctx, fname);
1459 if (*_fname == NULL) {
1460 return false;
1463 return true;
1466 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1467 void *private_data,
1468 struct smb_filename *smb_fname,
1469 uint32_t *_mode)
1471 struct smbd_dirptr_lanman2_state *state =
1472 (struct smbd_dirptr_lanman2_state *)private_data;
1473 bool ms_dfs_link = false;
1474 uint32_t mode = 0;
1476 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1477 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1478 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1479 "Couldn't lstat [%s] (%s)\n",
1480 smb_fname_str_dbg(smb_fname),
1481 strerror(errno)));
1482 return false;
1484 } else if (!VALID_STAT(smb_fname->st) &&
1485 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1486 /* Needed to show the msdfs symlinks as
1487 * directories */
1489 ms_dfs_link = check_msdfs_link(state->conn,
1490 smb_fname->base_name,
1491 &smb_fname->st);
1492 if (!ms_dfs_link) {
1493 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1494 "Couldn't stat [%s] (%s)\n",
1495 smb_fname_str_dbg(smb_fname),
1496 strerror(errno)));
1497 return false;
1501 if (ms_dfs_link) {
1502 mode = dos_mode_msdfs(state->conn, smb_fname);
1503 } else {
1504 mode = dos_mode(state->conn, smb_fname);
1507 *_mode = mode;
1508 return true;
1511 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1512 connection_struct *conn,
1513 uint16_t flags2,
1514 uint32_t info_level,
1515 struct ea_list *name_list,
1516 bool check_mangled_names,
1517 bool requires_resume_key,
1518 uint32_t mode,
1519 const char *fname,
1520 const struct smb_filename *smb_fname,
1521 int space_remaining,
1522 uint8_t align,
1523 bool do_pad,
1524 char *base_data,
1525 char **ppdata,
1526 char *end_data,
1527 bool *out_of_space,
1528 uint64_t *last_entry_off)
1530 char *p, *q, *pdata = *ppdata;
1531 uint32_t reskey=0;
1532 uint64_t file_size = 0;
1533 uint64_t allocation_size = 0;
1534 uint64_t file_index = 0;
1535 uint32_t len;
1536 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1537 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1538 time_t c_date = (time_t)0;
1539 char *nameptr;
1540 char *last_entry_ptr;
1541 bool was_8_3;
1542 int off;
1543 int pad = 0;
1545 *out_of_space = false;
1547 ZERO_STRUCT(mdate_ts);
1548 ZERO_STRUCT(adate_ts);
1549 ZERO_STRUCT(create_date_ts);
1550 ZERO_STRUCT(cdate_ts);
1552 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1553 file_size = get_file_size_stat(&smb_fname->st);
1555 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1557 file_index = get_FileIndex(conn, &smb_fname->st);
1559 mdate_ts = smb_fname->st.st_ex_mtime;
1560 adate_ts = smb_fname->st.st_ex_atime;
1561 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1562 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1564 if (lp_dos_filetime_resolution(SNUM(conn))) {
1565 dos_filetime_timespec(&create_date_ts);
1566 dos_filetime_timespec(&mdate_ts);
1567 dos_filetime_timespec(&adate_ts);
1568 dos_filetime_timespec(&cdate_ts);
1571 create_date = convert_timespec_to_time_t(create_date_ts);
1572 mdate = convert_timespec_to_time_t(mdate_ts);
1573 adate = convert_timespec_to_time_t(adate_ts);
1574 c_date = convert_timespec_to_time_t(cdate_ts);
1576 /* align the record */
1577 SMB_ASSERT(align >= 1);
1579 off = (int)PTR_DIFF(pdata, base_data);
1580 pad = (off + (align-1)) & ~(align-1);
1581 pad -= off;
1583 if (pad && pad > space_remaining) {
1584 *out_of_space = true;
1585 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1586 "for padding (wanted %u, had %d)\n",
1587 (unsigned int)pad,
1588 space_remaining ));
1589 return false; /* Not finished - just out of space */
1592 off += pad;
1593 /* initialize padding to 0 */
1594 if (pad) {
1595 memset(pdata, 0, pad);
1597 space_remaining -= pad;
1599 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1600 space_remaining ));
1602 pdata += pad;
1603 p = pdata;
1604 last_entry_ptr = p;
1606 pad = 0;
1607 off = 0;
1609 switch (info_level) {
1610 case SMB_FIND_INFO_STANDARD:
1611 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1612 if(requires_resume_key) {
1613 SIVAL(p,0,reskey);
1614 p += 4;
1616 srv_put_dos_date2(p,0,create_date);
1617 srv_put_dos_date2(p,4,adate);
1618 srv_put_dos_date2(p,8,mdate);
1619 SIVAL(p,12,(uint32)file_size);
1620 SIVAL(p,16,(uint32)allocation_size);
1621 SSVAL(p,20,mode);
1622 p += 23;
1623 nameptr = p;
1624 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1625 p += ucs2_align(base_data, p, 0);
1627 len = srvstr_push(base_data, flags2, p,
1628 fname, PTR_DIFF(end_data, p),
1629 STR_TERMINATE);
1630 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1631 if (len > 2) {
1632 SCVAL(nameptr, -1, len - 2);
1633 } else {
1634 SCVAL(nameptr, -1, 0);
1636 } else {
1637 if (len > 1) {
1638 SCVAL(nameptr, -1, len - 1);
1639 } else {
1640 SCVAL(nameptr, -1, 0);
1643 p += len;
1644 break;
1646 case SMB_FIND_EA_SIZE:
1647 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1648 if (requires_resume_key) {
1649 SIVAL(p,0,reskey);
1650 p += 4;
1652 srv_put_dos_date2(p,0,create_date);
1653 srv_put_dos_date2(p,4,adate);
1654 srv_put_dos_date2(p,8,mdate);
1655 SIVAL(p,12,(uint32)file_size);
1656 SIVAL(p,16,(uint32)allocation_size);
1657 SSVAL(p,20,mode);
1659 unsigned int ea_size = estimate_ea_size(conn, NULL,
1660 smb_fname->base_name);
1661 SIVAL(p,22,ea_size); /* Extended attributes */
1663 p += 27;
1664 nameptr = p - 1;
1665 len = srvstr_push(base_data, flags2,
1666 p, fname, PTR_DIFF(end_data, p),
1667 STR_TERMINATE | STR_NOALIGN);
1668 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1669 if (len > 2) {
1670 len -= 2;
1671 } else {
1672 len = 0;
1674 } else {
1675 if (len > 1) {
1676 len -= 1;
1677 } else {
1678 len = 0;
1681 SCVAL(nameptr,0,len);
1682 p += len;
1683 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1684 break;
1686 case SMB_FIND_EA_LIST:
1688 struct ea_list *file_list = NULL;
1689 size_t ea_len = 0;
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1692 if (!name_list) {
1693 return false;
1695 if (requires_resume_key) {
1696 SIVAL(p,0,reskey);
1697 p += 4;
1699 srv_put_dos_date2(p,0,create_date);
1700 srv_put_dos_date2(p,4,adate);
1701 srv_put_dos_date2(p,8,mdate);
1702 SIVAL(p,12,(uint32)file_size);
1703 SIVAL(p,16,(uint32)allocation_size);
1704 SSVAL(p,20,mode);
1705 p += 22; /* p now points to the EA area. */
1707 file_list = get_ea_list_from_file(ctx, conn, NULL,
1708 smb_fname->base_name,
1709 &ea_len);
1710 name_list = ea_list_union(name_list, file_list, &ea_len);
1712 /* We need to determine if this entry will fit in the space available. */
1713 /* Max string size is 255 bytes. */
1714 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1715 *out_of_space = true;
1716 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1717 "(wanted %u, had %d)\n",
1718 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1719 space_remaining ));
1720 return False; /* Not finished - just out of space */
1723 /* Push the ea_data followed by the name. */
1724 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1725 nameptr = p;
1726 len = srvstr_push(base_data, flags2,
1727 p + 1, fname, PTR_DIFF(end_data, p+1),
1728 STR_TERMINATE | STR_NOALIGN);
1729 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1730 if (len > 2) {
1731 len -= 2;
1732 } else {
1733 len = 0;
1735 } else {
1736 if (len > 1) {
1737 len -= 1;
1738 } else {
1739 len = 0;
1742 SCVAL(nameptr,0,len);
1743 p += len + 1;
1744 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1745 break;
1748 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1749 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1750 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1751 p += 4;
1752 SIVAL(p,0,reskey); p += 4;
1753 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1754 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1755 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1757 SOFF_T(p,0,file_size); p += 8;
1758 SOFF_T(p,0,allocation_size); p += 8;
1759 SIVAL(p,0,mode); p += 4;
1760 q = p; p += 4; /* q is placeholder for name length. */
1762 unsigned int ea_size = estimate_ea_size(conn, NULL,
1763 smb_fname->base_name);
1764 SIVAL(p,0,ea_size); /* Extended attributes */
1765 p += 4;
1767 /* Clear the short name buffer. This is
1768 * IMPORTANT as not doing so will trigger
1769 * a Win2k client bug. JRA.
1771 if (!was_8_3 && check_mangled_names) {
1772 char mangled_name[13]; /* mangled 8.3 name. */
1773 if (!name_to_8_3(fname,mangled_name,True,
1774 conn->params)) {
1775 /* Error - mangle failed ! */
1776 memset(mangled_name,'\0',12);
1778 mangled_name[12] = 0;
1779 len = srvstr_push(base_data, flags2,
1780 p+2, mangled_name, 24,
1781 STR_UPPER|STR_UNICODE);
1782 if (len < 24) {
1783 memset(p + 2 + len,'\0',24 - len);
1785 SSVAL(p, 0, len);
1786 } else {
1787 memset(p,'\0',26);
1789 p += 2 + 24;
1790 len = srvstr_push(base_data, flags2, p,
1791 fname, PTR_DIFF(end_data, p),
1792 STR_TERMINATE_ASCII);
1793 SIVAL(q,0,len);
1794 p += len;
1796 len = PTR_DIFF(p, pdata);
1797 pad = (len + (align-1)) & ~(align-1);
1799 * offset to the next entry, the caller
1800 * will overwrite it for the last entry
1801 * that's why we always include the padding
1803 SIVAL(pdata,0,pad);
1805 * set padding to zero
1807 if (do_pad) {
1808 memset(p, 0, pad - len);
1809 p = pdata + pad;
1810 } else {
1811 p = pdata + len;
1813 break;
1815 case SMB_FIND_FILE_DIRECTORY_INFO:
1816 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1817 p += 4;
1818 SIVAL(p,0,reskey); p += 4;
1819 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1820 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1821 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1823 SOFF_T(p,0,file_size); p += 8;
1824 SOFF_T(p,0,allocation_size); p += 8;
1825 SIVAL(p,0,mode); p += 4;
1826 len = srvstr_push(base_data, flags2,
1827 p + 4, fname, PTR_DIFF(end_data, p+4),
1828 STR_TERMINATE_ASCII);
1829 SIVAL(p,0,len);
1830 p += 4 + len;
1832 len = PTR_DIFF(p, pdata);
1833 pad = (len + (align-1)) & ~(align-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1839 SIVAL(pdata,0,pad);
1841 * set padding to zero
1843 if (do_pad) {
1844 memset(p, 0, pad - len);
1845 p = pdata + pad;
1846 } else {
1847 p = pdata + len;
1849 break;
1851 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1852 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1853 p += 4;
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,mode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname->base_name);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1867 p +=4;
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1872 SIVAL(q, 0, len);
1873 p += len;
1875 len = PTR_DIFF(p, pdata);
1876 pad = (len + (align-1)) & ~(align-1);
1878 * offset to the next entry, the caller
1879 * will overwrite it for the last entry
1880 * that's why we always include the padding
1882 SIVAL(pdata,0,pad);
1884 * set padding to zero
1886 if (do_pad) {
1887 memset(p, 0, pad - len);
1888 p = pdata + pad;
1889 } else {
1890 p = pdata + len;
1892 break;
1894 case SMB_FIND_FILE_NAMES_INFO:
1895 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1896 p += 4;
1897 SIVAL(p,0,reskey); p += 4;
1898 p += 4;
1899 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1900 acl on a dir (tridge) */
1901 len = srvstr_push(base_data, flags2, p,
1902 fname, PTR_DIFF(end_data, p),
1903 STR_TERMINATE_ASCII);
1904 SIVAL(p, -4, len);
1905 p += len;
1907 len = PTR_DIFF(p, pdata);
1908 pad = (len + (align-1)) & ~(align-1);
1910 * offset to the next entry, the caller
1911 * will overwrite it for the last entry
1912 * that's why we always include the padding
1914 SIVAL(pdata,0,pad);
1916 * set padding to zero
1918 if (do_pad) {
1919 memset(p, 0, pad - len);
1920 p = pdata + pad;
1921 } else {
1922 p = pdata + len;
1924 break;
1926 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1927 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1928 p += 4;
1929 SIVAL(p,0,reskey); p += 4;
1930 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1931 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1932 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1934 SOFF_T(p,0,file_size); p += 8;
1935 SOFF_T(p,0,allocation_size); p += 8;
1936 SIVAL(p,0,mode); p += 4;
1937 q = p; p += 4; /* q is placeholder for name length. */
1939 unsigned int ea_size = estimate_ea_size(conn, NULL,
1940 smb_fname->base_name);
1941 SIVAL(p,0,ea_size); /* Extended attributes */
1942 p +=4;
1944 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1945 SBVAL(p,0,file_index); p += 8;
1946 len = srvstr_push(base_data, flags2, p,
1947 fname, PTR_DIFF(end_data, p),
1948 STR_TERMINATE_ASCII);
1949 SIVAL(q, 0, len);
1950 p += len;
1952 len = PTR_DIFF(p, pdata);
1953 pad = (len + (align-1)) & ~(align-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1959 SIVAL(pdata,0,pad);
1961 * set padding to zero
1963 if (do_pad) {
1964 memset(p, 0, pad - len);
1965 p = pdata + pad;
1966 } else {
1967 p = pdata + len;
1969 break;
1971 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1972 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1973 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1974 p += 4;
1975 SIVAL(p,0,reskey); p += 4;
1976 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1977 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1978 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1980 SOFF_T(p,0,file_size); p += 8;
1981 SOFF_T(p,0,allocation_size); p += 8;
1982 SIVAL(p,0,mode); p += 4;
1983 q = p; p += 4; /* q is placeholder for name length */
1985 unsigned int ea_size = estimate_ea_size(conn, NULL,
1986 smb_fname->base_name);
1987 SIVAL(p,0,ea_size); /* Extended attributes */
1988 p +=4;
1990 /* Clear the short name buffer. This is
1991 * IMPORTANT as not doing so will trigger
1992 * a Win2k client bug. JRA.
1994 if (!was_8_3 && check_mangled_names) {
1995 char mangled_name[13]; /* mangled 8.3 name. */
1996 if (!name_to_8_3(fname,mangled_name,True,
1997 conn->params)) {
1998 /* Error - mangle failed ! */
1999 memset(mangled_name,'\0',12);
2001 mangled_name[12] = 0;
2002 len = srvstr_push(base_data, flags2,
2003 p+2, mangled_name, 24,
2004 STR_UPPER|STR_UNICODE);
2005 SSVAL(p, 0, len);
2006 if (len < 24) {
2007 memset(p + 2 + len,'\0',24 - len);
2009 SSVAL(p, 0, len);
2010 } else {
2011 memset(p,'\0',26);
2013 p += 26;
2014 SSVAL(p,0,0); p += 2; /* Reserved ? */
2015 SBVAL(p,0,file_index); p += 8;
2016 len = srvstr_push(base_data, flags2, p,
2017 fname, PTR_DIFF(end_data, p),
2018 STR_TERMINATE_ASCII);
2019 SIVAL(q,0,len);
2020 p += len;
2022 len = PTR_DIFF(p, pdata);
2023 pad = (len + (align-1)) & ~(align-1);
2025 * offset to the next entry, the caller
2026 * will overwrite it for the last entry
2027 * that's why we always include the padding
2029 SIVAL(pdata,0,pad);
2031 * set padding to zero
2033 if (do_pad) {
2034 memset(p, 0, pad - len);
2035 p = pdata + pad;
2036 } else {
2037 p = pdata + len;
2039 break;
2041 /* CIFS UNIX Extension. */
2043 case SMB_FIND_FILE_UNIX:
2044 case SMB_FIND_FILE_UNIX_INFO2:
2045 p+= 4;
2046 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2048 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2050 if (info_level == SMB_FIND_FILE_UNIX) {
2051 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2052 p = store_file_unix_basic(conn, p,
2053 NULL, &smb_fname->st);
2054 len = srvstr_push(base_data, flags2, p,
2055 fname, PTR_DIFF(end_data, p),
2056 STR_TERMINATE);
2057 } else {
2058 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2059 p = store_file_unix_basic_info2(conn, p,
2060 NULL, &smb_fname->st);
2061 nameptr = p;
2062 p += 4;
2063 len = srvstr_push(base_data, flags2, p, fname,
2064 PTR_DIFF(end_data, p), 0);
2065 SIVAL(nameptr, 0, len);
2068 p += len;
2070 len = PTR_DIFF(p, pdata);
2071 pad = (len + (align-1)) & ~(align-1);
2073 * offset to the next entry, the caller
2074 * will overwrite it for the last entry
2075 * that's why we always include the padding
2077 SIVAL(pdata,0,pad);
2079 * set padding to zero
2081 if (do_pad) {
2082 memset(p, 0, pad - len);
2083 p = pdata + pad;
2084 } else {
2085 p = pdata + len;
2087 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2089 break;
2091 default:
2092 return false;
2095 if (PTR_DIFF(p,pdata) > space_remaining) {
2096 *out_of_space = true;
2097 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2098 "(wanted %u, had %d)\n",
2099 (unsigned int)PTR_DIFF(p,pdata),
2100 space_remaining ));
2101 return false; /* Not finished - just out of space */
2104 /* Setup the last entry pointer, as an offset from base_data */
2105 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2106 /* Advance the data pointer to the next slot */
2107 *ppdata = p;
2109 return true;
2112 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2113 connection_struct *conn,
2114 struct dptr_struct *dirptr,
2115 uint16 flags2,
2116 const char *path_mask,
2117 uint32 dirtype,
2118 int info_level,
2119 int requires_resume_key,
2120 bool dont_descend,
2121 bool ask_sharemode,
2122 uint8_t align,
2123 bool do_pad,
2124 char **ppdata,
2125 char *base_data,
2126 char *end_data,
2127 int space_remaining,
2128 bool *out_of_space,
2129 bool *got_exact_match,
2130 int *_last_entry_off,
2131 struct ea_list *name_list)
2133 const char *p;
2134 const char *mask = NULL;
2135 long prev_dirpos = 0;
2136 uint32_t mode = 0;
2137 char *fname = NULL;
2138 struct smb_filename *smb_fname = NULL;
2139 struct smbd_dirptr_lanman2_state state;
2140 bool ok;
2141 uint64_t last_entry_off = 0;
2143 ZERO_STRUCT(state);
2144 state.conn = conn;
2145 state.info_level = info_level;
2146 state.check_mangled_names = lp_manglednames(conn->params);
2147 state.has_wild = dptr_has_wild(dirptr);
2148 state.got_exact_match = false;
2150 *out_of_space = false;
2151 *got_exact_match = false;
2153 p = strrchr_m(path_mask,'/');
2154 if(p != NULL) {
2155 if(p[1] == '\0') {
2156 mask = "*.*";
2157 } else {
2158 mask = p+1;
2160 } else {
2161 mask = path_mask;
2164 ok = smbd_dirptr_get_entry(ctx,
2165 dirptr,
2166 mask,
2167 dirtype,
2168 dont_descend,
2169 ask_sharemode,
2170 smbd_dirptr_lanman2_match_fn,
2171 smbd_dirptr_lanman2_mode_fn,
2172 &state,
2173 &fname,
2174 &smb_fname,
2175 &mode,
2176 &prev_dirpos);
2177 if (!ok) {
2178 return false;
2181 *got_exact_match = state.got_exact_match;
2183 ok = smbd_marshall_dir_entry(ctx,
2184 conn,
2185 flags2,
2186 info_level,
2187 name_list,
2188 state.check_mangled_names,
2189 requires_resume_key,
2190 mode,
2191 fname,
2192 smb_fname,
2193 space_remaining,
2194 align,
2195 do_pad,
2196 base_data,
2197 ppdata,
2198 end_data,
2199 out_of_space,
2200 &last_entry_off);
2201 TALLOC_FREE(fname);
2202 TALLOC_FREE(smb_fname);
2203 if (*out_of_space) {
2204 dptr_SeekDir(dirptr, prev_dirpos);
2205 return false;
2207 if (!ok) {
2208 return false;
2211 *_last_entry_off = last_entry_off;
2212 return true;
2215 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2216 connection_struct *conn,
2217 struct dptr_struct *dirptr,
2218 uint16 flags2,
2219 const char *path_mask,
2220 uint32 dirtype,
2221 int info_level,
2222 bool requires_resume_key,
2223 bool dont_descend,
2224 bool ask_sharemode,
2225 char **ppdata,
2226 char *base_data,
2227 char *end_data,
2228 int space_remaining,
2229 bool *out_of_space,
2230 bool *got_exact_match,
2231 int *last_entry_off,
2232 struct ea_list *name_list)
2234 uint8_t align = 4;
2235 const bool do_pad = true;
2237 if (info_level >= 1 && info_level <= 3) {
2238 /* No alignment on earlier info levels. */
2239 align = 1;
2242 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2243 path_mask, dirtype, info_level,
2244 requires_resume_key, dont_descend, ask_sharemode,
2245 align, do_pad,
2246 ppdata, base_data, end_data,
2247 space_remaining,
2248 out_of_space, got_exact_match,
2249 last_entry_off, name_list);
2252 /****************************************************************************
2253 Reply to a TRANS2_FINDFIRST.
2254 ****************************************************************************/
2256 static void call_trans2findfirst(connection_struct *conn,
2257 struct smb_request *req,
2258 char **pparams, int total_params,
2259 char **ppdata, int total_data,
2260 unsigned int max_data_bytes)
2262 /* We must be careful here that we don't return more than the
2263 allowed number of data bytes. If this means returning fewer than
2264 maxentries then so be it. We assume that the redirector has
2265 enough room for the fixed number of parameter bytes it has
2266 requested. */
2267 struct smb_filename *smb_dname = NULL;
2268 char *params = *pparams;
2269 char *pdata = *ppdata;
2270 char *data_end;
2271 uint32 dirtype;
2272 int maxentries;
2273 uint16 findfirst_flags;
2274 bool close_after_first;
2275 bool close_if_end;
2276 bool requires_resume_key;
2277 int info_level;
2278 char *directory = NULL;
2279 char *mask = NULL;
2280 char *p;
2281 int last_entry_off=0;
2282 int dptr_num = -1;
2283 int numentries = 0;
2284 int i;
2285 bool finished = False;
2286 bool dont_descend = False;
2287 bool out_of_space = False;
2288 int space_remaining;
2289 bool mask_contains_wcard = False;
2290 struct ea_list *ea_list = NULL;
2291 NTSTATUS ntstatus = NT_STATUS_OK;
2292 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2293 TALLOC_CTX *ctx = talloc_tos();
2294 struct dptr_struct *dirptr = NULL;
2295 struct smbd_server_connection *sconn = req->sconn;
2296 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2298 if (total_params < 13) {
2299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2300 goto out;
2303 dirtype = SVAL(params,0);
2304 maxentries = SVAL(params,2);
2305 findfirst_flags = SVAL(params,4);
2306 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2307 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2308 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2309 info_level = SVAL(params,6);
2311 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2312 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2313 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2314 info_level, max_data_bytes));
2316 if (!maxentries) {
2317 /* W2K3 seems to treat zero as 1. */
2318 maxentries = 1;
2321 switch (info_level) {
2322 case SMB_FIND_INFO_STANDARD:
2323 case SMB_FIND_EA_SIZE:
2324 case SMB_FIND_EA_LIST:
2325 case SMB_FIND_FILE_DIRECTORY_INFO:
2326 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2327 case SMB_FIND_FILE_NAMES_INFO:
2328 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2329 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2330 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2331 break;
2332 case SMB_FIND_FILE_UNIX:
2333 case SMB_FIND_FILE_UNIX_INFO2:
2334 /* Always use filesystem for UNIX mtime query. */
2335 ask_sharemode = false;
2336 if (!lp_unix_extensions()) {
2337 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2338 goto out;
2340 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2341 break;
2342 default:
2343 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2344 goto out;
2347 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2348 params+12, total_params - 12,
2349 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2350 if (!NT_STATUS_IS_OK(ntstatus)) {
2351 reply_nterror(req, ntstatus);
2352 goto out;
2355 ntstatus = filename_convert(ctx, conn,
2356 req->flags2 & FLAGS2_DFS_PATHNAMES,
2357 directory,
2358 ucf_flags,
2359 &mask_contains_wcard,
2360 &smb_dname);
2361 if (!NT_STATUS_IS_OK(ntstatus)) {
2362 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2363 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2364 ERRSRV, ERRbadpath);
2365 goto out;
2367 reply_nterror(req, ntstatus);
2368 goto out;
2371 mask = smb_dname->original_lcomp;
2373 directory = smb_dname->base_name;
2375 p = strrchr_m(directory,'/');
2376 if(p == NULL) {
2377 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2378 if((directory[0] == '.') && (directory[1] == '\0')) {
2379 mask = talloc_strdup(ctx,"*");
2380 if (!mask) {
2381 reply_nterror(req, NT_STATUS_NO_MEMORY);
2382 goto out;
2384 mask_contains_wcard = True;
2386 } else {
2387 *p = 0;
2390 if (p == NULL || p == directory) {
2391 /* Ensure we don't have a directory name of "". */
2392 directory = talloc_strdup(talloc_tos(), ".");
2393 if (!directory) {
2394 reply_nterror(req, NT_STATUS_NO_MEMORY);
2395 goto out;
2399 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2401 if (info_level == SMB_FIND_EA_LIST) {
2402 uint32 ea_size;
2404 if (total_data < 4) {
2405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2406 goto out;
2409 ea_size = IVAL(pdata,0);
2410 if (ea_size != total_data) {
2411 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2412 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2413 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2414 goto out;
2417 if (!lp_ea_support(SNUM(conn))) {
2418 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2419 goto out;
2422 /* Pull out the list of names. */
2423 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2424 if (!ea_list) {
2425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 goto out;
2430 *ppdata = (char *)SMB_REALLOC(
2431 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2432 if(*ppdata == NULL ) {
2433 reply_nterror(req, NT_STATUS_NO_MEMORY);
2434 goto out;
2436 pdata = *ppdata;
2437 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2439 /* Realloc the params space */
2440 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2441 if (*pparams == NULL) {
2442 reply_nterror(req, NT_STATUS_NO_MEMORY);
2443 goto out;
2445 params = *pparams;
2447 /* Save the wildcard match and attribs we are using on this directory -
2448 needed as lanman2 assumes these are being saved between calls */
2450 ntstatus = dptr_create(conn,
2451 NULL, /* fsp */
2452 directory,
2453 False,
2454 True,
2455 req->smbpid,
2456 mask,
2457 mask_contains_wcard,
2458 dirtype,
2459 &dirptr);
2461 if (!NT_STATUS_IS_OK(ntstatus)) {
2462 reply_nterror(req, ntstatus);
2463 goto out;
2466 dptr_num = dptr_dnum(dirptr);
2467 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2469 /* Initialize per TRANS2_FIND_FIRST operation data */
2470 dptr_init_search_op(dirptr);
2472 /* We don't need to check for VOL here as this is returned by
2473 a different TRANS2 call. */
2475 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2476 directory,lp_dontdescend(SNUM(conn))));
2477 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2478 dont_descend = True;
2480 p = pdata;
2481 space_remaining = max_data_bytes;
2482 out_of_space = False;
2484 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2485 bool got_exact_match = False;
2487 /* this is a heuristic to avoid seeking the dirptr except when
2488 absolutely necessary. It allows for a filename of about 40 chars */
2489 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2490 out_of_space = True;
2491 finished = False;
2492 } else {
2493 finished = !get_lanman2_dir_entry(ctx,
2494 conn,
2495 dirptr,
2496 req->flags2,
2497 mask,dirtype,info_level,
2498 requires_resume_key,dont_descend,
2499 ask_sharemode,
2500 &p,pdata,data_end,
2501 space_remaining, &out_of_space,
2502 &got_exact_match,
2503 &last_entry_off, ea_list);
2506 if (finished && out_of_space)
2507 finished = False;
2509 if (!finished && !out_of_space)
2510 numentries++;
2513 * As an optimisation if we know we aren't looking
2514 * for a wildcard name (ie. the name matches the wildcard exactly)
2515 * then we can finish on any (first) match.
2516 * This speeds up large directory searches. JRA.
2519 if(got_exact_match)
2520 finished = True;
2522 /* Ensure space_remaining never goes -ve. */
2523 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2524 space_remaining = 0;
2525 out_of_space = true;
2526 } else {
2527 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2531 /* Check if we can close the dirptr */
2532 if(close_after_first || (finished && close_if_end)) {
2533 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2534 dptr_close(sconn, &dptr_num);
2538 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2539 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2540 * the protocol level is less than NT1. Tested with smbclient. JRA.
2541 * This should fix the OS/2 client bug #2335.
2544 if(numentries == 0) {
2545 dptr_close(sconn, &dptr_num);
2546 if (get_Protocol() < PROTOCOL_NT1) {
2547 reply_force_doserror(req, ERRDOS, ERRnofiles);
2548 goto out;
2549 } else {
2550 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2551 ERRDOS, ERRbadfile);
2552 goto out;
2556 /* At this point pdata points to numentries directory entries. */
2558 /* Set up the return parameter block */
2559 SSVAL(params,0,dptr_num);
2560 SSVAL(params,2,numentries);
2561 SSVAL(params,4,finished);
2562 SSVAL(params,6,0); /* Never an EA error */
2563 SSVAL(params,8,last_entry_off);
2565 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2566 max_data_bytes);
2568 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2569 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2570 if (!directory) {
2571 reply_nterror(req, NT_STATUS_NO_MEMORY);
2575 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2576 smb_fn_name(req->cmd),
2577 mask, directory, dirtype, numentries ) );
2580 * Force a name mangle here to ensure that the
2581 * mask as an 8.3 name is top of the mangled cache.
2582 * The reasons for this are subtle. Don't remove
2583 * this code unless you know what you are doing
2584 * (see PR#13758). JRA.
2587 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2588 char mangled_name[13];
2589 name_to_8_3(mask, mangled_name, True, conn->params);
2591 out:
2592 TALLOC_FREE(smb_dname);
2593 return;
2596 /****************************************************************************
2597 Reply to a TRANS2_FINDNEXT.
2598 ****************************************************************************/
2600 static void call_trans2findnext(connection_struct *conn,
2601 struct smb_request *req,
2602 char **pparams, int total_params,
2603 char **ppdata, int total_data,
2604 unsigned int max_data_bytes)
2606 /* We must be careful here that we don't return more than the
2607 allowed number of data bytes. If this means returning fewer than
2608 maxentries then so be it. We assume that the redirector has
2609 enough room for the fixed number of parameter bytes it has
2610 requested. */
2611 char *params = *pparams;
2612 char *pdata = *ppdata;
2613 char *data_end;
2614 int dptr_num;
2615 int maxentries;
2616 uint16 info_level;
2617 uint32 resume_key;
2618 uint16 findnext_flags;
2619 bool close_after_request;
2620 bool close_if_end;
2621 bool requires_resume_key;
2622 bool continue_bit;
2623 bool mask_contains_wcard = False;
2624 char *resume_name = NULL;
2625 const char *mask = NULL;
2626 const char *directory = NULL;
2627 char *p = NULL;
2628 uint16 dirtype;
2629 int numentries = 0;
2630 int i, last_entry_off=0;
2631 bool finished = False;
2632 bool dont_descend = False;
2633 bool out_of_space = False;
2634 int space_remaining;
2635 struct ea_list *ea_list = NULL;
2636 NTSTATUS ntstatus = NT_STATUS_OK;
2637 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2638 TALLOC_CTX *ctx = talloc_tos();
2639 struct dptr_struct *dirptr;
2640 struct smbd_server_connection *sconn = req->sconn;
2642 if (total_params < 13) {
2643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2644 return;
2647 dptr_num = SVAL(params,0);
2648 maxentries = SVAL(params,2);
2649 info_level = SVAL(params,4);
2650 resume_key = IVAL(params,6);
2651 findnext_flags = SVAL(params,10);
2652 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2653 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2654 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2655 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2657 if (!continue_bit) {
2658 /* We only need resume_name if continue_bit is zero. */
2659 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2660 params+12,
2661 total_params - 12, STR_TERMINATE, &ntstatus,
2662 &mask_contains_wcard);
2663 if (!NT_STATUS_IS_OK(ntstatus)) {
2664 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2665 complain (it thinks we're asking for the directory above the shared
2666 path or an invalid name). Catch this as the resume name is only compared, never used in
2667 a file access. JRA. */
2668 srvstr_pull_talloc(ctx, params, req->flags2,
2669 &resume_name, params+12,
2670 total_params - 12,
2671 STR_TERMINATE);
2673 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2674 reply_nterror(req, ntstatus);
2675 return;
2680 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2681 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2682 resume_key = %d resume name = %s continue=%d level = %d\n",
2683 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2684 requires_resume_key, resume_key,
2685 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2687 if (!maxentries) {
2688 /* W2K3 seems to treat zero as 1. */
2689 maxentries = 1;
2692 switch (info_level) {
2693 case SMB_FIND_INFO_STANDARD:
2694 case SMB_FIND_EA_SIZE:
2695 case SMB_FIND_EA_LIST:
2696 case SMB_FIND_FILE_DIRECTORY_INFO:
2697 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2698 case SMB_FIND_FILE_NAMES_INFO:
2699 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2700 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2701 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2702 break;
2703 case SMB_FIND_FILE_UNIX:
2704 case SMB_FIND_FILE_UNIX_INFO2:
2705 /* Always use filesystem for UNIX mtime query. */
2706 ask_sharemode = false;
2707 if (!lp_unix_extensions()) {
2708 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2709 return;
2711 break;
2712 default:
2713 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2714 return;
2717 if (info_level == SMB_FIND_EA_LIST) {
2718 uint32 ea_size;
2720 if (total_data < 4) {
2721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2722 return;
2725 ea_size = IVAL(pdata,0);
2726 if (ea_size != total_data) {
2727 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2728 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2730 return;
2733 if (!lp_ea_support(SNUM(conn))) {
2734 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2735 return;
2738 /* Pull out the list of names. */
2739 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2740 if (!ea_list) {
2741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2742 return;
2746 *ppdata = (char *)SMB_REALLOC(
2747 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2748 if(*ppdata == NULL) {
2749 reply_nterror(req, NT_STATUS_NO_MEMORY);
2750 return;
2753 pdata = *ppdata;
2754 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2756 /* Realloc the params space */
2757 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2758 if(*pparams == NULL ) {
2759 reply_nterror(req, NT_STATUS_NO_MEMORY);
2760 return;
2763 params = *pparams;
2765 /* Check that the dptr is valid */
2766 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2767 reply_nterror(req, STATUS_NO_MORE_FILES);
2768 return;
2771 directory = dptr_path(sconn, dptr_num);
2773 /* Get the wildcard mask from the dptr */
2774 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2775 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2776 reply_nterror(req, STATUS_NO_MORE_FILES);
2777 return;
2780 mask = p;
2782 /* Get the attr mask from the dptr */
2783 dirtype = dptr_attr(sconn, dptr_num);
2785 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2786 dptr_num, mask, dirtype,
2787 (long)dirptr,
2788 dptr_TellDir(dirptr)));
2790 /* Initialize per TRANS2_FIND_NEXT operation data */
2791 dptr_init_search_op(dirptr);
2793 /* We don't need to check for VOL here as this is returned by
2794 a different TRANS2 call. */
2796 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2797 directory,lp_dontdescend(SNUM(conn))));
2798 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2799 dont_descend = True;
2801 p = pdata;
2802 space_remaining = max_data_bytes;
2803 out_of_space = False;
2806 * Seek to the correct position. We no longer use the resume key but
2807 * depend on the last file name instead.
2810 if(!continue_bit && resume_name && *resume_name) {
2811 SMB_STRUCT_STAT st;
2813 long current_pos = 0;
2815 * Remember, name_to_8_3 is called by
2816 * get_lanman2_dir_entry(), so the resume name
2817 * could be mangled. Ensure we check the unmangled name.
2820 if (mangle_is_mangled(resume_name, conn->params)) {
2821 char *new_resume_name = NULL;
2822 mangle_lookup_name_from_8_3(ctx,
2823 resume_name,
2824 &new_resume_name,
2825 conn->params);
2826 if (new_resume_name) {
2827 resume_name = new_resume_name;
2832 * Fix for NT redirector problem triggered by resume key indexes
2833 * changing between directory scans. We now return a resume key of 0
2834 * and instead look for the filename to continue from (also given
2835 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2836 * findfirst/findnext (as is usual) then the directory pointer
2837 * should already be at the correct place.
2840 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2841 } /* end if resume_name && !continue_bit */
2843 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2844 bool got_exact_match = False;
2846 /* this is a heuristic to avoid seeking the dirptr except when
2847 absolutely necessary. It allows for a filename of about 40 chars */
2848 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2849 out_of_space = True;
2850 finished = False;
2851 } else {
2852 finished = !get_lanman2_dir_entry(ctx,
2853 conn,
2854 dirptr,
2855 req->flags2,
2856 mask,dirtype,info_level,
2857 requires_resume_key,dont_descend,
2858 ask_sharemode,
2859 &p,pdata,data_end,
2860 space_remaining, &out_of_space,
2861 &got_exact_match,
2862 &last_entry_off, ea_list);
2865 if (finished && out_of_space)
2866 finished = False;
2868 if (!finished && !out_of_space)
2869 numentries++;
2872 * As an optimisation if we know we aren't looking
2873 * for a wildcard name (ie. the name matches the wildcard exactly)
2874 * then we can finish on any (first) match.
2875 * This speeds up large directory searches. JRA.
2878 if(got_exact_match)
2879 finished = True;
2881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2884 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2885 smb_fn_name(req->cmd),
2886 mask, directory, dirtype, numentries ) );
2888 /* Check if we can close the dirptr */
2889 if(close_after_request || (finished && close_if_end)) {
2890 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2891 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2894 /* Set up the return parameter block */
2895 SSVAL(params,0,numentries);
2896 SSVAL(params,2,finished);
2897 SSVAL(params,4,0); /* Never an EA error */
2898 SSVAL(params,6,last_entry_off);
2900 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2901 max_data_bytes);
2903 return;
2906 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2908 E_md4hash(lp_servicename(SNUM(conn)),objid);
2909 return objid;
2912 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2914 SMB_ASSERT(extended_info != NULL);
2916 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2917 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2918 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2919 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2920 #ifdef SAMBA_VERSION_REVISION
2921 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2922 #endif
2923 extended_info->samba_subversion = 0;
2924 #ifdef SAMBA_VERSION_RC_RELEASE
2925 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2926 #else
2927 #ifdef SAMBA_VERSION_PRE_RELEASE
2928 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2929 #endif
2930 #endif
2931 #ifdef SAMBA_VERSION_VENDOR_PATCH
2932 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2933 #endif
2934 extended_info->samba_gitcommitdate = 0;
2935 #ifdef SAMBA_VERSION_COMMIT_TIME
2936 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2937 #endif
2939 memset(extended_info->samba_version_string, 0,
2940 sizeof(extended_info->samba_version_string));
2942 snprintf (extended_info->samba_version_string,
2943 sizeof(extended_info->samba_version_string),
2944 "%s", samba_version_string());
2947 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2948 TALLOC_CTX *mem_ctx,
2949 uint16_t info_level,
2950 uint16_t flags2,
2951 unsigned int max_data_bytes,
2952 struct smb_filename *fname,
2953 char **ppdata,
2954 int *ret_data_len)
2956 char *pdata, *end_data;
2957 int data_len = 0, len;
2958 const char *vname = volume_label(SNUM(conn));
2959 int snum = SNUM(conn);
2960 char *fstype = lp_fstype(SNUM(conn));
2961 const char *filename = NULL;
2962 uint32 additional_flags = 0;
2963 struct smb_filename smb_fname;
2964 SMB_STRUCT_STAT st;
2966 if (fname == NULL || fname->base_name == NULL) {
2967 filename = ".";
2968 } else {
2969 filename = fname->base_name;
2972 if (IS_IPC(conn)) {
2973 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2974 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2975 "info level (0x%x) on IPC$.\n",
2976 (unsigned int)info_level));
2977 return NT_STATUS_ACCESS_DENIED;
2981 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2983 ZERO_STRUCT(smb_fname);
2984 smb_fname.base_name = discard_const_p(char, filename);
2986 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
2987 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2988 return map_nt_error_from_unix(errno);
2991 st = smb_fname.st;
2993 *ppdata = (char *)SMB_REALLOC(
2994 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2995 if (*ppdata == NULL) {
2996 return NT_STATUS_NO_MEMORY;
2999 pdata = *ppdata;
3000 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3001 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3003 switch (info_level) {
3004 case SMB_INFO_ALLOCATION:
3006 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3007 data_len = 18;
3008 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3009 return map_nt_error_from_unix(errno);
3012 block_size = lp_block_size(snum);
3013 if (bsize < block_size) {
3014 uint64_t factor = block_size/bsize;
3015 bsize = block_size;
3016 dsize /= factor;
3017 dfree /= factor;
3019 if (bsize > block_size) {
3020 uint64_t factor = bsize/block_size;
3021 bsize = block_size;
3022 dsize *= factor;
3023 dfree *= factor;
3025 bytes_per_sector = 512;
3026 sectors_per_unit = bsize/bytes_per_sector;
3028 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3029 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3030 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3032 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3033 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3034 SIVAL(pdata,l1_cUnit,dsize);
3035 SIVAL(pdata,l1_cUnitAvail,dfree);
3036 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3037 break;
3040 case SMB_INFO_VOLUME:
3041 /* Return volume name */
3043 * Add volume serial number - hash of a combination of
3044 * the called hostname and the service name.
3046 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3048 * Win2k3 and previous mess this up by sending a name length
3049 * one byte short. I believe only older clients (OS/2 Win9x) use
3050 * this call so try fixing this by adding a terminating null to
3051 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3053 len = srvstr_push(
3054 pdata, flags2,
3055 pdata+l2_vol_szVolLabel, vname,
3056 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3057 STR_NOALIGN|STR_TERMINATE);
3058 SCVAL(pdata,l2_vol_cch,len);
3059 data_len = l2_vol_szVolLabel + len;
3060 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3061 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3062 len, vname));
3063 break;
3065 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3066 case SMB_FS_ATTRIBUTE_INFORMATION:
3068 additional_flags = 0;
3069 #if defined(HAVE_SYS_QUOTAS)
3070 additional_flags |= FILE_VOLUME_QUOTAS;
3071 #endif
3073 if(lp_nt_acl_support(SNUM(conn))) {
3074 additional_flags |= FILE_PERSISTENT_ACLS;
3077 /* Capabilities are filled in at connection time through STATVFS call */
3078 additional_flags |= conn->fs_capabilities;
3079 additional_flags |= lp_parm_int(conn->params->service,
3080 "share", "fake_fscaps",
3083 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3084 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3085 additional_flags); /* FS ATTRIBUTES */
3087 SIVAL(pdata,4,255); /* Max filename component length */
3088 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3089 and will think we can't do long filenames */
3090 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3091 PTR_DIFF(end_data, pdata+12),
3092 STR_UNICODE);
3093 SIVAL(pdata,8,len);
3094 data_len = 12 + len;
3095 break;
3097 case SMB_QUERY_FS_LABEL_INFO:
3098 case SMB_FS_LABEL_INFORMATION:
3099 len = srvstr_push(pdata, flags2, pdata+4, vname,
3100 PTR_DIFF(end_data, pdata+4), 0);
3101 data_len = 4 + len;
3102 SIVAL(pdata,0,len);
3103 break;
3105 case SMB_QUERY_FS_VOLUME_INFO:
3106 case SMB_FS_VOLUME_INFORMATION:
3109 * Add volume serial number - hash of a combination of
3110 * the called hostname and the service name.
3112 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3113 (str_checksum(get_local_machine_name())<<16));
3115 /* Max label len is 32 characters. */
3116 len = srvstr_push(pdata, flags2, pdata+18, vname,
3117 PTR_DIFF(end_data, pdata+18),
3118 STR_UNICODE);
3119 SIVAL(pdata,12,len);
3120 data_len = 18+len;
3122 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3123 (int)strlen(vname),vname, lp_servicename(snum)));
3124 break;
3126 case SMB_QUERY_FS_SIZE_INFO:
3127 case SMB_FS_SIZE_INFORMATION:
3129 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3130 data_len = 24;
3131 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3137 bsize = block_size;
3138 dsize /= factor;
3139 dfree /= factor;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3143 bsize = block_size;
3144 dsize *= factor;
3145 dfree *= factor;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SBIG_UINT(pdata,0,dsize);
3153 SBIG_UINT(pdata,8,dfree);
3154 SIVAL(pdata,16,sectors_per_unit);
3155 SIVAL(pdata,20,bytes_per_sector);
3156 break;
3159 case SMB_FS_FULL_SIZE_INFORMATION:
3161 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3162 data_len = 32;
3163 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3164 return map_nt_error_from_unix(errno);
3166 block_size = lp_block_size(snum);
3167 if (bsize < block_size) {
3168 uint64_t factor = block_size/bsize;
3169 bsize = block_size;
3170 dsize /= factor;
3171 dfree /= factor;
3173 if (bsize > block_size) {
3174 uint64_t factor = bsize/block_size;
3175 bsize = block_size;
3176 dsize *= factor;
3177 dfree *= factor;
3179 bytes_per_sector = 512;
3180 sectors_per_unit = bsize/bytes_per_sector;
3181 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3182 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3183 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3184 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3185 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3186 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3187 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3188 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3189 break;
3192 case SMB_QUERY_FS_DEVICE_INFO:
3193 case SMB_FS_DEVICE_INFORMATION:
3195 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3197 if (!CAN_WRITE(conn)) {
3198 characteristics |= FILE_READ_ONLY_DEVICE;
3200 data_len = 8;
3201 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3202 SIVAL(pdata,4,characteristics);
3203 break;
3206 #ifdef HAVE_SYS_QUOTAS
3207 case SMB_FS_QUOTA_INFORMATION:
3209 * what we have to send --metze:
3211 * Unknown1: 24 NULL bytes
3212 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3213 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3214 * Quota Flags: 2 byte :
3215 * Unknown3: 6 NULL bytes
3217 * 48 bytes total
3219 * details for Quota Flags:
3221 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3222 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3223 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3224 * 0x0001 Enable Quotas: enable quota for this fs
3228 /* we need to fake up a fsp here,
3229 * because its not send in this call
3231 files_struct fsp;
3232 SMB_NTQUOTA_STRUCT quotas;
3234 ZERO_STRUCT(fsp);
3235 ZERO_STRUCT(quotas);
3237 fsp.conn = conn;
3238 fsp.fnum = -1;
3240 /* access check */
3241 if (get_current_uid(conn) != 0) {
3242 DEBUG(0,("set_user_quota: access_denied "
3243 "service [%s] user [%s]\n",
3244 lp_servicename(SNUM(conn)),
3245 conn->session_info->unix_name));
3246 return NT_STATUS_ACCESS_DENIED;
3249 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3250 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3251 return map_nt_error_from_unix(errno);
3254 data_len = 48;
3256 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3257 lp_servicename(SNUM(conn))));
3259 /* Unknown1 24 NULL bytes*/
3260 SBIG_UINT(pdata,0,(uint64_t)0);
3261 SBIG_UINT(pdata,8,(uint64_t)0);
3262 SBIG_UINT(pdata,16,(uint64_t)0);
3264 /* Default Soft Quota 8 bytes */
3265 SBIG_UINT(pdata,24,quotas.softlim);
3267 /* Default Hard Quota 8 bytes */
3268 SBIG_UINT(pdata,32,quotas.hardlim);
3270 /* Quota flag 2 bytes */
3271 SSVAL(pdata,40,quotas.qflags);
3273 /* Unknown3 6 NULL bytes */
3274 SSVAL(pdata,42,0);
3275 SIVAL(pdata,44,0);
3277 break;
3279 #endif /* HAVE_SYS_QUOTAS */
3280 case SMB_FS_OBJECTID_INFORMATION:
3282 unsigned char objid[16];
3283 struct smb_extended_info extended_info;
3284 memcpy(pdata,create_volume_objectid(conn, objid),16);
3285 samba_extended_info_version (&extended_info);
3286 SIVAL(pdata,16,extended_info.samba_magic);
3287 SIVAL(pdata,20,extended_info.samba_version);
3288 SIVAL(pdata,24,extended_info.samba_subversion);
3289 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3290 memcpy(pdata+36,extended_info.samba_version_string,28);
3291 data_len = 64;
3292 break;
3296 * Query the version and capabilities of the CIFS UNIX extensions
3297 * in use.
3300 case SMB_QUERY_CIFS_UNIX_INFO:
3302 bool large_write = lp_min_receive_file_size() &&
3303 !srv_is_signing_active(conn->sconn);
3304 bool large_read = !srv_is_signing_active(conn->sconn);
3305 int encrypt_caps = 0;
3307 if (!lp_unix_extensions()) {
3308 return NT_STATUS_INVALID_LEVEL;
3311 switch (conn->encrypt_level) {
3312 case 0:
3313 encrypt_caps = 0;
3314 break;
3315 case 1:
3316 case Auto:
3317 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3318 break;
3319 case Required:
3320 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3321 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3322 large_write = false;
3323 large_read = false;
3324 break;
3327 data_len = 12;
3328 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3329 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3331 /* We have POSIX ACLs, pathname, encryption,
3332 * large read/write, and locking capability. */
3334 SBIG_UINT(pdata,4,((uint64_t)(
3335 CIFS_UNIX_POSIX_ACLS_CAP|
3336 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3337 CIFS_UNIX_FCNTL_LOCKS_CAP|
3338 CIFS_UNIX_EXTATTR_CAP|
3339 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3340 encrypt_caps|
3341 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3342 (large_write ?
3343 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3344 break;
3347 case SMB_QUERY_POSIX_FS_INFO:
3349 int rc;
3350 vfs_statvfs_struct svfs;
3352 if (!lp_unix_extensions()) {
3353 return NT_STATUS_INVALID_LEVEL;
3356 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3358 if (!rc) {
3359 data_len = 56;
3360 SIVAL(pdata,0,svfs.OptimalTransferSize);
3361 SIVAL(pdata,4,svfs.BlockSize);
3362 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3363 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3364 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3365 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3366 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3367 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3368 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3369 #ifdef EOPNOTSUPP
3370 } else if (rc == EOPNOTSUPP) {
3371 return NT_STATUS_INVALID_LEVEL;
3372 #endif /* EOPNOTSUPP */
3373 } else {
3374 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3375 return NT_STATUS_DOS(ERRSRV, ERRerror);
3377 break;
3380 case SMB_QUERY_POSIX_WHOAMI:
3382 uint32_t flags = 0;
3383 uint32_t sid_bytes;
3384 int i;
3386 if (!lp_unix_extensions()) {
3387 return NT_STATUS_INVALID_LEVEL;
3390 if (max_data_bytes < 40) {
3391 return NT_STATUS_BUFFER_TOO_SMALL;
3394 /* We ARE guest if global_sid_Builtin_Guests is
3395 * in our list of SIDs.
3397 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3398 conn->session_info->security_token)) {
3399 flags |= SMB_WHOAMI_GUEST;
3402 /* We are NOT guest if global_sid_Authenticated_Users
3403 * is in our list of SIDs.
3405 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3406 conn->session_info->security_token)) {
3407 flags &= ~SMB_WHOAMI_GUEST;
3410 /* NOTE: 8 bytes for UID/GID, irrespective of native
3411 * platform size. This matches
3412 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3414 data_len = 4 /* flags */
3415 + 4 /* flag mask */
3416 + 8 /* uid */
3417 + 8 /* gid */
3418 + 4 /* ngroups */
3419 + 4 /* num_sids */
3420 + 4 /* SID bytes */
3421 + 4 /* pad/reserved */
3422 + (conn->session_info->utok.ngroups * 8)
3423 /* groups list */
3424 + (conn->session_info->security_token->num_sids *
3425 SID_MAX_SIZE)
3426 /* SID list */;
3428 SIVAL(pdata, 0, flags);
3429 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3430 SBIG_UINT(pdata, 8,
3431 (uint64_t)conn->session_info->utok.uid);
3432 SBIG_UINT(pdata, 16,
3433 (uint64_t)conn->session_info->utok.gid);
3436 if (data_len >= max_data_bytes) {
3437 /* Potential overflow, skip the GIDs and SIDs. */
3439 SIVAL(pdata, 24, 0); /* num_groups */
3440 SIVAL(pdata, 28, 0); /* num_sids */
3441 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3442 SIVAL(pdata, 36, 0); /* reserved */
3444 data_len = 40;
3445 break;
3448 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3449 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3451 /* We walk the SID list twice, but this call is fairly
3452 * infrequent, and I don't expect that it's performance
3453 * sensitive -- jpeach
3455 for (i = 0, sid_bytes = 0;
3456 i < conn->session_info->security_token->num_sids; ++i) {
3457 sid_bytes += ndr_size_dom_sid(
3458 &conn->session_info->security_token->sids[i],
3462 /* SID list byte count */
3463 SIVAL(pdata, 32, sid_bytes);
3465 /* 4 bytes pad/reserved - must be zero */
3466 SIVAL(pdata, 36, 0);
3467 data_len = 40;
3469 /* GID list */
3470 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3471 SBIG_UINT(pdata, data_len,
3472 (uint64_t)conn->session_info->utok.groups[i]);
3473 data_len += 8;
3476 /* SID list */
3477 for (i = 0;
3478 i < conn->session_info->security_token->num_sids; ++i) {
3479 int sid_len = ndr_size_dom_sid(
3480 &conn->session_info->security_token->sids[i],
3483 sid_linearize(pdata + data_len, sid_len,
3484 &conn->session_info->security_token->sids[i]);
3485 data_len += sid_len;
3488 break;
3491 case SMB_MAC_QUERY_FS_INFO:
3493 * Thursby MAC extension... ONLY on NTFS filesystems
3494 * once we do streams then we don't need this
3496 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3497 data_len = 88;
3498 SIVAL(pdata,84,0x100); /* Don't support mac... */
3499 break;
3501 /* drop through */
3502 default:
3503 return NT_STATUS_INVALID_LEVEL;
3506 *ret_data_len = data_len;
3507 return NT_STATUS_OK;
3510 /****************************************************************************
3511 Reply to a TRANS2_QFSINFO (query filesystem info).
3512 ****************************************************************************/
3514 static void call_trans2qfsinfo(connection_struct *conn,
3515 struct smb_request *req,
3516 char **pparams, int total_params,
3517 char **ppdata, int total_data,
3518 unsigned int max_data_bytes)
3520 char *params = *pparams;
3521 uint16_t info_level;
3522 int data_len = 0;
3523 NTSTATUS status;
3525 if (total_params < 2) {
3526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3527 return;
3530 info_level = SVAL(params,0);
3532 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3533 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3534 DEBUG(0,("call_trans2qfsinfo: encryption required "
3535 "and info level 0x%x sent.\n",
3536 (unsigned int)info_level));
3537 exit_server_cleanly("encryption required "
3538 "on connection");
3539 return;
3543 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3545 status = smbd_do_qfsinfo(conn, req,
3546 info_level,
3547 req->flags2,
3548 max_data_bytes,
3549 NULL,
3550 ppdata, &data_len);
3551 if (!NT_STATUS_IS_OK(status)) {
3552 reply_nterror(req, status);
3553 return;
3556 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3557 max_data_bytes);
3559 DEBUG( 4, ( "%s info_level = %d\n",
3560 smb_fn_name(req->cmd), info_level) );
3562 return;
3565 /****************************************************************************
3566 Reply to a TRANS2_SETFSINFO (set filesystem info).
3567 ****************************************************************************/
3569 static void call_trans2setfsinfo(connection_struct *conn,
3570 struct smb_request *req,
3571 char **pparams, int total_params,
3572 char **ppdata, int total_data,
3573 unsigned int max_data_bytes)
3575 char *pdata = *ppdata;
3576 char *params = *pparams;
3577 uint16 info_level;
3579 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3581 /* */
3582 if (total_params < 4) {
3583 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3584 total_params));
3585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3586 return;
3589 info_level = SVAL(params,2);
3591 if (IS_IPC(conn)) {
3592 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3593 info_level != SMB_SET_CIFS_UNIX_INFO) {
3594 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3595 "info level (0x%x) on IPC$.\n",
3596 (unsigned int)info_level));
3597 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3598 return;
3602 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3603 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3604 DEBUG(0,("call_trans2setfsinfo: encryption required "
3605 "and info level 0x%x sent.\n",
3606 (unsigned int)info_level));
3607 exit_server_cleanly("encryption required "
3608 "on connection");
3609 return;
3613 switch(info_level) {
3614 case SMB_SET_CIFS_UNIX_INFO:
3616 uint16 client_unix_major;
3617 uint16 client_unix_minor;
3618 uint32 client_unix_cap_low;
3619 uint32 client_unix_cap_high;
3621 if (!lp_unix_extensions()) {
3622 reply_nterror(req,
3623 NT_STATUS_INVALID_LEVEL);
3624 return;
3627 /* There should be 12 bytes of capabilities set. */
3628 if (total_data < 8) {
3629 reply_nterror(
3630 req,
3631 NT_STATUS_INVALID_PARAMETER);
3632 return;
3634 client_unix_major = SVAL(pdata,0);
3635 client_unix_minor = SVAL(pdata,2);
3636 client_unix_cap_low = IVAL(pdata,4);
3637 client_unix_cap_high = IVAL(pdata,8);
3638 /* Just print these values for now. */
3639 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3640 cap_low = 0x%x, cap_high = 0x%x\n",
3641 (unsigned int)client_unix_major,
3642 (unsigned int)client_unix_minor,
3643 (unsigned int)client_unix_cap_low,
3644 (unsigned int)client_unix_cap_high ));
3646 /* Here is where we must switch to posix pathname processing... */
3647 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3648 lp_set_posix_pathnames();
3649 mangle_change_to_posix();
3652 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3653 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3654 /* Client that knows how to do posix locks,
3655 * but not posix open/mkdir operations. Set a
3656 * default type for read/write checks. */
3658 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3661 break;
3664 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3666 NTSTATUS status;
3667 size_t param_len = 0;
3668 size_t data_len = total_data;
3670 if (!lp_unix_extensions()) {
3671 reply_nterror(
3672 req,
3673 NT_STATUS_INVALID_LEVEL);
3674 return;
3677 if (lp_smb_encrypt(SNUM(conn)) == false) {
3678 reply_nterror(
3679 req,
3680 NT_STATUS_NOT_SUPPORTED);
3681 return;
3684 if (req->sconn->smb1.echo_handler.trusted_fde) {
3685 DEBUG( 2,("call_trans2setfsinfo: "
3686 "request transport encryption disabled"
3687 "with 'fork echo handler = yes'\n"));
3688 reply_nterror(
3689 req,
3690 NT_STATUS_NOT_SUPPORTED);
3691 return;
3694 DEBUG( 4,("call_trans2setfsinfo: "
3695 "request transport encryption.\n"));
3697 status = srv_request_encryption_setup(conn,
3698 (unsigned char **)ppdata,
3699 &data_len,
3700 (unsigned char **)pparams,
3701 &param_len);
3703 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3704 !NT_STATUS_IS_OK(status)) {
3705 reply_nterror(req, status);
3706 return;
3709 send_trans2_replies(conn, req,
3710 *pparams,
3711 param_len,
3712 *ppdata,
3713 data_len,
3714 max_data_bytes);
3716 if (NT_STATUS_IS_OK(status)) {
3717 /* Server-side transport
3718 * encryption is now *on*. */
3719 status = srv_encryption_start(conn);
3720 if (!NT_STATUS_IS_OK(status)) {
3721 exit_server_cleanly(
3722 "Failure in setting "
3723 "up encrypted transport");
3726 return;
3729 case SMB_FS_QUOTA_INFORMATION:
3731 files_struct *fsp = NULL;
3732 SMB_NTQUOTA_STRUCT quotas;
3734 ZERO_STRUCT(quotas);
3736 /* access check */
3737 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3738 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3739 lp_servicename(SNUM(conn)),
3740 conn->session_info->unix_name));
3741 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3742 return;
3745 /* note: normaly there're 48 bytes,
3746 * but we didn't use the last 6 bytes for now
3747 * --metze
3749 fsp = file_fsp(req, SVAL(params,0));
3751 if (!check_fsp_ntquota_handle(conn, req,
3752 fsp)) {
3753 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3754 reply_nterror(
3755 req, NT_STATUS_INVALID_HANDLE);
3756 return;
3759 if (total_data < 42) {
3760 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3761 total_data));
3762 reply_nterror(
3763 req,
3764 NT_STATUS_INVALID_PARAMETER);
3765 return;
3768 /* unknown_1 24 NULL bytes in pdata*/
3770 /* the soft quotas 8 bytes (uint64_t)*/
3771 quotas.softlim = BVAL(pdata,24);
3773 /* the hard quotas 8 bytes (uint64_t)*/
3774 quotas.hardlim = BVAL(pdata,32);
3776 /* quota_flags 2 bytes **/
3777 quotas.qflags = SVAL(pdata,40);
3779 /* unknown_2 6 NULL bytes follow*/
3781 /* now set the quotas */
3782 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3783 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3784 reply_nterror(req, map_nt_error_from_unix(errno));
3785 return;
3788 break;
3790 default:
3791 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3792 info_level));
3793 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3794 return;
3795 break;
3799 * sending this reply works fine,
3800 * but I'm not sure it's the same
3801 * like windows do...
3802 * --metze
3804 reply_outbuf(req, 10, 0);
3807 #if defined(HAVE_POSIX_ACLS)
3808 /****************************************************************************
3809 Utility function to count the number of entries in a POSIX acl.
3810 ****************************************************************************/
3812 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3814 unsigned int ace_count = 0;
3815 int entry_id = SMB_ACL_FIRST_ENTRY;
3816 SMB_ACL_ENTRY_T entry;
3818 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3819 /* get_next... */
3820 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3821 entry_id = SMB_ACL_NEXT_ENTRY;
3823 ace_count++;
3825 return ace_count;
3828 /****************************************************************************
3829 Utility function to marshall a POSIX acl into wire format.
3830 ****************************************************************************/
3832 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3834 int entry_id = SMB_ACL_FIRST_ENTRY;
3835 SMB_ACL_ENTRY_T entry;
3837 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3838 SMB_ACL_TAG_T tagtype;
3839 SMB_ACL_PERMSET_T permset;
3840 unsigned char perms = 0;
3841 unsigned int own_grp;
3843 /* get_next... */
3844 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3845 entry_id = SMB_ACL_NEXT_ENTRY;
3848 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3849 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3850 return False;
3853 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3854 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3855 return False;
3858 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3859 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3860 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3862 SCVAL(pdata,1,perms);
3864 switch (tagtype) {
3865 case SMB_ACL_USER_OBJ:
3866 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3867 own_grp = (unsigned int)pst->st_ex_uid;
3868 SIVAL(pdata,2,own_grp);
3869 SIVAL(pdata,6,0);
3870 break;
3871 case SMB_ACL_USER:
3873 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3874 if (!puid) {
3875 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3876 return False;
3878 own_grp = (unsigned int)*puid;
3879 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3880 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3881 SIVAL(pdata,2,own_grp);
3882 SIVAL(pdata,6,0);
3883 break;
3885 case SMB_ACL_GROUP_OBJ:
3886 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3887 own_grp = (unsigned int)pst->st_ex_gid;
3888 SIVAL(pdata,2,own_grp);
3889 SIVAL(pdata,6,0);
3890 break;
3891 case SMB_ACL_GROUP:
3893 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3894 if (!pgid) {
3895 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3896 return False;
3898 own_grp = (unsigned int)*pgid;
3899 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3900 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3901 SIVAL(pdata,2,own_grp);
3902 SIVAL(pdata,6,0);
3903 break;
3905 case SMB_ACL_MASK:
3906 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3907 SIVAL(pdata,2,0xFFFFFFFF);
3908 SIVAL(pdata,6,0xFFFFFFFF);
3909 break;
3910 case SMB_ACL_OTHER:
3911 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3912 SIVAL(pdata,2,0xFFFFFFFF);
3913 SIVAL(pdata,6,0xFFFFFFFF);
3914 break;
3915 default:
3916 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3917 return False;
3919 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3922 return True;
3924 #endif
3926 /****************************************************************************
3927 Store the FILE_UNIX_BASIC info.
3928 ****************************************************************************/
3930 static char *store_file_unix_basic(connection_struct *conn,
3931 char *pdata,
3932 files_struct *fsp,
3933 const SMB_STRUCT_STAT *psbuf)
3935 uint64_t file_index = get_FileIndex(conn, psbuf);
3937 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3938 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3940 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3941 pdata += 8;
3943 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3944 pdata += 8;
3946 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3947 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3948 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3949 pdata += 24;
3951 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3952 SIVAL(pdata,4,0);
3953 pdata += 8;
3955 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3956 SIVAL(pdata,4,0);
3957 pdata += 8;
3959 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3960 pdata += 4;
3962 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3963 SIVAL(pdata,4,0);
3964 pdata += 8;
3966 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3967 SIVAL(pdata,4,0);
3968 pdata += 8;
3970 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3971 pdata += 8;
3973 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3974 SIVAL(pdata,4,0);
3975 pdata += 8;
3977 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3978 SIVAL(pdata,4,0);
3979 pdata += 8;
3981 return pdata;
3984 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3985 * the chflags(2) (or equivalent) flags.
3987 * XXX: this really should be behind the VFS interface. To do this, we would
3988 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3989 * Each VFS module could then implement its own mapping as appropriate for the
3990 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3992 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3993 info2_flags_map[] =
3995 #ifdef UF_NODUMP
3996 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3997 #endif
3999 #ifdef UF_IMMUTABLE
4000 { UF_IMMUTABLE, EXT_IMMUTABLE },
4001 #endif
4003 #ifdef UF_APPEND
4004 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4005 #endif
4007 #ifdef UF_HIDDEN
4008 { UF_HIDDEN, EXT_HIDDEN },
4009 #endif
4011 /* Do not remove. We need to guarantee that this array has at least one
4012 * entry to build on HP-UX.
4014 { 0, 0 }
4018 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4019 uint32 *smb_fflags, uint32 *smb_fmask)
4021 int i;
4023 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4024 *smb_fmask |= info2_flags_map[i].smb_fflag;
4025 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4026 *smb_fflags |= info2_flags_map[i].smb_fflag;
4031 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4032 const uint32 smb_fflags,
4033 const uint32 smb_fmask,
4034 int *stat_fflags)
4036 uint32 max_fmask = 0;
4037 int i;
4039 *stat_fflags = psbuf->st_ex_flags;
4041 /* For each flags requested in smb_fmask, check the state of the
4042 * corresponding flag in smb_fflags and set or clear the matching
4043 * stat flag.
4046 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4047 max_fmask |= info2_flags_map[i].smb_fflag;
4048 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4049 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4050 *stat_fflags |= info2_flags_map[i].stat_fflag;
4051 } else {
4052 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4057 /* If smb_fmask is asking to set any bits that are not supported by
4058 * our flag mappings, we should fail.
4060 if ((smb_fmask & max_fmask) != smb_fmask) {
4061 return False;
4064 return True;
4068 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4069 * of file flags and birth (create) time.
4071 static char *store_file_unix_basic_info2(connection_struct *conn,
4072 char *pdata,
4073 files_struct *fsp,
4074 const SMB_STRUCT_STAT *psbuf)
4076 uint32 file_flags = 0;
4077 uint32 flags_mask = 0;
4079 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4081 /* Create (birth) time 64 bit */
4082 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4083 pdata += 8;
4085 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4086 SIVAL(pdata, 0, file_flags); /* flags */
4087 SIVAL(pdata, 4, flags_mask); /* mask */
4088 pdata += 8;
4090 return pdata;
4093 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4094 const struct stream_struct *streams,
4095 char *data,
4096 unsigned int max_data_bytes,
4097 unsigned int *data_size)
4099 unsigned int i;
4100 unsigned int ofs = 0;
4102 for (i = 0; i < num_streams; i++) {
4103 unsigned int next_offset;
4104 size_t namelen;
4105 smb_ucs2_t *namebuf;
4107 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4108 streams[i].name, &namelen) ||
4109 namelen <= 2)
4111 return NT_STATUS_INVALID_PARAMETER;
4115 * name_buf is now null-terminated, we need to marshall as not
4116 * terminated
4119 namelen -= 2;
4122 * We cannot overflow ...
4124 if ((ofs + 24 + namelen) > max_data_bytes) {
4125 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4126 i));
4127 TALLOC_FREE(namebuf);
4128 return STATUS_BUFFER_OVERFLOW;
4131 SIVAL(data, ofs+4, namelen);
4132 SOFF_T(data, ofs+8, streams[i].size);
4133 SOFF_T(data, ofs+16, streams[i].alloc_size);
4134 memcpy(data+ofs+24, namebuf, namelen);
4135 TALLOC_FREE(namebuf);
4137 next_offset = ofs + 24 + namelen;
4139 if (i == num_streams-1) {
4140 SIVAL(data, ofs, 0);
4142 else {
4143 unsigned int align = ndr_align_size(next_offset, 8);
4145 if ((next_offset + align) > max_data_bytes) {
4146 DEBUG(10, ("refusing to overflow align "
4147 "reply at stream %u\n",
4148 i));
4149 TALLOC_FREE(namebuf);
4150 return STATUS_BUFFER_OVERFLOW;
4153 memset(data+next_offset, 0, align);
4154 next_offset += align;
4156 SIVAL(data, ofs, next_offset - ofs);
4157 ofs = next_offset;
4160 ofs = next_offset;
4163 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4165 *data_size = ofs;
4167 return NT_STATUS_OK;
4170 /****************************************************************************
4171 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4172 ****************************************************************************/
4174 static void call_trans2qpipeinfo(connection_struct *conn,
4175 struct smb_request *req,
4176 unsigned int tran_call,
4177 char **pparams, int total_params,
4178 char **ppdata, int total_data,
4179 unsigned int max_data_bytes)
4181 char *params = *pparams;
4182 char *pdata = *ppdata;
4183 unsigned int data_size = 0;
4184 unsigned int param_size = 2;
4185 uint16 info_level;
4186 files_struct *fsp;
4188 if (!params) {
4189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4190 return;
4193 if (total_params < 4) {
4194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4195 return;
4198 fsp = file_fsp(req, SVAL(params,0));
4199 if (!fsp_is_np(fsp)) {
4200 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4201 return;
4204 info_level = SVAL(params,2);
4206 *pparams = (char *)SMB_REALLOC(*pparams,2);
4207 if (*pparams == NULL) {
4208 reply_nterror(req, NT_STATUS_NO_MEMORY);
4209 return;
4211 params = *pparams;
4212 SSVAL(params,0,0);
4213 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4214 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4215 if (*ppdata == NULL ) {
4216 reply_nterror(req, NT_STATUS_NO_MEMORY);
4217 return;
4219 pdata = *ppdata;
4221 switch (info_level) {
4222 case SMB_FILE_STANDARD_INFORMATION:
4223 memset(pdata,0,24);
4224 SOFF_T(pdata,0,4096LL);
4225 SIVAL(pdata,16,1);
4226 SIVAL(pdata,20,1);
4227 data_size = 24;
4228 break;
4230 default:
4231 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4232 return;
4235 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4236 max_data_bytes);
4238 return;
4241 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4242 TALLOC_CTX *mem_ctx,
4243 uint16_t info_level,
4244 files_struct *fsp,
4245 struct smb_filename *smb_fname,
4246 bool delete_pending,
4247 struct timespec write_time_ts,
4248 struct ea_list *ea_list,
4249 int lock_data_count,
4250 char *lock_data,
4251 uint16_t flags2,
4252 unsigned int max_data_bytes,
4253 char **ppdata,
4254 unsigned int *pdata_size)
4256 char *pdata = *ppdata;
4257 char *dstart, *dend;
4258 unsigned int data_size;
4259 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4260 time_t create_time, mtime, atime, c_time;
4261 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4262 char *p;
4263 char *base_name;
4264 char *dos_fname;
4265 int mode;
4266 int nlink;
4267 NTSTATUS status;
4268 uint64_t file_size = 0;
4269 uint64_t pos = 0;
4270 uint64_t allocation_size = 0;
4271 uint64_t file_index = 0;
4272 uint32_t access_mask = 0;
4274 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4275 return NT_STATUS_INVALID_LEVEL;
4278 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4279 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4280 info_level, max_data_bytes));
4282 mode = dos_mode(conn, smb_fname);
4283 nlink = psbuf->st_ex_nlink;
4285 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4286 nlink = 1;
4289 if ((nlink > 0) && delete_pending) {
4290 nlink -= 1;
4293 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4294 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4295 if (*ppdata == NULL) {
4296 return NT_STATUS_NO_MEMORY;
4298 pdata = *ppdata;
4299 dstart = pdata;
4300 dend = dstart + data_size - 1;
4302 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4303 update_stat_ex_mtime(psbuf, write_time_ts);
4306 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4307 mtime_ts = psbuf->st_ex_mtime;
4308 atime_ts = psbuf->st_ex_atime;
4309 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4311 if (lp_dos_filetime_resolution(SNUM(conn))) {
4312 dos_filetime_timespec(&create_time_ts);
4313 dos_filetime_timespec(&mtime_ts);
4314 dos_filetime_timespec(&atime_ts);
4315 dos_filetime_timespec(&ctime_ts);
4318 create_time = convert_timespec_to_time_t(create_time_ts);
4319 mtime = convert_timespec_to_time_t(mtime_ts);
4320 atime = convert_timespec_to_time_t(atime_ts);
4321 c_time = convert_timespec_to_time_t(ctime_ts);
4323 p = strrchr_m(smb_fname->base_name,'/');
4324 if (!p)
4325 base_name = smb_fname->base_name;
4326 else
4327 base_name = p+1;
4329 /* NT expects the name to be in an exact form of the *full*
4330 filename. See the trans2 torture test */
4331 if (ISDOT(base_name)) {
4332 dos_fname = talloc_strdup(mem_ctx, "\\");
4333 if (!dos_fname) {
4334 return NT_STATUS_NO_MEMORY;
4336 } else {
4337 dos_fname = talloc_asprintf(mem_ctx,
4338 "\\%s",
4339 smb_fname->base_name);
4340 if (!dos_fname) {
4341 return NT_STATUS_NO_MEMORY;
4343 if (is_ntfs_stream_smb_fname(smb_fname)) {
4344 dos_fname = talloc_asprintf(dos_fname, "%s",
4345 smb_fname->stream_name);
4346 if (!dos_fname) {
4347 return NT_STATUS_NO_MEMORY;
4351 string_replace(dos_fname, '/', '\\');
4354 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4356 if (!fsp) {
4357 /* Do we have this path open ? */
4358 files_struct *fsp1;
4359 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4360 fsp1 = file_find_di_first(conn->sconn, fileid);
4361 if (fsp1 && fsp1->initial_allocation_size) {
4362 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4366 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4367 file_size = get_file_size_stat(psbuf);
4370 if (fsp) {
4371 pos = fsp->fh->position_information;
4374 if (fsp) {
4375 access_mask = fsp->access_mask;
4376 } else {
4377 /* GENERIC_EXECUTE mapping from Windows */
4378 access_mask = 0x12019F;
4381 /* This should be an index number - looks like
4382 dev/ino to me :-)
4384 I think this causes us to fail the IFSKIT
4385 BasicFileInformationTest. -tpot */
4386 file_index = get_FileIndex(conn, psbuf);
4388 switch (info_level) {
4389 case SMB_INFO_STANDARD:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4391 data_size = 22;
4392 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4393 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4394 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4395 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4396 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4397 SSVAL(pdata,l1_attrFile,mode);
4398 break;
4400 case SMB_INFO_QUERY_EA_SIZE:
4402 unsigned int ea_size =
4403 estimate_ea_size(conn, fsp,
4404 smb_fname->base_name);
4405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4406 data_size = 26;
4407 srv_put_dos_date2(pdata,0,create_time);
4408 srv_put_dos_date2(pdata,4,atime);
4409 srv_put_dos_date2(pdata,8,mtime); /* write time */
4410 SIVAL(pdata,12,(uint32)file_size);
4411 SIVAL(pdata,16,(uint32)allocation_size);
4412 SSVAL(pdata,20,mode);
4413 SIVAL(pdata,22,ea_size);
4414 break;
4417 case SMB_INFO_IS_NAME_VALID:
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4419 if (fsp) {
4420 /* os/2 needs this ? really ?*/
4421 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4423 /* This is only reached for qpathinfo */
4424 data_size = 0;
4425 break;
4427 case SMB_INFO_QUERY_EAS_FROM_LIST:
4429 size_t total_ea_len = 0;
4430 struct ea_list *ea_file_list = NULL;
4432 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4434 ea_file_list =
4435 get_ea_list_from_file(mem_ctx, conn, fsp,
4436 smb_fname->base_name,
4437 &total_ea_len);
4438 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4440 if (!ea_list || (total_ea_len > data_size)) {
4441 data_size = 4;
4442 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4443 break;
4446 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4447 break;
4450 case SMB_INFO_QUERY_ALL_EAS:
4452 /* We have data_size bytes to put EA's into. */
4453 size_t total_ea_len = 0;
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4457 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4458 smb_fname->base_name,
4459 &total_ea_len);
4460 if (!ea_list || (total_ea_len > data_size)) {
4461 data_size = 4;
4462 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4463 break;
4466 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4467 break;
4470 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4472 /* This is FileFullEaInformation - 0xF which maps to
4473 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4475 /* We have data_size bytes to put EA's into. */
4476 size_t total_ea_len = 0;
4477 struct ea_list *ea_file_list = NULL;
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4481 /*TODO: add filtering and index handling */
4483 ea_file_list =
4484 get_ea_list_from_file(mem_ctx, conn, fsp,
4485 smb_fname->base_name,
4486 &total_ea_len);
4487 if (!ea_file_list) {
4488 return NT_STATUS_NO_EAS_ON_FILE;
4491 status = fill_ea_chained_buffer(mem_ctx,
4492 pdata,
4493 data_size,
4494 &data_size,
4495 conn, ea_file_list);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 return status;
4499 break;
4502 case SMB_FILE_BASIC_INFORMATION:
4503 case SMB_QUERY_FILE_BASIC_INFO:
4505 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4507 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4508 } else {
4509 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4510 data_size = 40;
4511 SIVAL(pdata,36,0);
4513 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4514 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4515 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4516 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4517 SIVAL(pdata,32,mode);
4519 DEBUG(5,("SMB_QFBI - "));
4520 DEBUG(5,("create: %s ", ctime(&create_time)));
4521 DEBUG(5,("access: %s ", ctime(&atime)));
4522 DEBUG(5,("write: %s ", ctime(&mtime)));
4523 DEBUG(5,("change: %s ", ctime(&c_time)));
4524 DEBUG(5,("mode: %x\n", mode));
4525 break;
4527 case SMB_FILE_STANDARD_INFORMATION:
4528 case SMB_QUERY_FILE_STANDARD_INFO:
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4531 data_size = 24;
4532 SOFF_T(pdata,0,allocation_size);
4533 SOFF_T(pdata,8,file_size);
4534 SIVAL(pdata,16,nlink);
4535 SCVAL(pdata,20,delete_pending?1:0);
4536 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4537 SSVAL(pdata,22,0); /* Padding. */
4538 break;
4540 case SMB_FILE_EA_INFORMATION:
4541 case SMB_QUERY_FILE_EA_INFO:
4543 unsigned int ea_size =
4544 estimate_ea_size(conn, fsp, smb_fname->base_name);
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4546 data_size = 4;
4547 SIVAL(pdata,0,ea_size);
4548 break;
4551 /* Get the 8.3 name - used if NT SMB was negotiated. */
4552 case SMB_QUERY_FILE_ALT_NAME_INFO:
4553 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4555 int len;
4556 char mangled_name[13];
4557 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4558 if (!name_to_8_3(base_name,mangled_name,
4559 True,conn->params)) {
4560 return NT_STATUS_NO_MEMORY;
4562 len = srvstr_push(dstart, flags2,
4563 pdata+4, mangled_name,
4564 PTR_DIFF(dend, pdata+4),
4565 STR_UNICODE);
4566 data_size = 4 + len;
4567 SIVAL(pdata,0,len);
4568 break;
4571 case SMB_QUERY_FILE_NAME_INFO:
4573 int len;
4575 this must be *exactly* right for ACLs on mapped drives to work
4577 len = srvstr_push(dstart, flags2,
4578 pdata+4, dos_fname,
4579 PTR_DIFF(dend, pdata+4),
4580 STR_UNICODE);
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4582 data_size = 4 + len;
4583 SIVAL(pdata,0,len);
4584 break;
4587 case SMB_FILE_ALLOCATION_INFORMATION:
4588 case SMB_QUERY_FILE_ALLOCATION_INFO:
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4590 data_size = 8;
4591 SOFF_T(pdata,0,allocation_size);
4592 break;
4594 case SMB_FILE_END_OF_FILE_INFORMATION:
4595 case SMB_QUERY_FILE_END_OF_FILEINFO:
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4597 data_size = 8;
4598 SOFF_T(pdata,0,file_size);
4599 break;
4601 case SMB_QUERY_FILE_ALL_INFO:
4602 case SMB_FILE_ALL_INFORMATION:
4604 int len;
4605 unsigned int ea_size =
4606 estimate_ea_size(conn, fsp, smb_fname->base_name);
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4608 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4609 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4610 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4611 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4612 SIVAL(pdata,32,mode);
4613 SIVAL(pdata,36,0); /* padding. */
4614 pdata += 40;
4615 SOFF_T(pdata,0,allocation_size);
4616 SOFF_T(pdata,8,file_size);
4617 SIVAL(pdata,16,nlink);
4618 SCVAL(pdata,20,delete_pending);
4619 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4620 SSVAL(pdata,22,0);
4621 pdata += 24;
4622 SIVAL(pdata,0,ea_size);
4623 pdata += 4; /* EA info */
4624 len = srvstr_push(dstart, flags2,
4625 pdata+4, dos_fname,
4626 PTR_DIFF(dend, pdata+4),
4627 STR_UNICODE);
4628 SIVAL(pdata,0,len);
4629 pdata += 4 + len;
4630 data_size = PTR_DIFF(pdata,(*ppdata));
4631 break;
4634 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4636 int len;
4637 unsigned int ea_size =
4638 estimate_ea_size(conn, fsp, smb_fname->base_name);
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4640 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4641 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4642 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4643 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4644 SIVAL(pdata, 0x20, mode);
4645 SIVAL(pdata, 0x24, 0); /* padding. */
4646 SBVAL(pdata, 0x28, allocation_size);
4647 SBVAL(pdata, 0x30, file_size);
4648 SIVAL(pdata, 0x38, nlink);
4649 SCVAL(pdata, 0x3C, delete_pending);
4650 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4651 SSVAL(pdata, 0x3E, 0); /* padding */
4652 SBVAL(pdata, 0x40, file_index);
4653 SIVAL(pdata, 0x48, ea_size);
4654 SIVAL(pdata, 0x4C, access_mask);
4655 SBVAL(pdata, 0x50, pos);
4656 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4657 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4659 pdata += 0x60;
4661 len = srvstr_push(dstart, flags2,
4662 pdata+4, dos_fname,
4663 PTR_DIFF(dend, pdata+4),
4664 STR_UNICODE);
4665 SIVAL(pdata,0,len);
4666 pdata += 4 + len;
4667 data_size = PTR_DIFF(pdata,(*ppdata));
4668 break;
4670 case SMB_FILE_INTERNAL_INFORMATION:
4672 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4673 SBVAL(pdata, 0, file_index);
4674 data_size = 8;
4675 break;
4677 case SMB_FILE_ACCESS_INFORMATION:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4679 SIVAL(pdata, 0, access_mask);
4680 data_size = 4;
4681 break;
4683 case SMB_FILE_NAME_INFORMATION:
4684 /* Pathname with leading '\'. */
4686 size_t byte_len;
4687 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4689 SIVAL(pdata,0,byte_len);
4690 data_size = 4 + byte_len;
4691 break;
4694 case SMB_FILE_DISPOSITION_INFORMATION:
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4696 data_size = 1;
4697 SCVAL(pdata,0,delete_pending);
4698 break;
4700 case SMB_FILE_POSITION_INFORMATION:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4702 data_size = 8;
4703 SOFF_T(pdata,0,pos);
4704 break;
4706 case SMB_FILE_MODE_INFORMATION:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4708 SIVAL(pdata,0,mode);
4709 data_size = 4;
4710 break;
4712 case SMB_FILE_ALIGNMENT_INFORMATION:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4714 SIVAL(pdata,0,0); /* No alignment needed. */
4715 data_size = 4;
4716 break;
4719 * NT4 server just returns "invalid query" to this - if we try
4720 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4721 * want this. JRA.
4723 /* The first statement above is false - verified using Thursby
4724 * client against NT4 -- gcolley.
4726 case SMB_QUERY_FILE_STREAM_INFO:
4727 case SMB_FILE_STREAM_INFORMATION: {
4728 unsigned int num_streams = 0;
4729 struct stream_struct *streams = NULL;
4731 DEBUG(10,("smbd_do_qfilepathinfo: "
4732 "SMB_FILE_STREAM_INFORMATION\n"));
4734 if (is_ntfs_stream_smb_fname(smb_fname)) {
4735 return NT_STATUS_INVALID_PARAMETER;
4738 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4739 talloc_tos(), &num_streams, &streams);
4741 if (!NT_STATUS_IS_OK(status)) {
4742 DEBUG(10, ("could not get stream info: %s\n",
4743 nt_errstr(status)));
4744 return status;
4747 status = marshall_stream_info(num_streams, streams,
4748 pdata, max_data_bytes,
4749 &data_size);
4751 if (!NT_STATUS_IS_OK(status)) {
4752 DEBUG(10, ("marshall_stream_info failed: %s\n",
4753 nt_errstr(status)));
4754 TALLOC_FREE(streams);
4755 return status;
4758 TALLOC_FREE(streams);
4760 break;
4762 case SMB_QUERY_COMPRESSION_INFO:
4763 case SMB_FILE_COMPRESSION_INFORMATION:
4764 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4765 SOFF_T(pdata,0,file_size);
4766 SIVAL(pdata,8,0); /* ??? */
4767 SIVAL(pdata,12,0); /* ??? */
4768 data_size = 16;
4769 break;
4771 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4773 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4774 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4775 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4776 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4777 SOFF_T(pdata,32,allocation_size);
4778 SOFF_T(pdata,40,file_size);
4779 SIVAL(pdata,48,mode);
4780 SIVAL(pdata,52,0); /* ??? */
4781 data_size = 56;
4782 break;
4784 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4785 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4786 SIVAL(pdata,0,mode);
4787 SIVAL(pdata,4,0);
4788 data_size = 8;
4789 break;
4792 * CIFS UNIX Extensions.
4795 case SMB_QUERY_FILE_UNIX_BASIC:
4797 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4798 data_size = PTR_DIFF(pdata,(*ppdata));
4800 DEBUG(4,("smbd_do_qfilepathinfo: "
4801 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4802 dump_data(4, (uint8_t *)(*ppdata), data_size);
4804 break;
4806 case SMB_QUERY_FILE_UNIX_INFO2:
4808 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4809 data_size = PTR_DIFF(pdata,(*ppdata));
4812 int i;
4813 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4815 for (i=0; i<100; i++)
4816 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4817 DEBUG(4,("\n"));
4820 break;
4822 case SMB_QUERY_FILE_UNIX_LINK:
4824 int len;
4825 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4827 if (!buffer) {
4828 return NT_STATUS_NO_MEMORY;
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4832 #ifdef S_ISLNK
4833 if(!S_ISLNK(psbuf->st_ex_mode)) {
4834 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4836 #else
4837 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4838 #endif
4839 len = SMB_VFS_READLINK(conn,
4840 smb_fname->base_name,
4841 buffer, PATH_MAX);
4842 if (len == -1) {
4843 return map_nt_error_from_unix(errno);
4845 buffer[len] = 0;
4846 len = srvstr_push(dstart, flags2,
4847 pdata, buffer,
4848 PTR_DIFF(dend, pdata),
4849 STR_TERMINATE);
4850 pdata += len;
4851 data_size = PTR_DIFF(pdata,(*ppdata));
4853 break;
4856 #if defined(HAVE_POSIX_ACLS)
4857 case SMB_QUERY_POSIX_ACL:
4859 SMB_ACL_T file_acl = NULL;
4860 SMB_ACL_T def_acl = NULL;
4861 uint16 num_file_acls = 0;
4862 uint16 num_def_acls = 0;
4864 if (fsp && fsp->fh->fd != -1) {
4865 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4866 } else {
4867 file_acl =
4868 SMB_VFS_SYS_ACL_GET_FILE(conn,
4869 smb_fname->base_name,
4870 SMB_ACL_TYPE_ACCESS);
4873 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4874 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4875 "not implemented on "
4876 "filesystem containing %s\n",
4877 smb_fname->base_name));
4878 return NT_STATUS_NOT_IMPLEMENTED;
4881 if (S_ISDIR(psbuf->st_ex_mode)) {
4882 if (fsp && fsp->is_directory) {
4883 def_acl =
4884 SMB_VFS_SYS_ACL_GET_FILE(
4885 conn,
4886 fsp->fsp_name->base_name,
4887 SMB_ACL_TYPE_DEFAULT);
4888 } else {
4889 def_acl =
4890 SMB_VFS_SYS_ACL_GET_FILE(
4891 conn,
4892 smb_fname->base_name,
4893 SMB_ACL_TYPE_DEFAULT);
4895 def_acl = free_empty_sys_acl(conn, def_acl);
4898 num_file_acls = count_acl_entries(conn, file_acl);
4899 num_def_acls = count_acl_entries(conn, def_acl);
4901 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4902 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4903 data_size,
4904 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4905 SMB_POSIX_ACL_HEADER_SIZE) ));
4906 if (file_acl) {
4907 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4909 if (def_acl) {
4910 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4912 return NT_STATUS_BUFFER_TOO_SMALL;
4915 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4916 SSVAL(pdata,2,num_file_acls);
4917 SSVAL(pdata,4,num_def_acls);
4918 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4919 if (file_acl) {
4920 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4922 if (def_acl) {
4923 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4925 return NT_STATUS_INTERNAL_ERROR;
4927 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4928 if (file_acl) {
4929 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4931 if (def_acl) {
4932 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4934 return NT_STATUS_INTERNAL_ERROR;
4937 if (file_acl) {
4938 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4940 if (def_acl) {
4941 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4943 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4944 break;
4946 #endif
4949 case SMB_QUERY_POSIX_LOCK:
4951 uint64_t count;
4952 uint64_t offset;
4953 uint64_t smblctx;
4954 enum brl_type lock_type;
4956 /* We need an open file with a real fd for this. */
4957 if (!fsp || fsp->fh->fd == -1) {
4958 return NT_STATUS_INVALID_LEVEL;
4961 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4966 case POSIX_LOCK_TYPE_READ:
4967 lock_type = READ_LOCK;
4968 break;
4969 case POSIX_LOCK_TYPE_WRITE:
4970 lock_type = WRITE_LOCK;
4971 break;
4972 case POSIX_LOCK_TYPE_UNLOCK:
4973 default:
4974 /* There's no point in asking for an unlock... */
4975 return NT_STATUS_INVALID_PARAMETER;
4978 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4979 #if defined(HAVE_LONGLONG)
4980 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4981 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4982 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4983 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4984 #else /* HAVE_LONGLONG */
4985 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4986 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4987 #endif /* HAVE_LONGLONG */
4989 status = query_lock(fsp,
4990 &smblctx,
4991 &count,
4992 &offset,
4993 &lock_type,
4994 POSIX_LOCK);
4996 if (ERROR_WAS_LOCK_DENIED(status)) {
4997 /* Here we need to report who has it locked... */
4998 data_size = POSIX_LOCK_DATA_SIZE;
5000 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5001 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5002 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5003 #if defined(HAVE_LONGLONG)
5004 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5005 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5006 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5007 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5008 #else /* HAVE_LONGLONG */
5009 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5010 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5011 #endif /* HAVE_LONGLONG */
5013 } else if (NT_STATUS_IS_OK(status)) {
5014 /* For success we just return a copy of what we sent
5015 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5016 data_size = POSIX_LOCK_DATA_SIZE;
5017 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5018 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5019 } else {
5020 return status;
5022 break;
5025 default:
5026 return NT_STATUS_INVALID_LEVEL;
5029 *pdata_size = data_size;
5030 return NT_STATUS_OK;
5033 /****************************************************************************
5034 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5035 file name or file id).
5036 ****************************************************************************/
5038 static void call_trans2qfilepathinfo(connection_struct *conn,
5039 struct smb_request *req,
5040 unsigned int tran_call,
5041 char **pparams, int total_params,
5042 char **ppdata, int total_data,
5043 unsigned int max_data_bytes)
5045 char *params = *pparams;
5046 char *pdata = *ppdata;
5047 uint16 info_level;
5048 unsigned int data_size = 0;
5049 unsigned int param_size = 2;
5050 struct smb_filename *smb_fname = NULL;
5051 bool delete_pending = False;
5052 struct timespec write_time_ts;
5053 files_struct *fsp = NULL;
5054 struct file_id fileid;
5055 struct ea_list *ea_list = NULL;
5056 int lock_data_count = 0;
5057 char *lock_data = NULL;
5058 NTSTATUS status = NT_STATUS_OK;
5060 if (!params) {
5061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5062 return;
5065 ZERO_STRUCT(write_time_ts);
5067 if (tran_call == TRANSACT2_QFILEINFO) {
5068 if (total_params < 4) {
5069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5070 return;
5073 if (IS_IPC(conn)) {
5074 call_trans2qpipeinfo(conn, req, tran_call,
5075 pparams, total_params,
5076 ppdata, total_data,
5077 max_data_bytes);
5078 return;
5081 fsp = file_fsp(req, SVAL(params,0));
5082 info_level = SVAL(params,2);
5084 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5086 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5087 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5088 return;
5091 /* Initial check for valid fsp ptr. */
5092 if (!check_fsp_open(conn, req, fsp)) {
5093 return;
5096 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5097 &smb_fname);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 reply_nterror(req, status);
5100 return;
5103 if(fsp->fake_file_handle) {
5105 * This is actually for the QUOTA_FAKE_FILE --metze
5108 /* We know this name is ok, it's already passed the checks. */
5110 } else if(fsp->fh->fd == -1) {
5112 * This is actually a QFILEINFO on a directory
5113 * handle (returned from an NT SMB). NT5.0 seems
5114 * to do this call. JRA.
5117 if (INFO_LEVEL_IS_UNIX(info_level)) {
5118 /* Always do lstat for UNIX calls. */
5119 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5120 DEBUG(3,("call_trans2qfilepathinfo: "
5121 "SMB_VFS_LSTAT of %s failed "
5122 "(%s)\n",
5123 smb_fname_str_dbg(smb_fname),
5124 strerror(errno)));
5125 reply_nterror(req,
5126 map_nt_error_from_unix(errno));
5127 return;
5129 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5130 DEBUG(3,("call_trans2qfilepathinfo: "
5131 "SMB_VFS_STAT of %s failed (%s)\n",
5132 smb_fname_str_dbg(smb_fname),
5133 strerror(errno)));
5134 reply_nterror(req,
5135 map_nt_error_from_unix(errno));
5136 return;
5139 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5140 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5141 } else {
5143 * Original code - this is an open file.
5145 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5146 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5147 fsp->fnum, strerror(errno)));
5148 reply_nterror(req,
5149 map_nt_error_from_unix(errno));
5150 return;
5152 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5153 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5156 } else {
5157 uint32_t name_hash;
5158 char *fname = NULL;
5159 uint32_t ucf_flags = 0;
5161 /* qpathinfo */
5162 if (total_params < 7) {
5163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5164 return;
5167 info_level = SVAL(params,0);
5169 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5171 if (INFO_LEVEL_IS_UNIX(info_level)) {
5172 if (!lp_unix_extensions()) {
5173 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5174 return;
5176 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5177 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5178 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5179 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5183 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5184 total_params - 6,
5185 STR_TERMINATE, &status);
5186 if (!NT_STATUS_IS_OK(status)) {
5187 reply_nterror(req, status);
5188 return;
5191 status = filename_convert(req,
5192 conn,
5193 req->flags2 & FLAGS2_DFS_PATHNAMES,
5194 fname,
5195 ucf_flags,
5196 NULL,
5197 &smb_fname);
5198 if (!NT_STATUS_IS_OK(status)) {
5199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5200 reply_botherror(req,
5201 NT_STATUS_PATH_NOT_COVERED,
5202 ERRSRV, ERRbadpath);
5203 return;
5205 reply_nterror(req, status);
5206 return;
5209 /* If this is a stream, check if there is a delete_pending. */
5210 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5211 && is_ntfs_stream_smb_fname(smb_fname)) {
5212 struct smb_filename *smb_fname_base = NULL;
5214 /* Create an smb_filename with stream_name == NULL. */
5215 status =
5216 create_synthetic_smb_fname(talloc_tos(),
5217 smb_fname->base_name,
5218 NULL, NULL,
5219 &smb_fname_base);
5220 if (!NT_STATUS_IS_OK(status)) {
5221 reply_nterror(req, status);
5222 return;
5225 if (INFO_LEVEL_IS_UNIX(info_level)) {
5226 /* Always do lstat for UNIX calls. */
5227 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5228 DEBUG(3,("call_trans2qfilepathinfo: "
5229 "SMB_VFS_LSTAT of %s failed "
5230 "(%s)\n",
5231 smb_fname_str_dbg(smb_fname_base),
5232 strerror(errno)));
5233 TALLOC_FREE(smb_fname_base);
5234 reply_nterror(req,
5235 map_nt_error_from_unix(errno));
5236 return;
5238 } else {
5239 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5240 DEBUG(3,("call_trans2qfilepathinfo: "
5241 "fileinfo of %s failed "
5242 "(%s)\n",
5243 smb_fname_str_dbg(smb_fname_base),
5244 strerror(errno)));
5245 TALLOC_FREE(smb_fname_base);
5246 reply_nterror(req,
5247 map_nt_error_from_unix(errno));
5248 return;
5252 status = file_name_hash(conn,
5253 smb_fname_str_dbg(smb_fname_base),
5254 &name_hash);
5255 if (!NT_STATUS_IS_OK(status)) {
5256 TALLOC_FREE(smb_fname_base);
5257 reply_nterror(req, status);
5258 return;
5261 fileid = vfs_file_id_from_sbuf(conn,
5262 &smb_fname_base->st);
5263 TALLOC_FREE(smb_fname_base);
5264 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5265 if (delete_pending) {
5266 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5267 return;
5271 if (INFO_LEVEL_IS_UNIX(info_level)) {
5272 /* Always do lstat for UNIX calls. */
5273 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5274 DEBUG(3,("call_trans2qfilepathinfo: "
5275 "SMB_VFS_LSTAT of %s failed (%s)\n",
5276 smb_fname_str_dbg(smb_fname),
5277 strerror(errno)));
5278 reply_nterror(req,
5279 map_nt_error_from_unix(errno));
5280 return;
5283 } else {
5284 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5285 DEBUG(3,("call_trans2qfilepathinfo: "
5286 "SMB_VFS_STAT of %s failed (%s)\n",
5287 smb_fname_str_dbg(smb_fname),
5288 strerror(errno)));
5289 reply_nterror(req,
5290 map_nt_error_from_unix(errno));
5291 return;
5295 status = file_name_hash(conn,
5296 smb_fname_str_dbg(smb_fname),
5297 &name_hash);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 reply_nterror(req, status);
5300 return;
5303 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5304 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5305 if (delete_pending) {
5306 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5307 return;
5311 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5312 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5313 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5315 /* Pull out any data sent here before we realloc. */
5316 switch (info_level) {
5317 case SMB_INFO_QUERY_EAS_FROM_LIST:
5319 /* Pull any EA list from the data portion. */
5320 uint32 ea_size;
5322 if (total_data < 4) {
5323 reply_nterror(
5324 req, NT_STATUS_INVALID_PARAMETER);
5325 return;
5327 ea_size = IVAL(pdata,0);
5329 if (total_data > 0 && ea_size != total_data) {
5330 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5332 reply_nterror(
5333 req, NT_STATUS_INVALID_PARAMETER);
5334 return;
5337 if (!lp_ea_support(SNUM(conn))) {
5338 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5339 return;
5342 /* Pull out the list of names. */
5343 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5344 if (!ea_list) {
5345 reply_nterror(
5346 req, NT_STATUS_INVALID_PARAMETER);
5347 return;
5349 break;
5352 case SMB_QUERY_POSIX_LOCK:
5354 if (fsp == NULL || fsp->fh->fd == -1) {
5355 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5356 return;
5359 if (total_data != POSIX_LOCK_DATA_SIZE) {
5360 reply_nterror(
5361 req, NT_STATUS_INVALID_PARAMETER);
5362 return;
5365 /* Copy the lock range data. */
5366 lock_data = (char *)TALLOC_MEMDUP(
5367 req, pdata, total_data);
5368 if (!lock_data) {
5369 reply_nterror(req, NT_STATUS_NO_MEMORY);
5370 return;
5372 lock_data_count = total_data;
5374 default:
5375 break;
5378 *pparams = (char *)SMB_REALLOC(*pparams,2);
5379 if (*pparams == NULL) {
5380 reply_nterror(req, NT_STATUS_NO_MEMORY);
5381 return;
5383 params = *pparams;
5384 SSVAL(params,0,0);
5387 * draft-leach-cifs-v1-spec-02.txt
5388 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5389 * says:
5391 * The requested information is placed in the Data portion of the
5392 * transaction response. For the information levels greater than 0x100,
5393 * the transaction response has 1 parameter word which should be
5394 * ignored by the client.
5396 * However Windows only follows this rule for the IS_NAME_VALID call.
5398 switch (info_level) {
5399 case SMB_INFO_IS_NAME_VALID:
5400 param_size = 0;
5401 break;
5404 if ((info_level & 0xFF00) == 0xFF00) {
5406 * We use levels that start with 0xFF00
5407 * internally to represent SMB2 specific levels
5409 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5410 return;
5413 status = smbd_do_qfilepathinfo(conn, req, info_level,
5414 fsp, smb_fname,
5415 delete_pending, write_time_ts,
5416 ea_list,
5417 lock_data_count, lock_data,
5418 req->flags2, max_data_bytes,
5419 ppdata, &data_size);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 reply_nterror(req, status);
5422 return;
5425 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5426 max_data_bytes);
5428 return;
5431 /****************************************************************************
5432 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5433 code.
5434 ****************************************************************************/
5436 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5437 connection_struct *conn,
5438 struct smb_request *req,
5439 bool overwrite_if_exists,
5440 const struct smb_filename *smb_fname_old,
5441 struct smb_filename *smb_fname_new)
5443 NTSTATUS status = NT_STATUS_OK;
5445 /* source must already exist. */
5446 if (!VALID_STAT(smb_fname_old->st)) {
5447 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5450 if (VALID_STAT(smb_fname_new->st)) {
5451 if (overwrite_if_exists) {
5452 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5453 return NT_STATUS_FILE_IS_A_DIRECTORY;
5455 status = unlink_internals(conn,
5456 req,
5457 FILE_ATTRIBUTE_NORMAL,
5458 smb_fname_new,
5459 false);
5460 if (!NT_STATUS_IS_OK(status)) {
5461 return status;
5463 } else {
5464 /* Disallow if newname already exists. */
5465 return NT_STATUS_OBJECT_NAME_COLLISION;
5469 /* No links from a directory. */
5470 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5471 return NT_STATUS_FILE_IS_A_DIRECTORY;
5474 /* Setting a hardlink to/from a stream isn't currently supported. */
5475 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5476 is_ntfs_stream_smb_fname(smb_fname_new)) {
5477 return NT_STATUS_INVALID_PARAMETER;
5480 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5481 smb_fname_old->base_name, smb_fname_new->base_name));
5483 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5484 smb_fname_new->base_name) != 0) {
5485 status = map_nt_error_from_unix(errno);
5486 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5487 nt_errstr(status), smb_fname_old->base_name,
5488 smb_fname_new->base_name));
5490 return status;
5493 /****************************************************************************
5494 Deal with setting the time from any of the setfilepathinfo functions.
5495 ****************************************************************************/
5497 NTSTATUS smb_set_file_time(connection_struct *conn,
5498 files_struct *fsp,
5499 const struct smb_filename *smb_fname,
5500 struct smb_file_time *ft,
5501 bool setting_write_time)
5503 struct smb_filename smb_fname_base;
5504 uint32 action =
5505 FILE_NOTIFY_CHANGE_LAST_ACCESS
5506 |FILE_NOTIFY_CHANGE_LAST_WRITE
5507 |FILE_NOTIFY_CHANGE_CREATION;
5509 if (!VALID_STAT(smb_fname->st)) {
5510 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5513 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5514 return NT_STATUS_ACCESS_DENIED;
5517 /* get some defaults (no modifications) if any info is zero or -1. */
5518 if (null_timespec(ft->create_time)) {
5519 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5522 if (null_timespec(ft->atime)) {
5523 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5526 if (null_timespec(ft->mtime)) {
5527 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5530 if (!setting_write_time) {
5531 /* ft->mtime comes from change time, not write time. */
5532 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5535 /* Ensure the resolution is the correct for
5536 * what we can store on this filesystem. */
5538 round_timespec(conn->ts_res, &ft->create_time);
5539 round_timespec(conn->ts_res, &ft->ctime);
5540 round_timespec(conn->ts_res, &ft->atime);
5541 round_timespec(conn->ts_res, &ft->mtime);
5543 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5544 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5545 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5546 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5547 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5548 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5549 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5550 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5552 if (setting_write_time) {
5554 * This was a Windows setfileinfo on an open file.
5555 * NT does this a lot. We also need to
5556 * set the time here, as it can be read by
5557 * FindFirst/FindNext and with the patch for bug #2045
5558 * in smbd/fileio.c it ensures that this timestamp is
5559 * kept sticky even after a write. We save the request
5560 * away and will set it on file close and after a write. JRA.
5563 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5564 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5566 if (fsp != NULL) {
5567 if (fsp->base_fsp) {
5568 set_sticky_write_time_fsp(fsp->base_fsp,
5569 ft->mtime);
5570 } else {
5571 set_sticky_write_time_fsp(fsp, ft->mtime);
5573 } else {
5574 set_sticky_write_time_path(
5575 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5576 ft->mtime);
5580 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5582 /* Always call ntimes on the base, even if a stream was passed in. */
5583 smb_fname_base = *smb_fname;
5584 smb_fname_base.stream_name = NULL;
5586 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5587 return map_nt_error_from_unix(errno);
5590 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5591 smb_fname->base_name);
5592 return NT_STATUS_OK;
5595 /****************************************************************************
5596 Deal with setting the dosmode from any of the setfilepathinfo functions.
5597 ****************************************************************************/
5599 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5600 const struct smb_filename *smb_fname,
5601 uint32 dosmode)
5603 struct smb_filename *smb_fname_base = NULL;
5604 NTSTATUS status;
5606 if (!VALID_STAT(smb_fname->st)) {
5607 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5610 /* Always operate on the base_name, even if a stream was passed in. */
5611 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5612 NULL, &smb_fname->st,
5613 &smb_fname_base);
5614 if (!NT_STATUS_IS_OK(status)) {
5615 return status;
5618 if (dosmode) {
5619 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5620 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5621 } else {
5622 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5626 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5628 /* check the mode isn't different, before changing it */
5629 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5630 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5631 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5632 (unsigned int)dosmode));
5634 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5635 false)) {
5636 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5637 "%s failed (%s)\n",
5638 smb_fname_str_dbg(smb_fname_base),
5639 strerror(errno)));
5640 status = map_nt_error_from_unix(errno);
5641 goto out;
5644 status = NT_STATUS_OK;
5645 out:
5646 TALLOC_FREE(smb_fname_base);
5647 return status;
5650 /****************************************************************************
5651 Deal with setting the size from any of the setfilepathinfo functions.
5652 ****************************************************************************/
5654 static NTSTATUS smb_set_file_size(connection_struct *conn,
5655 struct smb_request *req,
5656 files_struct *fsp,
5657 const struct smb_filename *smb_fname,
5658 const SMB_STRUCT_STAT *psbuf,
5659 SMB_OFF_T size,
5660 bool fail_after_createfile)
5662 NTSTATUS status = NT_STATUS_OK;
5663 struct smb_filename *smb_fname_tmp = NULL;
5664 files_struct *new_fsp = NULL;
5666 if (!VALID_STAT(*psbuf)) {
5667 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5670 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5671 return NT_STATUS_ACCESS_DENIED;
5674 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5676 if (size == get_file_size_stat(psbuf)) {
5677 return NT_STATUS_OK;
5680 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5681 smb_fname_str_dbg(smb_fname), (double)size));
5683 if (fsp && fsp->fh->fd != -1) {
5684 /* Handle based call. */
5685 if (vfs_set_filelen(fsp, size) == -1) {
5686 return map_nt_error_from_unix(errno);
5688 trigger_write_time_update_immediate(fsp);
5689 return NT_STATUS_OK;
5692 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5693 if (!NT_STATUS_IS_OK(status)) {
5694 return status;
5697 smb_fname_tmp->st = *psbuf;
5699 status = SMB_VFS_CREATE_FILE(
5700 conn, /* conn */
5701 req, /* req */
5702 0, /* root_dir_fid */
5703 smb_fname_tmp, /* fname */
5704 FILE_WRITE_DATA, /* access_mask */
5705 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5706 FILE_SHARE_DELETE),
5707 FILE_OPEN, /* create_disposition*/
5708 0, /* create_options */
5709 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5710 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5711 0, /* allocation_size */
5712 0, /* private_flags */
5713 NULL, /* sd */
5714 NULL, /* ea_list */
5715 &new_fsp, /* result */
5716 NULL); /* pinfo */
5718 TALLOC_FREE(smb_fname_tmp);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 /* NB. We check for open_was_deferred in the caller. */
5722 return status;
5725 /* See RAW-SFILEINFO-END-OF-FILE */
5726 if (fail_after_createfile) {
5727 close_file(req, new_fsp,NORMAL_CLOSE);
5728 return NT_STATUS_INVALID_LEVEL;
5731 if (vfs_set_filelen(new_fsp, size) == -1) {
5732 status = map_nt_error_from_unix(errno);
5733 close_file(req, new_fsp,NORMAL_CLOSE);
5734 return status;
5737 trigger_write_time_update_immediate(new_fsp);
5738 close_file(req, new_fsp,NORMAL_CLOSE);
5739 return NT_STATUS_OK;
5742 /****************************************************************************
5743 Deal with SMB_INFO_SET_EA.
5744 ****************************************************************************/
5746 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5747 const char *pdata,
5748 int total_data,
5749 files_struct *fsp,
5750 const struct smb_filename *smb_fname)
5752 struct ea_list *ea_list = NULL;
5753 TALLOC_CTX *ctx = NULL;
5754 NTSTATUS status = NT_STATUS_OK;
5756 if (total_data < 10) {
5758 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5759 length. They seem to have no effect. Bug #3212. JRA */
5761 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5762 /* We're done. We only get EA info in this call. */
5763 return NT_STATUS_OK;
5766 return NT_STATUS_INVALID_PARAMETER;
5769 if (IVAL(pdata,0) > total_data) {
5770 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5771 IVAL(pdata,0), (unsigned int)total_data));
5772 return NT_STATUS_INVALID_PARAMETER;
5775 ctx = talloc_tos();
5776 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5777 if (!ea_list) {
5778 return NT_STATUS_INVALID_PARAMETER;
5781 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5782 return NT_STATUS_ACCESS_DENIED;
5785 status = set_ea(conn, fsp, smb_fname, ea_list);
5787 return status;
5790 /****************************************************************************
5791 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5792 ****************************************************************************/
5794 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5795 const char *pdata,
5796 int total_data,
5797 files_struct *fsp)
5799 struct ea_list *ea_list = NULL;
5800 NTSTATUS status;
5802 if (!fsp) {
5803 return NT_STATUS_INVALID_HANDLE;
5806 if (!lp_ea_support(SNUM(conn))) {
5807 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5808 "EA's not supported.\n",
5809 (unsigned int)total_data));
5810 return NT_STATUS_EAS_NOT_SUPPORTED;
5813 if (total_data < 10) {
5814 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5815 "too small.\n",
5816 (unsigned int)total_data));
5817 return NT_STATUS_INVALID_PARAMETER;
5820 ea_list = read_nttrans_ea_list(talloc_tos(),
5821 pdata,
5822 total_data);
5824 if (!ea_list) {
5825 return NT_STATUS_INVALID_PARAMETER;
5828 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5829 return NT_STATUS_ACCESS_DENIED;
5832 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5834 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5835 smb_fname_str_dbg(fsp->fsp_name),
5836 nt_errstr(status) ));
5838 return status;
5842 /****************************************************************************
5843 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5844 ****************************************************************************/
5846 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5847 const char *pdata,
5848 int total_data,
5849 files_struct *fsp,
5850 struct smb_filename *smb_fname)
5852 NTSTATUS status = NT_STATUS_OK;
5853 bool delete_on_close;
5854 uint32 dosmode = 0;
5856 if (total_data < 1) {
5857 return NT_STATUS_INVALID_PARAMETER;
5860 if (fsp == NULL) {
5861 return NT_STATUS_INVALID_HANDLE;
5864 delete_on_close = (CVAL(pdata,0) ? True : False);
5865 dosmode = dos_mode(conn, smb_fname);
5867 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5868 "delete_on_close = %u\n",
5869 smb_fname_str_dbg(smb_fname),
5870 (unsigned int)dosmode,
5871 (unsigned int)delete_on_close ));
5873 if (delete_on_close) {
5874 status = can_set_delete_on_close(fsp, dosmode);
5875 if (!NT_STATUS_IS_OK(status)) {
5876 return status;
5880 /* The set is across all open files on this dev/inode pair. */
5881 if (!set_delete_on_close(fsp, delete_on_close,
5882 conn->session_info->security_token,
5883 &conn->session_info->utok)) {
5884 return NT_STATUS_ACCESS_DENIED;
5886 return NT_STATUS_OK;
5889 /****************************************************************************
5890 Deal with SMB_FILE_POSITION_INFORMATION.
5891 ****************************************************************************/
5893 static NTSTATUS smb_file_position_information(connection_struct *conn,
5894 const char *pdata,
5895 int total_data,
5896 files_struct *fsp)
5898 uint64_t position_information;
5900 if (total_data < 8) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 if (fsp == NULL) {
5905 /* Ignore on pathname based set. */
5906 return NT_STATUS_OK;
5909 position_information = (uint64_t)IVAL(pdata,0);
5910 #ifdef LARGE_SMB_OFF_T
5911 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5912 #else /* LARGE_SMB_OFF_T */
5913 if (IVAL(pdata,4) != 0) {
5914 /* more than 32 bits? */
5915 return NT_STATUS_INVALID_PARAMETER;
5917 #endif /* LARGE_SMB_OFF_T */
5919 DEBUG(10,("smb_file_position_information: Set file position "
5920 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5921 (double)position_information));
5922 fsp->fh->position_information = position_information;
5923 return NT_STATUS_OK;
5926 /****************************************************************************
5927 Deal with SMB_FILE_MODE_INFORMATION.
5928 ****************************************************************************/
5930 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5931 const char *pdata,
5932 int total_data)
5934 uint32 mode;
5936 if (total_data < 4) {
5937 return NT_STATUS_INVALID_PARAMETER;
5939 mode = IVAL(pdata,0);
5940 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5941 return NT_STATUS_INVALID_PARAMETER;
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5951 struct smb_request *req,
5952 const char *pdata,
5953 int total_data,
5954 const struct smb_filename *smb_fname)
5956 char *link_target = NULL;
5957 const char *newname = smb_fname->base_name;
5958 TALLOC_CTX *ctx = talloc_tos();
5960 /* Set a symbolic link. */
5961 /* Don't allow this if follow links is false. */
5963 if (total_data == 0) {
5964 return NT_STATUS_INVALID_PARAMETER;
5967 if (!lp_symlinks(SNUM(conn))) {
5968 return NT_STATUS_ACCESS_DENIED;
5971 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5972 total_data, STR_TERMINATE);
5974 if (!link_target) {
5975 return NT_STATUS_INVALID_PARAMETER;
5978 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5979 newname, link_target ));
5981 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5982 return map_nt_error_from_unix(errno);
5985 return NT_STATUS_OK;
5988 /****************************************************************************
5989 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5990 ****************************************************************************/
5992 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5993 struct smb_request *req,
5994 const char *pdata, int total_data,
5995 struct smb_filename *smb_fname_new)
5997 char *oldname = NULL;
5998 struct smb_filename *smb_fname_old = NULL;
5999 TALLOC_CTX *ctx = talloc_tos();
6000 NTSTATUS status = NT_STATUS_OK;
6002 /* Set a hard link. */
6003 if (total_data == 0) {
6004 return NT_STATUS_INVALID_PARAMETER;
6007 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6008 total_data, STR_TERMINATE, &status);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 return status;
6013 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6014 smb_fname_str_dbg(smb_fname_new), oldname));
6016 status = filename_convert(ctx,
6017 conn,
6018 req->flags2 & FLAGS2_DFS_PATHNAMES,
6019 oldname,
6021 NULL,
6022 &smb_fname_old);
6023 if (!NT_STATUS_IS_OK(status)) {
6024 return status;
6027 return hardlink_internals(ctx, conn, req, false,
6028 smb_fname_old, smb_fname_new);
6031 /****************************************************************************
6032 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6033 ****************************************************************************/
6035 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6036 struct smb_request *req,
6037 const char *pdata,
6038 int total_data,
6039 files_struct *fsp,
6040 struct smb_filename *smb_fname_src)
6042 bool overwrite;
6043 uint32_t len;
6044 char *newname = NULL;
6045 struct smb_filename *smb_fname_dst = NULL;
6046 NTSTATUS status = NT_STATUS_OK;
6047 TALLOC_CTX *ctx = talloc_tos();
6049 if (!fsp) {
6050 return NT_STATUS_INVALID_HANDLE;
6053 if (total_data < 20) {
6054 return NT_STATUS_INVALID_PARAMETER;
6057 overwrite = (CVAL(pdata,0) ? True : False);
6058 len = IVAL(pdata,16);
6060 if (len > (total_data - 20) || (len == 0)) {
6061 return NT_STATUS_INVALID_PARAMETER;
6064 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6065 &pdata[20], len, STR_TERMINATE,
6066 &status);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 return status;
6071 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6072 newname));
6074 status = filename_convert(ctx,
6075 conn,
6076 req->flags2 & FLAGS2_DFS_PATHNAMES,
6077 newname,
6078 UCF_SAVE_LCOMP,
6079 NULL,
6080 &smb_fname_dst);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 return status;
6085 if (fsp->base_fsp) {
6086 /* newname must be a stream name. */
6087 if (newname[0] != ':') {
6088 return NT_STATUS_NOT_SUPPORTED;
6091 /* Create an smb_fname to call rename_internals_fsp() with. */
6092 status = create_synthetic_smb_fname(talloc_tos(),
6093 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6094 &smb_fname_dst);
6095 if (!NT_STATUS_IS_OK(status)) {
6096 goto out;
6100 * Set the original last component, since
6101 * rename_internals_fsp() requires it.
6103 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6104 newname);
6105 if (smb_fname_dst->original_lcomp == NULL) {
6106 status = NT_STATUS_NO_MEMORY;
6107 goto out;
6112 DEBUG(10,("smb2_file_rename_information: "
6113 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6114 fsp->fnum, fsp_str_dbg(fsp),
6115 smb_fname_str_dbg(smb_fname_dst)));
6116 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6117 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6118 overwrite);
6120 out:
6121 TALLOC_FREE(smb_fname_dst);
6122 return status;
6125 static NTSTATUS smb_file_link_information(connection_struct *conn,
6126 struct smb_request *req,
6127 const char *pdata,
6128 int total_data,
6129 files_struct *fsp,
6130 struct smb_filename *smb_fname_src)
6132 bool overwrite;
6133 uint32_t len;
6134 char *newname = NULL;
6135 struct smb_filename *smb_fname_dst = NULL;
6136 NTSTATUS status = NT_STATUS_OK;
6137 TALLOC_CTX *ctx = talloc_tos();
6139 if (!fsp) {
6140 return NT_STATUS_INVALID_HANDLE;
6143 if (total_data < 20) {
6144 return NT_STATUS_INVALID_PARAMETER;
6147 overwrite = (CVAL(pdata,0) ? true : false);
6148 len = IVAL(pdata,16);
6150 if (len > (total_data - 20) || (len == 0)) {
6151 return NT_STATUS_INVALID_PARAMETER;
6154 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6155 &pdata[20], len, STR_TERMINATE,
6156 &status);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 return status;
6161 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6162 newname));
6164 status = filename_convert(ctx,
6165 conn,
6166 req->flags2 & FLAGS2_DFS_PATHNAMES,
6167 newname,
6168 UCF_SAVE_LCOMP,
6169 NULL,
6170 &smb_fname_dst);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 return status;
6175 if (fsp->base_fsp) {
6176 /* No stream names. */
6177 return NT_STATUS_NOT_SUPPORTED;
6180 DEBUG(10,("smb_file_link_information: "
6181 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6182 fsp->fnum, fsp_str_dbg(fsp),
6183 smb_fname_str_dbg(smb_fname_dst)));
6184 status = hardlink_internals(ctx,
6185 conn,
6186 req,
6187 overwrite,
6188 fsp->fsp_name,
6189 smb_fname_dst);
6191 TALLOC_FREE(smb_fname_dst);
6192 return status;
6195 /****************************************************************************
6196 Deal with SMB_FILE_RENAME_INFORMATION.
6197 ****************************************************************************/
6199 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6200 struct smb_request *req,
6201 const char *pdata,
6202 int total_data,
6203 files_struct *fsp,
6204 struct smb_filename *smb_fname_src)
6206 bool overwrite;
6207 uint32 root_fid;
6208 uint32 len;
6209 char *newname = NULL;
6210 struct smb_filename *smb_fname_dst = NULL;
6211 bool dest_has_wcard = False;
6212 NTSTATUS status = NT_STATUS_OK;
6213 char *p;
6214 TALLOC_CTX *ctx = talloc_tos();
6216 if (total_data < 13) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 overwrite = (CVAL(pdata,0) ? True : False);
6221 root_fid = IVAL(pdata,4);
6222 len = IVAL(pdata,8);
6224 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6225 return NT_STATUS_INVALID_PARAMETER;
6228 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6229 len, 0, &status,
6230 &dest_has_wcard);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 return status;
6235 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6236 newname));
6238 status = resolve_dfspath_wcard(ctx, conn,
6239 req->flags2 & FLAGS2_DFS_PATHNAMES,
6240 newname,
6241 true,
6242 &newname,
6243 &dest_has_wcard);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 return status;
6248 /* Check the new name has no '/' characters. */
6249 if (strchr_m(newname, '/')) {
6250 return NT_STATUS_NOT_SUPPORTED;
6253 if (fsp && fsp->base_fsp) {
6254 /* newname must be a stream name. */
6255 if (newname[0] != ':') {
6256 return NT_STATUS_NOT_SUPPORTED;
6259 /* Create an smb_fname to call rename_internals_fsp() with. */
6260 status = create_synthetic_smb_fname(talloc_tos(),
6261 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6262 &smb_fname_dst);
6263 if (!NT_STATUS_IS_OK(status)) {
6264 goto out;
6268 * Set the original last component, since
6269 * rename_internals_fsp() requires it.
6271 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6272 newname);
6273 if (smb_fname_dst->original_lcomp == NULL) {
6274 status = NT_STATUS_NO_MEMORY;
6275 goto out;
6278 } else {
6280 * Build up an smb_fname_dst based on the filename passed in.
6281 * We basically just strip off the last component, and put on
6282 * the newname instead.
6284 char *base_name = NULL;
6286 /* newname must *not* be a stream name. */
6287 if (newname[0] == ':') {
6288 return NT_STATUS_NOT_SUPPORTED;
6292 * Strip off the last component (filename) of the path passed
6293 * in.
6295 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6296 if (!base_name) {
6297 return NT_STATUS_NO_MEMORY;
6299 p = strrchr_m(base_name, '/');
6300 if (p) {
6301 p[1] = '\0';
6302 } else {
6303 base_name = talloc_strdup(ctx, "");
6304 if (!base_name) {
6305 return NT_STATUS_NO_MEMORY;
6308 /* Append the new name. */
6309 base_name = talloc_asprintf_append(base_name,
6310 "%s",
6311 newname);
6312 if (!base_name) {
6313 return NT_STATUS_NO_MEMORY;
6316 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6317 (UCF_SAVE_LCOMP |
6318 (dest_has_wcard ?
6319 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6320 0)));
6322 /* If an error we expect this to be
6323 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6325 if (!NT_STATUS_IS_OK(status)) {
6326 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6327 status)) {
6328 goto out;
6330 /* Create an smb_fname to call rename_internals_fsp() */
6331 status = create_synthetic_smb_fname(ctx,
6332 base_name, NULL,
6333 NULL,
6334 &smb_fname_dst);
6335 if (!NT_STATUS_IS_OK(status)) {
6336 goto out;
6341 if (fsp) {
6342 DEBUG(10,("smb_file_rename_information: "
6343 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6344 fsp->fnum, fsp_str_dbg(fsp),
6345 smb_fname_str_dbg(smb_fname_dst)));
6346 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6347 overwrite);
6348 } else {
6349 DEBUG(10,("smb_file_rename_information: "
6350 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6351 smb_fname_str_dbg(smb_fname_src),
6352 smb_fname_str_dbg(smb_fname_dst)));
6353 status = rename_internals(ctx, conn, req, smb_fname_src,
6354 smb_fname_dst, 0, overwrite, false,
6355 dest_has_wcard,
6356 FILE_WRITE_ATTRIBUTES);
6358 out:
6359 TALLOC_FREE(smb_fname_dst);
6360 return status;
6363 /****************************************************************************
6364 Deal with SMB_SET_POSIX_ACL.
6365 ****************************************************************************/
6367 #if defined(HAVE_POSIX_ACLS)
6368 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6369 const char *pdata,
6370 int total_data,
6371 files_struct *fsp,
6372 const struct smb_filename *smb_fname)
6374 uint16 posix_acl_version;
6375 uint16 num_file_acls;
6376 uint16 num_def_acls;
6377 bool valid_file_acls = True;
6378 bool valid_def_acls = True;
6380 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6381 return NT_STATUS_INVALID_PARAMETER;
6383 posix_acl_version = SVAL(pdata,0);
6384 num_file_acls = SVAL(pdata,2);
6385 num_def_acls = SVAL(pdata,4);
6387 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6388 valid_file_acls = False;
6389 num_file_acls = 0;
6392 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6393 valid_def_acls = False;
6394 num_def_acls = 0;
6397 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6398 return NT_STATUS_INVALID_PARAMETER;
6401 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6402 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6403 return NT_STATUS_INVALID_PARAMETER;
6406 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6407 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6408 (unsigned int)num_file_acls,
6409 (unsigned int)num_def_acls));
6411 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6412 smb_fname->base_name, num_file_acls,
6413 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6414 return map_nt_error_from_unix(errno);
6417 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6418 smb_fname->base_name, &smb_fname->st, num_def_acls,
6419 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6420 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6421 return map_nt_error_from_unix(errno);
6423 return NT_STATUS_OK;
6425 #endif
6427 /****************************************************************************
6428 Deal with SMB_SET_POSIX_LOCK.
6429 ****************************************************************************/
6431 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6432 struct smb_request *req,
6433 const char *pdata,
6434 int total_data,
6435 files_struct *fsp)
6437 uint64_t count;
6438 uint64_t offset;
6439 uint64_t smblctx;
6440 bool blocking_lock = False;
6441 enum brl_type lock_type;
6443 NTSTATUS status = NT_STATUS_OK;
6445 if (fsp == NULL || fsp->fh->fd == -1) {
6446 return NT_STATUS_INVALID_HANDLE;
6449 if (total_data != POSIX_LOCK_DATA_SIZE) {
6450 return NT_STATUS_INVALID_PARAMETER;
6453 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6454 case POSIX_LOCK_TYPE_READ:
6455 lock_type = READ_LOCK;
6456 break;
6457 case POSIX_LOCK_TYPE_WRITE:
6458 /* Return the right POSIX-mappable error code for files opened read-only. */
6459 if (!fsp->can_write) {
6460 return NT_STATUS_INVALID_HANDLE;
6462 lock_type = WRITE_LOCK;
6463 break;
6464 case POSIX_LOCK_TYPE_UNLOCK:
6465 lock_type = UNLOCK_LOCK;
6466 break;
6467 default:
6468 return NT_STATUS_INVALID_PARAMETER;
6471 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6472 blocking_lock = False;
6473 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6474 blocking_lock = True;
6475 } else {
6476 return NT_STATUS_INVALID_PARAMETER;
6479 if (!lp_blocking_locks(SNUM(conn))) {
6480 blocking_lock = False;
6483 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6484 #if defined(HAVE_LONGLONG)
6485 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6486 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6487 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6488 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6489 #else /* HAVE_LONGLONG */
6490 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6491 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6492 #endif /* HAVE_LONGLONG */
6494 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6495 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6496 fsp_str_dbg(fsp),
6497 (unsigned int)lock_type,
6498 (unsigned long long)smblctx,
6499 (double)count,
6500 (double)offset ));
6502 if (lock_type == UNLOCK_LOCK) {
6503 status = do_unlock(req->sconn->msg_ctx,
6504 fsp,
6505 smblctx,
6506 count,
6507 offset,
6508 POSIX_LOCK);
6509 } else {
6510 uint64_t block_smblctx;
6512 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6513 fsp,
6514 smblctx,
6515 count,
6516 offset,
6517 lock_type,
6518 POSIX_LOCK,
6519 blocking_lock,
6520 &status,
6521 &block_smblctx,
6522 NULL);
6524 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6526 * A blocking lock was requested. Package up
6527 * this smb into a queued request and push it
6528 * onto the blocking lock queue.
6530 if(push_blocking_lock_request(br_lck,
6531 req,
6532 fsp,
6533 -1, /* infinite timeout. */
6535 smblctx,
6536 lock_type,
6537 POSIX_LOCK,
6538 offset,
6539 count,
6540 block_smblctx)) {
6541 TALLOC_FREE(br_lck);
6542 return status;
6545 TALLOC_FREE(br_lck);
6548 return status;
6551 /****************************************************************************
6552 Deal with SMB_SET_FILE_BASIC_INFO.
6553 ****************************************************************************/
6555 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6556 const char *pdata,
6557 int total_data,
6558 files_struct *fsp,
6559 const struct smb_filename *smb_fname)
6561 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6562 struct smb_file_time ft;
6563 uint32 dosmode = 0;
6564 NTSTATUS status = NT_STATUS_OK;
6566 ZERO_STRUCT(ft);
6568 if (total_data < 36) {
6569 return NT_STATUS_INVALID_PARAMETER;
6572 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6573 return NT_STATUS_ACCESS_DENIED;
6576 /* Set the attributes */
6577 dosmode = IVAL(pdata,32);
6578 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6579 if (!NT_STATUS_IS_OK(status)) {
6580 return status;
6583 /* create time */
6584 ft.create_time = interpret_long_date(pdata);
6586 /* access time */
6587 ft.atime = interpret_long_date(pdata+8);
6589 /* write time. */
6590 ft.mtime = interpret_long_date(pdata+16);
6592 /* change time. */
6593 ft.ctime = interpret_long_date(pdata+24);
6595 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6596 smb_fname_str_dbg(smb_fname)));
6598 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6599 true);
6602 /****************************************************************************
6603 Deal with SMB_INFO_STANDARD.
6604 ****************************************************************************/
6606 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6607 const char *pdata,
6608 int total_data,
6609 files_struct *fsp,
6610 const struct smb_filename *smb_fname)
6612 struct smb_file_time ft;
6614 ZERO_STRUCT(ft);
6616 if (total_data < 12) {
6617 return NT_STATUS_INVALID_PARAMETER;
6620 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6621 return NT_STATUS_ACCESS_DENIED;
6624 /* create time */
6625 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6626 /* access time */
6627 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6628 /* write time */
6629 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6631 DEBUG(10,("smb_set_info_standard: file %s\n",
6632 smb_fname_str_dbg(smb_fname)));
6634 return smb_set_file_time(conn,
6635 fsp,
6636 smb_fname,
6637 &ft,
6638 true);
6641 /****************************************************************************
6642 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6643 ****************************************************************************/
6645 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6646 struct smb_request *req,
6647 const char *pdata,
6648 int total_data,
6649 files_struct *fsp,
6650 struct smb_filename *smb_fname)
6652 uint64_t allocation_size = 0;
6653 NTSTATUS status = NT_STATUS_OK;
6654 files_struct *new_fsp = NULL;
6656 if (!VALID_STAT(smb_fname->st)) {
6657 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6660 if (total_data < 8) {
6661 return NT_STATUS_INVALID_PARAMETER;
6664 allocation_size = (uint64_t)IVAL(pdata,0);
6665 #ifdef LARGE_SMB_OFF_T
6666 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6667 #else /* LARGE_SMB_OFF_T */
6668 if (IVAL(pdata,4) != 0) {
6669 /* more than 32 bits? */
6670 return NT_STATUS_INVALID_PARAMETER;
6672 #endif /* LARGE_SMB_OFF_T */
6674 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6675 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6676 (double)allocation_size));
6678 if (allocation_size) {
6679 allocation_size = smb_roundup(conn, allocation_size);
6682 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6683 return NT_STATUS_ACCESS_DENIED;
6686 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6687 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6688 (double)allocation_size));
6690 if (fsp && fsp->fh->fd != -1) {
6691 /* Open file handle. */
6692 /* Only change if needed. */
6693 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6694 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6695 return map_nt_error_from_unix(errno);
6698 /* But always update the time. */
6700 * This is equivalent to a write. Ensure it's seen immediately
6701 * if there are no pending writes.
6703 trigger_write_time_update_immediate(fsp);
6704 return NT_STATUS_OK;
6707 /* Pathname or stat or directory file. */
6708 status = SMB_VFS_CREATE_FILE(
6709 conn, /* conn */
6710 req, /* req */
6711 0, /* root_dir_fid */
6712 smb_fname, /* fname */
6713 FILE_WRITE_DATA, /* access_mask */
6714 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6715 FILE_SHARE_DELETE),
6716 FILE_OPEN, /* create_disposition*/
6717 0, /* create_options */
6718 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6719 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6720 0, /* allocation_size */
6721 0, /* private_flags */
6722 NULL, /* sd */
6723 NULL, /* ea_list */
6724 &new_fsp, /* result */
6725 NULL); /* pinfo */
6727 if (!NT_STATUS_IS_OK(status)) {
6728 /* NB. We check for open_was_deferred in the caller. */
6729 return status;
6732 /* Only change if needed. */
6733 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6734 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6735 status = map_nt_error_from_unix(errno);
6736 close_file(req, new_fsp, NORMAL_CLOSE);
6737 return status;
6741 /* Changing the allocation size should set the last mod time. */
6743 * This is equivalent to a write. Ensure it's seen immediately
6744 * if there are no pending writes.
6746 trigger_write_time_update_immediate(new_fsp);
6748 close_file(req, new_fsp, NORMAL_CLOSE);
6749 return NT_STATUS_OK;
6752 /****************************************************************************
6753 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6754 ****************************************************************************/
6756 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6757 struct smb_request *req,
6758 const char *pdata,
6759 int total_data,
6760 files_struct *fsp,
6761 const struct smb_filename *smb_fname,
6762 bool fail_after_createfile)
6764 SMB_OFF_T size;
6766 if (total_data < 8) {
6767 return NT_STATUS_INVALID_PARAMETER;
6770 size = IVAL(pdata,0);
6771 #ifdef LARGE_SMB_OFF_T
6772 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6773 #else /* LARGE_SMB_OFF_T */
6774 if (IVAL(pdata,4) != 0) {
6775 /* more than 32 bits? */
6776 return NT_STATUS_INVALID_PARAMETER;
6778 #endif /* LARGE_SMB_OFF_T */
6779 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6780 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6781 (double)size));
6783 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6784 return NT_STATUS_ACCESS_DENIED;
6787 return smb_set_file_size(conn, req,
6788 fsp,
6789 smb_fname,
6790 &smb_fname->st,
6791 size,
6792 fail_after_createfile);
6795 /****************************************************************************
6796 Allow a UNIX info mknod.
6797 ****************************************************************************/
6799 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6800 const char *pdata,
6801 int total_data,
6802 const struct smb_filename *smb_fname)
6804 uint32 file_type = IVAL(pdata,56);
6805 #if defined(HAVE_MAKEDEV)
6806 uint32 dev_major = IVAL(pdata,60);
6807 uint32 dev_minor = IVAL(pdata,68);
6808 #endif
6809 SMB_DEV_T dev = (SMB_DEV_T)0;
6810 uint32 raw_unixmode = IVAL(pdata,84);
6811 NTSTATUS status;
6812 mode_t unixmode;
6814 if (total_data < 100) {
6815 return NT_STATUS_INVALID_PARAMETER;
6818 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6819 PERM_NEW_FILE, &unixmode);
6820 if (!NT_STATUS_IS_OK(status)) {
6821 return status;
6824 #if defined(HAVE_MAKEDEV)
6825 dev = makedev(dev_major, dev_minor);
6826 #endif
6828 switch (file_type) {
6829 #if defined(S_IFIFO)
6830 case UNIX_TYPE_FIFO:
6831 unixmode |= S_IFIFO;
6832 break;
6833 #endif
6834 #if defined(S_IFSOCK)
6835 case UNIX_TYPE_SOCKET:
6836 unixmode |= S_IFSOCK;
6837 break;
6838 #endif
6839 #if defined(S_IFCHR)
6840 case UNIX_TYPE_CHARDEV:
6841 unixmode |= S_IFCHR;
6842 break;
6843 #endif
6844 #if defined(S_IFBLK)
6845 case UNIX_TYPE_BLKDEV:
6846 unixmode |= S_IFBLK;
6847 break;
6848 #endif
6849 default:
6850 return NT_STATUS_INVALID_PARAMETER;
6853 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6854 "%.0f mode 0%o for file %s\n", (double)dev,
6855 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6857 /* Ok - do the mknod. */
6858 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6859 return map_nt_error_from_unix(errno);
6862 /* If any of the other "set" calls fail we
6863 * don't want to end up with a half-constructed mknod.
6866 if (lp_inherit_perms(SNUM(conn))) {
6867 char *parent;
6868 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6869 &parent, NULL)) {
6870 return NT_STATUS_NO_MEMORY;
6872 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6873 unixmode);
6874 TALLOC_FREE(parent);
6877 return NT_STATUS_OK;
6880 /****************************************************************************
6881 Deal with SMB_SET_FILE_UNIX_BASIC.
6882 ****************************************************************************/
6884 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6885 struct smb_request *req,
6886 const char *pdata,
6887 int total_data,
6888 files_struct *fsp,
6889 const struct smb_filename *smb_fname)
6891 struct smb_file_time ft;
6892 uint32 raw_unixmode;
6893 mode_t unixmode;
6894 SMB_OFF_T size = 0;
6895 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6896 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6897 NTSTATUS status = NT_STATUS_OK;
6898 bool delete_on_fail = False;
6899 enum perm_type ptype;
6900 files_struct *all_fsps = NULL;
6901 bool modify_mtime = true;
6902 struct file_id id;
6903 struct smb_filename *smb_fname_tmp = NULL;
6904 SMB_STRUCT_STAT sbuf;
6906 ZERO_STRUCT(ft);
6908 if (total_data < 100) {
6909 return NT_STATUS_INVALID_PARAMETER;
6912 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6913 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6914 size=IVAL(pdata,0); /* first 8 Bytes are size */
6915 #ifdef LARGE_SMB_OFF_T
6916 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6917 #else /* LARGE_SMB_OFF_T */
6918 if (IVAL(pdata,4) != 0) {
6919 /* more than 32 bits? */
6920 return NT_STATUS_INVALID_PARAMETER;
6922 #endif /* LARGE_SMB_OFF_T */
6925 ft.atime = interpret_long_date(pdata+24); /* access_time */
6926 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6927 set_owner = (uid_t)IVAL(pdata,40);
6928 set_grp = (gid_t)IVAL(pdata,48);
6929 raw_unixmode = IVAL(pdata,84);
6931 if (VALID_STAT(smb_fname->st)) {
6932 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6933 ptype = PERM_EXISTING_DIR;
6934 } else {
6935 ptype = PERM_EXISTING_FILE;
6937 } else {
6938 ptype = PERM_NEW_FILE;
6941 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6942 ptype, &unixmode);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 return status;
6947 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6948 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6949 smb_fname_str_dbg(smb_fname), (double)size,
6950 (unsigned int)set_owner, (unsigned int)set_grp,
6951 (int)raw_unixmode));
6953 sbuf = smb_fname->st;
6955 if (!VALID_STAT(sbuf)) {
6957 * The only valid use of this is to create character and block
6958 * devices, and named pipes. This is deprecated (IMHO) and
6959 * a new info level should be used for mknod. JRA.
6962 status = smb_unix_mknod(conn,
6963 pdata,
6964 total_data,
6965 smb_fname);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 return status;
6970 status = copy_smb_filename(talloc_tos(), smb_fname,
6971 &smb_fname_tmp);
6972 if (!NT_STATUS_IS_OK(status)) {
6973 return status;
6976 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6977 status = map_nt_error_from_unix(errno);
6978 TALLOC_FREE(smb_fname_tmp);
6979 SMB_VFS_UNLINK(conn, smb_fname);
6980 return status;
6983 sbuf = smb_fname_tmp->st;
6984 smb_fname = smb_fname_tmp;
6986 /* Ensure we don't try and change anything else. */
6987 raw_unixmode = SMB_MODE_NO_CHANGE;
6988 size = get_file_size_stat(&sbuf);
6989 ft.atime = sbuf.st_ex_atime;
6990 ft.mtime = sbuf.st_ex_mtime;
6992 * We continue here as we might want to change the
6993 * owner uid/gid.
6995 delete_on_fail = True;
6998 #if 1
6999 /* Horrible backwards compatibility hack as an old server bug
7000 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7001 * */
7003 if (!size) {
7004 size = get_file_size_stat(&sbuf);
7006 #endif
7009 * Deal with the UNIX specific mode set.
7012 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7013 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7014 "setting mode 0%o for file %s\n",
7015 (unsigned int)unixmode,
7016 smb_fname_str_dbg(smb_fname)));
7017 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7018 return map_nt_error_from_unix(errno);
7023 * Deal with the UNIX specific uid set.
7026 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7027 (sbuf.st_ex_uid != set_owner)) {
7028 int ret;
7030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7031 "changing owner %u for path %s\n",
7032 (unsigned int)set_owner,
7033 smb_fname_str_dbg(smb_fname)));
7035 if (S_ISLNK(sbuf.st_ex_mode)) {
7036 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7037 set_owner, (gid_t)-1);
7038 } else {
7039 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7040 set_owner, (gid_t)-1);
7043 if (ret != 0) {
7044 status = map_nt_error_from_unix(errno);
7045 if (delete_on_fail) {
7046 SMB_VFS_UNLINK(conn, smb_fname);
7048 return status;
7053 * Deal with the UNIX specific gid set.
7056 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7057 (sbuf.st_ex_gid != set_grp)) {
7058 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7059 "changing group %u for file %s\n",
7060 (unsigned int)set_owner,
7061 smb_fname_str_dbg(smb_fname)));
7062 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7063 set_grp) != 0) {
7064 status = map_nt_error_from_unix(errno);
7065 if (delete_on_fail) {
7066 SMB_VFS_UNLINK(conn, smb_fname);
7068 return status;
7072 /* Deal with any size changes. */
7074 status = smb_set_file_size(conn, req,
7075 fsp,
7076 smb_fname,
7077 &sbuf,
7078 size,
7079 false);
7080 if (!NT_STATUS_IS_OK(status)) {
7081 return status;
7084 /* Deal with any time changes. */
7085 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7086 /* No change, don't cancel anything. */
7087 return status;
7090 id = vfs_file_id_from_sbuf(conn, &sbuf);
7091 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7092 all_fsps = file_find_di_next(all_fsps)) {
7094 * We're setting the time explicitly for UNIX.
7095 * Cancel any pending changes over all handles.
7097 all_fsps->update_write_time_on_close = false;
7098 TALLOC_FREE(all_fsps->update_write_time_event);
7102 * Override the "setting_write_time"
7103 * parameter here as it almost does what
7104 * we need. Just remember if we modified
7105 * mtime and send the notify ourselves.
7107 if (null_timespec(ft.mtime)) {
7108 modify_mtime = false;
7111 status = smb_set_file_time(conn,
7112 fsp,
7113 smb_fname,
7114 &ft,
7115 false);
7116 if (modify_mtime) {
7117 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7118 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7120 return status;
7123 /****************************************************************************
7124 Deal with SMB_SET_FILE_UNIX_INFO2.
7125 ****************************************************************************/
7127 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7128 struct smb_request *req,
7129 const char *pdata,
7130 int total_data,
7131 files_struct *fsp,
7132 const struct smb_filename *smb_fname)
7134 NTSTATUS status;
7135 uint32 smb_fflags;
7136 uint32 smb_fmask;
7138 if (total_data < 116) {
7139 return NT_STATUS_INVALID_PARAMETER;
7142 /* Start by setting all the fields that are common between UNIX_BASIC
7143 * and UNIX_INFO2.
7145 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7146 fsp, smb_fname);
7147 if (!NT_STATUS_IS_OK(status)) {
7148 return status;
7151 smb_fflags = IVAL(pdata, 108);
7152 smb_fmask = IVAL(pdata, 112);
7154 /* NB: We should only attempt to alter the file flags if the client
7155 * sends a non-zero mask.
7157 if (smb_fmask != 0) {
7158 int stat_fflags = 0;
7160 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7161 smb_fmask, &stat_fflags)) {
7162 /* Client asked to alter a flag we don't understand. */
7163 return NT_STATUS_INVALID_PARAMETER;
7166 if (fsp && fsp->fh->fd != -1) {
7167 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7168 return NT_STATUS_NOT_SUPPORTED;
7169 } else {
7170 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7171 stat_fflags) != 0) {
7172 return map_nt_error_from_unix(errno);
7177 /* XXX: need to add support for changing the create_time here. You
7178 * can do this for paths on Darwin with setattrlist(2). The right way
7179 * to hook this up is probably by extending the VFS utimes interface.
7182 return NT_STATUS_OK;
7185 /****************************************************************************
7186 Create a directory with POSIX semantics.
7187 ****************************************************************************/
7189 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7190 struct smb_request *req,
7191 char **ppdata,
7192 int total_data,
7193 struct smb_filename *smb_fname,
7194 int *pdata_return_size)
7196 NTSTATUS status = NT_STATUS_OK;
7197 uint32 raw_unixmode = 0;
7198 uint32 mod_unixmode = 0;
7199 mode_t unixmode = (mode_t)0;
7200 files_struct *fsp = NULL;
7201 uint16 info_level_return = 0;
7202 int info;
7203 char *pdata = *ppdata;
7205 if (total_data < 18) {
7206 return NT_STATUS_INVALID_PARAMETER;
7209 raw_unixmode = IVAL(pdata,8);
7210 /* Next 4 bytes are not yet defined. */
7212 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7213 PERM_NEW_DIR, &unixmode);
7214 if (!NT_STATUS_IS_OK(status)) {
7215 return status;
7218 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7220 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7221 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7223 status = SMB_VFS_CREATE_FILE(
7224 conn, /* conn */
7225 req, /* req */
7226 0, /* root_dir_fid */
7227 smb_fname, /* fname */
7228 FILE_READ_ATTRIBUTES, /* access_mask */
7229 FILE_SHARE_NONE, /* share_access */
7230 FILE_CREATE, /* create_disposition*/
7231 FILE_DIRECTORY_FILE, /* create_options */
7232 mod_unixmode, /* file_attributes */
7233 0, /* oplock_request */
7234 0, /* allocation_size */
7235 0, /* private_flags */
7236 NULL, /* sd */
7237 NULL, /* ea_list */
7238 &fsp, /* result */
7239 &info); /* pinfo */
7241 if (NT_STATUS_IS_OK(status)) {
7242 close_file(req, fsp, NORMAL_CLOSE);
7245 info_level_return = SVAL(pdata,16);
7247 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7248 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7249 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7250 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7251 } else {
7252 *pdata_return_size = 12;
7255 /* Realloc the data size */
7256 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7257 if (*ppdata == NULL) {
7258 *pdata_return_size = 0;
7259 return NT_STATUS_NO_MEMORY;
7261 pdata = *ppdata;
7263 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7264 SSVAL(pdata,2,0); /* No fnum. */
7265 SIVAL(pdata,4,info); /* Was directory created. */
7267 switch (info_level_return) {
7268 case SMB_QUERY_FILE_UNIX_BASIC:
7269 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7270 SSVAL(pdata,10,0); /* Padding. */
7271 store_file_unix_basic(conn, pdata + 12, fsp,
7272 &smb_fname->st);
7273 break;
7274 case SMB_QUERY_FILE_UNIX_INFO2:
7275 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7276 SSVAL(pdata,10,0); /* Padding. */
7277 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7278 &smb_fname->st);
7279 break;
7280 default:
7281 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7282 SSVAL(pdata,10,0); /* Padding. */
7283 break;
7286 return status;
7289 /****************************************************************************
7290 Open/Create a file with POSIX semantics.
7291 ****************************************************************************/
7293 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7294 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7296 static NTSTATUS smb_posix_open(connection_struct *conn,
7297 struct smb_request *req,
7298 char **ppdata,
7299 int total_data,
7300 struct smb_filename *smb_fname,
7301 int *pdata_return_size)
7303 bool extended_oplock_granted = False;
7304 char *pdata = *ppdata;
7305 uint32 flags = 0;
7306 uint32 wire_open_mode = 0;
7307 uint32 raw_unixmode = 0;
7308 uint32 mod_unixmode = 0;
7309 uint32 create_disp = 0;
7310 uint32 access_mask = 0;
7311 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7312 NTSTATUS status = NT_STATUS_OK;
7313 mode_t unixmode = (mode_t)0;
7314 files_struct *fsp = NULL;
7315 int oplock_request = 0;
7316 int info = 0;
7317 uint16 info_level_return = 0;
7319 if (total_data < 18) {
7320 return NT_STATUS_INVALID_PARAMETER;
7323 flags = IVAL(pdata,0);
7324 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7325 if (oplock_request) {
7326 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7329 wire_open_mode = IVAL(pdata,4);
7331 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7332 return smb_posix_mkdir(conn, req,
7333 ppdata,
7334 total_data,
7335 smb_fname,
7336 pdata_return_size);
7339 switch (wire_open_mode & SMB_ACCMODE) {
7340 case SMB_O_RDONLY:
7341 access_mask = SMB_O_RDONLY_MAPPING;
7342 break;
7343 case SMB_O_WRONLY:
7344 access_mask = SMB_O_WRONLY_MAPPING;
7345 break;
7346 case SMB_O_RDWR:
7347 access_mask = (SMB_O_RDONLY_MAPPING|
7348 SMB_O_WRONLY_MAPPING);
7349 break;
7350 default:
7351 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7352 (unsigned int)wire_open_mode ));
7353 return NT_STATUS_INVALID_PARAMETER;
7356 wire_open_mode &= ~SMB_ACCMODE;
7358 /* First take care of O_CREAT|O_EXCL interactions. */
7359 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7360 case (SMB_O_CREAT | SMB_O_EXCL):
7361 /* File exists fail. File not exist create. */
7362 create_disp = FILE_CREATE;
7363 break;
7364 case SMB_O_CREAT:
7365 /* File exists open. File not exist create. */
7366 create_disp = FILE_OPEN_IF;
7367 break;
7368 case SMB_O_EXCL:
7369 /* O_EXCL on its own without O_CREAT is undefined.
7370 We deliberately ignore it as some versions of
7371 Linux CIFSFS can send a bare O_EXCL on the
7372 wire which other filesystems in the kernel
7373 ignore. See bug 9519 for details. */
7375 /* Fallthrough. */
7377 case 0:
7378 /* File exists open. File not exist fail. */
7379 create_disp = FILE_OPEN;
7380 break;
7381 default:
7382 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7383 (unsigned int)wire_open_mode ));
7384 return NT_STATUS_INVALID_PARAMETER;
7387 /* Next factor in the effects of O_TRUNC. */
7388 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7390 if (wire_open_mode & SMB_O_TRUNC) {
7391 switch (create_disp) {
7392 case FILE_CREATE:
7393 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7394 /* Leave create_disp alone as
7395 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7397 /* File exists fail. File not exist create. */
7398 break;
7399 case FILE_OPEN_IF:
7400 /* SMB_O_CREAT | SMB_O_TRUNC */
7401 /* File exists overwrite. File not exist create. */
7402 create_disp = FILE_OVERWRITE_IF;
7403 break;
7404 case FILE_OPEN:
7405 /* SMB_O_TRUNC */
7406 /* File exists overwrite. File not exist fail. */
7407 create_disp = FILE_OVERWRITE;
7408 break;
7409 default:
7410 /* Cannot get here. */
7411 smb_panic("smb_posix_open: logic error");
7412 return NT_STATUS_INVALID_PARAMETER;
7416 raw_unixmode = IVAL(pdata,8);
7417 /* Next 4 bytes are not yet defined. */
7419 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7420 (VALID_STAT(smb_fname->st) ?
7421 PERM_EXISTING_FILE : PERM_NEW_FILE),
7422 &unixmode);
7424 if (!NT_STATUS_IS_OK(status)) {
7425 return status;
7428 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7430 if (wire_open_mode & SMB_O_SYNC) {
7431 create_options |= FILE_WRITE_THROUGH;
7433 if (wire_open_mode & SMB_O_APPEND) {
7434 access_mask |= FILE_APPEND_DATA;
7436 if (wire_open_mode & SMB_O_DIRECT) {
7437 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7440 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7441 VALID_STAT_OF_DIR(smb_fname->st)) {
7442 if (access_mask != SMB_O_RDONLY_MAPPING) {
7443 return NT_STATUS_FILE_IS_A_DIRECTORY;
7445 create_options &= ~FILE_NON_DIRECTORY_FILE;
7446 create_options |= FILE_DIRECTORY_FILE;
7449 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7450 smb_fname_str_dbg(smb_fname),
7451 (unsigned int)wire_open_mode,
7452 (unsigned int)unixmode ));
7454 status = SMB_VFS_CREATE_FILE(
7455 conn, /* conn */
7456 req, /* req */
7457 0, /* root_dir_fid */
7458 smb_fname, /* fname */
7459 access_mask, /* access_mask */
7460 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7461 FILE_SHARE_DELETE),
7462 create_disp, /* create_disposition*/
7463 create_options, /* create_options */
7464 mod_unixmode, /* file_attributes */
7465 oplock_request, /* oplock_request */
7466 0, /* allocation_size */
7467 0, /* private_flags */
7468 NULL, /* sd */
7469 NULL, /* ea_list */
7470 &fsp, /* result */
7471 &info); /* pinfo */
7473 if (!NT_STATUS_IS_OK(status)) {
7474 return status;
7477 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7478 extended_oplock_granted = True;
7481 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7482 extended_oplock_granted = True;
7485 info_level_return = SVAL(pdata,16);
7487 /* Allocate the correct return size. */
7489 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7490 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7491 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7492 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7493 } else {
7494 *pdata_return_size = 12;
7497 /* Realloc the data size */
7498 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7499 if (*ppdata == NULL) {
7500 close_file(req, fsp, ERROR_CLOSE);
7501 *pdata_return_size = 0;
7502 return NT_STATUS_NO_MEMORY;
7504 pdata = *ppdata;
7506 if (extended_oplock_granted) {
7507 if (flags & REQUEST_BATCH_OPLOCK) {
7508 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7509 } else {
7510 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7512 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7513 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7514 } else {
7515 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7518 SSVAL(pdata,2,fsp->fnum);
7519 SIVAL(pdata,4,info); /* Was file created etc. */
7521 switch (info_level_return) {
7522 case SMB_QUERY_FILE_UNIX_BASIC:
7523 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7524 SSVAL(pdata,10,0); /* padding. */
7525 store_file_unix_basic(conn, pdata + 12, fsp,
7526 &smb_fname->st);
7527 break;
7528 case SMB_QUERY_FILE_UNIX_INFO2:
7529 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7530 SSVAL(pdata,10,0); /* padding. */
7531 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7532 &smb_fname->st);
7533 break;
7534 default:
7535 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7536 SSVAL(pdata,10,0); /* padding. */
7537 break;
7539 return NT_STATUS_OK;
7542 /****************************************************************************
7543 Delete a file with POSIX semantics.
7544 ****************************************************************************/
7546 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7547 struct smb_request *req,
7548 const char *pdata,
7549 int total_data,
7550 struct smb_filename *smb_fname)
7552 NTSTATUS status = NT_STATUS_OK;
7553 files_struct *fsp = NULL;
7554 uint16 flags = 0;
7555 char del = 1;
7556 int info = 0;
7557 int create_options = 0;
7558 int i;
7559 struct share_mode_lock *lck = NULL;
7561 if (total_data < 2) {
7562 return NT_STATUS_INVALID_PARAMETER;
7565 flags = SVAL(pdata,0);
7567 if (!VALID_STAT(smb_fname->st)) {
7568 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7571 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7572 !VALID_STAT_OF_DIR(smb_fname->st)) {
7573 return NT_STATUS_NOT_A_DIRECTORY;
7576 DEBUG(10,("smb_posix_unlink: %s %s\n",
7577 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7578 smb_fname_str_dbg(smb_fname)));
7580 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7581 create_options |= FILE_DIRECTORY_FILE;
7584 status = SMB_VFS_CREATE_FILE(
7585 conn, /* conn */
7586 req, /* req */
7587 0, /* root_dir_fid */
7588 smb_fname, /* fname */
7589 DELETE_ACCESS, /* access_mask */
7590 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7591 FILE_SHARE_DELETE),
7592 FILE_OPEN, /* create_disposition*/
7593 create_options, /* create_options */
7594 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7595 0, /* oplock_request */
7596 0, /* allocation_size */
7597 0, /* private_flags */
7598 NULL, /* sd */
7599 NULL, /* ea_list */
7600 &fsp, /* result */
7601 &info); /* pinfo */
7603 if (!NT_STATUS_IS_OK(status)) {
7604 return status;
7608 * Don't lie to client. If we can't really delete due to
7609 * non-POSIX opens return SHARING_VIOLATION.
7612 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7613 NULL);
7614 if (lck == NULL) {
7615 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7616 "lock for file %s\n", fsp_str_dbg(fsp)));
7617 close_file(req, fsp, NORMAL_CLOSE);
7618 return NT_STATUS_INVALID_PARAMETER;
7622 * See if others still have the file open. If this is the case, then
7623 * don't delete. If all opens are POSIX delete we can set the delete
7624 * on close disposition.
7626 for (i=0; i<lck->num_share_modes; i++) {
7627 struct share_mode_entry *e = &lck->share_modes[i];
7628 if (is_valid_share_mode_entry(e)) {
7629 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7630 continue;
7632 /* Fail with sharing violation. */
7633 TALLOC_FREE(lck);
7634 close_file(req, fsp, NORMAL_CLOSE);
7635 return NT_STATUS_SHARING_VIOLATION;
7640 * Set the delete on close.
7642 status = smb_set_file_disposition_info(conn,
7643 &del,
7645 fsp,
7646 smb_fname);
7648 TALLOC_FREE(lck);
7650 if (!NT_STATUS_IS_OK(status)) {
7651 close_file(req, fsp, NORMAL_CLOSE);
7652 return status;
7654 return close_file(req, fsp, NORMAL_CLOSE);
7657 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7658 struct smb_request *req,
7659 TALLOC_CTX *mem_ctx,
7660 uint16_t info_level,
7661 files_struct *fsp,
7662 struct smb_filename *smb_fname,
7663 char **ppdata, int total_data,
7664 int *ret_data_size)
7666 char *pdata = *ppdata;
7667 NTSTATUS status = NT_STATUS_OK;
7668 int data_return_size = 0;
7670 *ret_data_size = 0;
7672 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7673 return NT_STATUS_INVALID_LEVEL;
7676 if (!CAN_WRITE(conn)) {
7677 /* Allow POSIX opens. The open path will deny
7678 * any non-readonly opens. */
7679 if (info_level != SMB_POSIX_PATH_OPEN) {
7680 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7684 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7685 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7686 fsp ? fsp->fnum : -1, info_level, total_data));
7688 switch (info_level) {
7690 case SMB_INFO_STANDARD:
7692 status = smb_set_info_standard(conn,
7693 pdata,
7694 total_data,
7695 fsp,
7696 smb_fname);
7697 break;
7700 case SMB_INFO_SET_EA:
7702 status = smb_info_set_ea(conn,
7703 pdata,
7704 total_data,
7705 fsp,
7706 smb_fname);
7707 break;
7710 case SMB_SET_FILE_BASIC_INFO:
7711 case SMB_FILE_BASIC_INFORMATION:
7713 status = smb_set_file_basic_info(conn,
7714 pdata,
7715 total_data,
7716 fsp,
7717 smb_fname);
7718 break;
7721 case SMB_FILE_ALLOCATION_INFORMATION:
7722 case SMB_SET_FILE_ALLOCATION_INFO:
7724 status = smb_set_file_allocation_info(conn, req,
7725 pdata,
7726 total_data,
7727 fsp,
7728 smb_fname);
7729 break;
7732 case SMB_FILE_END_OF_FILE_INFORMATION:
7733 case SMB_SET_FILE_END_OF_FILE_INFO:
7736 * XP/Win7 both fail after the createfile with
7737 * SMB_SET_FILE_END_OF_FILE_INFO but not
7738 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7739 * The level is known here, so pass it down
7740 * appropriately.
7742 bool should_fail =
7743 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7745 status = smb_set_file_end_of_file_info(conn, req,
7746 pdata,
7747 total_data,
7748 fsp,
7749 smb_fname,
7750 should_fail);
7751 break;
7754 case SMB_FILE_DISPOSITION_INFORMATION:
7755 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7757 #if 0
7758 /* JRA - We used to just ignore this on a path ?
7759 * Shouldn't this be invalid level on a pathname
7760 * based call ?
7762 if (tran_call != TRANSACT2_SETFILEINFO) {
7763 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7765 #endif
7766 status = smb_set_file_disposition_info(conn,
7767 pdata,
7768 total_data,
7769 fsp,
7770 smb_fname);
7771 break;
7774 case SMB_FILE_POSITION_INFORMATION:
7776 status = smb_file_position_information(conn,
7777 pdata,
7778 total_data,
7779 fsp);
7780 break;
7783 case SMB_FILE_FULL_EA_INFORMATION:
7785 status = smb_set_file_full_ea_info(conn,
7786 pdata,
7787 total_data,
7788 fsp);
7789 break;
7792 /* From tridge Samba4 :
7793 * MODE_INFORMATION in setfileinfo (I have no
7794 * idea what "mode information" on a file is - it takes a value of 0,
7795 * 2, 4 or 6. What could it be?).
7798 case SMB_FILE_MODE_INFORMATION:
7800 status = smb_file_mode_information(conn,
7801 pdata,
7802 total_data);
7803 break;
7807 * CIFS UNIX extensions.
7810 case SMB_SET_FILE_UNIX_BASIC:
7812 status = smb_set_file_unix_basic(conn, req,
7813 pdata,
7814 total_data,
7815 fsp,
7816 smb_fname);
7817 break;
7820 case SMB_SET_FILE_UNIX_INFO2:
7822 status = smb_set_file_unix_info2(conn, req,
7823 pdata,
7824 total_data,
7825 fsp,
7826 smb_fname);
7827 break;
7830 case SMB_SET_FILE_UNIX_LINK:
7832 if (fsp) {
7833 /* We must have a pathname for this. */
7834 return NT_STATUS_INVALID_LEVEL;
7836 status = smb_set_file_unix_link(conn, req, pdata,
7837 total_data, smb_fname);
7838 break;
7841 case SMB_SET_FILE_UNIX_HLINK:
7843 if (fsp) {
7844 /* We must have a pathname for this. */
7845 return NT_STATUS_INVALID_LEVEL;
7847 status = smb_set_file_unix_hlink(conn, req,
7848 pdata, total_data,
7849 smb_fname);
7850 break;
7853 case SMB_FILE_RENAME_INFORMATION:
7855 status = smb_file_rename_information(conn, req,
7856 pdata, total_data,
7857 fsp, smb_fname);
7858 break;
7861 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7863 /* SMB2 rename information. */
7864 status = smb2_file_rename_information(conn, req,
7865 pdata, total_data,
7866 fsp, smb_fname);
7867 break;
7870 case SMB_FILE_LINK_INFORMATION:
7872 status = smb_file_link_information(conn, req,
7873 pdata, total_data,
7874 fsp, smb_fname);
7875 break;
7878 #if defined(HAVE_POSIX_ACLS)
7879 case SMB_SET_POSIX_ACL:
7881 status = smb_set_posix_acl(conn,
7882 pdata,
7883 total_data,
7884 fsp,
7885 smb_fname);
7886 break;
7888 #endif
7890 case SMB_SET_POSIX_LOCK:
7892 if (!fsp) {
7893 return NT_STATUS_INVALID_LEVEL;
7895 status = smb_set_posix_lock(conn, req,
7896 pdata, total_data, fsp);
7897 break;
7900 case SMB_POSIX_PATH_OPEN:
7902 if (fsp) {
7903 /* We must have a pathname for this. */
7904 return NT_STATUS_INVALID_LEVEL;
7907 status = smb_posix_open(conn, req,
7908 ppdata,
7909 total_data,
7910 smb_fname,
7911 &data_return_size);
7912 break;
7915 case SMB_POSIX_PATH_UNLINK:
7917 if (fsp) {
7918 /* We must have a pathname for this. */
7919 return NT_STATUS_INVALID_LEVEL;
7922 status = smb_posix_unlink(conn, req,
7923 pdata,
7924 total_data,
7925 smb_fname);
7926 break;
7929 default:
7930 return NT_STATUS_INVALID_LEVEL;
7933 if (!NT_STATUS_IS_OK(status)) {
7934 return status;
7937 *ret_data_size = data_return_size;
7938 return NT_STATUS_OK;
7941 /****************************************************************************
7942 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7943 ****************************************************************************/
7945 static void call_trans2setfilepathinfo(connection_struct *conn,
7946 struct smb_request *req,
7947 unsigned int tran_call,
7948 char **pparams, int total_params,
7949 char **ppdata, int total_data,
7950 unsigned int max_data_bytes)
7952 char *params = *pparams;
7953 char *pdata = *ppdata;
7954 uint16 info_level;
7955 struct smb_filename *smb_fname = NULL;
7956 files_struct *fsp = NULL;
7957 NTSTATUS status = NT_STATUS_OK;
7958 int data_return_size = 0;
7960 if (!params) {
7961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7962 return;
7965 if (tran_call == TRANSACT2_SETFILEINFO) {
7966 if (total_params < 4) {
7967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7968 return;
7971 fsp = file_fsp(req, SVAL(params,0));
7972 /* Basic check for non-null fsp. */
7973 if (!check_fsp_open(conn, req, fsp)) {
7974 return;
7976 info_level = SVAL(params,2);
7978 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7979 &smb_fname);
7980 if (!NT_STATUS_IS_OK(status)) {
7981 reply_nterror(req, status);
7982 return;
7985 if(fsp->fh->fd == -1) {
7987 * This is actually a SETFILEINFO on a directory
7988 * handle (returned from an NT SMB). NT5.0 seems
7989 * to do this call. JRA.
7991 if (INFO_LEVEL_IS_UNIX(info_level)) {
7992 /* Always do lstat for UNIX calls. */
7993 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7994 DEBUG(3,("call_trans2setfilepathinfo: "
7995 "SMB_VFS_LSTAT of %s failed "
7996 "(%s)\n",
7997 smb_fname_str_dbg(smb_fname),
7998 strerror(errno)));
7999 reply_nterror(req, map_nt_error_from_unix(errno));
8000 return;
8002 } else {
8003 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8004 DEBUG(3,("call_trans2setfilepathinfo: "
8005 "fileinfo of %s failed (%s)\n",
8006 smb_fname_str_dbg(smb_fname),
8007 strerror(errno)));
8008 reply_nterror(req, map_nt_error_from_unix(errno));
8009 return;
8012 } else if (fsp->print_file) {
8014 * Doing a DELETE_ON_CLOSE should cancel a print job.
8016 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8017 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8019 DEBUG(3,("call_trans2setfilepathinfo: "
8020 "Cancelling print job (%s)\n",
8021 fsp_str_dbg(fsp)));
8023 SSVAL(params,0,0);
8024 send_trans2_replies(conn, req, params, 2,
8025 *ppdata, 0,
8026 max_data_bytes);
8027 return;
8028 } else {
8029 reply_nterror(req,
8030 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8031 return;
8033 } else {
8035 * Original code - this is an open file.
8037 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8038 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8039 "of fnum %d failed (%s)\n", fsp->fnum,
8040 strerror(errno)));
8041 reply_nterror(req, map_nt_error_from_unix(errno));
8042 return;
8045 } else {
8046 char *fname = NULL;
8047 uint32_t ucf_flags = 0;
8049 /* set path info */
8050 if (total_params < 7) {
8051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8052 return;
8055 info_level = SVAL(params,0);
8056 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8057 total_params - 6, STR_TERMINATE,
8058 &status);
8059 if (!NT_STATUS_IS_OK(status)) {
8060 reply_nterror(req, status);
8061 return;
8064 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8065 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8066 info_level == SMB_FILE_RENAME_INFORMATION ||
8067 info_level == SMB_POSIX_PATH_UNLINK) {
8068 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8071 status = filename_convert(req, conn,
8072 req->flags2 & FLAGS2_DFS_PATHNAMES,
8073 fname,
8074 ucf_flags,
8075 NULL,
8076 &smb_fname);
8077 if (!NT_STATUS_IS_OK(status)) {
8078 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8079 reply_botherror(req,
8080 NT_STATUS_PATH_NOT_COVERED,
8081 ERRSRV, ERRbadpath);
8082 return;
8084 reply_nterror(req, status);
8085 return;
8088 if (INFO_LEVEL_IS_UNIX(info_level)) {
8090 * For CIFS UNIX extensions the target name may not exist.
8093 /* Always do lstat for UNIX calls. */
8094 SMB_VFS_LSTAT(conn, smb_fname);
8096 } else if (!VALID_STAT(smb_fname->st) &&
8097 SMB_VFS_STAT(conn, smb_fname)) {
8098 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8099 "%s failed (%s)\n",
8100 smb_fname_str_dbg(smb_fname),
8101 strerror(errno)));
8102 reply_nterror(req, map_nt_error_from_unix(errno));
8103 return;
8107 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8108 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8109 fsp ? fsp->fnum : -1, info_level,total_data));
8111 /* Realloc the parameter size */
8112 *pparams = (char *)SMB_REALLOC(*pparams,2);
8113 if (*pparams == NULL) {
8114 reply_nterror(req, NT_STATUS_NO_MEMORY);
8115 return;
8117 params = *pparams;
8119 SSVAL(params,0,0);
8121 status = smbd_do_setfilepathinfo(conn, req, req,
8122 info_level,
8123 fsp,
8124 smb_fname,
8125 ppdata, total_data,
8126 &data_return_size);
8127 if (!NT_STATUS_IS_OK(status)) {
8128 if (open_was_deferred(req->mid)) {
8129 /* We have re-scheduled this call. */
8130 return;
8132 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8133 /* We have re-scheduled this call. */
8134 return;
8136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8137 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8138 ERRSRV, ERRbadpath);
8139 return;
8141 if (info_level == SMB_POSIX_PATH_OPEN) {
8142 reply_openerror(req, status);
8143 return;
8146 reply_nterror(req, status);
8147 return;
8150 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8151 max_data_bytes);
8153 return;
8156 /****************************************************************************
8157 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8158 ****************************************************************************/
8160 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8161 char **pparams, int total_params,
8162 char **ppdata, int total_data,
8163 unsigned int max_data_bytes)
8165 struct smb_filename *smb_dname = NULL;
8166 char *params = *pparams;
8167 char *pdata = *ppdata;
8168 char *directory = NULL;
8169 NTSTATUS status = NT_STATUS_OK;
8170 struct ea_list *ea_list = NULL;
8171 TALLOC_CTX *ctx = talloc_tos();
8173 if (!CAN_WRITE(conn)) {
8174 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8175 return;
8178 if (total_params < 5) {
8179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8180 return;
8183 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8184 total_params - 4, STR_TERMINATE,
8185 &status);
8186 if (!NT_STATUS_IS_OK(status)) {
8187 reply_nterror(req, status);
8188 return;
8191 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8193 status = filename_convert(ctx,
8194 conn,
8195 req->flags2 & FLAGS2_DFS_PATHNAMES,
8196 directory,
8198 NULL,
8199 &smb_dname);
8201 if (!NT_STATUS_IS_OK(status)) {
8202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8203 reply_botherror(req,
8204 NT_STATUS_PATH_NOT_COVERED,
8205 ERRSRV, ERRbadpath);
8206 return;
8208 reply_nterror(req, status);
8209 return;
8213 * OS/2 workplace shell seems to send SET_EA requests of "null"
8214 * length (4 bytes containing IVAL 4).
8215 * They seem to have no effect. Bug #3212. JRA.
8218 if (total_data && (total_data != 4)) {
8219 /* Any data in this call is an EA list. */
8220 if (total_data < 10) {
8221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8222 goto out;
8225 if (IVAL(pdata,0) > total_data) {
8226 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8227 IVAL(pdata,0), (unsigned int)total_data));
8228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8229 goto out;
8232 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8233 total_data - 4);
8234 if (!ea_list) {
8235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8236 goto out;
8239 if (!lp_ea_support(SNUM(conn))) {
8240 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8241 goto out;
8244 /* If total_data == 4 Windows doesn't care what values
8245 * are placed in that field, it just ignores them.
8246 * The System i QNTC IBM SMB client puts bad values here,
8247 * so ignore them. */
8249 status = create_directory(conn, req, smb_dname);
8251 if (!NT_STATUS_IS_OK(status)) {
8252 reply_nterror(req, status);
8253 goto out;
8256 /* Try and set any given EA. */
8257 if (ea_list) {
8258 status = set_ea(conn, NULL, smb_dname, ea_list);
8259 if (!NT_STATUS_IS_OK(status)) {
8260 reply_nterror(req, status);
8261 goto out;
8265 /* Realloc the parameter and data sizes */
8266 *pparams = (char *)SMB_REALLOC(*pparams,2);
8267 if(*pparams == NULL) {
8268 reply_nterror(req, NT_STATUS_NO_MEMORY);
8269 goto out;
8271 params = *pparams;
8273 SSVAL(params,0,0);
8275 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8277 out:
8278 TALLOC_FREE(smb_dname);
8279 return;
8282 /****************************************************************************
8283 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8284 We don't actually do this - we just send a null response.
8285 ****************************************************************************/
8287 static void call_trans2findnotifyfirst(connection_struct *conn,
8288 struct smb_request *req,
8289 char **pparams, int total_params,
8290 char **ppdata, int total_data,
8291 unsigned int max_data_bytes)
8293 char *params = *pparams;
8294 uint16 info_level;
8296 if (total_params < 6) {
8297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8298 return;
8301 info_level = SVAL(params,4);
8302 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8304 switch (info_level) {
8305 case 1:
8306 case 2:
8307 break;
8308 default:
8309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8310 return;
8313 /* Realloc the parameter and data sizes */
8314 *pparams = (char *)SMB_REALLOC(*pparams,6);
8315 if (*pparams == NULL) {
8316 reply_nterror(req, NT_STATUS_NO_MEMORY);
8317 return;
8319 params = *pparams;
8321 SSVAL(params,0,fnf_handle);
8322 SSVAL(params,2,0); /* No changes */
8323 SSVAL(params,4,0); /* No EA errors */
8325 fnf_handle++;
8327 if(fnf_handle == 0)
8328 fnf_handle = 257;
8330 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8332 return;
8335 /****************************************************************************
8336 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8337 changes). Currently this does nothing.
8338 ****************************************************************************/
8340 static void call_trans2findnotifynext(connection_struct *conn,
8341 struct smb_request *req,
8342 char **pparams, int total_params,
8343 char **ppdata, int total_data,
8344 unsigned int max_data_bytes)
8346 char *params = *pparams;
8348 DEBUG(3,("call_trans2findnotifynext\n"));
8350 /* Realloc the parameter and data sizes */
8351 *pparams = (char *)SMB_REALLOC(*pparams,4);
8352 if (*pparams == NULL) {
8353 reply_nterror(req, NT_STATUS_NO_MEMORY);
8354 return;
8356 params = *pparams;
8358 SSVAL(params,0,0); /* No changes */
8359 SSVAL(params,2,0); /* No EA errors */
8361 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8363 return;
8366 /****************************************************************************
8367 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8368 ****************************************************************************/
8370 static void call_trans2getdfsreferral(connection_struct *conn,
8371 struct smb_request *req,
8372 char **pparams, int total_params,
8373 char **ppdata, int total_data,
8374 unsigned int max_data_bytes)
8376 char *params = *pparams;
8377 char *pathname = NULL;
8378 int reply_size = 0;
8379 int max_referral_level;
8380 NTSTATUS status = NT_STATUS_OK;
8381 TALLOC_CTX *ctx = talloc_tos();
8383 DEBUG(10,("call_trans2getdfsreferral\n"));
8385 if (total_params < 3) {
8386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8387 return;
8390 max_referral_level = SVAL(params,0);
8392 if(!lp_host_msdfs()) {
8393 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8394 return;
8397 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8398 total_params - 2, STR_TERMINATE);
8399 if (!pathname) {
8400 reply_nterror(req, NT_STATUS_NOT_FOUND);
8401 return;
8403 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8404 ppdata,&status)) < 0) {
8405 reply_nterror(req, status);
8406 return;
8409 SSVAL(req->inbuf, smb_flg2,
8410 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8411 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8413 return;
8416 #define LMCAT_SPL 0x53
8417 #define LMFUNC_GETJOBID 0x60
8419 /****************************************************************************
8420 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8421 ****************************************************************************/
8423 static void call_trans2ioctl(connection_struct *conn,
8424 struct smb_request *req,
8425 char **pparams, int total_params,
8426 char **ppdata, int total_data,
8427 unsigned int max_data_bytes)
8429 char *pdata = *ppdata;
8430 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8432 /* check for an invalid fid before proceeding */
8434 if (!fsp) {
8435 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8436 return;
8439 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8440 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8441 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8442 if (*ppdata == NULL) {
8443 reply_nterror(req, NT_STATUS_NO_MEMORY);
8444 return;
8446 pdata = *ppdata;
8448 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8449 CAN ACCEPT THIS IN UNICODE. JRA. */
8451 /* Job number */
8452 if (fsp->print_file) {
8453 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8454 } else {
8455 SSVAL(pdata, 0, 0);
8457 srvstr_push(pdata, req->flags2, pdata + 2,
8458 global_myname(), 15,
8459 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8460 srvstr_push(pdata, req->flags2, pdata+18,
8461 lp_servicename(SNUM(conn)), 13,
8462 STR_ASCII|STR_TERMINATE); /* Service name */
8463 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8464 max_data_bytes);
8465 return;
8468 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8469 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8472 /****************************************************************************
8473 Reply to a SMBfindclose (stop trans2 directory search).
8474 ****************************************************************************/
8476 void reply_findclose(struct smb_request *req)
8478 int dptr_num;
8479 struct smbd_server_connection *sconn = req->sconn;
8481 START_PROFILE(SMBfindclose);
8483 if (req->wct < 1) {
8484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8485 END_PROFILE(SMBfindclose);
8486 return;
8489 dptr_num = SVALS(req->vwv+0, 0);
8491 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8493 dptr_close(sconn, &dptr_num);
8495 reply_outbuf(req, 0, 0);
8497 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8499 END_PROFILE(SMBfindclose);
8500 return;
8503 /****************************************************************************
8504 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8505 ****************************************************************************/
8507 void reply_findnclose(struct smb_request *req)
8509 int dptr_num;
8511 START_PROFILE(SMBfindnclose);
8513 if (req->wct < 1) {
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8515 END_PROFILE(SMBfindnclose);
8516 return;
8519 dptr_num = SVAL(req->vwv+0, 0);
8521 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8523 /* We never give out valid handles for a
8524 findnotifyfirst - so any dptr_num is ok here.
8525 Just ignore it. */
8527 reply_outbuf(req, 0, 0);
8529 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8531 END_PROFILE(SMBfindnclose);
8532 return;
8535 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8536 struct trans_state *state)
8538 if (get_Protocol() >= PROTOCOL_NT1) {
8539 req->flags2 |= 0x40; /* IS_LONG_NAME */
8540 SSVAL(req->inbuf,smb_flg2,req->flags2);
8543 if (conn->encrypt_level == Required && !req->encrypted) {
8544 if (state->call != TRANSACT2_QFSINFO &&
8545 state->call != TRANSACT2_SETFSINFO) {
8546 DEBUG(0,("handle_trans2: encryption required "
8547 "with call 0x%x\n",
8548 (unsigned int)state->call));
8549 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8550 return;
8554 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8556 /* Now we must call the relevant TRANS2 function */
8557 switch(state->call) {
8558 case TRANSACT2_OPEN:
8560 START_PROFILE(Trans2_open);
8561 call_trans2open(conn, req,
8562 &state->param, state->total_param,
8563 &state->data, state->total_data,
8564 state->max_data_return);
8565 END_PROFILE(Trans2_open);
8566 break;
8569 case TRANSACT2_FINDFIRST:
8571 START_PROFILE(Trans2_findfirst);
8572 call_trans2findfirst(conn, req,
8573 &state->param, state->total_param,
8574 &state->data, state->total_data,
8575 state->max_data_return);
8576 END_PROFILE(Trans2_findfirst);
8577 break;
8580 case TRANSACT2_FINDNEXT:
8582 START_PROFILE(Trans2_findnext);
8583 call_trans2findnext(conn, req,
8584 &state->param, state->total_param,
8585 &state->data, state->total_data,
8586 state->max_data_return);
8587 END_PROFILE(Trans2_findnext);
8588 break;
8591 case TRANSACT2_QFSINFO:
8593 START_PROFILE(Trans2_qfsinfo);
8594 call_trans2qfsinfo(conn, req,
8595 &state->param, state->total_param,
8596 &state->data, state->total_data,
8597 state->max_data_return);
8598 END_PROFILE(Trans2_qfsinfo);
8599 break;
8602 case TRANSACT2_SETFSINFO:
8604 START_PROFILE(Trans2_setfsinfo);
8605 call_trans2setfsinfo(conn, req,
8606 &state->param, state->total_param,
8607 &state->data, state->total_data,
8608 state->max_data_return);
8609 END_PROFILE(Trans2_setfsinfo);
8610 break;
8613 case TRANSACT2_QPATHINFO:
8614 case TRANSACT2_QFILEINFO:
8616 START_PROFILE(Trans2_qpathinfo);
8617 call_trans2qfilepathinfo(conn, req, state->call,
8618 &state->param, state->total_param,
8619 &state->data, state->total_data,
8620 state->max_data_return);
8621 END_PROFILE(Trans2_qpathinfo);
8622 break;
8625 case TRANSACT2_SETPATHINFO:
8626 case TRANSACT2_SETFILEINFO:
8628 START_PROFILE(Trans2_setpathinfo);
8629 call_trans2setfilepathinfo(conn, req, state->call,
8630 &state->param, state->total_param,
8631 &state->data, state->total_data,
8632 state->max_data_return);
8633 END_PROFILE(Trans2_setpathinfo);
8634 break;
8637 case TRANSACT2_FINDNOTIFYFIRST:
8639 START_PROFILE(Trans2_findnotifyfirst);
8640 call_trans2findnotifyfirst(conn, req,
8641 &state->param, state->total_param,
8642 &state->data, state->total_data,
8643 state->max_data_return);
8644 END_PROFILE(Trans2_findnotifyfirst);
8645 break;
8648 case TRANSACT2_FINDNOTIFYNEXT:
8650 START_PROFILE(Trans2_findnotifynext);
8651 call_trans2findnotifynext(conn, req,
8652 &state->param, state->total_param,
8653 &state->data, state->total_data,
8654 state->max_data_return);
8655 END_PROFILE(Trans2_findnotifynext);
8656 break;
8659 case TRANSACT2_MKDIR:
8661 START_PROFILE(Trans2_mkdir);
8662 call_trans2mkdir(conn, req,
8663 &state->param, state->total_param,
8664 &state->data, state->total_data,
8665 state->max_data_return);
8666 END_PROFILE(Trans2_mkdir);
8667 break;
8670 case TRANSACT2_GET_DFS_REFERRAL:
8672 START_PROFILE(Trans2_get_dfs_referral);
8673 call_trans2getdfsreferral(conn, req,
8674 &state->param, state->total_param,
8675 &state->data, state->total_data,
8676 state->max_data_return);
8677 END_PROFILE(Trans2_get_dfs_referral);
8678 break;
8681 case TRANSACT2_IOCTL:
8683 START_PROFILE(Trans2_ioctl);
8684 call_trans2ioctl(conn, req,
8685 &state->param, state->total_param,
8686 &state->data, state->total_data,
8687 state->max_data_return);
8688 END_PROFILE(Trans2_ioctl);
8689 break;
8692 default:
8693 /* Error in request */
8694 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8695 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8699 /****************************************************************************
8700 Reply to a SMBtrans2.
8701 ****************************************************************************/
8703 void reply_trans2(struct smb_request *req)
8705 connection_struct *conn = req->conn;
8706 unsigned int dsoff;
8707 unsigned int dscnt;
8708 unsigned int psoff;
8709 unsigned int pscnt;
8710 unsigned int tran_call;
8711 struct trans_state *state;
8712 NTSTATUS result;
8714 START_PROFILE(SMBtrans2);
8716 if (req->wct < 14) {
8717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8718 END_PROFILE(SMBtrans2);
8719 return;
8722 dsoff = SVAL(req->vwv+12, 0);
8723 dscnt = SVAL(req->vwv+11, 0);
8724 psoff = SVAL(req->vwv+10, 0);
8725 pscnt = SVAL(req->vwv+9, 0);
8726 tran_call = SVAL(req->vwv+14, 0);
8728 result = allow_new_trans(conn->pending_trans, req->mid);
8729 if (!NT_STATUS_IS_OK(result)) {
8730 DEBUG(2, ("Got invalid trans2 request: %s\n",
8731 nt_errstr(result)));
8732 reply_nterror(req, result);
8733 END_PROFILE(SMBtrans2);
8734 return;
8737 if (IS_IPC(conn)) {
8738 switch (tran_call) {
8739 /* List the allowed trans2 calls on IPC$ */
8740 case TRANSACT2_OPEN:
8741 case TRANSACT2_GET_DFS_REFERRAL:
8742 case TRANSACT2_QFILEINFO:
8743 case TRANSACT2_QFSINFO:
8744 case TRANSACT2_SETFSINFO:
8745 break;
8746 default:
8747 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8748 END_PROFILE(SMBtrans2);
8749 return;
8753 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8754 DEBUG(0, ("talloc failed\n"));
8755 reply_nterror(req, NT_STATUS_NO_MEMORY);
8756 END_PROFILE(SMBtrans2);
8757 return;
8760 state->cmd = SMBtrans2;
8762 state->mid = req->mid;
8763 state->vuid = req->vuid;
8764 state->setup_count = SVAL(req->vwv+13, 0);
8765 state->setup = NULL;
8766 state->total_param = SVAL(req->vwv+0, 0);
8767 state->param = NULL;
8768 state->total_data = SVAL(req->vwv+1, 0);
8769 state->data = NULL;
8770 state->max_param_return = SVAL(req->vwv+2, 0);
8771 state->max_data_return = SVAL(req->vwv+3, 0);
8772 state->max_setup_return = SVAL(req->vwv+4, 0);
8773 state->close_on_completion = BITSETW(req->vwv+5, 0);
8774 state->one_way = BITSETW(req->vwv+5, 1);
8776 state->call = tran_call;
8778 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8779 is so as a sanity check */
8780 if (state->setup_count != 1) {
8782 * Need to have rc=0 for ioctl to get job id for OS/2.
8783 * Network printing will fail if function is not successful.
8784 * Similar function in reply.c will be used if protocol
8785 * is LANMAN1.0 instead of LM1.2X002.
8786 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8787 * outbuf doesn't have to be set(only job id is used).
8789 if ( (state->setup_count == 4)
8790 && (tran_call == TRANSACT2_IOCTL)
8791 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8792 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8793 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8794 } else {
8795 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8796 DEBUG(2,("Transaction is %d\n",tran_call));
8797 TALLOC_FREE(state);
8798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8799 END_PROFILE(SMBtrans2);
8800 return;
8804 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8805 goto bad_param;
8807 if (state->total_data) {
8809 if (trans_oob(state->total_data, 0, dscnt)
8810 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8811 goto bad_param;
8814 /* Can't use talloc here, the core routines do realloc on the
8815 * params and data. */
8816 state->data = (char *)SMB_MALLOC(state->total_data);
8817 if (state->data == NULL) {
8818 DEBUG(0,("reply_trans2: data malloc fail for %u "
8819 "bytes !\n", (unsigned int)state->total_data));
8820 TALLOC_FREE(state);
8821 reply_nterror(req, NT_STATUS_NO_MEMORY);
8822 END_PROFILE(SMBtrans2);
8823 return;
8826 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8829 if (state->total_param) {
8831 if (trans_oob(state->total_param, 0, pscnt)
8832 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8833 goto bad_param;
8836 /* Can't use talloc here, the core routines do realloc on the
8837 * params and data. */
8838 state->param = (char *)SMB_MALLOC(state->total_param);
8839 if (state->param == NULL) {
8840 DEBUG(0,("reply_trans: param malloc fail for %u "
8841 "bytes !\n", (unsigned int)state->total_param));
8842 SAFE_FREE(state->data);
8843 TALLOC_FREE(state);
8844 reply_nterror(req, NT_STATUS_NO_MEMORY);
8845 END_PROFILE(SMBtrans2);
8846 return;
8849 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8852 state->received_data = dscnt;
8853 state->received_param = pscnt;
8855 if ((state->received_param == state->total_param) &&
8856 (state->received_data == state->total_data)) {
8858 handle_trans2(conn, req, state);
8860 SAFE_FREE(state->data);
8861 SAFE_FREE(state->param);
8862 TALLOC_FREE(state);
8863 END_PROFILE(SMBtrans2);
8864 return;
8867 DLIST_ADD(conn->pending_trans, state);
8869 /* We need to send an interim response then receive the rest
8870 of the parameter/data bytes */
8871 reply_outbuf(req, 0, 0);
8872 show_msg((char *)req->outbuf);
8873 END_PROFILE(SMBtrans2);
8874 return;
8876 bad_param:
8878 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8879 SAFE_FREE(state->data);
8880 SAFE_FREE(state->param);
8881 TALLOC_FREE(state);
8882 END_PROFILE(SMBtrans2);
8883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8887 /****************************************************************************
8888 Reply to a SMBtranss2
8889 ****************************************************************************/
8891 void reply_transs2(struct smb_request *req)
8893 connection_struct *conn = req->conn;
8894 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8895 struct trans_state *state;
8897 START_PROFILE(SMBtranss2);
8899 show_msg((char *)req->inbuf);
8901 /* Windows clients expect all replies to
8902 a transact secondary (SMBtranss2 0x33)
8903 to have a command code of transact
8904 (SMBtrans2 0x32). See bug #8989
8905 and also [MS-CIFS] section 2.2.4.47.2
8906 for details.
8908 req->cmd = SMBtrans2;
8910 if (req->wct < 8) {
8911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8912 END_PROFILE(SMBtranss2);
8913 return;
8916 for (state = conn->pending_trans; state != NULL;
8917 state = state->next) {
8918 if (state->mid == req->mid) {
8919 break;
8923 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8925 END_PROFILE(SMBtranss2);
8926 return;
8929 /* Revise state->total_param and state->total_data in case they have
8930 changed downwards */
8932 if (SVAL(req->vwv+0, 0) < state->total_param)
8933 state->total_param = SVAL(req->vwv+0, 0);
8934 if (SVAL(req->vwv+1, 0) < state->total_data)
8935 state->total_data = SVAL(req->vwv+1, 0);
8937 pcnt = SVAL(req->vwv+2, 0);
8938 poff = SVAL(req->vwv+3, 0);
8939 pdisp = SVAL(req->vwv+4, 0);
8941 dcnt = SVAL(req->vwv+5, 0);
8942 doff = SVAL(req->vwv+6, 0);
8943 ddisp = SVAL(req->vwv+7, 0);
8945 state->received_param += pcnt;
8946 state->received_data += dcnt;
8948 if ((state->received_data > state->total_data) ||
8949 (state->received_param > state->total_param))
8950 goto bad_param;
8952 if (pcnt) {
8953 if (trans_oob(state->total_param, pdisp, pcnt)
8954 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8955 goto bad_param;
8957 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8960 if (dcnt) {
8961 if (trans_oob(state->total_data, ddisp, dcnt)
8962 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8963 goto bad_param;
8965 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8968 if ((state->received_param < state->total_param) ||
8969 (state->received_data < state->total_data)) {
8970 END_PROFILE(SMBtranss2);
8971 return;
8974 handle_trans2(conn, req, state);
8976 DLIST_REMOVE(conn->pending_trans, state);
8977 SAFE_FREE(state->data);
8978 SAFE_FREE(state->param);
8979 TALLOC_FREE(state);
8981 END_PROFILE(SMBtranss2);
8982 return;
8984 bad_param:
8986 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8987 DLIST_REMOVE(conn->pending_trans, state);
8988 SAFE_FREE(state->data);
8989 SAFE_FREE(state->param);
8990 TALLOC_FREE(state);
8991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8992 END_PROFILE(SMBtranss2);
8993 return;