s3-printing: Restrict printing=cups to systems with cups development headers at build...
[Samba/bb.git] / source3 / smbd / trans2.c
blob2bc85bf55052921d873d37546ef198a30d5a4d55
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 access_mask);
71 if (!NT_STATUS_IS_OK(status)) {
72 return status;
75 return NT_STATUS_OK;
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
92 return val;
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
103 uint64_t file_index;
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
109 return file_index;
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
125 SAMBA_XATTR_MARKER,
126 XATTR_NTACL_NAME,
127 NULL
130 int i;
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
134 return true;
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
138 return true;
140 return false;
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
153 char *val = NULL;
154 ssize_t sizeret;
156 again:
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
159 if (!val) {
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 } else {
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
170 attr_size = 65536;
171 goto again;
174 if (sizeret == -1) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
181 pea->flags = 0;
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
184 } else {
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
188 TALLOC_FREE(val);
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
193 return NT_STATUS_OK;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
204 char *p;
205 char **names, **tmp;
206 size_t num_names;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
214 return NT_STATUS_OK;
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
222 if (names == NULL) {
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
233 TALLOC_FREE(names);
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
239 ea_namelist_size);
240 } else {
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
242 ea_namelist_size);
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
248 else {
249 break;
253 if (sizeret == -1) {
254 TALLOC_FREE(names);
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
261 if (sizeret == 0) {
262 TALLOC_FREE(names);
263 if (pnames) {
264 *pnames = NULL;
266 *pnum_names = 0;
267 return NT_STATUS_OK;
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
275 TALLOC_FREE(names);
276 return NT_STATUS_INTERNAL_ERROR;
280 * count the names
282 num_names = 0;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
285 num_names += 1;
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
289 if (tmp == NULL) {
290 DEBUG(0, ("talloc failed\n"));
291 TALLOC_FREE(names);
292 return NT_STATUS_NO_MEMORY;
295 names = tmp;
296 num_names = 0;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
302 if (pnames) {
303 *pnames = names;
304 } else {
305 TALLOC_FREE(names);
307 *pnum_names = num_names;
308 return NT_STATUS_OK;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
318 /* Get a list of all xattrs. Max namesize is 64k. */
319 size_t i, num_names;
320 char **names;
321 struct ea_list *ea_list_head = NULL;
322 NTSTATUS status;
324 *pea_total_len = 0;
326 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
327 &names, &num_names);
329 if (!NT_STATUS_IS_OK(status)) {
330 return status;
333 if (num_names == 0) {
334 *ea_list = NULL;
335 return NT_STATUS_OK;
338 for (i=0; i<num_names; i++) {
339 struct ea_list *listp;
340 fstring dos_ea_name;
342 if (strnequal(names[i], "system.", 7)
343 || samba_private_attr_name(names[i]))
344 continue;
346 listp = talloc(mem_ctx, struct ea_list);
347 if (listp == NULL) {
348 return NT_STATUS_NO_MEMORY;
351 status = get_ea_value(mem_ctx, conn, fsp,
352 fname, names[i],
353 &listp->ea);
355 if (!NT_STATUS_IS_OK(status)) {
356 return status;
359 push_ascii_fstring(dos_ea_name, listp->ea.name);
361 *pea_total_len +=
362 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
364 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
365 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
366 (unsigned int)listp->ea.value.length));
368 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
372 /* Add on 4 for total length. */
373 if (*pea_total_len) {
374 *pea_total_len += 4;
377 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
378 (unsigned int)*pea_total_len));
380 *ea_list = ea_list_head;
381 return NT_STATUS_OK;
384 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
385 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
387 *pea_total_len = 0;
388 *ea_list = NULL;
390 if (!lp_ea_support(SNUM(conn))) {
391 return NT_STATUS_OK;
394 if (is_ntfs_stream_smb_fname(smb_fname)) {
395 return NT_STATUS_INVALID_PARAMETER;
398 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
401 /****************************************************************************
402 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
403 that was filled.
404 ****************************************************************************/
406 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
407 connection_struct *conn, struct ea_list *ea_list)
409 unsigned int ret_data_size = 4;
410 char *p = pdata;
412 SMB_ASSERT(total_data_size >= 4);
414 if (!lp_ea_support(SNUM(conn))) {
415 SIVAL(pdata,4,0);
416 return 4;
419 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
420 size_t dos_namelen;
421 fstring dos_ea_name;
422 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
423 dos_namelen = strlen(dos_ea_name);
424 if (dos_namelen > 255 || dos_namelen == 0) {
425 break;
427 if (ea_list->ea.value.length > 65535) {
428 break;
430 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
431 break;
434 /* We know we have room. */
435 SCVAL(p,0,ea_list->ea.flags);
436 SCVAL(p,1,dos_namelen);
437 SSVAL(p,2,ea_list->ea.value.length);
438 strlcpy(p+4, dos_ea_name, dos_namelen+1);
439 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
441 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
442 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
445 ret_data_size = PTR_DIFF(p, pdata);
446 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
447 SIVAL(pdata,0,ret_data_size);
448 return ret_data_size;
451 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
452 char *pdata,
453 unsigned int total_data_size,
454 unsigned int *ret_data_size,
455 connection_struct *conn,
456 struct ea_list *ea_list)
458 uint8_t *p = (uint8_t *)pdata;
459 uint8_t *last_start = NULL;
461 *ret_data_size = 0;
463 if (!lp_ea_support(SNUM(conn))) {
464 return NT_STATUS_NO_EAS_ON_FILE;
467 for (; ea_list; ea_list = ea_list->next) {
468 size_t dos_namelen;
469 fstring dos_ea_name;
470 size_t this_size;
472 if (last_start) {
473 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
475 last_start = p;
477 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
478 dos_namelen = strlen(dos_ea_name);
479 if (dos_namelen > 255 || dos_namelen == 0) {
480 return NT_STATUS_INTERNAL_ERROR;
482 if (ea_list->ea.value.length > 65535) {
483 return NT_STATUS_INTERNAL_ERROR;
486 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
488 if (ea_list->next) {
489 size_t pad = 4 - (this_size % 4);
490 this_size += pad;
493 if (this_size > total_data_size) {
494 return NT_STATUS_INFO_LENGTH_MISMATCH;
497 /* We know we have room. */
498 SIVAL(p, 0x00, 0); /* next offset */
499 SCVAL(p, 0x04, ea_list->ea.flags);
500 SCVAL(p, 0x05, dos_namelen);
501 SSVAL(p, 0x06, ea_list->ea.value.length);
502 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
503 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
505 total_data_size -= this_size;
506 p += this_size;
509 *ret_data_size = PTR_DIFF(p, pdata);
510 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
511 return NT_STATUS_OK;
514 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
516 size_t total_ea_len = 0;
517 TALLOC_CTX *mem_ctx;
518 struct ea_list *ea_list;
520 if (!lp_ea_support(SNUM(conn))) {
521 return 0;
523 mem_ctx = talloc_stackframe();
525 /* If this is a stream fsp, then we need to instead find the
526 * estimated ea len from the main file, not the stream
527 * (streams cannot have EAs), but the estimate isn't just 0 in
528 * this case! */
529 if (is_ntfs_stream_smb_fname(smb_fname)) {
530 fsp = NULL;
532 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
533 TALLOC_FREE(mem_ctx);
534 return total_ea_len;
537 /****************************************************************************
538 Ensure the EA name is case insensitive by matching any existing EA name.
539 ****************************************************************************/
541 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
543 size_t total_ea_len;
544 TALLOC_CTX *mem_ctx = talloc_tos();
545 struct ea_list *ea_list;
546 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
547 if (!NT_STATUS_IS_OK(status)) {
548 return;
551 for (; ea_list; ea_list = ea_list->next) {
552 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
553 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
554 &unix_ea_name[5], ea_list->ea.name));
555 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
556 break;
561 /****************************************************************************
562 Set or delete an extended attribute.
563 ****************************************************************************/
565 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
566 const struct smb_filename *smb_fname, struct ea_list *ea_list)
568 NTSTATUS status;
569 char *fname = NULL;
571 if (!lp_ea_support(SNUM(conn))) {
572 return NT_STATUS_EAS_NOT_SUPPORTED;
575 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
576 if (!NT_STATUS_IS_OK(status)) {
577 return status;
580 /* Setting EAs on streams isn't supported. */
581 if (is_ntfs_stream_smb_fname(smb_fname)) {
582 return NT_STATUS_INVALID_PARAMETER;
585 fname = smb_fname->base_name;
587 for (;ea_list; ea_list = ea_list->next) {
588 int ret;
589 fstring unix_ea_name;
591 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
592 fstrcat(unix_ea_name, ea_list->ea.name);
594 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
596 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
598 if (samba_private_attr_name(unix_ea_name)) {
599 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
600 return NT_STATUS_ACCESS_DENIED;
603 if (ea_list->ea.value.length == 0) {
604 /* Remove the attribute. */
605 if (fsp && (fsp->fh->fd != -1)) {
606 DEBUG(10,("set_ea: deleting ea name %s on "
607 "file %s by file descriptor.\n",
608 unix_ea_name, fsp_str_dbg(fsp)));
609 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
610 } else {
611 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
612 unix_ea_name, fname));
613 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
615 #ifdef ENOATTR
616 /* Removing a non existent attribute always succeeds. */
617 if (ret == -1 && errno == ENOATTR) {
618 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
619 unix_ea_name));
620 ret = 0;
622 #endif
623 } else {
624 if (fsp && (fsp->fh->fd != -1)) {
625 DEBUG(10,("set_ea: setting ea name %s on file "
626 "%s by file descriptor.\n",
627 unix_ea_name, fsp_str_dbg(fsp)));
628 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
629 ea_list->ea.value.data, ea_list->ea.value.length, 0);
630 } else {
631 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
632 unix_ea_name, fname));
633 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
634 ea_list->ea.value.data, ea_list->ea.value.length, 0);
638 if (ret == -1) {
639 #ifdef ENOTSUP
640 if (errno == ENOTSUP) {
641 return NT_STATUS_EAS_NOT_SUPPORTED;
643 #endif
644 return map_nt_error_from_unix(errno);
648 return NT_STATUS_OK;
650 /****************************************************************************
651 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
652 ****************************************************************************/
654 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
656 struct ea_list *ea_list_head = NULL;
657 size_t converted_size, offset = 0;
659 while (offset + 2 < data_size) {
660 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
661 unsigned int namelen = CVAL(pdata,offset);
663 offset++; /* Go past the namelen byte. */
665 /* integer wrap paranioa. */
666 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
667 (offset > data_size) || (namelen > data_size) ||
668 (offset + namelen >= data_size)) {
669 break;
671 /* Ensure the name is null terminated. */
672 if (pdata[offset + namelen] != '\0') {
673 return NULL;
675 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
676 &converted_size)) {
677 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
678 "failed: %s", strerror(errno)));
680 if (!eal->ea.name) {
681 return NULL;
684 offset += (namelen + 1); /* Go past the name + terminating zero. */
685 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
686 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
689 return ea_list_head;
692 /****************************************************************************
693 Read one EA list entry from the buffer.
694 ****************************************************************************/
696 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
698 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
699 uint16 val_len;
700 unsigned int namelen;
701 size_t converted_size;
703 if (!eal) {
704 return NULL;
707 if (data_size < 6) {
708 return NULL;
711 eal->ea.flags = CVAL(pdata,0);
712 namelen = CVAL(pdata,1);
713 val_len = SVAL(pdata,2);
715 if (4 + namelen + 1 + val_len > data_size) {
716 return NULL;
719 /* Ensure the name is null terminated. */
720 if (pdata[namelen + 4] != '\0') {
721 return NULL;
723 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
724 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
725 strerror(errno)));
727 if (!eal->ea.name) {
728 return NULL;
731 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
732 if (!eal->ea.value.data) {
733 return NULL;
736 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
738 /* Ensure we're null terminated just in case we print the value. */
739 eal->ea.value.data[val_len] = '\0';
740 /* But don't count the null. */
741 eal->ea.value.length--;
743 if (pbytes_used) {
744 *pbytes_used = 4 + namelen + 1 + val_len;
747 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
748 dump_data(10, eal->ea.value.data, eal->ea.value.length);
750 return eal;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 const char *params,
841 int paramsize,
842 const char *pdata,
843 int datasize,
844 int max_data_bytes)
846 /* As we are using a protocol > LANMAN1 then the max_send
847 variable must have been set in the sessetupX call.
848 This takes precedence over the max_xmit field in the
849 global struct. These different max_xmit variables should
850 be merged as this is now too confusing */
852 int data_to_send = datasize;
853 int params_to_send = paramsize;
854 int useable_space;
855 const char *pp = params;
856 const char *pd = pdata;
857 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
858 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
859 int data_alignment_offset = 0;
860 bool overflow = False;
861 struct smbd_server_connection *sconn = req->sconn;
862 int max_send = sconn->smb1.sessions.max_send;
864 /* Modify the data_to_send and datasize and set the error if
865 we're trying to send more than max_data_bytes. We still send
866 the part of the packet(s) that fit. Strange, but needed
867 for OS/2. */
869 if (max_data_bytes > 0 && datasize > max_data_bytes) {
870 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
871 max_data_bytes, datasize ));
872 datasize = data_to_send = max_data_bytes;
873 overflow = True;
876 /* If there genuinely are no parameters or data to send just send the empty packet */
878 if(params_to_send == 0 && data_to_send == 0) {
879 reply_outbuf(req, 10, 0);
880 show_msg((char *)req->outbuf);
881 if (!srv_send_smb(sconn,
882 (char *)req->outbuf,
883 true, req->seqnum+1,
884 IS_CONN_ENCRYPTED(conn),
885 &req->pcd)) {
886 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
888 TALLOC_FREE(req->outbuf);
889 return;
892 /* When sending params and data ensure that both are nicely aligned */
893 /* Only do this alignment when there is also data to send - else
894 can cause NT redirector problems. */
896 if (((params_to_send % 4) != 0) && (data_to_send != 0))
897 data_alignment_offset = 4 - (params_to_send % 4);
899 /* Space is bufsize minus Netbios over TCP header minus SMB header */
900 /* The alignment_offset is to align the param bytes on an even byte
901 boundary. NT 4.0 Beta needs this to work correctly. */
903 useable_space = max_send - (smb_size
904 + 2 * 10 /* wct */
905 + alignment_offset
906 + data_alignment_offset);
908 if (useable_space < 0) {
909 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
910 "= %d!!!", useable_space));
911 exit_server_cleanly("send_trans2_replies: Not enough space");
914 while (params_to_send || data_to_send) {
915 /* Calculate whether we will totally or partially fill this packet */
917 total_sent_thistime = params_to_send + data_to_send;
919 /* We can never send more than useable_space */
921 * Note that 'useable_space' does not include the alignment offsets,
922 * but we must include the alignment offsets in the calculation of
923 * the length of the data we send over the wire, as the alignment offsets
924 * are sent here. Fix from Marc_Jacobsen@hp.com.
927 total_sent_thistime = MIN(total_sent_thistime, useable_space);
929 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
930 + data_alignment_offset);
932 /* Set total params and data to be sent */
933 SSVAL(req->outbuf,smb_tprcnt,paramsize);
934 SSVAL(req->outbuf,smb_tdrcnt,datasize);
936 /* Calculate how many parameters and data we can fit into
937 * this packet. Parameters get precedence
940 params_sent_thistime = MIN(params_to_send,useable_space);
941 data_sent_thistime = useable_space - params_sent_thistime;
942 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
944 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
946 /* smb_proff is the offset from the start of the SMB header to the
947 parameter bytes, however the first 4 bytes of outbuf are
948 the Netbios over TCP header. Thus use smb_base() to subtract
949 them from the calculation */
951 SSVAL(req->outbuf,smb_proff,
952 ((smb_buf(req->outbuf)+alignment_offset)
953 - smb_base(req->outbuf)));
955 if(params_sent_thistime == 0)
956 SSVAL(req->outbuf,smb_prdisp,0);
957 else
958 /* Absolute displacement of param bytes sent in this packet */
959 SSVAL(req->outbuf,smb_prdisp,pp - params);
961 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
962 if(data_sent_thistime == 0) {
963 SSVAL(req->outbuf,smb_droff,0);
964 SSVAL(req->outbuf,smb_drdisp, 0);
965 } else {
966 /* The offset of the data bytes is the offset of the
967 parameter bytes plus the number of parameters being sent this time */
968 SSVAL(req->outbuf, smb_droff,
969 ((smb_buf(req->outbuf)+alignment_offset)
970 - smb_base(req->outbuf))
971 + params_sent_thistime + data_alignment_offset);
972 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
975 /* Initialize the padding for alignment */
977 if (alignment_offset != 0) {
978 memset(smb_buf(req->outbuf), 0, alignment_offset);
981 /* Copy the param bytes into the packet */
983 if(params_sent_thistime) {
984 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
985 params_sent_thistime);
988 /* Copy in the data bytes */
989 if(data_sent_thistime) {
990 if (data_alignment_offset != 0) {
991 memset((smb_buf(req->outbuf)+alignment_offset+
992 params_sent_thistime), 0,
993 data_alignment_offset);
995 memcpy(smb_buf(req->outbuf)+alignment_offset
996 +params_sent_thistime+data_alignment_offset,
997 pd,data_sent_thistime);
1000 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1001 params_sent_thistime, data_sent_thistime, useable_space));
1002 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1003 params_to_send, data_to_send, paramsize, datasize));
1005 if (overflow) {
1006 error_packet_set((char *)req->outbuf,
1007 ERRDOS,ERRbufferoverflow,
1008 STATUS_BUFFER_OVERFLOW,
1009 __LINE__,__FILE__);
1012 /* Send the packet */
1013 show_msg((char *)req->outbuf);
1014 if (!srv_send_smb(sconn,
1015 (char *)req->outbuf,
1016 true, req->seqnum+1,
1017 IS_CONN_ENCRYPTED(conn),
1018 &req->pcd))
1019 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1021 TALLOC_FREE(req->outbuf);
1023 pp += params_sent_thistime;
1024 pd += data_sent_thistime;
1026 params_to_send -= params_sent_thistime;
1027 data_to_send -= data_sent_thistime;
1029 /* Sanity check */
1030 if(params_to_send < 0 || data_to_send < 0) {
1031 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1032 params_to_send, data_to_send));
1033 return;
1037 return;
1040 /****************************************************************************
1041 Reply to a TRANSACT2_OPEN.
1042 ****************************************************************************/
1044 static void call_trans2open(connection_struct *conn,
1045 struct smb_request *req,
1046 char **pparams, int total_params,
1047 char **ppdata, int total_data,
1048 unsigned int max_data_bytes)
1050 struct smb_filename *smb_fname = NULL;
1051 char *params = *pparams;
1052 char *pdata = *ppdata;
1053 int deny_mode;
1054 int32 open_attr;
1055 bool oplock_request;
1056 #if 0
1057 bool return_additional_info;
1058 int16 open_sattr;
1059 time_t open_time;
1060 #endif
1061 int open_ofun;
1062 uint32 open_size;
1063 char *pname;
1064 char *fname = NULL;
1065 off_t size=0;
1066 int fattr=0,mtime=0;
1067 SMB_INO_T inode = 0;
1068 int smb_action = 0;
1069 files_struct *fsp;
1070 struct ea_list *ea_list = NULL;
1071 uint16 flags = 0;
1072 NTSTATUS status;
1073 uint32 access_mask;
1074 uint32 share_mode;
1075 uint32 create_disposition;
1076 uint32 create_options = 0;
1077 uint32_t private_flags = 0;
1078 TALLOC_CTX *ctx = talloc_tos();
1081 * Ensure we have enough parameters to perform the operation.
1084 if (total_params < 29) {
1085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1086 goto out;
1089 flags = SVAL(params, 0);
1090 deny_mode = SVAL(params, 2);
1091 open_attr = SVAL(params,6);
1092 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1093 if (oplock_request) {
1094 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1097 #if 0
1098 return_additional_info = BITSETW(params,0);
1099 open_sattr = SVAL(params, 4);
1100 open_time = make_unix_date3(params+8);
1101 #endif
1102 open_ofun = SVAL(params,12);
1103 open_size = IVAL(params,14);
1104 pname = &params[28];
1106 if (IS_IPC(conn)) {
1107 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1108 goto out;
1111 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1112 total_params - 28, STR_TERMINATE,
1113 &status);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 reply_nterror(req, status);
1116 goto out;
1119 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1120 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1121 (unsigned int)open_ofun, open_size));
1123 status = filename_convert(ctx,
1124 conn,
1125 req->flags2 & FLAGS2_DFS_PATHNAMES,
1126 fname,
1128 NULL,
1129 &smb_fname);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1132 reply_botherror(req,
1133 NT_STATUS_PATH_NOT_COVERED,
1134 ERRSRV, ERRbadpath);
1135 goto out;
1137 reply_nterror(req, status);
1138 goto out;
1141 if (open_ofun == 0) {
1142 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1143 goto out;
1146 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1147 open_ofun,
1148 &access_mask, &share_mode,
1149 &create_disposition,
1150 &create_options,
1151 &private_flags)) {
1152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1153 goto out;
1156 /* Any data in this call is an EA list. */
1157 if (total_data && (total_data != 4)) {
1158 if (total_data < 10) {
1159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1160 goto out;
1163 if (IVAL(pdata,0) > total_data) {
1164 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1165 IVAL(pdata,0), (unsigned int)total_data));
1166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1167 goto out;
1170 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1171 total_data - 4);
1172 if (!ea_list) {
1173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1174 goto out;
1177 if (!lp_ea_support(SNUM(conn))) {
1178 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1179 goto out;
1183 status = SMB_VFS_CREATE_FILE(
1184 conn, /* conn */
1185 req, /* req */
1186 0, /* root_dir_fid */
1187 smb_fname, /* fname */
1188 access_mask, /* access_mask */
1189 share_mode, /* share_access */
1190 create_disposition, /* create_disposition*/
1191 create_options, /* create_options */
1192 open_attr, /* file_attributes */
1193 oplock_request, /* oplock_request */
1194 open_size, /* allocation_size */
1195 private_flags,
1196 NULL, /* sd */
1197 ea_list, /* ea_list */
1198 &fsp, /* result */
1199 &smb_action); /* psbuf */
1201 if (!NT_STATUS_IS_OK(status)) {
1202 if (open_was_deferred(req->sconn, req->mid)) {
1203 /* We have re-scheduled this call. */
1204 goto out;
1206 reply_openerror(req, status);
1207 goto out;
1210 size = get_file_size_stat(&smb_fname->st);
1211 fattr = dos_mode(conn, smb_fname);
1212 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1213 inode = smb_fname->st.st_ex_ino;
1214 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1215 close_file(req, fsp, ERROR_CLOSE);
1216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1217 goto out;
1220 /* Realloc the size of parameters and data we will return */
1221 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1222 if(*pparams == NULL ) {
1223 reply_nterror(req, NT_STATUS_NO_MEMORY);
1224 goto out;
1226 params = *pparams;
1228 SSVAL(params,0,fsp->fnum);
1229 SSVAL(params,2,fattr);
1230 srv_put_dos_date2(params,4, mtime);
1231 SIVAL(params,8, (uint32)size);
1232 SSVAL(params,12,deny_mode);
1233 SSVAL(params,14,0); /* open_type - file or directory. */
1234 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1236 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1237 smb_action |= EXTENDED_OPLOCK_GRANTED;
1240 SSVAL(params,18,smb_action);
1243 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1245 SIVAL(params,20,inode);
1246 SSVAL(params,24,0); /* Padding. */
1247 if (flags & 8) {
1248 uint32 ea_size = estimate_ea_size(conn, fsp,
1249 smb_fname);
1250 SIVAL(params, 26, ea_size);
1251 } else {
1252 SIVAL(params, 26, 0);
1255 /* Send the required number of replies */
1256 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1257 out:
1258 TALLOC_FREE(smb_fname);
1261 /*********************************************************
1262 Routine to check if a given string matches exactly.
1263 as a special case a mask of "." does NOT match. That
1264 is required for correct wildcard semantics
1265 Case can be significant or not.
1266 **********************************************************/
1268 static bool exact_match(bool has_wild,
1269 bool case_sensitive,
1270 const char *str,
1271 const char *mask)
1273 if (mask[0] == '.' && mask[1] == 0) {
1274 return false;
1277 if (has_wild) {
1278 return false;
1281 if (case_sensitive) {
1282 return strcmp(str,mask)==0;
1283 } else {
1284 return strcasecmp_m(str,mask) == 0;
1288 /****************************************************************************
1289 Return the filetype for UNIX extensions.
1290 ****************************************************************************/
1292 static uint32 unix_filetype(mode_t mode)
1294 if(S_ISREG(mode))
1295 return UNIX_TYPE_FILE;
1296 else if(S_ISDIR(mode))
1297 return UNIX_TYPE_DIR;
1298 #ifdef S_ISLNK
1299 else if(S_ISLNK(mode))
1300 return UNIX_TYPE_SYMLINK;
1301 #endif
1302 #ifdef S_ISCHR
1303 else if(S_ISCHR(mode))
1304 return UNIX_TYPE_CHARDEV;
1305 #endif
1306 #ifdef S_ISBLK
1307 else if(S_ISBLK(mode))
1308 return UNIX_TYPE_BLKDEV;
1309 #endif
1310 #ifdef S_ISFIFO
1311 else if(S_ISFIFO(mode))
1312 return UNIX_TYPE_FIFO;
1313 #endif
1314 #ifdef S_ISSOCK
1315 else if(S_ISSOCK(mode))
1316 return UNIX_TYPE_SOCKET;
1317 #endif
1319 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1320 return UNIX_TYPE_UNKNOWN;
1323 /****************************************************************************
1324 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1325 ****************************************************************************/
1327 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1329 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1330 const SMB_STRUCT_STAT *psbuf,
1331 uint32 perms,
1332 enum perm_type ptype,
1333 mode_t *ret_perms)
1335 mode_t ret = 0;
1337 if (perms == SMB_MODE_NO_CHANGE) {
1338 if (!VALID_STAT(*psbuf)) {
1339 return NT_STATUS_INVALID_PARAMETER;
1340 } else {
1341 *ret_perms = psbuf->st_ex_mode;
1342 return NT_STATUS_OK;
1346 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1347 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1348 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1349 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1350 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1351 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1352 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1353 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1354 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1355 #ifdef S_ISVTX
1356 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1357 #endif
1358 #ifdef S_ISGID
1359 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1360 #endif
1361 #ifdef S_ISUID
1362 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1363 #endif
1365 switch (ptype) {
1366 case PERM_NEW_FILE:
1367 /* Apply mode mask */
1368 ret &= lp_create_mask(SNUM(conn));
1369 /* Add in force bits */
1370 ret |= lp_force_create_mode(SNUM(conn));
1371 break;
1372 case PERM_NEW_DIR:
1373 ret &= lp_dir_mask(SNUM(conn));
1374 /* Add in force bits */
1375 ret |= lp_force_dir_mode(SNUM(conn));
1376 break;
1377 case PERM_EXISTING_FILE:
1378 /* Apply mode mask */
1379 ret &= lp_security_mask(SNUM(conn));
1380 /* Add in force bits */
1381 ret |= lp_force_security_mode(SNUM(conn));
1382 break;
1383 case PERM_EXISTING_DIR:
1384 /* Apply mode mask */
1385 ret &= lp_dir_security_mask(SNUM(conn));
1386 /* Add in force bits */
1387 ret |= lp_force_dir_security_mode(SNUM(conn));
1388 break;
1391 *ret_perms = ret;
1392 return NT_STATUS_OK;
1395 /****************************************************************************
1396 Needed to show the msdfs symlinks as directories. Modifies psbuf
1397 to be a directory if it's a msdfs link.
1398 ****************************************************************************/
1400 static bool check_msdfs_link(connection_struct *conn,
1401 const char *pathname,
1402 SMB_STRUCT_STAT *psbuf)
1404 int saved_errno = errno;
1405 if(lp_host_msdfs() &&
1406 lp_msdfs_root(SNUM(conn)) &&
1407 is_msdfs_link(conn, pathname, psbuf)) {
1409 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1410 "as a directory\n",
1411 pathname));
1412 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1413 errno = saved_errno;
1414 return true;
1416 errno = saved_errno;
1417 return false;
1421 /****************************************************************************
1422 Get a level dependent lanman2 dir entry.
1423 ****************************************************************************/
1425 struct smbd_dirptr_lanman2_state {
1426 connection_struct *conn;
1427 uint32_t info_level;
1428 bool check_mangled_names;
1429 bool has_wild;
1430 bool got_exact_match;
1433 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1434 void *private_data,
1435 const char *dname,
1436 const char *mask,
1437 char **_fname)
1439 struct smbd_dirptr_lanman2_state *state =
1440 (struct smbd_dirptr_lanman2_state *)private_data;
1441 bool ok;
1442 char mangled_name[13]; /* mangled 8.3 name. */
1443 bool got_match;
1444 const char *fname;
1446 /* Mangle fname if it's an illegal name. */
1447 if (mangle_must_mangle(dname, state->conn->params)) {
1448 ok = name_to_8_3(dname, mangled_name,
1449 true, state->conn->params);
1450 if (!ok) {
1451 return false;
1453 fname = mangled_name;
1454 } else {
1455 fname = dname;
1458 got_match = exact_match(state->has_wild,
1459 state->conn->case_sensitive,
1460 fname, mask);
1461 state->got_exact_match = got_match;
1462 if (!got_match) {
1463 got_match = mask_match(fname, mask,
1464 state->conn->case_sensitive);
1467 if(!got_match && state->check_mangled_names &&
1468 !mangle_is_8_3(fname, false, state->conn->params)) {
1470 * It turns out that NT matches wildcards against
1471 * both long *and* short names. This may explain some
1472 * of the wildcard wierdness from old DOS clients
1473 * that some people have been seeing.... JRA.
1475 /* Force the mangling into 8.3. */
1476 ok = name_to_8_3(fname, mangled_name,
1477 false, state->conn->params);
1478 if (!ok) {
1479 return false;
1482 got_match = exact_match(state->has_wild,
1483 state->conn->case_sensitive,
1484 mangled_name, mask);
1485 state->got_exact_match = got_match;
1486 if (!got_match) {
1487 got_match = mask_match(mangled_name, mask,
1488 state->conn->case_sensitive);
1492 if (!got_match) {
1493 return false;
1496 *_fname = talloc_strdup(ctx, fname);
1497 if (*_fname == NULL) {
1498 return false;
1501 return true;
1504 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1505 void *private_data,
1506 struct smb_filename *smb_fname,
1507 uint32_t *_mode)
1509 struct smbd_dirptr_lanman2_state *state =
1510 (struct smbd_dirptr_lanman2_state *)private_data;
1511 bool ms_dfs_link = false;
1512 uint32_t mode = 0;
1514 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1515 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1516 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1517 "Couldn't lstat [%s] (%s)\n",
1518 smb_fname_str_dbg(smb_fname),
1519 strerror(errno)));
1520 return false;
1522 } else if (!VALID_STAT(smb_fname->st) &&
1523 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1524 /* Needed to show the msdfs symlinks as
1525 * directories */
1527 ms_dfs_link = check_msdfs_link(state->conn,
1528 smb_fname->base_name,
1529 &smb_fname->st);
1530 if (!ms_dfs_link) {
1531 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1532 "Couldn't stat [%s] (%s)\n",
1533 smb_fname_str_dbg(smb_fname),
1534 strerror(errno)));
1535 return false;
1539 if (ms_dfs_link) {
1540 mode = dos_mode_msdfs(state->conn, smb_fname);
1541 } else {
1542 mode = dos_mode(state->conn, smb_fname);
1545 *_mode = mode;
1546 return true;
1549 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1550 connection_struct *conn,
1551 uint16_t flags2,
1552 uint32_t info_level,
1553 struct ea_list *name_list,
1554 bool check_mangled_names,
1555 bool requires_resume_key,
1556 uint32_t mode,
1557 const char *fname,
1558 const struct smb_filename *smb_fname,
1559 int space_remaining,
1560 uint8_t align,
1561 bool do_pad,
1562 char *base_data,
1563 char **ppdata,
1564 char *end_data,
1565 bool *out_of_space,
1566 uint64_t *last_entry_off)
1568 char *p, *q, *pdata = *ppdata;
1569 uint32_t reskey=0;
1570 uint64_t file_size = 0;
1571 uint64_t allocation_size = 0;
1572 uint64_t file_index = 0;
1573 uint32_t len;
1574 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1575 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1576 char *nameptr;
1577 char *last_entry_ptr;
1578 bool was_8_3;
1579 int off;
1580 int pad = 0;
1582 *out_of_space = false;
1584 ZERO_STRUCT(mdate_ts);
1585 ZERO_STRUCT(adate_ts);
1586 ZERO_STRUCT(create_date_ts);
1587 ZERO_STRUCT(cdate_ts);
1589 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1590 file_size = get_file_size_stat(&smb_fname->st);
1592 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1594 file_index = get_FileIndex(conn, &smb_fname->st);
1596 mdate_ts = smb_fname->st.st_ex_mtime;
1597 adate_ts = smb_fname->st.st_ex_atime;
1598 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1599 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1601 if (lp_dos_filetime_resolution(SNUM(conn))) {
1602 dos_filetime_timespec(&create_date_ts);
1603 dos_filetime_timespec(&mdate_ts);
1604 dos_filetime_timespec(&adate_ts);
1605 dos_filetime_timespec(&cdate_ts);
1608 create_date = convert_timespec_to_time_t(create_date_ts);
1609 mdate = convert_timespec_to_time_t(mdate_ts);
1610 adate = convert_timespec_to_time_t(adate_ts);
1612 /* align the record */
1613 SMB_ASSERT(align >= 1);
1615 off = (int)PTR_DIFF(pdata, base_data);
1616 pad = (off + (align-1)) & ~(align-1);
1617 pad -= off;
1619 if (pad && pad > space_remaining) {
1620 *out_of_space = true;
1621 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1622 "for padding (wanted %u, had %d)\n",
1623 (unsigned int)pad,
1624 space_remaining ));
1625 return false; /* Not finished - just out of space */
1628 off += pad;
1629 /* initialize padding to 0 */
1630 if (pad) {
1631 memset(pdata, 0, pad);
1633 space_remaining -= pad;
1635 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1636 space_remaining ));
1638 pdata += pad;
1639 p = pdata;
1640 last_entry_ptr = p;
1642 pad = 0;
1643 off = 0;
1645 switch (info_level) {
1646 case SMB_FIND_INFO_STANDARD:
1647 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\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);
1658 p += 23;
1659 nameptr = p;
1660 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1661 p += ucs2_align(base_data, p, 0);
1663 len = srvstr_push(base_data, flags2, p,
1664 fname, PTR_DIFF(end_data, p),
1665 STR_TERMINATE);
1666 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1667 if (len > 2) {
1668 SCVAL(nameptr, -1, len - 2);
1669 } else {
1670 SCVAL(nameptr, -1, 0);
1672 } else {
1673 if (len > 1) {
1674 SCVAL(nameptr, -1, len - 1);
1675 } else {
1676 SCVAL(nameptr, -1, 0);
1679 p += len;
1680 break;
1682 case SMB_FIND_EA_SIZE:
1683 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1684 if (requires_resume_key) {
1685 SIVAL(p,0,reskey);
1686 p += 4;
1688 srv_put_dos_date2(p,0,create_date);
1689 srv_put_dos_date2(p,4,adate);
1690 srv_put_dos_date2(p,8,mdate);
1691 SIVAL(p,12,(uint32)file_size);
1692 SIVAL(p,16,(uint32)allocation_size);
1693 SSVAL(p,20,mode);
1695 unsigned int ea_size = estimate_ea_size(conn, NULL,
1696 smb_fname);
1697 SIVAL(p,22,ea_size); /* Extended attributes */
1699 p += 27;
1700 nameptr = p - 1;
1701 len = srvstr_push(base_data, flags2,
1702 p, fname, PTR_DIFF(end_data, p),
1703 STR_TERMINATE | STR_NOALIGN);
1704 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1705 if (len > 2) {
1706 len -= 2;
1707 } else {
1708 len = 0;
1710 } else {
1711 if (len > 1) {
1712 len -= 1;
1713 } else {
1714 len = 0;
1717 SCVAL(nameptr,0,len);
1718 p += len;
1719 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1720 break;
1722 case SMB_FIND_EA_LIST:
1724 struct ea_list *file_list = NULL;
1725 size_t ea_len = 0;
1726 NTSTATUS status;
1728 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1729 if (!name_list) {
1730 return false;
1732 if (requires_resume_key) {
1733 SIVAL(p,0,reskey);
1734 p += 4;
1736 srv_put_dos_date2(p,0,create_date);
1737 srv_put_dos_date2(p,4,adate);
1738 srv_put_dos_date2(p,8,mdate);
1739 SIVAL(p,12,(uint32)file_size);
1740 SIVAL(p,16,(uint32)allocation_size);
1741 SSVAL(p,20,mode);
1742 p += 22; /* p now points to the EA area. */
1744 status = get_ea_list_from_file(ctx, conn, NULL,
1745 smb_fname,
1746 &ea_len, &file_list);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 file_list = NULL;
1750 name_list = ea_list_union(name_list, file_list, &ea_len);
1752 /* We need to determine if this entry will fit in the space available. */
1753 /* Max string size is 255 bytes. */
1754 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1755 *out_of_space = true;
1756 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1757 "(wanted %u, had %d)\n",
1758 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1759 space_remaining ));
1760 return False; /* Not finished - just out of space */
1763 /* Push the ea_data followed by the name. */
1764 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1765 nameptr = p;
1766 len = srvstr_push(base_data, flags2,
1767 p + 1, fname, PTR_DIFF(end_data, p+1),
1768 STR_TERMINATE | STR_NOALIGN);
1769 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1770 if (len > 2) {
1771 len -= 2;
1772 } else {
1773 len = 0;
1775 } else {
1776 if (len > 1) {
1777 len -= 1;
1778 } else {
1779 len = 0;
1782 SCVAL(nameptr,0,len);
1783 p += len + 1;
1784 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1785 break;
1788 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1789 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1790 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1791 p += 4;
1792 SIVAL(p,0,reskey); p += 4;
1793 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1794 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1797 SOFF_T(p,0,file_size); p += 8;
1798 SOFF_T(p,0,allocation_size); p += 8;
1799 SIVAL(p,0,mode); p += 4;
1800 q = p; p += 4; /* q is placeholder for name length. */
1802 unsigned int ea_size = estimate_ea_size(conn, NULL,
1803 smb_fname);
1804 SIVAL(p,0,ea_size); /* Extended attributes */
1805 p += 4;
1807 /* Clear the short name buffer. This is
1808 * IMPORTANT as not doing so will trigger
1809 * a Win2k client bug. JRA.
1811 if (!was_8_3 && check_mangled_names) {
1812 char mangled_name[13]; /* mangled 8.3 name. */
1813 if (!name_to_8_3(fname,mangled_name,True,
1814 conn->params)) {
1815 /* Error - mangle failed ! */
1816 memset(mangled_name,'\0',12);
1818 mangled_name[12] = 0;
1819 len = srvstr_push(base_data, flags2,
1820 p+2, mangled_name, 24,
1821 STR_UPPER|STR_UNICODE);
1822 if (len < 24) {
1823 memset(p + 2 + len,'\0',24 - len);
1825 SSVAL(p, 0, len);
1826 } else {
1827 memset(p,'\0',26);
1829 p += 2 + 24;
1830 len = srvstr_push(base_data, flags2, p,
1831 fname, PTR_DIFF(end_data, p),
1832 STR_TERMINATE_ASCII);
1833 SIVAL(q,0,len);
1834 p += len;
1836 len = PTR_DIFF(p, pdata);
1837 pad = (len + (align-1)) & ~(align-1);
1839 * offset to the next entry, the caller
1840 * will overwrite it for the last entry
1841 * that's why we always include the padding
1843 SIVAL(pdata,0,pad);
1845 * set padding to zero
1847 if (do_pad) {
1848 memset(p, 0, pad - len);
1849 p = pdata + pad;
1850 } else {
1851 p = pdata + len;
1853 break;
1855 case SMB_FIND_FILE_DIRECTORY_INFO:
1856 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1857 p += 4;
1858 SIVAL(p,0,reskey); p += 4;
1859 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1863 SOFF_T(p,0,file_size); p += 8;
1864 SOFF_T(p,0,allocation_size); p += 8;
1865 SIVAL(p,0,mode); p += 4;
1866 len = srvstr_push(base_data, flags2,
1867 p + 4, fname, PTR_DIFF(end_data, p+4),
1868 STR_TERMINATE_ASCII);
1869 SIVAL(p,0,len);
1870 p += 4 + len;
1872 len = PTR_DIFF(p, pdata);
1873 pad = (len + (align-1)) & ~(align-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1879 SIVAL(pdata,0,pad);
1881 * set padding to zero
1883 if (do_pad) {
1884 memset(p, 0, pad - len);
1885 p = pdata + pad;
1886 } else {
1887 p = pdata + len;
1889 break;
1891 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1893 p += 4;
1894 SIVAL(p,0,reskey); p += 4;
1895 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1896 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1899 SOFF_T(p,0,file_size); p += 8;
1900 SOFF_T(p,0,allocation_size); p += 8;
1901 SIVAL(p,0,mode); p += 4;
1902 q = p; p += 4; /* q is placeholder for name length. */
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1905 smb_fname);
1906 SIVAL(p,0,ea_size); /* Extended attributes */
1907 p +=4;
1909 len = srvstr_push(base_data, flags2, p,
1910 fname, PTR_DIFF(end_data, p),
1911 STR_TERMINATE_ASCII);
1912 SIVAL(q, 0, len);
1913 p += len;
1915 len = PTR_DIFF(p, pdata);
1916 pad = (len + (align-1)) & ~(align-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1922 SIVAL(pdata,0,pad);
1924 * set padding to zero
1926 if (do_pad) {
1927 memset(p, 0, pad - len);
1928 p = pdata + pad;
1929 } else {
1930 p = pdata + len;
1932 break;
1934 case SMB_FIND_FILE_NAMES_INFO:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1936 p += 4;
1937 SIVAL(p,0,reskey); p += 4;
1938 p += 4;
1939 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1940 acl on a dir (tridge) */
1941 len = srvstr_push(base_data, flags2, p,
1942 fname, PTR_DIFF(end_data, p),
1943 STR_TERMINATE_ASCII);
1944 SIVAL(p, -4, len);
1945 p += len;
1947 len = PTR_DIFF(p, pdata);
1948 pad = (len + (align-1)) & ~(align-1);
1950 * offset to the next entry, the caller
1951 * will overwrite it for the last entry
1952 * that's why we always include the padding
1954 SIVAL(pdata,0,pad);
1956 * set padding to zero
1958 if (do_pad) {
1959 memset(p, 0, pad - len);
1960 p = pdata + pad;
1961 } else {
1962 p = pdata + len;
1964 break;
1966 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1967 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1968 p += 4;
1969 SIVAL(p,0,reskey); p += 4;
1970 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1971 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1972 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1973 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1974 SOFF_T(p,0,file_size); p += 8;
1975 SOFF_T(p,0,allocation_size); p += 8;
1976 SIVAL(p,0,mode); p += 4;
1977 q = p; p += 4; /* q is placeholder for name length. */
1979 unsigned int ea_size = estimate_ea_size(conn, NULL,
1980 smb_fname);
1981 SIVAL(p,0,ea_size); /* Extended attributes */
1982 p +=4;
1984 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1985 SBVAL(p,0,file_index); p += 8;
1986 len = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1988 STR_TERMINATE_ASCII);
1989 SIVAL(q, 0, len);
1990 p += len;
1992 len = PTR_DIFF(p, pdata);
1993 pad = (len + (align-1)) & ~(align-1);
1995 * offset to the next entry, the caller
1996 * will overwrite it for the last entry
1997 * that's why we always include the padding
1999 SIVAL(pdata,0,pad);
2001 * set padding to zero
2003 if (do_pad) {
2004 memset(p, 0, pad - len);
2005 p = pdata + pad;
2006 } else {
2007 p = pdata + len;
2009 break;
2011 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2012 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2013 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2014 p += 4;
2015 SIVAL(p,0,reskey); p += 4;
2016 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2017 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2018 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2019 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2020 SOFF_T(p,0,file_size); p += 8;
2021 SOFF_T(p,0,allocation_size); p += 8;
2022 SIVAL(p,0,mode); p += 4;
2023 q = p; p += 4; /* q is placeholder for name length */
2025 unsigned int ea_size = estimate_ea_size(conn, NULL,
2026 smb_fname);
2027 SIVAL(p,0,ea_size); /* Extended attributes */
2028 p +=4;
2030 /* Clear the short name buffer. This is
2031 * IMPORTANT as not doing so will trigger
2032 * a Win2k client bug. JRA.
2034 if (!was_8_3 && check_mangled_names) {
2035 char mangled_name[13]; /* mangled 8.3 name. */
2036 if (!name_to_8_3(fname,mangled_name,True,
2037 conn->params)) {
2038 /* Error - mangle failed ! */
2039 memset(mangled_name,'\0',12);
2041 mangled_name[12] = 0;
2042 len = srvstr_push(base_data, flags2,
2043 p+2, mangled_name, 24,
2044 STR_UPPER|STR_UNICODE);
2045 SSVAL(p, 0, len);
2046 if (len < 24) {
2047 memset(p + 2 + len,'\0',24 - len);
2049 SSVAL(p, 0, len);
2050 } else {
2051 memset(p,'\0',26);
2053 p += 26;
2054 SSVAL(p,0,0); p += 2; /* Reserved ? */
2055 SBVAL(p,0,file_index); p += 8;
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2058 STR_TERMINATE_ASCII);
2059 SIVAL(q,0,len);
2060 p += len;
2062 len = PTR_DIFF(p, pdata);
2063 pad = (len + (align-1)) & ~(align-1);
2065 * offset to the next entry, the caller
2066 * will overwrite it for the last entry
2067 * that's why we always include the padding
2069 SIVAL(pdata,0,pad);
2071 * set padding to zero
2073 if (do_pad) {
2074 memset(p, 0, pad - len);
2075 p = pdata + pad;
2076 } else {
2077 p = pdata + len;
2079 break;
2081 /* CIFS UNIX Extension. */
2083 case SMB_FIND_FILE_UNIX:
2084 case SMB_FIND_FILE_UNIX_INFO2:
2085 p+= 4;
2086 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2088 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2090 if (info_level == SMB_FIND_FILE_UNIX) {
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2092 p = store_file_unix_basic(conn, p,
2093 NULL, &smb_fname->st);
2094 len = srvstr_push(base_data, flags2, p,
2095 fname, PTR_DIFF(end_data, p),
2096 STR_TERMINATE);
2097 } else {
2098 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2099 p = store_file_unix_basic_info2(conn, p,
2100 NULL, &smb_fname->st);
2101 nameptr = p;
2102 p += 4;
2103 len = srvstr_push(base_data, flags2, p, fname,
2104 PTR_DIFF(end_data, p), 0);
2105 SIVAL(nameptr, 0, len);
2108 p += len;
2110 len = PTR_DIFF(p, pdata);
2111 pad = (len + (align-1)) & ~(align-1);
2113 * offset to the next entry, the caller
2114 * will overwrite it for the last entry
2115 * that's why we always include the padding
2117 SIVAL(pdata,0,pad);
2119 * set padding to zero
2121 if (do_pad) {
2122 memset(p, 0, pad - len);
2123 p = pdata + pad;
2124 } else {
2125 p = pdata + len;
2127 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2129 break;
2131 default:
2132 return false;
2135 if (PTR_DIFF(p,pdata) > space_remaining) {
2136 *out_of_space = true;
2137 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2138 "(wanted %u, had %d)\n",
2139 (unsigned int)PTR_DIFF(p,pdata),
2140 space_remaining ));
2141 return false; /* Not finished - just out of space */
2144 /* Setup the last entry pointer, as an offset from base_data */
2145 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2146 /* Advance the data pointer to the next slot */
2147 *ppdata = p;
2149 return true;
2152 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2153 connection_struct *conn,
2154 struct dptr_struct *dirptr,
2155 uint16 flags2,
2156 const char *path_mask,
2157 uint32 dirtype,
2158 int info_level,
2159 int requires_resume_key,
2160 bool dont_descend,
2161 bool ask_sharemode,
2162 uint8_t align,
2163 bool do_pad,
2164 char **ppdata,
2165 char *base_data,
2166 char *end_data,
2167 int space_remaining,
2168 bool *out_of_space,
2169 bool *got_exact_match,
2170 int *_last_entry_off,
2171 struct ea_list *name_list)
2173 const char *p;
2174 const char *mask = NULL;
2175 long prev_dirpos = 0;
2176 uint32_t mode = 0;
2177 char *fname = NULL;
2178 struct smb_filename *smb_fname = NULL;
2179 struct smbd_dirptr_lanman2_state state;
2180 bool ok;
2181 uint64_t last_entry_off = 0;
2183 ZERO_STRUCT(state);
2184 state.conn = conn;
2185 state.info_level = info_level;
2186 state.check_mangled_names = lp_manglednames(conn->params);
2187 state.has_wild = dptr_has_wild(dirptr);
2188 state.got_exact_match = false;
2190 *out_of_space = false;
2191 *got_exact_match = false;
2193 p = strrchr_m(path_mask,'/');
2194 if(p != NULL) {
2195 if(p[1] == '\0') {
2196 mask = "*.*";
2197 } else {
2198 mask = p+1;
2200 } else {
2201 mask = path_mask;
2204 ok = smbd_dirptr_get_entry(ctx,
2205 dirptr,
2206 mask,
2207 dirtype,
2208 dont_descend,
2209 ask_sharemode,
2210 smbd_dirptr_lanman2_match_fn,
2211 smbd_dirptr_lanman2_mode_fn,
2212 &state,
2213 &fname,
2214 &smb_fname,
2215 &mode,
2216 &prev_dirpos);
2217 if (!ok) {
2218 return false;
2221 *got_exact_match = state.got_exact_match;
2223 ok = smbd_marshall_dir_entry(ctx,
2224 conn,
2225 flags2,
2226 info_level,
2227 name_list,
2228 state.check_mangled_names,
2229 requires_resume_key,
2230 mode,
2231 fname,
2232 smb_fname,
2233 space_remaining,
2234 align,
2235 do_pad,
2236 base_data,
2237 ppdata,
2238 end_data,
2239 out_of_space,
2240 &last_entry_off);
2241 TALLOC_FREE(fname);
2242 TALLOC_FREE(smb_fname);
2243 if (*out_of_space) {
2244 dptr_SeekDir(dirptr, prev_dirpos);
2245 return false;
2247 if (!ok) {
2248 return false;
2251 *_last_entry_off = last_entry_off;
2252 return true;
2255 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2256 connection_struct *conn,
2257 struct dptr_struct *dirptr,
2258 uint16 flags2,
2259 const char *path_mask,
2260 uint32 dirtype,
2261 int info_level,
2262 bool requires_resume_key,
2263 bool dont_descend,
2264 bool ask_sharemode,
2265 char **ppdata,
2266 char *base_data,
2267 char *end_data,
2268 int space_remaining,
2269 bool *out_of_space,
2270 bool *got_exact_match,
2271 int *last_entry_off,
2272 struct ea_list *name_list)
2274 uint8_t align = 4;
2275 const bool do_pad = true;
2277 if (info_level >= 1 && info_level <= 3) {
2278 /* No alignment on earlier info levels. */
2279 align = 1;
2282 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2283 path_mask, dirtype, info_level,
2284 requires_resume_key, dont_descend, ask_sharemode,
2285 align, do_pad,
2286 ppdata, base_data, end_data,
2287 space_remaining,
2288 out_of_space, got_exact_match,
2289 last_entry_off, name_list);
2292 /****************************************************************************
2293 Reply to a TRANS2_FINDFIRST.
2294 ****************************************************************************/
2296 static void call_trans2findfirst(connection_struct *conn,
2297 struct smb_request *req,
2298 char **pparams, int total_params,
2299 char **ppdata, int total_data,
2300 unsigned int max_data_bytes)
2302 /* We must be careful here that we don't return more than the
2303 allowed number of data bytes. If this means returning fewer than
2304 maxentries then so be it. We assume that the redirector has
2305 enough room for the fixed number of parameter bytes it has
2306 requested. */
2307 struct smb_filename *smb_dname = NULL;
2308 char *params = *pparams;
2309 char *pdata = *ppdata;
2310 char *data_end;
2311 uint32 dirtype;
2312 int maxentries;
2313 uint16 findfirst_flags;
2314 bool close_after_first;
2315 bool close_if_end;
2316 bool requires_resume_key;
2317 int info_level;
2318 char *directory = NULL;
2319 char *mask = NULL;
2320 char *p;
2321 int last_entry_off=0;
2322 int dptr_num = -1;
2323 int numentries = 0;
2324 int i;
2325 bool finished = False;
2326 bool dont_descend = False;
2327 bool out_of_space = False;
2328 int space_remaining;
2329 bool mask_contains_wcard = False;
2330 struct ea_list *ea_list = NULL;
2331 NTSTATUS ntstatus = NT_STATUS_OK;
2332 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2333 TALLOC_CTX *ctx = talloc_tos();
2334 struct dptr_struct *dirptr = NULL;
2335 struct smbd_server_connection *sconn = req->sconn;
2336 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2337 bool backup_priv = false;
2339 if (total_params < 13) {
2340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2341 goto out;
2344 dirtype = SVAL(params,0);
2345 maxentries = SVAL(params,2);
2346 findfirst_flags = SVAL(params,4);
2347 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2348 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2349 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2350 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2351 security_token_has_privilege(get_current_nttok(conn),
2352 SEC_PRIV_BACKUP));
2354 info_level = SVAL(params,6);
2356 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2357 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2358 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2359 (int)backup_priv,
2360 info_level, max_data_bytes));
2362 if (!maxentries) {
2363 /* W2K3 seems to treat zero as 1. */
2364 maxentries = 1;
2367 switch (info_level) {
2368 case SMB_FIND_INFO_STANDARD:
2369 case SMB_FIND_EA_SIZE:
2370 case SMB_FIND_EA_LIST:
2371 case SMB_FIND_FILE_DIRECTORY_INFO:
2372 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2373 case SMB_FIND_FILE_NAMES_INFO:
2374 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2375 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2376 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2377 break;
2378 case SMB_FIND_FILE_UNIX:
2379 case SMB_FIND_FILE_UNIX_INFO2:
2380 /* Always use filesystem for UNIX mtime query. */
2381 ask_sharemode = false;
2382 if (!lp_unix_extensions()) {
2383 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2384 goto out;
2386 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2387 break;
2388 default:
2389 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2390 goto out;
2393 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2394 params+12, total_params - 12,
2395 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2396 if (!NT_STATUS_IS_OK(ntstatus)) {
2397 reply_nterror(req, ntstatus);
2398 goto out;
2401 if (backup_priv) {
2402 become_root();
2403 ntstatus = filename_convert_with_privilege(ctx,
2404 conn,
2405 req,
2406 directory,
2407 ucf_flags,
2408 &mask_contains_wcard,
2409 &smb_dname);
2410 } else {
2411 ntstatus = filename_convert(ctx, conn,
2412 req->flags2 & FLAGS2_DFS_PATHNAMES,
2413 directory,
2414 ucf_flags,
2415 &mask_contains_wcard,
2416 &smb_dname);
2419 if (!NT_STATUS_IS_OK(ntstatus)) {
2420 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2421 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2422 ERRSRV, ERRbadpath);
2423 goto out;
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 mask = smb_dname->original_lcomp;
2431 directory = smb_dname->base_name;
2433 p = strrchr_m(directory,'/');
2434 if(p == NULL) {
2435 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2436 if((directory[0] == '.') && (directory[1] == '\0')) {
2437 mask = talloc_strdup(ctx,"*");
2438 if (!mask) {
2439 reply_nterror(req, NT_STATUS_NO_MEMORY);
2440 goto out;
2442 mask_contains_wcard = True;
2444 } else {
2445 *p = 0;
2448 if (p == NULL || p == directory) {
2449 /* Ensure we don't have a directory name of "". */
2450 directory = talloc_strdup(talloc_tos(), ".");
2451 if (!directory) {
2452 reply_nterror(req, NT_STATUS_NO_MEMORY);
2453 goto out;
2457 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2459 if (info_level == SMB_FIND_EA_LIST) {
2460 uint32 ea_size;
2462 if (total_data < 4) {
2463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2464 goto out;
2467 ea_size = IVAL(pdata,0);
2468 if (ea_size != total_data) {
2469 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2470 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2472 goto out;
2475 if (!lp_ea_support(SNUM(conn))) {
2476 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2477 goto out;
2480 /* Pull out the list of names. */
2481 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2482 if (!ea_list) {
2483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2484 goto out;
2488 *ppdata = (char *)SMB_REALLOC(
2489 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2490 if(*ppdata == NULL ) {
2491 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 goto out;
2494 pdata = *ppdata;
2495 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2497 /* Realloc the params space */
2498 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2499 if (*pparams == NULL) {
2500 reply_nterror(req, NT_STATUS_NO_MEMORY);
2501 goto out;
2503 params = *pparams;
2505 /* Save the wildcard match and attribs we are using on this directory -
2506 needed as lanman2 assumes these are being saved between calls */
2508 ntstatus = dptr_create(conn,
2509 req,
2510 NULL, /* fsp */
2511 directory,
2512 False,
2513 True,
2514 req->smbpid,
2515 mask,
2516 mask_contains_wcard,
2517 dirtype,
2518 &dirptr);
2520 if (!NT_STATUS_IS_OK(ntstatus)) {
2521 reply_nterror(req, ntstatus);
2522 goto out;
2525 if (backup_priv) {
2526 /* Remember this in case we have
2527 to do a findnext. */
2528 dptr_set_priv(dirptr);
2531 dptr_num = dptr_dnum(dirptr);
2532 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2534 /* Initialize per TRANS2_FIND_FIRST operation data */
2535 dptr_init_search_op(dirptr);
2537 /* We don't need to check for VOL here as this is returned by
2538 a different TRANS2 call. */
2540 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2541 directory,lp_dontdescend(ctx, SNUM(conn))));
2542 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2543 dont_descend = True;
2545 p = pdata;
2546 space_remaining = max_data_bytes;
2547 out_of_space = False;
2549 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2550 bool got_exact_match = False;
2552 /* this is a heuristic to avoid seeking the dirptr except when
2553 absolutely necessary. It allows for a filename of about 40 chars */
2554 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2555 out_of_space = True;
2556 finished = False;
2557 } else {
2558 finished = !get_lanman2_dir_entry(ctx,
2559 conn,
2560 dirptr,
2561 req->flags2,
2562 mask,dirtype,info_level,
2563 requires_resume_key,dont_descend,
2564 ask_sharemode,
2565 &p,pdata,data_end,
2566 space_remaining, &out_of_space,
2567 &got_exact_match,
2568 &last_entry_off, ea_list);
2571 if (finished && out_of_space)
2572 finished = False;
2574 if (!finished && !out_of_space)
2575 numentries++;
2578 * As an optimisation if we know we aren't looking
2579 * for a wildcard name (ie. the name matches the wildcard exactly)
2580 * then we can finish on any (first) match.
2581 * This speeds up large directory searches. JRA.
2584 if(got_exact_match)
2585 finished = True;
2587 /* Ensure space_remaining never goes -ve. */
2588 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2589 space_remaining = 0;
2590 out_of_space = true;
2591 } else {
2592 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2596 /* Check if we can close the dirptr */
2597 if(close_after_first || (finished && close_if_end)) {
2598 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2599 dptr_close(sconn, &dptr_num);
2603 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2604 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2605 * the protocol level is less than NT1. Tested with smbclient. JRA.
2606 * This should fix the OS/2 client bug #2335.
2609 if(numentries == 0) {
2610 dptr_close(sconn, &dptr_num);
2611 if (get_Protocol() < PROTOCOL_NT1) {
2612 reply_force_doserror(req, ERRDOS, ERRnofiles);
2613 goto out;
2614 } else {
2615 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2616 ERRDOS, ERRbadfile);
2617 goto out;
2621 /* At this point pdata points to numentries directory entries. */
2623 /* Set up the return parameter block */
2624 SSVAL(params,0,dptr_num);
2625 SSVAL(params,2,numentries);
2626 SSVAL(params,4,finished);
2627 SSVAL(params,6,0); /* Never an EA error */
2628 SSVAL(params,8,last_entry_off);
2630 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2631 max_data_bytes);
2633 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2634 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2635 if (!directory) {
2636 reply_nterror(req, NT_STATUS_NO_MEMORY);
2640 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2641 smb_fn_name(req->cmd),
2642 mask, directory, dirtype, numentries ) );
2645 * Force a name mangle here to ensure that the
2646 * mask as an 8.3 name is top of the mangled cache.
2647 * The reasons for this are subtle. Don't remove
2648 * this code unless you know what you are doing
2649 * (see PR#13758). JRA.
2652 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2653 char mangled_name[13];
2654 name_to_8_3(mask, mangled_name, True, conn->params);
2656 out:
2658 if (backup_priv) {
2659 unbecome_root();
2662 TALLOC_FREE(smb_dname);
2663 return;
2666 /****************************************************************************
2667 Reply to a TRANS2_FINDNEXT.
2668 ****************************************************************************/
2670 static void call_trans2findnext(connection_struct *conn,
2671 struct smb_request *req,
2672 char **pparams, int total_params,
2673 char **ppdata, int total_data,
2674 unsigned int max_data_bytes)
2676 /* We must be careful here that we don't return more than the
2677 allowed number of data bytes. If this means returning fewer than
2678 maxentries then so be it. We assume that the redirector has
2679 enough room for the fixed number of parameter bytes it has
2680 requested. */
2681 char *params = *pparams;
2682 char *pdata = *ppdata;
2683 char *data_end;
2684 int dptr_num;
2685 int maxentries;
2686 uint16 info_level;
2687 uint32 resume_key;
2688 uint16 findnext_flags;
2689 bool close_after_request;
2690 bool close_if_end;
2691 bool requires_resume_key;
2692 bool continue_bit;
2693 bool mask_contains_wcard = False;
2694 char *resume_name = NULL;
2695 const char *mask = NULL;
2696 const char *directory = NULL;
2697 char *p = NULL;
2698 uint16 dirtype;
2699 int numentries = 0;
2700 int i, last_entry_off=0;
2701 bool finished = False;
2702 bool dont_descend = False;
2703 bool out_of_space = False;
2704 int space_remaining;
2705 struct ea_list *ea_list = NULL;
2706 NTSTATUS ntstatus = NT_STATUS_OK;
2707 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2708 TALLOC_CTX *ctx = talloc_tos();
2709 struct dptr_struct *dirptr;
2710 struct smbd_server_connection *sconn = req->sconn;
2711 bool backup_priv = false;
2713 if (total_params < 13) {
2714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2715 return;
2718 dptr_num = SVAL(params,0);
2719 maxentries = SVAL(params,2);
2720 info_level = SVAL(params,4);
2721 resume_key = IVAL(params,6);
2722 findnext_flags = SVAL(params,10);
2723 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2724 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2725 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2726 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2728 if (!continue_bit) {
2729 /* We only need resume_name if continue_bit is zero. */
2730 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2731 params+12,
2732 total_params - 12, STR_TERMINATE, &ntstatus,
2733 &mask_contains_wcard);
2734 if (!NT_STATUS_IS_OK(ntstatus)) {
2735 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2736 complain (it thinks we're asking for the directory above the shared
2737 path or an invalid name). Catch this as the resume name is only compared, never used in
2738 a file access. JRA. */
2739 srvstr_pull_talloc(ctx, params, req->flags2,
2740 &resume_name, params+12,
2741 total_params - 12,
2742 STR_TERMINATE);
2744 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2745 reply_nterror(req, ntstatus);
2746 return;
2751 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2752 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2753 resume_key = %d resume name = %s continue=%d level = %d\n",
2754 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2755 requires_resume_key, resume_key,
2756 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2758 if (!maxentries) {
2759 /* W2K3 seems to treat zero as 1. */
2760 maxentries = 1;
2763 switch (info_level) {
2764 case SMB_FIND_INFO_STANDARD:
2765 case SMB_FIND_EA_SIZE:
2766 case SMB_FIND_EA_LIST:
2767 case SMB_FIND_FILE_DIRECTORY_INFO:
2768 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2769 case SMB_FIND_FILE_NAMES_INFO:
2770 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2771 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2772 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2773 break;
2774 case SMB_FIND_FILE_UNIX:
2775 case SMB_FIND_FILE_UNIX_INFO2:
2776 /* Always use filesystem for UNIX mtime query. */
2777 ask_sharemode = false;
2778 if (!lp_unix_extensions()) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 return;
2782 break;
2783 default:
2784 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2785 return;
2788 if (info_level == SMB_FIND_EA_LIST) {
2789 uint32 ea_size;
2791 if (total_data < 4) {
2792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2793 return;
2796 ea_size = IVAL(pdata,0);
2797 if (ea_size != total_data) {
2798 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2799 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2801 return;
2804 if (!lp_ea_support(SNUM(conn))) {
2805 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2806 return;
2809 /* Pull out the list of names. */
2810 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2811 if (!ea_list) {
2812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2813 return;
2817 *ppdata = (char *)SMB_REALLOC(
2818 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2819 if(*ppdata == NULL) {
2820 reply_nterror(req, NT_STATUS_NO_MEMORY);
2821 return;
2824 pdata = *ppdata;
2825 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2827 /* Realloc the params space */
2828 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2829 if(*pparams == NULL ) {
2830 reply_nterror(req, NT_STATUS_NO_MEMORY);
2831 return;
2834 params = *pparams;
2836 /* Check that the dptr is valid */
2837 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2838 reply_nterror(req, STATUS_NO_MORE_FILES);
2839 return;
2842 directory = dptr_path(sconn, dptr_num);
2844 /* Get the wildcard mask from the dptr */
2845 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2846 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2847 reply_nterror(req, STATUS_NO_MORE_FILES);
2848 return;
2851 /* Get the attr mask from the dptr */
2852 dirtype = dptr_attr(sconn, dptr_num);
2854 backup_priv = dptr_get_priv(dirptr);
2856 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2857 "backup_priv = %d\n",
2858 dptr_num, mask, dirtype,
2859 (long)dirptr,
2860 dptr_TellDir(dirptr),
2861 (int)backup_priv));
2863 /* Initialize per TRANS2_FIND_NEXT operation data */
2864 dptr_init_search_op(dirptr);
2866 /* We don't need to check for VOL here as this is returned by
2867 a different TRANS2 call. */
2869 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2870 directory,lp_dontdescend(ctx, SNUM(conn))));
2871 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2872 dont_descend = True;
2874 p = pdata;
2875 space_remaining = max_data_bytes;
2876 out_of_space = False;
2878 if (backup_priv) {
2879 become_root();
2883 * Seek to the correct position. We no longer use the resume key but
2884 * depend on the last file name instead.
2887 if(!continue_bit && resume_name && *resume_name) {
2888 SMB_STRUCT_STAT st;
2890 long current_pos = 0;
2892 * Remember, name_to_8_3 is called by
2893 * get_lanman2_dir_entry(), so the resume name
2894 * could be mangled. Ensure we check the unmangled name.
2897 if (mangle_is_mangled(resume_name, conn->params)) {
2898 char *new_resume_name = NULL;
2899 mangle_lookup_name_from_8_3(ctx,
2900 resume_name,
2901 &new_resume_name,
2902 conn->params);
2903 if (new_resume_name) {
2904 resume_name = new_resume_name;
2909 * Fix for NT redirector problem triggered by resume key indexes
2910 * changing between directory scans. We now return a resume key of 0
2911 * and instead look for the filename to continue from (also given
2912 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2913 * findfirst/findnext (as is usual) then the directory pointer
2914 * should already be at the correct place.
2917 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2918 } /* end if resume_name && !continue_bit */
2920 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2921 bool got_exact_match = False;
2923 /* this is a heuristic to avoid seeking the dirptr except when
2924 absolutely necessary. It allows for a filename of about 40 chars */
2925 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2926 out_of_space = True;
2927 finished = False;
2928 } else {
2929 finished = !get_lanman2_dir_entry(ctx,
2930 conn,
2931 dirptr,
2932 req->flags2,
2933 mask,dirtype,info_level,
2934 requires_resume_key,dont_descend,
2935 ask_sharemode,
2936 &p,pdata,data_end,
2937 space_remaining, &out_of_space,
2938 &got_exact_match,
2939 &last_entry_off, ea_list);
2942 if (finished && out_of_space)
2943 finished = False;
2945 if (!finished && !out_of_space)
2946 numentries++;
2949 * As an optimisation if we know we aren't looking
2950 * for a wildcard name (ie. the name matches the wildcard exactly)
2951 * then we can finish on any (first) match.
2952 * This speeds up large directory searches. JRA.
2955 if(got_exact_match)
2956 finished = True;
2958 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2961 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2962 smb_fn_name(req->cmd),
2963 mask, directory, dirtype, numentries ) );
2965 /* Check if we can close the dirptr */
2966 if(close_after_request || (finished && close_if_end)) {
2967 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2968 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2971 if (backup_priv) {
2972 unbecome_root();
2975 /* Set up the return parameter block */
2976 SSVAL(params,0,numentries);
2977 SSVAL(params,2,finished);
2978 SSVAL(params,4,0); /* Never an EA error */
2979 SSVAL(params,6,last_entry_off);
2981 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2982 max_data_bytes);
2984 return;
2987 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2989 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2990 return objid;
2993 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2995 SMB_ASSERT(extended_info != NULL);
2997 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2998 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2999 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3000 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3001 #ifdef SAMBA_VERSION_REVISION
3002 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3003 #endif
3004 extended_info->samba_subversion = 0;
3005 #ifdef SAMBA_VERSION_RC_RELEASE
3006 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3007 #else
3008 #ifdef SAMBA_VERSION_PRE_RELEASE
3009 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3010 #endif
3011 #endif
3012 #ifdef SAMBA_VERSION_VENDOR_PATCH
3013 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3014 #endif
3015 extended_info->samba_gitcommitdate = 0;
3016 #ifdef SAMBA_VERSION_COMMIT_TIME
3017 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3018 #endif
3020 memset(extended_info->samba_version_string, 0,
3021 sizeof(extended_info->samba_version_string));
3023 snprintf (extended_info->samba_version_string,
3024 sizeof(extended_info->samba_version_string),
3025 "%s", samba_version_string());
3028 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3029 TALLOC_CTX *mem_ctx,
3030 uint16_t info_level,
3031 uint16_t flags2,
3032 unsigned int max_data_bytes,
3033 char **ppdata,
3034 int *ret_data_len)
3036 char *pdata, *end_data;
3037 int data_len = 0, len;
3038 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3039 int snum = SNUM(conn);
3040 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3041 uint32 additional_flags = 0;
3042 struct smb_filename smb_fname_dot;
3043 SMB_STRUCT_STAT st;
3045 if (IS_IPC(conn)) {
3046 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3047 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3048 "info level (0x%x) on IPC$.\n",
3049 (unsigned int)info_level));
3050 return NT_STATUS_ACCESS_DENIED;
3054 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3056 ZERO_STRUCT(smb_fname_dot);
3057 smb_fname_dot.base_name = discard_const_p(char, ".");
3059 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3060 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3061 return map_nt_error_from_unix(errno);
3064 st = smb_fname_dot.st;
3066 *ppdata = (char *)SMB_REALLOC(
3067 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3068 if (*ppdata == NULL) {
3069 return NT_STATUS_NO_MEMORY;
3072 pdata = *ppdata;
3073 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3074 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3076 switch (info_level) {
3077 case SMB_INFO_ALLOCATION:
3079 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3080 data_len = 18;
3081 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3082 return map_nt_error_from_unix(errno);
3085 block_size = lp_block_size(snum);
3086 if (bsize < block_size) {
3087 uint64_t factor = block_size/bsize;
3088 bsize = block_size;
3089 dsize /= factor;
3090 dfree /= factor;
3092 if (bsize > block_size) {
3093 uint64_t factor = bsize/block_size;
3094 bsize = block_size;
3095 dsize *= factor;
3096 dfree *= factor;
3098 bytes_per_sector = 512;
3099 sectors_per_unit = bsize/bytes_per_sector;
3101 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3102 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3103 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3105 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3106 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3107 SIVAL(pdata,l1_cUnit,dsize);
3108 SIVAL(pdata,l1_cUnitAvail,dfree);
3109 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3110 break;
3113 case SMB_INFO_VOLUME:
3114 /* Return volume name */
3116 * Add volume serial number - hash of a combination of
3117 * the called hostname and the service name.
3119 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3121 * Win2k3 and previous mess this up by sending a name length
3122 * one byte short. I believe only older clients (OS/2 Win9x) use
3123 * this call so try fixing this by adding a terminating null to
3124 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3126 len = srvstr_push(
3127 pdata, flags2,
3128 pdata+l2_vol_szVolLabel, vname,
3129 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3130 STR_NOALIGN|STR_TERMINATE);
3131 SCVAL(pdata,l2_vol_cch,len);
3132 data_len = l2_vol_szVolLabel + len;
3133 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3134 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3135 len, vname));
3136 break;
3138 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3139 case SMB_FS_ATTRIBUTE_INFORMATION:
3141 additional_flags = 0;
3142 #if defined(HAVE_SYS_QUOTAS)
3143 additional_flags |= FILE_VOLUME_QUOTAS;
3144 #endif
3146 if(lp_nt_acl_support(SNUM(conn))) {
3147 additional_flags |= FILE_PERSISTENT_ACLS;
3150 /* Capabilities are filled in at connection time through STATVFS call */
3151 additional_flags |= conn->fs_capabilities;
3152 additional_flags |= lp_parm_int(conn->params->service,
3153 "share", "fake_fscaps",
3156 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3157 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3158 additional_flags); /* FS ATTRIBUTES */
3160 SIVAL(pdata,4,255); /* Max filename component length */
3161 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3162 and will think we can't do long filenames */
3163 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3164 PTR_DIFF(end_data, pdata+12),
3165 STR_UNICODE);
3166 SIVAL(pdata,8,len);
3167 data_len = 12 + len;
3168 break;
3170 case SMB_QUERY_FS_LABEL_INFO:
3171 case SMB_FS_LABEL_INFORMATION:
3172 len = srvstr_push(pdata, flags2, pdata+4, vname,
3173 PTR_DIFF(end_data, pdata+4), 0);
3174 data_len = 4 + len;
3175 SIVAL(pdata,0,len);
3176 break;
3178 case SMB_QUERY_FS_VOLUME_INFO:
3179 case SMB_FS_VOLUME_INFORMATION:
3182 * Add volume serial number - hash of a combination of
3183 * the called hostname and the service name.
3185 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3186 (str_checksum(get_local_machine_name())<<16));
3188 /* Max label len is 32 characters. */
3189 len = srvstr_push(pdata, flags2, pdata+18, vname,
3190 PTR_DIFF(end_data, pdata+18),
3191 STR_UNICODE);
3192 SIVAL(pdata,12,len);
3193 data_len = 18+len;
3195 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3196 (int)strlen(vname),vname,
3197 lp_servicename(talloc_tos(), snum)));
3198 break;
3200 case SMB_QUERY_FS_SIZE_INFO:
3201 case SMB_FS_SIZE_INFORMATION:
3203 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3204 data_len = 24;
3205 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3206 return map_nt_error_from_unix(errno);
3208 block_size = lp_block_size(snum);
3209 if (bsize < block_size) {
3210 uint64_t factor = block_size/bsize;
3211 bsize = block_size;
3212 dsize /= factor;
3213 dfree /= factor;
3215 if (bsize > block_size) {
3216 uint64_t factor = bsize/block_size;
3217 bsize = block_size;
3218 dsize *= factor;
3219 dfree *= factor;
3221 bytes_per_sector = 512;
3222 sectors_per_unit = bsize/bytes_per_sector;
3223 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3224 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3225 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3226 SBIG_UINT(pdata,0,dsize);
3227 SBIG_UINT(pdata,8,dfree);
3228 SIVAL(pdata,16,sectors_per_unit);
3229 SIVAL(pdata,20,bytes_per_sector);
3230 break;
3233 case SMB_FS_FULL_SIZE_INFORMATION:
3235 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3236 data_len = 32;
3237 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3238 return map_nt_error_from_unix(errno);
3240 block_size = lp_block_size(snum);
3241 if (bsize < block_size) {
3242 uint64_t factor = block_size/bsize;
3243 bsize = block_size;
3244 dsize /= factor;
3245 dfree /= factor;
3247 if (bsize > block_size) {
3248 uint64_t factor = bsize/block_size;
3249 bsize = block_size;
3250 dsize *= factor;
3251 dfree *= factor;
3253 bytes_per_sector = 512;
3254 sectors_per_unit = bsize/bytes_per_sector;
3255 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3256 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3257 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3258 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3259 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3260 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3261 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3262 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3263 break;
3266 case SMB_QUERY_FS_DEVICE_INFO:
3267 case SMB_FS_DEVICE_INFORMATION:
3269 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3271 if (!CAN_WRITE(conn)) {
3272 characteristics |= FILE_READ_ONLY_DEVICE;
3274 data_len = 8;
3275 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3276 SIVAL(pdata,4,characteristics);
3277 break;
3280 #ifdef HAVE_SYS_QUOTAS
3281 case SMB_FS_QUOTA_INFORMATION:
3283 * what we have to send --metze:
3285 * Unknown1: 24 NULL bytes
3286 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3287 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3288 * Quota Flags: 2 byte :
3289 * Unknown3: 6 NULL bytes
3291 * 48 bytes total
3293 * details for Quota Flags:
3295 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3296 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3297 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3298 * 0x0001 Enable Quotas: enable quota for this fs
3302 /* we need to fake up a fsp here,
3303 * because its not send in this call
3305 files_struct fsp;
3306 SMB_NTQUOTA_STRUCT quotas;
3308 ZERO_STRUCT(fsp);
3309 ZERO_STRUCT(quotas);
3311 fsp.conn = conn;
3312 fsp.fnum = FNUM_FIELD_INVALID;
3314 /* access check */
3315 if (get_current_uid(conn) != 0) {
3316 DEBUG(0,("set_user_quota: access_denied "
3317 "service [%s] user [%s]\n",
3318 lp_servicename(talloc_tos(), SNUM(conn)),
3319 conn->session_info->unix_info->unix_name));
3320 return NT_STATUS_ACCESS_DENIED;
3323 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3324 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3325 return map_nt_error_from_unix(errno);
3328 data_len = 48;
3330 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3331 lp_servicename(talloc_tos(), SNUM(conn))));
3333 /* Unknown1 24 NULL bytes*/
3334 SBIG_UINT(pdata,0,(uint64_t)0);
3335 SBIG_UINT(pdata,8,(uint64_t)0);
3336 SBIG_UINT(pdata,16,(uint64_t)0);
3338 /* Default Soft Quota 8 bytes */
3339 SBIG_UINT(pdata,24,quotas.softlim);
3341 /* Default Hard Quota 8 bytes */
3342 SBIG_UINT(pdata,32,quotas.hardlim);
3344 /* Quota flag 2 bytes */
3345 SSVAL(pdata,40,quotas.qflags);
3347 /* Unknown3 6 NULL bytes */
3348 SSVAL(pdata,42,0);
3349 SIVAL(pdata,44,0);
3351 break;
3353 #endif /* HAVE_SYS_QUOTAS */
3354 case SMB_FS_OBJECTID_INFORMATION:
3356 unsigned char objid[16];
3357 struct smb_extended_info extended_info;
3358 memcpy(pdata,create_volume_objectid(conn, objid),16);
3359 samba_extended_info_version (&extended_info);
3360 SIVAL(pdata,16,extended_info.samba_magic);
3361 SIVAL(pdata,20,extended_info.samba_version);
3362 SIVAL(pdata,24,extended_info.samba_subversion);
3363 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3364 memcpy(pdata+36,extended_info.samba_version_string,28);
3365 data_len = 64;
3366 break;
3370 * Query the version and capabilities of the CIFS UNIX extensions
3371 * in use.
3374 case SMB_QUERY_CIFS_UNIX_INFO:
3376 bool large_write = lp_min_receive_file_size() &&
3377 !srv_is_signing_active(conn->sconn);
3378 bool large_read = !srv_is_signing_active(conn->sconn);
3379 int encrypt_caps = 0;
3381 if (!lp_unix_extensions()) {
3382 return NT_STATUS_INVALID_LEVEL;
3385 switch (conn->encrypt_level) {
3386 case SMB_SIGNING_OFF:
3387 encrypt_caps = 0;
3388 break;
3389 case SMB_SIGNING_IF_REQUIRED:
3390 case SMB_SIGNING_DEFAULT:
3391 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3392 break;
3393 case SMB_SIGNING_REQUIRED:
3394 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3395 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3396 large_write = false;
3397 large_read = false;
3398 break;
3401 data_len = 12;
3402 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3403 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3405 /* We have POSIX ACLs, pathname, encryption,
3406 * large read/write, and locking capability. */
3408 SBIG_UINT(pdata,4,((uint64_t)(
3409 CIFS_UNIX_POSIX_ACLS_CAP|
3410 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3411 CIFS_UNIX_FCNTL_LOCKS_CAP|
3412 CIFS_UNIX_EXTATTR_CAP|
3413 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3414 encrypt_caps|
3415 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3416 (large_write ?
3417 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3418 break;
3421 case SMB_QUERY_POSIX_FS_INFO:
3423 int rc;
3424 vfs_statvfs_struct svfs;
3426 if (!lp_unix_extensions()) {
3427 return NT_STATUS_INVALID_LEVEL;
3430 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3432 if (!rc) {
3433 data_len = 56;
3434 SIVAL(pdata,0,svfs.OptimalTransferSize);
3435 SIVAL(pdata,4,svfs.BlockSize);
3436 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3437 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3438 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3439 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3440 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3441 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3442 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3443 #ifdef EOPNOTSUPP
3444 } else if (rc == EOPNOTSUPP) {
3445 return NT_STATUS_INVALID_LEVEL;
3446 #endif /* EOPNOTSUPP */
3447 } else {
3448 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3449 return NT_STATUS_DOS(ERRSRV, ERRerror);
3451 break;
3454 case SMB_QUERY_POSIX_WHOAMI:
3456 uint32_t flags = 0;
3457 uint32_t sid_bytes;
3458 int i;
3460 if (!lp_unix_extensions()) {
3461 return NT_STATUS_INVALID_LEVEL;
3464 if (max_data_bytes < 40) {
3465 return NT_STATUS_BUFFER_TOO_SMALL;
3468 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3469 flags |= SMB_WHOAMI_GUEST;
3472 /* NOTE: 8 bytes for UID/GID, irrespective of native
3473 * platform size. This matches
3474 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3476 data_len = 4 /* flags */
3477 + 4 /* flag mask */
3478 + 8 /* uid */
3479 + 8 /* gid */
3480 + 4 /* ngroups */
3481 + 4 /* num_sids */
3482 + 4 /* SID bytes */
3483 + 4 /* pad/reserved */
3484 + (conn->session_info->unix_token->ngroups * 8)
3485 /* groups list */
3486 + (conn->session_info->security_token->num_sids *
3487 SID_MAX_SIZE)
3488 /* SID list */;
3490 SIVAL(pdata, 0, flags);
3491 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3492 SBIG_UINT(pdata, 8,
3493 (uint64_t)conn->session_info->unix_token->uid);
3494 SBIG_UINT(pdata, 16,
3495 (uint64_t)conn->session_info->unix_token->gid);
3498 if (data_len >= max_data_bytes) {
3499 /* Potential overflow, skip the GIDs and SIDs. */
3501 SIVAL(pdata, 24, 0); /* num_groups */
3502 SIVAL(pdata, 28, 0); /* num_sids */
3503 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3504 SIVAL(pdata, 36, 0); /* reserved */
3506 data_len = 40;
3507 break;
3510 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3511 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3513 /* We walk the SID list twice, but this call is fairly
3514 * infrequent, and I don't expect that it's performance
3515 * sensitive -- jpeach
3517 for (i = 0, sid_bytes = 0;
3518 i < conn->session_info->security_token->num_sids; ++i) {
3519 sid_bytes += ndr_size_dom_sid(
3520 &conn->session_info->security_token->sids[i],
3524 /* SID list byte count */
3525 SIVAL(pdata, 32, sid_bytes);
3527 /* 4 bytes pad/reserved - must be zero */
3528 SIVAL(pdata, 36, 0);
3529 data_len = 40;
3531 /* GID list */
3532 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3533 SBIG_UINT(pdata, data_len,
3534 (uint64_t)conn->session_info->unix_token->groups[i]);
3535 data_len += 8;
3538 /* SID list */
3539 for (i = 0;
3540 i < conn->session_info->security_token->num_sids; ++i) {
3541 int sid_len = ndr_size_dom_sid(
3542 &conn->session_info->security_token->sids[i],
3545 sid_linearize(pdata + data_len, sid_len,
3546 &conn->session_info->security_token->sids[i]);
3547 data_len += sid_len;
3550 break;
3553 case SMB_MAC_QUERY_FS_INFO:
3555 * Thursby MAC extension... ONLY on NTFS filesystems
3556 * once we do streams then we don't need this
3558 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3559 data_len = 88;
3560 SIVAL(pdata,84,0x100); /* Don't support mac... */
3561 break;
3563 /* drop through */
3564 default:
3565 return NT_STATUS_INVALID_LEVEL;
3568 *ret_data_len = data_len;
3569 return NT_STATUS_OK;
3572 /****************************************************************************
3573 Reply to a TRANS2_QFSINFO (query filesystem info).
3574 ****************************************************************************/
3576 static void call_trans2qfsinfo(connection_struct *conn,
3577 struct smb_request *req,
3578 char **pparams, int total_params,
3579 char **ppdata, int total_data,
3580 unsigned int max_data_bytes)
3582 char *params = *pparams;
3583 uint16_t info_level;
3584 int data_len = 0;
3585 NTSTATUS status;
3587 if (total_params < 2) {
3588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3589 return;
3592 info_level = SVAL(params,0);
3594 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3595 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3596 DEBUG(0,("call_trans2qfsinfo: encryption required "
3597 "and info level 0x%x sent.\n",
3598 (unsigned int)info_level));
3599 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3600 return;
3604 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3606 status = smbd_do_qfsinfo(conn, req,
3607 info_level,
3608 req->flags2,
3609 max_data_bytes,
3610 ppdata, &data_len);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 reply_nterror(req, status);
3613 return;
3616 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3617 max_data_bytes);
3619 DEBUG( 4, ( "%s info_level = %d\n",
3620 smb_fn_name(req->cmd), info_level) );
3622 return;
3625 /****************************************************************************
3626 Reply to a TRANS2_SETFSINFO (set filesystem info).
3627 ****************************************************************************/
3629 static void call_trans2setfsinfo(connection_struct *conn,
3630 struct smb_request *req,
3631 char **pparams, int total_params,
3632 char **ppdata, int total_data,
3633 unsigned int max_data_bytes)
3635 struct smbd_server_connection *sconn = req->sconn;
3636 char *pdata = *ppdata;
3637 char *params = *pparams;
3638 uint16 info_level;
3640 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3641 lp_servicename(talloc_tos(), SNUM(conn))));
3643 /* */
3644 if (total_params < 4) {
3645 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3646 total_params));
3647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3648 return;
3651 info_level = SVAL(params,2);
3653 if (IS_IPC(conn)) {
3654 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3655 info_level != SMB_SET_CIFS_UNIX_INFO) {
3656 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3657 "info level (0x%x) on IPC$.\n",
3658 (unsigned int)info_level));
3659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3660 return;
3664 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3665 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3666 DEBUG(0,("call_trans2setfsinfo: encryption required "
3667 "and info level 0x%x sent.\n",
3668 (unsigned int)info_level));
3669 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3670 return;
3674 switch(info_level) {
3675 case SMB_SET_CIFS_UNIX_INFO:
3676 if (!lp_unix_extensions()) {
3677 DEBUG(2,("call_trans2setfsinfo: "
3678 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3679 "unix extensions off\n"));
3680 reply_nterror(req,
3681 NT_STATUS_INVALID_LEVEL);
3682 return;
3685 /* There should be 12 bytes of capabilities set. */
3686 if (total_data < 12) {
3687 reply_nterror(
3688 req,
3689 NT_STATUS_INVALID_PARAMETER);
3690 return;
3692 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3693 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3694 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3695 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3696 /* Just print these values for now. */
3697 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3698 "major = %u, minor = %u cap_low = 0x%x, "
3699 "cap_high = 0x%xn",
3700 (unsigned int)sconn->
3701 smb1.unix_info.client_major,
3702 (unsigned int)sconn->
3703 smb1.unix_info.client_minor,
3704 (unsigned int)sconn->
3705 smb1.unix_info.client_cap_low,
3706 (unsigned int)sconn->
3707 smb1.unix_info.client_cap_high));
3709 /* Here is where we must switch to posix pathname processing... */
3710 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3711 lp_set_posix_pathnames();
3712 mangle_change_to_posix();
3715 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3716 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3717 /* Client that knows how to do posix locks,
3718 * but not posix open/mkdir operations. Set a
3719 * default type for read/write checks. */
3721 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3724 break;
3726 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3728 NTSTATUS status;
3729 size_t param_len = 0;
3730 size_t data_len = total_data;
3732 if (!lp_unix_extensions()) {
3733 reply_nterror(
3734 req,
3735 NT_STATUS_INVALID_LEVEL);
3736 return;
3739 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3740 reply_nterror(
3741 req,
3742 NT_STATUS_NOT_SUPPORTED);
3743 return;
3746 if (req->sconn->smb1.echo_handler.trusted_fde) {
3747 DEBUG( 2,("call_trans2setfsinfo: "
3748 "request transport encryption disabled"
3749 "with 'fork echo handler = yes'\n"));
3750 reply_nterror(
3751 req,
3752 NT_STATUS_NOT_SUPPORTED);
3753 return;
3756 DEBUG( 4,("call_trans2setfsinfo: "
3757 "request transport encryption.\n"));
3759 status = srv_request_encryption_setup(conn,
3760 (unsigned char **)ppdata,
3761 &data_len,
3762 (unsigned char **)pparams,
3763 &param_len);
3765 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3766 !NT_STATUS_IS_OK(status)) {
3767 reply_nterror(req, status);
3768 return;
3771 send_trans2_replies(conn, req,
3772 *pparams,
3773 param_len,
3774 *ppdata,
3775 data_len,
3776 max_data_bytes);
3778 if (NT_STATUS_IS_OK(status)) {
3779 /* Server-side transport
3780 * encryption is now *on*. */
3781 status = srv_encryption_start(conn);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 char *reason = talloc_asprintf(talloc_tos(),
3784 "Failure in setting "
3785 "up encrypted transport: %s",
3786 nt_errstr(status));
3787 exit_server_cleanly(reason);
3790 return;
3793 case SMB_FS_QUOTA_INFORMATION:
3795 files_struct *fsp = NULL;
3796 SMB_NTQUOTA_STRUCT quotas;
3798 ZERO_STRUCT(quotas);
3800 /* access check */
3801 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3802 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3803 lp_servicename(talloc_tos(), SNUM(conn)),
3804 conn->session_info->unix_info->unix_name));
3805 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3806 return;
3809 /* note: normaly there're 48 bytes,
3810 * but we didn't use the last 6 bytes for now
3811 * --metze
3813 fsp = file_fsp(req, SVAL(params,0));
3815 if (!check_fsp_ntquota_handle(conn, req,
3816 fsp)) {
3817 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3818 reply_nterror(
3819 req, NT_STATUS_INVALID_HANDLE);
3820 return;
3823 if (total_data < 42) {
3824 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3825 total_data));
3826 reply_nterror(
3827 req,
3828 NT_STATUS_INVALID_PARAMETER);
3829 return;
3832 /* unknown_1 24 NULL bytes in pdata*/
3834 /* the soft quotas 8 bytes (uint64_t)*/
3835 quotas.softlim = BVAL(pdata,24);
3837 /* the hard quotas 8 bytes (uint64_t)*/
3838 quotas.hardlim = BVAL(pdata,32);
3840 /* quota_flags 2 bytes **/
3841 quotas.qflags = SVAL(pdata,40);
3843 /* unknown_2 6 NULL bytes follow*/
3845 /* now set the quotas */
3846 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3847 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3848 reply_nterror(req, map_nt_error_from_unix(errno));
3849 return;
3852 break;
3854 default:
3855 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3856 info_level));
3857 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3858 return;
3859 break;
3863 * sending this reply works fine,
3864 * but I'm not sure it's the same
3865 * like windows do...
3866 * --metze
3868 reply_outbuf(req, 10, 0);
3871 #if defined(HAVE_POSIX_ACLS)
3872 /****************************************************************************
3873 Utility function to count the number of entries in a POSIX acl.
3874 ****************************************************************************/
3876 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3878 unsigned int ace_count = 0;
3879 int entry_id = SMB_ACL_FIRST_ENTRY;
3880 SMB_ACL_ENTRY_T entry;
3882 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3883 /* get_next... */
3884 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3885 entry_id = SMB_ACL_NEXT_ENTRY;
3887 ace_count++;
3889 return ace_count;
3892 /****************************************************************************
3893 Utility function to marshall a POSIX acl into wire format.
3894 ****************************************************************************/
3896 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3898 int entry_id = SMB_ACL_FIRST_ENTRY;
3899 SMB_ACL_ENTRY_T entry;
3901 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3902 SMB_ACL_TAG_T tagtype;
3903 SMB_ACL_PERMSET_T permset;
3904 unsigned char perms = 0;
3905 unsigned int own_grp;
3907 /* get_next... */
3908 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3909 entry_id = SMB_ACL_NEXT_ENTRY;
3912 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3914 return False;
3917 if (sys_acl_get_permset(entry, &permset) == -1) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3919 return False;
3922 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3923 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3924 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3926 SCVAL(pdata,1,perms);
3928 switch (tagtype) {
3929 case SMB_ACL_USER_OBJ:
3930 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3931 own_grp = (unsigned int)pst->st_ex_uid;
3932 SIVAL(pdata,2,own_grp);
3933 SIVAL(pdata,6,0);
3934 break;
3935 case SMB_ACL_USER:
3937 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3938 if (!puid) {
3939 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3940 return False;
3942 own_grp = (unsigned int)*puid;
3943 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3944 SIVAL(pdata,2,own_grp);
3945 SIVAL(pdata,6,0);
3946 break;
3948 case SMB_ACL_GROUP_OBJ:
3949 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3950 own_grp = (unsigned int)pst->st_ex_gid;
3951 SIVAL(pdata,2,own_grp);
3952 SIVAL(pdata,6,0);
3953 break;
3954 case SMB_ACL_GROUP:
3956 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3957 if (!pgid) {
3958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3959 return False;
3961 own_grp = (unsigned int)*pgid;
3962 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3963 SIVAL(pdata,2,own_grp);
3964 SIVAL(pdata,6,0);
3965 break;
3967 case SMB_ACL_MASK:
3968 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3969 SIVAL(pdata,2,0xFFFFFFFF);
3970 SIVAL(pdata,6,0xFFFFFFFF);
3971 break;
3972 case SMB_ACL_OTHER:
3973 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3974 SIVAL(pdata,2,0xFFFFFFFF);
3975 SIVAL(pdata,6,0xFFFFFFFF);
3976 break;
3977 default:
3978 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3979 return False;
3981 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3984 return True;
3986 #endif
3988 /****************************************************************************
3989 Store the FILE_UNIX_BASIC info.
3990 ****************************************************************************/
3992 static char *store_file_unix_basic(connection_struct *conn,
3993 char *pdata,
3994 files_struct *fsp,
3995 const SMB_STRUCT_STAT *psbuf)
3997 uint64_t file_index = get_FileIndex(conn, psbuf);
3998 dev_t devno;
4000 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4001 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4003 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4004 pdata += 8;
4006 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4007 pdata += 8;
4009 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4012 pdata += 24;
4014 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4015 SIVAL(pdata,4,0);
4016 pdata += 8;
4018 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4019 SIVAL(pdata,4,0);
4020 pdata += 8;
4022 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4023 pdata += 4;
4025 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4026 devno = psbuf->st_ex_rdev;
4027 } else {
4028 devno = psbuf->st_ex_dev;
4031 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4032 SIVAL(pdata,4,0);
4033 pdata += 8;
4035 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4036 SIVAL(pdata,4,0);
4037 pdata += 8;
4039 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4040 pdata += 8;
4042 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4043 SIVAL(pdata,4,0);
4044 pdata += 8;
4046 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4047 SIVAL(pdata,4,0);
4048 pdata += 8;
4050 return pdata;
4053 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4054 * the chflags(2) (or equivalent) flags.
4056 * XXX: this really should be behind the VFS interface. To do this, we would
4057 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4058 * Each VFS module could then implement its own mapping as appropriate for the
4059 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4061 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4062 info2_flags_map[] =
4064 #ifdef UF_NODUMP
4065 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4066 #endif
4068 #ifdef UF_IMMUTABLE
4069 { UF_IMMUTABLE, EXT_IMMUTABLE },
4070 #endif
4072 #ifdef UF_APPEND
4073 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4074 #endif
4076 #ifdef UF_HIDDEN
4077 { UF_HIDDEN, EXT_HIDDEN },
4078 #endif
4080 /* Do not remove. We need to guarantee that this array has at least one
4081 * entry to build on HP-UX.
4083 { 0, 0 }
4087 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4088 uint32 *smb_fflags, uint32 *smb_fmask)
4090 int i;
4092 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4093 *smb_fmask |= info2_flags_map[i].smb_fflag;
4094 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4095 *smb_fflags |= info2_flags_map[i].smb_fflag;
4100 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4101 const uint32 smb_fflags,
4102 const uint32 smb_fmask,
4103 int *stat_fflags)
4105 uint32 max_fmask = 0;
4106 int i;
4108 *stat_fflags = psbuf->st_ex_flags;
4110 /* For each flags requested in smb_fmask, check the state of the
4111 * corresponding flag in smb_fflags and set or clear the matching
4112 * stat flag.
4115 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4116 max_fmask |= info2_flags_map[i].smb_fflag;
4117 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4118 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4119 *stat_fflags |= info2_flags_map[i].stat_fflag;
4120 } else {
4121 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4126 /* If smb_fmask is asking to set any bits that are not supported by
4127 * our flag mappings, we should fail.
4129 if ((smb_fmask & max_fmask) != smb_fmask) {
4130 return False;
4133 return True;
4137 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4138 * of file flags and birth (create) time.
4140 static char *store_file_unix_basic_info2(connection_struct *conn,
4141 char *pdata,
4142 files_struct *fsp,
4143 const SMB_STRUCT_STAT *psbuf)
4145 uint32 file_flags = 0;
4146 uint32 flags_mask = 0;
4148 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4150 /* Create (birth) time 64 bit */
4151 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4152 pdata += 8;
4154 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4155 SIVAL(pdata, 0, file_flags); /* flags */
4156 SIVAL(pdata, 4, flags_mask); /* mask */
4157 pdata += 8;
4159 return pdata;
4162 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4163 const struct stream_struct *streams,
4164 char *data,
4165 unsigned int max_data_bytes,
4166 unsigned int *data_size)
4168 unsigned int i;
4169 unsigned int ofs = 0;
4171 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4172 unsigned int next_offset;
4173 size_t namelen;
4174 smb_ucs2_t *namebuf;
4176 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4177 streams[i].name, &namelen) ||
4178 namelen <= 2)
4180 return NT_STATUS_INVALID_PARAMETER;
4184 * name_buf is now null-terminated, we need to marshall as not
4185 * terminated
4188 namelen -= 2;
4190 SIVAL(data, ofs+4, namelen);
4191 SOFF_T(data, ofs+8, streams[i].size);
4192 SOFF_T(data, ofs+16, streams[i].alloc_size);
4193 memcpy(data+ofs+24, namebuf, namelen);
4194 TALLOC_FREE(namebuf);
4196 next_offset = ofs + 24 + namelen;
4198 if (i == num_streams-1) {
4199 SIVAL(data, ofs, 0);
4201 else {
4202 unsigned int align = ndr_align_size(next_offset, 8);
4204 memset(data+next_offset, 0, align);
4205 next_offset += align;
4207 SIVAL(data, ofs, next_offset - ofs);
4208 ofs = next_offset;
4211 ofs = next_offset;
4214 *data_size = ofs;
4216 return NT_STATUS_OK;
4219 /****************************************************************************
4220 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4221 ****************************************************************************/
4223 static void call_trans2qpipeinfo(connection_struct *conn,
4224 struct smb_request *req,
4225 unsigned int tran_call,
4226 char **pparams, int total_params,
4227 char **ppdata, int total_data,
4228 unsigned int max_data_bytes)
4230 char *params = *pparams;
4231 char *pdata = *ppdata;
4232 unsigned int data_size = 0;
4233 unsigned int param_size = 2;
4234 uint16 info_level;
4235 files_struct *fsp;
4237 if (!params) {
4238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4239 return;
4242 if (total_params < 4) {
4243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4244 return;
4247 fsp = file_fsp(req, SVAL(params,0));
4248 if (!fsp_is_np(fsp)) {
4249 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4250 return;
4253 info_level = SVAL(params,2);
4255 *pparams = (char *)SMB_REALLOC(*pparams,2);
4256 if (*pparams == NULL) {
4257 reply_nterror(req, NT_STATUS_NO_MEMORY);
4258 return;
4260 params = *pparams;
4261 SSVAL(params,0,0);
4262 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4263 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4264 if (*ppdata == NULL ) {
4265 reply_nterror(req, NT_STATUS_NO_MEMORY);
4266 return;
4268 pdata = *ppdata;
4270 switch (info_level) {
4271 case SMB_FILE_STANDARD_INFORMATION:
4272 memset(pdata,0,24);
4273 SOFF_T(pdata,0,4096LL);
4274 SIVAL(pdata,16,1);
4275 SIVAL(pdata,20,1);
4276 data_size = 24;
4277 break;
4279 default:
4280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4281 return;
4284 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4285 max_data_bytes);
4287 return;
4290 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4291 TALLOC_CTX *mem_ctx,
4292 uint16_t info_level,
4293 files_struct *fsp,
4294 struct smb_filename *smb_fname,
4295 bool delete_pending,
4296 struct timespec write_time_ts,
4297 struct ea_list *ea_list,
4298 int lock_data_count,
4299 char *lock_data,
4300 uint16_t flags2,
4301 unsigned int max_data_bytes,
4302 char **ppdata,
4303 unsigned int *pdata_size)
4305 char *pdata = *ppdata;
4306 char *dstart, *dend;
4307 unsigned int data_size;
4308 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4309 time_t create_time, mtime, atime, c_time;
4310 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4311 char *p;
4312 char *base_name;
4313 char *dos_fname;
4314 int mode;
4315 int nlink;
4316 NTSTATUS status;
4317 uint64_t file_size = 0;
4318 uint64_t pos = 0;
4319 uint64_t allocation_size = 0;
4320 uint64_t file_index = 0;
4321 uint32_t access_mask = 0;
4323 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4324 return NT_STATUS_INVALID_LEVEL;
4327 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4328 smb_fname_str_dbg(smb_fname),
4329 fsp_fnum_dbg(fsp),
4330 info_level, max_data_bytes));
4332 mode = dos_mode(conn, smb_fname);
4333 nlink = psbuf->st_ex_nlink;
4335 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4336 nlink = 1;
4339 if ((nlink > 0) && delete_pending) {
4340 nlink -= 1;
4343 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4344 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4345 if (*ppdata == NULL) {
4346 return NT_STATUS_NO_MEMORY;
4348 pdata = *ppdata;
4349 dstart = pdata;
4350 dend = dstart + data_size - 1;
4352 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4353 update_stat_ex_mtime(psbuf, write_time_ts);
4356 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4357 mtime_ts = psbuf->st_ex_mtime;
4358 atime_ts = psbuf->st_ex_atime;
4359 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4361 if (lp_dos_filetime_resolution(SNUM(conn))) {
4362 dos_filetime_timespec(&create_time_ts);
4363 dos_filetime_timespec(&mtime_ts);
4364 dos_filetime_timespec(&atime_ts);
4365 dos_filetime_timespec(&ctime_ts);
4368 create_time = convert_timespec_to_time_t(create_time_ts);
4369 mtime = convert_timespec_to_time_t(mtime_ts);
4370 atime = convert_timespec_to_time_t(atime_ts);
4371 c_time = convert_timespec_to_time_t(ctime_ts);
4373 p = strrchr_m(smb_fname->base_name,'/');
4374 if (!p)
4375 base_name = smb_fname->base_name;
4376 else
4377 base_name = p+1;
4379 /* NT expects the name to be in an exact form of the *full*
4380 filename. See the trans2 torture test */
4381 if (ISDOT(base_name)) {
4382 dos_fname = talloc_strdup(mem_ctx, "\\");
4383 if (!dos_fname) {
4384 return NT_STATUS_NO_MEMORY;
4386 } else {
4387 dos_fname = talloc_asprintf(mem_ctx,
4388 "\\%s",
4389 smb_fname->base_name);
4390 if (!dos_fname) {
4391 return NT_STATUS_NO_MEMORY;
4393 if (is_ntfs_stream_smb_fname(smb_fname)) {
4394 dos_fname = talloc_asprintf(dos_fname, "%s",
4395 smb_fname->stream_name);
4396 if (!dos_fname) {
4397 return NT_STATUS_NO_MEMORY;
4401 string_replace(dos_fname, '/', '\\');
4404 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4406 if (!fsp) {
4407 /* Do we have this path open ? */
4408 files_struct *fsp1;
4409 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4410 fsp1 = file_find_di_first(conn->sconn, fileid);
4411 if (fsp1 && fsp1->initial_allocation_size) {
4412 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4416 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4417 file_size = get_file_size_stat(psbuf);
4420 if (fsp) {
4421 pos = fsp->fh->position_information;
4424 if (fsp) {
4425 access_mask = fsp->access_mask;
4426 } else {
4427 /* GENERIC_EXECUTE mapping from Windows */
4428 access_mask = 0x12019F;
4431 /* This should be an index number - looks like
4432 dev/ino to me :-)
4434 I think this causes us to fail the IFSKIT
4435 BasicFileInformationTest. -tpot */
4436 file_index = get_FileIndex(conn, psbuf);
4438 switch (info_level) {
4439 case SMB_INFO_STANDARD:
4440 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4441 data_size = 22;
4442 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4443 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4444 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4445 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4446 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4447 SSVAL(pdata,l1_attrFile,mode);
4448 break;
4450 case SMB_INFO_QUERY_EA_SIZE:
4452 unsigned int ea_size =
4453 estimate_ea_size(conn, fsp,
4454 smb_fname);
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4456 data_size = 26;
4457 srv_put_dos_date2(pdata,0,create_time);
4458 srv_put_dos_date2(pdata,4,atime);
4459 srv_put_dos_date2(pdata,8,mtime); /* write time */
4460 SIVAL(pdata,12,(uint32)file_size);
4461 SIVAL(pdata,16,(uint32)allocation_size);
4462 SSVAL(pdata,20,mode);
4463 SIVAL(pdata,22,ea_size);
4464 break;
4467 case SMB_INFO_IS_NAME_VALID:
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4469 if (fsp) {
4470 /* os/2 needs this ? really ?*/
4471 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4473 /* This is only reached for qpathinfo */
4474 data_size = 0;
4475 break;
4477 case SMB_INFO_QUERY_EAS_FROM_LIST:
4479 size_t total_ea_len = 0;
4480 struct ea_list *ea_file_list = NULL;
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4483 status =
4484 get_ea_list_from_file(mem_ctx, conn, fsp,
4485 smb_fname,
4486 &total_ea_len, &ea_file_list);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 return status;
4491 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4493 if (!ea_list || (total_ea_len > data_size)) {
4494 data_size = 4;
4495 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4496 break;
4499 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4500 break;
4503 case SMB_INFO_QUERY_ALL_EAS:
4505 /* We have data_size bytes to put EA's into. */
4506 size_t total_ea_len = 0;
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4509 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4510 smb_fname,
4511 &total_ea_len, &ea_list);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 return status;
4516 if (!ea_list || (total_ea_len > data_size)) {
4517 data_size = 4;
4518 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4519 break;
4522 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4523 break;
4526 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4528 /* This is FileFullEaInformation - 0xF which maps to
4529 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4531 /* We have data_size bytes to put EA's into. */
4532 size_t total_ea_len = 0;
4533 struct ea_list *ea_file_list = NULL;
4535 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4537 /*TODO: add filtering and index handling */
4539 status =
4540 get_ea_list_from_file(mem_ctx, conn, fsp,
4541 smb_fname,
4542 &total_ea_len, &ea_file_list);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 return status;
4546 if (!ea_file_list) {
4547 return NT_STATUS_NO_EAS_ON_FILE;
4550 status = fill_ea_chained_buffer(mem_ctx,
4551 pdata,
4552 data_size,
4553 &data_size,
4554 conn, ea_file_list);
4555 if (!NT_STATUS_IS_OK(status)) {
4556 return status;
4558 break;
4561 case SMB_FILE_BASIC_INFORMATION:
4562 case SMB_QUERY_FILE_BASIC_INFO:
4564 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4566 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4567 } else {
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4569 data_size = 40;
4570 SIVAL(pdata,36,0);
4572 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4573 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4574 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4575 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4576 SIVAL(pdata,32,mode);
4578 DEBUG(5,("SMB_QFBI - "));
4579 DEBUG(5,("create: %s ", ctime(&create_time)));
4580 DEBUG(5,("access: %s ", ctime(&atime)));
4581 DEBUG(5,("write: %s ", ctime(&mtime)));
4582 DEBUG(5,("change: %s ", ctime(&c_time)));
4583 DEBUG(5,("mode: %x\n", mode));
4584 break;
4586 case SMB_FILE_STANDARD_INFORMATION:
4587 case SMB_QUERY_FILE_STANDARD_INFO:
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4590 data_size = 24;
4591 SOFF_T(pdata,0,allocation_size);
4592 SOFF_T(pdata,8,file_size);
4593 SIVAL(pdata,16,nlink);
4594 SCVAL(pdata,20,delete_pending?1:0);
4595 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4596 SSVAL(pdata,22,0); /* Padding. */
4597 break;
4599 case SMB_FILE_EA_INFORMATION:
4600 case SMB_QUERY_FILE_EA_INFO:
4602 unsigned int ea_size =
4603 estimate_ea_size(conn, fsp, smb_fname);
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4605 data_size = 4;
4606 SIVAL(pdata,0,ea_size);
4607 break;
4610 /* Get the 8.3 name - used if NT SMB was negotiated. */
4611 case SMB_QUERY_FILE_ALT_NAME_INFO:
4612 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4614 int len;
4615 char mangled_name[13];
4616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4617 if (!name_to_8_3(base_name,mangled_name,
4618 True,conn->params)) {
4619 return NT_STATUS_NO_MEMORY;
4621 len = srvstr_push(dstart, flags2,
4622 pdata+4, mangled_name,
4623 PTR_DIFF(dend, pdata+4),
4624 STR_UNICODE);
4625 data_size = 4 + len;
4626 SIVAL(pdata,0,len);
4627 break;
4630 case SMB_QUERY_FILE_NAME_INFO:
4632 int len;
4634 this must be *exactly* right for ACLs on mapped drives to work
4636 len = srvstr_push(dstart, flags2,
4637 pdata+4, dos_fname,
4638 PTR_DIFF(dend, pdata+4),
4639 STR_UNICODE);
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4641 data_size = 4 + len;
4642 SIVAL(pdata,0,len);
4643 break;
4646 case SMB_FILE_ALLOCATION_INFORMATION:
4647 case SMB_QUERY_FILE_ALLOCATION_INFO:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4649 data_size = 8;
4650 SOFF_T(pdata,0,allocation_size);
4651 break;
4653 case SMB_FILE_END_OF_FILE_INFORMATION:
4654 case SMB_QUERY_FILE_END_OF_FILEINFO:
4655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4656 data_size = 8;
4657 SOFF_T(pdata,0,file_size);
4658 break;
4660 case SMB_QUERY_FILE_ALL_INFO:
4661 case SMB_FILE_ALL_INFORMATION:
4663 int len;
4664 unsigned int ea_size =
4665 estimate_ea_size(conn, fsp, smb_fname);
4666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4667 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4668 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4669 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4670 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4671 SIVAL(pdata,32,mode);
4672 SIVAL(pdata,36,0); /* padding. */
4673 pdata += 40;
4674 SOFF_T(pdata,0,allocation_size);
4675 SOFF_T(pdata,8,file_size);
4676 SIVAL(pdata,16,nlink);
4677 SCVAL(pdata,20,delete_pending);
4678 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4679 SSVAL(pdata,22,0);
4680 pdata += 24;
4681 SIVAL(pdata,0,ea_size);
4682 pdata += 4; /* EA info */
4683 len = srvstr_push(dstart, flags2,
4684 pdata+4, dos_fname,
4685 PTR_DIFF(dend, pdata+4),
4686 STR_UNICODE);
4687 SIVAL(pdata,0,len);
4688 pdata += 4 + len;
4689 data_size = PTR_DIFF(pdata,(*ppdata));
4690 break;
4693 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4695 int len;
4696 unsigned int ea_size =
4697 estimate_ea_size(conn, fsp, smb_fname);
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4699 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4700 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4701 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4702 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4703 SIVAL(pdata, 0x20, mode);
4704 SIVAL(pdata, 0x24, 0); /* padding. */
4705 SBVAL(pdata, 0x28, allocation_size);
4706 SBVAL(pdata, 0x30, file_size);
4707 SIVAL(pdata, 0x38, nlink);
4708 SCVAL(pdata, 0x3C, delete_pending);
4709 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4710 SSVAL(pdata, 0x3E, 0); /* padding */
4711 SBVAL(pdata, 0x40, file_index);
4712 SIVAL(pdata, 0x48, ea_size);
4713 SIVAL(pdata, 0x4C, access_mask);
4714 SBVAL(pdata, 0x50, pos);
4715 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4716 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4718 pdata += 0x60;
4720 len = srvstr_push(dstart, flags2,
4721 pdata+4, dos_fname,
4722 PTR_DIFF(dend, pdata+4),
4723 STR_UNICODE);
4724 SIVAL(pdata,0,len);
4725 pdata += 4 + len;
4726 data_size = PTR_DIFF(pdata,(*ppdata));
4727 break;
4729 case SMB_FILE_INTERNAL_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4732 SBVAL(pdata, 0, file_index);
4733 data_size = 8;
4734 break;
4736 case SMB_FILE_ACCESS_INFORMATION:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4738 SIVAL(pdata, 0, access_mask);
4739 data_size = 4;
4740 break;
4742 case SMB_FILE_NAME_INFORMATION:
4743 /* Pathname with leading '\'. */
4745 size_t byte_len;
4746 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4748 SIVAL(pdata,0,byte_len);
4749 data_size = 4 + byte_len;
4750 break;
4753 case SMB_FILE_DISPOSITION_INFORMATION:
4754 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4755 data_size = 1;
4756 SCVAL(pdata,0,delete_pending);
4757 break;
4759 case SMB_FILE_POSITION_INFORMATION:
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4761 data_size = 8;
4762 SOFF_T(pdata,0,pos);
4763 break;
4765 case SMB_FILE_MODE_INFORMATION:
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4767 SIVAL(pdata,0,mode);
4768 data_size = 4;
4769 break;
4771 case SMB_FILE_ALIGNMENT_INFORMATION:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4773 SIVAL(pdata,0,0); /* No alignment needed. */
4774 data_size = 4;
4775 break;
4778 * NT4 server just returns "invalid query" to this - if we try
4779 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4780 * want this. JRA.
4782 /* The first statement above is false - verified using Thursby
4783 * client against NT4 -- gcolley.
4785 case SMB_QUERY_FILE_STREAM_INFO:
4786 case SMB_FILE_STREAM_INFORMATION: {
4787 unsigned int num_streams = 0;
4788 struct stream_struct *streams = NULL;
4790 DEBUG(10,("smbd_do_qfilepathinfo: "
4791 "SMB_FILE_STREAM_INFORMATION\n"));
4793 if (is_ntfs_stream_smb_fname(smb_fname)) {
4794 return NT_STATUS_INVALID_PARAMETER;
4797 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4798 talloc_tos(), &num_streams, &streams);
4800 if (!NT_STATUS_IS_OK(status)) {
4801 DEBUG(10, ("could not get stream info: %s\n",
4802 nt_errstr(status)));
4803 return status;
4806 status = marshall_stream_info(num_streams, streams,
4807 pdata, max_data_bytes,
4808 &data_size);
4810 if (!NT_STATUS_IS_OK(status)) {
4811 DEBUG(10, ("marshall_stream_info failed: %s\n",
4812 nt_errstr(status)));
4813 return status;
4816 TALLOC_FREE(streams);
4818 break;
4820 case SMB_QUERY_COMPRESSION_INFO:
4821 case SMB_FILE_COMPRESSION_INFORMATION:
4822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4823 SOFF_T(pdata,0,file_size);
4824 SIVAL(pdata,8,0); /* ??? */
4825 SIVAL(pdata,12,0); /* ??? */
4826 data_size = 16;
4827 break;
4829 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4831 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4832 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4833 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4834 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4835 SOFF_T(pdata,32,allocation_size);
4836 SOFF_T(pdata,40,file_size);
4837 SIVAL(pdata,48,mode);
4838 SIVAL(pdata,52,0); /* ??? */
4839 data_size = 56;
4840 break;
4842 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4844 SIVAL(pdata,0,mode);
4845 SIVAL(pdata,4,0);
4846 data_size = 8;
4847 break;
4850 * CIFS UNIX Extensions.
4853 case SMB_QUERY_FILE_UNIX_BASIC:
4855 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4856 data_size = PTR_DIFF(pdata,(*ppdata));
4858 DEBUG(4,("smbd_do_qfilepathinfo: "
4859 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4860 dump_data(4, (uint8_t *)(*ppdata), data_size);
4862 break;
4864 case SMB_QUERY_FILE_UNIX_INFO2:
4866 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4867 data_size = PTR_DIFF(pdata,(*ppdata));
4870 int i;
4871 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4873 for (i=0; i<100; i++)
4874 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4875 DEBUG(4,("\n"));
4878 break;
4880 case SMB_QUERY_FILE_UNIX_LINK:
4882 int len;
4883 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4885 if (!buffer) {
4886 return NT_STATUS_NO_MEMORY;
4889 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4890 #ifdef S_ISLNK
4891 if(!S_ISLNK(psbuf->st_ex_mode)) {
4892 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4894 #else
4895 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4896 #endif
4897 len = SMB_VFS_READLINK(conn,
4898 smb_fname->base_name,
4899 buffer, PATH_MAX);
4900 if (len == -1) {
4901 return map_nt_error_from_unix(errno);
4903 buffer[len] = 0;
4904 len = srvstr_push(dstart, flags2,
4905 pdata, buffer,
4906 PTR_DIFF(dend, pdata),
4907 STR_TERMINATE);
4908 pdata += len;
4909 data_size = PTR_DIFF(pdata,(*ppdata));
4911 break;
4914 #if defined(HAVE_POSIX_ACLS)
4915 case SMB_QUERY_POSIX_ACL:
4917 SMB_ACL_T file_acl = NULL;
4918 SMB_ACL_T def_acl = NULL;
4919 uint16 num_file_acls = 0;
4920 uint16 num_def_acls = 0;
4922 if (fsp && fsp->fh->fd != -1) {
4923 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4924 } else {
4925 file_acl =
4926 SMB_VFS_SYS_ACL_GET_FILE(conn,
4927 smb_fname->base_name,
4928 SMB_ACL_TYPE_ACCESS);
4931 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4932 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4933 "not implemented on "
4934 "filesystem containing %s\n",
4935 smb_fname->base_name));
4936 return NT_STATUS_NOT_IMPLEMENTED;
4939 if (S_ISDIR(psbuf->st_ex_mode)) {
4940 if (fsp && fsp->is_directory) {
4941 def_acl =
4942 SMB_VFS_SYS_ACL_GET_FILE(
4943 conn,
4944 fsp->fsp_name->base_name,
4945 SMB_ACL_TYPE_DEFAULT);
4946 } else {
4947 def_acl =
4948 SMB_VFS_SYS_ACL_GET_FILE(
4949 conn,
4950 smb_fname->base_name,
4951 SMB_ACL_TYPE_DEFAULT);
4953 def_acl = free_empty_sys_acl(conn, def_acl);
4956 num_file_acls = count_acl_entries(conn, file_acl);
4957 num_def_acls = count_acl_entries(conn, def_acl);
4959 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4960 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4961 data_size,
4962 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4963 SMB_POSIX_ACL_HEADER_SIZE) ));
4964 if (file_acl) {
4965 TALLOC_FREE(file_acl);
4967 if (def_acl) {
4968 TALLOC_FREE(def_acl);
4970 return NT_STATUS_BUFFER_TOO_SMALL;
4973 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4974 SSVAL(pdata,2,num_file_acls);
4975 SSVAL(pdata,4,num_def_acls);
4976 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4977 if (file_acl) {
4978 TALLOC_FREE(file_acl);
4980 if (def_acl) {
4981 TALLOC_FREE(def_acl);
4983 return NT_STATUS_INTERNAL_ERROR;
4985 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4986 if (file_acl) {
4987 TALLOC_FREE(file_acl);
4989 if (def_acl) {
4990 TALLOC_FREE(def_acl);
4992 return NT_STATUS_INTERNAL_ERROR;
4995 if (file_acl) {
4996 TALLOC_FREE(file_acl);
4998 if (def_acl) {
4999 TALLOC_FREE(def_acl);
5001 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5002 break;
5004 #endif
5007 case SMB_QUERY_POSIX_LOCK:
5009 uint64_t count;
5010 uint64_t offset;
5011 uint64_t smblctx;
5012 enum brl_type lock_type;
5014 /* We need an open file with a real fd for this. */
5015 if (!fsp || fsp->fh->fd == -1) {
5016 return NT_STATUS_INVALID_LEVEL;
5019 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5020 return NT_STATUS_INVALID_PARAMETER;
5023 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5024 case POSIX_LOCK_TYPE_READ:
5025 lock_type = READ_LOCK;
5026 break;
5027 case POSIX_LOCK_TYPE_WRITE:
5028 lock_type = WRITE_LOCK;
5029 break;
5030 case POSIX_LOCK_TYPE_UNLOCK:
5031 default:
5032 /* There's no point in asking for an unlock... */
5033 return NT_STATUS_INVALID_PARAMETER;
5036 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5037 #if defined(HAVE_LONGLONG)
5038 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5039 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5040 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5041 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5042 #else /* HAVE_LONGLONG */
5043 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5044 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5045 #endif /* HAVE_LONGLONG */
5047 status = query_lock(fsp,
5048 &smblctx,
5049 &count,
5050 &offset,
5051 &lock_type,
5052 POSIX_LOCK);
5054 if (ERROR_WAS_LOCK_DENIED(status)) {
5055 /* Here we need to report who has it locked... */
5056 data_size = POSIX_LOCK_DATA_SIZE;
5058 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5059 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5060 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5061 #if defined(HAVE_LONGLONG)
5062 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5063 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5064 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5065 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5066 #else /* HAVE_LONGLONG */
5067 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5068 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5069 #endif /* HAVE_LONGLONG */
5071 } else if (NT_STATUS_IS_OK(status)) {
5072 /* For success we just return a copy of what we sent
5073 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5074 data_size = POSIX_LOCK_DATA_SIZE;
5075 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5076 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5077 } else {
5078 return status;
5080 break;
5083 default:
5084 return NT_STATUS_INVALID_LEVEL;
5087 *pdata_size = data_size;
5088 return NT_STATUS_OK;
5091 /****************************************************************************
5092 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5093 file name or file id).
5094 ****************************************************************************/
5096 static void call_trans2qfilepathinfo(connection_struct *conn,
5097 struct smb_request *req,
5098 unsigned int tran_call,
5099 char **pparams, int total_params,
5100 char **ppdata, int total_data,
5101 unsigned int max_data_bytes)
5103 char *params = *pparams;
5104 char *pdata = *ppdata;
5105 uint16 info_level;
5106 unsigned int data_size = 0;
5107 unsigned int param_size = 2;
5108 struct smb_filename *smb_fname = NULL;
5109 bool delete_pending = False;
5110 struct timespec write_time_ts;
5111 files_struct *fsp = NULL;
5112 struct file_id fileid;
5113 struct ea_list *ea_list = NULL;
5114 int lock_data_count = 0;
5115 char *lock_data = NULL;
5116 NTSTATUS status = NT_STATUS_OK;
5118 if (!params) {
5119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5120 return;
5123 ZERO_STRUCT(write_time_ts);
5125 if (tran_call == TRANSACT2_QFILEINFO) {
5126 if (total_params < 4) {
5127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5128 return;
5131 if (IS_IPC(conn)) {
5132 call_trans2qpipeinfo(conn, req, tran_call,
5133 pparams, total_params,
5134 ppdata, total_data,
5135 max_data_bytes);
5136 return;
5139 fsp = file_fsp(req, SVAL(params,0));
5140 info_level = SVAL(params,2);
5142 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5144 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5145 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5146 return;
5149 /* Initial check for valid fsp ptr. */
5150 if (!check_fsp_open(conn, req, fsp)) {
5151 return;
5154 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5155 &smb_fname);
5156 if (!NT_STATUS_IS_OK(status)) {
5157 reply_nterror(req, status);
5158 return;
5161 if(fsp->fake_file_handle) {
5163 * This is actually for the QUOTA_FAKE_FILE --metze
5166 /* We know this name is ok, it's already passed the checks. */
5168 } else if(fsp->fh->fd == -1) {
5170 * This is actually a QFILEINFO on a directory
5171 * handle (returned from an NT SMB). NT5.0 seems
5172 * to do this call. JRA.
5175 if (INFO_LEVEL_IS_UNIX(info_level)) {
5176 /* Always do lstat for UNIX calls. */
5177 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "SMB_VFS_LSTAT of %s failed "
5180 "(%s)\n",
5181 smb_fname_str_dbg(smb_fname),
5182 strerror(errno)));
5183 reply_nterror(req,
5184 map_nt_error_from_unix(errno));
5185 return;
5187 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "SMB_VFS_STAT of %s failed (%s)\n",
5190 smb_fname_str_dbg(smb_fname),
5191 strerror(errno)));
5192 reply_nterror(req,
5193 map_nt_error_from_unix(errno));
5194 return;
5197 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5198 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5199 } else {
5201 * Original code - this is an open file.
5203 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5204 DEBUG(3, ("fstat of %s failed (%s)\n",
5205 fsp_fnum_dbg(fsp), strerror(errno)));
5206 reply_nterror(req,
5207 map_nt_error_from_unix(errno));
5208 return;
5210 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5211 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5214 } else {
5215 uint32_t name_hash;
5216 char *fname = NULL;
5217 uint32_t ucf_flags = 0;
5219 /* qpathinfo */
5220 if (total_params < 7) {
5221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5222 return;
5225 info_level = SVAL(params,0);
5227 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5229 if (INFO_LEVEL_IS_UNIX(info_level)) {
5230 if (!lp_unix_extensions()) {
5231 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5232 return;
5234 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5235 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5236 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5237 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5241 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5242 total_params - 6,
5243 STR_TERMINATE, &status);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 reply_nterror(req, status);
5246 return;
5249 status = filename_convert(req,
5250 conn,
5251 req->flags2 & FLAGS2_DFS_PATHNAMES,
5252 fname,
5253 ucf_flags,
5254 NULL,
5255 &smb_fname);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5258 reply_botherror(req,
5259 NT_STATUS_PATH_NOT_COVERED,
5260 ERRSRV, ERRbadpath);
5261 return;
5263 reply_nterror(req, status);
5264 return;
5267 /* If this is a stream, check if there is a delete_pending. */
5268 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5269 && is_ntfs_stream_smb_fname(smb_fname)) {
5270 struct smb_filename *smb_fname_base = NULL;
5272 /* Create an smb_filename with stream_name == NULL. */
5273 status =
5274 create_synthetic_smb_fname(talloc_tos(),
5275 smb_fname->base_name,
5276 NULL, NULL,
5277 &smb_fname_base);
5278 if (!NT_STATUS_IS_OK(status)) {
5279 reply_nterror(req, status);
5280 return;
5283 if (INFO_LEVEL_IS_UNIX(info_level)) {
5284 /* Always do lstat for UNIX calls. */
5285 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5286 DEBUG(3,("call_trans2qfilepathinfo: "
5287 "SMB_VFS_LSTAT of %s failed "
5288 "(%s)\n",
5289 smb_fname_str_dbg(smb_fname_base),
5290 strerror(errno)));
5291 TALLOC_FREE(smb_fname_base);
5292 reply_nterror(req,
5293 map_nt_error_from_unix(errno));
5294 return;
5296 } else {
5297 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "fileinfo of %s failed "
5300 "(%s)\n",
5301 smb_fname_str_dbg(smb_fname_base),
5302 strerror(errno)));
5303 TALLOC_FREE(smb_fname_base);
5304 reply_nterror(req,
5305 map_nt_error_from_unix(errno));
5306 return;
5310 status = file_name_hash(conn,
5311 smb_fname_str_dbg(smb_fname_base),
5312 &name_hash);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 TALLOC_FREE(smb_fname_base);
5315 reply_nterror(req, status);
5316 return;
5319 fileid = vfs_file_id_from_sbuf(conn,
5320 &smb_fname_base->st);
5321 TALLOC_FREE(smb_fname_base);
5322 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5323 if (delete_pending) {
5324 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5325 return;
5329 if (INFO_LEVEL_IS_UNIX(info_level)) {
5330 /* Always do lstat for UNIX calls. */
5331 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5332 DEBUG(3,("call_trans2qfilepathinfo: "
5333 "SMB_VFS_LSTAT of %s failed (%s)\n",
5334 smb_fname_str_dbg(smb_fname),
5335 strerror(errno)));
5336 reply_nterror(req,
5337 map_nt_error_from_unix(errno));
5338 return;
5341 } else {
5342 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5343 DEBUG(3,("call_trans2qfilepathinfo: "
5344 "SMB_VFS_STAT of %s failed (%s)\n",
5345 smb_fname_str_dbg(smb_fname),
5346 strerror(errno)));
5347 reply_nterror(req,
5348 map_nt_error_from_unix(errno));
5349 return;
5353 status = file_name_hash(conn,
5354 smb_fname_str_dbg(smb_fname),
5355 &name_hash);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 reply_nterror(req, status);
5358 return;
5361 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5362 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5363 if (delete_pending) {
5364 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5365 return;
5369 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5370 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5371 fsp_fnum_dbg(fsp),
5372 info_level,tran_call,total_data));
5374 /* Pull out any data sent here before we realloc. */
5375 switch (info_level) {
5376 case SMB_INFO_QUERY_EAS_FROM_LIST:
5378 /* Pull any EA list from the data portion. */
5379 uint32 ea_size;
5381 if (total_data < 4) {
5382 reply_nterror(
5383 req, NT_STATUS_INVALID_PARAMETER);
5384 return;
5386 ea_size = IVAL(pdata,0);
5388 if (total_data > 0 && ea_size != total_data) {
5389 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5390 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5391 reply_nterror(
5392 req, NT_STATUS_INVALID_PARAMETER);
5393 return;
5396 if (!lp_ea_support(SNUM(conn))) {
5397 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5398 return;
5401 /* Pull out the list of names. */
5402 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5403 if (!ea_list) {
5404 reply_nterror(
5405 req, NT_STATUS_INVALID_PARAMETER);
5406 return;
5408 break;
5411 case SMB_QUERY_POSIX_LOCK:
5413 if (fsp == NULL || fsp->fh->fd == -1) {
5414 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5415 return;
5418 if (total_data != POSIX_LOCK_DATA_SIZE) {
5419 reply_nterror(
5420 req, NT_STATUS_INVALID_PARAMETER);
5421 return;
5424 /* Copy the lock range data. */
5425 lock_data = (char *)talloc_memdup(
5426 req, pdata, total_data);
5427 if (!lock_data) {
5428 reply_nterror(req, NT_STATUS_NO_MEMORY);
5429 return;
5431 lock_data_count = total_data;
5433 default:
5434 break;
5437 *pparams = (char *)SMB_REALLOC(*pparams,2);
5438 if (*pparams == NULL) {
5439 reply_nterror(req, NT_STATUS_NO_MEMORY);
5440 return;
5442 params = *pparams;
5443 SSVAL(params,0,0);
5446 * draft-leach-cifs-v1-spec-02.txt
5447 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5448 * says:
5450 * The requested information is placed in the Data portion of the
5451 * transaction response. For the information levels greater than 0x100,
5452 * the transaction response has 1 parameter word which should be
5453 * ignored by the client.
5455 * However Windows only follows this rule for the IS_NAME_VALID call.
5457 switch (info_level) {
5458 case SMB_INFO_IS_NAME_VALID:
5459 param_size = 0;
5460 break;
5463 if ((info_level & 0xFF00) == 0xFF00) {
5465 * We use levels that start with 0xFF00
5466 * internally to represent SMB2 specific levels
5468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5469 return;
5472 status = smbd_do_qfilepathinfo(conn, req, info_level,
5473 fsp, smb_fname,
5474 delete_pending, write_time_ts,
5475 ea_list,
5476 lock_data_count, lock_data,
5477 req->flags2, max_data_bytes,
5478 ppdata, &data_size);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 reply_nterror(req, status);
5481 return;
5484 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5485 max_data_bytes);
5487 return;
5490 /****************************************************************************
5491 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5492 code.
5493 ****************************************************************************/
5495 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5496 connection_struct *conn,
5497 struct smb_request *req,
5498 bool overwrite_if_exists,
5499 const struct smb_filename *smb_fname_old,
5500 struct smb_filename *smb_fname_new)
5502 NTSTATUS status = NT_STATUS_OK;
5504 /* source must already exist. */
5505 if (!VALID_STAT(smb_fname_old->st)) {
5506 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5509 if (VALID_STAT(smb_fname_new->st)) {
5510 if (overwrite_if_exists) {
5511 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5512 return NT_STATUS_FILE_IS_A_DIRECTORY;
5514 status = unlink_internals(conn,
5515 req,
5516 FILE_ATTRIBUTE_NORMAL,
5517 smb_fname_new,
5518 false);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 return status;
5522 } else {
5523 /* Disallow if newname already exists. */
5524 return NT_STATUS_OBJECT_NAME_COLLISION;
5528 /* No links from a directory. */
5529 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5530 return NT_STATUS_FILE_IS_A_DIRECTORY;
5533 /* Setting a hardlink to/from a stream isn't currently supported. */
5534 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5535 is_ntfs_stream_smb_fname(smb_fname_new)) {
5536 return NT_STATUS_INVALID_PARAMETER;
5539 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5540 smb_fname_old->base_name, smb_fname_new->base_name));
5542 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5543 smb_fname_new->base_name) != 0) {
5544 status = map_nt_error_from_unix(errno);
5545 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5546 nt_errstr(status), smb_fname_old->base_name,
5547 smb_fname_new->base_name));
5549 return status;
5552 /****************************************************************************
5553 Deal with setting the time from any of the setfilepathinfo functions.
5554 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5555 calling this function.
5556 ****************************************************************************/
5558 NTSTATUS smb_set_file_time(connection_struct *conn,
5559 files_struct *fsp,
5560 const struct smb_filename *smb_fname,
5561 struct smb_file_time *ft,
5562 bool setting_write_time)
5564 struct smb_filename smb_fname_base;
5565 uint32 action =
5566 FILE_NOTIFY_CHANGE_LAST_ACCESS
5567 |FILE_NOTIFY_CHANGE_LAST_WRITE
5568 |FILE_NOTIFY_CHANGE_CREATION;
5570 if (!VALID_STAT(smb_fname->st)) {
5571 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5574 /* get some defaults (no modifications) if any info is zero or -1. */
5575 if (null_timespec(ft->create_time)) {
5576 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5579 if (null_timespec(ft->atime)) {
5580 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5583 if (null_timespec(ft->mtime)) {
5584 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5587 if (!setting_write_time) {
5588 /* ft->mtime comes from change time, not write time. */
5589 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5592 /* Ensure the resolution is the correct for
5593 * what we can store on this filesystem. */
5595 round_timespec(conn->ts_res, &ft->create_time);
5596 round_timespec(conn->ts_res, &ft->ctime);
5597 round_timespec(conn->ts_res, &ft->atime);
5598 round_timespec(conn->ts_res, &ft->mtime);
5600 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5601 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5602 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5603 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5604 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5605 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5606 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5607 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5609 if (setting_write_time) {
5611 * This was a Windows setfileinfo on an open file.
5612 * NT does this a lot. We also need to
5613 * set the time here, as it can be read by
5614 * FindFirst/FindNext and with the patch for bug #2045
5615 * in smbd/fileio.c it ensures that this timestamp is
5616 * kept sticky even after a write. We save the request
5617 * away and will set it on file close and after a write. JRA.
5620 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5621 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5623 if (fsp != NULL) {
5624 if (fsp->base_fsp) {
5625 set_sticky_write_time_fsp(fsp->base_fsp,
5626 ft->mtime);
5627 } else {
5628 set_sticky_write_time_fsp(fsp, ft->mtime);
5630 } else {
5631 set_sticky_write_time_path(
5632 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5633 ft->mtime);
5637 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5639 /* Always call ntimes on the base, even if a stream was passed in. */
5640 smb_fname_base = *smb_fname;
5641 smb_fname_base.stream_name = NULL;
5643 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5644 return map_nt_error_from_unix(errno);
5647 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5648 smb_fname->base_name);
5649 return NT_STATUS_OK;
5652 /****************************************************************************
5653 Deal with setting the dosmode from any of the setfilepathinfo functions.
5654 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5655 done before calling this function.
5656 ****************************************************************************/
5658 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5659 const struct smb_filename *smb_fname,
5660 uint32 dosmode)
5662 struct smb_filename *smb_fname_base = NULL;
5663 NTSTATUS status;
5665 if (!VALID_STAT(smb_fname->st)) {
5666 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5669 /* Always operate on the base_name, even if a stream was passed in. */
5670 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5671 NULL, &smb_fname->st,
5672 &smb_fname_base);
5673 if (!NT_STATUS_IS_OK(status)) {
5674 return status;
5677 if (dosmode) {
5678 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5679 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5680 } else {
5681 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5685 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5687 /* check the mode isn't different, before changing it */
5688 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5689 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5690 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5691 (unsigned int)dosmode));
5693 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5694 false)) {
5695 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5696 "%s failed (%s)\n",
5697 smb_fname_str_dbg(smb_fname_base),
5698 strerror(errno)));
5699 status = map_nt_error_from_unix(errno);
5700 goto out;
5703 status = NT_STATUS_OK;
5704 out:
5705 TALLOC_FREE(smb_fname_base);
5706 return status;
5709 /****************************************************************************
5710 Deal with setting the size from any of the setfilepathinfo functions.
5711 ****************************************************************************/
5713 static NTSTATUS smb_set_file_size(connection_struct *conn,
5714 struct smb_request *req,
5715 files_struct *fsp,
5716 const struct smb_filename *smb_fname,
5717 const SMB_STRUCT_STAT *psbuf,
5718 off_t size,
5719 bool fail_after_createfile)
5721 NTSTATUS status = NT_STATUS_OK;
5722 struct smb_filename *smb_fname_tmp = NULL;
5723 files_struct *new_fsp = NULL;
5725 if (!VALID_STAT(*psbuf)) {
5726 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5729 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5731 if (size == get_file_size_stat(psbuf)) {
5732 return NT_STATUS_OK;
5735 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5736 smb_fname_str_dbg(smb_fname), (double)size));
5738 if (fsp && fsp->fh->fd != -1) {
5739 /* Handle based call. */
5740 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5741 return NT_STATUS_ACCESS_DENIED;
5744 if (vfs_set_filelen(fsp, size) == -1) {
5745 return map_nt_error_from_unix(errno);
5747 trigger_write_time_update_immediate(fsp);
5748 return NT_STATUS_OK;
5751 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5752 if (!NT_STATUS_IS_OK(status)) {
5753 return status;
5756 smb_fname_tmp->st = *psbuf;
5758 status = SMB_VFS_CREATE_FILE(
5759 conn, /* conn */
5760 req, /* req */
5761 0, /* root_dir_fid */
5762 smb_fname_tmp, /* fname */
5763 FILE_WRITE_DATA, /* access_mask */
5764 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5765 FILE_SHARE_DELETE),
5766 FILE_OPEN, /* create_disposition*/
5767 0, /* create_options */
5768 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5769 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5770 0, /* allocation_size */
5771 0, /* private_flags */
5772 NULL, /* sd */
5773 NULL, /* ea_list */
5774 &new_fsp, /* result */
5775 NULL); /* pinfo */
5777 TALLOC_FREE(smb_fname_tmp);
5779 if (!NT_STATUS_IS_OK(status)) {
5780 /* NB. We check for open_was_deferred in the caller. */
5781 return status;
5784 /* See RAW-SFILEINFO-END-OF-FILE */
5785 if (fail_after_createfile) {
5786 close_file(req, new_fsp,NORMAL_CLOSE);
5787 return NT_STATUS_INVALID_LEVEL;
5790 if (vfs_set_filelen(new_fsp, size) == -1) {
5791 status = map_nt_error_from_unix(errno);
5792 close_file(req, new_fsp,NORMAL_CLOSE);
5793 return status;
5796 trigger_write_time_update_immediate(new_fsp);
5797 close_file(req, new_fsp,NORMAL_CLOSE);
5798 return NT_STATUS_OK;
5801 /****************************************************************************
5802 Deal with SMB_INFO_SET_EA.
5803 ****************************************************************************/
5805 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5806 const char *pdata,
5807 int total_data,
5808 files_struct *fsp,
5809 const struct smb_filename *smb_fname)
5811 struct ea_list *ea_list = NULL;
5812 TALLOC_CTX *ctx = NULL;
5813 NTSTATUS status = NT_STATUS_OK;
5815 if (total_data < 10) {
5817 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5818 length. They seem to have no effect. Bug #3212. JRA */
5820 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5821 /* We're done. We only get EA info in this call. */
5822 return NT_STATUS_OK;
5825 return NT_STATUS_INVALID_PARAMETER;
5828 if (IVAL(pdata,0) > total_data) {
5829 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5830 IVAL(pdata,0), (unsigned int)total_data));
5831 return NT_STATUS_INVALID_PARAMETER;
5834 ctx = talloc_tos();
5835 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5836 if (!ea_list) {
5837 return NT_STATUS_INVALID_PARAMETER;
5840 status = set_ea(conn, fsp, smb_fname, ea_list);
5842 return status;
5845 /****************************************************************************
5846 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5847 ****************************************************************************/
5849 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5850 const char *pdata,
5851 int total_data,
5852 files_struct *fsp)
5854 struct ea_list *ea_list = NULL;
5855 NTSTATUS status;
5857 if (!fsp) {
5858 return NT_STATUS_INVALID_HANDLE;
5861 if (!lp_ea_support(SNUM(conn))) {
5862 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5863 "EA's not supported.\n",
5864 (unsigned int)total_data));
5865 return NT_STATUS_EAS_NOT_SUPPORTED;
5868 if (total_data < 10) {
5869 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5870 "too small.\n",
5871 (unsigned int)total_data));
5872 return NT_STATUS_INVALID_PARAMETER;
5875 ea_list = read_nttrans_ea_list(talloc_tos(),
5876 pdata,
5877 total_data);
5879 if (!ea_list) {
5880 return NT_STATUS_INVALID_PARAMETER;
5883 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5885 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5886 smb_fname_str_dbg(fsp->fsp_name),
5887 nt_errstr(status) ));
5889 return status;
5893 /****************************************************************************
5894 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5895 ****************************************************************************/
5897 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5898 const char *pdata,
5899 int total_data,
5900 files_struct *fsp,
5901 struct smb_filename *smb_fname)
5903 NTSTATUS status = NT_STATUS_OK;
5904 bool delete_on_close;
5905 uint32 dosmode = 0;
5907 if (total_data < 1) {
5908 return NT_STATUS_INVALID_PARAMETER;
5911 if (fsp == NULL) {
5912 return NT_STATUS_INVALID_HANDLE;
5915 delete_on_close = (CVAL(pdata,0) ? True : False);
5916 dosmode = dos_mode(conn, smb_fname);
5918 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5919 "delete_on_close = %u\n",
5920 smb_fname_str_dbg(smb_fname),
5921 (unsigned int)dosmode,
5922 (unsigned int)delete_on_close ));
5924 if (delete_on_close) {
5925 status = can_set_delete_on_close(fsp, dosmode);
5926 if (!NT_STATUS_IS_OK(status)) {
5927 return status;
5931 /* The set is across all open files on this dev/inode pair. */
5932 if (!set_delete_on_close(fsp, delete_on_close,
5933 conn->session_info->security_token,
5934 conn->session_info->unix_token)) {
5935 return NT_STATUS_ACCESS_DENIED;
5937 return NT_STATUS_OK;
5940 /****************************************************************************
5941 Deal with SMB_FILE_POSITION_INFORMATION.
5942 ****************************************************************************/
5944 static NTSTATUS smb_file_position_information(connection_struct *conn,
5945 const char *pdata,
5946 int total_data,
5947 files_struct *fsp)
5949 uint64_t position_information;
5951 if (total_data < 8) {
5952 return NT_STATUS_INVALID_PARAMETER;
5955 if (fsp == NULL) {
5956 /* Ignore on pathname based set. */
5957 return NT_STATUS_OK;
5960 position_information = (uint64_t)IVAL(pdata,0);
5961 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5963 DEBUG(10,("smb_file_position_information: Set file position "
5964 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5965 (double)position_information));
5966 fsp->fh->position_information = position_information;
5967 return NT_STATUS_OK;
5970 /****************************************************************************
5971 Deal with SMB_FILE_MODE_INFORMATION.
5972 ****************************************************************************/
5974 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5975 const char *pdata,
5976 int total_data)
5978 uint32 mode;
5980 if (total_data < 4) {
5981 return NT_STATUS_INVALID_PARAMETER;
5983 mode = IVAL(pdata,0);
5984 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5985 return NT_STATUS_INVALID_PARAMETER;
5987 return NT_STATUS_OK;
5990 /****************************************************************************
5991 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5992 ****************************************************************************/
5994 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5995 struct smb_request *req,
5996 const char *pdata,
5997 int total_data,
5998 const struct smb_filename *smb_fname)
6000 char *link_target = NULL;
6001 const char *newname = smb_fname->base_name;
6002 TALLOC_CTX *ctx = talloc_tos();
6004 /* Set a symbolic link. */
6005 /* Don't allow this if follow links is false. */
6007 if (total_data == 0) {
6008 return NT_STATUS_INVALID_PARAMETER;
6011 if (!lp_symlinks(SNUM(conn))) {
6012 return NT_STATUS_ACCESS_DENIED;
6015 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6016 total_data, STR_TERMINATE);
6018 if (!link_target) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6023 newname, link_target ));
6025 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6026 return map_nt_error_from_unix(errno);
6029 return NT_STATUS_OK;
6032 /****************************************************************************
6033 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6034 ****************************************************************************/
6036 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6037 struct smb_request *req,
6038 const char *pdata, int total_data,
6039 struct smb_filename *smb_fname_new)
6041 char *oldname = NULL;
6042 struct smb_filename *smb_fname_old = NULL;
6043 TALLOC_CTX *ctx = talloc_tos();
6044 NTSTATUS status = NT_STATUS_OK;
6046 /* Set a hard link. */
6047 if (total_data == 0) {
6048 return NT_STATUS_INVALID_PARAMETER;
6051 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6052 total_data, STR_TERMINATE, &status);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 return status;
6057 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6058 smb_fname_str_dbg(smb_fname_new), oldname));
6060 status = filename_convert(ctx,
6061 conn,
6062 req->flags2 & FLAGS2_DFS_PATHNAMES,
6063 oldname,
6065 NULL,
6066 &smb_fname_old);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 return status;
6071 return hardlink_internals(ctx, conn, req, false,
6072 smb_fname_old, smb_fname_new);
6075 /****************************************************************************
6076 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6077 ****************************************************************************/
6079 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6080 struct smb_request *req,
6081 const char *pdata,
6082 int total_data,
6083 files_struct *fsp,
6084 struct smb_filename *smb_fname_src)
6086 bool overwrite;
6087 uint32_t len;
6088 char *newname = NULL;
6089 struct smb_filename *smb_fname_dst = NULL;
6090 NTSTATUS status = NT_STATUS_OK;
6091 TALLOC_CTX *ctx = talloc_tos();
6093 if (!fsp) {
6094 return NT_STATUS_INVALID_HANDLE;
6097 if (total_data < 20) {
6098 return NT_STATUS_INVALID_PARAMETER;
6101 overwrite = (CVAL(pdata,0) ? True : False);
6102 len = IVAL(pdata,16);
6104 if (len > (total_data - 20) || (len == 0)) {
6105 return NT_STATUS_INVALID_PARAMETER;
6108 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6109 &pdata[20], len, STR_TERMINATE,
6110 &status);
6111 if (!NT_STATUS_IS_OK(status)) {
6112 return status;
6115 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6116 newname));
6118 status = filename_convert(ctx,
6119 conn,
6120 req->flags2 & FLAGS2_DFS_PATHNAMES,
6121 newname,
6122 UCF_SAVE_LCOMP,
6123 NULL,
6124 &smb_fname_dst);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 return status;
6129 if (fsp->base_fsp) {
6130 /* newname must be a stream name. */
6131 if (newname[0] != ':') {
6132 return NT_STATUS_NOT_SUPPORTED;
6135 /* Create an smb_fname to call rename_internals_fsp() with. */
6136 status = create_synthetic_smb_fname(talloc_tos(),
6137 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6138 &smb_fname_dst);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 goto out;
6144 * Set the original last component, since
6145 * rename_internals_fsp() requires it.
6147 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6148 newname);
6149 if (smb_fname_dst->original_lcomp == NULL) {
6150 status = NT_STATUS_NO_MEMORY;
6151 goto out;
6156 DEBUG(10,("smb2_file_rename_information: "
6157 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6158 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6159 smb_fname_str_dbg(smb_fname_dst)));
6160 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6161 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6162 overwrite);
6164 out:
6165 TALLOC_FREE(smb_fname_dst);
6166 return status;
6169 static NTSTATUS smb_file_link_information(connection_struct *conn,
6170 struct smb_request *req,
6171 const char *pdata,
6172 int total_data,
6173 files_struct *fsp,
6174 struct smb_filename *smb_fname_src)
6176 bool overwrite;
6177 uint32_t len;
6178 char *newname = NULL;
6179 struct smb_filename *smb_fname_dst = NULL;
6180 NTSTATUS status = NT_STATUS_OK;
6181 TALLOC_CTX *ctx = talloc_tos();
6183 if (!fsp) {
6184 return NT_STATUS_INVALID_HANDLE;
6187 if (total_data < 20) {
6188 return NT_STATUS_INVALID_PARAMETER;
6191 overwrite = (CVAL(pdata,0) ? true : false);
6192 len = IVAL(pdata,16);
6194 if (len > (total_data - 20) || (len == 0)) {
6195 return NT_STATUS_INVALID_PARAMETER;
6198 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6199 &pdata[20], len, STR_TERMINATE,
6200 &status);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 return status;
6205 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6206 newname));
6208 status = filename_convert(ctx,
6209 conn,
6210 req->flags2 & FLAGS2_DFS_PATHNAMES,
6211 newname,
6212 UCF_SAVE_LCOMP,
6213 NULL,
6214 &smb_fname_dst);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 return status;
6219 if (fsp->base_fsp) {
6220 /* No stream names. */
6221 return NT_STATUS_NOT_SUPPORTED;
6224 DEBUG(10,("smb_file_link_information: "
6225 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6226 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6227 smb_fname_str_dbg(smb_fname_dst)));
6228 status = hardlink_internals(ctx,
6229 conn,
6230 req,
6231 overwrite,
6232 fsp->fsp_name,
6233 smb_fname_dst);
6235 TALLOC_FREE(smb_fname_dst);
6236 return status;
6239 /****************************************************************************
6240 Deal with SMB_FILE_RENAME_INFORMATION.
6241 ****************************************************************************/
6243 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6244 struct smb_request *req,
6245 const char *pdata,
6246 int total_data,
6247 files_struct *fsp,
6248 struct smb_filename *smb_fname_src)
6250 bool overwrite;
6251 uint32 root_fid;
6252 uint32 len;
6253 char *newname = NULL;
6254 struct smb_filename *smb_fname_dst = NULL;
6255 bool dest_has_wcard = False;
6256 NTSTATUS status = NT_STATUS_OK;
6257 char *p;
6258 TALLOC_CTX *ctx = talloc_tos();
6260 if (total_data < 13) {
6261 return NT_STATUS_INVALID_PARAMETER;
6264 overwrite = (CVAL(pdata,0) ? True : False);
6265 root_fid = IVAL(pdata,4);
6266 len = IVAL(pdata,8);
6268 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6269 return NT_STATUS_INVALID_PARAMETER;
6272 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6273 len, 0, &status,
6274 &dest_has_wcard);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 return status;
6279 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6280 newname));
6282 status = resolve_dfspath_wcard(ctx, conn,
6283 req->flags2 & FLAGS2_DFS_PATHNAMES,
6284 newname,
6285 true,
6286 !conn->sconn->using_smb2,
6287 &newname,
6288 &dest_has_wcard);
6289 if (!NT_STATUS_IS_OK(status)) {
6290 return status;
6293 /* Check the new name has no '/' characters. */
6294 if (strchr_m(newname, '/')) {
6295 return NT_STATUS_NOT_SUPPORTED;
6298 if (fsp && fsp->base_fsp) {
6299 /* newname must be a stream name. */
6300 if (newname[0] != ':') {
6301 return NT_STATUS_NOT_SUPPORTED;
6304 /* Create an smb_fname to call rename_internals_fsp() with. */
6305 status = create_synthetic_smb_fname(talloc_tos(),
6306 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6307 &smb_fname_dst);
6308 if (!NT_STATUS_IS_OK(status)) {
6309 goto out;
6313 * Set the original last component, since
6314 * rename_internals_fsp() requires it.
6316 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6317 newname);
6318 if (smb_fname_dst->original_lcomp == NULL) {
6319 status = NT_STATUS_NO_MEMORY;
6320 goto out;
6323 } else {
6325 * Build up an smb_fname_dst based on the filename passed in.
6326 * We basically just strip off the last component, and put on
6327 * the newname instead.
6329 char *base_name = NULL;
6331 /* newname must *not* be a stream name. */
6332 if (newname[0] == ':') {
6333 return NT_STATUS_NOT_SUPPORTED;
6337 * Strip off the last component (filename) of the path passed
6338 * in.
6340 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6341 if (!base_name) {
6342 return NT_STATUS_NO_MEMORY;
6344 p = strrchr_m(base_name, '/');
6345 if (p) {
6346 p[1] = '\0';
6347 } else {
6348 base_name = talloc_strdup(ctx, "");
6349 if (!base_name) {
6350 return NT_STATUS_NO_MEMORY;
6353 /* Append the new name. */
6354 base_name = talloc_asprintf_append(base_name,
6355 "%s",
6356 newname);
6357 if (!base_name) {
6358 return NT_STATUS_NO_MEMORY;
6361 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6362 (UCF_SAVE_LCOMP |
6363 (dest_has_wcard ?
6364 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6365 0)));
6367 /* If an error we expect this to be
6368 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6370 if (!NT_STATUS_IS_OK(status)) {
6371 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6372 status)) {
6373 goto out;
6375 /* Create an smb_fname to call rename_internals_fsp() */
6376 status = create_synthetic_smb_fname(ctx,
6377 base_name, NULL,
6378 NULL,
6379 &smb_fname_dst);
6380 if (!NT_STATUS_IS_OK(status)) {
6381 goto out;
6386 if (fsp) {
6387 DEBUG(10,("smb_file_rename_information: "
6388 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6389 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6390 smb_fname_str_dbg(smb_fname_dst)));
6391 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6392 overwrite);
6393 } else {
6394 DEBUG(10,("smb_file_rename_information: "
6395 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6396 smb_fname_str_dbg(smb_fname_src),
6397 smb_fname_str_dbg(smb_fname_dst)));
6398 status = rename_internals(ctx, conn, req, smb_fname_src,
6399 smb_fname_dst, 0, overwrite, false,
6400 dest_has_wcard,
6401 FILE_WRITE_ATTRIBUTES);
6403 out:
6404 TALLOC_FREE(smb_fname_dst);
6405 return status;
6408 /****************************************************************************
6409 Deal with SMB_SET_POSIX_ACL.
6410 ****************************************************************************/
6412 #if defined(HAVE_POSIX_ACLS)
6413 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6414 const char *pdata,
6415 int total_data,
6416 files_struct *fsp,
6417 const struct smb_filename *smb_fname)
6419 uint16 posix_acl_version;
6420 uint16 num_file_acls;
6421 uint16 num_def_acls;
6422 bool valid_file_acls = True;
6423 bool valid_def_acls = True;
6425 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6426 return NT_STATUS_INVALID_PARAMETER;
6428 posix_acl_version = SVAL(pdata,0);
6429 num_file_acls = SVAL(pdata,2);
6430 num_def_acls = SVAL(pdata,4);
6432 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6433 valid_file_acls = False;
6434 num_file_acls = 0;
6437 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6438 valid_def_acls = False;
6439 num_def_acls = 0;
6442 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6443 return NT_STATUS_INVALID_PARAMETER;
6446 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6447 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6448 return NT_STATUS_INVALID_PARAMETER;
6451 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6452 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6453 (unsigned int)num_file_acls,
6454 (unsigned int)num_def_acls));
6456 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6457 smb_fname->base_name, num_file_acls,
6458 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6459 return map_nt_error_from_unix(errno);
6462 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6463 smb_fname->base_name, &smb_fname->st, num_def_acls,
6464 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6465 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6466 return map_nt_error_from_unix(errno);
6468 return NT_STATUS_OK;
6470 #endif
6472 /****************************************************************************
6473 Deal with SMB_SET_POSIX_LOCK.
6474 ****************************************************************************/
6476 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6477 struct smb_request *req,
6478 const char *pdata,
6479 int total_data,
6480 files_struct *fsp)
6482 uint64_t count;
6483 uint64_t offset;
6484 uint64_t smblctx;
6485 bool blocking_lock = False;
6486 enum brl_type lock_type;
6488 NTSTATUS status = NT_STATUS_OK;
6490 if (fsp == NULL || fsp->fh->fd == -1) {
6491 return NT_STATUS_INVALID_HANDLE;
6494 if (total_data != POSIX_LOCK_DATA_SIZE) {
6495 return NT_STATUS_INVALID_PARAMETER;
6498 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6499 case POSIX_LOCK_TYPE_READ:
6500 lock_type = READ_LOCK;
6501 break;
6502 case POSIX_LOCK_TYPE_WRITE:
6503 /* Return the right POSIX-mappable error code for files opened read-only. */
6504 if (!fsp->can_write) {
6505 return NT_STATUS_INVALID_HANDLE;
6507 lock_type = WRITE_LOCK;
6508 break;
6509 case POSIX_LOCK_TYPE_UNLOCK:
6510 lock_type = UNLOCK_LOCK;
6511 break;
6512 default:
6513 return NT_STATUS_INVALID_PARAMETER;
6516 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6517 blocking_lock = False;
6518 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6519 blocking_lock = True;
6520 } else {
6521 return NT_STATUS_INVALID_PARAMETER;
6524 if (!lp_blocking_locks(SNUM(conn))) {
6525 blocking_lock = False;
6528 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6529 #if defined(HAVE_LONGLONG)
6530 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6531 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6532 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6533 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6534 #else /* HAVE_LONGLONG */
6535 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6536 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6537 #endif /* HAVE_LONGLONG */
6539 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6540 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6541 fsp_str_dbg(fsp),
6542 (unsigned int)lock_type,
6543 (unsigned long long)smblctx,
6544 (double)count,
6545 (double)offset ));
6547 if (lock_type == UNLOCK_LOCK) {
6548 status = do_unlock(req->sconn->msg_ctx,
6549 fsp,
6550 smblctx,
6551 count,
6552 offset,
6553 POSIX_LOCK);
6554 } else {
6555 uint64_t block_smblctx;
6557 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6558 fsp,
6559 smblctx,
6560 count,
6561 offset,
6562 lock_type,
6563 POSIX_LOCK,
6564 blocking_lock,
6565 &status,
6566 &block_smblctx,
6567 NULL);
6569 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6571 * A blocking lock was requested. Package up
6572 * this smb into a queued request and push it
6573 * onto the blocking lock queue.
6575 if(push_blocking_lock_request(br_lck,
6576 req,
6577 fsp,
6578 -1, /* infinite timeout. */
6580 smblctx,
6581 lock_type,
6582 POSIX_LOCK,
6583 offset,
6584 count,
6585 block_smblctx)) {
6586 TALLOC_FREE(br_lck);
6587 return status;
6590 TALLOC_FREE(br_lck);
6593 return status;
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_BASIC_INFO.
6598 ****************************************************************************/
6600 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6601 const char *pdata,
6602 int total_data,
6603 files_struct *fsp,
6604 const struct smb_filename *smb_fname)
6606 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6607 struct smb_file_time ft;
6608 uint32 dosmode = 0;
6609 NTSTATUS status = NT_STATUS_OK;
6611 ZERO_STRUCT(ft);
6613 if (total_data < 36) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6618 if (!NT_STATUS_IS_OK(status)) {
6619 return status;
6622 /* Set the attributes */
6623 dosmode = IVAL(pdata,32);
6624 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6625 if (!NT_STATUS_IS_OK(status)) {
6626 return status;
6629 /* create time */
6630 ft.create_time = interpret_long_date(pdata);
6632 /* access time */
6633 ft.atime = interpret_long_date(pdata+8);
6635 /* write time. */
6636 ft.mtime = interpret_long_date(pdata+16);
6638 /* change time. */
6639 ft.ctime = interpret_long_date(pdata+24);
6641 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6642 smb_fname_str_dbg(smb_fname)));
6644 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6645 true);
6648 /****************************************************************************
6649 Deal with SMB_INFO_STANDARD.
6650 ****************************************************************************/
6652 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6653 const char *pdata,
6654 int total_data,
6655 files_struct *fsp,
6656 const struct smb_filename *smb_fname)
6658 NTSTATUS status;
6659 struct smb_file_time ft;
6661 ZERO_STRUCT(ft);
6663 if (total_data < 12) {
6664 return NT_STATUS_INVALID_PARAMETER;
6667 /* create time */
6668 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6669 /* access time */
6670 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6671 /* write time */
6672 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6674 DEBUG(10,("smb_set_info_standard: file %s\n",
6675 smb_fname_str_dbg(smb_fname)));
6677 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6678 if (!NT_STATUS_IS_OK(status)) {
6679 return status;
6682 return smb_set_file_time(conn,
6683 fsp,
6684 smb_fname,
6685 &ft,
6686 true);
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6694 struct smb_request *req,
6695 const char *pdata,
6696 int total_data,
6697 files_struct *fsp,
6698 struct smb_filename *smb_fname)
6700 uint64_t allocation_size = 0;
6701 NTSTATUS status = NT_STATUS_OK;
6702 files_struct *new_fsp = NULL;
6704 if (!VALID_STAT(smb_fname->st)) {
6705 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6708 if (total_data < 8) {
6709 return NT_STATUS_INVALID_PARAMETER;
6712 allocation_size = (uint64_t)IVAL(pdata,0);
6713 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6714 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6715 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6716 (double)allocation_size));
6718 if (allocation_size) {
6719 allocation_size = smb_roundup(conn, allocation_size);
6722 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6723 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6724 (double)allocation_size));
6726 if (fsp && fsp->fh->fd != -1) {
6727 /* Open file handle. */
6728 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6729 return NT_STATUS_ACCESS_DENIED;
6732 /* Only change if needed. */
6733 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6734 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6735 return map_nt_error_from_unix(errno);
6738 /* But always update the time. */
6740 * This is equivalent to a write. Ensure it's seen immediately
6741 * if there are no pending writes.
6743 trigger_write_time_update_immediate(fsp);
6744 return NT_STATUS_OK;
6747 /* Pathname or stat or directory file. */
6748 status = SMB_VFS_CREATE_FILE(
6749 conn, /* conn */
6750 req, /* req */
6751 0, /* root_dir_fid */
6752 smb_fname, /* fname */
6753 FILE_WRITE_DATA, /* access_mask */
6754 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6755 FILE_SHARE_DELETE),
6756 FILE_OPEN, /* create_disposition*/
6757 0, /* create_options */
6758 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6759 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6760 0, /* allocation_size */
6761 0, /* private_flags */
6762 NULL, /* sd */
6763 NULL, /* ea_list */
6764 &new_fsp, /* result */
6765 NULL); /* pinfo */
6767 if (!NT_STATUS_IS_OK(status)) {
6768 /* NB. We check for open_was_deferred in the caller. */
6769 return status;
6772 /* Only change if needed. */
6773 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6774 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6775 status = map_nt_error_from_unix(errno);
6776 close_file(req, new_fsp, NORMAL_CLOSE);
6777 return status;
6781 /* Changing the allocation size should set the last mod time. */
6783 * This is equivalent to a write. Ensure it's seen immediately
6784 * if there are no pending writes.
6786 trigger_write_time_update_immediate(new_fsp);
6788 close_file(req, new_fsp, NORMAL_CLOSE);
6789 return NT_STATUS_OK;
6792 /****************************************************************************
6793 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6794 ****************************************************************************/
6796 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6797 struct smb_request *req,
6798 const char *pdata,
6799 int total_data,
6800 files_struct *fsp,
6801 const struct smb_filename *smb_fname,
6802 bool fail_after_createfile)
6804 off_t size;
6806 if (total_data < 8) {
6807 return NT_STATUS_INVALID_PARAMETER;
6810 size = IVAL(pdata,0);
6811 size |= (((off_t)IVAL(pdata,4)) << 32);
6812 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6813 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6814 (double)size));
6816 return smb_set_file_size(conn, req,
6817 fsp,
6818 smb_fname,
6819 &smb_fname->st,
6820 size,
6821 fail_after_createfile);
6824 /****************************************************************************
6825 Allow a UNIX info mknod.
6826 ****************************************************************************/
6828 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6829 const char *pdata,
6830 int total_data,
6831 const struct smb_filename *smb_fname)
6833 uint32 file_type = IVAL(pdata,56);
6834 #if defined(HAVE_MAKEDEV)
6835 uint32 dev_major = IVAL(pdata,60);
6836 uint32 dev_minor = IVAL(pdata,68);
6837 #endif
6838 SMB_DEV_T dev = (SMB_DEV_T)0;
6839 uint32 raw_unixmode = IVAL(pdata,84);
6840 NTSTATUS status;
6841 mode_t unixmode;
6843 if (total_data < 100) {
6844 return NT_STATUS_INVALID_PARAMETER;
6847 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6848 PERM_NEW_FILE, &unixmode);
6849 if (!NT_STATUS_IS_OK(status)) {
6850 return status;
6853 #if defined(HAVE_MAKEDEV)
6854 dev = makedev(dev_major, dev_minor);
6855 #endif
6857 switch (file_type) {
6858 #if defined(S_IFIFO)
6859 case UNIX_TYPE_FIFO:
6860 unixmode |= S_IFIFO;
6861 break;
6862 #endif
6863 #if defined(S_IFSOCK)
6864 case UNIX_TYPE_SOCKET:
6865 unixmode |= S_IFSOCK;
6866 break;
6867 #endif
6868 #if defined(S_IFCHR)
6869 case UNIX_TYPE_CHARDEV:
6870 unixmode |= S_IFCHR;
6871 break;
6872 #endif
6873 #if defined(S_IFBLK)
6874 case UNIX_TYPE_BLKDEV:
6875 unixmode |= S_IFBLK;
6876 break;
6877 #endif
6878 default:
6879 return NT_STATUS_INVALID_PARAMETER;
6882 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6883 "%.0f mode 0%o for file %s\n", (double)dev,
6884 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6886 /* Ok - do the mknod. */
6887 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6888 return map_nt_error_from_unix(errno);
6891 /* If any of the other "set" calls fail we
6892 * don't want to end up with a half-constructed mknod.
6895 if (lp_inherit_perms(SNUM(conn))) {
6896 char *parent;
6897 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6898 &parent, NULL)) {
6899 return NT_STATUS_NO_MEMORY;
6901 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6902 unixmode);
6903 TALLOC_FREE(parent);
6906 return NT_STATUS_OK;
6909 /****************************************************************************
6910 Deal with SMB_SET_FILE_UNIX_BASIC.
6911 ****************************************************************************/
6913 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6914 struct smb_request *req,
6915 const char *pdata,
6916 int total_data,
6917 files_struct *fsp,
6918 const struct smb_filename *smb_fname)
6920 struct smb_file_time ft;
6921 uint32 raw_unixmode;
6922 mode_t unixmode;
6923 off_t size = 0;
6924 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6925 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6926 NTSTATUS status = NT_STATUS_OK;
6927 bool delete_on_fail = False;
6928 enum perm_type ptype;
6929 files_struct *all_fsps = NULL;
6930 bool modify_mtime = true;
6931 struct file_id id;
6932 struct smb_filename *smb_fname_tmp = NULL;
6933 SMB_STRUCT_STAT sbuf;
6935 ZERO_STRUCT(ft);
6937 if (total_data < 100) {
6938 return NT_STATUS_INVALID_PARAMETER;
6941 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6942 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6943 size=IVAL(pdata,0); /* first 8 Bytes are size */
6944 size |= (((off_t)IVAL(pdata,4)) << 32);
6947 ft.atime = interpret_long_date(pdata+24); /* access_time */
6948 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6949 set_owner = (uid_t)IVAL(pdata,40);
6950 set_grp = (gid_t)IVAL(pdata,48);
6951 raw_unixmode = IVAL(pdata,84);
6953 if (VALID_STAT(smb_fname->st)) {
6954 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6955 ptype = PERM_EXISTING_DIR;
6956 } else {
6957 ptype = PERM_EXISTING_FILE;
6959 } else {
6960 ptype = PERM_NEW_FILE;
6963 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6964 ptype, &unixmode);
6965 if (!NT_STATUS_IS_OK(status)) {
6966 return status;
6969 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6970 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6971 smb_fname_str_dbg(smb_fname), (double)size,
6972 (unsigned int)set_owner, (unsigned int)set_grp,
6973 (int)raw_unixmode));
6975 sbuf = smb_fname->st;
6977 if (!VALID_STAT(sbuf)) {
6979 * The only valid use of this is to create character and block
6980 * devices, and named pipes. This is deprecated (IMHO) and
6981 * a new info level should be used for mknod. JRA.
6984 status = smb_unix_mknod(conn,
6985 pdata,
6986 total_data,
6987 smb_fname);
6988 if (!NT_STATUS_IS_OK(status)) {
6989 return status;
6992 status = copy_smb_filename(talloc_tos(), smb_fname,
6993 &smb_fname_tmp);
6994 if (!NT_STATUS_IS_OK(status)) {
6995 return status;
6998 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6999 status = map_nt_error_from_unix(errno);
7000 TALLOC_FREE(smb_fname_tmp);
7001 SMB_VFS_UNLINK(conn, smb_fname);
7002 return status;
7005 sbuf = smb_fname_tmp->st;
7006 smb_fname = smb_fname_tmp;
7008 /* Ensure we don't try and change anything else. */
7009 raw_unixmode = SMB_MODE_NO_CHANGE;
7010 size = get_file_size_stat(&sbuf);
7011 ft.atime = sbuf.st_ex_atime;
7012 ft.mtime = sbuf.st_ex_mtime;
7014 * We continue here as we might want to change the
7015 * owner uid/gid.
7017 delete_on_fail = True;
7020 #if 1
7021 /* Horrible backwards compatibility hack as an old server bug
7022 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7023 * */
7025 if (!size) {
7026 size = get_file_size_stat(&sbuf);
7028 #endif
7031 * Deal with the UNIX specific mode set.
7034 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7035 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7036 "setting mode 0%o for file %s\n",
7037 (unsigned int)unixmode,
7038 smb_fname_str_dbg(smb_fname)));
7039 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7040 return map_nt_error_from_unix(errno);
7045 * Deal with the UNIX specific uid set.
7048 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7049 (sbuf.st_ex_uid != set_owner)) {
7050 int ret;
7052 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7053 "changing owner %u for path %s\n",
7054 (unsigned int)set_owner,
7055 smb_fname_str_dbg(smb_fname)));
7057 if (S_ISLNK(sbuf.st_ex_mode)) {
7058 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7059 set_owner, (gid_t)-1);
7060 } else {
7061 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7062 set_owner, (gid_t)-1);
7065 if (ret != 0) {
7066 status = map_nt_error_from_unix(errno);
7067 if (delete_on_fail) {
7068 SMB_VFS_UNLINK(conn, smb_fname);
7070 return status;
7075 * Deal with the UNIX specific gid set.
7078 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7079 (sbuf.st_ex_gid != set_grp)) {
7080 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7081 "changing group %u for file %s\n",
7082 (unsigned int)set_owner,
7083 smb_fname_str_dbg(smb_fname)));
7084 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7085 set_grp) != 0) {
7086 status = map_nt_error_from_unix(errno);
7087 if (delete_on_fail) {
7088 SMB_VFS_UNLINK(conn, smb_fname);
7090 return status;
7094 /* Deal with any size changes. */
7096 status = smb_set_file_size(conn, req,
7097 fsp,
7098 smb_fname,
7099 &sbuf,
7100 size,
7101 false);
7102 if (!NT_STATUS_IS_OK(status)) {
7103 return status;
7106 /* Deal with any time changes. */
7107 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7108 /* No change, don't cancel anything. */
7109 return status;
7112 id = vfs_file_id_from_sbuf(conn, &sbuf);
7113 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7114 all_fsps = file_find_di_next(all_fsps)) {
7116 * We're setting the time explicitly for UNIX.
7117 * Cancel any pending changes over all handles.
7119 all_fsps->update_write_time_on_close = false;
7120 TALLOC_FREE(all_fsps->update_write_time_event);
7124 * Override the "setting_write_time"
7125 * parameter here as it almost does what
7126 * we need. Just remember if we modified
7127 * mtime and send the notify ourselves.
7129 if (null_timespec(ft.mtime)) {
7130 modify_mtime = false;
7133 status = smb_set_file_time(conn,
7134 fsp,
7135 smb_fname,
7136 &ft,
7137 false);
7138 if (modify_mtime) {
7139 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7140 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7142 return status;
7145 /****************************************************************************
7146 Deal with SMB_SET_FILE_UNIX_INFO2.
7147 ****************************************************************************/
7149 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7150 struct smb_request *req,
7151 const char *pdata,
7152 int total_data,
7153 files_struct *fsp,
7154 const struct smb_filename *smb_fname)
7156 NTSTATUS status;
7157 uint32 smb_fflags;
7158 uint32 smb_fmask;
7160 if (total_data < 116) {
7161 return NT_STATUS_INVALID_PARAMETER;
7164 /* Start by setting all the fields that are common between UNIX_BASIC
7165 * and UNIX_INFO2.
7167 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7168 fsp, smb_fname);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 return status;
7173 smb_fflags = IVAL(pdata, 108);
7174 smb_fmask = IVAL(pdata, 112);
7176 /* NB: We should only attempt to alter the file flags if the client
7177 * sends a non-zero mask.
7179 if (smb_fmask != 0) {
7180 int stat_fflags = 0;
7182 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7183 smb_fmask, &stat_fflags)) {
7184 /* Client asked to alter a flag we don't understand. */
7185 return NT_STATUS_INVALID_PARAMETER;
7188 if (fsp && fsp->fh->fd != -1) {
7189 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7190 return NT_STATUS_NOT_SUPPORTED;
7191 } else {
7192 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7193 stat_fflags) != 0) {
7194 return map_nt_error_from_unix(errno);
7199 /* XXX: need to add support for changing the create_time here. You
7200 * can do this for paths on Darwin with setattrlist(2). The right way
7201 * to hook this up is probably by extending the VFS utimes interface.
7204 return NT_STATUS_OK;
7207 /****************************************************************************
7208 Create a directory with POSIX semantics.
7209 ****************************************************************************/
7211 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7212 struct smb_request *req,
7213 char **ppdata,
7214 int total_data,
7215 struct smb_filename *smb_fname,
7216 int *pdata_return_size)
7218 NTSTATUS status = NT_STATUS_OK;
7219 uint32 raw_unixmode = 0;
7220 uint32 mod_unixmode = 0;
7221 mode_t unixmode = (mode_t)0;
7222 files_struct *fsp = NULL;
7223 uint16 info_level_return = 0;
7224 int info;
7225 char *pdata = *ppdata;
7227 if (total_data < 18) {
7228 return NT_STATUS_INVALID_PARAMETER;
7231 raw_unixmode = IVAL(pdata,8);
7232 /* Next 4 bytes are not yet defined. */
7234 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7235 PERM_NEW_DIR, &unixmode);
7236 if (!NT_STATUS_IS_OK(status)) {
7237 return status;
7240 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7242 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7243 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7245 status = SMB_VFS_CREATE_FILE(
7246 conn, /* conn */
7247 req, /* req */
7248 0, /* root_dir_fid */
7249 smb_fname, /* fname */
7250 FILE_READ_ATTRIBUTES, /* access_mask */
7251 FILE_SHARE_NONE, /* share_access */
7252 FILE_CREATE, /* create_disposition*/
7253 FILE_DIRECTORY_FILE, /* create_options */
7254 mod_unixmode, /* file_attributes */
7255 0, /* oplock_request */
7256 0, /* allocation_size */
7257 0, /* private_flags */
7258 NULL, /* sd */
7259 NULL, /* ea_list */
7260 &fsp, /* result */
7261 &info); /* pinfo */
7263 if (NT_STATUS_IS_OK(status)) {
7264 close_file(req, fsp, NORMAL_CLOSE);
7267 info_level_return = SVAL(pdata,16);
7269 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7270 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7271 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7272 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7273 } else {
7274 *pdata_return_size = 12;
7277 /* Realloc the data size */
7278 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7279 if (*ppdata == NULL) {
7280 *pdata_return_size = 0;
7281 return NT_STATUS_NO_MEMORY;
7283 pdata = *ppdata;
7285 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7286 SSVAL(pdata,2,0); /* No fnum. */
7287 SIVAL(pdata,4,info); /* Was directory created. */
7289 switch (info_level_return) {
7290 case SMB_QUERY_FILE_UNIX_BASIC:
7291 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7292 SSVAL(pdata,10,0); /* Padding. */
7293 store_file_unix_basic(conn, pdata + 12, fsp,
7294 &smb_fname->st);
7295 break;
7296 case SMB_QUERY_FILE_UNIX_INFO2:
7297 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7298 SSVAL(pdata,10,0); /* Padding. */
7299 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7300 &smb_fname->st);
7301 break;
7302 default:
7303 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7304 SSVAL(pdata,10,0); /* Padding. */
7305 break;
7308 return status;
7311 /****************************************************************************
7312 Open/Create a file with POSIX semantics.
7313 ****************************************************************************/
7315 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7316 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7318 static NTSTATUS smb_posix_open(connection_struct *conn,
7319 struct smb_request *req,
7320 char **ppdata,
7321 int total_data,
7322 struct smb_filename *smb_fname,
7323 int *pdata_return_size)
7325 bool extended_oplock_granted = False;
7326 char *pdata = *ppdata;
7327 uint32 flags = 0;
7328 uint32 wire_open_mode = 0;
7329 uint32 raw_unixmode = 0;
7330 uint32 mod_unixmode = 0;
7331 uint32 create_disp = 0;
7332 uint32 access_mask = 0;
7333 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7334 NTSTATUS status = NT_STATUS_OK;
7335 mode_t unixmode = (mode_t)0;
7336 files_struct *fsp = NULL;
7337 int oplock_request = 0;
7338 int info = 0;
7339 uint16 info_level_return = 0;
7341 if (total_data < 18) {
7342 return NT_STATUS_INVALID_PARAMETER;
7345 flags = IVAL(pdata,0);
7346 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7347 if (oplock_request) {
7348 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7351 wire_open_mode = IVAL(pdata,4);
7353 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7354 return smb_posix_mkdir(conn, req,
7355 ppdata,
7356 total_data,
7357 smb_fname,
7358 pdata_return_size);
7361 switch (wire_open_mode & SMB_ACCMODE) {
7362 case SMB_O_RDONLY:
7363 access_mask = SMB_O_RDONLY_MAPPING;
7364 break;
7365 case SMB_O_WRONLY:
7366 access_mask = SMB_O_WRONLY_MAPPING;
7367 break;
7368 case SMB_O_RDWR:
7369 access_mask = (SMB_O_RDONLY_MAPPING|
7370 SMB_O_WRONLY_MAPPING);
7371 break;
7372 default:
7373 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7374 (unsigned int)wire_open_mode ));
7375 return NT_STATUS_INVALID_PARAMETER;
7378 wire_open_mode &= ~SMB_ACCMODE;
7380 /* First take care of O_CREAT|O_EXCL interactions. */
7381 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7382 case (SMB_O_CREAT | SMB_O_EXCL):
7383 /* File exists fail. File not exist create. */
7384 create_disp = FILE_CREATE;
7385 break;
7386 case SMB_O_CREAT:
7387 /* File exists open. File not exist create. */
7388 create_disp = FILE_OPEN_IF;
7389 break;
7390 case 0:
7391 /* File exists open. File not exist fail. */
7392 create_disp = FILE_OPEN;
7393 break;
7394 case SMB_O_EXCL:
7395 /* O_EXCL on its own without O_CREAT is undefined. */
7396 default:
7397 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7398 (unsigned int)wire_open_mode ));
7399 return NT_STATUS_INVALID_PARAMETER;
7402 /* Next factor in the effects of O_TRUNC. */
7403 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7405 if (wire_open_mode & SMB_O_TRUNC) {
7406 switch (create_disp) {
7407 case FILE_CREATE:
7408 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7409 /* Leave create_disp alone as
7410 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7412 /* File exists fail. File not exist create. */
7413 break;
7414 case FILE_OPEN_IF:
7415 /* SMB_O_CREAT | SMB_O_TRUNC */
7416 /* File exists overwrite. File not exist create. */
7417 create_disp = FILE_OVERWRITE_IF;
7418 break;
7419 case FILE_OPEN:
7420 /* SMB_O_TRUNC */
7421 /* File exists overwrite. File not exist fail. */
7422 create_disp = FILE_OVERWRITE;
7423 break;
7424 default:
7425 /* Cannot get here. */
7426 smb_panic("smb_posix_open: logic error");
7427 return NT_STATUS_INVALID_PARAMETER;
7431 raw_unixmode = IVAL(pdata,8);
7432 /* Next 4 bytes are not yet defined. */
7434 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7435 (VALID_STAT(smb_fname->st) ?
7436 PERM_EXISTING_FILE : PERM_NEW_FILE),
7437 &unixmode);
7439 if (!NT_STATUS_IS_OK(status)) {
7440 return status;
7443 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7445 if (wire_open_mode & SMB_O_SYNC) {
7446 create_options |= FILE_WRITE_THROUGH;
7448 if (wire_open_mode & SMB_O_APPEND) {
7449 access_mask |= FILE_APPEND_DATA;
7451 if (wire_open_mode & SMB_O_DIRECT) {
7452 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7455 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7456 VALID_STAT_OF_DIR(smb_fname->st)) {
7457 if (access_mask != SMB_O_RDONLY_MAPPING) {
7458 return NT_STATUS_FILE_IS_A_DIRECTORY;
7460 create_options &= ~FILE_NON_DIRECTORY_FILE;
7461 create_options |= FILE_DIRECTORY_FILE;
7464 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7465 smb_fname_str_dbg(smb_fname),
7466 (unsigned int)wire_open_mode,
7467 (unsigned int)unixmode ));
7469 status = SMB_VFS_CREATE_FILE(
7470 conn, /* conn */
7471 req, /* req */
7472 0, /* root_dir_fid */
7473 smb_fname, /* fname */
7474 access_mask, /* access_mask */
7475 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7476 FILE_SHARE_DELETE),
7477 create_disp, /* create_disposition*/
7478 create_options, /* create_options */
7479 mod_unixmode, /* file_attributes */
7480 oplock_request, /* oplock_request */
7481 0, /* allocation_size */
7482 0, /* private_flags */
7483 NULL, /* sd */
7484 NULL, /* ea_list */
7485 &fsp, /* result */
7486 &info); /* pinfo */
7488 if (!NT_STATUS_IS_OK(status)) {
7489 return status;
7492 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7493 extended_oplock_granted = True;
7496 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7497 extended_oplock_granted = True;
7500 info_level_return = SVAL(pdata,16);
7502 /* Allocate the correct return size. */
7504 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7505 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7506 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7507 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7508 } else {
7509 *pdata_return_size = 12;
7512 /* Realloc the data size */
7513 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7514 if (*ppdata == NULL) {
7515 close_file(req, fsp, ERROR_CLOSE);
7516 *pdata_return_size = 0;
7517 return NT_STATUS_NO_MEMORY;
7519 pdata = *ppdata;
7521 if (extended_oplock_granted) {
7522 if (flags & REQUEST_BATCH_OPLOCK) {
7523 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7524 } else {
7525 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7527 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7528 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7529 } else {
7530 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7533 SSVAL(pdata,2,fsp->fnum);
7534 SIVAL(pdata,4,info); /* Was file created etc. */
7536 switch (info_level_return) {
7537 case SMB_QUERY_FILE_UNIX_BASIC:
7538 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7539 SSVAL(pdata,10,0); /* padding. */
7540 store_file_unix_basic(conn, pdata + 12, fsp,
7541 &smb_fname->st);
7542 break;
7543 case SMB_QUERY_FILE_UNIX_INFO2:
7544 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7545 SSVAL(pdata,10,0); /* padding. */
7546 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7547 &smb_fname->st);
7548 break;
7549 default:
7550 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7551 SSVAL(pdata,10,0); /* padding. */
7552 break;
7554 return NT_STATUS_OK;
7557 /****************************************************************************
7558 Delete a file with POSIX semantics.
7559 ****************************************************************************/
7561 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7562 struct smb_request *req,
7563 const char *pdata,
7564 int total_data,
7565 struct smb_filename *smb_fname)
7567 NTSTATUS status = NT_STATUS_OK;
7568 files_struct *fsp = NULL;
7569 uint16 flags = 0;
7570 char del = 1;
7571 int info = 0;
7572 int create_options = 0;
7573 int i;
7574 struct share_mode_lock *lck = NULL;
7576 if (total_data < 2) {
7577 return NT_STATUS_INVALID_PARAMETER;
7580 flags = SVAL(pdata,0);
7582 if (!VALID_STAT(smb_fname->st)) {
7583 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7586 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7587 !VALID_STAT_OF_DIR(smb_fname->st)) {
7588 return NT_STATUS_NOT_A_DIRECTORY;
7591 DEBUG(10,("smb_posix_unlink: %s %s\n",
7592 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7593 smb_fname_str_dbg(smb_fname)));
7595 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7596 create_options |= FILE_DIRECTORY_FILE;
7599 status = SMB_VFS_CREATE_FILE(
7600 conn, /* conn */
7601 req, /* req */
7602 0, /* root_dir_fid */
7603 smb_fname, /* fname */
7604 DELETE_ACCESS, /* access_mask */
7605 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7606 FILE_SHARE_DELETE),
7607 FILE_OPEN, /* create_disposition*/
7608 create_options, /* create_options */
7609 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7610 0, /* oplock_request */
7611 0, /* allocation_size */
7612 0, /* private_flags */
7613 NULL, /* sd */
7614 NULL, /* ea_list */
7615 &fsp, /* result */
7616 &info); /* pinfo */
7618 if (!NT_STATUS_IS_OK(status)) {
7619 return status;
7623 * Don't lie to client. If we can't really delete due to
7624 * non-POSIX opens return SHARING_VIOLATION.
7627 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7628 if (lck == NULL) {
7629 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7630 "lock for file %s\n", fsp_str_dbg(fsp)));
7631 close_file(req, fsp, NORMAL_CLOSE);
7632 return NT_STATUS_INVALID_PARAMETER;
7636 * See if others still have the file open. If this is the case, then
7637 * don't delete. If all opens are POSIX delete we can set the delete
7638 * on close disposition.
7640 for (i=0; i<lck->data->num_share_modes; i++) {
7641 struct share_mode_entry *e = &lck->data->share_modes[i];
7642 if (is_valid_share_mode_entry(e)) {
7643 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7644 continue;
7646 if (share_mode_stale_pid(lck->data, i)) {
7647 continue;
7649 /* Fail with sharing violation. */
7650 close_file(req, fsp, NORMAL_CLOSE);
7651 TALLOC_FREE(lck);
7652 return NT_STATUS_SHARING_VIOLATION;
7657 * Set the delete on close.
7659 status = smb_set_file_disposition_info(conn,
7660 &del,
7662 fsp,
7663 smb_fname);
7665 if (!NT_STATUS_IS_OK(status)) {
7666 close_file(req, fsp, NORMAL_CLOSE);
7667 TALLOC_FREE(lck);
7668 return status;
7670 TALLOC_FREE(lck);
7671 return close_file(req, fsp, NORMAL_CLOSE);
7674 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7675 struct smb_request *req,
7676 TALLOC_CTX *mem_ctx,
7677 uint16_t info_level,
7678 files_struct *fsp,
7679 struct smb_filename *smb_fname,
7680 char **ppdata, int total_data,
7681 int *ret_data_size)
7683 char *pdata = *ppdata;
7684 NTSTATUS status = NT_STATUS_OK;
7685 int data_return_size = 0;
7687 *ret_data_size = 0;
7689 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7690 return NT_STATUS_INVALID_LEVEL;
7693 if (!CAN_WRITE(conn)) {
7694 /* Allow POSIX opens. The open path will deny
7695 * any non-readonly opens. */
7696 if (info_level != SMB_POSIX_PATH_OPEN) {
7697 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7701 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7702 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7703 fsp_fnum_dbg(fsp),
7704 info_level, total_data));
7706 switch (info_level) {
7708 case SMB_INFO_STANDARD:
7710 status = smb_set_info_standard(conn,
7711 pdata,
7712 total_data,
7713 fsp,
7714 smb_fname);
7715 break;
7718 case SMB_INFO_SET_EA:
7720 status = smb_info_set_ea(conn,
7721 pdata,
7722 total_data,
7723 fsp,
7724 smb_fname);
7725 break;
7728 case SMB_SET_FILE_BASIC_INFO:
7729 case SMB_FILE_BASIC_INFORMATION:
7731 status = smb_set_file_basic_info(conn,
7732 pdata,
7733 total_data,
7734 fsp,
7735 smb_fname);
7736 break;
7739 case SMB_FILE_ALLOCATION_INFORMATION:
7740 case SMB_SET_FILE_ALLOCATION_INFO:
7742 status = smb_set_file_allocation_info(conn, req,
7743 pdata,
7744 total_data,
7745 fsp,
7746 smb_fname);
7747 break;
7750 case SMB_FILE_END_OF_FILE_INFORMATION:
7751 case SMB_SET_FILE_END_OF_FILE_INFO:
7754 * XP/Win7 both fail after the createfile with
7755 * SMB_SET_FILE_END_OF_FILE_INFO but not
7756 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7757 * The level is known here, so pass it down
7758 * appropriately.
7760 bool should_fail =
7761 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7763 status = smb_set_file_end_of_file_info(conn, req,
7764 pdata,
7765 total_data,
7766 fsp,
7767 smb_fname,
7768 should_fail);
7769 break;
7772 case SMB_FILE_DISPOSITION_INFORMATION:
7773 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7775 #if 0
7776 /* JRA - We used to just ignore this on a path ?
7777 * Shouldn't this be invalid level on a pathname
7778 * based call ?
7780 if (tran_call != TRANSACT2_SETFILEINFO) {
7781 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7783 #endif
7784 status = smb_set_file_disposition_info(conn,
7785 pdata,
7786 total_data,
7787 fsp,
7788 smb_fname);
7789 break;
7792 case SMB_FILE_POSITION_INFORMATION:
7794 status = smb_file_position_information(conn,
7795 pdata,
7796 total_data,
7797 fsp);
7798 break;
7801 case SMB_FILE_FULL_EA_INFORMATION:
7803 status = smb_set_file_full_ea_info(conn,
7804 pdata,
7805 total_data,
7806 fsp);
7807 break;
7810 /* From tridge Samba4 :
7811 * MODE_INFORMATION in setfileinfo (I have no
7812 * idea what "mode information" on a file is - it takes a value of 0,
7813 * 2, 4 or 6. What could it be?).
7816 case SMB_FILE_MODE_INFORMATION:
7818 status = smb_file_mode_information(conn,
7819 pdata,
7820 total_data);
7821 break;
7825 * CIFS UNIX extensions.
7828 case SMB_SET_FILE_UNIX_BASIC:
7830 status = smb_set_file_unix_basic(conn, req,
7831 pdata,
7832 total_data,
7833 fsp,
7834 smb_fname);
7835 break;
7838 case SMB_SET_FILE_UNIX_INFO2:
7840 status = smb_set_file_unix_info2(conn, req,
7841 pdata,
7842 total_data,
7843 fsp,
7844 smb_fname);
7845 break;
7848 case SMB_SET_FILE_UNIX_LINK:
7850 if (fsp) {
7851 /* We must have a pathname for this. */
7852 return NT_STATUS_INVALID_LEVEL;
7854 status = smb_set_file_unix_link(conn, req, pdata,
7855 total_data, smb_fname);
7856 break;
7859 case SMB_SET_FILE_UNIX_HLINK:
7861 if (fsp) {
7862 /* We must have a pathname for this. */
7863 return NT_STATUS_INVALID_LEVEL;
7865 status = smb_set_file_unix_hlink(conn, req,
7866 pdata, total_data,
7867 smb_fname);
7868 break;
7871 case SMB_FILE_RENAME_INFORMATION:
7873 status = smb_file_rename_information(conn, req,
7874 pdata, total_data,
7875 fsp, smb_fname);
7876 break;
7879 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7881 /* SMB2 rename information. */
7882 status = smb2_file_rename_information(conn, req,
7883 pdata, total_data,
7884 fsp, smb_fname);
7885 break;
7888 case SMB_FILE_LINK_INFORMATION:
7890 status = smb_file_link_information(conn, req,
7891 pdata, total_data,
7892 fsp, smb_fname);
7893 break;
7896 #if defined(HAVE_POSIX_ACLS)
7897 case SMB_SET_POSIX_ACL:
7899 status = smb_set_posix_acl(conn,
7900 pdata,
7901 total_data,
7902 fsp,
7903 smb_fname);
7904 break;
7906 #endif
7908 case SMB_SET_POSIX_LOCK:
7910 if (!fsp) {
7911 return NT_STATUS_INVALID_LEVEL;
7913 status = smb_set_posix_lock(conn, req,
7914 pdata, total_data, fsp);
7915 break;
7918 case SMB_POSIX_PATH_OPEN:
7920 if (fsp) {
7921 /* We must have a pathname for this. */
7922 return NT_STATUS_INVALID_LEVEL;
7925 status = smb_posix_open(conn, req,
7926 ppdata,
7927 total_data,
7928 smb_fname,
7929 &data_return_size);
7930 break;
7933 case SMB_POSIX_PATH_UNLINK:
7935 if (fsp) {
7936 /* We must have a pathname for this. */
7937 return NT_STATUS_INVALID_LEVEL;
7940 status = smb_posix_unlink(conn, req,
7941 pdata,
7942 total_data,
7943 smb_fname);
7944 break;
7947 default:
7948 return NT_STATUS_INVALID_LEVEL;
7951 if (!NT_STATUS_IS_OK(status)) {
7952 return status;
7955 *ret_data_size = data_return_size;
7956 return NT_STATUS_OK;
7959 /****************************************************************************
7960 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7961 ****************************************************************************/
7963 static void call_trans2setfilepathinfo(connection_struct *conn,
7964 struct smb_request *req,
7965 unsigned int tran_call,
7966 char **pparams, int total_params,
7967 char **ppdata, int total_data,
7968 unsigned int max_data_bytes)
7970 char *params = *pparams;
7971 char *pdata = *ppdata;
7972 uint16 info_level;
7973 struct smb_filename *smb_fname = NULL;
7974 files_struct *fsp = NULL;
7975 NTSTATUS status = NT_STATUS_OK;
7976 int data_return_size = 0;
7978 if (!params) {
7979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7980 return;
7983 if (tran_call == TRANSACT2_SETFILEINFO) {
7984 if (total_params < 4) {
7985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7986 return;
7989 fsp = file_fsp(req, SVAL(params,0));
7990 /* Basic check for non-null fsp. */
7991 if (!check_fsp_open(conn, req, fsp)) {
7992 return;
7994 info_level = SVAL(params,2);
7996 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7997 &smb_fname);
7998 if (!NT_STATUS_IS_OK(status)) {
7999 reply_nterror(req, status);
8000 return;
8003 if(fsp->fh->fd == -1) {
8005 * This is actually a SETFILEINFO on a directory
8006 * handle (returned from an NT SMB). NT5.0 seems
8007 * to do this call. JRA.
8009 if (INFO_LEVEL_IS_UNIX(info_level)) {
8010 /* Always do lstat for UNIX calls. */
8011 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8012 DEBUG(3,("call_trans2setfilepathinfo: "
8013 "SMB_VFS_LSTAT of %s failed "
8014 "(%s)\n",
8015 smb_fname_str_dbg(smb_fname),
8016 strerror(errno)));
8017 reply_nterror(req, map_nt_error_from_unix(errno));
8018 return;
8020 } else {
8021 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8022 DEBUG(3,("call_trans2setfilepathinfo: "
8023 "fileinfo of %s failed (%s)\n",
8024 smb_fname_str_dbg(smb_fname),
8025 strerror(errno)));
8026 reply_nterror(req, map_nt_error_from_unix(errno));
8027 return;
8030 } else if (fsp->print_file) {
8032 * Doing a DELETE_ON_CLOSE should cancel a print job.
8034 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8035 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8037 DEBUG(3,("call_trans2setfilepathinfo: "
8038 "Cancelling print job (%s)\n",
8039 fsp_str_dbg(fsp)));
8041 SSVAL(params,0,0);
8042 send_trans2_replies(conn, req, params, 2,
8043 *ppdata, 0,
8044 max_data_bytes);
8045 return;
8046 } else {
8047 reply_nterror(req,
8048 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8049 return;
8051 } else {
8053 * Original code - this is an open file.
8055 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8056 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8057 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8058 strerror(errno)));
8059 reply_nterror(req, map_nt_error_from_unix(errno));
8060 return;
8063 } else {
8064 char *fname = NULL;
8065 uint32_t ucf_flags = 0;
8067 /* set path info */
8068 if (total_params < 7) {
8069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8070 return;
8073 info_level = SVAL(params,0);
8074 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8075 total_params - 6, STR_TERMINATE,
8076 &status);
8077 if (!NT_STATUS_IS_OK(status)) {
8078 reply_nterror(req, status);
8079 return;
8082 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8083 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8084 info_level == SMB_FILE_RENAME_INFORMATION ||
8085 info_level == SMB_POSIX_PATH_UNLINK) {
8086 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8089 status = filename_convert(req, conn,
8090 req->flags2 & FLAGS2_DFS_PATHNAMES,
8091 fname,
8092 ucf_flags,
8093 NULL,
8094 &smb_fname);
8095 if (!NT_STATUS_IS_OK(status)) {
8096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8097 reply_botherror(req,
8098 NT_STATUS_PATH_NOT_COVERED,
8099 ERRSRV, ERRbadpath);
8100 return;
8102 reply_nterror(req, status);
8103 return;
8106 if (INFO_LEVEL_IS_UNIX(info_level)) {
8108 * For CIFS UNIX extensions the target name may not exist.
8111 /* Always do lstat for UNIX calls. */
8112 SMB_VFS_LSTAT(conn, smb_fname);
8114 } else if (!VALID_STAT(smb_fname->st) &&
8115 SMB_VFS_STAT(conn, smb_fname)) {
8116 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8117 "%s failed (%s)\n",
8118 smb_fname_str_dbg(smb_fname),
8119 strerror(errno)));
8120 reply_nterror(req, map_nt_error_from_unix(errno));
8121 return;
8125 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8126 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8127 fsp_fnum_dbg(fsp),
8128 info_level,total_data));
8130 /* Realloc the parameter size */
8131 *pparams = (char *)SMB_REALLOC(*pparams,2);
8132 if (*pparams == NULL) {
8133 reply_nterror(req, NT_STATUS_NO_MEMORY);
8134 return;
8136 params = *pparams;
8138 SSVAL(params,0,0);
8140 status = smbd_do_setfilepathinfo(conn, req, req,
8141 info_level,
8142 fsp,
8143 smb_fname,
8144 ppdata, total_data,
8145 &data_return_size);
8146 if (!NT_STATUS_IS_OK(status)) {
8147 if (open_was_deferred(req->sconn, req->mid)) {
8148 /* We have re-scheduled this call. */
8149 return;
8151 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8152 /* We have re-scheduled this call. */
8153 return;
8155 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8156 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8157 ERRSRV, ERRbadpath);
8158 return;
8160 if (info_level == SMB_POSIX_PATH_OPEN) {
8161 reply_openerror(req, status);
8162 return;
8165 reply_nterror(req, status);
8166 return;
8169 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8170 max_data_bytes);
8172 return;
8175 /****************************************************************************
8176 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8177 ****************************************************************************/
8179 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8180 char **pparams, int total_params,
8181 char **ppdata, int total_data,
8182 unsigned int max_data_bytes)
8184 struct smb_filename *smb_dname = NULL;
8185 char *params = *pparams;
8186 char *pdata = *ppdata;
8187 char *directory = NULL;
8188 NTSTATUS status = NT_STATUS_OK;
8189 struct ea_list *ea_list = NULL;
8190 TALLOC_CTX *ctx = talloc_tos();
8192 if (!CAN_WRITE(conn)) {
8193 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8194 return;
8197 if (total_params < 5) {
8198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8199 return;
8202 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8203 total_params - 4, STR_TERMINATE,
8204 &status);
8205 if (!NT_STATUS_IS_OK(status)) {
8206 reply_nterror(req, status);
8207 return;
8210 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8212 status = filename_convert(ctx,
8213 conn,
8214 req->flags2 & FLAGS2_DFS_PATHNAMES,
8215 directory,
8217 NULL,
8218 &smb_dname);
8220 if (!NT_STATUS_IS_OK(status)) {
8221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8222 reply_botherror(req,
8223 NT_STATUS_PATH_NOT_COVERED,
8224 ERRSRV, ERRbadpath);
8225 return;
8227 reply_nterror(req, status);
8228 return;
8232 * OS/2 workplace shell seems to send SET_EA requests of "null"
8233 * length (4 bytes containing IVAL 4).
8234 * They seem to have no effect. Bug #3212. JRA.
8237 if (total_data && (total_data != 4)) {
8238 /* Any data in this call is an EA list. */
8239 if (total_data < 10) {
8240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8241 goto out;
8244 if (IVAL(pdata,0) > total_data) {
8245 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8246 IVAL(pdata,0), (unsigned int)total_data));
8247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8248 goto out;
8251 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8252 total_data - 4);
8253 if (!ea_list) {
8254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8255 goto out;
8258 if (!lp_ea_support(SNUM(conn))) {
8259 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8260 goto out;
8263 /* If total_data == 4 Windows doesn't care what values
8264 * are placed in that field, it just ignores them.
8265 * The System i QNTC IBM SMB client puts bad values here,
8266 * so ignore them. */
8268 status = create_directory(conn, req, smb_dname);
8270 if (!NT_STATUS_IS_OK(status)) {
8271 reply_nterror(req, status);
8272 goto out;
8275 /* Try and set any given EA. */
8276 if (ea_list) {
8277 status = set_ea(conn, NULL, smb_dname, ea_list);
8278 if (!NT_STATUS_IS_OK(status)) {
8279 reply_nterror(req, status);
8280 goto out;
8284 /* Realloc the parameter and data sizes */
8285 *pparams = (char *)SMB_REALLOC(*pparams,2);
8286 if(*pparams == NULL) {
8287 reply_nterror(req, NT_STATUS_NO_MEMORY);
8288 goto out;
8290 params = *pparams;
8292 SSVAL(params,0,0);
8294 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8296 out:
8297 TALLOC_FREE(smb_dname);
8298 return;
8301 /****************************************************************************
8302 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8303 We don't actually do this - we just send a null response.
8304 ****************************************************************************/
8306 static void call_trans2findnotifyfirst(connection_struct *conn,
8307 struct smb_request *req,
8308 char **pparams, int total_params,
8309 char **ppdata, int total_data,
8310 unsigned int max_data_bytes)
8312 char *params = *pparams;
8313 uint16 info_level;
8315 if (total_params < 6) {
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 return;
8320 info_level = SVAL(params,4);
8321 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8323 switch (info_level) {
8324 case 1:
8325 case 2:
8326 break;
8327 default:
8328 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8329 return;
8332 /* Realloc the parameter and data sizes */
8333 *pparams = (char *)SMB_REALLOC(*pparams,6);
8334 if (*pparams == NULL) {
8335 reply_nterror(req, NT_STATUS_NO_MEMORY);
8336 return;
8338 params = *pparams;
8340 SSVAL(params,0,fnf_handle);
8341 SSVAL(params,2,0); /* No changes */
8342 SSVAL(params,4,0); /* No EA errors */
8344 fnf_handle++;
8346 if(fnf_handle == 0)
8347 fnf_handle = 257;
8349 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8351 return;
8354 /****************************************************************************
8355 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8356 changes). Currently this does nothing.
8357 ****************************************************************************/
8359 static void call_trans2findnotifynext(connection_struct *conn,
8360 struct smb_request *req,
8361 char **pparams, int total_params,
8362 char **ppdata, int total_data,
8363 unsigned int max_data_bytes)
8365 char *params = *pparams;
8367 DEBUG(3,("call_trans2findnotifynext\n"));
8369 /* Realloc the parameter and data sizes */
8370 *pparams = (char *)SMB_REALLOC(*pparams,4);
8371 if (*pparams == NULL) {
8372 reply_nterror(req, NT_STATUS_NO_MEMORY);
8373 return;
8375 params = *pparams;
8377 SSVAL(params,0,0); /* No changes */
8378 SSVAL(params,2,0); /* No EA errors */
8380 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8382 return;
8385 /****************************************************************************
8386 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8387 ****************************************************************************/
8389 static void call_trans2getdfsreferral(connection_struct *conn,
8390 struct smb_request *req,
8391 char **pparams, int total_params,
8392 char **ppdata, int total_data,
8393 unsigned int max_data_bytes)
8395 char *params = *pparams;
8396 char *pathname = NULL;
8397 int reply_size = 0;
8398 int max_referral_level;
8399 NTSTATUS status = NT_STATUS_OK;
8400 TALLOC_CTX *ctx = talloc_tos();
8402 DEBUG(10,("call_trans2getdfsreferral\n"));
8404 if (total_params < 3) {
8405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 return;
8409 max_referral_level = SVAL(params,0);
8411 if(!lp_host_msdfs()) {
8412 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8413 return;
8416 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8417 total_params - 2, STR_TERMINATE);
8418 if (!pathname) {
8419 reply_nterror(req, NT_STATUS_NOT_FOUND);
8420 return;
8422 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8423 ppdata,&status)) < 0) {
8424 reply_nterror(req, status);
8425 return;
8428 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8429 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8430 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8432 return;
8435 #define LMCAT_SPL 0x53
8436 #define LMFUNC_GETJOBID 0x60
8438 /****************************************************************************
8439 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8440 ****************************************************************************/
8442 static void call_trans2ioctl(connection_struct *conn,
8443 struct smb_request *req,
8444 char **pparams, int total_params,
8445 char **ppdata, int total_data,
8446 unsigned int max_data_bytes)
8448 char *pdata = *ppdata;
8449 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8451 /* check for an invalid fid before proceeding */
8453 if (!fsp) {
8454 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8455 return;
8458 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8459 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8460 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8461 if (*ppdata == NULL) {
8462 reply_nterror(req, NT_STATUS_NO_MEMORY);
8463 return;
8465 pdata = *ppdata;
8467 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8468 CAN ACCEPT THIS IN UNICODE. JRA. */
8470 /* Job number */
8471 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8473 srvstr_push(pdata, req->flags2, pdata + 2,
8474 lp_netbios_name(), 15,
8475 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8476 srvstr_push(pdata, req->flags2, pdata+18,
8477 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8478 STR_ASCII|STR_TERMINATE); /* Service name */
8479 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8480 max_data_bytes);
8481 return;
8484 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8485 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8488 /****************************************************************************
8489 Reply to a SMBfindclose (stop trans2 directory search).
8490 ****************************************************************************/
8492 void reply_findclose(struct smb_request *req)
8494 int dptr_num;
8495 struct smbd_server_connection *sconn = req->sconn;
8497 START_PROFILE(SMBfindclose);
8499 if (req->wct < 1) {
8500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8501 END_PROFILE(SMBfindclose);
8502 return;
8505 dptr_num = SVALS(req->vwv+0, 0);
8507 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8509 dptr_close(sconn, &dptr_num);
8511 reply_outbuf(req, 0, 0);
8513 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8515 END_PROFILE(SMBfindclose);
8516 return;
8519 /****************************************************************************
8520 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8521 ****************************************************************************/
8523 void reply_findnclose(struct smb_request *req)
8525 int dptr_num;
8527 START_PROFILE(SMBfindnclose);
8529 if (req->wct < 1) {
8530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8531 END_PROFILE(SMBfindnclose);
8532 return;
8535 dptr_num = SVAL(req->vwv+0, 0);
8537 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8539 /* We never give out valid handles for a
8540 findnotifyfirst - so any dptr_num is ok here.
8541 Just ignore it. */
8543 reply_outbuf(req, 0, 0);
8545 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8547 END_PROFILE(SMBfindnclose);
8548 return;
8551 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8552 struct trans_state *state)
8554 if (get_Protocol() >= PROTOCOL_NT1) {
8555 req->flags2 |= 0x40; /* IS_LONG_NAME */
8556 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8559 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8560 if (state->call != TRANSACT2_QFSINFO &&
8561 state->call != TRANSACT2_SETFSINFO) {
8562 DEBUG(0,("handle_trans2: encryption required "
8563 "with call 0x%x\n",
8564 (unsigned int)state->call));
8565 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8566 return;
8570 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8572 /* Now we must call the relevant TRANS2 function */
8573 switch(state->call) {
8574 case TRANSACT2_OPEN:
8576 START_PROFILE(Trans2_open);
8577 call_trans2open(conn, req,
8578 &state->param, state->total_param,
8579 &state->data, state->total_data,
8580 state->max_data_return);
8581 END_PROFILE(Trans2_open);
8582 break;
8585 case TRANSACT2_FINDFIRST:
8587 START_PROFILE(Trans2_findfirst);
8588 call_trans2findfirst(conn, req,
8589 &state->param, state->total_param,
8590 &state->data, state->total_data,
8591 state->max_data_return);
8592 END_PROFILE(Trans2_findfirst);
8593 break;
8596 case TRANSACT2_FINDNEXT:
8598 START_PROFILE(Trans2_findnext);
8599 call_trans2findnext(conn, req,
8600 &state->param, state->total_param,
8601 &state->data, state->total_data,
8602 state->max_data_return);
8603 END_PROFILE(Trans2_findnext);
8604 break;
8607 case TRANSACT2_QFSINFO:
8609 START_PROFILE(Trans2_qfsinfo);
8610 call_trans2qfsinfo(conn, req,
8611 &state->param, state->total_param,
8612 &state->data, state->total_data,
8613 state->max_data_return);
8614 END_PROFILE(Trans2_qfsinfo);
8615 break;
8618 case TRANSACT2_SETFSINFO:
8620 START_PROFILE(Trans2_setfsinfo);
8621 call_trans2setfsinfo(conn, req,
8622 &state->param, state->total_param,
8623 &state->data, state->total_data,
8624 state->max_data_return);
8625 END_PROFILE(Trans2_setfsinfo);
8626 break;
8629 case TRANSACT2_QPATHINFO:
8630 case TRANSACT2_QFILEINFO:
8632 START_PROFILE(Trans2_qpathinfo);
8633 call_trans2qfilepathinfo(conn, req, state->call,
8634 &state->param, state->total_param,
8635 &state->data, state->total_data,
8636 state->max_data_return);
8637 END_PROFILE(Trans2_qpathinfo);
8638 break;
8641 case TRANSACT2_SETPATHINFO:
8642 case TRANSACT2_SETFILEINFO:
8644 START_PROFILE(Trans2_setpathinfo);
8645 call_trans2setfilepathinfo(conn, req, state->call,
8646 &state->param, state->total_param,
8647 &state->data, state->total_data,
8648 state->max_data_return);
8649 END_PROFILE(Trans2_setpathinfo);
8650 break;
8653 case TRANSACT2_FINDNOTIFYFIRST:
8655 START_PROFILE(Trans2_findnotifyfirst);
8656 call_trans2findnotifyfirst(conn, req,
8657 &state->param, state->total_param,
8658 &state->data, state->total_data,
8659 state->max_data_return);
8660 END_PROFILE(Trans2_findnotifyfirst);
8661 break;
8664 case TRANSACT2_FINDNOTIFYNEXT:
8666 START_PROFILE(Trans2_findnotifynext);
8667 call_trans2findnotifynext(conn, req,
8668 &state->param, state->total_param,
8669 &state->data, state->total_data,
8670 state->max_data_return);
8671 END_PROFILE(Trans2_findnotifynext);
8672 break;
8675 case TRANSACT2_MKDIR:
8677 START_PROFILE(Trans2_mkdir);
8678 call_trans2mkdir(conn, req,
8679 &state->param, state->total_param,
8680 &state->data, state->total_data,
8681 state->max_data_return);
8682 END_PROFILE(Trans2_mkdir);
8683 break;
8686 case TRANSACT2_GET_DFS_REFERRAL:
8688 START_PROFILE(Trans2_get_dfs_referral);
8689 call_trans2getdfsreferral(conn, req,
8690 &state->param, state->total_param,
8691 &state->data, state->total_data,
8692 state->max_data_return);
8693 END_PROFILE(Trans2_get_dfs_referral);
8694 break;
8697 case TRANSACT2_IOCTL:
8699 START_PROFILE(Trans2_ioctl);
8700 call_trans2ioctl(conn, req,
8701 &state->param, state->total_param,
8702 &state->data, state->total_data,
8703 state->max_data_return);
8704 END_PROFILE(Trans2_ioctl);
8705 break;
8708 default:
8709 /* Error in request */
8710 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8711 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8715 /****************************************************************************
8716 Reply to a SMBtrans2.
8717 ****************************************************************************/
8719 void reply_trans2(struct smb_request *req)
8721 connection_struct *conn = req->conn;
8722 unsigned int dsoff;
8723 unsigned int dscnt;
8724 unsigned int psoff;
8725 unsigned int pscnt;
8726 unsigned int tran_call;
8727 struct trans_state *state;
8728 NTSTATUS result;
8730 START_PROFILE(SMBtrans2);
8732 if (req->wct < 14) {
8733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8734 END_PROFILE(SMBtrans2);
8735 return;
8738 dsoff = SVAL(req->vwv+12, 0);
8739 dscnt = SVAL(req->vwv+11, 0);
8740 psoff = SVAL(req->vwv+10, 0);
8741 pscnt = SVAL(req->vwv+9, 0);
8742 tran_call = SVAL(req->vwv+14, 0);
8744 result = allow_new_trans(conn->pending_trans, req->mid);
8745 if (!NT_STATUS_IS_OK(result)) {
8746 DEBUG(2, ("Got invalid trans2 request: %s\n",
8747 nt_errstr(result)));
8748 reply_nterror(req, result);
8749 END_PROFILE(SMBtrans2);
8750 return;
8753 if (IS_IPC(conn)) {
8754 switch (tran_call) {
8755 /* List the allowed trans2 calls on IPC$ */
8756 case TRANSACT2_OPEN:
8757 case TRANSACT2_GET_DFS_REFERRAL:
8758 case TRANSACT2_QFILEINFO:
8759 case TRANSACT2_QFSINFO:
8760 case TRANSACT2_SETFSINFO:
8761 break;
8762 default:
8763 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8764 END_PROFILE(SMBtrans2);
8765 return;
8769 if ((state = talloc(conn, struct trans_state)) == NULL) {
8770 DEBUG(0, ("talloc failed\n"));
8771 reply_nterror(req, NT_STATUS_NO_MEMORY);
8772 END_PROFILE(SMBtrans2);
8773 return;
8776 state->cmd = SMBtrans2;
8778 state->mid = req->mid;
8779 state->vuid = req->vuid;
8780 state->setup_count = SVAL(req->vwv+13, 0);
8781 state->setup = NULL;
8782 state->total_param = SVAL(req->vwv+0, 0);
8783 state->param = NULL;
8784 state->total_data = SVAL(req->vwv+1, 0);
8785 state->data = NULL;
8786 state->max_param_return = SVAL(req->vwv+2, 0);
8787 state->max_data_return = SVAL(req->vwv+3, 0);
8788 state->max_setup_return = SVAL(req->vwv+4, 0);
8789 state->close_on_completion = BITSETW(req->vwv+5, 0);
8790 state->one_way = BITSETW(req->vwv+5, 1);
8792 state->call = tran_call;
8794 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8795 is so as a sanity check */
8796 if (state->setup_count != 1) {
8798 * Need to have rc=0 for ioctl to get job id for OS/2.
8799 * Network printing will fail if function is not successful.
8800 * Similar function in reply.c will be used if protocol
8801 * is LANMAN1.0 instead of LM1.2X002.
8802 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8803 * outbuf doesn't have to be set(only job id is used).
8805 if ( (state->setup_count == 4)
8806 && (tran_call == TRANSACT2_IOCTL)
8807 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8808 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8809 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8810 } else {
8811 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8812 DEBUG(2,("Transaction is %d\n",tran_call));
8813 TALLOC_FREE(state);
8814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8815 END_PROFILE(SMBtrans2);
8816 return;
8820 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8821 goto bad_param;
8823 if (state->total_data) {
8825 if (trans_oob(state->total_data, 0, dscnt)
8826 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8827 goto bad_param;
8830 /* Can't use talloc here, the core routines do realloc on the
8831 * params and data. */
8832 state->data = (char *)SMB_MALLOC(state->total_data);
8833 if (state->data == NULL) {
8834 DEBUG(0,("reply_trans2: data malloc fail for %u "
8835 "bytes !\n", (unsigned int)state->total_data));
8836 TALLOC_FREE(state);
8837 reply_nterror(req, NT_STATUS_NO_MEMORY);
8838 END_PROFILE(SMBtrans2);
8839 return;
8842 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8845 if (state->total_param) {
8847 if (trans_oob(state->total_param, 0, pscnt)
8848 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8849 goto bad_param;
8852 /* Can't use talloc here, the core routines do realloc on the
8853 * params and data. */
8854 state->param = (char *)SMB_MALLOC(state->total_param);
8855 if (state->param == NULL) {
8856 DEBUG(0,("reply_trans: param malloc fail for %u "
8857 "bytes !\n", (unsigned int)state->total_param));
8858 SAFE_FREE(state->data);
8859 TALLOC_FREE(state);
8860 reply_nterror(req, NT_STATUS_NO_MEMORY);
8861 END_PROFILE(SMBtrans2);
8862 return;
8865 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8868 state->received_data = dscnt;
8869 state->received_param = pscnt;
8871 if ((state->received_param == state->total_param) &&
8872 (state->received_data == state->total_data)) {
8874 handle_trans2(conn, req, state);
8876 SAFE_FREE(state->data);
8877 SAFE_FREE(state->param);
8878 TALLOC_FREE(state);
8879 END_PROFILE(SMBtrans2);
8880 return;
8883 DLIST_ADD(conn->pending_trans, state);
8885 /* We need to send an interim response then receive the rest
8886 of the parameter/data bytes */
8887 reply_outbuf(req, 0, 0);
8888 show_msg((char *)req->outbuf);
8889 END_PROFILE(SMBtrans2);
8890 return;
8892 bad_param:
8894 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8895 SAFE_FREE(state->data);
8896 SAFE_FREE(state->param);
8897 TALLOC_FREE(state);
8898 END_PROFILE(SMBtrans2);
8899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8903 /****************************************************************************
8904 Reply to a SMBtranss2
8905 ****************************************************************************/
8907 void reply_transs2(struct smb_request *req)
8909 connection_struct *conn = req->conn;
8910 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8911 struct trans_state *state;
8913 START_PROFILE(SMBtranss2);
8915 show_msg((const char *)req->inbuf);
8917 /* Windows clients expect all replies to
8918 a transact secondary (SMBtranss2 0x33)
8919 to have a command code of transact
8920 (SMBtrans2 0x32). See bug #8989
8921 and also [MS-CIFS] section 2.2.4.47.2
8922 for details.
8924 req->cmd = SMBtrans2;
8926 if (req->wct < 8) {
8927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8928 END_PROFILE(SMBtranss2);
8929 return;
8932 for (state = conn->pending_trans; state != NULL;
8933 state = state->next) {
8934 if (state->mid == req->mid) {
8935 break;
8939 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8940 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8941 END_PROFILE(SMBtranss2);
8942 return;
8945 /* Revise state->total_param and state->total_data in case they have
8946 changed downwards */
8948 if (SVAL(req->vwv+0, 0) < state->total_param)
8949 state->total_param = SVAL(req->vwv+0, 0);
8950 if (SVAL(req->vwv+1, 0) < state->total_data)
8951 state->total_data = SVAL(req->vwv+1, 0);
8953 pcnt = SVAL(req->vwv+2, 0);
8954 poff = SVAL(req->vwv+3, 0);
8955 pdisp = SVAL(req->vwv+4, 0);
8957 dcnt = SVAL(req->vwv+5, 0);
8958 doff = SVAL(req->vwv+6, 0);
8959 ddisp = SVAL(req->vwv+7, 0);
8961 state->received_param += pcnt;
8962 state->received_data += dcnt;
8964 if ((state->received_data > state->total_data) ||
8965 (state->received_param > state->total_param))
8966 goto bad_param;
8968 if (pcnt) {
8969 if (trans_oob(state->total_param, pdisp, pcnt)
8970 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8971 goto bad_param;
8973 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8976 if (dcnt) {
8977 if (trans_oob(state->total_data, ddisp, dcnt)
8978 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8979 goto bad_param;
8981 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8984 if ((state->received_param < state->total_param) ||
8985 (state->received_data < state->total_data)) {
8986 END_PROFILE(SMBtranss2);
8987 return;
8990 handle_trans2(conn, req, state);
8992 DLIST_REMOVE(conn->pending_trans, state);
8993 SAFE_FREE(state->data);
8994 SAFE_FREE(state->param);
8995 TALLOC_FREE(state);
8997 END_PROFILE(SMBtranss2);
8998 return;
9000 bad_param:
9002 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9003 DLIST_REMOVE(conn->pending_trans, state);
9004 SAFE_FREE(state->data);
9005 SAFE_FREE(state->param);
9006 TALLOC_FREE(state);
9007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9008 END_PROFILE(SMBtranss2);
9009 return;