Modify fill_ea_chained_buffer() to be able to do size calculation only, no marshalling.
[Samba.git] / source3 / smbd / trans2.c
blob61252ba50736f306f4d91f368abbfb4d2ed43d0d
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 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
326 *ea_list = NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 &names, &num_names);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 if (num_names == 0) {
336 *ea_list = NULL;
337 return NT_STATUS_OK;
340 for (i=0; i<num_names; i++) {
341 struct ea_list *listp;
342 fstring dos_ea_name;
344 if (strnequal(names[i], "system.", 7)
345 || samba_private_attr_name(names[i]))
346 continue;
348 listp = talloc(mem_ctx, struct ea_list);
349 if (listp == NULL) {
350 return NT_STATUS_NO_MEMORY;
353 status = get_ea_value(mem_ctx, conn, fsp,
354 fname, names[i],
355 &listp->ea);
357 if (!NT_STATUS_IS_OK(status)) {
358 return status;
361 push_ascii_fstring(dos_ea_name, listp->ea.name);
363 *pea_total_len +=
364 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
366 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
367 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
368 (unsigned int)listp->ea.value.length));
370 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
374 /* Add on 4 for total length. */
375 if (*pea_total_len) {
376 *pea_total_len += 4;
379 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
380 (unsigned int)*pea_total_len));
382 *ea_list = ea_list_head;
383 return NT_STATUS_OK;
386 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
387 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
389 *pea_total_len = 0;
390 *ea_list = NULL;
392 if (!lp_ea_support(SNUM(conn))) {
393 return NT_STATUS_OK;
396 if (is_ntfs_stream_smb_fname(smb_fname)) {
397 return NT_STATUS_INVALID_PARAMETER;
400 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
403 /****************************************************************************
404 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
405 that was filled.
406 ****************************************************************************/
408 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
409 connection_struct *conn, struct ea_list *ea_list)
411 unsigned int ret_data_size = 4;
412 char *p = pdata;
414 SMB_ASSERT(total_data_size >= 4);
416 if (!lp_ea_support(SNUM(conn))) {
417 SIVAL(pdata,4,0);
418 return 4;
421 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
422 size_t dos_namelen;
423 fstring dos_ea_name;
424 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
425 dos_namelen = strlen(dos_ea_name);
426 if (dos_namelen > 255 || dos_namelen == 0) {
427 break;
429 if (ea_list->ea.value.length > 65535) {
430 break;
432 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
433 break;
436 /* We know we have room. */
437 SCVAL(p,0,ea_list->ea.flags);
438 SCVAL(p,1,dos_namelen);
439 SSVAL(p,2,ea_list->ea.value.length);
440 strlcpy(p+4, dos_ea_name, dos_namelen+1);
441 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
443 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
444 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
447 ret_data_size = PTR_DIFF(p, pdata);
448 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
449 SIVAL(pdata,0,ret_data_size);
450 return ret_data_size;
453 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
454 char *pdata,
455 unsigned int total_data_size,
456 unsigned int *ret_data_size,
457 connection_struct *conn,
458 struct ea_list *ea_list)
460 uint8_t *p = (uint8_t *)pdata;
461 uint8_t *last_start = NULL;
462 bool do_store_data = (pdata != NULL);
464 *ret_data_size = 0;
466 if (!lp_ea_support(SNUM(conn))) {
467 return NT_STATUS_NO_EAS_ON_FILE;
470 for (; ea_list; ea_list = ea_list->next) {
471 size_t dos_namelen;
472 fstring dos_ea_name;
473 size_t this_size;
475 if (last_start != NULL && do_store_data) {
476 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
478 last_start = p;
480 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
481 dos_namelen = strlen(dos_ea_name);
482 if (dos_namelen > 255 || dos_namelen == 0) {
483 return NT_STATUS_INTERNAL_ERROR;
485 if (ea_list->ea.value.length > 65535) {
486 return NT_STATUS_INTERNAL_ERROR;
489 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
491 if (ea_list->next) {
492 size_t pad = 4 - (this_size % 4);
493 this_size += pad;
496 if (do_store_data) {
497 if (this_size > total_data_size) {
498 return NT_STATUS_INFO_LENGTH_MISMATCH;
501 /* We know we have room. */
502 SIVAL(p, 0x00, 0); /* next offset */
503 SCVAL(p, 0x04, ea_list->ea.flags);
504 SCVAL(p, 0x05, dos_namelen);
505 SSVAL(p, 0x06, ea_list->ea.value.length);
506 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
507 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
508 total_data_size -= this_size;
511 p += this_size;
514 *ret_data_size = PTR_DIFF(p, pdata);
515 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
516 return NT_STATUS_OK;
519 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
521 size_t total_ea_len = 0;
522 TALLOC_CTX *mem_ctx;
523 struct ea_list *ea_list = NULL;
525 if (!lp_ea_support(SNUM(conn))) {
526 return 0;
528 mem_ctx = talloc_stackframe();
530 /* If this is a stream fsp, then we need to instead find the
531 * estimated ea len from the main file, not the stream
532 * (streams cannot have EAs), but the estimate isn't just 0 in
533 * this case! */
534 if (is_ntfs_stream_smb_fname(smb_fname)) {
535 fsp = NULL;
537 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
538 TALLOC_FREE(mem_ctx);
539 return total_ea_len;
542 /****************************************************************************
543 Ensure the EA name is case insensitive by matching any existing EA name.
544 ****************************************************************************/
546 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
548 size_t total_ea_len;
549 TALLOC_CTX *mem_ctx = talloc_tos();
550 struct ea_list *ea_list;
551 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
552 if (!NT_STATUS_IS_OK(status)) {
553 return;
556 for (; ea_list; ea_list = ea_list->next) {
557 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
558 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
559 &unix_ea_name[5], ea_list->ea.name));
560 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
561 break;
566 /****************************************************************************
567 Set or delete an extended attribute.
568 ****************************************************************************/
570 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
571 const struct smb_filename *smb_fname, struct ea_list *ea_list)
573 NTSTATUS status;
574 char *fname = NULL;
576 if (!lp_ea_support(SNUM(conn))) {
577 return NT_STATUS_EAS_NOT_SUPPORTED;
580 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
581 if (!NT_STATUS_IS_OK(status)) {
582 return status;
585 /* Setting EAs on streams isn't supported. */
586 if (is_ntfs_stream_smb_fname(smb_fname)) {
587 return NT_STATUS_INVALID_PARAMETER;
590 fname = smb_fname->base_name;
592 for (;ea_list; ea_list = ea_list->next) {
593 int ret;
594 fstring unix_ea_name;
596 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
597 fstrcat(unix_ea_name, ea_list->ea.name);
599 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
601 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
603 if (samba_private_attr_name(unix_ea_name)) {
604 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
605 return NT_STATUS_ACCESS_DENIED;
608 if (ea_list->ea.value.length == 0) {
609 /* Remove the attribute. */
610 if (fsp && (fsp->fh->fd != -1)) {
611 DEBUG(10,("set_ea: deleting ea name %s on "
612 "file %s by file descriptor.\n",
613 unix_ea_name, fsp_str_dbg(fsp)));
614 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
615 } else {
616 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
617 unix_ea_name, fname));
618 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
620 #ifdef ENOATTR
621 /* Removing a non existent attribute always succeeds. */
622 if (ret == -1 && errno == ENOATTR) {
623 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
624 unix_ea_name));
625 ret = 0;
627 #endif
628 } else {
629 if (fsp && (fsp->fh->fd != -1)) {
630 DEBUG(10,("set_ea: setting ea name %s on file "
631 "%s by file descriptor.\n",
632 unix_ea_name, fsp_str_dbg(fsp)));
633 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
634 ea_list->ea.value.data, ea_list->ea.value.length, 0);
635 } else {
636 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
637 unix_ea_name, fname));
638 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
639 ea_list->ea.value.data, ea_list->ea.value.length, 0);
643 if (ret == -1) {
644 #ifdef ENOTSUP
645 if (errno == ENOTSUP) {
646 return NT_STATUS_EAS_NOT_SUPPORTED;
648 #endif
649 return map_nt_error_from_unix(errno);
653 return NT_STATUS_OK;
655 /****************************************************************************
656 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
657 ****************************************************************************/
659 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
661 struct ea_list *ea_list_head = NULL;
662 size_t converted_size, offset = 0;
664 while (offset + 2 < data_size) {
665 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
666 unsigned int namelen = CVAL(pdata,offset);
668 offset++; /* Go past the namelen byte. */
670 /* integer wrap paranioa. */
671 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
672 (offset > data_size) || (namelen > data_size) ||
673 (offset + namelen >= data_size)) {
674 break;
676 /* Ensure the name is null terminated. */
677 if (pdata[offset + namelen] != '\0') {
678 return NULL;
680 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
681 &converted_size)) {
682 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
683 "failed: %s", strerror(errno)));
685 if (!eal->ea.name) {
686 return NULL;
689 offset += (namelen + 1); /* Go past the name + terminating zero. */
690 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
691 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
694 return ea_list_head;
697 /****************************************************************************
698 Read one EA list entry from the buffer.
699 ****************************************************************************/
701 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
703 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
704 uint16 val_len;
705 unsigned int namelen;
706 size_t converted_size;
708 if (!eal) {
709 return NULL;
712 if (data_size < 6) {
713 return NULL;
716 eal->ea.flags = CVAL(pdata,0);
717 namelen = CVAL(pdata,1);
718 val_len = SVAL(pdata,2);
720 if (4 + namelen + 1 + val_len > data_size) {
721 return NULL;
724 /* Ensure the name is null terminated. */
725 if (pdata[namelen + 4] != '\0') {
726 return NULL;
728 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
729 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
730 strerror(errno)));
732 if (!eal->ea.name) {
733 return NULL;
736 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
737 if (!eal->ea.value.data) {
738 return NULL;
741 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
743 /* Ensure we're null terminated just in case we print the value. */
744 eal->ea.value.data[val_len] = '\0';
745 /* But don't count the null. */
746 eal->ea.value.length--;
748 if (pbytes_used) {
749 *pbytes_used = 4 + namelen + 1 + val_len;
752 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
753 dump_data(10, eal->ea.value.data, eal->ea.value.length);
755 return eal;
758 /****************************************************************************
759 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
760 ****************************************************************************/
762 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
764 struct ea_list *ea_list_head = NULL;
765 size_t offset = 0;
766 size_t bytes_used = 0;
768 while (offset < data_size) {
769 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
771 if (!eal) {
772 return NULL;
775 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
776 offset += bytes_used;
779 return ea_list_head;
782 /****************************************************************************
783 Count the total EA size needed.
784 ****************************************************************************/
786 static size_t ea_list_size(struct ea_list *ealist)
788 fstring dos_ea_name;
789 struct ea_list *listp;
790 size_t ret = 0;
792 for (listp = ealist; listp; listp = listp->next) {
793 push_ascii_fstring(dos_ea_name, listp->ea.name);
794 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
796 /* Add on 4 for total length. */
797 if (ret) {
798 ret += 4;
801 return ret;
804 /****************************************************************************
805 Return a union of EA's from a file list and a list of names.
806 The TALLOC context for the two lists *MUST* be identical as we steal
807 memory from one list to add to another. JRA.
808 ****************************************************************************/
810 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
812 struct ea_list *nlistp, *flistp;
814 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
815 for (flistp = file_list; flistp; flistp = flistp->next) {
816 if (strequal(nlistp->ea.name, flistp->ea.name)) {
817 break;
821 if (flistp) {
822 /* Copy the data from this entry. */
823 nlistp->ea.flags = flistp->ea.flags;
824 nlistp->ea.value = flistp->ea.value;
825 } else {
826 /* Null entry. */
827 nlistp->ea.flags = 0;
828 ZERO_STRUCT(nlistp->ea.value);
832 *total_ea_len = ea_list_size(name_list);
833 return name_list;
836 /****************************************************************************
837 Send the required number of replies back.
838 We assume all fields other than the data fields are
839 set correctly for the type of call.
840 HACK ! Always assumes smb_setup field is zero.
841 ****************************************************************************/
843 void send_trans2_replies(connection_struct *conn,
844 struct smb_request *req,
845 const char *params,
846 int paramsize,
847 const char *pdata,
848 int datasize,
849 int max_data_bytes)
851 /* As we are using a protocol > LANMAN1 then the max_send
852 variable must have been set in the sessetupX call.
853 This takes precedence over the max_xmit field in the
854 global struct. These different max_xmit variables should
855 be merged as this is now too confusing */
857 int data_to_send = datasize;
858 int params_to_send = paramsize;
859 int useable_space;
860 const char *pp = params;
861 const char *pd = pdata;
862 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
863 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
864 int data_alignment_offset = 0;
865 bool overflow = False;
866 struct smbd_server_connection *sconn = req->sconn;
867 int max_send = sconn->smb1.sessions.max_send;
869 /* Modify the data_to_send and datasize and set the error if
870 we're trying to send more than max_data_bytes. We still send
871 the part of the packet(s) that fit. Strange, but needed
872 for OS/2. */
874 if (max_data_bytes > 0 && datasize > max_data_bytes) {
875 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
876 max_data_bytes, datasize ));
877 datasize = data_to_send = max_data_bytes;
878 overflow = True;
881 /* If there genuinely are no parameters or data to send just send the empty packet */
883 if(params_to_send == 0 && data_to_send == 0) {
884 reply_outbuf(req, 10, 0);
885 show_msg((char *)req->outbuf);
886 if (!srv_send_smb(sconn,
887 (char *)req->outbuf,
888 true, req->seqnum+1,
889 IS_CONN_ENCRYPTED(conn),
890 &req->pcd)) {
891 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
893 TALLOC_FREE(req->outbuf);
894 return;
897 /* When sending params and data ensure that both are nicely aligned */
898 /* Only do this alignment when there is also data to send - else
899 can cause NT redirector problems. */
901 if (((params_to_send % 4) != 0) && (data_to_send != 0))
902 data_alignment_offset = 4 - (params_to_send % 4);
904 /* Space is bufsize minus Netbios over TCP header minus SMB header */
905 /* The alignment_offset is to align the param bytes on an even byte
906 boundary. NT 4.0 Beta needs this to work correctly. */
908 useable_space = max_send - (smb_size
909 + 2 * 10 /* wct */
910 + alignment_offset
911 + data_alignment_offset);
913 if (useable_space < 0) {
914 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
915 "= %d!!!", useable_space));
916 exit_server_cleanly("send_trans2_replies: Not enough space");
919 while (params_to_send || data_to_send) {
920 /* Calculate whether we will totally or partially fill this packet */
922 total_sent_thistime = params_to_send + data_to_send;
924 /* We can never send more than useable_space */
926 * Note that 'useable_space' does not include the alignment offsets,
927 * but we must include the alignment offsets in the calculation of
928 * the length of the data we send over the wire, as the alignment offsets
929 * are sent here. Fix from Marc_Jacobsen@hp.com.
932 total_sent_thistime = MIN(total_sent_thistime, useable_space);
934 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
935 + data_alignment_offset);
937 /* Set total params and data to be sent */
938 SSVAL(req->outbuf,smb_tprcnt,paramsize);
939 SSVAL(req->outbuf,smb_tdrcnt,datasize);
941 /* Calculate how many parameters and data we can fit into
942 * this packet. Parameters get precedence
945 params_sent_thistime = MIN(params_to_send,useable_space);
946 data_sent_thistime = useable_space - params_sent_thistime;
947 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
949 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
951 /* smb_proff is the offset from the start of the SMB header to the
952 parameter bytes, however the first 4 bytes of outbuf are
953 the Netbios over TCP header. Thus use smb_base() to subtract
954 them from the calculation */
956 SSVAL(req->outbuf,smb_proff,
957 ((smb_buf(req->outbuf)+alignment_offset)
958 - smb_base(req->outbuf)));
960 if(params_sent_thistime == 0)
961 SSVAL(req->outbuf,smb_prdisp,0);
962 else
963 /* Absolute displacement of param bytes sent in this packet */
964 SSVAL(req->outbuf,smb_prdisp,pp - params);
966 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
967 if(data_sent_thistime == 0) {
968 SSVAL(req->outbuf,smb_droff,0);
969 SSVAL(req->outbuf,smb_drdisp, 0);
970 } else {
971 /* The offset of the data bytes is the offset of the
972 parameter bytes plus the number of parameters being sent this time */
973 SSVAL(req->outbuf, smb_droff,
974 ((smb_buf(req->outbuf)+alignment_offset)
975 - smb_base(req->outbuf))
976 + params_sent_thistime + data_alignment_offset);
977 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
980 /* Initialize the padding for alignment */
982 if (alignment_offset != 0) {
983 memset(smb_buf(req->outbuf), 0, alignment_offset);
986 /* Copy the param bytes into the packet */
988 if(params_sent_thistime) {
989 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
990 params_sent_thistime);
993 /* Copy in the data bytes */
994 if(data_sent_thistime) {
995 if (data_alignment_offset != 0) {
996 memset((smb_buf(req->outbuf)+alignment_offset+
997 params_sent_thistime), 0,
998 data_alignment_offset);
1000 memcpy(smb_buf(req->outbuf)+alignment_offset
1001 +params_sent_thistime+data_alignment_offset,
1002 pd,data_sent_thistime);
1005 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1006 params_sent_thistime, data_sent_thistime, useable_space));
1007 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1008 params_to_send, data_to_send, paramsize, datasize));
1010 if (overflow) {
1011 error_packet_set((char *)req->outbuf,
1012 ERRDOS,ERRbufferoverflow,
1013 STATUS_BUFFER_OVERFLOW,
1014 __LINE__,__FILE__);
1017 /* Send the packet */
1018 show_msg((char *)req->outbuf);
1019 if (!srv_send_smb(sconn,
1020 (char *)req->outbuf,
1021 true, req->seqnum+1,
1022 IS_CONN_ENCRYPTED(conn),
1023 &req->pcd))
1024 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1026 TALLOC_FREE(req->outbuf);
1028 pp += params_sent_thistime;
1029 pd += data_sent_thistime;
1031 params_to_send -= params_sent_thistime;
1032 data_to_send -= data_sent_thistime;
1034 /* Sanity check */
1035 if(params_to_send < 0 || data_to_send < 0) {
1036 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1037 params_to_send, data_to_send));
1038 return;
1042 return;
1045 /****************************************************************************
1046 Reply to a TRANSACT2_OPEN.
1047 ****************************************************************************/
1049 static void call_trans2open(connection_struct *conn,
1050 struct smb_request *req,
1051 char **pparams, int total_params,
1052 char **ppdata, int total_data,
1053 unsigned int max_data_bytes)
1055 struct smb_filename *smb_fname = NULL;
1056 char *params = *pparams;
1057 char *pdata = *ppdata;
1058 int deny_mode;
1059 int32 open_attr;
1060 bool oplock_request;
1061 #if 0
1062 bool return_additional_info;
1063 int16 open_sattr;
1064 time_t open_time;
1065 #endif
1066 int open_ofun;
1067 uint32 open_size;
1068 char *pname;
1069 char *fname = NULL;
1070 off_t size=0;
1071 int fattr=0,mtime=0;
1072 SMB_INO_T inode = 0;
1073 int smb_action = 0;
1074 files_struct *fsp;
1075 struct ea_list *ea_list = NULL;
1076 uint16 flags = 0;
1077 NTSTATUS status;
1078 uint32 access_mask;
1079 uint32 share_mode;
1080 uint32 create_disposition;
1081 uint32 create_options = 0;
1082 uint32_t private_flags = 0;
1083 TALLOC_CTX *ctx = talloc_tos();
1086 * Ensure we have enough parameters to perform the operation.
1089 if (total_params < 29) {
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 goto out;
1094 flags = SVAL(params, 0);
1095 deny_mode = SVAL(params, 2);
1096 open_attr = SVAL(params,6);
1097 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1098 if (oplock_request) {
1099 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1102 #if 0
1103 return_additional_info = BITSETW(params,0);
1104 open_sattr = SVAL(params, 4);
1105 open_time = make_unix_date3(params+8);
1106 #endif
1107 open_ofun = SVAL(params,12);
1108 open_size = IVAL(params,14);
1109 pname = &params[28];
1111 if (IS_IPC(conn)) {
1112 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1113 goto out;
1116 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1117 total_params - 28, STR_TERMINATE,
1118 &status);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 reply_nterror(req, status);
1121 goto out;
1124 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1125 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1126 (unsigned int)open_ofun, open_size));
1128 status = filename_convert(ctx,
1129 conn,
1130 req->flags2 & FLAGS2_DFS_PATHNAMES,
1131 fname,
1133 NULL,
1134 &smb_fname);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1137 reply_botherror(req,
1138 NT_STATUS_PATH_NOT_COVERED,
1139 ERRSRV, ERRbadpath);
1140 goto out;
1142 reply_nterror(req, status);
1143 goto out;
1146 if (open_ofun == 0) {
1147 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1148 goto out;
1151 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1152 open_ofun,
1153 &access_mask, &share_mode,
1154 &create_disposition,
1155 &create_options,
1156 &private_flags)) {
1157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1158 goto out;
1161 /* Any data in this call is an EA list. */
1162 if (total_data && (total_data != 4)) {
1163 if (total_data < 10) {
1164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1165 goto out;
1168 if (IVAL(pdata,0) > total_data) {
1169 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1170 IVAL(pdata,0), (unsigned int)total_data));
1171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1172 goto out;
1175 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1176 total_data - 4);
1177 if (!ea_list) {
1178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1179 goto out;
1182 if (!lp_ea_support(SNUM(conn))) {
1183 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1184 goto out;
1188 status = SMB_VFS_CREATE_FILE(
1189 conn, /* conn */
1190 req, /* req */
1191 0, /* root_dir_fid */
1192 smb_fname, /* fname */
1193 access_mask, /* access_mask */
1194 share_mode, /* share_access */
1195 create_disposition, /* create_disposition*/
1196 create_options, /* create_options */
1197 open_attr, /* file_attributes */
1198 oplock_request, /* oplock_request */
1199 open_size, /* allocation_size */
1200 private_flags,
1201 NULL, /* sd */
1202 ea_list, /* ea_list */
1203 &fsp, /* result */
1204 &smb_action); /* psbuf */
1206 if (!NT_STATUS_IS_OK(status)) {
1207 if (open_was_deferred(req->sconn, req->mid)) {
1208 /* We have re-scheduled this call. */
1209 goto out;
1211 reply_openerror(req, status);
1212 goto out;
1215 size = get_file_size_stat(&smb_fname->st);
1216 fattr = dos_mode(conn, smb_fname);
1217 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1218 inode = smb_fname->st.st_ex_ino;
1219 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1220 close_file(req, fsp, ERROR_CLOSE);
1221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1222 goto out;
1225 /* Realloc the size of parameters and data we will return */
1226 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1227 if(*pparams == NULL ) {
1228 reply_nterror(req, NT_STATUS_NO_MEMORY);
1229 goto out;
1231 params = *pparams;
1233 SSVAL(params,0,fsp->fnum);
1234 SSVAL(params,2,fattr);
1235 srv_put_dos_date2(params,4, mtime);
1236 SIVAL(params,8, (uint32)size);
1237 SSVAL(params,12,deny_mode);
1238 SSVAL(params,14,0); /* open_type - file or directory. */
1239 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1241 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1242 smb_action |= EXTENDED_OPLOCK_GRANTED;
1245 SSVAL(params,18,smb_action);
1248 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1250 SIVAL(params,20,inode);
1251 SSVAL(params,24,0); /* Padding. */
1252 if (flags & 8) {
1253 uint32 ea_size = estimate_ea_size(conn, fsp,
1254 smb_fname);
1255 SIVAL(params, 26, ea_size);
1256 } else {
1257 SIVAL(params, 26, 0);
1260 /* Send the required number of replies */
1261 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1262 out:
1263 TALLOC_FREE(smb_fname);
1266 /*********************************************************
1267 Routine to check if a given string matches exactly.
1268 as a special case a mask of "." does NOT match. That
1269 is required for correct wildcard semantics
1270 Case can be significant or not.
1271 **********************************************************/
1273 static bool exact_match(bool has_wild,
1274 bool case_sensitive,
1275 const char *str,
1276 const char *mask)
1278 if (mask[0] == '.' && mask[1] == 0) {
1279 return false;
1282 if (has_wild) {
1283 return false;
1286 if (case_sensitive) {
1287 return strcmp(str,mask)==0;
1288 } else {
1289 return strcasecmp_m(str,mask) == 0;
1293 /****************************************************************************
1294 Return the filetype for UNIX extensions.
1295 ****************************************************************************/
1297 static uint32 unix_filetype(mode_t mode)
1299 if(S_ISREG(mode))
1300 return UNIX_TYPE_FILE;
1301 else if(S_ISDIR(mode))
1302 return UNIX_TYPE_DIR;
1303 #ifdef S_ISLNK
1304 else if(S_ISLNK(mode))
1305 return UNIX_TYPE_SYMLINK;
1306 #endif
1307 #ifdef S_ISCHR
1308 else if(S_ISCHR(mode))
1309 return UNIX_TYPE_CHARDEV;
1310 #endif
1311 #ifdef S_ISBLK
1312 else if(S_ISBLK(mode))
1313 return UNIX_TYPE_BLKDEV;
1314 #endif
1315 #ifdef S_ISFIFO
1316 else if(S_ISFIFO(mode))
1317 return UNIX_TYPE_FIFO;
1318 #endif
1319 #ifdef S_ISSOCK
1320 else if(S_ISSOCK(mode))
1321 return UNIX_TYPE_SOCKET;
1322 #endif
1324 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1325 return UNIX_TYPE_UNKNOWN;
1328 /****************************************************************************
1329 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1330 ****************************************************************************/
1332 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1334 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1335 const SMB_STRUCT_STAT *psbuf,
1336 uint32 perms,
1337 enum perm_type ptype,
1338 mode_t *ret_perms)
1340 mode_t ret = 0;
1342 if (perms == SMB_MODE_NO_CHANGE) {
1343 if (!VALID_STAT(*psbuf)) {
1344 return NT_STATUS_INVALID_PARAMETER;
1345 } else {
1346 *ret_perms = psbuf->st_ex_mode;
1347 return NT_STATUS_OK;
1351 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1352 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1353 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1354 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1355 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1356 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1357 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1358 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1359 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1360 #ifdef S_ISVTX
1361 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1362 #endif
1363 #ifdef S_ISGID
1364 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1365 #endif
1366 #ifdef S_ISUID
1367 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1368 #endif
1370 switch (ptype) {
1371 case PERM_NEW_FILE:
1372 case PERM_EXISTING_FILE:
1373 /* Apply mode mask */
1374 ret &= lp_create_mask(SNUM(conn));
1375 /* Add in force bits */
1376 ret |= lp_force_create_mode(SNUM(conn));
1377 break;
1378 case PERM_NEW_DIR:
1379 case PERM_EXISTING_DIR:
1380 ret &= lp_dir_mask(SNUM(conn));
1381 /* Add in force bits */
1382 ret |= lp_force_dir_mode(SNUM(conn));
1383 break;
1386 *ret_perms = ret;
1387 return NT_STATUS_OK;
1390 /****************************************************************************
1391 Needed to show the msdfs symlinks as directories. Modifies psbuf
1392 to be a directory if it's a msdfs link.
1393 ****************************************************************************/
1395 static bool check_msdfs_link(connection_struct *conn,
1396 const char *pathname,
1397 SMB_STRUCT_STAT *psbuf)
1399 int saved_errno = errno;
1400 if(lp_host_msdfs() &&
1401 lp_msdfs_root(SNUM(conn)) &&
1402 is_msdfs_link(conn, pathname, psbuf)) {
1404 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1405 "as a directory\n",
1406 pathname));
1407 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1408 errno = saved_errno;
1409 return true;
1411 errno = saved_errno;
1412 return false;
1416 /****************************************************************************
1417 Get a level dependent lanman2 dir entry.
1418 ****************************************************************************/
1420 struct smbd_dirptr_lanman2_state {
1421 connection_struct *conn;
1422 uint32_t info_level;
1423 bool check_mangled_names;
1424 bool has_wild;
1425 bool got_exact_match;
1428 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1429 void *private_data,
1430 const char *dname,
1431 const char *mask,
1432 char **_fname)
1434 struct smbd_dirptr_lanman2_state *state =
1435 (struct smbd_dirptr_lanman2_state *)private_data;
1436 bool ok;
1437 char mangled_name[13]; /* mangled 8.3 name. */
1438 bool got_match;
1439 const char *fname;
1441 /* Mangle fname if it's an illegal name. */
1442 if (mangle_must_mangle(dname, state->conn->params)) {
1443 ok = name_to_8_3(dname, mangled_name,
1444 true, state->conn->params);
1445 if (!ok) {
1446 return false;
1448 fname = mangled_name;
1449 } else {
1450 fname = dname;
1453 got_match = exact_match(state->has_wild,
1454 state->conn->case_sensitive,
1455 fname, mask);
1456 state->got_exact_match = got_match;
1457 if (!got_match) {
1458 got_match = mask_match(fname, mask,
1459 state->conn->case_sensitive);
1462 if(!got_match && state->check_mangled_names &&
1463 !mangle_is_8_3(fname, false, state->conn->params)) {
1465 * It turns out that NT matches wildcards against
1466 * both long *and* short names. This may explain some
1467 * of the wildcard wierdness from old DOS clients
1468 * that some people have been seeing.... JRA.
1470 /* Force the mangling into 8.3. */
1471 ok = name_to_8_3(fname, mangled_name,
1472 false, state->conn->params);
1473 if (!ok) {
1474 return false;
1477 got_match = exact_match(state->has_wild,
1478 state->conn->case_sensitive,
1479 mangled_name, mask);
1480 state->got_exact_match = got_match;
1481 if (!got_match) {
1482 got_match = mask_match(mangled_name, mask,
1483 state->conn->case_sensitive);
1487 if (!got_match) {
1488 return false;
1491 *_fname = talloc_strdup(ctx, fname);
1492 if (*_fname == NULL) {
1493 return false;
1496 return true;
1499 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1500 void *private_data,
1501 struct smb_filename *smb_fname,
1502 uint32_t *_mode)
1504 struct smbd_dirptr_lanman2_state *state =
1505 (struct smbd_dirptr_lanman2_state *)private_data;
1506 bool ms_dfs_link = false;
1507 uint32_t mode = 0;
1509 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1510 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1511 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1512 "Couldn't lstat [%s] (%s)\n",
1513 smb_fname_str_dbg(smb_fname),
1514 strerror(errno)));
1515 return false;
1517 } else if (!VALID_STAT(smb_fname->st) &&
1518 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1519 /* Needed to show the msdfs symlinks as
1520 * directories */
1522 ms_dfs_link = check_msdfs_link(state->conn,
1523 smb_fname->base_name,
1524 &smb_fname->st);
1525 if (!ms_dfs_link) {
1526 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1527 "Couldn't stat [%s] (%s)\n",
1528 smb_fname_str_dbg(smb_fname),
1529 strerror(errno)));
1530 return false;
1534 if (ms_dfs_link) {
1535 mode = dos_mode_msdfs(state->conn, smb_fname);
1536 } else {
1537 mode = dos_mode(state->conn, smb_fname);
1540 *_mode = mode;
1541 return true;
1544 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1545 connection_struct *conn,
1546 uint16_t flags2,
1547 uint32_t info_level,
1548 struct ea_list *name_list,
1549 bool check_mangled_names,
1550 bool requires_resume_key,
1551 uint32_t mode,
1552 const char *fname,
1553 const struct smb_filename *smb_fname,
1554 int space_remaining,
1555 uint8_t align,
1556 bool do_pad,
1557 char *base_data,
1558 char **ppdata,
1559 char *end_data,
1560 bool *out_of_space,
1561 uint64_t *last_entry_off)
1563 char *p, *q, *pdata = *ppdata;
1564 uint32_t reskey=0;
1565 uint64_t file_size = 0;
1566 uint64_t allocation_size = 0;
1567 uint64_t file_index = 0;
1568 uint32_t len;
1569 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1570 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1571 char *nameptr;
1572 char *last_entry_ptr;
1573 bool was_8_3;
1574 int off;
1575 int pad = 0;
1577 *out_of_space = false;
1579 ZERO_STRUCT(mdate_ts);
1580 ZERO_STRUCT(adate_ts);
1581 ZERO_STRUCT(create_date_ts);
1582 ZERO_STRUCT(cdate_ts);
1584 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1585 file_size = get_file_size_stat(&smb_fname->st);
1587 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1589 file_index = get_FileIndex(conn, &smb_fname->st);
1591 mdate_ts = smb_fname->st.st_ex_mtime;
1592 adate_ts = smb_fname->st.st_ex_atime;
1593 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1594 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1596 if (lp_dos_filetime_resolution(SNUM(conn))) {
1597 dos_filetime_timespec(&create_date_ts);
1598 dos_filetime_timespec(&mdate_ts);
1599 dos_filetime_timespec(&adate_ts);
1600 dos_filetime_timespec(&cdate_ts);
1603 create_date = convert_timespec_to_time_t(create_date_ts);
1604 mdate = convert_timespec_to_time_t(mdate_ts);
1605 adate = convert_timespec_to_time_t(adate_ts);
1607 /* align the record */
1608 SMB_ASSERT(align >= 1);
1610 off = (int)PTR_DIFF(pdata, base_data);
1611 pad = (off + (align-1)) & ~(align-1);
1612 pad -= off;
1614 if (pad && pad > space_remaining) {
1615 *out_of_space = true;
1616 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1617 "for padding (wanted %u, had %d)\n",
1618 (unsigned int)pad,
1619 space_remaining ));
1620 return false; /* Not finished - just out of space */
1623 off += pad;
1624 /* initialize padding to 0 */
1625 if (pad) {
1626 memset(pdata, 0, pad);
1628 space_remaining -= pad;
1630 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1631 space_remaining ));
1633 pdata += pad;
1634 p = pdata;
1635 last_entry_ptr = p;
1637 pad = 0;
1638 off = 0;
1640 switch (info_level) {
1641 case SMB_FIND_INFO_STANDARD:
1642 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1643 if(requires_resume_key) {
1644 SIVAL(p,0,reskey);
1645 p += 4;
1647 srv_put_dos_date2(p,0,create_date);
1648 srv_put_dos_date2(p,4,adate);
1649 srv_put_dos_date2(p,8,mdate);
1650 SIVAL(p,12,(uint32)file_size);
1651 SIVAL(p,16,(uint32)allocation_size);
1652 SSVAL(p,20,mode);
1653 p += 23;
1654 nameptr = p;
1655 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1656 p += ucs2_align(base_data, p, 0);
1658 len = srvstr_push(base_data, flags2, p,
1659 fname, PTR_DIFF(end_data, p),
1660 STR_TERMINATE);
1661 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1662 if (len > 2) {
1663 SCVAL(nameptr, -1, len - 2);
1664 } else {
1665 SCVAL(nameptr, -1, 0);
1667 } else {
1668 if (len > 1) {
1669 SCVAL(nameptr, -1, len - 1);
1670 } else {
1671 SCVAL(nameptr, -1, 0);
1674 p += len;
1675 break;
1677 case SMB_FIND_EA_SIZE:
1678 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1679 if (requires_resume_key) {
1680 SIVAL(p,0,reskey);
1681 p += 4;
1683 srv_put_dos_date2(p,0,create_date);
1684 srv_put_dos_date2(p,4,adate);
1685 srv_put_dos_date2(p,8,mdate);
1686 SIVAL(p,12,(uint32)file_size);
1687 SIVAL(p,16,(uint32)allocation_size);
1688 SSVAL(p,20,mode);
1690 unsigned int ea_size = estimate_ea_size(conn, NULL,
1691 smb_fname);
1692 SIVAL(p,22,ea_size); /* Extended attributes */
1694 p += 27;
1695 nameptr = p - 1;
1696 len = srvstr_push(base_data, flags2,
1697 p, fname, PTR_DIFF(end_data, p),
1698 STR_TERMINATE | STR_NOALIGN);
1699 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1700 if (len > 2) {
1701 len -= 2;
1702 } else {
1703 len = 0;
1705 } else {
1706 if (len > 1) {
1707 len -= 1;
1708 } else {
1709 len = 0;
1712 SCVAL(nameptr,0,len);
1713 p += len;
1714 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1715 break;
1717 case SMB_FIND_EA_LIST:
1719 struct ea_list *file_list = NULL;
1720 size_t ea_len = 0;
1721 NTSTATUS status;
1723 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1724 if (!name_list) {
1725 return false;
1727 if (requires_resume_key) {
1728 SIVAL(p,0,reskey);
1729 p += 4;
1731 srv_put_dos_date2(p,0,create_date);
1732 srv_put_dos_date2(p,4,adate);
1733 srv_put_dos_date2(p,8,mdate);
1734 SIVAL(p,12,(uint32)file_size);
1735 SIVAL(p,16,(uint32)allocation_size);
1736 SSVAL(p,20,mode);
1737 p += 22; /* p now points to the EA area. */
1739 status = get_ea_list_from_file(ctx, conn, NULL,
1740 smb_fname,
1741 &ea_len, &file_list);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 file_list = NULL;
1745 name_list = ea_list_union(name_list, file_list, &ea_len);
1747 /* We need to determine if this entry will fit in the space available. */
1748 /* Max string size is 255 bytes. */
1749 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1750 *out_of_space = true;
1751 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1752 "(wanted %u, had %d)\n",
1753 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1754 space_remaining ));
1755 return False; /* Not finished - just out of space */
1758 /* Push the ea_data followed by the name. */
1759 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1760 nameptr = p;
1761 len = srvstr_push(base_data, flags2,
1762 p + 1, fname, PTR_DIFF(end_data, p+1),
1763 STR_TERMINATE | STR_NOALIGN);
1764 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1765 if (len > 2) {
1766 len -= 2;
1767 } else {
1768 len = 0;
1770 } else {
1771 if (len > 1) {
1772 len -= 1;
1773 } else {
1774 len = 0;
1777 SCVAL(nameptr,0,len);
1778 p += len + 1;
1779 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1780 break;
1783 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1784 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1785 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1786 p += 4;
1787 SIVAL(p,0,reskey); p += 4;
1788 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1789 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1790 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1791 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1792 SOFF_T(p,0,file_size); p += 8;
1793 SOFF_T(p,0,allocation_size); p += 8;
1794 SIVAL(p,0,mode); p += 4;
1795 q = p; p += 4; /* q is placeholder for name length. */
1797 unsigned int ea_size = estimate_ea_size(conn, NULL,
1798 smb_fname);
1799 SIVAL(p,0,ea_size); /* Extended attributes */
1800 p += 4;
1802 /* Clear the short name buffer. This is
1803 * IMPORTANT as not doing so will trigger
1804 * a Win2k client bug. JRA.
1806 if (!was_8_3 && check_mangled_names) {
1807 char mangled_name[13]; /* mangled 8.3 name. */
1808 if (!name_to_8_3(fname,mangled_name,True,
1809 conn->params)) {
1810 /* Error - mangle failed ! */
1811 memset(mangled_name,'\0',12);
1813 mangled_name[12] = 0;
1814 len = srvstr_push(base_data, flags2,
1815 p+2, mangled_name, 24,
1816 STR_UPPER|STR_UNICODE);
1817 if (len < 24) {
1818 memset(p + 2 + len,'\0',24 - len);
1820 SSVAL(p, 0, len);
1821 } else {
1822 memset(p,'\0',26);
1824 p += 2 + 24;
1825 len = srvstr_push(base_data, flags2, p,
1826 fname, PTR_DIFF(end_data, p),
1827 STR_TERMINATE_ASCII);
1828 SIVAL(q,0,len);
1829 p += len;
1831 len = PTR_DIFF(p, pdata);
1832 pad = (len + (align-1)) & ~(align-1);
1834 * offset to the next entry, the caller
1835 * will overwrite it for the last entry
1836 * that's why we always include the padding
1838 SIVAL(pdata,0,pad);
1840 * set padding to zero
1842 if (do_pad) {
1843 memset(p, 0, pad - len);
1844 p = pdata + pad;
1845 } else {
1846 p = pdata + len;
1848 break;
1850 case SMB_FIND_FILE_DIRECTORY_INFO:
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1852 p += 4;
1853 SIVAL(p,0,reskey); p += 4;
1854 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1858 SOFF_T(p,0,file_size); p += 8;
1859 SOFF_T(p,0,allocation_size); p += 8;
1860 SIVAL(p,0,mode); p += 4;
1861 len = srvstr_push(base_data, flags2,
1862 p + 4, fname, PTR_DIFF(end_data, p+4),
1863 STR_TERMINATE_ASCII);
1864 SIVAL(p,0,len);
1865 p += 4 + len;
1867 len = PTR_DIFF(p, pdata);
1868 pad = (len + (align-1)) & ~(align-1);
1870 * offset to the next entry, the caller
1871 * will overwrite it for the last entry
1872 * that's why we always include the padding
1874 SIVAL(pdata,0,pad);
1876 * set padding to zero
1878 if (do_pad) {
1879 memset(p, 0, pad - len);
1880 p = pdata + pad;
1881 } else {
1882 p = pdata + len;
1884 break;
1886 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1887 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1888 p += 4;
1889 SIVAL(p,0,reskey); p += 4;
1890 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1891 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1892 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1893 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1894 SOFF_T(p,0,file_size); p += 8;
1895 SOFF_T(p,0,allocation_size); p += 8;
1896 SIVAL(p,0,mode); p += 4;
1897 q = p; p += 4; /* q is placeholder for name length. */
1899 unsigned int ea_size = estimate_ea_size(conn, NULL,
1900 smb_fname);
1901 SIVAL(p,0,ea_size); /* Extended attributes */
1902 p +=4;
1904 len = srvstr_push(base_data, flags2, p,
1905 fname, PTR_DIFF(end_data, p),
1906 STR_TERMINATE_ASCII);
1907 SIVAL(q, 0, len);
1908 p += len;
1910 len = PTR_DIFF(p, pdata);
1911 pad = (len + (align-1)) & ~(align-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1917 SIVAL(pdata,0,pad);
1919 * set padding to zero
1921 if (do_pad) {
1922 memset(p, 0, pad - len);
1923 p = pdata + pad;
1924 } else {
1925 p = pdata + len;
1927 break;
1929 case SMB_FIND_FILE_NAMES_INFO:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1931 p += 4;
1932 SIVAL(p,0,reskey); p += 4;
1933 p += 4;
1934 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1935 acl on a dir (tridge) */
1936 len = srvstr_push(base_data, flags2, p,
1937 fname, PTR_DIFF(end_data, p),
1938 STR_TERMINATE_ASCII);
1939 SIVAL(p, -4, len);
1940 p += len;
1942 len = PTR_DIFF(p, pdata);
1943 pad = (len + (align-1)) & ~(align-1);
1945 * offset to the next entry, the caller
1946 * will overwrite it for the last entry
1947 * that's why we always include the padding
1949 SIVAL(pdata,0,pad);
1951 * set padding to zero
1953 if (do_pad) {
1954 memset(p, 0, pad - len);
1955 p = pdata + pad;
1956 } else {
1957 p = pdata + len;
1959 break;
1961 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1962 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1963 p += 4;
1964 SIVAL(p,0,reskey); p += 4;
1965 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1966 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1967 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1968 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1969 SOFF_T(p,0,file_size); p += 8;
1970 SOFF_T(p,0,allocation_size); p += 8;
1971 SIVAL(p,0,mode); p += 4;
1972 q = p; p += 4; /* q is placeholder for name length. */
1974 unsigned int ea_size = estimate_ea_size(conn, NULL,
1975 smb_fname);
1976 SIVAL(p,0,ea_size); /* Extended attributes */
1977 p +=4;
1979 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1980 SBVAL(p,0,file_index); p += 8;
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE_ASCII);
1984 SIVAL(q, 0, len);
1985 p += len;
1987 len = PTR_DIFF(p, pdata);
1988 pad = (len + (align-1)) & ~(align-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1994 SIVAL(pdata,0,pad);
1996 * set padding to zero
1998 if (do_pad) {
1999 memset(p, 0, pad - len);
2000 p = pdata + pad;
2001 } else {
2002 p = pdata + len;
2004 break;
2006 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2008 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2009 p += 4;
2010 SIVAL(p,0,reskey); p += 4;
2011 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2012 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2013 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2014 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2015 SOFF_T(p,0,file_size); p += 8;
2016 SOFF_T(p,0,allocation_size); p += 8;
2017 SIVAL(p,0,mode); p += 4;
2018 q = p; p += 4; /* q is placeholder for name length */
2020 unsigned int ea_size = estimate_ea_size(conn, NULL,
2021 smb_fname);
2022 SIVAL(p,0,ea_size); /* Extended attributes */
2023 p +=4;
2025 /* Clear the short name buffer. This is
2026 * IMPORTANT as not doing so will trigger
2027 * a Win2k client bug. JRA.
2029 if (!was_8_3 && check_mangled_names) {
2030 char mangled_name[13]; /* mangled 8.3 name. */
2031 if (!name_to_8_3(fname,mangled_name,True,
2032 conn->params)) {
2033 /* Error - mangle failed ! */
2034 memset(mangled_name,'\0',12);
2036 mangled_name[12] = 0;
2037 len = srvstr_push(base_data, flags2,
2038 p+2, mangled_name, 24,
2039 STR_UPPER|STR_UNICODE);
2040 SSVAL(p, 0, len);
2041 if (len < 24) {
2042 memset(p + 2 + len,'\0',24 - len);
2044 SSVAL(p, 0, len);
2045 } else {
2046 memset(p,'\0',26);
2048 p += 26;
2049 SSVAL(p,0,0); p += 2; /* Reserved ? */
2050 SBVAL(p,0,file_index); p += 8;
2051 len = srvstr_push(base_data, flags2, p,
2052 fname, PTR_DIFF(end_data, p),
2053 STR_TERMINATE_ASCII);
2054 SIVAL(q,0,len);
2055 p += len;
2057 len = PTR_DIFF(p, pdata);
2058 pad = (len + (align-1)) & ~(align-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2064 SIVAL(pdata,0,pad);
2066 * set padding to zero
2068 if (do_pad) {
2069 memset(p, 0, pad - len);
2070 p = pdata + pad;
2071 } else {
2072 p = pdata + len;
2074 break;
2076 /* CIFS UNIX Extension. */
2078 case SMB_FIND_FILE_UNIX:
2079 case SMB_FIND_FILE_UNIX_INFO2:
2080 p+= 4;
2081 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2083 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2085 if (info_level == SMB_FIND_FILE_UNIX) {
2086 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2087 p = store_file_unix_basic(conn, p,
2088 NULL, &smb_fname->st);
2089 len = srvstr_push(base_data, flags2, p,
2090 fname, PTR_DIFF(end_data, p),
2091 STR_TERMINATE);
2092 } else {
2093 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2094 p = store_file_unix_basic_info2(conn, p,
2095 NULL, &smb_fname->st);
2096 nameptr = p;
2097 p += 4;
2098 len = srvstr_push(base_data, flags2, p, fname,
2099 PTR_DIFF(end_data, p), 0);
2100 SIVAL(nameptr, 0, len);
2103 p += len;
2105 len = PTR_DIFF(p, pdata);
2106 pad = (len + (align-1)) & ~(align-1);
2108 * offset to the next entry, the caller
2109 * will overwrite it for the last entry
2110 * that's why we always include the padding
2112 SIVAL(pdata,0,pad);
2114 * set padding to zero
2116 if (do_pad) {
2117 memset(p, 0, pad - len);
2118 p = pdata + pad;
2119 } else {
2120 p = pdata + len;
2122 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2124 break;
2126 default:
2127 return false;
2130 if (PTR_DIFF(p,pdata) > space_remaining) {
2131 *out_of_space = true;
2132 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2133 "(wanted %u, had %d)\n",
2134 (unsigned int)PTR_DIFF(p,pdata),
2135 space_remaining ));
2136 return false; /* Not finished - just out of space */
2139 /* Setup the last entry pointer, as an offset from base_data */
2140 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2141 /* Advance the data pointer to the next slot */
2142 *ppdata = p;
2144 return true;
2147 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2148 connection_struct *conn,
2149 struct dptr_struct *dirptr,
2150 uint16 flags2,
2151 const char *path_mask,
2152 uint32 dirtype,
2153 int info_level,
2154 int requires_resume_key,
2155 bool dont_descend,
2156 bool ask_sharemode,
2157 uint8_t align,
2158 bool do_pad,
2159 char **ppdata,
2160 char *base_data,
2161 char *end_data,
2162 int space_remaining,
2163 bool *out_of_space,
2164 bool *got_exact_match,
2165 int *_last_entry_off,
2166 struct ea_list *name_list)
2168 const char *p;
2169 const char *mask = NULL;
2170 long prev_dirpos = 0;
2171 uint32_t mode = 0;
2172 char *fname = NULL;
2173 struct smb_filename *smb_fname = NULL;
2174 struct smbd_dirptr_lanman2_state state;
2175 bool ok;
2176 uint64_t last_entry_off = 0;
2178 ZERO_STRUCT(state);
2179 state.conn = conn;
2180 state.info_level = info_level;
2181 state.check_mangled_names = lp_manglednames(conn->params);
2182 state.has_wild = dptr_has_wild(dirptr);
2183 state.got_exact_match = false;
2185 *out_of_space = false;
2186 *got_exact_match = false;
2188 p = strrchr_m(path_mask,'/');
2189 if(p != NULL) {
2190 if(p[1] == '\0') {
2191 mask = "*.*";
2192 } else {
2193 mask = p+1;
2195 } else {
2196 mask = path_mask;
2199 ok = smbd_dirptr_get_entry(ctx,
2200 dirptr,
2201 mask,
2202 dirtype,
2203 dont_descend,
2204 ask_sharemode,
2205 smbd_dirptr_lanman2_match_fn,
2206 smbd_dirptr_lanman2_mode_fn,
2207 &state,
2208 &fname,
2209 &smb_fname,
2210 &mode,
2211 &prev_dirpos);
2212 if (!ok) {
2213 return false;
2216 *got_exact_match = state.got_exact_match;
2218 ok = smbd_marshall_dir_entry(ctx,
2219 conn,
2220 flags2,
2221 info_level,
2222 name_list,
2223 state.check_mangled_names,
2224 requires_resume_key,
2225 mode,
2226 fname,
2227 smb_fname,
2228 space_remaining,
2229 align,
2230 do_pad,
2231 base_data,
2232 ppdata,
2233 end_data,
2234 out_of_space,
2235 &last_entry_off);
2236 TALLOC_FREE(fname);
2237 TALLOC_FREE(smb_fname);
2238 if (*out_of_space) {
2239 dptr_SeekDir(dirptr, prev_dirpos);
2240 return false;
2242 if (!ok) {
2243 return false;
2246 *_last_entry_off = last_entry_off;
2247 return true;
2250 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2251 connection_struct *conn,
2252 struct dptr_struct *dirptr,
2253 uint16 flags2,
2254 const char *path_mask,
2255 uint32 dirtype,
2256 int info_level,
2257 bool requires_resume_key,
2258 bool dont_descend,
2259 bool ask_sharemode,
2260 char **ppdata,
2261 char *base_data,
2262 char *end_data,
2263 int space_remaining,
2264 bool *out_of_space,
2265 bool *got_exact_match,
2266 int *last_entry_off,
2267 struct ea_list *name_list)
2269 uint8_t align = 4;
2270 const bool do_pad = true;
2272 if (info_level >= 1 && info_level <= 3) {
2273 /* No alignment on earlier info levels. */
2274 align = 1;
2277 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2278 path_mask, dirtype, info_level,
2279 requires_resume_key, dont_descend, ask_sharemode,
2280 align, do_pad,
2281 ppdata, base_data, end_data,
2282 space_remaining,
2283 out_of_space, got_exact_match,
2284 last_entry_off, name_list);
2287 /****************************************************************************
2288 Reply to a TRANS2_FINDFIRST.
2289 ****************************************************************************/
2291 static void call_trans2findfirst(connection_struct *conn,
2292 struct smb_request *req,
2293 char **pparams, int total_params,
2294 char **ppdata, int total_data,
2295 unsigned int max_data_bytes)
2297 /* We must be careful here that we don't return more than the
2298 allowed number of data bytes. If this means returning fewer than
2299 maxentries then so be it. We assume that the redirector has
2300 enough room for the fixed number of parameter bytes it has
2301 requested. */
2302 struct smb_filename *smb_dname = NULL;
2303 char *params = *pparams;
2304 char *pdata = *ppdata;
2305 char *data_end;
2306 uint32 dirtype;
2307 int maxentries;
2308 uint16 findfirst_flags;
2309 bool close_after_first;
2310 bool close_if_end;
2311 bool requires_resume_key;
2312 int info_level;
2313 char *directory = NULL;
2314 char *mask = NULL;
2315 char *p;
2316 int last_entry_off=0;
2317 int dptr_num = -1;
2318 int numentries = 0;
2319 int i;
2320 bool finished = False;
2321 bool dont_descend = False;
2322 bool out_of_space = False;
2323 int space_remaining;
2324 bool mask_contains_wcard = False;
2325 struct ea_list *ea_list = NULL;
2326 NTSTATUS ntstatus = NT_STATUS_OK;
2327 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2328 TALLOC_CTX *ctx = talloc_tos();
2329 struct dptr_struct *dirptr = NULL;
2330 struct smbd_server_connection *sconn = req->sconn;
2331 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2332 bool backup_priv = false;
2334 if (total_params < 13) {
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 goto out;
2339 dirtype = SVAL(params,0);
2340 maxentries = SVAL(params,2);
2341 findfirst_flags = SVAL(params,4);
2342 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2343 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2344 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2345 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2346 security_token_has_privilege(get_current_nttok(conn),
2347 SEC_PRIV_BACKUP));
2349 info_level = SVAL(params,6);
2351 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2352 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2353 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2354 (int)backup_priv,
2355 info_level, max_data_bytes));
2357 if (!maxentries) {
2358 /* W2K3 seems to treat zero as 1. */
2359 maxentries = 1;
2362 switch (info_level) {
2363 case SMB_FIND_INFO_STANDARD:
2364 case SMB_FIND_EA_SIZE:
2365 case SMB_FIND_EA_LIST:
2366 case SMB_FIND_FILE_DIRECTORY_INFO:
2367 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2368 case SMB_FIND_FILE_NAMES_INFO:
2369 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2370 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2371 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2372 break;
2373 case SMB_FIND_FILE_UNIX:
2374 case SMB_FIND_FILE_UNIX_INFO2:
2375 /* Always use filesystem for UNIX mtime query. */
2376 ask_sharemode = false;
2377 if (!lp_unix_extensions()) {
2378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2379 goto out;
2381 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2382 break;
2383 default:
2384 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2385 goto out;
2388 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2389 params+12, total_params - 12,
2390 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2391 if (!NT_STATUS_IS_OK(ntstatus)) {
2392 reply_nterror(req, ntstatus);
2393 goto out;
2396 if (backup_priv) {
2397 become_root();
2398 ntstatus = filename_convert_with_privilege(ctx,
2399 conn,
2400 req,
2401 directory,
2402 ucf_flags,
2403 &mask_contains_wcard,
2404 &smb_dname);
2405 } else {
2406 ntstatus = filename_convert(ctx, conn,
2407 req->flags2 & FLAGS2_DFS_PATHNAMES,
2408 directory,
2409 ucf_flags,
2410 &mask_contains_wcard,
2411 &smb_dname);
2414 if (!NT_STATUS_IS_OK(ntstatus)) {
2415 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2416 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2417 ERRSRV, ERRbadpath);
2418 goto out;
2420 reply_nterror(req, ntstatus);
2421 goto out;
2424 mask = smb_dname->original_lcomp;
2426 directory = smb_dname->base_name;
2428 p = strrchr_m(directory,'/');
2429 if(p == NULL) {
2430 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2431 if((directory[0] == '.') && (directory[1] == '\0')) {
2432 mask = talloc_strdup(ctx,"*");
2433 if (!mask) {
2434 reply_nterror(req, NT_STATUS_NO_MEMORY);
2435 goto out;
2437 mask_contains_wcard = True;
2439 } else {
2440 *p = 0;
2443 if (p == NULL || p == directory) {
2444 /* Ensure we don't have a directory name of "". */
2445 directory = talloc_strdup(talloc_tos(), ".");
2446 if (!directory) {
2447 reply_nterror(req, NT_STATUS_NO_MEMORY);
2448 goto out;
2452 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2454 if (info_level == SMB_FIND_EA_LIST) {
2455 uint32 ea_size;
2457 if (total_data < 4) {
2458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2459 goto out;
2462 ea_size = IVAL(pdata,0);
2463 if (ea_size != total_data) {
2464 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2465 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2467 goto out;
2470 if (!lp_ea_support(SNUM(conn))) {
2471 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2472 goto out;
2475 /* Pull out the list of names. */
2476 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2477 if (!ea_list) {
2478 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2479 goto out;
2483 *ppdata = (char *)SMB_REALLOC(
2484 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2485 if(*ppdata == NULL ) {
2486 reply_nterror(req, NT_STATUS_NO_MEMORY);
2487 goto out;
2489 pdata = *ppdata;
2490 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2492 /* Realloc the params space */
2493 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2494 if (*pparams == NULL) {
2495 reply_nterror(req, NT_STATUS_NO_MEMORY);
2496 goto out;
2498 params = *pparams;
2500 /* Save the wildcard match and attribs we are using on this directory -
2501 needed as lanman2 assumes these are being saved between calls */
2503 ntstatus = dptr_create(conn,
2504 req,
2505 NULL, /* fsp */
2506 directory,
2507 False,
2508 True,
2509 req->smbpid,
2510 mask,
2511 mask_contains_wcard,
2512 dirtype,
2513 &dirptr);
2515 if (!NT_STATUS_IS_OK(ntstatus)) {
2516 reply_nterror(req, ntstatus);
2517 goto out;
2520 if (backup_priv) {
2521 /* Remember this in case we have
2522 to do a findnext. */
2523 dptr_set_priv(dirptr);
2526 dptr_num = dptr_dnum(dirptr);
2527 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2529 /* Initialize per TRANS2_FIND_FIRST operation data */
2530 dptr_init_search_op(dirptr);
2532 /* We don't need to check for VOL here as this is returned by
2533 a different TRANS2 call. */
2535 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2536 directory,lp_dontdescend(ctx, SNUM(conn))));
2537 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2538 dont_descend = True;
2540 p = pdata;
2541 space_remaining = max_data_bytes;
2542 out_of_space = False;
2544 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2545 bool got_exact_match = False;
2547 /* this is a heuristic to avoid seeking the dirptr except when
2548 absolutely necessary. It allows for a filename of about 40 chars */
2549 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2550 out_of_space = True;
2551 finished = False;
2552 } else {
2553 finished = !get_lanman2_dir_entry(ctx,
2554 conn,
2555 dirptr,
2556 req->flags2,
2557 mask,dirtype,info_level,
2558 requires_resume_key,dont_descend,
2559 ask_sharemode,
2560 &p,pdata,data_end,
2561 space_remaining, &out_of_space,
2562 &got_exact_match,
2563 &last_entry_off, ea_list);
2566 if (finished && out_of_space)
2567 finished = False;
2569 if (!finished && !out_of_space)
2570 numentries++;
2573 * As an optimisation if we know we aren't looking
2574 * for a wildcard name (ie. the name matches the wildcard exactly)
2575 * then we can finish on any (first) match.
2576 * This speeds up large directory searches. JRA.
2579 if(got_exact_match)
2580 finished = True;
2582 /* Ensure space_remaining never goes -ve. */
2583 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2584 space_remaining = 0;
2585 out_of_space = true;
2586 } else {
2587 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2591 /* Check if we can close the dirptr */
2592 if(close_after_first || (finished && close_if_end)) {
2593 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2594 dptr_close(sconn, &dptr_num);
2598 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2599 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2600 * the protocol level is less than NT1. Tested with smbclient. JRA.
2601 * This should fix the OS/2 client bug #2335.
2604 if(numentries == 0) {
2605 dptr_close(sconn, &dptr_num);
2606 if (get_Protocol() < PROTOCOL_NT1) {
2607 reply_force_doserror(req, ERRDOS, ERRnofiles);
2608 goto out;
2609 } else {
2610 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2611 ERRDOS, ERRbadfile);
2612 goto out;
2616 /* At this point pdata points to numentries directory entries. */
2618 /* Set up the return parameter block */
2619 SSVAL(params,0,dptr_num);
2620 SSVAL(params,2,numentries);
2621 SSVAL(params,4,finished);
2622 SSVAL(params,6,0); /* Never an EA error */
2623 SSVAL(params,8,last_entry_off);
2625 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2626 max_data_bytes);
2628 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2629 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2630 if (!directory) {
2631 reply_nterror(req, NT_STATUS_NO_MEMORY);
2635 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2636 smb_fn_name(req->cmd),
2637 mask, directory, dirtype, numentries ) );
2640 * Force a name mangle here to ensure that the
2641 * mask as an 8.3 name is top of the mangled cache.
2642 * The reasons for this are subtle. Don't remove
2643 * this code unless you know what you are doing
2644 * (see PR#13758). JRA.
2647 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2648 char mangled_name[13];
2649 name_to_8_3(mask, mangled_name, True, conn->params);
2651 out:
2653 if (backup_priv) {
2654 unbecome_root();
2657 TALLOC_FREE(smb_dname);
2658 return;
2661 /****************************************************************************
2662 Reply to a TRANS2_FINDNEXT.
2663 ****************************************************************************/
2665 static void call_trans2findnext(connection_struct *conn,
2666 struct smb_request *req,
2667 char **pparams, int total_params,
2668 char **ppdata, int total_data,
2669 unsigned int max_data_bytes)
2671 /* We must be careful here that we don't return more than the
2672 allowed number of data bytes. If this means returning fewer than
2673 maxentries then so be it. We assume that the redirector has
2674 enough room for the fixed number of parameter bytes it has
2675 requested. */
2676 char *params = *pparams;
2677 char *pdata = *ppdata;
2678 char *data_end;
2679 int dptr_num;
2680 int maxentries;
2681 uint16 info_level;
2682 uint32 resume_key;
2683 uint16 findnext_flags;
2684 bool close_after_request;
2685 bool close_if_end;
2686 bool requires_resume_key;
2687 bool continue_bit;
2688 bool mask_contains_wcard = False;
2689 char *resume_name = NULL;
2690 const char *mask = NULL;
2691 const char *directory = NULL;
2692 char *p = NULL;
2693 uint16 dirtype;
2694 int numentries = 0;
2695 int i, last_entry_off=0;
2696 bool finished = False;
2697 bool dont_descend = False;
2698 bool out_of_space = False;
2699 int space_remaining;
2700 struct ea_list *ea_list = NULL;
2701 NTSTATUS ntstatus = NT_STATUS_OK;
2702 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2703 TALLOC_CTX *ctx = talloc_tos();
2704 struct dptr_struct *dirptr;
2705 struct smbd_server_connection *sconn = req->sconn;
2706 bool backup_priv = false;
2708 if (total_params < 13) {
2709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2710 return;
2713 dptr_num = SVAL(params,0);
2714 maxentries = SVAL(params,2);
2715 info_level = SVAL(params,4);
2716 resume_key = IVAL(params,6);
2717 findnext_flags = SVAL(params,10);
2718 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2719 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2720 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2721 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2723 if (!continue_bit) {
2724 /* We only need resume_name if continue_bit is zero. */
2725 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2726 params+12,
2727 total_params - 12, STR_TERMINATE, &ntstatus,
2728 &mask_contains_wcard);
2729 if (!NT_STATUS_IS_OK(ntstatus)) {
2730 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2731 complain (it thinks we're asking for the directory above the shared
2732 path or an invalid name). Catch this as the resume name is only compared, never used in
2733 a file access. JRA. */
2734 srvstr_pull_talloc(ctx, params, req->flags2,
2735 &resume_name, params+12,
2736 total_params - 12,
2737 STR_TERMINATE);
2739 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2740 reply_nterror(req, ntstatus);
2741 return;
2746 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2747 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2748 resume_key = %d resume name = %s continue=%d level = %d\n",
2749 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2750 requires_resume_key, resume_key,
2751 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2753 if (!maxentries) {
2754 /* W2K3 seems to treat zero as 1. */
2755 maxentries = 1;
2758 switch (info_level) {
2759 case SMB_FIND_INFO_STANDARD:
2760 case SMB_FIND_EA_SIZE:
2761 case SMB_FIND_EA_LIST:
2762 case SMB_FIND_FILE_DIRECTORY_INFO:
2763 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2764 case SMB_FIND_FILE_NAMES_INFO:
2765 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2766 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2767 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2768 break;
2769 case SMB_FIND_FILE_UNIX:
2770 case SMB_FIND_FILE_UNIX_INFO2:
2771 /* Always use filesystem for UNIX mtime query. */
2772 ask_sharemode = false;
2773 if (!lp_unix_extensions()) {
2774 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2775 return;
2777 break;
2778 default:
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 return;
2783 if (info_level == SMB_FIND_EA_LIST) {
2784 uint32 ea_size;
2786 if (total_data < 4) {
2787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2788 return;
2791 ea_size = IVAL(pdata,0);
2792 if (ea_size != total_data) {
2793 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2794 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2796 return;
2799 if (!lp_ea_support(SNUM(conn))) {
2800 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2801 return;
2804 /* Pull out the list of names. */
2805 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2806 if (!ea_list) {
2807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2808 return;
2812 *ppdata = (char *)SMB_REALLOC(
2813 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2814 if(*ppdata == NULL) {
2815 reply_nterror(req, NT_STATUS_NO_MEMORY);
2816 return;
2819 pdata = *ppdata;
2820 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2822 /* Realloc the params space */
2823 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2824 if(*pparams == NULL ) {
2825 reply_nterror(req, NT_STATUS_NO_MEMORY);
2826 return;
2829 params = *pparams;
2831 /* Check that the dptr is valid */
2832 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2833 reply_nterror(req, STATUS_NO_MORE_FILES);
2834 return;
2837 directory = dptr_path(sconn, dptr_num);
2839 /* Get the wildcard mask from the dptr */
2840 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2841 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2842 reply_nterror(req, STATUS_NO_MORE_FILES);
2843 return;
2846 /* Get the attr mask from the dptr */
2847 dirtype = dptr_attr(sconn, dptr_num);
2849 backup_priv = dptr_get_priv(dirptr);
2851 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2852 "backup_priv = %d\n",
2853 dptr_num, mask, dirtype,
2854 (long)dirptr,
2855 dptr_TellDir(dirptr),
2856 (int)backup_priv));
2858 /* Initialize per TRANS2_FIND_NEXT operation data */
2859 dptr_init_search_op(dirptr);
2861 /* We don't need to check for VOL here as this is returned by
2862 a different TRANS2 call. */
2864 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2865 directory,lp_dontdescend(ctx, SNUM(conn))));
2866 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2867 dont_descend = True;
2869 p = pdata;
2870 space_remaining = max_data_bytes;
2871 out_of_space = False;
2873 if (backup_priv) {
2874 become_root();
2878 * Seek to the correct position. We no longer use the resume key but
2879 * depend on the last file name instead.
2882 if(!continue_bit && resume_name && *resume_name) {
2883 SMB_STRUCT_STAT st;
2885 long current_pos = 0;
2887 * Remember, name_to_8_3 is called by
2888 * get_lanman2_dir_entry(), so the resume name
2889 * could be mangled. Ensure we check the unmangled name.
2892 if (mangle_is_mangled(resume_name, conn->params)) {
2893 char *new_resume_name = NULL;
2894 mangle_lookup_name_from_8_3(ctx,
2895 resume_name,
2896 &new_resume_name,
2897 conn->params);
2898 if (new_resume_name) {
2899 resume_name = new_resume_name;
2904 * Fix for NT redirector problem triggered by resume key indexes
2905 * changing between directory scans. We now return a resume key of 0
2906 * and instead look for the filename to continue from (also given
2907 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2908 * findfirst/findnext (as is usual) then the directory pointer
2909 * should already be at the correct place.
2912 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2913 } /* end if resume_name && !continue_bit */
2915 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2916 bool got_exact_match = False;
2918 /* this is a heuristic to avoid seeking the dirptr except when
2919 absolutely necessary. It allows for a filename of about 40 chars */
2920 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2921 out_of_space = True;
2922 finished = False;
2923 } else {
2924 finished = !get_lanman2_dir_entry(ctx,
2925 conn,
2926 dirptr,
2927 req->flags2,
2928 mask,dirtype,info_level,
2929 requires_resume_key,dont_descend,
2930 ask_sharemode,
2931 &p,pdata,data_end,
2932 space_remaining, &out_of_space,
2933 &got_exact_match,
2934 &last_entry_off, ea_list);
2937 if (finished && out_of_space)
2938 finished = False;
2940 if (!finished && !out_of_space)
2941 numentries++;
2944 * As an optimisation if we know we aren't looking
2945 * for a wildcard name (ie. the name matches the wildcard exactly)
2946 * then we can finish on any (first) match.
2947 * This speeds up large directory searches. JRA.
2950 if(got_exact_match)
2951 finished = True;
2953 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2956 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2957 smb_fn_name(req->cmd),
2958 mask, directory, dirtype, numentries ) );
2960 /* Check if we can close the dirptr */
2961 if(close_after_request || (finished && close_if_end)) {
2962 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2963 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2966 if (backup_priv) {
2967 unbecome_root();
2970 /* Set up the return parameter block */
2971 SSVAL(params,0,numentries);
2972 SSVAL(params,2,finished);
2973 SSVAL(params,4,0); /* Never an EA error */
2974 SSVAL(params,6,last_entry_off);
2976 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2977 max_data_bytes);
2979 return;
2982 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2984 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2985 return objid;
2988 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2990 SMB_ASSERT(extended_info != NULL);
2992 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2993 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2994 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2995 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2996 #ifdef SAMBA_VERSION_REVISION
2997 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2998 #endif
2999 extended_info->samba_subversion = 0;
3000 #ifdef SAMBA_VERSION_RC_RELEASE
3001 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3002 #else
3003 #ifdef SAMBA_VERSION_PRE_RELEASE
3004 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3005 #endif
3006 #endif
3007 #ifdef SAMBA_VERSION_VENDOR_PATCH
3008 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3009 #endif
3010 extended_info->samba_gitcommitdate = 0;
3011 #ifdef SAMBA_VERSION_COMMIT_TIME
3012 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3013 #endif
3015 memset(extended_info->samba_version_string, 0,
3016 sizeof(extended_info->samba_version_string));
3018 snprintf (extended_info->samba_version_string,
3019 sizeof(extended_info->samba_version_string),
3020 "%s", samba_version_string());
3023 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3024 TALLOC_CTX *mem_ctx,
3025 uint16_t info_level,
3026 uint16_t flags2,
3027 unsigned int max_data_bytes,
3028 struct smb_filename *fname,
3029 char **ppdata,
3030 int *ret_data_len)
3032 char *pdata, *end_data;
3033 int data_len = 0, len;
3034 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3035 int snum = SNUM(conn);
3036 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3037 char *filename = NULL;
3038 uint32 additional_flags = 0;
3039 struct smb_filename smb_fname;
3040 SMB_STRUCT_STAT st;
3042 if (fname == NULL || fname->base_name == NULL) {
3043 filename = ".";
3044 } else {
3045 filename = fname->base_name;
3048 if (IS_IPC(conn)) {
3049 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3050 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3051 "info level (0x%x) on IPC$.\n",
3052 (unsigned int)info_level));
3053 return NT_STATUS_ACCESS_DENIED;
3057 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3059 ZERO_STRUCT(smb_fname);
3060 smb_fname.base_name = discard_const_p(char, filename);
3062 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3063 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3064 return map_nt_error_from_unix(errno);
3067 st = smb_fname.st;
3069 *ppdata = (char *)SMB_REALLOC(
3070 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3071 if (*ppdata == NULL) {
3072 return NT_STATUS_NO_MEMORY;
3075 pdata = *ppdata;
3076 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3077 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3079 switch (info_level) {
3080 case SMB_INFO_ALLOCATION:
3082 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3083 data_len = 18;
3084 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno);
3088 block_size = lp_block_size(snum);
3089 if (bsize < block_size) {
3090 uint64_t factor = block_size/bsize;
3091 bsize = block_size;
3092 dsize /= factor;
3093 dfree /= factor;
3095 if (bsize > block_size) {
3096 uint64_t factor = bsize/block_size;
3097 bsize = block_size;
3098 dsize *= factor;
3099 dfree *= factor;
3101 bytes_per_sector = 512;
3102 sectors_per_unit = bsize/bytes_per_sector;
3104 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3105 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3106 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3108 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3109 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3110 SIVAL(pdata,l1_cUnit,dsize);
3111 SIVAL(pdata,l1_cUnitAvail,dfree);
3112 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3113 break;
3116 case SMB_INFO_VOLUME:
3117 /* Return volume name */
3119 * Add volume serial number - hash of a combination of
3120 * the called hostname and the service name.
3122 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3124 * Win2k3 and previous mess this up by sending a name length
3125 * one byte short. I believe only older clients (OS/2 Win9x) use
3126 * this call so try fixing this by adding a terminating null to
3127 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3129 len = srvstr_push(
3130 pdata, flags2,
3131 pdata+l2_vol_szVolLabel, vname,
3132 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3133 STR_NOALIGN|STR_TERMINATE);
3134 SCVAL(pdata,l2_vol_cch,len);
3135 data_len = l2_vol_szVolLabel + len;
3136 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3137 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3138 len, vname));
3139 break;
3141 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3142 case SMB_FS_ATTRIBUTE_INFORMATION:
3144 additional_flags = 0;
3145 #if defined(HAVE_SYS_QUOTAS)
3146 additional_flags |= FILE_VOLUME_QUOTAS;
3147 #endif
3149 if(lp_nt_acl_support(SNUM(conn))) {
3150 additional_flags |= FILE_PERSISTENT_ACLS;
3153 /* Capabilities are filled in at connection time through STATVFS call */
3154 additional_flags |= conn->fs_capabilities;
3155 additional_flags |= lp_parm_int(conn->params->service,
3156 "share", "fake_fscaps",
3159 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3160 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3161 additional_flags); /* FS ATTRIBUTES */
3163 SIVAL(pdata,4,255); /* Max filename component length */
3164 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3165 and will think we can't do long filenames */
3166 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3167 PTR_DIFF(end_data, pdata+12),
3168 STR_UNICODE);
3169 SIVAL(pdata,8,len);
3170 data_len = 12 + len;
3171 break;
3173 case SMB_QUERY_FS_LABEL_INFO:
3174 case SMB_FS_LABEL_INFORMATION:
3175 len = srvstr_push(pdata, flags2, pdata+4, vname,
3176 PTR_DIFF(end_data, pdata+4), 0);
3177 data_len = 4 + len;
3178 SIVAL(pdata,0,len);
3179 break;
3181 case SMB_QUERY_FS_VOLUME_INFO:
3182 case SMB_FS_VOLUME_INFORMATION:
3185 * Add volume serial number - hash of a combination of
3186 * the called hostname and the service name.
3188 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3189 (str_checksum(get_local_machine_name())<<16));
3191 /* Max label len is 32 characters. */
3192 len = srvstr_push(pdata, flags2, pdata+18, vname,
3193 PTR_DIFF(end_data, pdata+18),
3194 STR_UNICODE);
3195 SIVAL(pdata,12,len);
3196 data_len = 18+len;
3198 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3199 (int)strlen(vname),vname,
3200 lp_servicename(talloc_tos(), snum)));
3201 break;
3203 case SMB_QUERY_FS_SIZE_INFO:
3204 case SMB_FS_SIZE_INFORMATION:
3206 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3207 data_len = 24;
3208 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3209 return map_nt_error_from_unix(errno);
3211 block_size = lp_block_size(snum);
3212 if (bsize < block_size) {
3213 uint64_t factor = block_size/bsize;
3214 bsize = block_size;
3215 dsize /= factor;
3216 dfree /= factor;
3218 if (bsize > block_size) {
3219 uint64_t factor = bsize/block_size;
3220 bsize = block_size;
3221 dsize *= factor;
3222 dfree *= factor;
3224 bytes_per_sector = 512;
3225 sectors_per_unit = bsize/bytes_per_sector;
3226 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3227 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3228 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3229 SBIG_UINT(pdata,0,dsize);
3230 SBIG_UINT(pdata,8,dfree);
3231 SIVAL(pdata,16,sectors_per_unit);
3232 SIVAL(pdata,20,bytes_per_sector);
3233 break;
3236 case SMB_FS_FULL_SIZE_INFORMATION:
3238 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3239 data_len = 32;
3240 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3241 return map_nt_error_from_unix(errno);
3243 block_size = lp_block_size(snum);
3244 if (bsize < block_size) {
3245 uint64_t factor = block_size/bsize;
3246 bsize = block_size;
3247 dsize /= factor;
3248 dfree /= factor;
3250 if (bsize > block_size) {
3251 uint64_t factor = bsize/block_size;
3252 bsize = block_size;
3253 dsize *= factor;
3254 dfree *= factor;
3256 bytes_per_sector = 512;
3257 sectors_per_unit = bsize/bytes_per_sector;
3258 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3259 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3260 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3261 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3262 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3263 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3264 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3265 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3266 break;
3269 case SMB_QUERY_FS_DEVICE_INFO:
3270 case SMB_FS_DEVICE_INFORMATION:
3272 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3274 if (!CAN_WRITE(conn)) {
3275 characteristics |= FILE_READ_ONLY_DEVICE;
3277 data_len = 8;
3278 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3279 SIVAL(pdata,4,characteristics);
3280 break;
3283 #ifdef HAVE_SYS_QUOTAS
3284 case SMB_FS_QUOTA_INFORMATION:
3286 * what we have to send --metze:
3288 * Unknown1: 24 NULL bytes
3289 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3290 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3291 * Quota Flags: 2 byte :
3292 * Unknown3: 6 NULL bytes
3294 * 48 bytes total
3296 * details for Quota Flags:
3298 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3299 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3300 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3301 * 0x0001 Enable Quotas: enable quota for this fs
3305 /* we need to fake up a fsp here,
3306 * because its not send in this call
3308 files_struct fsp;
3309 SMB_NTQUOTA_STRUCT quotas;
3311 ZERO_STRUCT(fsp);
3312 ZERO_STRUCT(quotas);
3314 fsp.conn = conn;
3315 fsp.fnum = FNUM_FIELD_INVALID;
3317 /* access check */
3318 if (get_current_uid(conn) != 0) {
3319 DEBUG(0,("set_user_quota: access_denied "
3320 "service [%s] user [%s]\n",
3321 lp_servicename(talloc_tos(), SNUM(conn)),
3322 conn->session_info->unix_info->unix_name));
3323 return NT_STATUS_ACCESS_DENIED;
3326 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3327 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3328 return map_nt_error_from_unix(errno);
3331 data_len = 48;
3333 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3334 lp_servicename(talloc_tos(), SNUM(conn))));
3336 /* Unknown1 24 NULL bytes*/
3337 SBIG_UINT(pdata,0,(uint64_t)0);
3338 SBIG_UINT(pdata,8,(uint64_t)0);
3339 SBIG_UINT(pdata,16,(uint64_t)0);
3341 /* Default Soft Quota 8 bytes */
3342 SBIG_UINT(pdata,24,quotas.softlim);
3344 /* Default Hard Quota 8 bytes */
3345 SBIG_UINT(pdata,32,quotas.hardlim);
3347 /* Quota flag 2 bytes */
3348 SSVAL(pdata,40,quotas.qflags);
3350 /* Unknown3 6 NULL bytes */
3351 SSVAL(pdata,42,0);
3352 SIVAL(pdata,44,0);
3354 break;
3356 #endif /* HAVE_SYS_QUOTAS */
3357 case SMB_FS_OBJECTID_INFORMATION:
3359 unsigned char objid[16];
3360 struct smb_extended_info extended_info;
3361 memcpy(pdata,create_volume_objectid(conn, objid),16);
3362 samba_extended_info_version (&extended_info);
3363 SIVAL(pdata,16,extended_info.samba_magic);
3364 SIVAL(pdata,20,extended_info.samba_version);
3365 SIVAL(pdata,24,extended_info.samba_subversion);
3366 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3367 memcpy(pdata+36,extended_info.samba_version_string,28);
3368 data_len = 64;
3369 break;
3373 * Query the version and capabilities of the CIFS UNIX extensions
3374 * in use.
3377 case SMB_QUERY_CIFS_UNIX_INFO:
3379 bool large_write = lp_min_receive_file_size() &&
3380 !srv_is_signing_active(conn->sconn);
3381 bool large_read = !srv_is_signing_active(conn->sconn);
3382 int encrypt_caps = 0;
3384 if (!lp_unix_extensions()) {
3385 return NT_STATUS_INVALID_LEVEL;
3388 switch (conn->encrypt_level) {
3389 case SMB_SIGNING_OFF:
3390 encrypt_caps = 0;
3391 break;
3392 case SMB_SIGNING_IF_REQUIRED:
3393 case SMB_SIGNING_DEFAULT:
3394 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3395 break;
3396 case SMB_SIGNING_REQUIRED:
3397 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3398 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3399 large_write = false;
3400 large_read = false;
3401 break;
3404 data_len = 12;
3405 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3406 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3408 /* We have POSIX ACLs, pathname, encryption,
3409 * large read/write, and locking capability. */
3411 SBIG_UINT(pdata,4,((uint64_t)(
3412 CIFS_UNIX_POSIX_ACLS_CAP|
3413 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3414 CIFS_UNIX_FCNTL_LOCKS_CAP|
3415 CIFS_UNIX_EXTATTR_CAP|
3416 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3417 encrypt_caps|
3418 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3419 (large_write ?
3420 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3421 break;
3424 case SMB_QUERY_POSIX_FS_INFO:
3426 int rc;
3427 vfs_statvfs_struct svfs;
3429 if (!lp_unix_extensions()) {
3430 return NT_STATUS_INVALID_LEVEL;
3433 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3435 if (!rc) {
3436 data_len = 56;
3437 SIVAL(pdata,0,svfs.OptimalTransferSize);
3438 SIVAL(pdata,4,svfs.BlockSize);
3439 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3440 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3441 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3442 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3443 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3444 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3445 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3446 #ifdef EOPNOTSUPP
3447 } else if (rc == EOPNOTSUPP) {
3448 return NT_STATUS_INVALID_LEVEL;
3449 #endif /* EOPNOTSUPP */
3450 } else {
3451 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3452 return NT_STATUS_DOS(ERRSRV, ERRerror);
3454 break;
3457 case SMB_QUERY_POSIX_WHOAMI:
3459 uint32_t flags = 0;
3460 uint32_t sid_bytes;
3461 int i;
3463 if (!lp_unix_extensions()) {
3464 return NT_STATUS_INVALID_LEVEL;
3467 if (max_data_bytes < 40) {
3468 return NT_STATUS_BUFFER_TOO_SMALL;
3471 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3472 flags |= SMB_WHOAMI_GUEST;
3475 /* NOTE: 8 bytes for UID/GID, irrespective of native
3476 * platform size. This matches
3477 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3479 data_len = 4 /* flags */
3480 + 4 /* flag mask */
3481 + 8 /* uid */
3482 + 8 /* gid */
3483 + 4 /* ngroups */
3484 + 4 /* num_sids */
3485 + 4 /* SID bytes */
3486 + 4 /* pad/reserved */
3487 + (conn->session_info->unix_token->ngroups * 8)
3488 /* groups list */
3489 + (conn->session_info->security_token->num_sids *
3490 SID_MAX_SIZE)
3491 /* SID list */;
3493 SIVAL(pdata, 0, flags);
3494 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3495 SBIG_UINT(pdata, 8,
3496 (uint64_t)conn->session_info->unix_token->uid);
3497 SBIG_UINT(pdata, 16,
3498 (uint64_t)conn->session_info->unix_token->gid);
3501 if (data_len >= max_data_bytes) {
3502 /* Potential overflow, skip the GIDs and SIDs. */
3504 SIVAL(pdata, 24, 0); /* num_groups */
3505 SIVAL(pdata, 28, 0); /* num_sids */
3506 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3507 SIVAL(pdata, 36, 0); /* reserved */
3509 data_len = 40;
3510 break;
3513 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3514 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3516 /* We walk the SID list twice, but this call is fairly
3517 * infrequent, and I don't expect that it's performance
3518 * sensitive -- jpeach
3520 for (i = 0, sid_bytes = 0;
3521 i < conn->session_info->security_token->num_sids; ++i) {
3522 sid_bytes += ndr_size_dom_sid(
3523 &conn->session_info->security_token->sids[i],
3527 /* SID list byte count */
3528 SIVAL(pdata, 32, sid_bytes);
3530 /* 4 bytes pad/reserved - must be zero */
3531 SIVAL(pdata, 36, 0);
3532 data_len = 40;
3534 /* GID list */
3535 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3536 SBIG_UINT(pdata, data_len,
3537 (uint64_t)conn->session_info->unix_token->groups[i]);
3538 data_len += 8;
3541 /* SID list */
3542 for (i = 0;
3543 i < conn->session_info->security_token->num_sids; ++i) {
3544 int sid_len = ndr_size_dom_sid(
3545 &conn->session_info->security_token->sids[i],
3548 sid_linearize(pdata + data_len, sid_len,
3549 &conn->session_info->security_token->sids[i]);
3550 data_len += sid_len;
3553 break;
3556 case SMB_MAC_QUERY_FS_INFO:
3558 * Thursby MAC extension... ONLY on NTFS filesystems
3559 * once we do streams then we don't need this
3561 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3562 data_len = 88;
3563 SIVAL(pdata,84,0x100); /* Don't support mac... */
3564 break;
3566 /* drop through */
3567 default:
3568 return NT_STATUS_INVALID_LEVEL;
3571 *ret_data_len = data_len;
3572 return NT_STATUS_OK;
3575 /****************************************************************************
3576 Reply to a TRANS2_QFSINFO (query filesystem info).
3577 ****************************************************************************/
3579 static void call_trans2qfsinfo(connection_struct *conn,
3580 struct smb_request *req,
3581 char **pparams, int total_params,
3582 char **ppdata, int total_data,
3583 unsigned int max_data_bytes)
3585 char *params = *pparams;
3586 uint16_t info_level;
3587 int data_len = 0;
3588 NTSTATUS status;
3590 if (total_params < 2) {
3591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3592 return;
3595 info_level = SVAL(params,0);
3597 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3598 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3599 DEBUG(0,("call_trans2qfsinfo: encryption required "
3600 "and info level 0x%x sent.\n",
3601 (unsigned int)info_level));
3602 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3603 return;
3607 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3609 status = smbd_do_qfsinfo(conn, req,
3610 info_level,
3611 req->flags2,
3612 max_data_bytes,
3613 NULL,
3614 ppdata, &data_len);
3615 if (!NT_STATUS_IS_OK(status)) {
3616 reply_nterror(req, status);
3617 return;
3620 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3621 max_data_bytes);
3623 DEBUG( 4, ( "%s info_level = %d\n",
3624 smb_fn_name(req->cmd), info_level) );
3626 return;
3629 /****************************************************************************
3630 Reply to a TRANS2_SETFSINFO (set filesystem info).
3631 ****************************************************************************/
3633 static void call_trans2setfsinfo(connection_struct *conn,
3634 struct smb_request *req,
3635 char **pparams, int total_params,
3636 char **ppdata, int total_data,
3637 unsigned int max_data_bytes)
3639 struct smbd_server_connection *sconn = req->sconn;
3640 char *pdata = *ppdata;
3641 char *params = *pparams;
3642 uint16 info_level;
3644 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3645 lp_servicename(talloc_tos(), SNUM(conn))));
3647 /* */
3648 if (total_params < 4) {
3649 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3650 total_params));
3651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3652 return;
3655 info_level = SVAL(params,2);
3657 if (IS_IPC(conn)) {
3658 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3659 info_level != SMB_SET_CIFS_UNIX_INFO) {
3660 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3661 "info level (0x%x) on IPC$.\n",
3662 (unsigned int)info_level));
3663 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3664 return;
3668 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3669 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3670 DEBUG(0,("call_trans2setfsinfo: encryption required "
3671 "and info level 0x%x sent.\n",
3672 (unsigned int)info_level));
3673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3674 return;
3678 switch(info_level) {
3679 case SMB_SET_CIFS_UNIX_INFO:
3680 if (!lp_unix_extensions()) {
3681 DEBUG(2,("call_trans2setfsinfo: "
3682 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3683 "unix extensions off\n"));
3684 reply_nterror(req,
3685 NT_STATUS_INVALID_LEVEL);
3686 return;
3689 /* There should be 12 bytes of capabilities set. */
3690 if (total_data < 12) {
3691 reply_nterror(
3692 req,
3693 NT_STATUS_INVALID_PARAMETER);
3694 return;
3696 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3697 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3698 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3699 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3700 /* Just print these values for now. */
3701 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3702 "major = %u, minor = %u cap_low = 0x%x, "
3703 "cap_high = 0x%xn",
3704 (unsigned int)sconn->
3705 smb1.unix_info.client_major,
3706 (unsigned int)sconn->
3707 smb1.unix_info.client_minor,
3708 (unsigned int)sconn->
3709 smb1.unix_info.client_cap_low,
3710 (unsigned int)sconn->
3711 smb1.unix_info.client_cap_high));
3713 /* Here is where we must switch to posix pathname processing... */
3714 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3715 lp_set_posix_pathnames();
3716 mangle_change_to_posix();
3719 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3720 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3721 /* Client that knows how to do posix locks,
3722 * but not posix open/mkdir operations. Set a
3723 * default type for read/write checks. */
3725 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3728 break;
3730 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3732 NTSTATUS status;
3733 size_t param_len = 0;
3734 size_t data_len = total_data;
3736 if (!lp_unix_extensions()) {
3737 reply_nterror(
3738 req,
3739 NT_STATUS_INVALID_LEVEL);
3740 return;
3743 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3744 reply_nterror(
3745 req,
3746 NT_STATUS_NOT_SUPPORTED);
3747 return;
3750 if (req->sconn->smb1.echo_handler.trusted_fde) {
3751 DEBUG( 2,("call_trans2setfsinfo: "
3752 "request transport encryption disabled"
3753 "with 'fork echo handler = yes'\n"));
3754 reply_nterror(
3755 req,
3756 NT_STATUS_NOT_SUPPORTED);
3757 return;
3760 DEBUG( 4,("call_trans2setfsinfo: "
3761 "request transport encryption.\n"));
3763 status = srv_request_encryption_setup(conn,
3764 (unsigned char **)ppdata,
3765 &data_len,
3766 (unsigned char **)pparams,
3767 &param_len);
3769 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3770 !NT_STATUS_IS_OK(status)) {
3771 reply_nterror(req, status);
3772 return;
3775 send_trans2_replies(conn, req,
3776 *pparams,
3777 param_len,
3778 *ppdata,
3779 data_len,
3780 max_data_bytes);
3782 if (NT_STATUS_IS_OK(status)) {
3783 /* Server-side transport
3784 * encryption is now *on*. */
3785 status = srv_encryption_start(conn);
3786 if (!NT_STATUS_IS_OK(status)) {
3787 char *reason = talloc_asprintf(talloc_tos(),
3788 "Failure in setting "
3789 "up encrypted transport: %s",
3790 nt_errstr(status));
3791 exit_server_cleanly(reason);
3794 return;
3797 case SMB_FS_QUOTA_INFORMATION:
3799 files_struct *fsp = NULL;
3800 SMB_NTQUOTA_STRUCT quotas;
3802 ZERO_STRUCT(quotas);
3804 /* access check */
3805 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3806 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3807 lp_servicename(talloc_tos(), SNUM(conn)),
3808 conn->session_info->unix_info->unix_name));
3809 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3810 return;
3813 /* note: normaly there're 48 bytes,
3814 * but we didn't use the last 6 bytes for now
3815 * --metze
3817 fsp = file_fsp(req, SVAL(params,0));
3819 if (!check_fsp_ntquota_handle(conn, req,
3820 fsp)) {
3821 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3822 reply_nterror(
3823 req, NT_STATUS_INVALID_HANDLE);
3824 return;
3827 if (total_data < 42) {
3828 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3829 total_data));
3830 reply_nterror(
3831 req,
3832 NT_STATUS_INVALID_PARAMETER);
3833 return;
3836 /* unknown_1 24 NULL bytes in pdata*/
3838 /* the soft quotas 8 bytes (uint64_t)*/
3839 quotas.softlim = BVAL(pdata,24);
3841 /* the hard quotas 8 bytes (uint64_t)*/
3842 quotas.hardlim = BVAL(pdata,32);
3844 /* quota_flags 2 bytes **/
3845 quotas.qflags = SVAL(pdata,40);
3847 /* unknown_2 6 NULL bytes follow*/
3849 /* now set the quotas */
3850 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3851 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3852 reply_nterror(req, map_nt_error_from_unix(errno));
3853 return;
3856 break;
3858 default:
3859 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3860 info_level));
3861 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3862 return;
3863 break;
3867 * sending this reply works fine,
3868 * but I'm not sure it's the same
3869 * like windows do...
3870 * --metze
3872 reply_outbuf(req, 10, 0);
3875 #if defined(HAVE_POSIX_ACLS)
3876 /****************************************************************************
3877 Utility function to count the number of entries in a POSIX acl.
3878 ****************************************************************************/
3880 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3882 unsigned int ace_count = 0;
3883 int entry_id = SMB_ACL_FIRST_ENTRY;
3884 SMB_ACL_ENTRY_T entry;
3886 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3887 /* get_next... */
3888 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3889 entry_id = SMB_ACL_NEXT_ENTRY;
3891 ace_count++;
3893 return ace_count;
3896 /****************************************************************************
3897 Utility function to marshall a POSIX acl into wire format.
3898 ****************************************************************************/
3900 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3902 int entry_id = SMB_ACL_FIRST_ENTRY;
3903 SMB_ACL_ENTRY_T entry;
3905 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3906 SMB_ACL_TAG_T tagtype;
3907 SMB_ACL_PERMSET_T permset;
3908 unsigned char perms = 0;
3909 unsigned int own_grp;
3911 /* get_next... */
3912 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3913 entry_id = SMB_ACL_NEXT_ENTRY;
3916 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3917 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3918 return False;
3921 if (sys_acl_get_permset(entry, &permset) == -1) {
3922 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3923 return False;
3926 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3927 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3928 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3930 SCVAL(pdata,1,perms);
3932 switch (tagtype) {
3933 case SMB_ACL_USER_OBJ:
3934 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3935 own_grp = (unsigned int)pst->st_ex_uid;
3936 SIVAL(pdata,2,own_grp);
3937 SIVAL(pdata,6,0);
3938 break;
3939 case SMB_ACL_USER:
3941 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3942 if (!puid) {
3943 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3944 return False;
3946 own_grp = (unsigned int)*puid;
3947 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3948 SIVAL(pdata,2,own_grp);
3949 SIVAL(pdata,6,0);
3950 break;
3952 case SMB_ACL_GROUP_OBJ:
3953 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3954 own_grp = (unsigned int)pst->st_ex_gid;
3955 SIVAL(pdata,2,own_grp);
3956 SIVAL(pdata,6,0);
3957 break;
3958 case SMB_ACL_GROUP:
3960 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3961 if (!pgid) {
3962 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3963 return False;
3965 own_grp = (unsigned int)*pgid;
3966 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3967 SIVAL(pdata,2,own_grp);
3968 SIVAL(pdata,6,0);
3969 break;
3971 case SMB_ACL_MASK:
3972 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3973 SIVAL(pdata,2,0xFFFFFFFF);
3974 SIVAL(pdata,6,0xFFFFFFFF);
3975 break;
3976 case SMB_ACL_OTHER:
3977 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3978 SIVAL(pdata,2,0xFFFFFFFF);
3979 SIVAL(pdata,6,0xFFFFFFFF);
3980 break;
3981 default:
3982 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3983 return False;
3985 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3988 return True;
3990 #endif
3992 /****************************************************************************
3993 Store the FILE_UNIX_BASIC info.
3994 ****************************************************************************/
3996 static char *store_file_unix_basic(connection_struct *conn,
3997 char *pdata,
3998 files_struct *fsp,
3999 const SMB_STRUCT_STAT *psbuf)
4001 uint64_t file_index = get_FileIndex(conn, psbuf);
4002 dev_t devno;
4004 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4005 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4007 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4008 pdata += 8;
4010 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4011 pdata += 8;
4013 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4014 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4015 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4016 pdata += 24;
4018 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4019 SIVAL(pdata,4,0);
4020 pdata += 8;
4022 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4023 SIVAL(pdata,4,0);
4024 pdata += 8;
4026 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4027 pdata += 4;
4029 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4030 devno = psbuf->st_ex_rdev;
4031 } else {
4032 devno = psbuf->st_ex_dev;
4035 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4036 SIVAL(pdata,4,0);
4037 pdata += 8;
4039 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4040 SIVAL(pdata,4,0);
4041 pdata += 8;
4043 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4044 pdata += 8;
4046 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4047 SIVAL(pdata,4,0);
4048 pdata += 8;
4050 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4051 SIVAL(pdata,4,0);
4052 pdata += 8;
4054 return pdata;
4057 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4058 * the chflags(2) (or equivalent) flags.
4060 * XXX: this really should be behind the VFS interface. To do this, we would
4061 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4062 * Each VFS module could then implement its own mapping as appropriate for the
4063 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4065 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4066 info2_flags_map[] =
4068 #ifdef UF_NODUMP
4069 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4070 #endif
4072 #ifdef UF_IMMUTABLE
4073 { UF_IMMUTABLE, EXT_IMMUTABLE },
4074 #endif
4076 #ifdef UF_APPEND
4077 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4078 #endif
4080 #ifdef UF_HIDDEN
4081 { UF_HIDDEN, EXT_HIDDEN },
4082 #endif
4084 /* Do not remove. We need to guarantee that this array has at least one
4085 * entry to build on HP-UX.
4087 { 0, 0 }
4091 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4092 uint32 *smb_fflags, uint32 *smb_fmask)
4094 int i;
4096 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4097 *smb_fmask |= info2_flags_map[i].smb_fflag;
4098 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4099 *smb_fflags |= info2_flags_map[i].smb_fflag;
4104 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4105 const uint32 smb_fflags,
4106 const uint32 smb_fmask,
4107 int *stat_fflags)
4109 uint32 max_fmask = 0;
4110 int i;
4112 *stat_fflags = psbuf->st_ex_flags;
4114 /* For each flags requested in smb_fmask, check the state of the
4115 * corresponding flag in smb_fflags and set or clear the matching
4116 * stat flag.
4119 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4120 max_fmask |= info2_flags_map[i].smb_fflag;
4121 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4122 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4123 *stat_fflags |= info2_flags_map[i].stat_fflag;
4124 } else {
4125 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4130 /* If smb_fmask is asking to set any bits that are not supported by
4131 * our flag mappings, we should fail.
4133 if ((smb_fmask & max_fmask) != smb_fmask) {
4134 return False;
4137 return True;
4141 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4142 * of file flags and birth (create) time.
4144 static char *store_file_unix_basic_info2(connection_struct *conn,
4145 char *pdata,
4146 files_struct *fsp,
4147 const SMB_STRUCT_STAT *psbuf)
4149 uint32 file_flags = 0;
4150 uint32 flags_mask = 0;
4152 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4154 /* Create (birth) time 64 bit */
4155 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4156 pdata += 8;
4158 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4159 SIVAL(pdata, 0, file_flags); /* flags */
4160 SIVAL(pdata, 4, flags_mask); /* mask */
4161 pdata += 8;
4163 return pdata;
4166 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4167 const struct stream_struct *streams,
4168 char *data,
4169 unsigned int max_data_bytes,
4170 unsigned int *data_size)
4172 unsigned int i;
4173 unsigned int ofs = 0;
4175 for (i = 0; i < num_streams; i++) {
4176 unsigned int next_offset;
4177 size_t namelen;
4178 smb_ucs2_t *namebuf;
4180 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4181 streams[i].name, &namelen) ||
4182 namelen <= 2)
4184 return NT_STATUS_INVALID_PARAMETER;
4188 * name_buf is now null-terminated, we need to marshall as not
4189 * terminated
4192 namelen -= 2;
4195 * We cannot overflow ...
4197 if ((ofs + 24 + namelen) > max_data_bytes) {
4198 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4199 i));
4200 TALLOC_FREE(namebuf);
4201 return STATUS_BUFFER_OVERFLOW;
4204 SIVAL(data, ofs+4, namelen);
4205 SOFF_T(data, ofs+8, streams[i].size);
4206 SOFF_T(data, ofs+16, streams[i].alloc_size);
4207 memcpy(data+ofs+24, namebuf, namelen);
4208 TALLOC_FREE(namebuf);
4210 next_offset = ofs + 24 + namelen;
4212 if (i == num_streams-1) {
4213 SIVAL(data, ofs, 0);
4215 else {
4216 unsigned int align = ndr_align_size(next_offset, 8);
4218 if ((next_offset + align) > max_data_bytes) {
4219 DEBUG(10, ("refusing to overflow align "
4220 "reply at stream %u\n",
4221 i));
4222 TALLOC_FREE(namebuf);
4223 return STATUS_BUFFER_OVERFLOW;
4226 memset(data+next_offset, 0, align);
4227 next_offset += align;
4229 SIVAL(data, ofs, next_offset - ofs);
4230 ofs = next_offset;
4233 ofs = next_offset;
4236 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4238 *data_size = ofs;
4240 return NT_STATUS_OK;
4243 /****************************************************************************
4244 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4245 ****************************************************************************/
4247 static void call_trans2qpipeinfo(connection_struct *conn,
4248 struct smb_request *req,
4249 unsigned int tran_call,
4250 char **pparams, int total_params,
4251 char **ppdata, int total_data,
4252 unsigned int max_data_bytes)
4254 char *params = *pparams;
4255 char *pdata = *ppdata;
4256 unsigned int data_size = 0;
4257 unsigned int param_size = 2;
4258 uint16 info_level;
4259 files_struct *fsp;
4261 if (!params) {
4262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4263 return;
4266 if (total_params < 4) {
4267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4268 return;
4271 fsp = file_fsp(req, SVAL(params,0));
4272 if (!fsp_is_np(fsp)) {
4273 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4274 return;
4277 info_level = SVAL(params,2);
4279 *pparams = (char *)SMB_REALLOC(*pparams,2);
4280 if (*pparams == NULL) {
4281 reply_nterror(req, NT_STATUS_NO_MEMORY);
4282 return;
4284 params = *pparams;
4285 SSVAL(params,0,0);
4286 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4287 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4288 if (*ppdata == NULL ) {
4289 reply_nterror(req, NT_STATUS_NO_MEMORY);
4290 return;
4292 pdata = *ppdata;
4294 switch (info_level) {
4295 case SMB_FILE_STANDARD_INFORMATION:
4296 memset(pdata,0,24);
4297 SOFF_T(pdata,0,4096LL);
4298 SIVAL(pdata,16,1);
4299 SIVAL(pdata,20,1);
4300 data_size = 24;
4301 break;
4303 default:
4304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4305 return;
4308 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4309 max_data_bytes);
4311 return;
4314 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4315 TALLOC_CTX *mem_ctx,
4316 uint16_t info_level,
4317 files_struct *fsp,
4318 struct smb_filename *smb_fname,
4319 bool delete_pending,
4320 struct timespec write_time_ts,
4321 struct ea_list *ea_list,
4322 int lock_data_count,
4323 char *lock_data,
4324 uint16_t flags2,
4325 unsigned int max_data_bytes,
4326 char **ppdata,
4327 unsigned int *pdata_size)
4329 char *pdata = *ppdata;
4330 char *dstart, *dend;
4331 unsigned int data_size;
4332 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4333 time_t create_time, mtime, atime, c_time;
4334 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4335 char *p;
4336 char *base_name;
4337 char *dos_fname;
4338 int mode;
4339 int nlink;
4340 NTSTATUS status;
4341 uint64_t file_size = 0;
4342 uint64_t pos = 0;
4343 uint64_t allocation_size = 0;
4344 uint64_t file_index = 0;
4345 uint32_t access_mask = 0;
4347 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4348 return NT_STATUS_INVALID_LEVEL;
4351 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4352 smb_fname_str_dbg(smb_fname),
4353 fsp_fnum_dbg(fsp),
4354 info_level, max_data_bytes));
4356 mode = dos_mode(conn, smb_fname);
4357 nlink = psbuf->st_ex_nlink;
4359 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4360 nlink = 1;
4363 if ((nlink > 0) && delete_pending) {
4364 nlink -= 1;
4367 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4368 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4369 if (*ppdata == NULL) {
4370 return NT_STATUS_NO_MEMORY;
4372 pdata = *ppdata;
4373 dstart = pdata;
4374 dend = dstart + data_size - 1;
4376 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4377 update_stat_ex_mtime(psbuf, write_time_ts);
4380 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4381 mtime_ts = psbuf->st_ex_mtime;
4382 atime_ts = psbuf->st_ex_atime;
4383 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4385 if (lp_dos_filetime_resolution(SNUM(conn))) {
4386 dos_filetime_timespec(&create_time_ts);
4387 dos_filetime_timespec(&mtime_ts);
4388 dos_filetime_timespec(&atime_ts);
4389 dos_filetime_timespec(&ctime_ts);
4392 create_time = convert_timespec_to_time_t(create_time_ts);
4393 mtime = convert_timespec_to_time_t(mtime_ts);
4394 atime = convert_timespec_to_time_t(atime_ts);
4395 c_time = convert_timespec_to_time_t(ctime_ts);
4397 p = strrchr_m(smb_fname->base_name,'/');
4398 if (!p)
4399 base_name = smb_fname->base_name;
4400 else
4401 base_name = p+1;
4403 /* NT expects the name to be in an exact form of the *full*
4404 filename. See the trans2 torture test */
4405 if (ISDOT(base_name)) {
4406 dos_fname = talloc_strdup(mem_ctx, "\\");
4407 if (!dos_fname) {
4408 return NT_STATUS_NO_MEMORY;
4410 } else {
4411 dos_fname = talloc_asprintf(mem_ctx,
4412 "\\%s",
4413 smb_fname->base_name);
4414 if (!dos_fname) {
4415 return NT_STATUS_NO_MEMORY;
4417 if (is_ntfs_stream_smb_fname(smb_fname)) {
4418 dos_fname = talloc_asprintf(dos_fname, "%s",
4419 smb_fname->stream_name);
4420 if (!dos_fname) {
4421 return NT_STATUS_NO_MEMORY;
4425 string_replace(dos_fname, '/', '\\');
4428 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4430 if (!fsp) {
4431 /* Do we have this path open ? */
4432 files_struct *fsp1;
4433 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4434 fsp1 = file_find_di_first(conn->sconn, fileid);
4435 if (fsp1 && fsp1->initial_allocation_size) {
4436 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4440 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4441 file_size = get_file_size_stat(psbuf);
4444 if (fsp) {
4445 pos = fsp->fh->position_information;
4448 if (fsp) {
4449 access_mask = fsp->access_mask;
4450 } else {
4451 /* GENERIC_EXECUTE mapping from Windows */
4452 access_mask = 0x12019F;
4455 /* This should be an index number - looks like
4456 dev/ino to me :-)
4458 I think this causes us to fail the IFSKIT
4459 BasicFileInformationTest. -tpot */
4460 file_index = get_FileIndex(conn, psbuf);
4462 switch (info_level) {
4463 case SMB_INFO_STANDARD:
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4465 data_size = 22;
4466 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4467 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4468 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4469 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4470 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4471 SSVAL(pdata,l1_attrFile,mode);
4472 break;
4474 case SMB_INFO_QUERY_EA_SIZE:
4476 unsigned int ea_size =
4477 estimate_ea_size(conn, fsp,
4478 smb_fname);
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4480 data_size = 26;
4481 srv_put_dos_date2(pdata,0,create_time);
4482 srv_put_dos_date2(pdata,4,atime);
4483 srv_put_dos_date2(pdata,8,mtime); /* write time */
4484 SIVAL(pdata,12,(uint32)file_size);
4485 SIVAL(pdata,16,(uint32)allocation_size);
4486 SSVAL(pdata,20,mode);
4487 SIVAL(pdata,22,ea_size);
4488 break;
4491 case SMB_INFO_IS_NAME_VALID:
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4493 if (fsp) {
4494 /* os/2 needs this ? really ?*/
4495 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4497 /* This is only reached for qpathinfo */
4498 data_size = 0;
4499 break;
4501 case SMB_INFO_QUERY_EAS_FROM_LIST:
4503 size_t total_ea_len = 0;
4504 struct ea_list *ea_file_list = NULL;
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4507 status =
4508 get_ea_list_from_file(mem_ctx, conn, fsp,
4509 smb_fname,
4510 &total_ea_len, &ea_file_list);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 return status;
4515 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4517 if (!ea_list || (total_ea_len > data_size)) {
4518 data_size = 4;
4519 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4520 break;
4523 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4524 break;
4527 case SMB_INFO_QUERY_ALL_EAS:
4529 /* We have data_size bytes to put EA's into. */
4530 size_t total_ea_len = 0;
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4533 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4534 smb_fname,
4535 &total_ea_len, &ea_list);
4536 if (!NT_STATUS_IS_OK(status)) {
4537 return status;
4540 if (!ea_list || (total_ea_len > data_size)) {
4541 data_size = 4;
4542 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4543 break;
4546 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4547 break;
4550 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4552 /* This is FileFullEaInformation - 0xF which maps to
4553 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4555 /* We have data_size bytes to put EA's into. */
4556 size_t total_ea_len = 0;
4557 struct ea_list *ea_file_list = NULL;
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4561 /*TODO: add filtering and index handling */
4563 status =
4564 get_ea_list_from_file(mem_ctx, conn, fsp,
4565 smb_fname,
4566 &total_ea_len, &ea_file_list);
4567 if (!NT_STATUS_IS_OK(status)) {
4568 return status;
4570 if (!ea_file_list) {
4571 return NT_STATUS_NO_EAS_ON_FILE;
4574 status = fill_ea_chained_buffer(mem_ctx,
4575 pdata,
4576 data_size,
4577 &data_size,
4578 conn, ea_file_list);
4579 if (!NT_STATUS_IS_OK(status)) {
4580 return status;
4582 break;
4585 case SMB_FILE_BASIC_INFORMATION:
4586 case SMB_QUERY_FILE_BASIC_INFO:
4588 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4590 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4591 } else {
4592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4593 data_size = 40;
4594 SIVAL(pdata,36,0);
4596 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4597 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4598 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4599 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4600 SIVAL(pdata,32,mode);
4602 DEBUG(5,("SMB_QFBI - "));
4603 DEBUG(5,("create: %s ", ctime(&create_time)));
4604 DEBUG(5,("access: %s ", ctime(&atime)));
4605 DEBUG(5,("write: %s ", ctime(&mtime)));
4606 DEBUG(5,("change: %s ", ctime(&c_time)));
4607 DEBUG(5,("mode: %x\n", mode));
4608 break;
4610 case SMB_FILE_STANDARD_INFORMATION:
4611 case SMB_QUERY_FILE_STANDARD_INFO:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4614 data_size = 24;
4615 SOFF_T(pdata,0,allocation_size);
4616 SOFF_T(pdata,8,file_size);
4617 SIVAL(pdata,16,nlink);
4618 SCVAL(pdata,20,delete_pending?1:0);
4619 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4620 SSVAL(pdata,22,0); /* Padding. */
4621 break;
4623 case SMB_FILE_EA_INFORMATION:
4624 case SMB_QUERY_FILE_EA_INFO:
4626 unsigned int ea_size =
4627 estimate_ea_size(conn, fsp, smb_fname);
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4629 data_size = 4;
4630 SIVAL(pdata,0,ea_size);
4631 break;
4634 /* Get the 8.3 name - used if NT SMB was negotiated. */
4635 case SMB_QUERY_FILE_ALT_NAME_INFO:
4636 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4638 int len;
4639 char mangled_name[13];
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4641 if (!name_to_8_3(base_name,mangled_name,
4642 True,conn->params)) {
4643 return NT_STATUS_NO_MEMORY;
4645 len = srvstr_push(dstart, flags2,
4646 pdata+4, mangled_name,
4647 PTR_DIFF(dend, pdata+4),
4648 STR_UNICODE);
4649 data_size = 4 + len;
4650 SIVAL(pdata,0,len);
4651 break;
4654 case SMB_QUERY_FILE_NAME_INFO:
4656 int len;
4658 this must be *exactly* right for ACLs on mapped drives to work
4660 len = srvstr_push(dstart, flags2,
4661 pdata+4, dos_fname,
4662 PTR_DIFF(dend, pdata+4),
4663 STR_UNICODE);
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4665 data_size = 4 + len;
4666 SIVAL(pdata,0,len);
4667 break;
4670 case SMB_FILE_ALLOCATION_INFORMATION:
4671 case SMB_QUERY_FILE_ALLOCATION_INFO:
4672 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4673 data_size = 8;
4674 SOFF_T(pdata,0,allocation_size);
4675 break;
4677 case SMB_FILE_END_OF_FILE_INFORMATION:
4678 case SMB_QUERY_FILE_END_OF_FILEINFO:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4680 data_size = 8;
4681 SOFF_T(pdata,0,file_size);
4682 break;
4684 case SMB_QUERY_FILE_ALL_INFO:
4685 case SMB_FILE_ALL_INFORMATION:
4687 int len;
4688 unsigned int ea_size =
4689 estimate_ea_size(conn, fsp, smb_fname);
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4691 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4692 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4693 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4694 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4695 SIVAL(pdata,32,mode);
4696 SIVAL(pdata,36,0); /* padding. */
4697 pdata += 40;
4698 SOFF_T(pdata,0,allocation_size);
4699 SOFF_T(pdata,8,file_size);
4700 SIVAL(pdata,16,nlink);
4701 SCVAL(pdata,20,delete_pending);
4702 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4703 SSVAL(pdata,22,0);
4704 pdata += 24;
4705 SIVAL(pdata,0,ea_size);
4706 pdata += 4; /* EA info */
4707 len = srvstr_push(dstart, flags2,
4708 pdata+4, dos_fname,
4709 PTR_DIFF(dend, pdata+4),
4710 STR_UNICODE);
4711 SIVAL(pdata,0,len);
4712 pdata += 4 + len;
4713 data_size = PTR_DIFF(pdata,(*ppdata));
4714 break;
4717 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4719 int len;
4720 unsigned int ea_size =
4721 estimate_ea_size(conn, fsp, smb_fname);
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4723 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4724 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4725 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4726 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4727 SIVAL(pdata, 0x20, mode);
4728 SIVAL(pdata, 0x24, 0); /* padding. */
4729 SBVAL(pdata, 0x28, allocation_size);
4730 SBVAL(pdata, 0x30, file_size);
4731 SIVAL(pdata, 0x38, nlink);
4732 SCVAL(pdata, 0x3C, delete_pending);
4733 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4734 SSVAL(pdata, 0x3E, 0); /* padding */
4735 SBVAL(pdata, 0x40, file_index);
4736 SIVAL(pdata, 0x48, ea_size);
4737 SIVAL(pdata, 0x4C, access_mask);
4738 SBVAL(pdata, 0x50, pos);
4739 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4740 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4742 pdata += 0x60;
4744 len = srvstr_push(dstart, flags2,
4745 pdata+4, dos_fname,
4746 PTR_DIFF(dend, pdata+4),
4747 STR_UNICODE);
4748 SIVAL(pdata,0,len);
4749 pdata += 4 + len;
4750 data_size = PTR_DIFF(pdata,(*ppdata));
4751 break;
4753 case SMB_FILE_INTERNAL_INFORMATION:
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4756 SBVAL(pdata, 0, file_index);
4757 data_size = 8;
4758 break;
4760 case SMB_FILE_ACCESS_INFORMATION:
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4762 SIVAL(pdata, 0, access_mask);
4763 data_size = 4;
4764 break;
4766 case SMB_FILE_NAME_INFORMATION:
4767 /* Pathname with leading '\'. */
4769 size_t byte_len;
4770 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4772 SIVAL(pdata,0,byte_len);
4773 data_size = 4 + byte_len;
4774 break;
4777 case SMB_FILE_DISPOSITION_INFORMATION:
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4779 data_size = 1;
4780 SCVAL(pdata,0,delete_pending);
4781 break;
4783 case SMB_FILE_POSITION_INFORMATION:
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4785 data_size = 8;
4786 SOFF_T(pdata,0,pos);
4787 break;
4789 case SMB_FILE_MODE_INFORMATION:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4791 SIVAL(pdata,0,mode);
4792 data_size = 4;
4793 break;
4795 case SMB_FILE_ALIGNMENT_INFORMATION:
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4797 SIVAL(pdata,0,0); /* No alignment needed. */
4798 data_size = 4;
4799 break;
4802 * NT4 server just returns "invalid query" to this - if we try
4803 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4804 * want this. JRA.
4806 /* The first statement above is false - verified using Thursby
4807 * client against NT4 -- gcolley.
4809 case SMB_QUERY_FILE_STREAM_INFO:
4810 case SMB_FILE_STREAM_INFORMATION: {
4811 unsigned int num_streams = 0;
4812 struct stream_struct *streams = NULL;
4814 DEBUG(10,("smbd_do_qfilepathinfo: "
4815 "SMB_FILE_STREAM_INFORMATION\n"));
4817 if (is_ntfs_stream_smb_fname(smb_fname)) {
4818 return NT_STATUS_INVALID_PARAMETER;
4821 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4822 talloc_tos(), &num_streams, &streams);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 DEBUG(10, ("could not get stream info: %s\n",
4826 nt_errstr(status)));
4827 return status;
4830 status = marshall_stream_info(num_streams, streams,
4831 pdata, max_data_bytes,
4832 &data_size);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 DEBUG(10, ("marshall_stream_info failed: %s\n",
4836 nt_errstr(status)));
4837 TALLOC_FREE(streams);
4838 return status;
4841 TALLOC_FREE(streams);
4843 break;
4845 case SMB_QUERY_COMPRESSION_INFO:
4846 case SMB_FILE_COMPRESSION_INFORMATION:
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4848 SOFF_T(pdata,0,file_size);
4849 SIVAL(pdata,8,0); /* ??? */
4850 SIVAL(pdata,12,0); /* ??? */
4851 data_size = 16;
4852 break;
4854 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4856 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4857 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4858 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4859 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4860 SOFF_T(pdata,32,allocation_size);
4861 SOFF_T(pdata,40,file_size);
4862 SIVAL(pdata,48,mode);
4863 SIVAL(pdata,52,0); /* ??? */
4864 data_size = 56;
4865 break;
4867 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4868 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4869 SIVAL(pdata,0,mode);
4870 SIVAL(pdata,4,0);
4871 data_size = 8;
4872 break;
4875 * CIFS UNIX Extensions.
4878 case SMB_QUERY_FILE_UNIX_BASIC:
4880 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4881 data_size = PTR_DIFF(pdata,(*ppdata));
4883 DEBUG(4,("smbd_do_qfilepathinfo: "
4884 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4885 dump_data(4, (uint8_t *)(*ppdata), data_size);
4887 break;
4889 case SMB_QUERY_FILE_UNIX_INFO2:
4891 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4892 data_size = PTR_DIFF(pdata,(*ppdata));
4895 int i;
4896 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4898 for (i=0; i<100; i++)
4899 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4900 DEBUG(4,("\n"));
4903 break;
4905 case SMB_QUERY_FILE_UNIX_LINK:
4907 int len;
4908 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4910 if (!buffer) {
4911 return NT_STATUS_NO_MEMORY;
4914 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4915 #ifdef S_ISLNK
4916 if(!S_ISLNK(psbuf->st_ex_mode)) {
4917 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4919 #else
4920 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4921 #endif
4922 len = SMB_VFS_READLINK(conn,
4923 smb_fname->base_name,
4924 buffer, PATH_MAX);
4925 if (len == -1) {
4926 return map_nt_error_from_unix(errno);
4928 buffer[len] = 0;
4929 len = srvstr_push(dstart, flags2,
4930 pdata, buffer,
4931 PTR_DIFF(dend, pdata),
4932 STR_TERMINATE);
4933 pdata += len;
4934 data_size = PTR_DIFF(pdata,(*ppdata));
4936 break;
4939 #if defined(HAVE_POSIX_ACLS)
4940 case SMB_QUERY_POSIX_ACL:
4942 SMB_ACL_T file_acl = NULL;
4943 SMB_ACL_T def_acl = NULL;
4944 uint16 num_file_acls = 0;
4945 uint16 num_def_acls = 0;
4947 if (fsp && fsp->fh->fd != -1) {
4948 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4949 talloc_tos());
4950 } else {
4951 file_acl =
4952 SMB_VFS_SYS_ACL_GET_FILE(conn,
4953 smb_fname->base_name,
4954 SMB_ACL_TYPE_ACCESS,
4955 talloc_tos());
4958 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4959 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4960 "not implemented on "
4961 "filesystem containing %s\n",
4962 smb_fname->base_name));
4963 return NT_STATUS_NOT_IMPLEMENTED;
4966 if (S_ISDIR(psbuf->st_ex_mode)) {
4967 if (fsp && fsp->is_directory) {
4968 def_acl =
4969 SMB_VFS_SYS_ACL_GET_FILE(
4970 conn,
4971 fsp->fsp_name->base_name,
4972 SMB_ACL_TYPE_DEFAULT,
4973 talloc_tos());
4974 } else {
4975 def_acl =
4976 SMB_VFS_SYS_ACL_GET_FILE(
4977 conn,
4978 smb_fname->base_name,
4979 SMB_ACL_TYPE_DEFAULT,
4980 talloc_tos());
4982 def_acl = free_empty_sys_acl(conn, def_acl);
4985 num_file_acls = count_acl_entries(conn, file_acl);
4986 num_def_acls = count_acl_entries(conn, def_acl);
4988 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4989 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4990 data_size,
4991 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4992 SMB_POSIX_ACL_HEADER_SIZE) ));
4993 if (file_acl) {
4994 TALLOC_FREE(file_acl);
4996 if (def_acl) {
4997 TALLOC_FREE(def_acl);
4999 return NT_STATUS_BUFFER_TOO_SMALL;
5002 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5003 SSVAL(pdata,2,num_file_acls);
5004 SSVAL(pdata,4,num_def_acls);
5005 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5006 if (file_acl) {
5007 TALLOC_FREE(file_acl);
5009 if (def_acl) {
5010 TALLOC_FREE(def_acl);
5012 return NT_STATUS_INTERNAL_ERROR;
5014 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5015 if (file_acl) {
5016 TALLOC_FREE(file_acl);
5018 if (def_acl) {
5019 TALLOC_FREE(def_acl);
5021 return NT_STATUS_INTERNAL_ERROR;
5024 if (file_acl) {
5025 TALLOC_FREE(file_acl);
5027 if (def_acl) {
5028 TALLOC_FREE(def_acl);
5030 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5031 break;
5033 #endif
5036 case SMB_QUERY_POSIX_LOCK:
5038 uint64_t count;
5039 uint64_t offset;
5040 uint64_t smblctx;
5041 enum brl_type lock_type;
5043 /* We need an open file with a real fd for this. */
5044 if (!fsp || fsp->fh->fd == -1) {
5045 return NT_STATUS_INVALID_LEVEL;
5048 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5049 return NT_STATUS_INVALID_PARAMETER;
5052 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5053 case POSIX_LOCK_TYPE_READ:
5054 lock_type = READ_LOCK;
5055 break;
5056 case POSIX_LOCK_TYPE_WRITE:
5057 lock_type = WRITE_LOCK;
5058 break;
5059 case POSIX_LOCK_TYPE_UNLOCK:
5060 default:
5061 /* There's no point in asking for an unlock... */
5062 return NT_STATUS_INVALID_PARAMETER;
5065 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5066 #if defined(HAVE_LONGLONG)
5067 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5068 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5069 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5070 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5071 #else /* HAVE_LONGLONG */
5072 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5073 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5074 #endif /* HAVE_LONGLONG */
5076 status = query_lock(fsp,
5077 &smblctx,
5078 &count,
5079 &offset,
5080 &lock_type,
5081 POSIX_LOCK);
5083 if (ERROR_WAS_LOCK_DENIED(status)) {
5084 /* Here we need to report who has it locked... */
5085 data_size = POSIX_LOCK_DATA_SIZE;
5087 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5088 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5089 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5090 #if defined(HAVE_LONGLONG)
5091 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5092 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5093 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5094 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5095 #else /* HAVE_LONGLONG */
5096 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5097 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5098 #endif /* HAVE_LONGLONG */
5100 } else if (NT_STATUS_IS_OK(status)) {
5101 /* For success we just return a copy of what we sent
5102 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5103 data_size = POSIX_LOCK_DATA_SIZE;
5104 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5105 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5106 } else {
5107 return status;
5109 break;
5112 default:
5113 return NT_STATUS_INVALID_LEVEL;
5116 *pdata_size = data_size;
5117 return NT_STATUS_OK;
5120 /****************************************************************************
5121 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5122 file name or file id).
5123 ****************************************************************************/
5125 static void call_trans2qfilepathinfo(connection_struct *conn,
5126 struct smb_request *req,
5127 unsigned int tran_call,
5128 char **pparams, int total_params,
5129 char **ppdata, int total_data,
5130 unsigned int max_data_bytes)
5132 char *params = *pparams;
5133 char *pdata = *ppdata;
5134 uint16 info_level;
5135 unsigned int data_size = 0;
5136 unsigned int param_size = 2;
5137 struct smb_filename *smb_fname = NULL;
5138 bool delete_pending = False;
5139 struct timespec write_time_ts;
5140 files_struct *fsp = NULL;
5141 struct file_id fileid;
5142 struct ea_list *ea_list = NULL;
5143 int lock_data_count = 0;
5144 char *lock_data = NULL;
5145 NTSTATUS status = NT_STATUS_OK;
5147 if (!params) {
5148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5149 return;
5152 ZERO_STRUCT(write_time_ts);
5154 if (tran_call == TRANSACT2_QFILEINFO) {
5155 if (total_params < 4) {
5156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5157 return;
5160 if (IS_IPC(conn)) {
5161 call_trans2qpipeinfo(conn, req, tran_call,
5162 pparams, total_params,
5163 ppdata, total_data,
5164 max_data_bytes);
5165 return;
5168 fsp = file_fsp(req, SVAL(params,0));
5169 info_level = SVAL(params,2);
5171 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5173 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5174 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5175 return;
5178 /* Initial check for valid fsp ptr. */
5179 if (!check_fsp_open(conn, req, fsp)) {
5180 return;
5183 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5184 &smb_fname);
5185 if (!NT_STATUS_IS_OK(status)) {
5186 reply_nterror(req, status);
5187 return;
5190 if(fsp->fake_file_handle) {
5192 * This is actually for the QUOTA_FAKE_FILE --metze
5195 /* We know this name is ok, it's already passed the checks. */
5197 } else if(fsp->fh->fd == -1) {
5199 * This is actually a QFILEINFO on a directory
5200 * handle (returned from an NT SMB). NT5.0 seems
5201 * to do this call. JRA.
5204 if (INFO_LEVEL_IS_UNIX(info_level)) {
5205 /* Always do lstat for UNIX calls. */
5206 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5207 DEBUG(3,("call_trans2qfilepathinfo: "
5208 "SMB_VFS_LSTAT of %s failed "
5209 "(%s)\n",
5210 smb_fname_str_dbg(smb_fname),
5211 strerror(errno)));
5212 reply_nterror(req,
5213 map_nt_error_from_unix(errno));
5214 return;
5216 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5217 DEBUG(3,("call_trans2qfilepathinfo: "
5218 "SMB_VFS_STAT of %s failed (%s)\n",
5219 smb_fname_str_dbg(smb_fname),
5220 strerror(errno)));
5221 reply_nterror(req,
5222 map_nt_error_from_unix(errno));
5223 return;
5226 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5227 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5228 } else {
5230 * Original code - this is an open file.
5232 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5233 DEBUG(3, ("fstat of %s failed (%s)\n",
5234 fsp_fnum_dbg(fsp), strerror(errno)));
5235 reply_nterror(req,
5236 map_nt_error_from_unix(errno));
5237 return;
5239 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5240 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5243 } else {
5244 uint32_t name_hash;
5245 char *fname = NULL;
5246 uint32_t ucf_flags = 0;
5248 /* qpathinfo */
5249 if (total_params < 7) {
5250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5251 return;
5254 info_level = SVAL(params,0);
5256 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5258 if (INFO_LEVEL_IS_UNIX(info_level)) {
5259 if (!lp_unix_extensions()) {
5260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5261 return;
5263 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5264 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5265 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5266 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5270 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5271 total_params - 6,
5272 STR_TERMINATE, &status);
5273 if (!NT_STATUS_IS_OK(status)) {
5274 reply_nterror(req, status);
5275 return;
5278 status = filename_convert(req,
5279 conn,
5280 req->flags2 & FLAGS2_DFS_PATHNAMES,
5281 fname,
5282 ucf_flags,
5283 NULL,
5284 &smb_fname);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5287 reply_botherror(req,
5288 NT_STATUS_PATH_NOT_COVERED,
5289 ERRSRV, ERRbadpath);
5290 return;
5292 reply_nterror(req, status);
5293 return;
5296 /* If this is a stream, check if there is a delete_pending. */
5297 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5298 && is_ntfs_stream_smb_fname(smb_fname)) {
5299 struct smb_filename *smb_fname_base = NULL;
5301 /* Create an smb_filename with stream_name == NULL. */
5302 status =
5303 create_synthetic_smb_fname(talloc_tos(),
5304 smb_fname->base_name,
5305 NULL, NULL,
5306 &smb_fname_base);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 reply_nterror(req, status);
5309 return;
5312 if (INFO_LEVEL_IS_UNIX(info_level)) {
5313 /* Always do lstat for UNIX calls. */
5314 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5315 DEBUG(3,("call_trans2qfilepathinfo: "
5316 "SMB_VFS_LSTAT of %s failed "
5317 "(%s)\n",
5318 smb_fname_str_dbg(smb_fname_base),
5319 strerror(errno)));
5320 TALLOC_FREE(smb_fname_base);
5321 reply_nterror(req,
5322 map_nt_error_from_unix(errno));
5323 return;
5325 } else {
5326 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5327 DEBUG(3,("call_trans2qfilepathinfo: "
5328 "fileinfo of %s failed "
5329 "(%s)\n",
5330 smb_fname_str_dbg(smb_fname_base),
5331 strerror(errno)));
5332 TALLOC_FREE(smb_fname_base);
5333 reply_nterror(req,
5334 map_nt_error_from_unix(errno));
5335 return;
5339 status = file_name_hash(conn,
5340 smb_fname_str_dbg(smb_fname_base),
5341 &name_hash);
5342 if (!NT_STATUS_IS_OK(status)) {
5343 TALLOC_FREE(smb_fname_base);
5344 reply_nterror(req, status);
5345 return;
5348 fileid = vfs_file_id_from_sbuf(conn,
5349 &smb_fname_base->st);
5350 TALLOC_FREE(smb_fname_base);
5351 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5352 if (delete_pending) {
5353 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5354 return;
5358 if (INFO_LEVEL_IS_UNIX(info_level)) {
5359 /* Always do lstat for UNIX calls. */
5360 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5361 DEBUG(3,("call_trans2qfilepathinfo: "
5362 "SMB_VFS_LSTAT of %s failed (%s)\n",
5363 smb_fname_str_dbg(smb_fname),
5364 strerror(errno)));
5365 reply_nterror(req,
5366 map_nt_error_from_unix(errno));
5367 return;
5370 } else {
5371 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5372 DEBUG(3,("call_trans2qfilepathinfo: "
5373 "SMB_VFS_STAT of %s failed (%s)\n",
5374 smb_fname_str_dbg(smb_fname),
5375 strerror(errno)));
5376 reply_nterror(req,
5377 map_nt_error_from_unix(errno));
5378 return;
5382 status = file_name_hash(conn,
5383 smb_fname_str_dbg(smb_fname),
5384 &name_hash);
5385 if (!NT_STATUS_IS_OK(status)) {
5386 reply_nterror(req, status);
5387 return;
5390 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5391 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5392 if (delete_pending) {
5393 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5394 return;
5398 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5399 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5400 fsp_fnum_dbg(fsp),
5401 info_level,tran_call,total_data));
5403 /* Pull out any data sent here before we realloc. */
5404 switch (info_level) {
5405 case SMB_INFO_QUERY_EAS_FROM_LIST:
5407 /* Pull any EA list from the data portion. */
5408 uint32 ea_size;
5410 if (total_data < 4) {
5411 reply_nterror(
5412 req, NT_STATUS_INVALID_PARAMETER);
5413 return;
5415 ea_size = IVAL(pdata,0);
5417 if (total_data > 0 && ea_size != total_data) {
5418 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5419 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5420 reply_nterror(
5421 req, NT_STATUS_INVALID_PARAMETER);
5422 return;
5425 if (!lp_ea_support(SNUM(conn))) {
5426 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5427 return;
5430 /* Pull out the list of names. */
5431 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5432 if (!ea_list) {
5433 reply_nterror(
5434 req, NT_STATUS_INVALID_PARAMETER);
5435 return;
5437 break;
5440 case SMB_QUERY_POSIX_LOCK:
5442 if (fsp == NULL || fsp->fh->fd == -1) {
5443 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5444 return;
5447 if (total_data != POSIX_LOCK_DATA_SIZE) {
5448 reply_nterror(
5449 req, NT_STATUS_INVALID_PARAMETER);
5450 return;
5453 /* Copy the lock range data. */
5454 lock_data = (char *)talloc_memdup(
5455 req, pdata, total_data);
5456 if (!lock_data) {
5457 reply_nterror(req, NT_STATUS_NO_MEMORY);
5458 return;
5460 lock_data_count = total_data;
5462 default:
5463 break;
5466 *pparams = (char *)SMB_REALLOC(*pparams,2);
5467 if (*pparams == NULL) {
5468 reply_nterror(req, NT_STATUS_NO_MEMORY);
5469 return;
5471 params = *pparams;
5472 SSVAL(params,0,0);
5475 * draft-leach-cifs-v1-spec-02.txt
5476 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5477 * says:
5479 * The requested information is placed in the Data portion of the
5480 * transaction response. For the information levels greater than 0x100,
5481 * the transaction response has 1 parameter word which should be
5482 * ignored by the client.
5484 * However Windows only follows this rule for the IS_NAME_VALID call.
5486 switch (info_level) {
5487 case SMB_INFO_IS_NAME_VALID:
5488 param_size = 0;
5489 break;
5492 if ((info_level & 0xFF00) == 0xFF00) {
5494 * We use levels that start with 0xFF00
5495 * internally to represent SMB2 specific levels
5497 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5498 return;
5501 status = smbd_do_qfilepathinfo(conn, req, info_level,
5502 fsp, smb_fname,
5503 delete_pending, write_time_ts,
5504 ea_list,
5505 lock_data_count, lock_data,
5506 req->flags2, max_data_bytes,
5507 ppdata, &data_size);
5508 if (!NT_STATUS_IS_OK(status)) {
5509 reply_nterror(req, status);
5510 return;
5513 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5514 max_data_bytes);
5516 return;
5519 /****************************************************************************
5520 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5521 code.
5522 ****************************************************************************/
5524 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5525 connection_struct *conn,
5526 struct smb_request *req,
5527 bool overwrite_if_exists,
5528 const struct smb_filename *smb_fname_old,
5529 struct smb_filename *smb_fname_new)
5531 NTSTATUS status = NT_STATUS_OK;
5533 /* source must already exist. */
5534 if (!VALID_STAT(smb_fname_old->st)) {
5535 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5538 if (VALID_STAT(smb_fname_new->st)) {
5539 if (overwrite_if_exists) {
5540 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5541 return NT_STATUS_FILE_IS_A_DIRECTORY;
5543 status = unlink_internals(conn,
5544 req,
5545 FILE_ATTRIBUTE_NORMAL,
5546 smb_fname_new,
5547 false);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 return status;
5551 } else {
5552 /* Disallow if newname already exists. */
5553 return NT_STATUS_OBJECT_NAME_COLLISION;
5557 /* No links from a directory. */
5558 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5559 return NT_STATUS_FILE_IS_A_DIRECTORY;
5562 /* Setting a hardlink to/from a stream isn't currently supported. */
5563 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5564 is_ntfs_stream_smb_fname(smb_fname_new)) {
5565 return NT_STATUS_INVALID_PARAMETER;
5568 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5569 smb_fname_old->base_name, smb_fname_new->base_name));
5571 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5572 smb_fname_new->base_name) != 0) {
5573 status = map_nt_error_from_unix(errno);
5574 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5575 nt_errstr(status), smb_fname_old->base_name,
5576 smb_fname_new->base_name));
5578 return status;
5581 /****************************************************************************
5582 Deal with setting the time from any of the setfilepathinfo functions.
5583 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5584 calling this function.
5585 ****************************************************************************/
5587 NTSTATUS smb_set_file_time(connection_struct *conn,
5588 files_struct *fsp,
5589 const struct smb_filename *smb_fname,
5590 struct smb_file_time *ft,
5591 bool setting_write_time)
5593 struct smb_filename smb_fname_base;
5594 uint32 action =
5595 FILE_NOTIFY_CHANGE_LAST_ACCESS
5596 |FILE_NOTIFY_CHANGE_LAST_WRITE
5597 |FILE_NOTIFY_CHANGE_CREATION;
5599 if (!VALID_STAT(smb_fname->st)) {
5600 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5603 /* get some defaults (no modifications) if any info is zero or -1. */
5604 if (null_timespec(ft->create_time)) {
5605 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5608 if (null_timespec(ft->atime)) {
5609 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5612 if (null_timespec(ft->mtime)) {
5613 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5616 if (!setting_write_time) {
5617 /* ft->mtime comes from change time, not write time. */
5618 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5621 /* Ensure the resolution is the correct for
5622 * what we can store on this filesystem. */
5624 round_timespec(conn->ts_res, &ft->create_time);
5625 round_timespec(conn->ts_res, &ft->ctime);
5626 round_timespec(conn->ts_res, &ft->atime);
5627 round_timespec(conn->ts_res, &ft->mtime);
5629 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5630 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5631 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5632 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5633 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5634 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5635 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5636 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5638 if (setting_write_time) {
5640 * This was a Windows setfileinfo on an open file.
5641 * NT does this a lot. We also need to
5642 * set the time here, as it can be read by
5643 * FindFirst/FindNext and with the patch for bug #2045
5644 * in smbd/fileio.c it ensures that this timestamp is
5645 * kept sticky even after a write. We save the request
5646 * away and will set it on file close and after a write. JRA.
5649 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5650 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5652 if (fsp != NULL) {
5653 if (fsp->base_fsp) {
5654 set_sticky_write_time_fsp(fsp->base_fsp,
5655 ft->mtime);
5656 } else {
5657 set_sticky_write_time_fsp(fsp, ft->mtime);
5659 } else {
5660 set_sticky_write_time_path(
5661 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5662 ft->mtime);
5666 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5668 /* Always call ntimes on the base, even if a stream was passed in. */
5669 smb_fname_base = *smb_fname;
5670 smb_fname_base.stream_name = NULL;
5672 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5673 return map_nt_error_from_unix(errno);
5676 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5677 smb_fname->base_name);
5678 return NT_STATUS_OK;
5681 /****************************************************************************
5682 Deal with setting the dosmode from any of the setfilepathinfo functions.
5683 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5684 done before calling this function.
5685 ****************************************************************************/
5687 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5688 const struct smb_filename *smb_fname,
5689 uint32 dosmode)
5691 struct smb_filename *smb_fname_base = NULL;
5692 NTSTATUS status;
5694 if (!VALID_STAT(smb_fname->st)) {
5695 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5698 /* Always operate on the base_name, even if a stream was passed in. */
5699 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5700 NULL, &smb_fname->st,
5701 &smb_fname_base);
5702 if (!NT_STATUS_IS_OK(status)) {
5703 return status;
5706 if (dosmode) {
5707 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5708 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5709 } else {
5710 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5714 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5716 /* check the mode isn't different, before changing it */
5717 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5718 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5719 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5720 (unsigned int)dosmode));
5722 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5723 false)) {
5724 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5725 "%s failed (%s)\n",
5726 smb_fname_str_dbg(smb_fname_base),
5727 strerror(errno)));
5728 status = map_nt_error_from_unix(errno);
5729 goto out;
5732 status = NT_STATUS_OK;
5733 out:
5734 TALLOC_FREE(smb_fname_base);
5735 return status;
5738 /****************************************************************************
5739 Deal with setting the size from any of the setfilepathinfo functions.
5740 ****************************************************************************/
5742 static NTSTATUS smb_set_file_size(connection_struct *conn,
5743 struct smb_request *req,
5744 files_struct *fsp,
5745 const struct smb_filename *smb_fname,
5746 const SMB_STRUCT_STAT *psbuf,
5747 off_t size,
5748 bool fail_after_createfile)
5750 NTSTATUS status = NT_STATUS_OK;
5751 struct smb_filename *smb_fname_tmp = NULL;
5752 files_struct *new_fsp = NULL;
5754 if (!VALID_STAT(*psbuf)) {
5755 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5758 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5760 if (size == get_file_size_stat(psbuf)) {
5761 return NT_STATUS_OK;
5764 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5765 smb_fname_str_dbg(smb_fname), (double)size));
5767 if (fsp && fsp->fh->fd != -1) {
5768 /* Handle based call. */
5769 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5770 return NT_STATUS_ACCESS_DENIED;
5773 if (vfs_set_filelen(fsp, size) == -1) {
5774 return map_nt_error_from_unix(errno);
5776 trigger_write_time_update_immediate(fsp);
5777 return NT_STATUS_OK;
5780 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5781 if (!NT_STATUS_IS_OK(status)) {
5782 return status;
5785 smb_fname_tmp->st = *psbuf;
5787 status = SMB_VFS_CREATE_FILE(
5788 conn, /* conn */
5789 req, /* req */
5790 0, /* root_dir_fid */
5791 smb_fname_tmp, /* fname */
5792 FILE_WRITE_DATA, /* access_mask */
5793 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5794 FILE_SHARE_DELETE),
5795 FILE_OPEN, /* create_disposition*/
5796 0, /* create_options */
5797 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5798 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5799 0, /* allocation_size */
5800 0, /* private_flags */
5801 NULL, /* sd */
5802 NULL, /* ea_list */
5803 &new_fsp, /* result */
5804 NULL); /* pinfo */
5806 TALLOC_FREE(smb_fname_tmp);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 /* NB. We check for open_was_deferred in the caller. */
5810 return status;
5813 /* See RAW-SFILEINFO-END-OF-FILE */
5814 if (fail_after_createfile) {
5815 close_file(req, new_fsp,NORMAL_CLOSE);
5816 return NT_STATUS_INVALID_LEVEL;
5819 if (vfs_set_filelen(new_fsp, size) == -1) {
5820 status = map_nt_error_from_unix(errno);
5821 close_file(req, new_fsp,NORMAL_CLOSE);
5822 return status;
5825 trigger_write_time_update_immediate(new_fsp);
5826 close_file(req, new_fsp,NORMAL_CLOSE);
5827 return NT_STATUS_OK;
5830 /****************************************************************************
5831 Deal with SMB_INFO_SET_EA.
5832 ****************************************************************************/
5834 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5835 const char *pdata,
5836 int total_data,
5837 files_struct *fsp,
5838 const struct smb_filename *smb_fname)
5840 struct ea_list *ea_list = NULL;
5841 TALLOC_CTX *ctx = NULL;
5842 NTSTATUS status = NT_STATUS_OK;
5844 if (total_data < 10) {
5846 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5847 length. They seem to have no effect. Bug #3212. JRA */
5849 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5850 /* We're done. We only get EA info in this call. */
5851 return NT_STATUS_OK;
5854 return NT_STATUS_INVALID_PARAMETER;
5857 if (IVAL(pdata,0) > total_data) {
5858 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5859 IVAL(pdata,0), (unsigned int)total_data));
5860 return NT_STATUS_INVALID_PARAMETER;
5863 ctx = talloc_tos();
5864 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5865 if (!ea_list) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 status = set_ea(conn, fsp, smb_fname, ea_list);
5871 return status;
5874 /****************************************************************************
5875 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5876 ****************************************************************************/
5878 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5879 const char *pdata,
5880 int total_data,
5881 files_struct *fsp)
5883 struct ea_list *ea_list = NULL;
5884 NTSTATUS status;
5886 if (!fsp) {
5887 return NT_STATUS_INVALID_HANDLE;
5890 if (!lp_ea_support(SNUM(conn))) {
5891 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5892 "EA's not supported.\n",
5893 (unsigned int)total_data));
5894 return NT_STATUS_EAS_NOT_SUPPORTED;
5897 if (total_data < 10) {
5898 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5899 "too small.\n",
5900 (unsigned int)total_data));
5901 return NT_STATUS_INVALID_PARAMETER;
5904 ea_list = read_nttrans_ea_list(talloc_tos(),
5905 pdata,
5906 total_data);
5908 if (!ea_list) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5914 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5915 smb_fname_str_dbg(fsp->fsp_name),
5916 nt_errstr(status) ));
5918 return status;
5922 /****************************************************************************
5923 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5924 ****************************************************************************/
5926 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5927 const char *pdata,
5928 int total_data,
5929 files_struct *fsp,
5930 struct smb_filename *smb_fname)
5932 NTSTATUS status = NT_STATUS_OK;
5933 bool delete_on_close;
5934 uint32 dosmode = 0;
5936 if (total_data < 1) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 if (fsp == NULL) {
5941 return NT_STATUS_INVALID_HANDLE;
5944 delete_on_close = (CVAL(pdata,0) ? True : False);
5945 dosmode = dos_mode(conn, smb_fname);
5947 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5948 "delete_on_close = %u\n",
5949 smb_fname_str_dbg(smb_fname),
5950 (unsigned int)dosmode,
5951 (unsigned int)delete_on_close ));
5953 if (delete_on_close) {
5954 status = can_set_delete_on_close(fsp, dosmode);
5955 if (!NT_STATUS_IS_OK(status)) {
5956 return status;
5960 /* The set is across all open files on this dev/inode pair. */
5961 if (!set_delete_on_close(fsp, delete_on_close,
5962 conn->session_info->security_token,
5963 conn->session_info->unix_token)) {
5964 return NT_STATUS_ACCESS_DENIED;
5966 return NT_STATUS_OK;
5969 /****************************************************************************
5970 Deal with SMB_FILE_POSITION_INFORMATION.
5971 ****************************************************************************/
5973 static NTSTATUS smb_file_position_information(connection_struct *conn,
5974 const char *pdata,
5975 int total_data,
5976 files_struct *fsp)
5978 uint64_t position_information;
5980 if (total_data < 8) {
5981 return NT_STATUS_INVALID_PARAMETER;
5984 if (fsp == NULL) {
5985 /* Ignore on pathname based set. */
5986 return NT_STATUS_OK;
5989 position_information = (uint64_t)IVAL(pdata,0);
5990 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5992 DEBUG(10,("smb_file_position_information: Set file position "
5993 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5994 (double)position_information));
5995 fsp->fh->position_information = position_information;
5996 return NT_STATUS_OK;
5999 /****************************************************************************
6000 Deal with SMB_FILE_MODE_INFORMATION.
6001 ****************************************************************************/
6003 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6004 const char *pdata,
6005 int total_data)
6007 uint32 mode;
6009 if (total_data < 4) {
6010 return NT_STATUS_INVALID_PARAMETER;
6012 mode = IVAL(pdata,0);
6013 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6014 return NT_STATUS_INVALID_PARAMETER;
6016 return NT_STATUS_OK;
6019 /****************************************************************************
6020 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6021 ****************************************************************************/
6023 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6024 struct smb_request *req,
6025 const char *pdata,
6026 int total_data,
6027 const struct smb_filename *smb_fname)
6029 char *link_target = NULL;
6030 const char *newname = smb_fname->base_name;
6031 TALLOC_CTX *ctx = talloc_tos();
6033 /* Set a symbolic link. */
6034 /* Don't allow this if follow links is false. */
6036 if (total_data == 0) {
6037 return NT_STATUS_INVALID_PARAMETER;
6040 if (!lp_symlinks(SNUM(conn))) {
6041 return NT_STATUS_ACCESS_DENIED;
6044 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6045 total_data, STR_TERMINATE);
6047 if (!link_target) {
6048 return NT_STATUS_INVALID_PARAMETER;
6051 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6052 newname, link_target ));
6054 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6055 return map_nt_error_from_unix(errno);
6058 return NT_STATUS_OK;
6061 /****************************************************************************
6062 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6063 ****************************************************************************/
6065 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6066 struct smb_request *req,
6067 const char *pdata, int total_data,
6068 struct smb_filename *smb_fname_new)
6070 char *oldname = NULL;
6071 struct smb_filename *smb_fname_old = NULL;
6072 TALLOC_CTX *ctx = talloc_tos();
6073 NTSTATUS status = NT_STATUS_OK;
6075 /* Set a hard link. */
6076 if (total_data == 0) {
6077 return NT_STATUS_INVALID_PARAMETER;
6080 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6081 total_data, STR_TERMINATE, &status);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 return status;
6086 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6087 smb_fname_str_dbg(smb_fname_new), oldname));
6089 status = filename_convert(ctx,
6090 conn,
6091 req->flags2 & FLAGS2_DFS_PATHNAMES,
6092 oldname,
6094 NULL,
6095 &smb_fname_old);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 return status;
6100 return hardlink_internals(ctx, conn, req, false,
6101 smb_fname_old, smb_fname_new);
6104 /****************************************************************************
6105 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6106 ****************************************************************************/
6108 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6109 struct smb_request *req,
6110 const char *pdata,
6111 int total_data,
6112 files_struct *fsp,
6113 struct smb_filename *smb_fname_src)
6115 bool overwrite;
6116 uint32_t len;
6117 char *newname = NULL;
6118 struct smb_filename *smb_fname_dst = NULL;
6119 NTSTATUS status = NT_STATUS_OK;
6120 TALLOC_CTX *ctx = talloc_tos();
6122 if (!fsp) {
6123 return NT_STATUS_INVALID_HANDLE;
6126 if (total_data < 20) {
6127 return NT_STATUS_INVALID_PARAMETER;
6130 overwrite = (CVAL(pdata,0) ? True : False);
6131 len = IVAL(pdata,16);
6133 if (len > (total_data - 20) || (len == 0)) {
6134 return NT_STATUS_INVALID_PARAMETER;
6137 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6138 &pdata[20], len, STR_TERMINATE,
6139 &status);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 return status;
6144 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6145 newname));
6147 status = filename_convert(ctx,
6148 conn,
6149 req->flags2 & FLAGS2_DFS_PATHNAMES,
6150 newname,
6151 UCF_SAVE_LCOMP,
6152 NULL,
6153 &smb_fname_dst);
6154 if (!NT_STATUS_IS_OK(status)) {
6155 return status;
6158 if (fsp->base_fsp) {
6159 /* newname must be a stream name. */
6160 if (newname[0] != ':') {
6161 return NT_STATUS_NOT_SUPPORTED;
6164 /* Create an smb_fname to call rename_internals_fsp() with. */
6165 status = create_synthetic_smb_fname(talloc_tos(),
6166 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6167 &smb_fname_dst);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 goto out;
6173 * Set the original last component, since
6174 * rename_internals_fsp() requires it.
6176 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6177 newname);
6178 if (smb_fname_dst->original_lcomp == NULL) {
6179 status = NT_STATUS_NO_MEMORY;
6180 goto out;
6185 DEBUG(10,("smb2_file_rename_information: "
6186 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6187 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6188 smb_fname_str_dbg(smb_fname_dst)));
6189 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6190 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6191 overwrite);
6193 out:
6194 TALLOC_FREE(smb_fname_dst);
6195 return status;
6198 static NTSTATUS smb_file_link_information(connection_struct *conn,
6199 struct smb_request *req,
6200 const char *pdata,
6201 int total_data,
6202 files_struct *fsp,
6203 struct smb_filename *smb_fname_src)
6205 bool overwrite;
6206 uint32_t len;
6207 char *newname = NULL;
6208 struct smb_filename *smb_fname_dst = NULL;
6209 NTSTATUS status = NT_STATUS_OK;
6210 TALLOC_CTX *ctx = talloc_tos();
6212 if (!fsp) {
6213 return NT_STATUS_INVALID_HANDLE;
6216 if (total_data < 20) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 overwrite = (CVAL(pdata,0) ? true : false);
6221 len = IVAL(pdata,16);
6223 if (len > (total_data - 20) || (len == 0)) {
6224 return NT_STATUS_INVALID_PARAMETER;
6227 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6228 &pdata[20], len, STR_TERMINATE,
6229 &status);
6230 if (!NT_STATUS_IS_OK(status)) {
6231 return status;
6234 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6235 newname));
6237 status = filename_convert(ctx,
6238 conn,
6239 req->flags2 & FLAGS2_DFS_PATHNAMES,
6240 newname,
6241 UCF_SAVE_LCOMP,
6242 NULL,
6243 &smb_fname_dst);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 return status;
6248 if (fsp->base_fsp) {
6249 /* No stream names. */
6250 return NT_STATUS_NOT_SUPPORTED;
6253 DEBUG(10,("smb_file_link_information: "
6254 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6255 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6256 smb_fname_str_dbg(smb_fname_dst)));
6257 status = hardlink_internals(ctx,
6258 conn,
6259 req,
6260 overwrite,
6261 fsp->fsp_name,
6262 smb_fname_dst);
6264 TALLOC_FREE(smb_fname_dst);
6265 return status;
6268 /****************************************************************************
6269 Deal with SMB_FILE_RENAME_INFORMATION.
6270 ****************************************************************************/
6272 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6273 struct smb_request *req,
6274 const char *pdata,
6275 int total_data,
6276 files_struct *fsp,
6277 struct smb_filename *smb_fname_src)
6279 bool overwrite;
6280 uint32 root_fid;
6281 uint32 len;
6282 char *newname = NULL;
6283 struct smb_filename *smb_fname_dst = NULL;
6284 bool dest_has_wcard = False;
6285 NTSTATUS status = NT_STATUS_OK;
6286 char *p;
6287 TALLOC_CTX *ctx = talloc_tos();
6289 if (total_data < 13) {
6290 return NT_STATUS_INVALID_PARAMETER;
6293 overwrite = (CVAL(pdata,0) ? True : False);
6294 root_fid = IVAL(pdata,4);
6295 len = IVAL(pdata,8);
6297 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6302 len, 0, &status,
6303 &dest_has_wcard);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 return status;
6308 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6309 newname));
6311 status = resolve_dfspath_wcard(ctx, conn,
6312 req->flags2 & FLAGS2_DFS_PATHNAMES,
6313 newname,
6314 true,
6315 !conn->sconn->using_smb2,
6316 &newname,
6317 &dest_has_wcard);
6318 if (!NT_STATUS_IS_OK(status)) {
6319 return status;
6322 /* Check the new name has no '/' characters. */
6323 if (strchr_m(newname, '/')) {
6324 return NT_STATUS_NOT_SUPPORTED;
6327 if (fsp && fsp->base_fsp) {
6328 /* newname must be a stream name. */
6329 if (newname[0] != ':') {
6330 return NT_STATUS_NOT_SUPPORTED;
6333 /* Create an smb_fname to call rename_internals_fsp() with. */
6334 status = create_synthetic_smb_fname(talloc_tos(),
6335 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6336 &smb_fname_dst);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 goto out;
6342 * Set the original last component, since
6343 * rename_internals_fsp() requires it.
6345 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6346 newname);
6347 if (smb_fname_dst->original_lcomp == NULL) {
6348 status = NT_STATUS_NO_MEMORY;
6349 goto out;
6352 } else {
6354 * Build up an smb_fname_dst based on the filename passed in.
6355 * We basically just strip off the last component, and put on
6356 * the newname instead.
6358 char *base_name = NULL;
6360 /* newname must *not* be a stream name. */
6361 if (newname[0] == ':') {
6362 return NT_STATUS_NOT_SUPPORTED;
6366 * Strip off the last component (filename) of the path passed
6367 * in.
6369 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6370 if (!base_name) {
6371 return NT_STATUS_NO_MEMORY;
6373 p = strrchr_m(base_name, '/');
6374 if (p) {
6375 p[1] = '\0';
6376 } else {
6377 base_name = talloc_strdup(ctx, "");
6378 if (!base_name) {
6379 return NT_STATUS_NO_MEMORY;
6382 /* Append the new name. */
6383 base_name = talloc_asprintf_append(base_name,
6384 "%s",
6385 newname);
6386 if (!base_name) {
6387 return NT_STATUS_NO_MEMORY;
6390 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6391 (UCF_SAVE_LCOMP |
6392 (dest_has_wcard ?
6393 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6394 0)));
6396 /* If an error we expect this to be
6397 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6399 if (!NT_STATUS_IS_OK(status)) {
6400 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6401 status)) {
6402 goto out;
6404 /* Create an smb_fname to call rename_internals_fsp() */
6405 status = create_synthetic_smb_fname(ctx,
6406 base_name, NULL,
6407 NULL,
6408 &smb_fname_dst);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 goto out;
6415 if (fsp) {
6416 DEBUG(10,("smb_file_rename_information: "
6417 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6418 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6419 smb_fname_str_dbg(smb_fname_dst)));
6420 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6421 overwrite);
6422 } else {
6423 DEBUG(10,("smb_file_rename_information: "
6424 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6425 smb_fname_str_dbg(smb_fname_src),
6426 smb_fname_str_dbg(smb_fname_dst)));
6427 status = rename_internals(ctx, conn, req, smb_fname_src,
6428 smb_fname_dst, 0, overwrite, false,
6429 dest_has_wcard,
6430 FILE_WRITE_ATTRIBUTES);
6432 out:
6433 TALLOC_FREE(smb_fname_dst);
6434 return status;
6437 /****************************************************************************
6438 Deal with SMB_SET_POSIX_ACL.
6439 ****************************************************************************/
6441 #if defined(HAVE_POSIX_ACLS)
6442 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6443 const char *pdata,
6444 int total_data,
6445 files_struct *fsp,
6446 const struct smb_filename *smb_fname)
6448 uint16 posix_acl_version;
6449 uint16 num_file_acls;
6450 uint16 num_def_acls;
6451 bool valid_file_acls = True;
6452 bool valid_def_acls = True;
6454 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6455 return NT_STATUS_INVALID_PARAMETER;
6457 posix_acl_version = SVAL(pdata,0);
6458 num_file_acls = SVAL(pdata,2);
6459 num_def_acls = SVAL(pdata,4);
6461 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6462 valid_file_acls = False;
6463 num_file_acls = 0;
6466 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6467 valid_def_acls = False;
6468 num_def_acls = 0;
6471 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6472 return NT_STATUS_INVALID_PARAMETER;
6475 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6476 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6477 return NT_STATUS_INVALID_PARAMETER;
6480 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6481 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6482 (unsigned int)num_file_acls,
6483 (unsigned int)num_def_acls));
6485 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6486 smb_fname->base_name, num_file_acls,
6487 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6488 return map_nt_error_from_unix(errno);
6491 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6492 smb_fname->base_name, &smb_fname->st, num_def_acls,
6493 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6494 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6495 return map_nt_error_from_unix(errno);
6497 return NT_STATUS_OK;
6499 #endif
6501 /****************************************************************************
6502 Deal with SMB_SET_POSIX_LOCK.
6503 ****************************************************************************/
6505 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6506 struct smb_request *req,
6507 const char *pdata,
6508 int total_data,
6509 files_struct *fsp)
6511 uint64_t count;
6512 uint64_t offset;
6513 uint64_t smblctx;
6514 bool blocking_lock = False;
6515 enum brl_type lock_type;
6517 NTSTATUS status = NT_STATUS_OK;
6519 if (fsp == NULL || fsp->fh->fd == -1) {
6520 return NT_STATUS_INVALID_HANDLE;
6523 if (total_data != POSIX_LOCK_DATA_SIZE) {
6524 return NT_STATUS_INVALID_PARAMETER;
6527 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6528 case POSIX_LOCK_TYPE_READ:
6529 lock_type = READ_LOCK;
6530 break;
6531 case POSIX_LOCK_TYPE_WRITE:
6532 /* Return the right POSIX-mappable error code for files opened read-only. */
6533 if (!fsp->can_write) {
6534 return NT_STATUS_INVALID_HANDLE;
6536 lock_type = WRITE_LOCK;
6537 break;
6538 case POSIX_LOCK_TYPE_UNLOCK:
6539 lock_type = UNLOCK_LOCK;
6540 break;
6541 default:
6542 return NT_STATUS_INVALID_PARAMETER;
6545 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6546 blocking_lock = False;
6547 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6548 blocking_lock = True;
6549 } else {
6550 return NT_STATUS_INVALID_PARAMETER;
6553 if (!lp_blocking_locks(SNUM(conn))) {
6554 blocking_lock = False;
6557 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6558 #if defined(HAVE_LONGLONG)
6559 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6560 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6561 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6562 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6563 #else /* HAVE_LONGLONG */
6564 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6565 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6566 #endif /* HAVE_LONGLONG */
6568 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6569 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6570 fsp_str_dbg(fsp),
6571 (unsigned int)lock_type,
6572 (unsigned long long)smblctx,
6573 (double)count,
6574 (double)offset ));
6576 if (lock_type == UNLOCK_LOCK) {
6577 status = do_unlock(req->sconn->msg_ctx,
6578 fsp,
6579 smblctx,
6580 count,
6581 offset,
6582 POSIX_LOCK);
6583 } else {
6584 uint64_t block_smblctx;
6586 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6587 fsp,
6588 smblctx,
6589 count,
6590 offset,
6591 lock_type,
6592 POSIX_LOCK,
6593 blocking_lock,
6594 &status,
6595 &block_smblctx,
6596 NULL);
6598 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6600 * A blocking lock was requested. Package up
6601 * this smb into a queued request and push it
6602 * onto the blocking lock queue.
6604 if(push_blocking_lock_request(br_lck,
6605 req,
6606 fsp,
6607 -1, /* infinite timeout. */
6609 smblctx,
6610 lock_type,
6611 POSIX_LOCK,
6612 offset,
6613 count,
6614 block_smblctx)) {
6615 TALLOC_FREE(br_lck);
6616 return status;
6619 TALLOC_FREE(br_lck);
6622 return status;
6625 /****************************************************************************
6626 Deal with SMB_SET_FILE_BASIC_INFO.
6627 ****************************************************************************/
6629 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6630 const char *pdata,
6631 int total_data,
6632 files_struct *fsp,
6633 const struct smb_filename *smb_fname)
6635 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6636 struct smb_file_time ft;
6637 uint32 dosmode = 0;
6638 NTSTATUS status = NT_STATUS_OK;
6640 ZERO_STRUCT(ft);
6642 if (total_data < 36) {
6643 return NT_STATUS_INVALID_PARAMETER;
6646 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6647 if (!NT_STATUS_IS_OK(status)) {
6648 return status;
6651 /* Set the attributes */
6652 dosmode = IVAL(pdata,32);
6653 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6654 if (!NT_STATUS_IS_OK(status)) {
6655 return status;
6658 /* create time */
6659 ft.create_time = interpret_long_date(pdata);
6661 /* access time */
6662 ft.atime = interpret_long_date(pdata+8);
6664 /* write time. */
6665 ft.mtime = interpret_long_date(pdata+16);
6667 /* change time. */
6668 ft.ctime = interpret_long_date(pdata+24);
6670 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6671 smb_fname_str_dbg(smb_fname)));
6673 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6674 true);
6677 /****************************************************************************
6678 Deal with SMB_INFO_STANDARD.
6679 ****************************************************************************/
6681 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6682 const char *pdata,
6683 int total_data,
6684 files_struct *fsp,
6685 const struct smb_filename *smb_fname)
6687 NTSTATUS status;
6688 struct smb_file_time ft;
6690 ZERO_STRUCT(ft);
6692 if (total_data < 12) {
6693 return NT_STATUS_INVALID_PARAMETER;
6696 /* create time */
6697 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6698 /* access time */
6699 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6700 /* write time */
6701 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6703 DEBUG(10,("smb_set_info_standard: file %s\n",
6704 smb_fname_str_dbg(smb_fname)));
6706 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 return status;
6711 return smb_set_file_time(conn,
6712 fsp,
6713 smb_fname,
6714 &ft,
6715 true);
6718 /****************************************************************************
6719 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6720 ****************************************************************************/
6722 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6723 struct smb_request *req,
6724 const char *pdata,
6725 int total_data,
6726 files_struct *fsp,
6727 struct smb_filename *smb_fname)
6729 uint64_t allocation_size = 0;
6730 NTSTATUS status = NT_STATUS_OK;
6731 files_struct *new_fsp = NULL;
6733 if (!VALID_STAT(smb_fname->st)) {
6734 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6737 if (total_data < 8) {
6738 return NT_STATUS_INVALID_PARAMETER;
6741 allocation_size = (uint64_t)IVAL(pdata,0);
6742 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6743 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6744 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6745 (double)allocation_size));
6747 if (allocation_size) {
6748 allocation_size = smb_roundup(conn, allocation_size);
6751 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6752 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6753 (double)allocation_size));
6755 if (fsp && fsp->fh->fd != -1) {
6756 /* Open file handle. */
6757 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6758 return NT_STATUS_ACCESS_DENIED;
6761 /* Only change if needed. */
6762 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6763 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6764 return map_nt_error_from_unix(errno);
6767 /* But always update the time. */
6769 * This is equivalent to a write. Ensure it's seen immediately
6770 * if there are no pending writes.
6772 trigger_write_time_update_immediate(fsp);
6773 return NT_STATUS_OK;
6776 /* Pathname or stat or directory file. */
6777 status = SMB_VFS_CREATE_FILE(
6778 conn, /* conn */
6779 req, /* req */
6780 0, /* root_dir_fid */
6781 smb_fname, /* fname */
6782 FILE_WRITE_DATA, /* access_mask */
6783 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6784 FILE_SHARE_DELETE),
6785 FILE_OPEN, /* create_disposition*/
6786 0, /* create_options */
6787 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6788 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6789 0, /* allocation_size */
6790 0, /* private_flags */
6791 NULL, /* sd */
6792 NULL, /* ea_list */
6793 &new_fsp, /* result */
6794 NULL); /* pinfo */
6796 if (!NT_STATUS_IS_OK(status)) {
6797 /* NB. We check for open_was_deferred in the caller. */
6798 return status;
6801 /* Only change if needed. */
6802 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6803 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6804 status = map_nt_error_from_unix(errno);
6805 close_file(req, new_fsp, NORMAL_CLOSE);
6806 return status;
6810 /* Changing the allocation size should set the last mod time. */
6812 * This is equivalent to a write. Ensure it's seen immediately
6813 * if there are no pending writes.
6815 trigger_write_time_update_immediate(new_fsp);
6817 close_file(req, new_fsp, NORMAL_CLOSE);
6818 return NT_STATUS_OK;
6821 /****************************************************************************
6822 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6823 ****************************************************************************/
6825 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6826 struct smb_request *req,
6827 const char *pdata,
6828 int total_data,
6829 files_struct *fsp,
6830 const struct smb_filename *smb_fname,
6831 bool fail_after_createfile)
6833 off_t size;
6835 if (total_data < 8) {
6836 return NT_STATUS_INVALID_PARAMETER;
6839 size = IVAL(pdata,0);
6840 size |= (((off_t)IVAL(pdata,4)) << 32);
6841 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6842 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6843 (double)size));
6845 return smb_set_file_size(conn, req,
6846 fsp,
6847 smb_fname,
6848 &smb_fname->st,
6849 size,
6850 fail_after_createfile);
6853 /****************************************************************************
6854 Allow a UNIX info mknod.
6855 ****************************************************************************/
6857 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6858 const char *pdata,
6859 int total_data,
6860 const struct smb_filename *smb_fname)
6862 uint32 file_type = IVAL(pdata,56);
6863 #if defined(HAVE_MAKEDEV)
6864 uint32 dev_major = IVAL(pdata,60);
6865 uint32 dev_minor = IVAL(pdata,68);
6866 #endif
6867 SMB_DEV_T dev = (SMB_DEV_T)0;
6868 uint32 raw_unixmode = IVAL(pdata,84);
6869 NTSTATUS status;
6870 mode_t unixmode;
6872 if (total_data < 100) {
6873 return NT_STATUS_INVALID_PARAMETER;
6876 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6877 PERM_NEW_FILE, &unixmode);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 return status;
6882 #if defined(HAVE_MAKEDEV)
6883 dev = makedev(dev_major, dev_minor);
6884 #endif
6886 switch (file_type) {
6887 #if defined(S_IFIFO)
6888 case UNIX_TYPE_FIFO:
6889 unixmode |= S_IFIFO;
6890 break;
6891 #endif
6892 #if defined(S_IFSOCK)
6893 case UNIX_TYPE_SOCKET:
6894 unixmode |= S_IFSOCK;
6895 break;
6896 #endif
6897 #if defined(S_IFCHR)
6898 case UNIX_TYPE_CHARDEV:
6899 unixmode |= S_IFCHR;
6900 break;
6901 #endif
6902 #if defined(S_IFBLK)
6903 case UNIX_TYPE_BLKDEV:
6904 unixmode |= S_IFBLK;
6905 break;
6906 #endif
6907 default:
6908 return NT_STATUS_INVALID_PARAMETER;
6911 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6912 "%.0f mode 0%o for file %s\n", (double)dev,
6913 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6915 /* Ok - do the mknod. */
6916 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6917 return map_nt_error_from_unix(errno);
6920 /* If any of the other "set" calls fail we
6921 * don't want to end up with a half-constructed mknod.
6924 if (lp_inherit_perms(SNUM(conn))) {
6925 char *parent;
6926 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6927 &parent, NULL)) {
6928 return NT_STATUS_NO_MEMORY;
6930 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6931 unixmode);
6932 TALLOC_FREE(parent);
6935 return NT_STATUS_OK;
6938 /****************************************************************************
6939 Deal with SMB_SET_FILE_UNIX_BASIC.
6940 ****************************************************************************/
6942 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6943 struct smb_request *req,
6944 const char *pdata,
6945 int total_data,
6946 files_struct *fsp,
6947 const struct smb_filename *smb_fname)
6949 struct smb_file_time ft;
6950 uint32 raw_unixmode;
6951 mode_t unixmode;
6952 off_t size = 0;
6953 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6954 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6955 NTSTATUS status = NT_STATUS_OK;
6956 bool delete_on_fail = False;
6957 enum perm_type ptype;
6958 files_struct *all_fsps = NULL;
6959 bool modify_mtime = true;
6960 struct file_id id;
6961 struct smb_filename *smb_fname_tmp = NULL;
6962 SMB_STRUCT_STAT sbuf;
6964 ZERO_STRUCT(ft);
6966 if (total_data < 100) {
6967 return NT_STATUS_INVALID_PARAMETER;
6970 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6971 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6972 size=IVAL(pdata,0); /* first 8 Bytes are size */
6973 size |= (((off_t)IVAL(pdata,4)) << 32);
6976 ft.atime = interpret_long_date(pdata+24); /* access_time */
6977 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6978 set_owner = (uid_t)IVAL(pdata,40);
6979 set_grp = (gid_t)IVAL(pdata,48);
6980 raw_unixmode = IVAL(pdata,84);
6982 if (VALID_STAT(smb_fname->st)) {
6983 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6984 ptype = PERM_EXISTING_DIR;
6985 } else {
6986 ptype = PERM_EXISTING_FILE;
6988 } else {
6989 ptype = PERM_NEW_FILE;
6992 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6993 ptype, &unixmode);
6994 if (!NT_STATUS_IS_OK(status)) {
6995 return status;
6998 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6999 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7000 smb_fname_str_dbg(smb_fname), (double)size,
7001 (unsigned int)set_owner, (unsigned int)set_grp,
7002 (int)raw_unixmode));
7004 sbuf = smb_fname->st;
7006 if (!VALID_STAT(sbuf)) {
7008 * The only valid use of this is to create character and block
7009 * devices, and named pipes. This is deprecated (IMHO) and
7010 * a new info level should be used for mknod. JRA.
7013 status = smb_unix_mknod(conn,
7014 pdata,
7015 total_data,
7016 smb_fname);
7017 if (!NT_STATUS_IS_OK(status)) {
7018 return status;
7021 status = copy_smb_filename(talloc_tos(), smb_fname,
7022 &smb_fname_tmp);
7023 if (!NT_STATUS_IS_OK(status)) {
7024 return status;
7027 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7028 status = map_nt_error_from_unix(errno);
7029 TALLOC_FREE(smb_fname_tmp);
7030 SMB_VFS_UNLINK(conn, smb_fname);
7031 return status;
7034 sbuf = smb_fname_tmp->st;
7035 smb_fname = smb_fname_tmp;
7037 /* Ensure we don't try and change anything else. */
7038 raw_unixmode = SMB_MODE_NO_CHANGE;
7039 size = get_file_size_stat(&sbuf);
7040 ft.atime = sbuf.st_ex_atime;
7041 ft.mtime = sbuf.st_ex_mtime;
7043 * We continue here as we might want to change the
7044 * owner uid/gid.
7046 delete_on_fail = True;
7049 #if 1
7050 /* Horrible backwards compatibility hack as an old server bug
7051 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7052 * */
7054 if (!size) {
7055 size = get_file_size_stat(&sbuf);
7057 #endif
7060 * Deal with the UNIX specific mode set.
7063 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7064 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7065 "setting mode 0%o for file %s\n",
7066 (unsigned int)unixmode,
7067 smb_fname_str_dbg(smb_fname)));
7068 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7069 return map_nt_error_from_unix(errno);
7074 * Deal with the UNIX specific uid set.
7077 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7078 (sbuf.st_ex_uid != set_owner)) {
7079 int ret;
7081 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7082 "changing owner %u for path %s\n",
7083 (unsigned int)set_owner,
7084 smb_fname_str_dbg(smb_fname)));
7086 if (S_ISLNK(sbuf.st_ex_mode)) {
7087 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7088 set_owner, (gid_t)-1);
7089 } else {
7090 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7091 set_owner, (gid_t)-1);
7094 if (ret != 0) {
7095 status = map_nt_error_from_unix(errno);
7096 if (delete_on_fail) {
7097 SMB_VFS_UNLINK(conn, smb_fname);
7099 return status;
7104 * Deal with the UNIX specific gid set.
7107 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7108 (sbuf.st_ex_gid != set_grp)) {
7109 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7110 "changing group %u for file %s\n",
7111 (unsigned int)set_owner,
7112 smb_fname_str_dbg(smb_fname)));
7113 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7114 set_grp) != 0) {
7115 status = map_nt_error_from_unix(errno);
7116 if (delete_on_fail) {
7117 SMB_VFS_UNLINK(conn, smb_fname);
7119 return status;
7123 /* Deal with any size changes. */
7125 status = smb_set_file_size(conn, req,
7126 fsp,
7127 smb_fname,
7128 &sbuf,
7129 size,
7130 false);
7131 if (!NT_STATUS_IS_OK(status)) {
7132 return status;
7135 /* Deal with any time changes. */
7136 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7137 /* No change, don't cancel anything. */
7138 return status;
7141 id = vfs_file_id_from_sbuf(conn, &sbuf);
7142 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7143 all_fsps = file_find_di_next(all_fsps)) {
7145 * We're setting the time explicitly for UNIX.
7146 * Cancel any pending changes over all handles.
7148 all_fsps->update_write_time_on_close = false;
7149 TALLOC_FREE(all_fsps->update_write_time_event);
7153 * Override the "setting_write_time"
7154 * parameter here as it almost does what
7155 * we need. Just remember if we modified
7156 * mtime and send the notify ourselves.
7158 if (null_timespec(ft.mtime)) {
7159 modify_mtime = false;
7162 status = smb_set_file_time(conn,
7163 fsp,
7164 smb_fname,
7165 &ft,
7166 false);
7167 if (modify_mtime) {
7168 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7169 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7171 return status;
7174 /****************************************************************************
7175 Deal with SMB_SET_FILE_UNIX_INFO2.
7176 ****************************************************************************/
7178 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7179 struct smb_request *req,
7180 const char *pdata,
7181 int total_data,
7182 files_struct *fsp,
7183 const struct smb_filename *smb_fname)
7185 NTSTATUS status;
7186 uint32 smb_fflags;
7187 uint32 smb_fmask;
7189 if (total_data < 116) {
7190 return NT_STATUS_INVALID_PARAMETER;
7193 /* Start by setting all the fields that are common between UNIX_BASIC
7194 * and UNIX_INFO2.
7196 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7197 fsp, smb_fname);
7198 if (!NT_STATUS_IS_OK(status)) {
7199 return status;
7202 smb_fflags = IVAL(pdata, 108);
7203 smb_fmask = IVAL(pdata, 112);
7205 /* NB: We should only attempt to alter the file flags if the client
7206 * sends a non-zero mask.
7208 if (smb_fmask != 0) {
7209 int stat_fflags = 0;
7211 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7212 smb_fmask, &stat_fflags)) {
7213 /* Client asked to alter a flag we don't understand. */
7214 return NT_STATUS_INVALID_PARAMETER;
7217 if (fsp && fsp->fh->fd != -1) {
7218 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7219 return NT_STATUS_NOT_SUPPORTED;
7220 } else {
7221 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7222 stat_fflags) != 0) {
7223 return map_nt_error_from_unix(errno);
7228 /* XXX: need to add support for changing the create_time here. You
7229 * can do this for paths on Darwin with setattrlist(2). The right way
7230 * to hook this up is probably by extending the VFS utimes interface.
7233 return NT_STATUS_OK;
7236 /****************************************************************************
7237 Create a directory with POSIX semantics.
7238 ****************************************************************************/
7240 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7241 struct smb_request *req,
7242 char **ppdata,
7243 int total_data,
7244 struct smb_filename *smb_fname,
7245 int *pdata_return_size)
7247 NTSTATUS status = NT_STATUS_OK;
7248 uint32 raw_unixmode = 0;
7249 uint32 mod_unixmode = 0;
7250 mode_t unixmode = (mode_t)0;
7251 files_struct *fsp = NULL;
7252 uint16 info_level_return = 0;
7253 int info;
7254 char *pdata = *ppdata;
7256 if (total_data < 18) {
7257 return NT_STATUS_INVALID_PARAMETER;
7260 raw_unixmode = IVAL(pdata,8);
7261 /* Next 4 bytes are not yet defined. */
7263 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7264 PERM_NEW_DIR, &unixmode);
7265 if (!NT_STATUS_IS_OK(status)) {
7266 return status;
7269 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7271 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7272 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7274 status = SMB_VFS_CREATE_FILE(
7275 conn, /* conn */
7276 req, /* req */
7277 0, /* root_dir_fid */
7278 smb_fname, /* fname */
7279 FILE_READ_ATTRIBUTES, /* access_mask */
7280 FILE_SHARE_NONE, /* share_access */
7281 FILE_CREATE, /* create_disposition*/
7282 FILE_DIRECTORY_FILE, /* create_options */
7283 mod_unixmode, /* file_attributes */
7284 0, /* oplock_request */
7285 0, /* allocation_size */
7286 0, /* private_flags */
7287 NULL, /* sd */
7288 NULL, /* ea_list */
7289 &fsp, /* result */
7290 &info); /* pinfo */
7292 if (NT_STATUS_IS_OK(status)) {
7293 close_file(req, fsp, NORMAL_CLOSE);
7296 info_level_return = SVAL(pdata,16);
7298 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7299 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7300 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7301 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7302 } else {
7303 *pdata_return_size = 12;
7306 /* Realloc the data size */
7307 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7308 if (*ppdata == NULL) {
7309 *pdata_return_size = 0;
7310 return NT_STATUS_NO_MEMORY;
7312 pdata = *ppdata;
7314 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7315 SSVAL(pdata,2,0); /* No fnum. */
7316 SIVAL(pdata,4,info); /* Was directory created. */
7318 switch (info_level_return) {
7319 case SMB_QUERY_FILE_UNIX_BASIC:
7320 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7321 SSVAL(pdata,10,0); /* Padding. */
7322 store_file_unix_basic(conn, pdata + 12, fsp,
7323 &smb_fname->st);
7324 break;
7325 case SMB_QUERY_FILE_UNIX_INFO2:
7326 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7327 SSVAL(pdata,10,0); /* Padding. */
7328 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7329 &smb_fname->st);
7330 break;
7331 default:
7332 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7333 SSVAL(pdata,10,0); /* Padding. */
7334 break;
7337 return status;
7340 /****************************************************************************
7341 Open/Create a file with POSIX semantics.
7342 ****************************************************************************/
7344 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7345 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7347 static NTSTATUS smb_posix_open(connection_struct *conn,
7348 struct smb_request *req,
7349 char **ppdata,
7350 int total_data,
7351 struct smb_filename *smb_fname,
7352 int *pdata_return_size)
7354 bool extended_oplock_granted = False;
7355 char *pdata = *ppdata;
7356 uint32 flags = 0;
7357 uint32 wire_open_mode = 0;
7358 uint32 raw_unixmode = 0;
7359 uint32 mod_unixmode = 0;
7360 uint32 create_disp = 0;
7361 uint32 access_mask = 0;
7362 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7363 NTSTATUS status = NT_STATUS_OK;
7364 mode_t unixmode = (mode_t)0;
7365 files_struct *fsp = NULL;
7366 int oplock_request = 0;
7367 int info = 0;
7368 uint16 info_level_return = 0;
7370 if (total_data < 18) {
7371 return NT_STATUS_INVALID_PARAMETER;
7374 flags = IVAL(pdata,0);
7375 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7376 if (oplock_request) {
7377 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7380 wire_open_mode = IVAL(pdata,4);
7382 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7383 return smb_posix_mkdir(conn, req,
7384 ppdata,
7385 total_data,
7386 smb_fname,
7387 pdata_return_size);
7390 switch (wire_open_mode & SMB_ACCMODE) {
7391 case SMB_O_RDONLY:
7392 access_mask = SMB_O_RDONLY_MAPPING;
7393 break;
7394 case SMB_O_WRONLY:
7395 access_mask = SMB_O_WRONLY_MAPPING;
7396 break;
7397 case SMB_O_RDWR:
7398 access_mask = (SMB_O_RDONLY_MAPPING|
7399 SMB_O_WRONLY_MAPPING);
7400 break;
7401 default:
7402 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7403 (unsigned int)wire_open_mode ));
7404 return NT_STATUS_INVALID_PARAMETER;
7407 wire_open_mode &= ~SMB_ACCMODE;
7409 /* First take care of O_CREAT|O_EXCL interactions. */
7410 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7411 case (SMB_O_CREAT | SMB_O_EXCL):
7412 /* File exists fail. File not exist create. */
7413 create_disp = FILE_CREATE;
7414 break;
7415 case SMB_O_CREAT:
7416 /* File exists open. File not exist create. */
7417 create_disp = FILE_OPEN_IF;
7418 break;
7419 case SMB_O_EXCL:
7420 /* O_EXCL on its own without O_CREAT is undefined.
7421 We deliberately ignore it as some versions of
7422 Linux CIFSFS can send a bare O_EXCL on the
7423 wire which other filesystems in the kernel
7424 ignore. See bug 9519 for details. */
7426 /* Fallthrough. */
7428 case 0:
7429 /* File exists open. File not exist fail. */
7430 create_disp = FILE_OPEN;
7431 break;
7432 default:
7433 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7434 (unsigned int)wire_open_mode ));
7435 return NT_STATUS_INVALID_PARAMETER;
7438 /* Next factor in the effects of O_TRUNC. */
7439 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7441 if (wire_open_mode & SMB_O_TRUNC) {
7442 switch (create_disp) {
7443 case FILE_CREATE:
7444 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7445 /* Leave create_disp alone as
7446 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7448 /* File exists fail. File not exist create. */
7449 break;
7450 case FILE_OPEN_IF:
7451 /* SMB_O_CREAT | SMB_O_TRUNC */
7452 /* File exists overwrite. File not exist create. */
7453 create_disp = FILE_OVERWRITE_IF;
7454 break;
7455 case FILE_OPEN:
7456 /* SMB_O_TRUNC */
7457 /* File exists overwrite. File not exist fail. */
7458 create_disp = FILE_OVERWRITE;
7459 break;
7460 default:
7461 /* Cannot get here. */
7462 smb_panic("smb_posix_open: logic error");
7463 return NT_STATUS_INVALID_PARAMETER;
7467 raw_unixmode = IVAL(pdata,8);
7468 /* Next 4 bytes are not yet defined. */
7470 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7471 (VALID_STAT(smb_fname->st) ?
7472 PERM_EXISTING_FILE : PERM_NEW_FILE),
7473 &unixmode);
7475 if (!NT_STATUS_IS_OK(status)) {
7476 return status;
7479 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7481 if (wire_open_mode & SMB_O_SYNC) {
7482 create_options |= FILE_WRITE_THROUGH;
7484 if (wire_open_mode & SMB_O_APPEND) {
7485 access_mask |= FILE_APPEND_DATA;
7487 if (wire_open_mode & SMB_O_DIRECT) {
7488 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7491 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7492 VALID_STAT_OF_DIR(smb_fname->st)) {
7493 if (access_mask != SMB_O_RDONLY_MAPPING) {
7494 return NT_STATUS_FILE_IS_A_DIRECTORY;
7496 create_options &= ~FILE_NON_DIRECTORY_FILE;
7497 create_options |= FILE_DIRECTORY_FILE;
7500 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7501 smb_fname_str_dbg(smb_fname),
7502 (unsigned int)wire_open_mode,
7503 (unsigned int)unixmode ));
7505 status = SMB_VFS_CREATE_FILE(
7506 conn, /* conn */
7507 req, /* req */
7508 0, /* root_dir_fid */
7509 smb_fname, /* fname */
7510 access_mask, /* access_mask */
7511 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7512 FILE_SHARE_DELETE),
7513 create_disp, /* create_disposition*/
7514 create_options, /* create_options */
7515 mod_unixmode, /* file_attributes */
7516 oplock_request, /* oplock_request */
7517 0, /* allocation_size */
7518 0, /* private_flags */
7519 NULL, /* sd */
7520 NULL, /* ea_list */
7521 &fsp, /* result */
7522 &info); /* pinfo */
7524 if (!NT_STATUS_IS_OK(status)) {
7525 return status;
7528 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7529 extended_oplock_granted = True;
7532 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7533 extended_oplock_granted = True;
7536 info_level_return = SVAL(pdata,16);
7538 /* Allocate the correct return size. */
7540 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7541 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7542 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7543 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7544 } else {
7545 *pdata_return_size = 12;
7548 /* Realloc the data size */
7549 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7550 if (*ppdata == NULL) {
7551 close_file(req, fsp, ERROR_CLOSE);
7552 *pdata_return_size = 0;
7553 return NT_STATUS_NO_MEMORY;
7555 pdata = *ppdata;
7557 if (extended_oplock_granted) {
7558 if (flags & REQUEST_BATCH_OPLOCK) {
7559 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7560 } else {
7561 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7563 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7564 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7565 } else {
7566 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7569 SSVAL(pdata,2,fsp->fnum);
7570 SIVAL(pdata,4,info); /* Was file created etc. */
7572 switch (info_level_return) {
7573 case SMB_QUERY_FILE_UNIX_BASIC:
7574 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7575 SSVAL(pdata,10,0); /* padding. */
7576 store_file_unix_basic(conn, pdata + 12, fsp,
7577 &smb_fname->st);
7578 break;
7579 case SMB_QUERY_FILE_UNIX_INFO2:
7580 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7581 SSVAL(pdata,10,0); /* padding. */
7582 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7583 &smb_fname->st);
7584 break;
7585 default:
7586 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7587 SSVAL(pdata,10,0); /* padding. */
7588 break;
7590 return NT_STATUS_OK;
7593 /****************************************************************************
7594 Delete a file with POSIX semantics.
7595 ****************************************************************************/
7597 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7598 struct smb_request *req,
7599 const char *pdata,
7600 int total_data,
7601 struct smb_filename *smb_fname)
7603 NTSTATUS status = NT_STATUS_OK;
7604 files_struct *fsp = NULL;
7605 uint16 flags = 0;
7606 char del = 1;
7607 int info = 0;
7608 int create_options = 0;
7609 int i;
7610 struct share_mode_lock *lck = NULL;
7612 if (total_data < 2) {
7613 return NT_STATUS_INVALID_PARAMETER;
7616 flags = SVAL(pdata,0);
7618 if (!VALID_STAT(smb_fname->st)) {
7619 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7622 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7623 !VALID_STAT_OF_DIR(smb_fname->st)) {
7624 return NT_STATUS_NOT_A_DIRECTORY;
7627 DEBUG(10,("smb_posix_unlink: %s %s\n",
7628 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7629 smb_fname_str_dbg(smb_fname)));
7631 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7632 create_options |= FILE_DIRECTORY_FILE;
7635 status = SMB_VFS_CREATE_FILE(
7636 conn, /* conn */
7637 req, /* req */
7638 0, /* root_dir_fid */
7639 smb_fname, /* fname */
7640 DELETE_ACCESS, /* access_mask */
7641 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7642 FILE_SHARE_DELETE),
7643 FILE_OPEN, /* create_disposition*/
7644 create_options, /* create_options */
7645 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7646 0, /* oplock_request */
7647 0, /* allocation_size */
7648 0, /* private_flags */
7649 NULL, /* sd */
7650 NULL, /* ea_list */
7651 &fsp, /* result */
7652 &info); /* pinfo */
7654 if (!NT_STATUS_IS_OK(status)) {
7655 return status;
7659 * Don't lie to client. If we can't really delete due to
7660 * non-POSIX opens return SHARING_VIOLATION.
7663 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7664 if (lck == NULL) {
7665 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7666 "lock for file %s\n", fsp_str_dbg(fsp)));
7667 close_file(req, fsp, NORMAL_CLOSE);
7668 return NT_STATUS_INVALID_PARAMETER;
7672 * See if others still have the file open. If this is the case, then
7673 * don't delete. If all opens are POSIX delete we can set the delete
7674 * on close disposition.
7676 for (i=0; i<lck->data->num_share_modes; i++) {
7677 struct share_mode_entry *e = &lck->data->share_modes[i];
7678 if (is_valid_share_mode_entry(e)) {
7679 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7680 continue;
7682 if (share_mode_stale_pid(lck->data, i)) {
7683 continue;
7685 /* Fail with sharing violation. */
7686 TALLOC_FREE(lck);
7687 close_file(req, fsp, NORMAL_CLOSE);
7688 return NT_STATUS_SHARING_VIOLATION;
7693 * Set the delete on close.
7695 status = smb_set_file_disposition_info(conn,
7696 &del,
7698 fsp,
7699 smb_fname);
7701 TALLOC_FREE(lck);
7703 if (!NT_STATUS_IS_OK(status)) {
7704 close_file(req, fsp, NORMAL_CLOSE);
7705 return status;
7707 return close_file(req, fsp, NORMAL_CLOSE);
7710 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7711 struct smb_request *req,
7712 TALLOC_CTX *mem_ctx,
7713 uint16_t info_level,
7714 files_struct *fsp,
7715 struct smb_filename *smb_fname,
7716 char **ppdata, int total_data,
7717 int *ret_data_size)
7719 char *pdata = *ppdata;
7720 NTSTATUS status = NT_STATUS_OK;
7721 int data_return_size = 0;
7723 *ret_data_size = 0;
7725 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7726 return NT_STATUS_INVALID_LEVEL;
7729 if (!CAN_WRITE(conn)) {
7730 /* Allow POSIX opens. The open path will deny
7731 * any non-readonly opens. */
7732 if (info_level != SMB_POSIX_PATH_OPEN) {
7733 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7737 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7738 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7739 fsp_fnum_dbg(fsp),
7740 info_level, total_data));
7742 switch (info_level) {
7744 case SMB_INFO_STANDARD:
7746 status = smb_set_info_standard(conn,
7747 pdata,
7748 total_data,
7749 fsp,
7750 smb_fname);
7751 break;
7754 case SMB_INFO_SET_EA:
7756 status = smb_info_set_ea(conn,
7757 pdata,
7758 total_data,
7759 fsp,
7760 smb_fname);
7761 break;
7764 case SMB_SET_FILE_BASIC_INFO:
7765 case SMB_FILE_BASIC_INFORMATION:
7767 status = smb_set_file_basic_info(conn,
7768 pdata,
7769 total_data,
7770 fsp,
7771 smb_fname);
7772 break;
7775 case SMB_FILE_ALLOCATION_INFORMATION:
7776 case SMB_SET_FILE_ALLOCATION_INFO:
7778 status = smb_set_file_allocation_info(conn, req,
7779 pdata,
7780 total_data,
7781 fsp,
7782 smb_fname);
7783 break;
7786 case SMB_FILE_END_OF_FILE_INFORMATION:
7787 case SMB_SET_FILE_END_OF_FILE_INFO:
7790 * XP/Win7 both fail after the createfile with
7791 * SMB_SET_FILE_END_OF_FILE_INFO but not
7792 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7793 * The level is known here, so pass it down
7794 * appropriately.
7796 bool should_fail =
7797 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7799 status = smb_set_file_end_of_file_info(conn, req,
7800 pdata,
7801 total_data,
7802 fsp,
7803 smb_fname,
7804 should_fail);
7805 break;
7808 case SMB_FILE_DISPOSITION_INFORMATION:
7809 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7811 #if 0
7812 /* JRA - We used to just ignore this on a path ?
7813 * Shouldn't this be invalid level on a pathname
7814 * based call ?
7816 if (tran_call != TRANSACT2_SETFILEINFO) {
7817 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7819 #endif
7820 status = smb_set_file_disposition_info(conn,
7821 pdata,
7822 total_data,
7823 fsp,
7824 smb_fname);
7825 break;
7828 case SMB_FILE_POSITION_INFORMATION:
7830 status = smb_file_position_information(conn,
7831 pdata,
7832 total_data,
7833 fsp);
7834 break;
7837 case SMB_FILE_FULL_EA_INFORMATION:
7839 status = smb_set_file_full_ea_info(conn,
7840 pdata,
7841 total_data,
7842 fsp);
7843 break;
7846 /* From tridge Samba4 :
7847 * MODE_INFORMATION in setfileinfo (I have no
7848 * idea what "mode information" on a file is - it takes a value of 0,
7849 * 2, 4 or 6. What could it be?).
7852 case SMB_FILE_MODE_INFORMATION:
7854 status = smb_file_mode_information(conn,
7855 pdata,
7856 total_data);
7857 break;
7861 * CIFS UNIX extensions.
7864 case SMB_SET_FILE_UNIX_BASIC:
7866 status = smb_set_file_unix_basic(conn, req,
7867 pdata,
7868 total_data,
7869 fsp,
7870 smb_fname);
7871 break;
7874 case SMB_SET_FILE_UNIX_INFO2:
7876 status = smb_set_file_unix_info2(conn, req,
7877 pdata,
7878 total_data,
7879 fsp,
7880 smb_fname);
7881 break;
7884 case SMB_SET_FILE_UNIX_LINK:
7886 if (fsp) {
7887 /* We must have a pathname for this. */
7888 return NT_STATUS_INVALID_LEVEL;
7890 status = smb_set_file_unix_link(conn, req, pdata,
7891 total_data, smb_fname);
7892 break;
7895 case SMB_SET_FILE_UNIX_HLINK:
7897 if (fsp) {
7898 /* We must have a pathname for this. */
7899 return NT_STATUS_INVALID_LEVEL;
7901 status = smb_set_file_unix_hlink(conn, req,
7902 pdata, total_data,
7903 smb_fname);
7904 break;
7907 case SMB_FILE_RENAME_INFORMATION:
7909 status = smb_file_rename_information(conn, req,
7910 pdata, total_data,
7911 fsp, smb_fname);
7912 break;
7915 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7917 /* SMB2 rename information. */
7918 status = smb2_file_rename_information(conn, req,
7919 pdata, total_data,
7920 fsp, smb_fname);
7921 break;
7924 case SMB_FILE_LINK_INFORMATION:
7926 status = smb_file_link_information(conn, req,
7927 pdata, total_data,
7928 fsp, smb_fname);
7929 break;
7932 #if defined(HAVE_POSIX_ACLS)
7933 case SMB_SET_POSIX_ACL:
7935 status = smb_set_posix_acl(conn,
7936 pdata,
7937 total_data,
7938 fsp,
7939 smb_fname);
7940 break;
7942 #endif
7944 case SMB_SET_POSIX_LOCK:
7946 if (!fsp) {
7947 return NT_STATUS_INVALID_LEVEL;
7949 status = smb_set_posix_lock(conn, req,
7950 pdata, total_data, fsp);
7951 break;
7954 case SMB_POSIX_PATH_OPEN:
7956 if (fsp) {
7957 /* We must have a pathname for this. */
7958 return NT_STATUS_INVALID_LEVEL;
7961 status = smb_posix_open(conn, req,
7962 ppdata,
7963 total_data,
7964 smb_fname,
7965 &data_return_size);
7966 break;
7969 case SMB_POSIX_PATH_UNLINK:
7971 if (fsp) {
7972 /* We must have a pathname for this. */
7973 return NT_STATUS_INVALID_LEVEL;
7976 status = smb_posix_unlink(conn, req,
7977 pdata,
7978 total_data,
7979 smb_fname);
7980 break;
7983 default:
7984 return NT_STATUS_INVALID_LEVEL;
7987 if (!NT_STATUS_IS_OK(status)) {
7988 return status;
7991 *ret_data_size = data_return_size;
7992 return NT_STATUS_OK;
7995 /****************************************************************************
7996 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7997 ****************************************************************************/
7999 static void call_trans2setfilepathinfo(connection_struct *conn,
8000 struct smb_request *req,
8001 unsigned int tran_call,
8002 char **pparams, int total_params,
8003 char **ppdata, int total_data,
8004 unsigned int max_data_bytes)
8006 char *params = *pparams;
8007 char *pdata = *ppdata;
8008 uint16 info_level;
8009 struct smb_filename *smb_fname = NULL;
8010 files_struct *fsp = NULL;
8011 NTSTATUS status = NT_STATUS_OK;
8012 int data_return_size = 0;
8014 if (!params) {
8015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8016 return;
8019 if (tran_call == TRANSACT2_SETFILEINFO) {
8020 if (total_params < 4) {
8021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8022 return;
8025 fsp = file_fsp(req, SVAL(params,0));
8026 /* Basic check for non-null fsp. */
8027 if (!check_fsp_open(conn, req, fsp)) {
8028 return;
8030 info_level = SVAL(params,2);
8032 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8033 &smb_fname);
8034 if (!NT_STATUS_IS_OK(status)) {
8035 reply_nterror(req, status);
8036 return;
8039 if(fsp->fh->fd == -1) {
8041 * This is actually a SETFILEINFO on a directory
8042 * handle (returned from an NT SMB). NT5.0 seems
8043 * to do this call. JRA.
8045 if (INFO_LEVEL_IS_UNIX(info_level)) {
8046 /* Always do lstat for UNIX calls. */
8047 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8048 DEBUG(3,("call_trans2setfilepathinfo: "
8049 "SMB_VFS_LSTAT of %s failed "
8050 "(%s)\n",
8051 smb_fname_str_dbg(smb_fname),
8052 strerror(errno)));
8053 reply_nterror(req, map_nt_error_from_unix(errno));
8054 return;
8056 } else {
8057 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8058 DEBUG(3,("call_trans2setfilepathinfo: "
8059 "fileinfo of %s failed (%s)\n",
8060 smb_fname_str_dbg(smb_fname),
8061 strerror(errno)));
8062 reply_nterror(req, map_nt_error_from_unix(errno));
8063 return;
8066 } else if (fsp->print_file) {
8068 * Doing a DELETE_ON_CLOSE should cancel a print job.
8070 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8071 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8073 DEBUG(3,("call_trans2setfilepathinfo: "
8074 "Cancelling print job (%s)\n",
8075 fsp_str_dbg(fsp)));
8077 SSVAL(params,0,0);
8078 send_trans2_replies(conn, req, params, 2,
8079 *ppdata, 0,
8080 max_data_bytes);
8081 return;
8082 } else {
8083 reply_nterror(req,
8084 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8085 return;
8087 } else {
8089 * Original code - this is an open file.
8091 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8092 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8093 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8094 strerror(errno)));
8095 reply_nterror(req, map_nt_error_from_unix(errno));
8096 return;
8099 } else {
8100 char *fname = NULL;
8101 uint32_t ucf_flags = 0;
8103 /* set path info */
8104 if (total_params < 7) {
8105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8106 return;
8109 info_level = SVAL(params,0);
8110 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8111 total_params - 6, STR_TERMINATE,
8112 &status);
8113 if (!NT_STATUS_IS_OK(status)) {
8114 reply_nterror(req, status);
8115 return;
8118 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8119 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8120 info_level == SMB_FILE_RENAME_INFORMATION ||
8121 info_level == SMB_POSIX_PATH_UNLINK) {
8122 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8125 status = filename_convert(req, conn,
8126 req->flags2 & FLAGS2_DFS_PATHNAMES,
8127 fname,
8128 ucf_flags,
8129 NULL,
8130 &smb_fname);
8131 if (!NT_STATUS_IS_OK(status)) {
8132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8133 reply_botherror(req,
8134 NT_STATUS_PATH_NOT_COVERED,
8135 ERRSRV, ERRbadpath);
8136 return;
8138 reply_nterror(req, status);
8139 return;
8142 if (INFO_LEVEL_IS_UNIX(info_level)) {
8144 * For CIFS UNIX extensions the target name may not exist.
8147 /* Always do lstat for UNIX calls. */
8148 SMB_VFS_LSTAT(conn, smb_fname);
8150 } else if (!VALID_STAT(smb_fname->st) &&
8151 SMB_VFS_STAT(conn, smb_fname)) {
8152 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8153 "%s failed (%s)\n",
8154 smb_fname_str_dbg(smb_fname),
8155 strerror(errno)));
8156 reply_nterror(req, map_nt_error_from_unix(errno));
8157 return;
8161 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8162 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8163 fsp_fnum_dbg(fsp),
8164 info_level,total_data));
8166 /* Realloc the parameter size */
8167 *pparams = (char *)SMB_REALLOC(*pparams,2);
8168 if (*pparams == NULL) {
8169 reply_nterror(req, NT_STATUS_NO_MEMORY);
8170 return;
8172 params = *pparams;
8174 SSVAL(params,0,0);
8176 status = smbd_do_setfilepathinfo(conn, req, req,
8177 info_level,
8178 fsp,
8179 smb_fname,
8180 ppdata, total_data,
8181 &data_return_size);
8182 if (!NT_STATUS_IS_OK(status)) {
8183 if (open_was_deferred(req->sconn, req->mid)) {
8184 /* We have re-scheduled this call. */
8185 return;
8187 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8188 /* We have re-scheduled this call. */
8189 return;
8191 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8192 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8193 ERRSRV, ERRbadpath);
8194 return;
8196 if (info_level == SMB_POSIX_PATH_OPEN) {
8197 reply_openerror(req, status);
8198 return;
8201 reply_nterror(req, status);
8202 return;
8205 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8206 max_data_bytes);
8208 return;
8211 /****************************************************************************
8212 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8213 ****************************************************************************/
8215 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8216 char **pparams, int total_params,
8217 char **ppdata, int total_data,
8218 unsigned int max_data_bytes)
8220 struct smb_filename *smb_dname = NULL;
8221 char *params = *pparams;
8222 char *pdata = *ppdata;
8223 char *directory = NULL;
8224 NTSTATUS status = NT_STATUS_OK;
8225 struct ea_list *ea_list = NULL;
8226 TALLOC_CTX *ctx = talloc_tos();
8228 if (!CAN_WRITE(conn)) {
8229 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8230 return;
8233 if (total_params < 5) {
8234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8235 return;
8238 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8239 total_params - 4, STR_TERMINATE,
8240 &status);
8241 if (!NT_STATUS_IS_OK(status)) {
8242 reply_nterror(req, status);
8243 return;
8246 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8248 status = filename_convert(ctx,
8249 conn,
8250 req->flags2 & FLAGS2_DFS_PATHNAMES,
8251 directory,
8253 NULL,
8254 &smb_dname);
8256 if (!NT_STATUS_IS_OK(status)) {
8257 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8258 reply_botherror(req,
8259 NT_STATUS_PATH_NOT_COVERED,
8260 ERRSRV, ERRbadpath);
8261 return;
8263 reply_nterror(req, status);
8264 return;
8268 * OS/2 workplace shell seems to send SET_EA requests of "null"
8269 * length (4 bytes containing IVAL 4).
8270 * They seem to have no effect. Bug #3212. JRA.
8273 if (total_data && (total_data != 4)) {
8274 /* Any data in this call is an EA list. */
8275 if (total_data < 10) {
8276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8277 goto out;
8280 if (IVAL(pdata,0) > total_data) {
8281 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8282 IVAL(pdata,0), (unsigned int)total_data));
8283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8284 goto out;
8287 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8288 total_data - 4);
8289 if (!ea_list) {
8290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8291 goto out;
8294 if (!lp_ea_support(SNUM(conn))) {
8295 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8296 goto out;
8299 /* If total_data == 4 Windows doesn't care what values
8300 * are placed in that field, it just ignores them.
8301 * The System i QNTC IBM SMB client puts bad values here,
8302 * so ignore them. */
8304 status = create_directory(conn, req, smb_dname);
8306 if (!NT_STATUS_IS_OK(status)) {
8307 reply_nterror(req, status);
8308 goto out;
8311 /* Try and set any given EA. */
8312 if (ea_list) {
8313 status = set_ea(conn, NULL, smb_dname, ea_list);
8314 if (!NT_STATUS_IS_OK(status)) {
8315 reply_nterror(req, status);
8316 goto out;
8320 /* Realloc the parameter and data sizes */
8321 *pparams = (char *)SMB_REALLOC(*pparams,2);
8322 if(*pparams == NULL) {
8323 reply_nterror(req, NT_STATUS_NO_MEMORY);
8324 goto out;
8326 params = *pparams;
8328 SSVAL(params,0,0);
8330 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8332 out:
8333 TALLOC_FREE(smb_dname);
8334 return;
8337 /****************************************************************************
8338 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8339 We don't actually do this - we just send a null response.
8340 ****************************************************************************/
8342 static void call_trans2findnotifyfirst(connection_struct *conn,
8343 struct smb_request *req,
8344 char **pparams, int total_params,
8345 char **ppdata, int total_data,
8346 unsigned int max_data_bytes)
8348 char *params = *pparams;
8349 uint16 info_level;
8351 if (total_params < 6) {
8352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8353 return;
8356 info_level = SVAL(params,4);
8357 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8359 switch (info_level) {
8360 case 1:
8361 case 2:
8362 break;
8363 default:
8364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8365 return;
8368 /* Realloc the parameter and data sizes */
8369 *pparams = (char *)SMB_REALLOC(*pparams,6);
8370 if (*pparams == NULL) {
8371 reply_nterror(req, NT_STATUS_NO_MEMORY);
8372 return;
8374 params = *pparams;
8376 SSVAL(params,0,fnf_handle);
8377 SSVAL(params,2,0); /* No changes */
8378 SSVAL(params,4,0); /* No EA errors */
8380 fnf_handle++;
8382 if(fnf_handle == 0)
8383 fnf_handle = 257;
8385 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8387 return;
8390 /****************************************************************************
8391 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8392 changes). Currently this does nothing.
8393 ****************************************************************************/
8395 static void call_trans2findnotifynext(connection_struct *conn,
8396 struct smb_request *req,
8397 char **pparams, int total_params,
8398 char **ppdata, int total_data,
8399 unsigned int max_data_bytes)
8401 char *params = *pparams;
8403 DEBUG(3,("call_trans2findnotifynext\n"));
8405 /* Realloc the parameter and data sizes */
8406 *pparams = (char *)SMB_REALLOC(*pparams,4);
8407 if (*pparams == NULL) {
8408 reply_nterror(req, NT_STATUS_NO_MEMORY);
8409 return;
8411 params = *pparams;
8413 SSVAL(params,0,0); /* No changes */
8414 SSVAL(params,2,0); /* No EA errors */
8416 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8418 return;
8421 /****************************************************************************
8422 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8423 ****************************************************************************/
8425 static void call_trans2getdfsreferral(connection_struct *conn,
8426 struct smb_request *req,
8427 char **pparams, int total_params,
8428 char **ppdata, int total_data,
8429 unsigned int max_data_bytes)
8431 char *params = *pparams;
8432 char *pathname = NULL;
8433 int reply_size = 0;
8434 int max_referral_level;
8435 NTSTATUS status = NT_STATUS_OK;
8436 TALLOC_CTX *ctx = talloc_tos();
8438 DEBUG(10,("call_trans2getdfsreferral\n"));
8440 if (total_params < 3) {
8441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8442 return;
8445 max_referral_level = SVAL(params,0);
8447 if(!lp_host_msdfs()) {
8448 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8449 return;
8452 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8453 total_params - 2, STR_TERMINATE);
8454 if (!pathname) {
8455 reply_nterror(req, NT_STATUS_NOT_FOUND);
8456 return;
8458 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8459 ppdata,&status)) < 0) {
8460 reply_nterror(req, status);
8461 return;
8464 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8465 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8466 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8468 return;
8471 #define LMCAT_SPL 0x53
8472 #define LMFUNC_GETJOBID 0x60
8474 /****************************************************************************
8475 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8476 ****************************************************************************/
8478 static void call_trans2ioctl(connection_struct *conn,
8479 struct smb_request *req,
8480 char **pparams, int total_params,
8481 char **ppdata, int total_data,
8482 unsigned int max_data_bytes)
8484 char *pdata = *ppdata;
8485 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8487 /* check for an invalid fid before proceeding */
8489 if (!fsp) {
8490 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8491 return;
8494 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8495 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8496 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8497 if (*ppdata == NULL) {
8498 reply_nterror(req, NT_STATUS_NO_MEMORY);
8499 return;
8501 pdata = *ppdata;
8503 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8504 CAN ACCEPT THIS IN UNICODE. JRA. */
8506 /* Job number */
8507 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8509 srvstr_push(pdata, req->flags2, pdata + 2,
8510 lp_netbios_name(), 15,
8511 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8512 srvstr_push(pdata, req->flags2, pdata+18,
8513 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8514 STR_ASCII|STR_TERMINATE); /* Service name */
8515 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8516 max_data_bytes);
8517 return;
8520 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8521 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8524 /****************************************************************************
8525 Reply to a SMBfindclose (stop trans2 directory search).
8526 ****************************************************************************/
8528 void reply_findclose(struct smb_request *req)
8530 int dptr_num;
8531 struct smbd_server_connection *sconn = req->sconn;
8533 START_PROFILE(SMBfindclose);
8535 if (req->wct < 1) {
8536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8537 END_PROFILE(SMBfindclose);
8538 return;
8541 dptr_num = SVALS(req->vwv+0, 0);
8543 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8545 dptr_close(sconn, &dptr_num);
8547 reply_outbuf(req, 0, 0);
8549 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8551 END_PROFILE(SMBfindclose);
8552 return;
8555 /****************************************************************************
8556 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8557 ****************************************************************************/
8559 void reply_findnclose(struct smb_request *req)
8561 int dptr_num;
8563 START_PROFILE(SMBfindnclose);
8565 if (req->wct < 1) {
8566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8567 END_PROFILE(SMBfindnclose);
8568 return;
8571 dptr_num = SVAL(req->vwv+0, 0);
8573 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8575 /* We never give out valid handles for a
8576 findnotifyfirst - so any dptr_num is ok here.
8577 Just ignore it. */
8579 reply_outbuf(req, 0, 0);
8581 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8583 END_PROFILE(SMBfindnclose);
8584 return;
8587 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8588 struct trans_state *state)
8590 if (get_Protocol() >= PROTOCOL_NT1) {
8591 req->flags2 |= 0x40; /* IS_LONG_NAME */
8592 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8595 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8596 if (state->call != TRANSACT2_QFSINFO &&
8597 state->call != TRANSACT2_SETFSINFO) {
8598 DEBUG(0,("handle_trans2: encryption required "
8599 "with call 0x%x\n",
8600 (unsigned int)state->call));
8601 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8602 return;
8606 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8608 /* Now we must call the relevant TRANS2 function */
8609 switch(state->call) {
8610 case TRANSACT2_OPEN:
8612 START_PROFILE(Trans2_open);
8613 call_trans2open(conn, req,
8614 &state->param, state->total_param,
8615 &state->data, state->total_data,
8616 state->max_data_return);
8617 END_PROFILE(Trans2_open);
8618 break;
8621 case TRANSACT2_FINDFIRST:
8623 START_PROFILE(Trans2_findfirst);
8624 call_trans2findfirst(conn, req,
8625 &state->param, state->total_param,
8626 &state->data, state->total_data,
8627 state->max_data_return);
8628 END_PROFILE(Trans2_findfirst);
8629 break;
8632 case TRANSACT2_FINDNEXT:
8634 START_PROFILE(Trans2_findnext);
8635 call_trans2findnext(conn, req,
8636 &state->param, state->total_param,
8637 &state->data, state->total_data,
8638 state->max_data_return);
8639 END_PROFILE(Trans2_findnext);
8640 break;
8643 case TRANSACT2_QFSINFO:
8645 START_PROFILE(Trans2_qfsinfo);
8646 call_trans2qfsinfo(conn, req,
8647 &state->param, state->total_param,
8648 &state->data, state->total_data,
8649 state->max_data_return);
8650 END_PROFILE(Trans2_qfsinfo);
8651 break;
8654 case TRANSACT2_SETFSINFO:
8656 START_PROFILE(Trans2_setfsinfo);
8657 call_trans2setfsinfo(conn, req,
8658 &state->param, state->total_param,
8659 &state->data, state->total_data,
8660 state->max_data_return);
8661 END_PROFILE(Trans2_setfsinfo);
8662 break;
8665 case TRANSACT2_QPATHINFO:
8666 case TRANSACT2_QFILEINFO:
8668 START_PROFILE(Trans2_qpathinfo);
8669 call_trans2qfilepathinfo(conn, req, state->call,
8670 &state->param, state->total_param,
8671 &state->data, state->total_data,
8672 state->max_data_return);
8673 END_PROFILE(Trans2_qpathinfo);
8674 break;
8677 case TRANSACT2_SETPATHINFO:
8678 case TRANSACT2_SETFILEINFO:
8680 START_PROFILE(Trans2_setpathinfo);
8681 call_trans2setfilepathinfo(conn, req, state->call,
8682 &state->param, state->total_param,
8683 &state->data, state->total_data,
8684 state->max_data_return);
8685 END_PROFILE(Trans2_setpathinfo);
8686 break;
8689 case TRANSACT2_FINDNOTIFYFIRST:
8691 START_PROFILE(Trans2_findnotifyfirst);
8692 call_trans2findnotifyfirst(conn, req,
8693 &state->param, state->total_param,
8694 &state->data, state->total_data,
8695 state->max_data_return);
8696 END_PROFILE(Trans2_findnotifyfirst);
8697 break;
8700 case TRANSACT2_FINDNOTIFYNEXT:
8702 START_PROFILE(Trans2_findnotifynext);
8703 call_trans2findnotifynext(conn, req,
8704 &state->param, state->total_param,
8705 &state->data, state->total_data,
8706 state->max_data_return);
8707 END_PROFILE(Trans2_findnotifynext);
8708 break;
8711 case TRANSACT2_MKDIR:
8713 START_PROFILE(Trans2_mkdir);
8714 call_trans2mkdir(conn, req,
8715 &state->param, state->total_param,
8716 &state->data, state->total_data,
8717 state->max_data_return);
8718 END_PROFILE(Trans2_mkdir);
8719 break;
8722 case TRANSACT2_GET_DFS_REFERRAL:
8724 START_PROFILE(Trans2_get_dfs_referral);
8725 call_trans2getdfsreferral(conn, req,
8726 &state->param, state->total_param,
8727 &state->data, state->total_data,
8728 state->max_data_return);
8729 END_PROFILE(Trans2_get_dfs_referral);
8730 break;
8733 case TRANSACT2_IOCTL:
8735 START_PROFILE(Trans2_ioctl);
8736 call_trans2ioctl(conn, req,
8737 &state->param, state->total_param,
8738 &state->data, state->total_data,
8739 state->max_data_return);
8740 END_PROFILE(Trans2_ioctl);
8741 break;
8744 default:
8745 /* Error in request */
8746 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8747 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8751 /****************************************************************************
8752 Reply to a SMBtrans2.
8753 ****************************************************************************/
8755 void reply_trans2(struct smb_request *req)
8757 connection_struct *conn = req->conn;
8758 unsigned int dsoff;
8759 unsigned int dscnt;
8760 unsigned int psoff;
8761 unsigned int pscnt;
8762 unsigned int tran_call;
8763 struct trans_state *state;
8764 NTSTATUS result;
8766 START_PROFILE(SMBtrans2);
8768 if (req->wct < 14) {
8769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8770 END_PROFILE(SMBtrans2);
8771 return;
8774 dsoff = SVAL(req->vwv+12, 0);
8775 dscnt = SVAL(req->vwv+11, 0);
8776 psoff = SVAL(req->vwv+10, 0);
8777 pscnt = SVAL(req->vwv+9, 0);
8778 tran_call = SVAL(req->vwv+14, 0);
8780 result = allow_new_trans(conn->pending_trans, req->mid);
8781 if (!NT_STATUS_IS_OK(result)) {
8782 DEBUG(2, ("Got invalid trans2 request: %s\n",
8783 nt_errstr(result)));
8784 reply_nterror(req, result);
8785 END_PROFILE(SMBtrans2);
8786 return;
8789 if (IS_IPC(conn)) {
8790 switch (tran_call) {
8791 /* List the allowed trans2 calls on IPC$ */
8792 case TRANSACT2_OPEN:
8793 case TRANSACT2_GET_DFS_REFERRAL:
8794 case TRANSACT2_QFILEINFO:
8795 case TRANSACT2_QFSINFO:
8796 case TRANSACT2_SETFSINFO:
8797 break;
8798 default:
8799 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8800 END_PROFILE(SMBtrans2);
8801 return;
8805 if ((state = talloc(conn, struct trans_state)) == NULL) {
8806 DEBUG(0, ("talloc failed\n"));
8807 reply_nterror(req, NT_STATUS_NO_MEMORY);
8808 END_PROFILE(SMBtrans2);
8809 return;
8812 state->cmd = SMBtrans2;
8814 state->mid = req->mid;
8815 state->vuid = req->vuid;
8816 state->setup_count = SVAL(req->vwv+13, 0);
8817 state->setup = NULL;
8818 state->total_param = SVAL(req->vwv+0, 0);
8819 state->param = NULL;
8820 state->total_data = SVAL(req->vwv+1, 0);
8821 state->data = NULL;
8822 state->max_param_return = SVAL(req->vwv+2, 0);
8823 state->max_data_return = SVAL(req->vwv+3, 0);
8824 state->max_setup_return = SVAL(req->vwv+4, 0);
8825 state->close_on_completion = BITSETW(req->vwv+5, 0);
8826 state->one_way = BITSETW(req->vwv+5, 1);
8828 state->call = tran_call;
8830 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8831 is so as a sanity check */
8832 if (state->setup_count != 1) {
8834 * Need to have rc=0 for ioctl to get job id for OS/2.
8835 * Network printing will fail if function is not successful.
8836 * Similar function in reply.c will be used if protocol
8837 * is LANMAN1.0 instead of LM1.2X002.
8838 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8839 * outbuf doesn't have to be set(only job id is used).
8841 if ( (state->setup_count == 4)
8842 && (tran_call == TRANSACT2_IOCTL)
8843 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8844 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8845 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8846 } else {
8847 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8848 DEBUG(2,("Transaction is %d\n",tran_call));
8849 TALLOC_FREE(state);
8850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8851 END_PROFILE(SMBtrans2);
8852 return;
8856 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8857 goto bad_param;
8859 if (state->total_data) {
8861 if (trans_oob(state->total_data, 0, dscnt)
8862 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8863 goto bad_param;
8866 /* Can't use talloc here, the core routines do realloc on the
8867 * params and data. */
8868 state->data = (char *)SMB_MALLOC(state->total_data);
8869 if (state->data == NULL) {
8870 DEBUG(0,("reply_trans2: data malloc fail for %u "
8871 "bytes !\n", (unsigned int)state->total_data));
8872 TALLOC_FREE(state);
8873 reply_nterror(req, NT_STATUS_NO_MEMORY);
8874 END_PROFILE(SMBtrans2);
8875 return;
8878 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8881 if (state->total_param) {
8883 if (trans_oob(state->total_param, 0, pscnt)
8884 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8885 goto bad_param;
8888 /* Can't use talloc here, the core routines do realloc on the
8889 * params and data. */
8890 state->param = (char *)SMB_MALLOC(state->total_param);
8891 if (state->param == NULL) {
8892 DEBUG(0,("reply_trans: param malloc fail for %u "
8893 "bytes !\n", (unsigned int)state->total_param));
8894 SAFE_FREE(state->data);
8895 TALLOC_FREE(state);
8896 reply_nterror(req, NT_STATUS_NO_MEMORY);
8897 END_PROFILE(SMBtrans2);
8898 return;
8901 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8904 state->received_data = dscnt;
8905 state->received_param = pscnt;
8907 if ((state->received_param == state->total_param) &&
8908 (state->received_data == state->total_data)) {
8910 handle_trans2(conn, req, state);
8912 SAFE_FREE(state->data);
8913 SAFE_FREE(state->param);
8914 TALLOC_FREE(state);
8915 END_PROFILE(SMBtrans2);
8916 return;
8919 DLIST_ADD(conn->pending_trans, state);
8921 /* We need to send an interim response then receive the rest
8922 of the parameter/data bytes */
8923 reply_outbuf(req, 0, 0);
8924 show_msg((char *)req->outbuf);
8925 END_PROFILE(SMBtrans2);
8926 return;
8928 bad_param:
8930 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8931 SAFE_FREE(state->data);
8932 SAFE_FREE(state->param);
8933 TALLOC_FREE(state);
8934 END_PROFILE(SMBtrans2);
8935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8939 /****************************************************************************
8940 Reply to a SMBtranss2
8941 ****************************************************************************/
8943 void reply_transs2(struct smb_request *req)
8945 connection_struct *conn = req->conn;
8946 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8947 struct trans_state *state;
8949 START_PROFILE(SMBtranss2);
8951 show_msg((const char *)req->inbuf);
8953 /* Windows clients expect all replies to
8954 a transact secondary (SMBtranss2 0x33)
8955 to have a command code of transact
8956 (SMBtrans2 0x32). See bug #8989
8957 and also [MS-CIFS] section 2.2.4.47.2
8958 for details.
8960 req->cmd = SMBtrans2;
8962 if (req->wct < 8) {
8963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8964 END_PROFILE(SMBtranss2);
8965 return;
8968 for (state = conn->pending_trans; state != NULL;
8969 state = state->next) {
8970 if (state->mid == req->mid) {
8971 break;
8975 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8977 END_PROFILE(SMBtranss2);
8978 return;
8981 /* Revise state->total_param and state->total_data in case they have
8982 changed downwards */
8984 if (SVAL(req->vwv+0, 0) < state->total_param)
8985 state->total_param = SVAL(req->vwv+0, 0);
8986 if (SVAL(req->vwv+1, 0) < state->total_data)
8987 state->total_data = SVAL(req->vwv+1, 0);
8989 pcnt = SVAL(req->vwv+2, 0);
8990 poff = SVAL(req->vwv+3, 0);
8991 pdisp = SVAL(req->vwv+4, 0);
8993 dcnt = SVAL(req->vwv+5, 0);
8994 doff = SVAL(req->vwv+6, 0);
8995 ddisp = SVAL(req->vwv+7, 0);
8997 state->received_param += pcnt;
8998 state->received_data += dcnt;
9000 if ((state->received_data > state->total_data) ||
9001 (state->received_param > state->total_param))
9002 goto bad_param;
9004 if (pcnt) {
9005 if (trans_oob(state->total_param, pdisp, pcnt)
9006 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9007 goto bad_param;
9009 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9012 if (dcnt) {
9013 if (trans_oob(state->total_data, ddisp, dcnt)
9014 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9015 goto bad_param;
9017 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9020 if ((state->received_param < state->total_param) ||
9021 (state->received_data < state->total_data)) {
9022 END_PROFILE(SMBtranss2);
9023 return;
9026 handle_trans2(conn, req, state);
9028 DLIST_REMOVE(conn->pending_trans, state);
9029 SAFE_FREE(state->data);
9030 SAFE_FREE(state->param);
9031 TALLOC_FREE(state);
9033 END_PROFILE(SMBtranss2);
9034 return;
9036 bad_param:
9038 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9039 DLIST_REMOVE(conn->pending_trans, state);
9040 SAFE_FREE(state->data);
9041 SAFE_FREE(state->param);
9042 TALLOC_FREE(state);
9043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9044 END_PROFILE(SMBtranss2);
9045 return;