s3:smbd: allow info class SMB_QUERY_FS_ATTRIBUTE_INFO to return partial data
[Samba.git] / source3 / smbd / trans2.c
blobda0b1ea92cba5a5b3b308f46fcb022e3abfc640a
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;
349 * Filter out any underlying POSIX EA names
350 * that a Windows client can't handle.
352 if (!lp_posix_pathnames() &&
353 is_invalid_windows_ea_name(names[i])) {
354 continue;
357 listp = talloc(mem_ctx, struct ea_list);
358 if (listp == NULL) {
359 return NT_STATUS_NO_MEMORY;
362 status = get_ea_value(listp, conn, fsp,
363 fname, names[i],
364 &listp->ea);
366 if (!NT_STATUS_IS_OK(status)) {
367 TALLOC_FREE(listp);
368 return status;
371 if (listp->ea.value.length == 0) {
373 * We can never return a zero length EA.
374 * Windows reports the EA's as corrupted.
376 TALLOC_FREE(listp);
377 continue;
380 push_ascii_fstring(dos_ea_name, listp->ea.name);
382 *pea_total_len +=
383 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
385 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
386 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
387 (unsigned int)listp->ea.value.length));
389 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
393 /* Add on 4 for total length. */
394 if (*pea_total_len) {
395 *pea_total_len += 4;
398 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
399 (unsigned int)*pea_total_len));
401 *ea_list = ea_list_head;
402 return NT_STATUS_OK;
405 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
406 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
408 *pea_total_len = 0;
409 *ea_list = NULL;
411 if (!lp_ea_support(SNUM(conn))) {
412 return NT_STATUS_OK;
415 if (is_ntfs_stream_smb_fname(smb_fname)) {
416 return NT_STATUS_INVALID_PARAMETER;
419 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
422 /****************************************************************************
423 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
424 that was filled.
425 ****************************************************************************/
427 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
428 connection_struct *conn, struct ea_list *ea_list)
430 unsigned int ret_data_size = 4;
431 char *p = pdata;
433 SMB_ASSERT(total_data_size >= 4);
435 if (!lp_ea_support(SNUM(conn))) {
436 SIVAL(pdata,4,0);
437 return 4;
440 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
441 size_t dos_namelen;
442 fstring dos_ea_name;
443 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
444 dos_namelen = strlen(dos_ea_name);
445 if (dos_namelen > 255 || dos_namelen == 0) {
446 break;
448 if (ea_list->ea.value.length > 65535) {
449 break;
451 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
452 break;
455 /* We know we have room. */
456 SCVAL(p,0,ea_list->ea.flags);
457 SCVAL(p,1,dos_namelen);
458 SSVAL(p,2,ea_list->ea.value.length);
459 strlcpy(p+4, dos_ea_name, dos_namelen+1);
460 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
462 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
463 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 ret_data_size = PTR_DIFF(p, pdata);
467 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
468 SIVAL(pdata,0,ret_data_size);
469 return ret_data_size;
472 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
473 char *pdata,
474 unsigned int total_data_size,
475 unsigned int *ret_data_size,
476 connection_struct *conn,
477 struct ea_list *ea_list)
479 uint8_t *p = (uint8_t *)pdata;
480 uint8_t *last_start = NULL;
481 bool do_store_data = (pdata != NULL);
483 *ret_data_size = 0;
485 if (!lp_ea_support(SNUM(conn))) {
486 return NT_STATUS_NO_EAS_ON_FILE;
489 for (; ea_list; ea_list = ea_list->next) {
490 size_t dos_namelen;
491 fstring dos_ea_name;
492 size_t this_size;
493 size_t pad = 0;
495 if (last_start != NULL && do_store_data) {
496 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
498 last_start = p;
500 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
501 dos_namelen = strlen(dos_ea_name);
502 if (dos_namelen > 255 || dos_namelen == 0) {
503 return NT_STATUS_INTERNAL_ERROR;
505 if (ea_list->ea.value.length > 65535) {
506 return NT_STATUS_INTERNAL_ERROR;
509 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
511 if (ea_list->next) {
512 pad = (4 - (this_size % 4)) % 4;
513 this_size += pad;
516 if (do_store_data) {
517 if (this_size > total_data_size) {
518 return NT_STATUS_INFO_LENGTH_MISMATCH;
521 /* We know we have room. */
522 SIVAL(p, 0x00, 0); /* next offset */
523 SCVAL(p, 0x04, ea_list->ea.flags);
524 SCVAL(p, 0x05, dos_namelen);
525 SSVAL(p, 0x06, ea_list->ea.value.length);
526 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
527 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
528 if (pad) {
529 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
530 '\0',
531 pad);
533 total_data_size -= this_size;
536 p += this_size;
539 *ret_data_size = PTR_DIFF(p, pdata);
540 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
541 return NT_STATUS_OK;
544 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
546 size_t total_ea_len = 0;
547 TALLOC_CTX *mem_ctx;
548 struct ea_list *ea_list = NULL;
550 if (!lp_ea_support(SNUM(conn))) {
551 return 0;
553 mem_ctx = talloc_stackframe();
555 /* If this is a stream fsp, then we need to instead find the
556 * estimated ea len from the main file, not the stream
557 * (streams cannot have EAs), but the estimate isn't just 0 in
558 * this case! */
559 if (is_ntfs_stream_smb_fname(smb_fname)) {
560 fsp = NULL;
562 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
563 if(conn->sconn->using_smb2) {
564 NTSTATUS status;
565 unsigned int ret_data_size;
567 * We're going to be using fill_ea_chained_buffer() to
568 * marshall EA's - this size is significantly larger
569 * than the SMB1 buffer. Re-calculate the size without
570 * marshalling.
572 status = fill_ea_chained_buffer(mem_ctx,
573 NULL,
575 &ret_data_size,
576 conn,
577 ea_list);
578 if (!NT_STATUS_IS_OK(status)) {
579 ret_data_size = 0;
581 total_ea_len = ret_data_size;
583 TALLOC_FREE(mem_ctx);
584 return total_ea_len;
587 /****************************************************************************
588 Ensure the EA name is case insensitive by matching any existing EA name.
589 ****************************************************************************/
591 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
593 size_t total_ea_len;
594 TALLOC_CTX *mem_ctx = talloc_tos();
595 struct ea_list *ea_list;
596 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
597 if (!NT_STATUS_IS_OK(status)) {
598 return;
601 for (; ea_list; ea_list = ea_list->next) {
602 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
603 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
604 &unix_ea_name[5], ea_list->ea.name));
605 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
606 break;
611 /****************************************************************************
612 Set or delete an extended attribute.
613 ****************************************************************************/
615 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
616 const struct smb_filename *smb_fname, struct ea_list *ea_list)
618 NTSTATUS status;
619 char *fname = NULL;
621 if (!lp_ea_support(SNUM(conn))) {
622 return NT_STATUS_EAS_NOT_SUPPORTED;
625 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
626 if (!NT_STATUS_IS_OK(status)) {
627 return status;
630 /* Setting EAs on streams isn't supported. */
631 if (is_ntfs_stream_smb_fname(smb_fname)) {
632 return NT_STATUS_INVALID_PARAMETER;
636 * Filter out invalid Windows EA names - before
637 * we set *any* of them.
640 if (ea_list_has_invalid_name(ea_list)) {
641 return STATUS_INVALID_EA_NAME;
644 fname = smb_fname->base_name;
646 for (;ea_list; ea_list = ea_list->next) {
647 int ret;
648 fstring unix_ea_name;
650 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
651 fstrcat(unix_ea_name, ea_list->ea.name);
653 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
655 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
657 if (samba_private_attr_name(unix_ea_name)) {
658 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
659 return NT_STATUS_ACCESS_DENIED;
662 if (ea_list->ea.value.length == 0) {
663 /* Remove the attribute. */
664 if (fsp && (fsp->fh->fd != -1)) {
665 DEBUG(10,("set_ea: deleting ea name %s on "
666 "file %s by file descriptor.\n",
667 unix_ea_name, fsp_str_dbg(fsp)));
668 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
669 } else {
670 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
671 unix_ea_name, fname));
672 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
674 #ifdef ENOATTR
675 /* Removing a non existent attribute always succeeds. */
676 if (ret == -1 && errno == ENOATTR) {
677 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
678 unix_ea_name));
679 ret = 0;
681 #endif
682 } else {
683 if (fsp && (fsp->fh->fd != -1)) {
684 DEBUG(10,("set_ea: setting ea name %s on file "
685 "%s by file descriptor.\n",
686 unix_ea_name, fsp_str_dbg(fsp)));
687 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
688 ea_list->ea.value.data, ea_list->ea.value.length, 0);
689 } else {
690 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
691 unix_ea_name, fname));
692 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
693 ea_list->ea.value.data, ea_list->ea.value.length, 0);
697 if (ret == -1) {
698 #ifdef ENOTSUP
699 if (errno == ENOTSUP) {
700 return NT_STATUS_EAS_NOT_SUPPORTED;
702 #endif
703 return map_nt_error_from_unix(errno);
707 return NT_STATUS_OK;
709 /****************************************************************************
710 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
711 ****************************************************************************/
713 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
715 struct ea_list *ea_list_head = NULL;
716 size_t converted_size, offset = 0;
718 while (offset + 2 < data_size) {
719 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
720 unsigned int namelen = CVAL(pdata,offset);
722 offset++; /* Go past the namelen byte. */
724 /* integer wrap paranioa. */
725 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
726 (offset > data_size) || (namelen > data_size) ||
727 (offset + namelen >= data_size)) {
728 break;
730 /* Ensure the name is null terminated. */
731 if (pdata[offset + namelen] != '\0') {
732 return NULL;
734 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
735 &converted_size)) {
736 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
737 "failed: %s", strerror(errno)));
739 if (!eal->ea.name) {
740 return NULL;
743 offset += (namelen + 1); /* Go past the name + terminating zero. */
744 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
745 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
748 return ea_list_head;
751 /****************************************************************************
752 Read one EA list entry from the buffer.
753 ****************************************************************************/
755 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
757 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
758 uint16 val_len;
759 unsigned int namelen;
760 size_t converted_size;
762 if (!eal) {
763 return NULL;
766 if (data_size < 6) {
767 return NULL;
770 eal->ea.flags = CVAL(pdata,0);
771 namelen = CVAL(pdata,1);
772 val_len = SVAL(pdata,2);
774 if (4 + namelen + 1 + val_len > data_size) {
775 return NULL;
778 /* Ensure the name is null terminated. */
779 if (pdata[namelen + 4] != '\0') {
780 return NULL;
782 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
783 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
784 strerror(errno)));
786 if (!eal->ea.name) {
787 return NULL;
790 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
791 if (!eal->ea.value.data) {
792 return NULL;
795 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
797 /* Ensure we're null terminated just in case we print the value. */
798 eal->ea.value.data[val_len] = '\0';
799 /* But don't count the null. */
800 eal->ea.value.length--;
802 if (pbytes_used) {
803 *pbytes_used = 4 + namelen + 1 + val_len;
806 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
807 dump_data(10, eal->ea.value.data, eal->ea.value.length);
809 return eal;
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
818 struct ea_list *ea_list_head = NULL;
819 size_t offset = 0;
820 size_t bytes_used = 0;
822 while (offset < data_size) {
823 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
825 if (!eal) {
826 return NULL;
829 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
830 offset += bytes_used;
833 return ea_list_head;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list *ealist)
842 fstring dos_ea_name;
843 struct ea_list *listp;
844 size_t ret = 0;
846 for (listp = ealist; listp; listp = listp->next) {
847 push_ascii_fstring(dos_ea_name, listp->ea.name);
848 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
850 /* Add on 4 for total length. */
851 if (ret) {
852 ret += 4;
855 return ret;
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
866 struct ea_list *nlistp, *flistp;
868 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
869 for (flistp = file_list; flistp; flistp = flistp->next) {
870 if (strequal(nlistp->ea.name, flistp->ea.name)) {
871 break;
875 if (flistp) {
876 /* Copy the data from this entry. */
877 nlistp->ea.flags = flistp->ea.flags;
878 nlistp->ea.value = flistp->ea.value;
879 } else {
880 /* Null entry. */
881 nlistp->ea.flags = 0;
882 ZERO_STRUCT(nlistp->ea.value);
886 *total_ea_len = ea_list_size(name_list);
887 return name_list;
890 /****************************************************************************
891 Send the required number of replies back.
892 We assume all fields other than the data fields are
893 set correctly for the type of call.
894 HACK ! Always assumes smb_setup field is zero.
895 ****************************************************************************/
897 void send_trans2_replies(connection_struct *conn,
898 struct smb_request *req,
899 NTSTATUS status,
900 const char *params,
901 int paramsize,
902 const char *pdata,
903 int datasize,
904 int max_data_bytes)
906 /* As we are using a protocol > LANMAN1 then the max_send
907 variable must have been set in the sessetupX call.
908 This takes precedence over the max_xmit field in the
909 global struct. These different max_xmit variables should
910 be merged as this is now too confusing */
912 int data_to_send = datasize;
913 int params_to_send = paramsize;
914 int useable_space;
915 const char *pp = params;
916 const char *pd = pdata;
917 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
918 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
919 int data_alignment_offset = 0;
920 bool overflow = False;
921 struct smbd_server_connection *sconn = req->sconn;
922 int max_send = sconn->smb1.sessions.max_send;
924 /* Modify the data_to_send and datasize and set the error if
925 we're trying to send more than max_data_bytes. We still send
926 the part of the packet(s) that fit. Strange, but needed
927 for OS/2. */
929 if (max_data_bytes > 0 && datasize > max_data_bytes) {
930 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
931 max_data_bytes, datasize ));
932 datasize = data_to_send = max_data_bytes;
933 overflow = True;
936 /* If there genuinely are no parameters or data to send just send the empty packet */
938 if(params_to_send == 0 && data_to_send == 0) {
939 reply_outbuf(req, 10, 0);
940 if (NT_STATUS_V(status)) {
941 uint8_t eclass;
942 uint32_t ecode;
943 ntstatus_to_dos(status, &eclass, &ecode);
944 error_packet_set((char *)req->outbuf,
945 eclass, ecode, status,
946 __LINE__,__FILE__);
948 show_msg((char *)req->outbuf);
949 if (!srv_send_smb(sconn,
950 (char *)req->outbuf,
951 true, req->seqnum+1,
952 IS_CONN_ENCRYPTED(conn),
953 &req->pcd)) {
954 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
956 TALLOC_FREE(req->outbuf);
957 return;
960 /* When sending params and data ensure that both are nicely aligned */
961 /* Only do this alignment when there is also data to send - else
962 can cause NT redirector problems. */
964 if (((params_to_send % 4) != 0) && (data_to_send != 0))
965 data_alignment_offset = 4 - (params_to_send % 4);
967 /* Space is bufsize minus Netbios over TCP header minus SMB header */
968 /* The alignment_offset is to align the param bytes on an even byte
969 boundary. NT 4.0 Beta needs this to work correctly. */
971 useable_space = max_send - (smb_size
972 + 2 * 10 /* wct */
973 + alignment_offset
974 + data_alignment_offset);
976 if (useable_space < 0) {
977 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
978 "= %d!!!", useable_space));
979 exit_server_cleanly("send_trans2_replies: Not enough space");
982 while (params_to_send || data_to_send) {
983 /* Calculate whether we will totally or partially fill this packet */
985 total_sent_thistime = params_to_send + data_to_send;
987 /* We can never send more than useable_space */
989 * Note that 'useable_space' does not include the alignment offsets,
990 * but we must include the alignment offsets in the calculation of
991 * the length of the data we send over the wire, as the alignment offsets
992 * are sent here. Fix from Marc_Jacobsen@hp.com.
995 total_sent_thistime = MIN(total_sent_thistime, useable_space);
997 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
998 + data_alignment_offset);
1000 /* Set total params and data to be sent */
1001 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1002 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1004 /* Calculate how many parameters and data we can fit into
1005 * this packet. Parameters get precedence
1008 params_sent_thistime = MIN(params_to_send,useable_space);
1009 data_sent_thistime = useable_space - params_sent_thistime;
1010 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1012 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1014 /* smb_proff is the offset from the start of the SMB header to the
1015 parameter bytes, however the first 4 bytes of outbuf are
1016 the Netbios over TCP header. Thus use smb_base() to subtract
1017 them from the calculation */
1019 SSVAL(req->outbuf,smb_proff,
1020 ((smb_buf(req->outbuf)+alignment_offset)
1021 - smb_base(req->outbuf)));
1023 if(params_sent_thistime == 0)
1024 SSVAL(req->outbuf,smb_prdisp,0);
1025 else
1026 /* Absolute displacement of param bytes sent in this packet */
1027 SSVAL(req->outbuf,smb_prdisp,pp - params);
1029 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1030 if(data_sent_thistime == 0) {
1031 SSVAL(req->outbuf,smb_droff,0);
1032 SSVAL(req->outbuf,smb_drdisp, 0);
1033 } else {
1034 /* The offset of the data bytes is the offset of the
1035 parameter bytes plus the number of parameters being sent this time */
1036 SSVAL(req->outbuf, smb_droff,
1037 ((smb_buf(req->outbuf)+alignment_offset)
1038 - smb_base(req->outbuf))
1039 + params_sent_thistime + data_alignment_offset);
1040 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1043 /* Initialize the padding for alignment */
1045 if (alignment_offset != 0) {
1046 memset(smb_buf(req->outbuf), 0, alignment_offset);
1049 /* Copy the param bytes into the packet */
1051 if(params_sent_thistime) {
1052 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1053 params_sent_thistime);
1056 /* Copy in the data bytes */
1057 if(data_sent_thistime) {
1058 if (data_alignment_offset != 0) {
1059 memset((smb_buf(req->outbuf)+alignment_offset+
1060 params_sent_thistime), 0,
1061 data_alignment_offset);
1063 memcpy(smb_buf(req->outbuf)+alignment_offset
1064 +params_sent_thistime+data_alignment_offset,
1065 pd,data_sent_thistime);
1068 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1069 params_sent_thistime, data_sent_thistime, useable_space));
1070 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1071 params_to_send, data_to_send, paramsize, datasize));
1073 if (overflow) {
1074 error_packet_set((char *)req->outbuf,
1075 ERRDOS,ERRbufferoverflow,
1076 STATUS_BUFFER_OVERFLOW,
1077 __LINE__,__FILE__);
1078 } else if (NT_STATUS_V(status)) {
1079 uint8_t eclass;
1080 uint32_t ecode;
1081 ntstatus_to_dos(status, &eclass, &ecode);
1082 error_packet_set((char *)req->outbuf,
1083 eclass, ecode, status,
1084 __LINE__,__FILE__);
1087 /* Send the packet */
1088 show_msg((char *)req->outbuf);
1089 if (!srv_send_smb(sconn,
1090 (char *)req->outbuf,
1091 true, req->seqnum+1,
1092 IS_CONN_ENCRYPTED(conn),
1093 &req->pcd))
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req->outbuf);
1098 pp += params_sent_thistime;
1099 pd += data_sent_thistime;
1101 params_to_send -= params_sent_thistime;
1102 data_to_send -= data_sent_thistime;
1104 /* Sanity check */
1105 if(params_to_send < 0 || data_to_send < 0) {
1106 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1107 params_to_send, data_to_send));
1108 return;
1112 return;
1115 /****************************************************************************
1116 Reply to a TRANSACT2_OPEN.
1117 ****************************************************************************/
1119 static void call_trans2open(connection_struct *conn,
1120 struct smb_request *req,
1121 char **pparams, int total_params,
1122 char **ppdata, int total_data,
1123 unsigned int max_data_bytes)
1125 struct smb_filename *smb_fname = NULL;
1126 char *params = *pparams;
1127 char *pdata = *ppdata;
1128 int deny_mode;
1129 int32 open_attr;
1130 bool oplock_request;
1131 #if 0
1132 bool return_additional_info;
1133 int16 open_sattr;
1134 time_t open_time;
1135 #endif
1136 int open_ofun;
1137 uint32 open_size;
1138 char *pname;
1139 char *fname = NULL;
1140 off_t size=0;
1141 int fattr=0,mtime=0;
1142 SMB_INO_T inode = 0;
1143 int smb_action = 0;
1144 files_struct *fsp;
1145 struct ea_list *ea_list = NULL;
1146 uint16 flags = 0;
1147 NTSTATUS status;
1148 uint32 access_mask;
1149 uint32 share_mode;
1150 uint32 create_disposition;
1151 uint32 create_options = 0;
1152 uint32_t private_flags = 0;
1153 TALLOC_CTX *ctx = talloc_tos();
1156 * Ensure we have enough parameters to perform the operation.
1159 if (total_params < 29) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 goto out;
1164 flags = SVAL(params, 0);
1165 deny_mode = SVAL(params, 2);
1166 open_attr = SVAL(params,6);
1167 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1168 if (oplock_request) {
1169 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1172 #if 0
1173 return_additional_info = BITSETW(params,0);
1174 open_sattr = SVAL(params, 4);
1175 open_time = make_unix_date3(params+8);
1176 #endif
1177 open_ofun = SVAL(params,12);
1178 open_size = IVAL(params,14);
1179 pname = &params[28];
1181 if (IS_IPC(conn)) {
1182 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1183 goto out;
1186 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1187 total_params - 28, STR_TERMINATE,
1188 &status);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 reply_nterror(req, status);
1191 goto out;
1194 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1195 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1196 (unsigned int)open_ofun, open_size));
1198 status = filename_convert(ctx,
1199 conn,
1200 req->flags2 & FLAGS2_DFS_PATHNAMES,
1201 fname,
1203 NULL,
1204 &smb_fname);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1207 reply_botherror(req,
1208 NT_STATUS_PATH_NOT_COVERED,
1209 ERRSRV, ERRbadpath);
1210 goto out;
1212 reply_nterror(req, status);
1213 goto out;
1216 if (open_ofun == 0) {
1217 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1218 goto out;
1221 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1222 open_ofun,
1223 &access_mask, &share_mode,
1224 &create_disposition,
1225 &create_options,
1226 &private_flags)) {
1227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1228 goto out;
1231 /* Any data in this call is an EA list. */
1232 if (total_data && (total_data != 4)) {
1233 if (total_data < 10) {
1234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1235 goto out;
1238 if (IVAL(pdata,0) > total_data) {
1239 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1240 IVAL(pdata,0), (unsigned int)total_data));
1241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1242 goto out;
1245 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1246 total_data - 4);
1247 if (!ea_list) {
1248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1249 goto out;
1252 if (!lp_ea_support(SNUM(conn))) {
1253 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1254 goto out;
1257 if (ea_list_has_invalid_name(ea_list)) {
1258 int param_len = 30;
1259 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1260 if(*pparams == NULL ) {
1261 reply_nterror(req, NT_STATUS_NO_MEMORY);
1262 goto out;
1264 params = *pparams;
1265 memset(params, '\0', param_len);
1266 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1267 params, param_len, NULL, 0, max_data_bytes);
1268 goto out;
1272 status = SMB_VFS_CREATE_FILE(
1273 conn, /* conn */
1274 req, /* req */
1275 0, /* root_dir_fid */
1276 smb_fname, /* fname */
1277 access_mask, /* access_mask */
1278 share_mode, /* share_access */
1279 create_disposition, /* create_disposition*/
1280 create_options, /* create_options */
1281 open_attr, /* file_attributes */
1282 oplock_request, /* oplock_request */
1283 open_size, /* allocation_size */
1284 private_flags,
1285 NULL, /* sd */
1286 ea_list, /* ea_list */
1287 &fsp, /* result */
1288 &smb_action); /* psbuf */
1290 if (!NT_STATUS_IS_OK(status)) {
1291 if (open_was_deferred(req->sconn, req->mid)) {
1292 /* We have re-scheduled this call. */
1293 goto out;
1295 reply_openerror(req, status);
1296 goto out;
1299 size = get_file_size_stat(&smb_fname->st);
1300 fattr = dos_mode(conn, smb_fname);
1301 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1302 inode = smb_fname->st.st_ex_ino;
1303 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1304 close_file(req, fsp, ERROR_CLOSE);
1305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1306 goto out;
1309 /* Realloc the size of parameters and data we will return */
1310 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1311 if(*pparams == NULL ) {
1312 reply_nterror(req, NT_STATUS_NO_MEMORY);
1313 goto out;
1315 params = *pparams;
1317 SSVAL(params,0,fsp->fnum);
1318 SSVAL(params,2,fattr);
1319 srv_put_dos_date2(params,4, mtime);
1320 SIVAL(params,8, (uint32)size);
1321 SSVAL(params,12,deny_mode);
1322 SSVAL(params,14,0); /* open_type - file or directory. */
1323 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1325 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1326 smb_action |= EXTENDED_OPLOCK_GRANTED;
1329 SSVAL(params,18,smb_action);
1332 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1334 SIVAL(params,20,inode);
1335 SSVAL(params,24,0); /* Padding. */
1336 if (flags & 8) {
1337 uint32 ea_size = estimate_ea_size(conn, fsp,
1338 smb_fname);
1339 SIVAL(params, 26, ea_size);
1340 } else {
1341 SIVAL(params, 26, 0);
1344 /* Send the required number of replies */
1345 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1346 out:
1347 TALLOC_FREE(smb_fname);
1350 /*********************************************************
1351 Routine to check if a given string matches exactly.
1352 as a special case a mask of "." does NOT match. That
1353 is required for correct wildcard semantics
1354 Case can be significant or not.
1355 **********************************************************/
1357 static bool exact_match(bool has_wild,
1358 bool case_sensitive,
1359 const char *str,
1360 const char *mask)
1362 if (mask[0] == '.' && mask[1] == 0) {
1363 return false;
1366 if (has_wild) {
1367 return false;
1370 if (case_sensitive) {
1371 return strcmp(str,mask)==0;
1372 } else {
1373 return strcasecmp_m(str,mask) == 0;
1377 /****************************************************************************
1378 Return the filetype for UNIX extensions.
1379 ****************************************************************************/
1381 static uint32 unix_filetype(mode_t mode)
1383 if(S_ISREG(mode))
1384 return UNIX_TYPE_FILE;
1385 else if(S_ISDIR(mode))
1386 return UNIX_TYPE_DIR;
1387 #ifdef S_ISLNK
1388 else if(S_ISLNK(mode))
1389 return UNIX_TYPE_SYMLINK;
1390 #endif
1391 #ifdef S_ISCHR
1392 else if(S_ISCHR(mode))
1393 return UNIX_TYPE_CHARDEV;
1394 #endif
1395 #ifdef S_ISBLK
1396 else if(S_ISBLK(mode))
1397 return UNIX_TYPE_BLKDEV;
1398 #endif
1399 #ifdef S_ISFIFO
1400 else if(S_ISFIFO(mode))
1401 return UNIX_TYPE_FIFO;
1402 #endif
1403 #ifdef S_ISSOCK
1404 else if(S_ISSOCK(mode))
1405 return UNIX_TYPE_SOCKET;
1406 #endif
1408 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1409 return UNIX_TYPE_UNKNOWN;
1412 /****************************************************************************
1413 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1414 ****************************************************************************/
1416 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1418 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1419 const SMB_STRUCT_STAT *psbuf,
1420 uint32 perms,
1421 enum perm_type ptype,
1422 mode_t *ret_perms)
1424 mode_t ret = 0;
1426 if (perms == SMB_MODE_NO_CHANGE) {
1427 if (!VALID_STAT(*psbuf)) {
1428 return NT_STATUS_INVALID_PARAMETER;
1429 } else {
1430 *ret_perms = psbuf->st_ex_mode;
1431 return NT_STATUS_OK;
1435 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1436 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1437 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1438 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1439 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1440 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1441 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1442 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1443 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1444 #ifdef S_ISVTX
1445 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1446 #endif
1447 #ifdef S_ISGID
1448 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1449 #endif
1450 #ifdef S_ISUID
1451 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1452 #endif
1454 switch (ptype) {
1455 case PERM_NEW_FILE:
1456 case PERM_EXISTING_FILE:
1457 /* Apply mode mask */
1458 ret &= lp_create_mask(SNUM(conn));
1459 /* Add in force bits */
1460 ret |= lp_force_create_mode(SNUM(conn));
1461 break;
1462 case PERM_NEW_DIR:
1463 case PERM_EXISTING_DIR:
1464 ret &= lp_dir_mask(SNUM(conn));
1465 /* Add in force bits */
1466 ret |= lp_force_dir_mode(SNUM(conn));
1467 break;
1470 *ret_perms = ret;
1471 return NT_STATUS_OK;
1474 /****************************************************************************
1475 Needed to show the msdfs symlinks as directories. Modifies psbuf
1476 to be a directory if it's a msdfs link.
1477 ****************************************************************************/
1479 static bool check_msdfs_link(connection_struct *conn,
1480 const char *pathname,
1481 SMB_STRUCT_STAT *psbuf)
1483 int saved_errno = errno;
1484 if(lp_host_msdfs() &&
1485 lp_msdfs_root(SNUM(conn)) &&
1486 is_msdfs_link(conn, pathname, psbuf)) {
1488 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1489 "as a directory\n",
1490 pathname));
1491 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1492 errno = saved_errno;
1493 return true;
1495 errno = saved_errno;
1496 return false;
1500 /****************************************************************************
1501 Get a level dependent lanman2 dir entry.
1502 ****************************************************************************/
1504 struct smbd_dirptr_lanman2_state {
1505 connection_struct *conn;
1506 uint32_t info_level;
1507 bool check_mangled_names;
1508 bool has_wild;
1509 bool got_exact_match;
1512 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1513 void *private_data,
1514 const char *dname,
1515 const char *mask,
1516 char **_fname)
1518 struct smbd_dirptr_lanman2_state *state =
1519 (struct smbd_dirptr_lanman2_state *)private_data;
1520 bool ok;
1521 char mangled_name[13]; /* mangled 8.3 name. */
1522 bool got_match;
1523 const char *fname;
1525 /* Mangle fname if it's an illegal name. */
1526 if (mangle_must_mangle(dname, state->conn->params)) {
1527 ok = name_to_8_3(dname, mangled_name,
1528 true, state->conn->params);
1529 if (!ok) {
1530 return false;
1532 fname = mangled_name;
1533 } else {
1534 fname = dname;
1537 got_match = exact_match(state->has_wild,
1538 state->conn->case_sensitive,
1539 fname, mask);
1540 state->got_exact_match = got_match;
1541 if (!got_match) {
1542 got_match = mask_match(fname, mask,
1543 state->conn->case_sensitive);
1546 if(!got_match && state->check_mangled_names &&
1547 !mangle_is_8_3(fname, false, state->conn->params)) {
1549 * It turns out that NT matches wildcards against
1550 * both long *and* short names. This may explain some
1551 * of the wildcard wierdness from old DOS clients
1552 * that some people have been seeing.... JRA.
1554 /* Force the mangling into 8.3. */
1555 ok = name_to_8_3(fname, mangled_name,
1556 false, state->conn->params);
1557 if (!ok) {
1558 return false;
1561 got_match = exact_match(state->has_wild,
1562 state->conn->case_sensitive,
1563 mangled_name, mask);
1564 state->got_exact_match = got_match;
1565 if (!got_match) {
1566 got_match = mask_match(mangled_name, mask,
1567 state->conn->case_sensitive);
1571 if (!got_match) {
1572 return false;
1575 *_fname = talloc_strdup(ctx, fname);
1576 if (*_fname == NULL) {
1577 return false;
1580 return true;
1583 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1584 void *private_data,
1585 struct smb_filename *smb_fname,
1586 uint32_t *_mode)
1588 struct smbd_dirptr_lanman2_state *state =
1589 (struct smbd_dirptr_lanman2_state *)private_data;
1590 bool ms_dfs_link = false;
1591 uint32_t mode = 0;
1593 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1594 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1595 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1596 "Couldn't lstat [%s] (%s)\n",
1597 smb_fname_str_dbg(smb_fname),
1598 strerror(errno)));
1599 return false;
1601 } else if (!VALID_STAT(smb_fname->st) &&
1602 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1603 /* Needed to show the msdfs symlinks as
1604 * directories */
1606 ms_dfs_link = check_msdfs_link(state->conn,
1607 smb_fname->base_name,
1608 &smb_fname->st);
1609 if (!ms_dfs_link) {
1610 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1611 "Couldn't stat [%s] (%s)\n",
1612 smb_fname_str_dbg(smb_fname),
1613 strerror(errno)));
1614 return false;
1618 if (ms_dfs_link) {
1619 mode = dos_mode_msdfs(state->conn, smb_fname);
1620 } else {
1621 mode = dos_mode(state->conn, smb_fname);
1624 *_mode = mode;
1625 return true;
1628 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1629 connection_struct *conn,
1630 uint16_t flags2,
1631 uint32_t info_level,
1632 struct ea_list *name_list,
1633 bool check_mangled_names,
1634 bool requires_resume_key,
1635 uint32_t mode,
1636 const char *fname,
1637 const struct smb_filename *smb_fname,
1638 int space_remaining,
1639 uint8_t align,
1640 bool do_pad,
1641 char *base_data,
1642 char **ppdata,
1643 char *end_data,
1644 bool *out_of_space,
1645 uint64_t *last_entry_off)
1647 char *p, *q, *pdata = *ppdata;
1648 uint32_t reskey=0;
1649 uint64_t file_size = 0;
1650 uint64_t allocation_size = 0;
1651 uint64_t file_index = 0;
1652 uint32_t len;
1653 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1654 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1655 char *nameptr;
1656 char *last_entry_ptr;
1657 bool was_8_3;
1658 int off;
1659 int pad = 0;
1661 *out_of_space = false;
1663 ZERO_STRUCT(mdate_ts);
1664 ZERO_STRUCT(adate_ts);
1665 ZERO_STRUCT(create_date_ts);
1666 ZERO_STRUCT(cdate_ts);
1668 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1669 file_size = get_file_size_stat(&smb_fname->st);
1671 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1673 file_index = get_FileIndex(conn, &smb_fname->st);
1675 mdate_ts = smb_fname->st.st_ex_mtime;
1676 adate_ts = smb_fname->st.st_ex_atime;
1677 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1678 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1680 if (lp_dos_filetime_resolution(SNUM(conn))) {
1681 dos_filetime_timespec(&create_date_ts);
1682 dos_filetime_timespec(&mdate_ts);
1683 dos_filetime_timespec(&adate_ts);
1684 dos_filetime_timespec(&cdate_ts);
1687 create_date = convert_timespec_to_time_t(create_date_ts);
1688 mdate = convert_timespec_to_time_t(mdate_ts);
1689 adate = convert_timespec_to_time_t(adate_ts);
1691 /* align the record */
1692 SMB_ASSERT(align >= 1);
1694 off = (int)PTR_DIFF(pdata, base_data);
1695 pad = (off + (align-1)) & ~(align-1);
1696 pad -= off;
1698 if (pad && pad > space_remaining) {
1699 *out_of_space = true;
1700 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1701 "for padding (wanted %u, had %d)\n",
1702 (unsigned int)pad,
1703 space_remaining ));
1704 return false; /* Not finished - just out of space */
1707 off += pad;
1708 /* initialize padding to 0 */
1709 if (pad) {
1710 memset(pdata, 0, pad);
1712 space_remaining -= pad;
1714 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1715 space_remaining ));
1717 pdata += pad;
1718 p = pdata;
1719 last_entry_ptr = p;
1721 pad = 0;
1722 off = 0;
1724 switch (info_level) {
1725 case SMB_FIND_INFO_STANDARD:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
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 += 23;
1738 nameptr = p;
1739 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1740 p += ucs2_align(base_data, p, 0);
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE);
1745 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1746 if (len > 2) {
1747 SCVAL(nameptr, -1, len - 2);
1748 } else {
1749 SCVAL(nameptr, -1, 0);
1751 } else {
1752 if (len > 1) {
1753 SCVAL(nameptr, -1, len - 1);
1754 } else {
1755 SCVAL(nameptr, -1, 0);
1758 p += len;
1759 break;
1761 case SMB_FIND_EA_SIZE:
1762 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1763 if (requires_resume_key) {
1764 SIVAL(p,0,reskey);
1765 p += 4;
1767 srv_put_dos_date2(p,0,create_date);
1768 srv_put_dos_date2(p,4,adate);
1769 srv_put_dos_date2(p,8,mdate);
1770 SIVAL(p,12,(uint32)file_size);
1771 SIVAL(p,16,(uint32)allocation_size);
1772 SSVAL(p,20,mode);
1774 unsigned int ea_size = estimate_ea_size(conn, NULL,
1775 smb_fname);
1776 SIVAL(p,22,ea_size); /* Extended attributes */
1778 p += 27;
1779 nameptr = p - 1;
1780 len = srvstr_push(base_data, flags2,
1781 p, fname, PTR_DIFF(end_data, p),
1782 STR_TERMINATE | STR_NOALIGN);
1783 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1784 if (len > 2) {
1785 len -= 2;
1786 } else {
1787 len = 0;
1789 } else {
1790 if (len > 1) {
1791 len -= 1;
1792 } else {
1793 len = 0;
1796 SCVAL(nameptr,0,len);
1797 p += len;
1798 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1799 break;
1801 case SMB_FIND_EA_LIST:
1803 struct ea_list *file_list = NULL;
1804 size_t ea_len = 0;
1805 NTSTATUS status;
1807 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1808 if (!name_list) {
1809 return false;
1811 if (requires_resume_key) {
1812 SIVAL(p,0,reskey);
1813 p += 4;
1815 srv_put_dos_date2(p,0,create_date);
1816 srv_put_dos_date2(p,4,adate);
1817 srv_put_dos_date2(p,8,mdate);
1818 SIVAL(p,12,(uint32)file_size);
1819 SIVAL(p,16,(uint32)allocation_size);
1820 SSVAL(p,20,mode);
1821 p += 22; /* p now points to the EA area. */
1823 status = get_ea_list_from_file(ctx, conn, NULL,
1824 smb_fname,
1825 &ea_len, &file_list);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 file_list = NULL;
1829 name_list = ea_list_union(name_list, file_list, &ea_len);
1831 /* We need to determine if this entry will fit in the space available. */
1832 /* Max string size is 255 bytes. */
1833 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1834 *out_of_space = true;
1835 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1836 "(wanted %u, had %d)\n",
1837 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1838 space_remaining ));
1839 return False; /* Not finished - just out of space */
1842 /* Push the ea_data followed by the name. */
1843 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1844 nameptr = p;
1845 len = srvstr_push(base_data, flags2,
1846 p + 1, fname, PTR_DIFF(end_data, p+1),
1847 STR_TERMINATE | STR_NOALIGN);
1848 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1849 if (len > 2) {
1850 len -= 2;
1851 } else {
1852 len = 0;
1854 } else {
1855 if (len > 1) {
1856 len -= 1;
1857 } else {
1858 len = 0;
1861 SCVAL(nameptr,0,len);
1862 p += len + 1;
1863 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1864 break;
1867 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1868 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1869 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1870 p += 4;
1871 SIVAL(p,0,reskey); p += 4;
1872 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1876 SOFF_T(p,0,file_size); p += 8;
1877 SOFF_T(p,0,allocation_size); p += 8;
1878 SIVAL(p,0,mode); p += 4;
1879 q = p; p += 4; /* q is placeholder for name length. */
1881 unsigned int ea_size = estimate_ea_size(conn, NULL,
1882 smb_fname);
1883 SIVAL(p,0,ea_size); /* Extended attributes */
1884 p += 4;
1886 /* Clear the short name buffer. This is
1887 * IMPORTANT as not doing so will trigger
1888 * a Win2k client bug. JRA.
1890 if (!was_8_3 && check_mangled_names) {
1891 char mangled_name[13]; /* mangled 8.3 name. */
1892 if (!name_to_8_3(fname,mangled_name,True,
1893 conn->params)) {
1894 /* Error - mangle failed ! */
1895 memset(mangled_name,'\0',12);
1897 mangled_name[12] = 0;
1898 len = srvstr_push(base_data, flags2,
1899 p+2, mangled_name, 24,
1900 STR_UPPER|STR_UNICODE);
1901 if (len < 24) {
1902 memset(p + 2 + len,'\0',24 - len);
1904 SSVAL(p, 0, len);
1905 } else {
1906 memset(p,'\0',26);
1908 p += 2 + 24;
1909 len = srvstr_push(base_data, flags2, p,
1910 fname, PTR_DIFF(end_data, p),
1911 STR_TERMINATE_ASCII);
1912 SIVAL(q,0,len);
1913 p += len;
1915 len = PTR_DIFF(p, pdata);
1916 pad = (len + (align-1)) & ~(align-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1922 SIVAL(pdata,0,pad);
1924 * set padding to zero
1926 if (do_pad) {
1927 memset(p, 0, pad - len);
1928 p = pdata + pad;
1929 } else {
1930 p = pdata + len;
1932 break;
1934 case SMB_FIND_FILE_DIRECTORY_INFO:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1936 p += 4;
1937 SIVAL(p,0,reskey); p += 4;
1938 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1939 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1940 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1941 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1942 SOFF_T(p,0,file_size); p += 8;
1943 SOFF_T(p,0,allocation_size); p += 8;
1944 SIVAL(p,0,mode); p += 4;
1945 len = srvstr_push(base_data, flags2,
1946 p + 4, fname, PTR_DIFF(end_data, p+4),
1947 STR_TERMINATE_ASCII);
1948 SIVAL(p,0,len);
1949 p += 4 + len;
1951 len = PTR_DIFF(p, pdata);
1952 pad = (len + (align-1)) & ~(align-1);
1954 * offset to the next entry, the caller
1955 * will overwrite it for the last entry
1956 * that's why we always include the padding
1958 SIVAL(pdata,0,pad);
1960 * set padding to zero
1962 if (do_pad) {
1963 memset(p, 0, pad - len);
1964 p = pdata + pad;
1965 } else {
1966 p = pdata + len;
1968 break;
1970 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1971 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1972 p += 4;
1973 SIVAL(p,0,reskey); p += 4;
1974 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1975 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1976 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1977 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1978 SOFF_T(p,0,file_size); p += 8;
1979 SOFF_T(p,0,allocation_size); p += 8;
1980 SIVAL(p,0,mode); p += 4;
1981 q = p; p += 4; /* q is placeholder for name length. */
1983 unsigned int ea_size = estimate_ea_size(conn, NULL,
1984 smb_fname);
1985 SIVAL(p,0,ea_size); /* Extended attributes */
1986 p +=4;
1988 len = srvstr_push(base_data, flags2, p,
1989 fname, PTR_DIFF(end_data, p),
1990 STR_TERMINATE_ASCII);
1991 SIVAL(q, 0, len);
1992 p += len;
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2001 SIVAL(pdata,0,pad);
2003 * set padding to zero
2005 if (do_pad) {
2006 memset(p, 0, pad - len);
2007 p = pdata + pad;
2008 } else {
2009 p = pdata + len;
2011 break;
2013 case SMB_FIND_FILE_NAMES_INFO:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2015 p += 4;
2016 SIVAL(p,0,reskey); p += 4;
2017 p += 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 len = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2022 STR_TERMINATE_ASCII);
2023 SIVAL(p, -4, len);
2024 p += len;
2026 len = PTR_DIFF(p, pdata);
2027 pad = (len + (align-1)) & ~(align-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2033 SIVAL(pdata,0,pad);
2035 * set padding to zero
2037 if (do_pad) {
2038 memset(p, 0, pad - len);
2039 p = pdata + pad;
2040 } else {
2041 p = pdata + len;
2043 break;
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2047 p += 4;
2048 SIVAL(p,0,reskey); p += 4;
2049 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2051 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2053 SOFF_T(p,0,file_size); p += 8;
2054 SOFF_T(p,0,allocation_size); p += 8;
2055 SIVAL(p,0,mode); p += 4;
2056 q = p; p += 4; /* q is placeholder for name length. */
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2059 smb_fname);
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2061 p +=4;
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 len = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII);
2068 SIVAL(q, 0, len);
2069 p += len;
2071 len = PTR_DIFF(p, pdata);
2072 pad = (len + (align-1)) & ~(align-1);
2074 * offset to the next entry, the caller
2075 * will overwrite it for the last entry
2076 * that's why we always include the padding
2078 SIVAL(pdata,0,pad);
2080 * set padding to zero
2082 if (do_pad) {
2083 memset(p, 0, pad - len);
2084 p = pdata + pad;
2085 } else {
2086 p = pdata + len;
2088 break;
2090 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2092 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2093 p += 4;
2094 SIVAL(p,0,reskey); p += 4;
2095 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2096 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2097 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2098 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2099 SOFF_T(p,0,file_size); p += 8;
2100 SOFF_T(p,0,allocation_size); p += 8;
2101 SIVAL(p,0,mode); p += 4;
2102 q = p; p += 4; /* q is placeholder for name length */
2104 unsigned int ea_size = estimate_ea_size(conn, NULL,
2105 smb_fname);
2106 SIVAL(p,0,ea_size); /* Extended attributes */
2107 p +=4;
2109 /* Clear the short name buffer. This is
2110 * IMPORTANT as not doing so will trigger
2111 * a Win2k client bug. JRA.
2113 if (!was_8_3 && check_mangled_names) {
2114 char mangled_name[13]; /* mangled 8.3 name. */
2115 if (!name_to_8_3(fname,mangled_name,True,
2116 conn->params)) {
2117 /* Error - mangle failed ! */
2118 memset(mangled_name,'\0',12);
2120 mangled_name[12] = 0;
2121 len = srvstr_push(base_data, flags2,
2122 p+2, mangled_name, 24,
2123 STR_UPPER|STR_UNICODE);
2124 SSVAL(p, 0, len);
2125 if (len < 24) {
2126 memset(p + 2 + len,'\0',24 - len);
2128 SSVAL(p, 0, len);
2129 } else {
2130 memset(p,'\0',26);
2132 p += 26;
2133 SSVAL(p,0,0); p += 2; /* Reserved ? */
2134 SBVAL(p,0,file_index); p += 8;
2135 len = srvstr_push(base_data, flags2, p,
2136 fname, PTR_DIFF(end_data, p),
2137 STR_TERMINATE_ASCII);
2138 SIVAL(q,0,len);
2139 p += len;
2141 len = PTR_DIFF(p, pdata);
2142 pad = (len + (align-1)) & ~(align-1);
2144 * offset to the next entry, the caller
2145 * will overwrite it for the last entry
2146 * that's why we always include the padding
2148 SIVAL(pdata,0,pad);
2150 * set padding to zero
2152 if (do_pad) {
2153 memset(p, 0, pad - len);
2154 p = pdata + pad;
2155 } else {
2156 p = pdata + len;
2158 break;
2160 /* CIFS UNIX Extension. */
2162 case SMB_FIND_FILE_UNIX:
2163 case SMB_FIND_FILE_UNIX_INFO2:
2164 p+= 4;
2165 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2167 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2169 if (info_level == SMB_FIND_FILE_UNIX) {
2170 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2171 p = store_file_unix_basic(conn, p,
2172 NULL, &smb_fname->st);
2173 len = srvstr_push(base_data, flags2, p,
2174 fname, PTR_DIFF(end_data, p),
2175 STR_TERMINATE);
2176 } else {
2177 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2178 p = store_file_unix_basic_info2(conn, p,
2179 NULL, &smb_fname->st);
2180 nameptr = p;
2181 p += 4;
2182 len = srvstr_push(base_data, flags2, p, fname,
2183 PTR_DIFF(end_data, p), 0);
2184 SIVAL(nameptr, 0, len);
2187 p += len;
2189 len = PTR_DIFF(p, pdata);
2190 pad = (len + (align-1)) & ~(align-1);
2192 * offset to the next entry, the caller
2193 * will overwrite it for the last entry
2194 * that's why we always include the padding
2196 SIVAL(pdata,0,pad);
2198 * set padding to zero
2200 if (do_pad) {
2201 memset(p, 0, pad - len);
2202 p = pdata + pad;
2203 } else {
2204 p = pdata + len;
2206 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2208 break;
2210 default:
2211 return false;
2214 if (PTR_DIFF(p,pdata) > space_remaining) {
2215 *out_of_space = true;
2216 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2217 "(wanted %u, had %d)\n",
2218 (unsigned int)PTR_DIFF(p,pdata),
2219 space_remaining ));
2220 return false; /* Not finished - just out of space */
2223 /* Setup the last entry pointer, as an offset from base_data */
2224 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2225 /* Advance the data pointer to the next slot */
2226 *ppdata = p;
2228 return true;
2231 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2232 connection_struct *conn,
2233 struct dptr_struct *dirptr,
2234 uint16 flags2,
2235 const char *path_mask,
2236 uint32 dirtype,
2237 int info_level,
2238 int requires_resume_key,
2239 bool dont_descend,
2240 bool ask_sharemode,
2241 uint8_t align,
2242 bool do_pad,
2243 char **ppdata,
2244 char *base_data,
2245 char *end_data,
2246 int space_remaining,
2247 bool *out_of_space,
2248 bool *got_exact_match,
2249 int *_last_entry_off,
2250 struct ea_list *name_list)
2252 const char *p;
2253 const char *mask = NULL;
2254 long prev_dirpos = 0;
2255 uint32_t mode = 0;
2256 char *fname = NULL;
2257 struct smb_filename *smb_fname = NULL;
2258 struct smbd_dirptr_lanman2_state state;
2259 bool ok;
2260 uint64_t last_entry_off = 0;
2262 ZERO_STRUCT(state);
2263 state.conn = conn;
2264 state.info_level = info_level;
2265 state.check_mangled_names = lp_manglednames(conn->params);
2266 state.has_wild = dptr_has_wild(dirptr);
2267 state.got_exact_match = false;
2269 *out_of_space = false;
2270 *got_exact_match = false;
2272 p = strrchr_m(path_mask,'/');
2273 if(p != NULL) {
2274 if(p[1] == '\0') {
2275 mask = "*.*";
2276 } else {
2277 mask = p+1;
2279 } else {
2280 mask = path_mask;
2283 ok = smbd_dirptr_get_entry(ctx,
2284 dirptr,
2285 mask,
2286 dirtype,
2287 dont_descend,
2288 ask_sharemode,
2289 smbd_dirptr_lanman2_match_fn,
2290 smbd_dirptr_lanman2_mode_fn,
2291 &state,
2292 &fname,
2293 &smb_fname,
2294 &mode,
2295 &prev_dirpos);
2296 if (!ok) {
2297 return false;
2300 *got_exact_match = state.got_exact_match;
2302 ok = smbd_marshall_dir_entry(ctx,
2303 conn,
2304 flags2,
2305 info_level,
2306 name_list,
2307 state.check_mangled_names,
2308 requires_resume_key,
2309 mode,
2310 fname,
2311 smb_fname,
2312 space_remaining,
2313 align,
2314 do_pad,
2315 base_data,
2316 ppdata,
2317 end_data,
2318 out_of_space,
2319 &last_entry_off);
2320 TALLOC_FREE(fname);
2321 TALLOC_FREE(smb_fname);
2322 if (*out_of_space) {
2323 dptr_SeekDir(dirptr, prev_dirpos);
2324 return false;
2326 if (!ok) {
2327 return false;
2330 *_last_entry_off = last_entry_off;
2331 return true;
2334 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2335 connection_struct *conn,
2336 struct dptr_struct *dirptr,
2337 uint16 flags2,
2338 const char *path_mask,
2339 uint32 dirtype,
2340 int info_level,
2341 bool requires_resume_key,
2342 bool dont_descend,
2343 bool ask_sharemode,
2344 char **ppdata,
2345 char *base_data,
2346 char *end_data,
2347 int space_remaining,
2348 bool *out_of_space,
2349 bool *got_exact_match,
2350 int *last_entry_off,
2351 struct ea_list *name_list)
2353 uint8_t align = 4;
2354 const bool do_pad = true;
2356 if (info_level >= 1 && info_level <= 3) {
2357 /* No alignment on earlier info levels. */
2358 align = 1;
2361 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2362 path_mask, dirtype, info_level,
2363 requires_resume_key, dont_descend, ask_sharemode,
2364 align, do_pad,
2365 ppdata, base_data, end_data,
2366 space_remaining,
2367 out_of_space, got_exact_match,
2368 last_entry_off, name_list);
2371 /****************************************************************************
2372 Reply to a TRANS2_FINDFIRST.
2373 ****************************************************************************/
2375 static void call_trans2findfirst(connection_struct *conn,
2376 struct smb_request *req,
2377 char **pparams, int total_params,
2378 char **ppdata, int total_data,
2379 unsigned int max_data_bytes)
2381 /* We must be careful here that we don't return more than the
2382 allowed number of data bytes. If this means returning fewer than
2383 maxentries then so be it. We assume that the redirector has
2384 enough room for the fixed number of parameter bytes it has
2385 requested. */
2386 struct smb_filename *smb_dname = NULL;
2387 char *params = *pparams;
2388 char *pdata = *ppdata;
2389 char *data_end;
2390 uint32 dirtype;
2391 int maxentries;
2392 uint16 findfirst_flags;
2393 bool close_after_first;
2394 bool close_if_end;
2395 bool requires_resume_key;
2396 int info_level;
2397 char *directory = NULL;
2398 char *mask = NULL;
2399 char *p;
2400 int last_entry_off=0;
2401 int dptr_num = -1;
2402 int numentries = 0;
2403 int i;
2404 bool finished = False;
2405 bool dont_descend = False;
2406 bool out_of_space = False;
2407 int space_remaining;
2408 bool mask_contains_wcard = False;
2409 struct ea_list *ea_list = NULL;
2410 NTSTATUS ntstatus = NT_STATUS_OK;
2411 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2412 TALLOC_CTX *ctx = talloc_tos();
2413 struct dptr_struct *dirptr = NULL;
2414 struct smbd_server_connection *sconn = req->sconn;
2415 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2416 bool backup_priv = false;
2418 if (total_params < 13) {
2419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2420 goto out;
2423 dirtype = SVAL(params,0);
2424 maxentries = SVAL(params,2);
2425 findfirst_flags = SVAL(params,4);
2426 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2427 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2428 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2429 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2430 security_token_has_privilege(get_current_nttok(conn),
2431 SEC_PRIV_BACKUP));
2433 info_level = SVAL(params,6);
2435 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2436 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2437 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2438 (int)backup_priv,
2439 info_level, max_data_bytes));
2441 if (!maxentries) {
2442 /* W2K3 seems to treat zero as 1. */
2443 maxentries = 1;
2446 switch (info_level) {
2447 case SMB_FIND_INFO_STANDARD:
2448 case SMB_FIND_EA_SIZE:
2449 case SMB_FIND_EA_LIST:
2450 case SMB_FIND_FILE_DIRECTORY_INFO:
2451 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2452 case SMB_FIND_FILE_NAMES_INFO:
2453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2454 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2455 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2456 break;
2457 case SMB_FIND_FILE_UNIX:
2458 case SMB_FIND_FILE_UNIX_INFO2:
2459 /* Always use filesystem for UNIX mtime query. */
2460 ask_sharemode = false;
2461 if (!lp_unix_extensions()) {
2462 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2463 goto out;
2465 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2466 break;
2467 default:
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2469 goto out;
2472 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2473 params+12, total_params - 12,
2474 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2475 if (!NT_STATUS_IS_OK(ntstatus)) {
2476 reply_nterror(req, ntstatus);
2477 goto out;
2480 if (backup_priv) {
2481 become_root();
2482 ntstatus = filename_convert_with_privilege(ctx,
2483 conn,
2484 req,
2485 directory,
2486 ucf_flags,
2487 &mask_contains_wcard,
2488 &smb_dname);
2489 } else {
2490 ntstatus = filename_convert(ctx, conn,
2491 req->flags2 & FLAGS2_DFS_PATHNAMES,
2492 directory,
2493 ucf_flags,
2494 &mask_contains_wcard,
2495 &smb_dname);
2498 if (!NT_STATUS_IS_OK(ntstatus)) {
2499 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2501 ERRSRV, ERRbadpath);
2502 goto out;
2504 reply_nterror(req, ntstatus);
2505 goto out;
2508 mask = smb_dname->original_lcomp;
2510 directory = smb_dname->base_name;
2512 p = strrchr_m(directory,'/');
2513 if(p == NULL) {
2514 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2515 if((directory[0] == '.') && (directory[1] == '\0')) {
2516 mask = talloc_strdup(ctx,"*");
2517 if (!mask) {
2518 reply_nterror(req, NT_STATUS_NO_MEMORY);
2519 goto out;
2521 mask_contains_wcard = True;
2523 } else {
2524 *p = 0;
2527 if (p == NULL || p == directory) {
2528 /* Ensure we don't have a directory name of "". */
2529 directory = talloc_strdup(talloc_tos(), ".");
2530 if (!directory) {
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2532 goto out;
2536 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2538 if (info_level == SMB_FIND_EA_LIST) {
2539 uint32 ea_size;
2541 if (total_data < 4) {
2542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2543 goto out;
2546 ea_size = IVAL(pdata,0);
2547 if (ea_size != total_data) {
2548 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2549 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2551 goto out;
2554 if (!lp_ea_support(SNUM(conn))) {
2555 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2556 goto out;
2559 /* Pull out the list of names. */
2560 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2561 if (!ea_list) {
2562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2563 goto out;
2567 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2569 goto out;
2572 *ppdata = (char *)SMB_REALLOC(
2573 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2574 if(*ppdata == NULL ) {
2575 reply_nterror(req, NT_STATUS_NO_MEMORY);
2576 goto out;
2578 pdata = *ppdata;
2579 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2581 /* Realloc the params space */
2582 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2583 if (*pparams == NULL) {
2584 reply_nterror(req, NT_STATUS_NO_MEMORY);
2585 goto out;
2587 params = *pparams;
2589 /* Save the wildcard match and attribs we are using on this directory -
2590 needed as lanman2 assumes these are being saved between calls */
2592 ntstatus = dptr_create(conn,
2593 req,
2594 NULL, /* fsp */
2595 directory,
2596 False,
2597 True,
2598 req->smbpid,
2599 mask,
2600 mask_contains_wcard,
2601 dirtype,
2602 &dirptr);
2604 if (!NT_STATUS_IS_OK(ntstatus)) {
2605 reply_nterror(req, ntstatus);
2606 goto out;
2609 if (backup_priv) {
2610 /* Remember this in case we have
2611 to do a findnext. */
2612 dptr_set_priv(dirptr);
2615 dptr_num = dptr_dnum(dirptr);
2616 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2618 /* Initialize per TRANS2_FIND_FIRST operation data */
2619 dptr_init_search_op(dirptr);
2621 /* We don't need to check for VOL here as this is returned by
2622 a different TRANS2 call. */
2624 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2625 directory,lp_dontdescend(ctx, SNUM(conn))));
2626 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2627 dont_descend = True;
2629 p = pdata;
2630 space_remaining = max_data_bytes;
2631 out_of_space = False;
2633 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2634 bool got_exact_match = False;
2636 /* this is a heuristic to avoid seeking the dirptr except when
2637 absolutely necessary. It allows for a filename of about 40 chars */
2638 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2639 out_of_space = True;
2640 finished = False;
2641 } else {
2642 finished = !get_lanman2_dir_entry(ctx,
2643 conn,
2644 dirptr,
2645 req->flags2,
2646 mask,dirtype,info_level,
2647 requires_resume_key,dont_descend,
2648 ask_sharemode,
2649 &p,pdata,data_end,
2650 space_remaining, &out_of_space,
2651 &got_exact_match,
2652 &last_entry_off, ea_list);
2655 if (finished && out_of_space)
2656 finished = False;
2658 if (!finished && !out_of_space)
2659 numentries++;
2662 * As an optimisation if we know we aren't looking
2663 * for a wildcard name (ie. the name matches the wildcard exactly)
2664 * then we can finish on any (first) match.
2665 * This speeds up large directory searches. JRA.
2668 if(got_exact_match)
2669 finished = True;
2671 /* Ensure space_remaining never goes -ve. */
2672 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2673 space_remaining = 0;
2674 out_of_space = true;
2675 } else {
2676 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2680 /* Check if we can close the dirptr */
2681 if(close_after_first || (finished && close_if_end)) {
2682 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2683 dptr_close(sconn, &dptr_num);
2687 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2688 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2689 * the protocol level is less than NT1. Tested with smbclient. JRA.
2690 * This should fix the OS/2 client bug #2335.
2693 if(numentries == 0) {
2694 dptr_close(sconn, &dptr_num);
2695 if (get_Protocol() < PROTOCOL_NT1) {
2696 reply_force_doserror(req, ERRDOS, ERRnofiles);
2697 goto out;
2698 } else {
2699 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2700 ERRDOS, ERRbadfile);
2701 goto out;
2705 /* At this point pdata points to numentries directory entries. */
2707 /* Set up the return parameter block */
2708 SSVAL(params,0,dptr_num);
2709 SSVAL(params,2,numentries);
2710 SSVAL(params,4,finished);
2711 SSVAL(params,6,0); /* Never an EA error */
2712 SSVAL(params,8,last_entry_off);
2714 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2715 max_data_bytes);
2717 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2718 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2719 if (!directory) {
2720 reply_nterror(req, NT_STATUS_NO_MEMORY);
2724 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2725 smb_fn_name(req->cmd),
2726 mask, directory, dirtype, numentries ) );
2729 * Force a name mangle here to ensure that the
2730 * mask as an 8.3 name is top of the mangled cache.
2731 * The reasons for this are subtle. Don't remove
2732 * this code unless you know what you are doing
2733 * (see PR#13758). JRA.
2736 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2737 char mangled_name[13];
2738 name_to_8_3(mask, mangled_name, True, conn->params);
2740 out:
2742 if (backup_priv) {
2743 unbecome_root();
2746 TALLOC_FREE(smb_dname);
2747 return;
2750 /****************************************************************************
2751 Reply to a TRANS2_FINDNEXT.
2752 ****************************************************************************/
2754 static void call_trans2findnext(connection_struct *conn,
2755 struct smb_request *req,
2756 char **pparams, int total_params,
2757 char **ppdata, int total_data,
2758 unsigned int max_data_bytes)
2760 /* We must be careful here that we don't return more than the
2761 allowed number of data bytes. If this means returning fewer than
2762 maxentries then so be it. We assume that the redirector has
2763 enough room for the fixed number of parameter bytes it has
2764 requested. */
2765 char *params = *pparams;
2766 char *pdata = *ppdata;
2767 char *data_end;
2768 int dptr_num;
2769 int maxentries;
2770 uint16 info_level;
2771 uint32 resume_key;
2772 uint16 findnext_flags;
2773 bool close_after_request;
2774 bool close_if_end;
2775 bool requires_resume_key;
2776 bool continue_bit;
2777 bool mask_contains_wcard = False;
2778 char *resume_name = NULL;
2779 const char *mask = NULL;
2780 const char *directory = NULL;
2781 char *p = NULL;
2782 uint16 dirtype;
2783 int numentries = 0;
2784 int i, last_entry_off=0;
2785 bool finished = False;
2786 bool dont_descend = False;
2787 bool out_of_space = False;
2788 int space_remaining;
2789 struct ea_list *ea_list = NULL;
2790 NTSTATUS ntstatus = NT_STATUS_OK;
2791 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2792 TALLOC_CTX *ctx = talloc_tos();
2793 struct dptr_struct *dirptr;
2794 struct smbd_server_connection *sconn = req->sconn;
2795 bool backup_priv = false;
2797 if (total_params < 13) {
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 return;
2802 dptr_num = SVAL(params,0);
2803 maxentries = SVAL(params,2);
2804 info_level = SVAL(params,4);
2805 resume_key = IVAL(params,6);
2806 findnext_flags = SVAL(params,10);
2807 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2808 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2809 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2810 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2812 if (!continue_bit) {
2813 /* We only need resume_name if continue_bit is zero. */
2814 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2815 params+12,
2816 total_params - 12, STR_TERMINATE, &ntstatus,
2817 &mask_contains_wcard);
2818 if (!NT_STATUS_IS_OK(ntstatus)) {
2819 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2820 complain (it thinks we're asking for the directory above the shared
2821 path or an invalid name). Catch this as the resume name is only compared, never used in
2822 a file access. JRA. */
2823 srvstr_pull_talloc(ctx, params, req->flags2,
2824 &resume_name, params+12,
2825 total_params - 12,
2826 STR_TERMINATE);
2828 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2829 reply_nterror(req, ntstatus);
2830 return;
2835 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2836 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2837 resume_key = %d resume name = %s continue=%d level = %d\n",
2838 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2839 requires_resume_key, resume_key,
2840 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2842 if (!maxentries) {
2843 /* W2K3 seems to treat zero as 1. */
2844 maxentries = 1;
2847 switch (info_level) {
2848 case SMB_FIND_INFO_STANDARD:
2849 case SMB_FIND_EA_SIZE:
2850 case SMB_FIND_EA_LIST:
2851 case SMB_FIND_FILE_DIRECTORY_INFO:
2852 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2853 case SMB_FIND_FILE_NAMES_INFO:
2854 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2855 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2856 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2857 break;
2858 case SMB_FIND_FILE_UNIX:
2859 case SMB_FIND_FILE_UNIX_INFO2:
2860 /* Always use filesystem for UNIX mtime query. */
2861 ask_sharemode = false;
2862 if (!lp_unix_extensions()) {
2863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2864 return;
2866 break;
2867 default:
2868 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2869 return;
2872 if (info_level == SMB_FIND_EA_LIST) {
2873 uint32 ea_size;
2875 if (total_data < 4) {
2876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2877 return;
2880 ea_size = IVAL(pdata,0);
2881 if (ea_size != total_data) {
2882 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2883 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2885 return;
2888 if (!lp_ea_support(SNUM(conn))) {
2889 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2890 return;
2893 /* Pull out the list of names. */
2894 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2895 if (!ea_list) {
2896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2897 return;
2901 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2903 return;
2906 *ppdata = (char *)SMB_REALLOC(
2907 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2908 if(*ppdata == NULL) {
2909 reply_nterror(req, NT_STATUS_NO_MEMORY);
2910 return;
2913 pdata = *ppdata;
2914 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2916 /* Realloc the params space */
2917 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2918 if(*pparams == NULL ) {
2919 reply_nterror(req, NT_STATUS_NO_MEMORY);
2920 return;
2923 params = *pparams;
2925 /* Check that the dptr is valid */
2926 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2927 reply_nterror(req, STATUS_NO_MORE_FILES);
2928 return;
2931 directory = dptr_path(sconn, dptr_num);
2933 /* Get the wildcard mask from the dptr */
2934 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2935 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2936 reply_nterror(req, STATUS_NO_MORE_FILES);
2937 return;
2940 /* Get the attr mask from the dptr */
2941 dirtype = dptr_attr(sconn, dptr_num);
2943 backup_priv = dptr_get_priv(dirptr);
2945 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2946 "backup_priv = %d\n",
2947 dptr_num, mask, dirtype,
2948 (long)dirptr,
2949 dptr_TellDir(dirptr),
2950 (int)backup_priv));
2952 /* Initialize per TRANS2_FIND_NEXT operation data */
2953 dptr_init_search_op(dirptr);
2955 /* We don't need to check for VOL here as this is returned by
2956 a different TRANS2 call. */
2958 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2959 directory,lp_dontdescend(ctx, SNUM(conn))));
2960 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2961 dont_descend = True;
2963 p = pdata;
2964 space_remaining = max_data_bytes;
2965 out_of_space = False;
2967 if (backup_priv) {
2968 become_root();
2972 * Seek to the correct position. We no longer use the resume key but
2973 * depend on the last file name instead.
2976 if(!continue_bit && resume_name && *resume_name) {
2977 SMB_STRUCT_STAT st;
2979 long current_pos = 0;
2981 * Remember, name_to_8_3 is called by
2982 * get_lanman2_dir_entry(), so the resume name
2983 * could be mangled. Ensure we check the unmangled name.
2986 if (mangle_is_mangled(resume_name, conn->params)) {
2987 char *new_resume_name = NULL;
2988 mangle_lookup_name_from_8_3(ctx,
2989 resume_name,
2990 &new_resume_name,
2991 conn->params);
2992 if (new_resume_name) {
2993 resume_name = new_resume_name;
2998 * Fix for NT redirector problem triggered by resume key indexes
2999 * changing between directory scans. We now return a resume key of 0
3000 * and instead look for the filename to continue from (also given
3001 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3002 * findfirst/findnext (as is usual) then the directory pointer
3003 * should already be at the correct place.
3006 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3007 } /* end if resume_name && !continue_bit */
3009 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3010 bool got_exact_match = False;
3012 /* this is a heuristic to avoid seeking the dirptr except when
3013 absolutely necessary. It allows for a filename of about 40 chars */
3014 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3015 out_of_space = True;
3016 finished = False;
3017 } else {
3018 finished = !get_lanman2_dir_entry(ctx,
3019 conn,
3020 dirptr,
3021 req->flags2,
3022 mask,dirtype,info_level,
3023 requires_resume_key,dont_descend,
3024 ask_sharemode,
3025 &p,pdata,data_end,
3026 space_remaining, &out_of_space,
3027 &got_exact_match,
3028 &last_entry_off, ea_list);
3031 if (finished && out_of_space)
3032 finished = False;
3034 if (!finished && !out_of_space)
3035 numentries++;
3038 * As an optimisation if we know we aren't looking
3039 * for a wildcard name (ie. the name matches the wildcard exactly)
3040 * then we can finish on any (first) match.
3041 * This speeds up large directory searches. JRA.
3044 if(got_exact_match)
3045 finished = True;
3047 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3050 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3051 smb_fn_name(req->cmd),
3052 mask, directory, dirtype, numentries ) );
3054 /* Check if we can close the dirptr */
3055 if(close_after_request || (finished && close_if_end)) {
3056 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3057 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3060 if (backup_priv) {
3061 unbecome_root();
3064 /* Set up the return parameter block */
3065 SSVAL(params,0,numentries);
3066 SSVAL(params,2,finished);
3067 SSVAL(params,4,0); /* Never an EA error */
3068 SSVAL(params,6,last_entry_off);
3070 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3071 max_data_bytes);
3073 return;
3076 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3078 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3079 return objid;
3082 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3084 SMB_ASSERT(extended_info != NULL);
3086 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3087 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3088 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3089 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3090 #ifdef SAMBA_VERSION_REVISION
3091 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3092 #endif
3093 extended_info->samba_subversion = 0;
3094 #ifdef SAMBA_VERSION_RC_RELEASE
3095 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3096 #else
3097 #ifdef SAMBA_VERSION_PRE_RELEASE
3098 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3099 #endif
3100 #endif
3101 #ifdef SAMBA_VERSION_VENDOR_PATCH
3102 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3103 #endif
3104 extended_info->samba_gitcommitdate = 0;
3105 #ifdef SAMBA_VERSION_COMMIT_TIME
3106 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3107 #endif
3109 memset(extended_info->samba_version_string, 0,
3110 sizeof(extended_info->samba_version_string));
3112 snprintf (extended_info->samba_version_string,
3113 sizeof(extended_info->samba_version_string),
3114 "%s", samba_version_string());
3117 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3118 TALLOC_CTX *mem_ctx,
3119 uint16_t info_level,
3120 uint16_t flags2,
3121 unsigned int max_data_bytes,
3122 struct smb_filename *fname,
3123 char **ppdata,
3124 int *ret_data_len)
3126 char *pdata, *end_data;
3127 int data_len = 0, len;
3128 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3129 int snum = SNUM(conn);
3130 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3131 char *filename = NULL;
3132 uint32 additional_flags = 0;
3133 struct smb_filename smb_fname;
3134 SMB_STRUCT_STAT st;
3135 NTSTATUS status = NT_STATUS_OK;
3137 if (fname == NULL || fname->base_name == NULL) {
3138 filename = ".";
3139 } else {
3140 filename = fname->base_name;
3143 if (IS_IPC(conn)) {
3144 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3145 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3146 "info level (0x%x) on IPC$.\n",
3147 (unsigned int)info_level));
3148 return NT_STATUS_ACCESS_DENIED;
3152 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3154 ZERO_STRUCT(smb_fname);
3155 smb_fname.base_name = discard_const_p(char, filename);
3157 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3158 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3159 return map_nt_error_from_unix(errno);
3162 st = smb_fname.st;
3164 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3165 return NT_STATUS_INVALID_PARAMETER;
3168 *ppdata = (char *)SMB_REALLOC(
3169 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3170 if (*ppdata == NULL) {
3171 return NT_STATUS_NO_MEMORY;
3174 pdata = *ppdata;
3175 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3176 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3178 switch (info_level) {
3179 case SMB_INFO_ALLOCATION:
3181 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3182 data_len = 18;
3183 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3184 return map_nt_error_from_unix(errno);
3187 block_size = lp_block_size(snum);
3188 if (bsize < block_size) {
3189 uint64_t factor = block_size/bsize;
3190 bsize = block_size;
3191 dsize /= factor;
3192 dfree /= factor;
3194 if (bsize > block_size) {
3195 uint64_t factor = bsize/block_size;
3196 bsize = block_size;
3197 dsize *= factor;
3198 dfree *= factor;
3200 bytes_per_sector = 512;
3201 sectors_per_unit = bsize/bytes_per_sector;
3203 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3204 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3205 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3207 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3208 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3209 SIVAL(pdata,l1_cUnit,dsize);
3210 SIVAL(pdata,l1_cUnitAvail,dfree);
3211 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3212 break;
3215 case SMB_INFO_VOLUME:
3216 /* Return volume name */
3218 * Add volume serial number - hash of a combination of
3219 * the called hostname and the service name.
3221 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3223 * Win2k3 and previous mess this up by sending a name length
3224 * one byte short. I believe only older clients (OS/2 Win9x) use
3225 * this call so try fixing this by adding a terminating null to
3226 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3228 len = srvstr_push(
3229 pdata, flags2,
3230 pdata+l2_vol_szVolLabel, vname,
3231 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3232 STR_NOALIGN|STR_TERMINATE);
3233 SCVAL(pdata,l2_vol_cch,len);
3234 data_len = l2_vol_szVolLabel + len;
3235 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3236 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3237 len, vname));
3238 break;
3240 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3241 case SMB_FS_ATTRIBUTE_INFORMATION:
3243 additional_flags = 0;
3244 #if defined(HAVE_SYS_QUOTAS)
3245 additional_flags |= FILE_VOLUME_QUOTAS;
3246 #endif
3248 if(lp_nt_acl_support(SNUM(conn))) {
3249 additional_flags |= FILE_PERSISTENT_ACLS;
3252 /* Capabilities are filled in at connection time through STATVFS call */
3253 additional_flags |= conn->fs_capabilities;
3254 additional_flags |= lp_parm_int(conn->params->service,
3255 "share", "fake_fscaps",
3258 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3259 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3260 additional_flags); /* FS ATTRIBUTES */
3262 SIVAL(pdata,4,255); /* Max filename component length */
3263 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3264 and will think we can't do long filenames */
3265 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3266 PTR_DIFF(end_data, pdata+12),
3267 STR_UNICODE);
3268 SIVAL(pdata,8,len);
3269 data_len = 12 + len;
3270 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3271 /* the client only requested a portion of the
3272 file system name */
3273 data_len = max_data_bytes;
3274 status = STATUS_BUFFER_OVERFLOW;
3276 break;
3278 case SMB_QUERY_FS_LABEL_INFO:
3279 case SMB_FS_LABEL_INFORMATION:
3280 len = srvstr_push(pdata, flags2, pdata+4, vname,
3281 PTR_DIFF(end_data, pdata+4), 0);
3282 data_len = 4 + len;
3283 SIVAL(pdata,0,len);
3284 break;
3286 case SMB_QUERY_FS_VOLUME_INFO:
3287 case SMB_FS_VOLUME_INFORMATION:
3290 * Add volume serial number - hash of a combination of
3291 * the called hostname and the service name.
3293 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3294 (str_checksum(get_local_machine_name())<<16));
3296 /* Max label len is 32 characters. */
3297 len = srvstr_push(pdata, flags2, pdata+18, vname,
3298 PTR_DIFF(end_data, pdata+18),
3299 STR_UNICODE);
3300 SIVAL(pdata,12,len);
3301 data_len = 18+len;
3303 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3304 (int)strlen(vname),vname,
3305 lp_servicename(talloc_tos(), snum)));
3306 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3307 /* the client only requested a portion of the
3308 volume label */
3309 data_len = max_data_bytes;
3310 status = STATUS_BUFFER_OVERFLOW;
3312 break;
3314 case SMB_QUERY_FS_SIZE_INFO:
3315 case SMB_FS_SIZE_INFORMATION:
3317 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3318 data_len = 24;
3319 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3320 return map_nt_error_from_unix(errno);
3322 block_size = lp_block_size(snum);
3323 if (bsize < block_size) {
3324 uint64_t factor = block_size/bsize;
3325 bsize = block_size;
3326 dsize /= factor;
3327 dfree /= factor;
3329 if (bsize > block_size) {
3330 uint64_t factor = bsize/block_size;
3331 bsize = block_size;
3332 dsize *= factor;
3333 dfree *= factor;
3335 bytes_per_sector = 512;
3336 sectors_per_unit = bsize/bytes_per_sector;
3337 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3338 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3339 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3340 SBIG_UINT(pdata,0,dsize);
3341 SBIG_UINT(pdata,8,dfree);
3342 SIVAL(pdata,16,sectors_per_unit);
3343 SIVAL(pdata,20,bytes_per_sector);
3344 break;
3347 case SMB_FS_FULL_SIZE_INFORMATION:
3349 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3350 data_len = 32;
3351 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3352 return map_nt_error_from_unix(errno);
3354 block_size = lp_block_size(snum);
3355 if (bsize < block_size) {
3356 uint64_t factor = block_size/bsize;
3357 bsize = block_size;
3358 dsize /= factor;
3359 dfree /= factor;
3361 if (bsize > block_size) {
3362 uint64_t factor = bsize/block_size;
3363 bsize = block_size;
3364 dsize *= factor;
3365 dfree *= factor;
3367 bytes_per_sector = 512;
3368 sectors_per_unit = bsize/bytes_per_sector;
3369 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3370 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3371 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3372 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3373 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3374 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3375 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3376 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3377 break;
3380 case SMB_QUERY_FS_DEVICE_INFO:
3381 case SMB_FS_DEVICE_INFORMATION:
3383 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3385 if (!CAN_WRITE(conn)) {
3386 characteristics |= FILE_READ_ONLY_DEVICE;
3388 data_len = 8;
3389 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3390 SIVAL(pdata,4,characteristics);
3391 break;
3394 #ifdef HAVE_SYS_QUOTAS
3395 case SMB_FS_QUOTA_INFORMATION:
3397 * what we have to send --metze:
3399 * Unknown1: 24 NULL bytes
3400 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3401 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3402 * Quota Flags: 2 byte :
3403 * Unknown3: 6 NULL bytes
3405 * 48 bytes total
3407 * details for Quota Flags:
3409 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3410 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3411 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3412 * 0x0001 Enable Quotas: enable quota for this fs
3416 /* we need to fake up a fsp here,
3417 * because its not send in this call
3419 files_struct fsp;
3420 SMB_NTQUOTA_STRUCT quotas;
3422 ZERO_STRUCT(fsp);
3423 ZERO_STRUCT(quotas);
3425 fsp.conn = conn;
3426 fsp.fnum = FNUM_FIELD_INVALID;
3428 /* access check */
3429 if (get_current_uid(conn) != 0) {
3430 DEBUG(0,("set_user_quota: access_denied "
3431 "service [%s] user [%s]\n",
3432 lp_servicename(talloc_tos(), SNUM(conn)),
3433 conn->session_info->unix_info->unix_name));
3434 return NT_STATUS_ACCESS_DENIED;
3437 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3438 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3439 return map_nt_error_from_unix(errno);
3442 data_len = 48;
3444 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3445 lp_servicename(talloc_tos(), SNUM(conn))));
3447 /* Unknown1 24 NULL bytes*/
3448 SBIG_UINT(pdata,0,(uint64_t)0);
3449 SBIG_UINT(pdata,8,(uint64_t)0);
3450 SBIG_UINT(pdata,16,(uint64_t)0);
3452 /* Default Soft Quota 8 bytes */
3453 SBIG_UINT(pdata,24,quotas.softlim);
3455 /* Default Hard Quota 8 bytes */
3456 SBIG_UINT(pdata,32,quotas.hardlim);
3458 /* Quota flag 2 bytes */
3459 SSVAL(pdata,40,quotas.qflags);
3461 /* Unknown3 6 NULL bytes */
3462 SSVAL(pdata,42,0);
3463 SIVAL(pdata,44,0);
3465 break;
3467 #endif /* HAVE_SYS_QUOTAS */
3468 case SMB_FS_OBJECTID_INFORMATION:
3470 unsigned char objid[16];
3471 struct smb_extended_info extended_info;
3472 memcpy(pdata,create_volume_objectid(conn, objid),16);
3473 samba_extended_info_version (&extended_info);
3474 SIVAL(pdata,16,extended_info.samba_magic);
3475 SIVAL(pdata,20,extended_info.samba_version);
3476 SIVAL(pdata,24,extended_info.samba_subversion);
3477 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3478 memcpy(pdata+36,extended_info.samba_version_string,28);
3479 data_len = 64;
3480 break;
3484 * Query the version and capabilities of the CIFS UNIX extensions
3485 * in use.
3488 case SMB_QUERY_CIFS_UNIX_INFO:
3490 bool large_write = lp_min_receive_file_size() &&
3491 !srv_is_signing_active(conn->sconn);
3492 bool large_read = !srv_is_signing_active(conn->sconn);
3493 int encrypt_caps = 0;
3495 if (!lp_unix_extensions()) {
3496 return NT_STATUS_INVALID_LEVEL;
3499 switch (conn->encrypt_level) {
3500 case SMB_SIGNING_OFF:
3501 encrypt_caps = 0;
3502 break;
3503 case SMB_SIGNING_IF_REQUIRED:
3504 case SMB_SIGNING_DEFAULT:
3505 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3506 break;
3507 case SMB_SIGNING_REQUIRED:
3508 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3509 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3510 large_write = false;
3511 large_read = false;
3512 break;
3515 data_len = 12;
3516 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3517 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3519 /* We have POSIX ACLs, pathname, encryption,
3520 * large read/write, and locking capability. */
3522 SBIG_UINT(pdata,4,((uint64_t)(
3523 CIFS_UNIX_POSIX_ACLS_CAP|
3524 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3525 CIFS_UNIX_FCNTL_LOCKS_CAP|
3526 CIFS_UNIX_EXTATTR_CAP|
3527 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3528 encrypt_caps|
3529 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3530 (large_write ?
3531 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3532 break;
3535 case SMB_QUERY_POSIX_FS_INFO:
3537 int rc;
3538 vfs_statvfs_struct svfs;
3540 if (!lp_unix_extensions()) {
3541 return NT_STATUS_INVALID_LEVEL;
3544 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3546 if (!rc) {
3547 data_len = 56;
3548 SIVAL(pdata,0,svfs.OptimalTransferSize);
3549 SIVAL(pdata,4,svfs.BlockSize);
3550 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3551 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3552 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3553 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3554 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3555 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3556 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3557 #ifdef EOPNOTSUPP
3558 } else if (rc == EOPNOTSUPP) {
3559 return NT_STATUS_INVALID_LEVEL;
3560 #endif /* EOPNOTSUPP */
3561 } else {
3562 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3563 return NT_STATUS_DOS(ERRSRV, ERRerror);
3565 break;
3568 case SMB_QUERY_POSIX_WHOAMI:
3570 uint32_t flags = 0;
3571 uint32_t sid_bytes;
3572 int i;
3574 if (!lp_unix_extensions()) {
3575 return NT_STATUS_INVALID_LEVEL;
3578 if (max_data_bytes < 40) {
3579 return NT_STATUS_BUFFER_TOO_SMALL;
3582 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3583 flags |= SMB_WHOAMI_GUEST;
3586 /* NOTE: 8 bytes for UID/GID, irrespective of native
3587 * platform size. This matches
3588 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3590 data_len = 4 /* flags */
3591 + 4 /* flag mask */
3592 + 8 /* uid */
3593 + 8 /* gid */
3594 + 4 /* ngroups */
3595 + 4 /* num_sids */
3596 + 4 /* SID bytes */
3597 + 4 /* pad/reserved */
3598 + (conn->session_info->unix_token->ngroups * 8)
3599 /* groups list */
3600 + (conn->session_info->security_token->num_sids *
3601 SID_MAX_SIZE)
3602 /* SID list */;
3604 SIVAL(pdata, 0, flags);
3605 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3606 SBIG_UINT(pdata, 8,
3607 (uint64_t)conn->session_info->unix_token->uid);
3608 SBIG_UINT(pdata, 16,
3609 (uint64_t)conn->session_info->unix_token->gid);
3612 if (data_len >= max_data_bytes) {
3613 /* Potential overflow, skip the GIDs and SIDs. */
3615 SIVAL(pdata, 24, 0); /* num_groups */
3616 SIVAL(pdata, 28, 0); /* num_sids */
3617 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3618 SIVAL(pdata, 36, 0); /* reserved */
3620 data_len = 40;
3621 break;
3624 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3625 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3627 /* We walk the SID list twice, but this call is fairly
3628 * infrequent, and I don't expect that it's performance
3629 * sensitive -- jpeach
3631 for (i = 0, sid_bytes = 0;
3632 i < conn->session_info->security_token->num_sids; ++i) {
3633 sid_bytes += ndr_size_dom_sid(
3634 &conn->session_info->security_token->sids[i],
3638 /* SID list byte count */
3639 SIVAL(pdata, 32, sid_bytes);
3641 /* 4 bytes pad/reserved - must be zero */
3642 SIVAL(pdata, 36, 0);
3643 data_len = 40;
3645 /* GID list */
3646 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3647 SBIG_UINT(pdata, data_len,
3648 (uint64_t)conn->session_info->unix_token->groups[i]);
3649 data_len += 8;
3652 /* SID list */
3653 for (i = 0;
3654 i < conn->session_info->security_token->num_sids; ++i) {
3655 int sid_len = ndr_size_dom_sid(
3656 &conn->session_info->security_token->sids[i],
3659 sid_linearize(pdata + data_len, sid_len,
3660 &conn->session_info->security_token->sids[i]);
3661 data_len += sid_len;
3664 break;
3667 case SMB_MAC_QUERY_FS_INFO:
3669 * Thursby MAC extension... ONLY on NTFS filesystems
3670 * once we do streams then we don't need this
3672 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3673 data_len = 88;
3674 SIVAL(pdata,84,0x100); /* Don't support mac... */
3675 break;
3677 /* drop through */
3678 default:
3679 return NT_STATUS_INVALID_LEVEL;
3682 *ret_data_len = data_len;
3683 return status;
3686 /****************************************************************************
3687 Reply to a TRANS2_QFSINFO (query filesystem info).
3688 ****************************************************************************/
3690 static void call_trans2qfsinfo(connection_struct *conn,
3691 struct smb_request *req,
3692 char **pparams, int total_params,
3693 char **ppdata, int total_data,
3694 unsigned int max_data_bytes)
3696 char *params = *pparams;
3697 uint16_t info_level;
3698 int data_len = 0;
3699 NTSTATUS status;
3701 if (total_params < 2) {
3702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3703 return;
3706 info_level = SVAL(params,0);
3708 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3709 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3710 DEBUG(0,("call_trans2qfsinfo: encryption required "
3711 "and info level 0x%x sent.\n",
3712 (unsigned int)info_level));
3713 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3714 return;
3718 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3720 status = smbd_do_qfsinfo(conn, req,
3721 info_level,
3722 req->flags2,
3723 max_data_bytes,
3724 NULL,
3725 ppdata, &data_len);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 reply_nterror(req, status);
3728 return;
3731 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3732 max_data_bytes);
3734 DEBUG( 4, ( "%s info_level = %d\n",
3735 smb_fn_name(req->cmd), info_level) );
3737 return;
3740 /****************************************************************************
3741 Reply to a TRANS2_SETFSINFO (set filesystem info).
3742 ****************************************************************************/
3744 static void call_trans2setfsinfo(connection_struct *conn,
3745 struct smb_request *req,
3746 char **pparams, int total_params,
3747 char **ppdata, int total_data,
3748 unsigned int max_data_bytes)
3750 struct smbd_server_connection *sconn = req->sconn;
3751 char *pdata = *ppdata;
3752 char *params = *pparams;
3753 uint16 info_level;
3755 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3756 lp_servicename(talloc_tos(), SNUM(conn))));
3758 /* */
3759 if (total_params < 4) {
3760 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3761 total_params));
3762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3763 return;
3766 info_level = SVAL(params,2);
3768 if (IS_IPC(conn)) {
3769 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3770 info_level != SMB_SET_CIFS_UNIX_INFO) {
3771 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3772 "info level (0x%x) on IPC$.\n",
3773 (unsigned int)info_level));
3774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3775 return;
3779 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3780 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3781 DEBUG(0,("call_trans2setfsinfo: encryption required "
3782 "and info level 0x%x sent.\n",
3783 (unsigned int)info_level));
3784 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3785 return;
3789 switch(info_level) {
3790 case SMB_SET_CIFS_UNIX_INFO:
3791 if (!lp_unix_extensions()) {
3792 DEBUG(2,("call_trans2setfsinfo: "
3793 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3794 "unix extensions off\n"));
3795 reply_nterror(req,
3796 NT_STATUS_INVALID_LEVEL);
3797 return;
3800 /* There should be 12 bytes of capabilities set. */
3801 if (total_data < 12) {
3802 reply_nterror(
3803 req,
3804 NT_STATUS_INVALID_PARAMETER);
3805 return;
3807 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3808 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3809 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3810 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3811 /* Just print these values for now. */
3812 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3813 "major = %u, minor = %u cap_low = 0x%x, "
3814 "cap_high = 0x%xn",
3815 (unsigned int)sconn->
3816 smb1.unix_info.client_major,
3817 (unsigned int)sconn->
3818 smb1.unix_info.client_minor,
3819 (unsigned int)sconn->
3820 smb1.unix_info.client_cap_low,
3821 (unsigned int)sconn->
3822 smb1.unix_info.client_cap_high));
3824 /* Here is where we must switch to posix pathname processing... */
3825 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3826 lp_set_posix_pathnames();
3827 mangle_change_to_posix();
3830 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3831 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3832 /* Client that knows how to do posix locks,
3833 * but not posix open/mkdir operations. Set a
3834 * default type for read/write checks. */
3836 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3839 break;
3841 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3843 NTSTATUS status;
3844 size_t param_len = 0;
3845 size_t data_len = total_data;
3847 if (!lp_unix_extensions()) {
3848 reply_nterror(
3849 req,
3850 NT_STATUS_INVALID_LEVEL);
3851 return;
3854 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3855 reply_nterror(
3856 req,
3857 NT_STATUS_NOT_SUPPORTED);
3858 return;
3861 if (req->sconn->smb1.echo_handler.trusted_fde) {
3862 DEBUG( 2,("call_trans2setfsinfo: "
3863 "request transport encryption disabled"
3864 "with 'fork echo handler = yes'\n"));
3865 reply_nterror(
3866 req,
3867 NT_STATUS_NOT_SUPPORTED);
3868 return;
3871 DEBUG( 4,("call_trans2setfsinfo: "
3872 "request transport encryption.\n"));
3874 status = srv_request_encryption_setup(conn,
3875 (unsigned char **)ppdata,
3876 &data_len,
3877 (unsigned char **)pparams,
3878 &param_len);
3880 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3881 !NT_STATUS_IS_OK(status)) {
3882 reply_nterror(req, status);
3883 return;
3886 send_trans2_replies(conn, req,
3887 NT_STATUS_OK,
3888 *pparams,
3889 param_len,
3890 *ppdata,
3891 data_len,
3892 max_data_bytes);
3894 if (NT_STATUS_IS_OK(status)) {
3895 /* Server-side transport
3896 * encryption is now *on*. */
3897 status = srv_encryption_start(conn);
3898 if (!NT_STATUS_IS_OK(status)) {
3899 char *reason = talloc_asprintf(talloc_tos(),
3900 "Failure in setting "
3901 "up encrypted transport: %s",
3902 nt_errstr(status));
3903 exit_server_cleanly(reason);
3906 return;
3909 case SMB_FS_QUOTA_INFORMATION:
3911 files_struct *fsp = NULL;
3912 SMB_NTQUOTA_STRUCT quotas;
3914 ZERO_STRUCT(quotas);
3916 /* access check */
3917 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3918 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3919 lp_servicename(talloc_tos(), SNUM(conn)),
3920 conn->session_info->unix_info->unix_name));
3921 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3922 return;
3925 /* note: normaly there're 48 bytes,
3926 * but we didn't use the last 6 bytes for now
3927 * --metze
3929 fsp = file_fsp(req, SVAL(params,0));
3931 if (!check_fsp_ntquota_handle(conn, req,
3932 fsp)) {
3933 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3934 reply_nterror(
3935 req, NT_STATUS_INVALID_HANDLE);
3936 return;
3939 if (total_data < 42) {
3940 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3941 total_data));
3942 reply_nterror(
3943 req,
3944 NT_STATUS_INVALID_PARAMETER);
3945 return;
3948 /* unknown_1 24 NULL bytes in pdata*/
3950 /* the soft quotas 8 bytes (uint64_t)*/
3951 quotas.softlim = BVAL(pdata,24);
3953 /* the hard quotas 8 bytes (uint64_t)*/
3954 quotas.hardlim = BVAL(pdata,32);
3956 /* quota_flags 2 bytes **/
3957 quotas.qflags = SVAL(pdata,40);
3959 /* unknown_2 6 NULL bytes follow*/
3961 /* now set the quotas */
3962 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3963 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3964 reply_nterror(req, map_nt_error_from_unix(errno));
3965 return;
3968 break;
3970 default:
3971 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3972 info_level));
3973 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3974 return;
3975 break;
3979 * sending this reply works fine,
3980 * but I'm not sure it's the same
3981 * like windows do...
3982 * --metze
3984 reply_outbuf(req, 10, 0);
3987 #if defined(HAVE_POSIX_ACLS)
3988 /****************************************************************************
3989 Utility function to count the number of entries in a POSIX acl.
3990 ****************************************************************************/
3992 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3994 unsigned int ace_count = 0;
3995 int entry_id = SMB_ACL_FIRST_ENTRY;
3996 SMB_ACL_ENTRY_T entry;
3998 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3999 /* get_next... */
4000 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4001 entry_id = SMB_ACL_NEXT_ENTRY;
4003 ace_count++;
4005 return ace_count;
4008 /****************************************************************************
4009 Utility function to marshall a POSIX acl into wire format.
4010 ****************************************************************************/
4012 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4014 int entry_id = SMB_ACL_FIRST_ENTRY;
4015 SMB_ACL_ENTRY_T entry;
4017 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4018 SMB_ACL_TAG_T tagtype;
4019 SMB_ACL_PERMSET_T permset;
4020 unsigned char perms = 0;
4021 unsigned int own_grp;
4023 /* get_next... */
4024 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4025 entry_id = SMB_ACL_NEXT_ENTRY;
4028 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4029 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4030 return False;
4033 if (sys_acl_get_permset(entry, &permset) == -1) {
4034 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4035 return False;
4038 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4039 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4040 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4042 SCVAL(pdata,1,perms);
4044 switch (tagtype) {
4045 case SMB_ACL_USER_OBJ:
4046 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4047 own_grp = (unsigned int)pst->st_ex_uid;
4048 SIVAL(pdata,2,own_grp);
4049 SIVAL(pdata,6,0);
4050 break;
4051 case SMB_ACL_USER:
4053 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4054 if (!puid) {
4055 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4056 return False;
4058 own_grp = (unsigned int)*puid;
4059 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4060 SIVAL(pdata,2,own_grp);
4061 SIVAL(pdata,6,0);
4062 break;
4064 case SMB_ACL_GROUP_OBJ:
4065 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4066 own_grp = (unsigned int)pst->st_ex_gid;
4067 SIVAL(pdata,2,own_grp);
4068 SIVAL(pdata,6,0);
4069 break;
4070 case SMB_ACL_GROUP:
4072 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4073 if (!pgid) {
4074 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4075 return False;
4077 own_grp = (unsigned int)*pgid;
4078 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4079 SIVAL(pdata,2,own_grp);
4080 SIVAL(pdata,6,0);
4081 break;
4083 case SMB_ACL_MASK:
4084 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4085 SIVAL(pdata,2,0xFFFFFFFF);
4086 SIVAL(pdata,6,0xFFFFFFFF);
4087 break;
4088 case SMB_ACL_OTHER:
4089 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4090 SIVAL(pdata,2,0xFFFFFFFF);
4091 SIVAL(pdata,6,0xFFFFFFFF);
4092 break;
4093 default:
4094 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4095 return False;
4097 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4100 return True;
4102 #endif
4104 /****************************************************************************
4105 Store the FILE_UNIX_BASIC info.
4106 ****************************************************************************/
4108 static char *store_file_unix_basic(connection_struct *conn,
4109 char *pdata,
4110 files_struct *fsp,
4111 const SMB_STRUCT_STAT *psbuf)
4113 uint64_t file_index = get_FileIndex(conn, psbuf);
4114 dev_t devno;
4116 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4117 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4119 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4120 pdata += 8;
4122 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4123 pdata += 8;
4125 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4126 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4127 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4128 pdata += 24;
4130 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4131 SIVAL(pdata,4,0);
4132 pdata += 8;
4134 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4135 SIVAL(pdata,4,0);
4136 pdata += 8;
4138 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4139 pdata += 4;
4141 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4142 devno = psbuf->st_ex_rdev;
4143 } else {
4144 devno = psbuf->st_ex_dev;
4147 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4148 SIVAL(pdata,4,0);
4149 pdata += 8;
4151 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4152 SIVAL(pdata,4,0);
4153 pdata += 8;
4155 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4156 pdata += 8;
4158 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4159 SIVAL(pdata,4,0);
4160 pdata += 8;
4162 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4163 SIVAL(pdata,4,0);
4164 pdata += 8;
4166 return pdata;
4169 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4170 * the chflags(2) (or equivalent) flags.
4172 * XXX: this really should be behind the VFS interface. To do this, we would
4173 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4174 * Each VFS module could then implement its own mapping as appropriate for the
4175 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4177 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4178 info2_flags_map[] =
4180 #ifdef UF_NODUMP
4181 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4182 #endif
4184 #ifdef UF_IMMUTABLE
4185 { UF_IMMUTABLE, EXT_IMMUTABLE },
4186 #endif
4188 #ifdef UF_APPEND
4189 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4190 #endif
4192 #ifdef UF_HIDDEN
4193 { UF_HIDDEN, EXT_HIDDEN },
4194 #endif
4196 /* Do not remove. We need to guarantee that this array has at least one
4197 * entry to build on HP-UX.
4199 { 0, 0 }
4203 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4204 uint32 *smb_fflags, uint32 *smb_fmask)
4206 int i;
4208 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4209 *smb_fmask |= info2_flags_map[i].smb_fflag;
4210 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4211 *smb_fflags |= info2_flags_map[i].smb_fflag;
4216 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4217 const uint32 smb_fflags,
4218 const uint32 smb_fmask,
4219 int *stat_fflags)
4221 uint32 max_fmask = 0;
4222 int i;
4224 *stat_fflags = psbuf->st_ex_flags;
4226 /* For each flags requested in smb_fmask, check the state of the
4227 * corresponding flag in smb_fflags and set or clear the matching
4228 * stat flag.
4231 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4232 max_fmask |= info2_flags_map[i].smb_fflag;
4233 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4234 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4235 *stat_fflags |= info2_flags_map[i].stat_fflag;
4236 } else {
4237 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4242 /* If smb_fmask is asking to set any bits that are not supported by
4243 * our flag mappings, we should fail.
4245 if ((smb_fmask & max_fmask) != smb_fmask) {
4246 return False;
4249 return True;
4253 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4254 * of file flags and birth (create) time.
4256 static char *store_file_unix_basic_info2(connection_struct *conn,
4257 char *pdata,
4258 files_struct *fsp,
4259 const SMB_STRUCT_STAT *psbuf)
4261 uint32 file_flags = 0;
4262 uint32 flags_mask = 0;
4264 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4266 /* Create (birth) time 64 bit */
4267 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4268 pdata += 8;
4270 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4271 SIVAL(pdata, 0, file_flags); /* flags */
4272 SIVAL(pdata, 4, flags_mask); /* mask */
4273 pdata += 8;
4275 return pdata;
4278 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4279 const struct stream_struct *streams,
4280 char *data,
4281 unsigned int max_data_bytes,
4282 unsigned int *data_size)
4284 unsigned int i;
4285 unsigned int ofs = 0;
4287 for (i = 0; i < num_streams; i++) {
4288 unsigned int next_offset;
4289 size_t namelen;
4290 smb_ucs2_t *namebuf;
4292 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4293 streams[i].name, &namelen) ||
4294 namelen <= 2)
4296 return NT_STATUS_INVALID_PARAMETER;
4300 * name_buf is now null-terminated, we need to marshall as not
4301 * terminated
4304 namelen -= 2;
4307 * We cannot overflow ...
4309 if ((ofs + 24 + namelen) > max_data_bytes) {
4310 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4311 i));
4312 TALLOC_FREE(namebuf);
4313 return STATUS_BUFFER_OVERFLOW;
4316 SIVAL(data, ofs+4, namelen);
4317 SOFF_T(data, ofs+8, streams[i].size);
4318 SOFF_T(data, ofs+16, streams[i].alloc_size);
4319 memcpy(data+ofs+24, namebuf, namelen);
4320 TALLOC_FREE(namebuf);
4322 next_offset = ofs + 24 + namelen;
4324 if (i == num_streams-1) {
4325 SIVAL(data, ofs, 0);
4327 else {
4328 unsigned int align = ndr_align_size(next_offset, 8);
4330 if ((next_offset + align) > max_data_bytes) {
4331 DEBUG(10, ("refusing to overflow align "
4332 "reply at stream %u\n",
4333 i));
4334 TALLOC_FREE(namebuf);
4335 return STATUS_BUFFER_OVERFLOW;
4338 memset(data+next_offset, 0, align);
4339 next_offset += align;
4341 SIVAL(data, ofs, next_offset - ofs);
4342 ofs = next_offset;
4345 ofs = next_offset;
4348 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4350 *data_size = ofs;
4352 return NT_STATUS_OK;
4355 /****************************************************************************
4356 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4357 ****************************************************************************/
4359 static void call_trans2qpipeinfo(connection_struct *conn,
4360 struct smb_request *req,
4361 unsigned int tran_call,
4362 char **pparams, int total_params,
4363 char **ppdata, int total_data,
4364 unsigned int max_data_bytes)
4366 char *params = *pparams;
4367 char *pdata = *ppdata;
4368 unsigned int data_size = 0;
4369 unsigned int param_size = 2;
4370 uint16 info_level;
4371 files_struct *fsp;
4373 if (!params) {
4374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4375 return;
4378 if (total_params < 4) {
4379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4380 return;
4383 fsp = file_fsp(req, SVAL(params,0));
4384 if (!fsp_is_np(fsp)) {
4385 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4386 return;
4389 info_level = SVAL(params,2);
4391 *pparams = (char *)SMB_REALLOC(*pparams,2);
4392 if (*pparams == NULL) {
4393 reply_nterror(req, NT_STATUS_NO_MEMORY);
4394 return;
4396 params = *pparams;
4397 SSVAL(params,0,0);
4398 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4400 return;
4402 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4403 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4404 if (*ppdata == NULL ) {
4405 reply_nterror(req, NT_STATUS_NO_MEMORY);
4406 return;
4408 pdata = *ppdata;
4410 switch (info_level) {
4411 case SMB_FILE_STANDARD_INFORMATION:
4412 memset(pdata,0,24);
4413 SOFF_T(pdata,0,4096LL);
4414 SIVAL(pdata,16,1);
4415 SIVAL(pdata,20,1);
4416 data_size = 24;
4417 break;
4419 default:
4420 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4421 return;
4424 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4425 max_data_bytes);
4427 return;
4430 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4431 TALLOC_CTX *mem_ctx,
4432 uint16_t info_level,
4433 files_struct *fsp,
4434 struct smb_filename *smb_fname,
4435 bool delete_pending,
4436 struct timespec write_time_ts,
4437 struct ea_list *ea_list,
4438 int lock_data_count,
4439 char *lock_data,
4440 uint16_t flags2,
4441 unsigned int max_data_bytes,
4442 char **ppdata,
4443 unsigned int *pdata_size)
4445 char *pdata = *ppdata;
4446 char *dstart, *dend;
4447 unsigned int data_size;
4448 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4449 time_t create_time, mtime, atime, c_time;
4450 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4451 char *p;
4452 char *base_name;
4453 char *dos_fname;
4454 int mode;
4455 int nlink;
4456 NTSTATUS status;
4457 uint64_t file_size = 0;
4458 uint64_t pos = 0;
4459 uint64_t allocation_size = 0;
4460 uint64_t file_index = 0;
4461 uint32_t access_mask = 0;
4463 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4464 return NT_STATUS_INVALID_LEVEL;
4467 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4468 smb_fname_str_dbg(smb_fname),
4469 fsp_fnum_dbg(fsp),
4470 info_level, max_data_bytes));
4472 mode = dos_mode(conn, smb_fname);
4473 nlink = psbuf->st_ex_nlink;
4475 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4476 nlink = 1;
4479 if ((nlink > 0) && delete_pending) {
4480 nlink -= 1;
4483 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4484 return NT_STATUS_INVALID_PARAMETER;
4487 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4488 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4489 if (*ppdata == NULL) {
4490 return NT_STATUS_NO_MEMORY;
4492 pdata = *ppdata;
4493 dstart = pdata;
4494 dend = dstart + data_size - 1;
4496 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4497 update_stat_ex_mtime(psbuf, write_time_ts);
4500 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4501 mtime_ts = psbuf->st_ex_mtime;
4502 atime_ts = psbuf->st_ex_atime;
4503 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4505 if (lp_dos_filetime_resolution(SNUM(conn))) {
4506 dos_filetime_timespec(&create_time_ts);
4507 dos_filetime_timespec(&mtime_ts);
4508 dos_filetime_timespec(&atime_ts);
4509 dos_filetime_timespec(&ctime_ts);
4512 create_time = convert_timespec_to_time_t(create_time_ts);
4513 mtime = convert_timespec_to_time_t(mtime_ts);
4514 atime = convert_timespec_to_time_t(atime_ts);
4515 c_time = convert_timespec_to_time_t(ctime_ts);
4517 p = strrchr_m(smb_fname->base_name,'/');
4518 if (!p)
4519 base_name = smb_fname->base_name;
4520 else
4521 base_name = p+1;
4523 /* NT expects the name to be in an exact form of the *full*
4524 filename. See the trans2 torture test */
4525 if (ISDOT(base_name)) {
4526 dos_fname = talloc_strdup(mem_ctx, "\\");
4527 if (!dos_fname) {
4528 return NT_STATUS_NO_MEMORY;
4530 } else {
4531 dos_fname = talloc_asprintf(mem_ctx,
4532 "\\%s",
4533 smb_fname->base_name);
4534 if (!dos_fname) {
4535 return NT_STATUS_NO_MEMORY;
4537 if (is_ntfs_stream_smb_fname(smb_fname)) {
4538 dos_fname = talloc_asprintf(dos_fname, "%s",
4539 smb_fname->stream_name);
4540 if (!dos_fname) {
4541 return NT_STATUS_NO_MEMORY;
4545 string_replace(dos_fname, '/', '\\');
4548 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4550 if (!fsp) {
4551 /* Do we have this path open ? */
4552 files_struct *fsp1;
4553 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4554 fsp1 = file_find_di_first(conn->sconn, fileid);
4555 if (fsp1 && fsp1->initial_allocation_size) {
4556 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4560 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4561 file_size = get_file_size_stat(psbuf);
4564 if (fsp) {
4565 pos = fsp->fh->position_information;
4568 if (fsp) {
4569 access_mask = fsp->access_mask;
4570 } else {
4571 /* GENERIC_EXECUTE mapping from Windows */
4572 access_mask = 0x12019F;
4575 /* This should be an index number - looks like
4576 dev/ino to me :-)
4578 I think this causes us to fail the IFSKIT
4579 BasicFileInformationTest. -tpot */
4580 file_index = get_FileIndex(conn, psbuf);
4582 switch (info_level) {
4583 case SMB_INFO_STANDARD:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4585 data_size = 22;
4586 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4587 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4588 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4589 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4590 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4591 SSVAL(pdata,l1_attrFile,mode);
4592 break;
4594 case SMB_INFO_QUERY_EA_SIZE:
4596 unsigned int ea_size =
4597 estimate_ea_size(conn, fsp,
4598 smb_fname);
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4600 data_size = 26;
4601 srv_put_dos_date2(pdata,0,create_time);
4602 srv_put_dos_date2(pdata,4,atime);
4603 srv_put_dos_date2(pdata,8,mtime); /* write time */
4604 SIVAL(pdata,12,(uint32)file_size);
4605 SIVAL(pdata,16,(uint32)allocation_size);
4606 SSVAL(pdata,20,mode);
4607 SIVAL(pdata,22,ea_size);
4608 break;
4611 case SMB_INFO_IS_NAME_VALID:
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4613 if (fsp) {
4614 /* os/2 needs this ? really ?*/
4615 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4617 /* This is only reached for qpathinfo */
4618 data_size = 0;
4619 break;
4621 case SMB_INFO_QUERY_EAS_FROM_LIST:
4623 size_t total_ea_len = 0;
4624 struct ea_list *ea_file_list = NULL;
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4627 status =
4628 get_ea_list_from_file(mem_ctx, conn, fsp,
4629 smb_fname,
4630 &total_ea_len, &ea_file_list);
4631 if (!NT_STATUS_IS_OK(status)) {
4632 return status;
4635 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4637 if (!ea_list || (total_ea_len > data_size)) {
4638 data_size = 4;
4639 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4640 break;
4643 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4644 break;
4647 case SMB_INFO_QUERY_ALL_EAS:
4649 /* We have data_size bytes to put EA's into. */
4650 size_t total_ea_len = 0;
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4653 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4654 smb_fname,
4655 &total_ea_len, &ea_list);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 return status;
4660 if (!ea_list || (total_ea_len > data_size)) {
4661 data_size = 4;
4662 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4663 break;
4666 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4667 break;
4670 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4672 /* This is FileFullEaInformation - 0xF which maps to
4673 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4675 /* We have data_size bytes to put EA's into. */
4676 size_t total_ea_len = 0;
4677 struct ea_list *ea_file_list = NULL;
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4681 /*TODO: add filtering and index handling */
4683 status =
4684 get_ea_list_from_file(mem_ctx, conn, fsp,
4685 smb_fname,
4686 &total_ea_len, &ea_file_list);
4687 if (!NT_STATUS_IS_OK(status)) {
4688 return status;
4690 if (!ea_file_list) {
4691 return NT_STATUS_NO_EAS_ON_FILE;
4694 status = fill_ea_chained_buffer(mem_ctx,
4695 pdata,
4696 data_size,
4697 &data_size,
4698 conn, ea_file_list);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 return status;
4702 break;
4705 case SMB_FILE_BASIC_INFORMATION:
4706 case SMB_QUERY_FILE_BASIC_INFO:
4708 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4710 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4711 } else {
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4713 data_size = 40;
4714 SIVAL(pdata,36,0);
4716 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4717 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4718 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4719 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4720 SIVAL(pdata,32,mode);
4722 DEBUG(5,("SMB_QFBI - "));
4723 DEBUG(5,("create: %s ", ctime(&create_time)));
4724 DEBUG(5,("access: %s ", ctime(&atime)));
4725 DEBUG(5,("write: %s ", ctime(&mtime)));
4726 DEBUG(5,("change: %s ", ctime(&c_time)));
4727 DEBUG(5,("mode: %x\n", mode));
4728 break;
4730 case SMB_FILE_STANDARD_INFORMATION:
4731 case SMB_QUERY_FILE_STANDARD_INFO:
4733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4734 data_size = 24;
4735 SOFF_T(pdata,0,allocation_size);
4736 SOFF_T(pdata,8,file_size);
4737 SIVAL(pdata,16,nlink);
4738 SCVAL(pdata,20,delete_pending?1:0);
4739 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4740 SSVAL(pdata,22,0); /* Padding. */
4741 break;
4743 case SMB_FILE_EA_INFORMATION:
4744 case SMB_QUERY_FILE_EA_INFO:
4746 unsigned int ea_size =
4747 estimate_ea_size(conn, fsp, smb_fname);
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4749 data_size = 4;
4750 SIVAL(pdata,0,ea_size);
4751 break;
4754 /* Get the 8.3 name - used if NT SMB was negotiated. */
4755 case SMB_QUERY_FILE_ALT_NAME_INFO:
4756 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4758 int len;
4759 char mangled_name[13];
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4761 if (!name_to_8_3(base_name,mangled_name,
4762 True,conn->params)) {
4763 return NT_STATUS_NO_MEMORY;
4765 len = srvstr_push(dstart, flags2,
4766 pdata+4, mangled_name,
4767 PTR_DIFF(dend, pdata+4),
4768 STR_UNICODE);
4769 data_size = 4 + len;
4770 SIVAL(pdata,0,len);
4771 break;
4774 case SMB_QUERY_FILE_NAME_INFO:
4776 int len;
4778 this must be *exactly* right for ACLs on mapped drives to work
4780 len = srvstr_push(dstart, flags2,
4781 pdata+4, dos_fname,
4782 PTR_DIFF(dend, pdata+4),
4783 STR_UNICODE);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4785 data_size = 4 + len;
4786 SIVAL(pdata,0,len);
4787 break;
4790 case SMB_FILE_ALLOCATION_INFORMATION:
4791 case SMB_QUERY_FILE_ALLOCATION_INFO:
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4793 data_size = 8;
4794 SOFF_T(pdata,0,allocation_size);
4795 break;
4797 case SMB_FILE_END_OF_FILE_INFORMATION:
4798 case SMB_QUERY_FILE_END_OF_FILEINFO:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4800 data_size = 8;
4801 SOFF_T(pdata,0,file_size);
4802 break;
4804 case SMB_QUERY_FILE_ALL_INFO:
4805 case SMB_FILE_ALL_INFORMATION:
4807 int len;
4808 unsigned int ea_size =
4809 estimate_ea_size(conn, fsp, smb_fname);
4810 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4811 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4812 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4813 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4814 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4815 SIVAL(pdata,32,mode);
4816 SIVAL(pdata,36,0); /* padding. */
4817 pdata += 40;
4818 SOFF_T(pdata,0,allocation_size);
4819 SOFF_T(pdata,8,file_size);
4820 SIVAL(pdata,16,nlink);
4821 SCVAL(pdata,20,delete_pending);
4822 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4823 SSVAL(pdata,22,0);
4824 pdata += 24;
4825 SIVAL(pdata,0,ea_size);
4826 pdata += 4; /* EA info */
4827 len = srvstr_push(dstart, flags2,
4828 pdata+4, dos_fname,
4829 PTR_DIFF(dend, pdata+4),
4830 STR_UNICODE);
4831 SIVAL(pdata,0,len);
4832 pdata += 4 + len;
4833 data_size = PTR_DIFF(pdata,(*ppdata));
4834 break;
4837 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4839 int len;
4840 unsigned int ea_size =
4841 estimate_ea_size(conn, fsp, smb_fname);
4842 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4843 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4844 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4845 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4846 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4847 SIVAL(pdata, 0x20, mode);
4848 SIVAL(pdata, 0x24, 0); /* padding. */
4849 SBVAL(pdata, 0x28, allocation_size);
4850 SBVAL(pdata, 0x30, file_size);
4851 SIVAL(pdata, 0x38, nlink);
4852 SCVAL(pdata, 0x3C, delete_pending);
4853 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4854 SSVAL(pdata, 0x3E, 0); /* padding */
4855 SBVAL(pdata, 0x40, file_index);
4856 SIVAL(pdata, 0x48, ea_size);
4857 SIVAL(pdata, 0x4C, access_mask);
4858 SBVAL(pdata, 0x50, pos);
4859 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4860 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4862 pdata += 0x60;
4864 len = srvstr_push(dstart, flags2,
4865 pdata+4, dos_fname,
4866 PTR_DIFF(dend, pdata+4),
4867 STR_UNICODE);
4868 SIVAL(pdata,0,len);
4869 pdata += 4 + len;
4870 data_size = PTR_DIFF(pdata,(*ppdata));
4871 break;
4873 case SMB_FILE_INTERNAL_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4876 SBVAL(pdata, 0, file_index);
4877 data_size = 8;
4878 break;
4880 case SMB_FILE_ACCESS_INFORMATION:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4882 SIVAL(pdata, 0, access_mask);
4883 data_size = 4;
4884 break;
4886 case SMB_FILE_NAME_INFORMATION:
4887 /* Pathname with leading '\'. */
4889 size_t byte_len;
4890 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4892 SIVAL(pdata,0,byte_len);
4893 data_size = 4 + byte_len;
4894 break;
4897 case SMB_FILE_DISPOSITION_INFORMATION:
4898 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4899 data_size = 1;
4900 SCVAL(pdata,0,delete_pending);
4901 break;
4903 case SMB_FILE_POSITION_INFORMATION:
4904 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4905 data_size = 8;
4906 SOFF_T(pdata,0,pos);
4907 break;
4909 case SMB_FILE_MODE_INFORMATION:
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4911 SIVAL(pdata,0,mode);
4912 data_size = 4;
4913 break;
4915 case SMB_FILE_ALIGNMENT_INFORMATION:
4916 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4917 SIVAL(pdata,0,0); /* No alignment needed. */
4918 data_size = 4;
4919 break;
4922 * NT4 server just returns "invalid query" to this - if we try
4923 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4924 * want this. JRA.
4926 /* The first statement above is false - verified using Thursby
4927 * client against NT4 -- gcolley.
4929 case SMB_QUERY_FILE_STREAM_INFO:
4930 case SMB_FILE_STREAM_INFORMATION: {
4931 unsigned int num_streams = 0;
4932 struct stream_struct *streams = NULL;
4934 DEBUG(10,("smbd_do_qfilepathinfo: "
4935 "SMB_FILE_STREAM_INFORMATION\n"));
4937 if (is_ntfs_stream_smb_fname(smb_fname)) {
4938 return NT_STATUS_INVALID_PARAMETER;
4941 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4942 talloc_tos(), &num_streams, &streams);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 DEBUG(10, ("could not get stream info: %s\n",
4946 nt_errstr(status)));
4947 return status;
4950 status = marshall_stream_info(num_streams, streams,
4951 pdata, max_data_bytes,
4952 &data_size);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 DEBUG(10, ("marshall_stream_info failed: %s\n",
4956 nt_errstr(status)));
4957 TALLOC_FREE(streams);
4958 return status;
4961 TALLOC_FREE(streams);
4963 break;
4965 case SMB_QUERY_COMPRESSION_INFO:
4966 case SMB_FILE_COMPRESSION_INFORMATION:
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4968 SOFF_T(pdata,0,file_size);
4969 SIVAL(pdata,8,0); /* ??? */
4970 SIVAL(pdata,12,0); /* ??? */
4971 data_size = 16;
4972 break;
4974 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4975 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4976 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4977 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4978 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4979 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4980 SOFF_T(pdata,32,allocation_size);
4981 SOFF_T(pdata,40,file_size);
4982 SIVAL(pdata,48,mode);
4983 SIVAL(pdata,52,0); /* ??? */
4984 data_size = 56;
4985 break;
4987 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4988 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4989 SIVAL(pdata,0,mode);
4990 SIVAL(pdata,4,0);
4991 data_size = 8;
4992 break;
4995 * CIFS UNIX Extensions.
4998 case SMB_QUERY_FILE_UNIX_BASIC:
5000 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5001 data_size = PTR_DIFF(pdata,(*ppdata));
5003 DEBUG(4,("smbd_do_qfilepathinfo: "
5004 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5005 dump_data(4, (uint8_t *)(*ppdata), data_size);
5007 break;
5009 case SMB_QUERY_FILE_UNIX_INFO2:
5011 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5012 data_size = PTR_DIFF(pdata,(*ppdata));
5015 int i;
5016 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5018 for (i=0; i<100; i++)
5019 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5020 DEBUG(4,("\n"));
5023 break;
5025 case SMB_QUERY_FILE_UNIX_LINK:
5027 int len;
5028 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5030 if (!buffer) {
5031 return NT_STATUS_NO_MEMORY;
5034 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5035 #ifdef S_ISLNK
5036 if(!S_ISLNK(psbuf->st_ex_mode)) {
5037 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5039 #else
5040 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5041 #endif
5042 len = SMB_VFS_READLINK(conn,
5043 smb_fname->base_name,
5044 buffer, PATH_MAX);
5045 if (len == -1) {
5046 return map_nt_error_from_unix(errno);
5048 buffer[len] = 0;
5049 len = srvstr_push(dstart, flags2,
5050 pdata, buffer,
5051 PTR_DIFF(dend, pdata),
5052 STR_TERMINATE);
5053 pdata += len;
5054 data_size = PTR_DIFF(pdata,(*ppdata));
5056 break;
5059 #if defined(HAVE_POSIX_ACLS)
5060 case SMB_QUERY_POSIX_ACL:
5062 SMB_ACL_T file_acl = NULL;
5063 SMB_ACL_T def_acl = NULL;
5064 uint16 num_file_acls = 0;
5065 uint16 num_def_acls = 0;
5067 if (fsp && fsp->fh->fd != -1) {
5068 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5069 talloc_tos());
5070 } else {
5071 file_acl =
5072 SMB_VFS_SYS_ACL_GET_FILE(conn,
5073 smb_fname->base_name,
5074 SMB_ACL_TYPE_ACCESS,
5075 talloc_tos());
5078 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5079 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5080 "not implemented on "
5081 "filesystem containing %s\n",
5082 smb_fname->base_name));
5083 return NT_STATUS_NOT_IMPLEMENTED;
5086 if (S_ISDIR(psbuf->st_ex_mode)) {
5087 if (fsp && fsp->is_directory) {
5088 def_acl =
5089 SMB_VFS_SYS_ACL_GET_FILE(
5090 conn,
5091 fsp->fsp_name->base_name,
5092 SMB_ACL_TYPE_DEFAULT,
5093 talloc_tos());
5094 } else {
5095 def_acl =
5096 SMB_VFS_SYS_ACL_GET_FILE(
5097 conn,
5098 smb_fname->base_name,
5099 SMB_ACL_TYPE_DEFAULT,
5100 talloc_tos());
5102 def_acl = free_empty_sys_acl(conn, def_acl);
5105 num_file_acls = count_acl_entries(conn, file_acl);
5106 num_def_acls = count_acl_entries(conn, def_acl);
5108 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5109 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5110 data_size,
5111 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5112 SMB_POSIX_ACL_HEADER_SIZE) ));
5113 if (file_acl) {
5114 TALLOC_FREE(file_acl);
5116 if (def_acl) {
5117 TALLOC_FREE(def_acl);
5119 return NT_STATUS_BUFFER_TOO_SMALL;
5122 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5123 SSVAL(pdata,2,num_file_acls);
5124 SSVAL(pdata,4,num_def_acls);
5125 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5126 if (file_acl) {
5127 TALLOC_FREE(file_acl);
5129 if (def_acl) {
5130 TALLOC_FREE(def_acl);
5132 return NT_STATUS_INTERNAL_ERROR;
5134 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5135 if (file_acl) {
5136 TALLOC_FREE(file_acl);
5138 if (def_acl) {
5139 TALLOC_FREE(def_acl);
5141 return NT_STATUS_INTERNAL_ERROR;
5144 if (file_acl) {
5145 TALLOC_FREE(file_acl);
5147 if (def_acl) {
5148 TALLOC_FREE(def_acl);
5150 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5151 break;
5153 #endif
5156 case SMB_QUERY_POSIX_LOCK:
5158 uint64_t count;
5159 uint64_t offset;
5160 uint64_t smblctx;
5161 enum brl_type lock_type;
5163 /* We need an open file with a real fd for this. */
5164 if (!fsp || fsp->fh->fd == -1) {
5165 return NT_STATUS_INVALID_LEVEL;
5168 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5169 return NT_STATUS_INVALID_PARAMETER;
5172 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5173 case POSIX_LOCK_TYPE_READ:
5174 lock_type = READ_LOCK;
5175 break;
5176 case POSIX_LOCK_TYPE_WRITE:
5177 lock_type = WRITE_LOCK;
5178 break;
5179 case POSIX_LOCK_TYPE_UNLOCK:
5180 default:
5181 /* There's no point in asking for an unlock... */
5182 return NT_STATUS_INVALID_PARAMETER;
5185 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5186 #if defined(HAVE_LONGLONG)
5187 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5188 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5189 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5190 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5191 #else /* HAVE_LONGLONG */
5192 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5193 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5194 #endif /* HAVE_LONGLONG */
5196 status = query_lock(fsp,
5197 &smblctx,
5198 &count,
5199 &offset,
5200 &lock_type,
5201 POSIX_LOCK);
5203 if (ERROR_WAS_LOCK_DENIED(status)) {
5204 /* Here we need to report who has it locked... */
5205 data_size = POSIX_LOCK_DATA_SIZE;
5207 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5208 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5209 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5210 #if defined(HAVE_LONGLONG)
5211 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5212 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5213 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5214 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5215 #else /* HAVE_LONGLONG */
5216 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5217 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5218 #endif /* HAVE_LONGLONG */
5220 } else if (NT_STATUS_IS_OK(status)) {
5221 /* For success we just return a copy of what we sent
5222 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5223 data_size = POSIX_LOCK_DATA_SIZE;
5224 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5225 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5226 } else {
5227 return status;
5229 break;
5232 default:
5233 return NT_STATUS_INVALID_LEVEL;
5236 *pdata_size = data_size;
5237 return NT_STATUS_OK;
5240 /****************************************************************************
5241 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5242 file name or file id).
5243 ****************************************************************************/
5245 static void call_trans2qfilepathinfo(connection_struct *conn,
5246 struct smb_request *req,
5247 unsigned int tran_call,
5248 char **pparams, int total_params,
5249 char **ppdata, int total_data,
5250 unsigned int max_data_bytes)
5252 char *params = *pparams;
5253 char *pdata = *ppdata;
5254 uint16 info_level;
5255 unsigned int data_size = 0;
5256 unsigned int param_size = 2;
5257 struct smb_filename *smb_fname = NULL;
5258 bool delete_pending = False;
5259 struct timespec write_time_ts;
5260 files_struct *fsp = NULL;
5261 struct file_id fileid;
5262 struct ea_list *ea_list = NULL;
5263 int lock_data_count = 0;
5264 char *lock_data = NULL;
5265 NTSTATUS status = NT_STATUS_OK;
5267 if (!params) {
5268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5269 return;
5272 ZERO_STRUCT(write_time_ts);
5274 if (tran_call == TRANSACT2_QFILEINFO) {
5275 if (total_params < 4) {
5276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5277 return;
5280 if (IS_IPC(conn)) {
5281 call_trans2qpipeinfo(conn, req, tran_call,
5282 pparams, total_params,
5283 ppdata, total_data,
5284 max_data_bytes);
5285 return;
5288 fsp = file_fsp(req, SVAL(params,0));
5289 info_level = SVAL(params,2);
5291 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5293 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5294 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5295 return;
5298 /* Initial check for valid fsp ptr. */
5299 if (!check_fsp_open(conn, req, fsp)) {
5300 return;
5303 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5304 if (smb_fname == NULL) {
5305 reply_nterror(req, NT_STATUS_NO_MEMORY);
5306 return;
5309 if(fsp->fake_file_handle) {
5311 * This is actually for the QUOTA_FAKE_FILE --metze
5314 /* We know this name is ok, it's already passed the checks. */
5316 } else if(fsp->fh->fd == -1) {
5318 * This is actually a QFILEINFO on a directory
5319 * handle (returned from an NT SMB). NT5.0 seems
5320 * to do this call. JRA.
5323 if (INFO_LEVEL_IS_UNIX(info_level)) {
5324 /* Always do lstat for UNIX calls. */
5325 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5326 DEBUG(3,("call_trans2qfilepathinfo: "
5327 "SMB_VFS_LSTAT of %s failed "
5328 "(%s)\n",
5329 smb_fname_str_dbg(smb_fname),
5330 strerror(errno)));
5331 reply_nterror(req,
5332 map_nt_error_from_unix(errno));
5333 return;
5335 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5336 DEBUG(3,("call_trans2qfilepathinfo: "
5337 "SMB_VFS_STAT of %s failed (%s)\n",
5338 smb_fname_str_dbg(smb_fname),
5339 strerror(errno)));
5340 reply_nterror(req,
5341 map_nt_error_from_unix(errno));
5342 return;
5345 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5346 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5347 } else {
5349 * Original code - this is an open file.
5351 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5352 DEBUG(3, ("fstat of %s failed (%s)\n",
5353 fsp_fnum_dbg(fsp), strerror(errno)));
5354 reply_nterror(req,
5355 map_nt_error_from_unix(errno));
5356 return;
5358 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5359 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5362 } else {
5363 uint32_t name_hash;
5364 char *fname = NULL;
5365 uint32_t ucf_flags = 0;
5367 /* qpathinfo */
5368 if (total_params < 7) {
5369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5370 return;
5373 info_level = SVAL(params,0);
5375 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5377 if (INFO_LEVEL_IS_UNIX(info_level)) {
5378 if (!lp_unix_extensions()) {
5379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5380 return;
5382 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5383 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5384 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5385 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5389 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5390 total_params - 6,
5391 STR_TERMINATE, &status);
5392 if (!NT_STATUS_IS_OK(status)) {
5393 reply_nterror(req, status);
5394 return;
5397 status = filename_convert(req,
5398 conn,
5399 req->flags2 & FLAGS2_DFS_PATHNAMES,
5400 fname,
5401 ucf_flags,
5402 NULL,
5403 &smb_fname);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5406 reply_botherror(req,
5407 NT_STATUS_PATH_NOT_COVERED,
5408 ERRSRV, ERRbadpath);
5409 return;
5411 reply_nterror(req, status);
5412 return;
5415 /* If this is a stream, check if there is a delete_pending. */
5416 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5417 && is_ntfs_stream_smb_fname(smb_fname)) {
5418 struct smb_filename *smb_fname_base;
5420 /* Create an smb_filename with stream_name == NULL. */
5421 smb_fname_base = synthetic_smb_fname(
5422 talloc_tos(), smb_fname->base_name,
5423 NULL, NULL);
5424 if (smb_fname_base == NULL) {
5425 reply_nterror(req, NT_STATUS_NO_MEMORY);
5426 return;
5429 if (INFO_LEVEL_IS_UNIX(info_level)) {
5430 /* Always do lstat for UNIX calls. */
5431 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5432 DEBUG(3,("call_trans2qfilepathinfo: "
5433 "SMB_VFS_LSTAT of %s failed "
5434 "(%s)\n",
5435 smb_fname_str_dbg(smb_fname_base),
5436 strerror(errno)));
5437 TALLOC_FREE(smb_fname_base);
5438 reply_nterror(req,
5439 map_nt_error_from_unix(errno));
5440 return;
5442 } else {
5443 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5444 DEBUG(3,("call_trans2qfilepathinfo: "
5445 "fileinfo of %s failed "
5446 "(%s)\n",
5447 smb_fname_str_dbg(smb_fname_base),
5448 strerror(errno)));
5449 TALLOC_FREE(smb_fname_base);
5450 reply_nterror(req,
5451 map_nt_error_from_unix(errno));
5452 return;
5456 status = file_name_hash(conn,
5457 smb_fname_str_dbg(smb_fname_base),
5458 &name_hash);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 TALLOC_FREE(smb_fname_base);
5461 reply_nterror(req, status);
5462 return;
5465 fileid = vfs_file_id_from_sbuf(conn,
5466 &smb_fname_base->st);
5467 TALLOC_FREE(smb_fname_base);
5468 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5469 if (delete_pending) {
5470 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5471 return;
5475 if (INFO_LEVEL_IS_UNIX(info_level)) {
5476 /* Always do lstat for UNIX calls. */
5477 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5478 DEBUG(3,("call_trans2qfilepathinfo: "
5479 "SMB_VFS_LSTAT of %s failed (%s)\n",
5480 smb_fname_str_dbg(smb_fname),
5481 strerror(errno)));
5482 reply_nterror(req,
5483 map_nt_error_from_unix(errno));
5484 return;
5487 } else {
5488 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5489 DEBUG(3,("call_trans2qfilepathinfo: "
5490 "SMB_VFS_STAT of %s failed (%s)\n",
5491 smb_fname_str_dbg(smb_fname),
5492 strerror(errno)));
5493 reply_nterror(req,
5494 map_nt_error_from_unix(errno));
5495 return;
5499 status = file_name_hash(conn,
5500 smb_fname_str_dbg(smb_fname),
5501 &name_hash);
5502 if (!NT_STATUS_IS_OK(status)) {
5503 reply_nterror(req, status);
5504 return;
5507 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5508 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5509 if (delete_pending) {
5510 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5511 return;
5515 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5516 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5517 fsp_fnum_dbg(fsp),
5518 info_level,tran_call,total_data));
5520 /* Pull out any data sent here before we realloc. */
5521 switch (info_level) {
5522 case SMB_INFO_QUERY_EAS_FROM_LIST:
5524 /* Pull any EA list from the data portion. */
5525 uint32 ea_size;
5527 if (total_data < 4) {
5528 reply_nterror(
5529 req, NT_STATUS_INVALID_PARAMETER);
5530 return;
5532 ea_size = IVAL(pdata,0);
5534 if (total_data > 0 && ea_size != total_data) {
5535 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5536 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5537 reply_nterror(
5538 req, NT_STATUS_INVALID_PARAMETER);
5539 return;
5542 if (!lp_ea_support(SNUM(conn))) {
5543 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5544 return;
5547 /* Pull out the list of names. */
5548 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5549 if (!ea_list) {
5550 reply_nterror(
5551 req, NT_STATUS_INVALID_PARAMETER);
5552 return;
5554 break;
5557 case SMB_QUERY_POSIX_LOCK:
5559 if (fsp == NULL || fsp->fh->fd == -1) {
5560 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5561 return;
5564 if (total_data != POSIX_LOCK_DATA_SIZE) {
5565 reply_nterror(
5566 req, NT_STATUS_INVALID_PARAMETER);
5567 return;
5570 /* Copy the lock range data. */
5571 lock_data = (char *)talloc_memdup(
5572 req, pdata, total_data);
5573 if (!lock_data) {
5574 reply_nterror(req, NT_STATUS_NO_MEMORY);
5575 return;
5577 lock_data_count = total_data;
5579 default:
5580 break;
5583 *pparams = (char *)SMB_REALLOC(*pparams,2);
5584 if (*pparams == NULL) {
5585 reply_nterror(req, NT_STATUS_NO_MEMORY);
5586 return;
5588 params = *pparams;
5589 SSVAL(params,0,0);
5592 * draft-leach-cifs-v1-spec-02.txt
5593 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5594 * says:
5596 * The requested information is placed in the Data portion of the
5597 * transaction response. For the information levels greater than 0x100,
5598 * the transaction response has 1 parameter word which should be
5599 * ignored by the client.
5601 * However Windows only follows this rule for the IS_NAME_VALID call.
5603 switch (info_level) {
5604 case SMB_INFO_IS_NAME_VALID:
5605 param_size = 0;
5606 break;
5609 if ((info_level & 0xFF00) == 0xFF00) {
5611 * We use levels that start with 0xFF00
5612 * internally to represent SMB2 specific levels
5614 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5615 return;
5618 status = smbd_do_qfilepathinfo(conn, req, info_level,
5619 fsp, smb_fname,
5620 delete_pending, write_time_ts,
5621 ea_list,
5622 lock_data_count, lock_data,
5623 req->flags2, max_data_bytes,
5624 ppdata, &data_size);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 reply_nterror(req, status);
5627 return;
5630 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5631 max_data_bytes);
5633 return;
5636 /****************************************************************************
5637 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5638 code.
5639 ****************************************************************************/
5641 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5642 connection_struct *conn,
5643 struct smb_request *req,
5644 bool overwrite_if_exists,
5645 const struct smb_filename *smb_fname_old,
5646 struct smb_filename *smb_fname_new)
5648 NTSTATUS status = NT_STATUS_OK;
5650 /* source must already exist. */
5651 if (!VALID_STAT(smb_fname_old->st)) {
5652 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5655 if (VALID_STAT(smb_fname_new->st)) {
5656 if (overwrite_if_exists) {
5657 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5658 return NT_STATUS_FILE_IS_A_DIRECTORY;
5660 status = unlink_internals(conn,
5661 req,
5662 FILE_ATTRIBUTE_NORMAL,
5663 smb_fname_new,
5664 false);
5665 if (!NT_STATUS_IS_OK(status)) {
5666 return status;
5668 } else {
5669 /* Disallow if newname already exists. */
5670 return NT_STATUS_OBJECT_NAME_COLLISION;
5674 /* No links from a directory. */
5675 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5676 return NT_STATUS_FILE_IS_A_DIRECTORY;
5679 /* Setting a hardlink to/from a stream isn't currently supported. */
5680 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5681 is_ntfs_stream_smb_fname(smb_fname_new)) {
5682 return NT_STATUS_INVALID_PARAMETER;
5685 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5686 smb_fname_old->base_name, smb_fname_new->base_name));
5688 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5689 smb_fname_new->base_name) != 0) {
5690 status = map_nt_error_from_unix(errno);
5691 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5692 nt_errstr(status), smb_fname_old->base_name,
5693 smb_fname_new->base_name));
5695 return status;
5698 /****************************************************************************
5699 Deal with setting the time from any of the setfilepathinfo functions.
5700 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5701 calling this function.
5702 ****************************************************************************/
5704 NTSTATUS smb_set_file_time(connection_struct *conn,
5705 files_struct *fsp,
5706 const struct smb_filename *smb_fname,
5707 struct smb_file_time *ft,
5708 bool setting_write_time)
5710 struct smb_filename smb_fname_base;
5711 uint32 action =
5712 FILE_NOTIFY_CHANGE_LAST_ACCESS
5713 |FILE_NOTIFY_CHANGE_LAST_WRITE
5714 |FILE_NOTIFY_CHANGE_CREATION;
5716 if (!VALID_STAT(smb_fname->st)) {
5717 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5720 /* get some defaults (no modifications) if any info is zero or -1. */
5721 if (null_timespec(ft->create_time)) {
5722 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5725 if (null_timespec(ft->atime)) {
5726 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5729 if (null_timespec(ft->mtime)) {
5730 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5733 if (!setting_write_time) {
5734 /* ft->mtime comes from change time, not write time. */
5735 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5738 /* Ensure the resolution is the correct for
5739 * what we can store on this filesystem. */
5741 round_timespec(conn->ts_res, &ft->create_time);
5742 round_timespec(conn->ts_res, &ft->ctime);
5743 round_timespec(conn->ts_res, &ft->atime);
5744 round_timespec(conn->ts_res, &ft->mtime);
5746 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5747 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5748 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5749 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5750 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5751 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5752 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5753 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5755 if (setting_write_time) {
5757 * This was a Windows setfileinfo on an open file.
5758 * NT does this a lot. We also need to
5759 * set the time here, as it can be read by
5760 * FindFirst/FindNext and with the patch for bug #2045
5761 * in smbd/fileio.c it ensures that this timestamp is
5762 * kept sticky even after a write. We save the request
5763 * away and will set it on file close and after a write. JRA.
5766 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5767 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5769 if (fsp != NULL) {
5770 if (fsp->base_fsp) {
5771 set_sticky_write_time_fsp(fsp->base_fsp,
5772 ft->mtime);
5773 } else {
5774 set_sticky_write_time_fsp(fsp, ft->mtime);
5776 } else {
5777 set_sticky_write_time_path(
5778 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5779 ft->mtime);
5783 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5785 /* Always call ntimes on the base, even if a stream was passed in. */
5786 smb_fname_base = *smb_fname;
5787 smb_fname_base.stream_name = NULL;
5789 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5790 return map_nt_error_from_unix(errno);
5793 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5794 smb_fname->base_name);
5795 return NT_STATUS_OK;
5798 /****************************************************************************
5799 Deal with setting the dosmode from any of the setfilepathinfo functions.
5800 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5801 done before calling this function.
5802 ****************************************************************************/
5804 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5805 const struct smb_filename *smb_fname,
5806 uint32 dosmode)
5808 struct smb_filename *smb_fname_base;
5809 NTSTATUS status;
5811 if (!VALID_STAT(smb_fname->st)) {
5812 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5815 /* Always operate on the base_name, even if a stream was passed in. */
5816 smb_fname_base = synthetic_smb_fname(
5817 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5818 if (smb_fname_base == NULL) {
5819 return NT_STATUS_NO_MEMORY;
5822 if (dosmode) {
5823 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5824 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5825 } else {
5826 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5830 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5832 /* check the mode isn't different, before changing it */
5833 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5834 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5835 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5836 (unsigned int)dosmode));
5838 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5839 false)) {
5840 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5841 "%s failed (%s)\n",
5842 smb_fname_str_dbg(smb_fname_base),
5843 strerror(errno)));
5844 status = map_nt_error_from_unix(errno);
5845 goto out;
5848 status = NT_STATUS_OK;
5849 out:
5850 TALLOC_FREE(smb_fname_base);
5851 return status;
5854 /****************************************************************************
5855 Deal with setting the size from any of the setfilepathinfo functions.
5856 ****************************************************************************/
5858 static NTSTATUS smb_set_file_size(connection_struct *conn,
5859 struct smb_request *req,
5860 files_struct *fsp,
5861 const struct smb_filename *smb_fname,
5862 const SMB_STRUCT_STAT *psbuf,
5863 off_t size,
5864 bool fail_after_createfile)
5866 NTSTATUS status = NT_STATUS_OK;
5867 struct smb_filename *smb_fname_tmp = NULL;
5868 files_struct *new_fsp = NULL;
5870 if (!VALID_STAT(*psbuf)) {
5871 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5874 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5876 if (size == get_file_size_stat(psbuf)) {
5877 return NT_STATUS_OK;
5880 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5881 smb_fname_str_dbg(smb_fname), (double)size));
5883 if (fsp && fsp->fh->fd != -1) {
5884 /* Handle based call. */
5885 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5886 return NT_STATUS_ACCESS_DENIED;
5889 if (vfs_set_filelen(fsp, size) == -1) {
5890 return map_nt_error_from_unix(errno);
5892 trigger_write_time_update_immediate(fsp);
5893 return NT_STATUS_OK;
5896 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5897 if (smb_fname_tmp == NULL) {
5898 return NT_STATUS_NO_MEMORY;
5901 smb_fname_tmp->st = *psbuf;
5903 status = SMB_VFS_CREATE_FILE(
5904 conn, /* conn */
5905 req, /* req */
5906 0, /* root_dir_fid */
5907 smb_fname_tmp, /* fname */
5908 FILE_WRITE_DATA, /* access_mask */
5909 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5910 FILE_SHARE_DELETE),
5911 FILE_OPEN, /* create_disposition*/
5912 0, /* create_options */
5913 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5914 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5915 0, /* allocation_size */
5916 0, /* private_flags */
5917 NULL, /* sd */
5918 NULL, /* ea_list */
5919 &new_fsp, /* result */
5920 NULL); /* pinfo */
5922 TALLOC_FREE(smb_fname_tmp);
5924 if (!NT_STATUS_IS_OK(status)) {
5925 /* NB. We check for open_was_deferred in the caller. */
5926 return status;
5929 /* See RAW-SFILEINFO-END-OF-FILE */
5930 if (fail_after_createfile) {
5931 close_file(req, new_fsp,NORMAL_CLOSE);
5932 return NT_STATUS_INVALID_LEVEL;
5935 if (vfs_set_filelen(new_fsp, size) == -1) {
5936 status = map_nt_error_from_unix(errno);
5937 close_file(req, new_fsp,NORMAL_CLOSE);
5938 return status;
5941 trigger_write_time_update_immediate(new_fsp);
5942 close_file(req, new_fsp,NORMAL_CLOSE);
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_INFO_SET_EA.
5948 ****************************************************************************/
5950 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5951 const char *pdata,
5952 int total_data,
5953 files_struct *fsp,
5954 const struct smb_filename *smb_fname)
5956 struct ea_list *ea_list = NULL;
5957 TALLOC_CTX *ctx = NULL;
5958 NTSTATUS status = NT_STATUS_OK;
5960 if (total_data < 10) {
5962 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5963 length. They seem to have no effect. Bug #3212. JRA */
5965 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5966 /* We're done. We only get EA info in this call. */
5967 return NT_STATUS_OK;
5970 return NT_STATUS_INVALID_PARAMETER;
5973 if (IVAL(pdata,0) > total_data) {
5974 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5975 IVAL(pdata,0), (unsigned int)total_data));
5976 return NT_STATUS_INVALID_PARAMETER;
5979 ctx = talloc_tos();
5980 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5981 if (!ea_list) {
5982 return NT_STATUS_INVALID_PARAMETER;
5985 status = set_ea(conn, fsp, smb_fname, ea_list);
5987 return status;
5990 /****************************************************************************
5991 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5992 ****************************************************************************/
5994 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5995 const char *pdata,
5996 int total_data,
5997 files_struct *fsp)
5999 struct ea_list *ea_list = NULL;
6000 NTSTATUS status;
6002 if (!fsp) {
6003 return NT_STATUS_INVALID_HANDLE;
6006 if (!lp_ea_support(SNUM(conn))) {
6007 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6008 "EA's not supported.\n",
6009 (unsigned int)total_data));
6010 return NT_STATUS_EAS_NOT_SUPPORTED;
6013 if (total_data < 10) {
6014 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6015 "too small.\n",
6016 (unsigned int)total_data));
6017 return NT_STATUS_INVALID_PARAMETER;
6020 ea_list = read_nttrans_ea_list(talloc_tos(),
6021 pdata,
6022 total_data);
6024 if (!ea_list) {
6025 return NT_STATUS_INVALID_PARAMETER;
6028 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6030 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6031 smb_fname_str_dbg(fsp->fsp_name),
6032 nt_errstr(status) ));
6034 return status;
6038 /****************************************************************************
6039 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6040 ****************************************************************************/
6042 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6043 const char *pdata,
6044 int total_data,
6045 files_struct *fsp,
6046 struct smb_filename *smb_fname)
6048 NTSTATUS status = NT_STATUS_OK;
6049 bool delete_on_close;
6050 uint32 dosmode = 0;
6052 if (total_data < 1) {
6053 return NT_STATUS_INVALID_PARAMETER;
6056 if (fsp == NULL) {
6057 return NT_STATUS_INVALID_HANDLE;
6060 delete_on_close = (CVAL(pdata,0) ? True : False);
6061 dosmode = dos_mode(conn, smb_fname);
6063 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6064 "delete_on_close = %u\n",
6065 smb_fname_str_dbg(smb_fname),
6066 (unsigned int)dosmode,
6067 (unsigned int)delete_on_close ));
6069 if (delete_on_close) {
6070 status = can_set_delete_on_close(fsp, dosmode);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 return status;
6076 /* The set is across all open files on this dev/inode pair. */
6077 if (!set_delete_on_close(fsp, delete_on_close,
6078 conn->session_info->security_token,
6079 conn->session_info->unix_token)) {
6080 return NT_STATUS_ACCESS_DENIED;
6082 return NT_STATUS_OK;
6085 /****************************************************************************
6086 Deal with SMB_FILE_POSITION_INFORMATION.
6087 ****************************************************************************/
6089 static NTSTATUS smb_file_position_information(connection_struct *conn,
6090 const char *pdata,
6091 int total_data,
6092 files_struct *fsp)
6094 uint64_t position_information;
6096 if (total_data < 8) {
6097 return NT_STATUS_INVALID_PARAMETER;
6100 if (fsp == NULL) {
6101 /* Ignore on pathname based set. */
6102 return NT_STATUS_OK;
6105 position_information = (uint64_t)IVAL(pdata,0);
6106 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6108 DEBUG(10,("smb_file_position_information: Set file position "
6109 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6110 (double)position_information));
6111 fsp->fh->position_information = position_information;
6112 return NT_STATUS_OK;
6115 /****************************************************************************
6116 Deal with SMB_FILE_MODE_INFORMATION.
6117 ****************************************************************************/
6119 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6120 const char *pdata,
6121 int total_data)
6123 uint32 mode;
6125 if (total_data < 4) {
6126 return NT_STATUS_INVALID_PARAMETER;
6128 mode = IVAL(pdata,0);
6129 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6130 return NT_STATUS_INVALID_PARAMETER;
6132 return NT_STATUS_OK;
6135 /****************************************************************************
6136 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6137 ****************************************************************************/
6139 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6140 struct smb_request *req,
6141 const char *pdata,
6142 int total_data,
6143 const struct smb_filename *smb_fname)
6145 char *link_target = NULL;
6146 const char *newname = smb_fname->base_name;
6147 TALLOC_CTX *ctx = talloc_tos();
6149 /* Set a symbolic link. */
6150 /* Don't allow this if follow links is false. */
6152 if (total_data == 0) {
6153 return NT_STATUS_INVALID_PARAMETER;
6156 if (!lp_symlinks(SNUM(conn))) {
6157 return NT_STATUS_ACCESS_DENIED;
6160 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6161 total_data, STR_TERMINATE);
6163 if (!link_target) {
6164 return NT_STATUS_INVALID_PARAMETER;
6167 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6168 newname, link_target ));
6170 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6171 return map_nt_error_from_unix(errno);
6174 return NT_STATUS_OK;
6177 /****************************************************************************
6178 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6179 ****************************************************************************/
6181 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6182 struct smb_request *req,
6183 const char *pdata, int total_data,
6184 struct smb_filename *smb_fname_new)
6186 char *oldname = NULL;
6187 struct smb_filename *smb_fname_old = NULL;
6188 TALLOC_CTX *ctx = talloc_tos();
6189 NTSTATUS status = NT_STATUS_OK;
6191 /* Set a hard link. */
6192 if (total_data == 0) {
6193 return NT_STATUS_INVALID_PARAMETER;
6196 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6197 total_data, STR_TERMINATE, &status);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 return status;
6202 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6203 smb_fname_str_dbg(smb_fname_new), oldname));
6205 status = filename_convert(ctx,
6206 conn,
6207 req->flags2 & FLAGS2_DFS_PATHNAMES,
6208 oldname,
6210 NULL,
6211 &smb_fname_old);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 return status;
6216 return hardlink_internals(ctx, conn, req, false,
6217 smb_fname_old, smb_fname_new);
6220 /****************************************************************************
6221 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6222 ****************************************************************************/
6224 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6225 struct smb_request *req,
6226 const char *pdata,
6227 int total_data,
6228 files_struct *fsp,
6229 struct smb_filename *smb_fname_src)
6231 bool overwrite;
6232 uint32_t len;
6233 char *newname = NULL;
6234 struct smb_filename *smb_fname_dst = NULL;
6235 NTSTATUS status = NT_STATUS_OK;
6236 TALLOC_CTX *ctx = talloc_tos();
6238 if (!fsp) {
6239 return NT_STATUS_INVALID_HANDLE;
6242 if (total_data < 20) {
6243 return NT_STATUS_INVALID_PARAMETER;
6246 overwrite = (CVAL(pdata,0) ? True : False);
6247 len = IVAL(pdata,16);
6249 if (len > (total_data - 20) || (len == 0)) {
6250 return NT_STATUS_INVALID_PARAMETER;
6253 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6254 &pdata[20], len, STR_TERMINATE,
6255 &status);
6256 if (!NT_STATUS_IS_OK(status)) {
6257 return status;
6260 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6261 newname));
6263 status = filename_convert(ctx,
6264 conn,
6265 req->flags2 & FLAGS2_DFS_PATHNAMES,
6266 newname,
6267 UCF_SAVE_LCOMP,
6268 NULL,
6269 &smb_fname_dst);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 return status;
6274 if (fsp->base_fsp) {
6275 /* newname must be a stream name. */
6276 if (newname[0] != ':') {
6277 return NT_STATUS_NOT_SUPPORTED;
6280 /* Create an smb_fname to call rename_internals_fsp() with. */
6281 smb_fname_dst = synthetic_smb_fname(
6282 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6283 newname, NULL);
6284 if (smb_fname_dst == NULL) {
6285 status = NT_STATUS_NO_MEMORY;
6286 goto out;
6290 * Set the original last component, since
6291 * rename_internals_fsp() requires it.
6293 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6294 newname);
6295 if (smb_fname_dst->original_lcomp == NULL) {
6296 status = NT_STATUS_NO_MEMORY;
6297 goto out;
6302 DEBUG(10,("smb2_file_rename_information: "
6303 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6304 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6305 smb_fname_str_dbg(smb_fname_dst)));
6306 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6307 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6308 overwrite);
6310 out:
6311 TALLOC_FREE(smb_fname_dst);
6312 return status;
6315 static NTSTATUS smb_file_link_information(connection_struct *conn,
6316 struct smb_request *req,
6317 const char *pdata,
6318 int total_data,
6319 files_struct *fsp,
6320 struct smb_filename *smb_fname_src)
6322 bool overwrite;
6323 uint32_t len;
6324 char *newname = NULL;
6325 struct smb_filename *smb_fname_dst = NULL;
6326 NTSTATUS status = NT_STATUS_OK;
6327 TALLOC_CTX *ctx = talloc_tos();
6329 if (!fsp) {
6330 return NT_STATUS_INVALID_HANDLE;
6333 if (total_data < 20) {
6334 return NT_STATUS_INVALID_PARAMETER;
6337 overwrite = (CVAL(pdata,0) ? true : false);
6338 len = IVAL(pdata,16);
6340 if (len > (total_data - 20) || (len == 0)) {
6341 return NT_STATUS_INVALID_PARAMETER;
6344 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6345 &pdata[20], len, STR_TERMINATE,
6346 &status);
6347 if (!NT_STATUS_IS_OK(status)) {
6348 return status;
6351 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6352 newname));
6354 status = filename_convert(ctx,
6355 conn,
6356 req->flags2 & FLAGS2_DFS_PATHNAMES,
6357 newname,
6358 UCF_SAVE_LCOMP,
6359 NULL,
6360 &smb_fname_dst);
6361 if (!NT_STATUS_IS_OK(status)) {
6362 return status;
6365 if (fsp->base_fsp) {
6366 /* No stream names. */
6367 return NT_STATUS_NOT_SUPPORTED;
6370 DEBUG(10,("smb_file_link_information: "
6371 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6372 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6373 smb_fname_str_dbg(smb_fname_dst)));
6374 status = hardlink_internals(ctx,
6375 conn,
6376 req,
6377 overwrite,
6378 fsp->fsp_name,
6379 smb_fname_dst);
6381 TALLOC_FREE(smb_fname_dst);
6382 return status;
6385 /****************************************************************************
6386 Deal with SMB_FILE_RENAME_INFORMATION.
6387 ****************************************************************************/
6389 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6390 struct smb_request *req,
6391 const char *pdata,
6392 int total_data,
6393 files_struct *fsp,
6394 struct smb_filename *smb_fname_src)
6396 bool overwrite;
6397 uint32 root_fid;
6398 uint32 len;
6399 char *newname = NULL;
6400 struct smb_filename *smb_fname_dst = NULL;
6401 bool dest_has_wcard = False;
6402 NTSTATUS status = NT_STATUS_OK;
6403 char *p;
6404 TALLOC_CTX *ctx = talloc_tos();
6406 if (total_data < 13) {
6407 return NT_STATUS_INVALID_PARAMETER;
6410 overwrite = (CVAL(pdata,0) ? True : False);
6411 root_fid = IVAL(pdata,4);
6412 len = IVAL(pdata,8);
6414 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6415 return NT_STATUS_INVALID_PARAMETER;
6418 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6419 len, 0, &status,
6420 &dest_has_wcard);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 return status;
6425 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6426 newname));
6428 status = resolve_dfspath_wcard(ctx, conn,
6429 req->flags2 & FLAGS2_DFS_PATHNAMES,
6430 newname,
6431 true,
6432 !conn->sconn->using_smb2,
6433 &newname,
6434 &dest_has_wcard);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 return status;
6439 /* Check the new name has no '/' characters. */
6440 if (strchr_m(newname, '/')) {
6441 return NT_STATUS_NOT_SUPPORTED;
6444 if (fsp && fsp->base_fsp) {
6445 /* newname must be a stream name. */
6446 if (newname[0] != ':') {
6447 return NT_STATUS_NOT_SUPPORTED;
6450 /* Create an smb_fname to call rename_internals_fsp() with. */
6451 smb_fname_dst = synthetic_smb_fname(
6452 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6453 newname, NULL);
6454 if (smb_fname_dst == NULL) {
6455 status = NT_STATUS_NO_MEMORY;
6456 goto out;
6460 * Set the original last component, since
6461 * rename_internals_fsp() requires it.
6463 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6464 newname);
6465 if (smb_fname_dst->original_lcomp == NULL) {
6466 status = NT_STATUS_NO_MEMORY;
6467 goto out;
6470 } else {
6472 * Build up an smb_fname_dst based on the filename passed in.
6473 * We basically just strip off the last component, and put on
6474 * the newname instead.
6476 char *base_name = NULL;
6478 /* newname must *not* be a stream name. */
6479 if (newname[0] == ':') {
6480 return NT_STATUS_NOT_SUPPORTED;
6484 * Strip off the last component (filename) of the path passed
6485 * in.
6487 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6488 if (!base_name) {
6489 return NT_STATUS_NO_MEMORY;
6491 p = strrchr_m(base_name, '/');
6492 if (p) {
6493 p[1] = '\0';
6494 } else {
6495 base_name = talloc_strdup(ctx, "");
6496 if (!base_name) {
6497 return NT_STATUS_NO_MEMORY;
6500 /* Append the new name. */
6501 base_name = talloc_asprintf_append(base_name,
6502 "%s",
6503 newname);
6504 if (!base_name) {
6505 return NT_STATUS_NO_MEMORY;
6508 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6509 (UCF_SAVE_LCOMP |
6510 (dest_has_wcard ?
6511 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6512 0)));
6514 /* If an error we expect this to be
6515 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6517 if (!NT_STATUS_IS_OK(status)) {
6518 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6519 status)) {
6520 goto out;
6522 /* Create an smb_fname to call rename_internals_fsp() */
6523 smb_fname_dst = synthetic_smb_fname(
6524 ctx, base_name, NULL, NULL);
6525 if (smb_fname_dst == NULL) {
6526 status = NT_STATUS_NO_MEMORY;
6527 goto out;
6532 if (fsp) {
6533 DEBUG(10,("smb_file_rename_information: "
6534 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6535 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6536 smb_fname_str_dbg(smb_fname_dst)));
6537 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6538 overwrite);
6539 } else {
6540 DEBUG(10,("smb_file_rename_information: "
6541 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6542 smb_fname_str_dbg(smb_fname_src),
6543 smb_fname_str_dbg(smb_fname_dst)));
6544 status = rename_internals(ctx, conn, req, smb_fname_src,
6545 smb_fname_dst, 0, overwrite, false,
6546 dest_has_wcard,
6547 FILE_WRITE_ATTRIBUTES);
6549 out:
6550 TALLOC_FREE(smb_fname_dst);
6551 return status;
6554 /****************************************************************************
6555 Deal with SMB_SET_POSIX_ACL.
6556 ****************************************************************************/
6558 #if defined(HAVE_POSIX_ACLS)
6559 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6560 const char *pdata,
6561 int total_data,
6562 files_struct *fsp,
6563 const struct smb_filename *smb_fname)
6565 uint16 posix_acl_version;
6566 uint16 num_file_acls;
6567 uint16 num_def_acls;
6568 bool valid_file_acls = True;
6569 bool valid_def_acls = True;
6571 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6572 return NT_STATUS_INVALID_PARAMETER;
6574 posix_acl_version = SVAL(pdata,0);
6575 num_file_acls = SVAL(pdata,2);
6576 num_def_acls = SVAL(pdata,4);
6578 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6579 valid_file_acls = False;
6580 num_file_acls = 0;
6583 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6584 valid_def_acls = False;
6585 num_def_acls = 0;
6588 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6589 return NT_STATUS_INVALID_PARAMETER;
6592 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6593 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6598 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6599 (unsigned int)num_file_acls,
6600 (unsigned int)num_def_acls));
6602 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6603 smb_fname->base_name, num_file_acls,
6604 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6605 return map_nt_error_from_unix(errno);
6608 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6609 smb_fname->base_name, &smb_fname->st, num_def_acls,
6610 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6611 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6612 return map_nt_error_from_unix(errno);
6614 return NT_STATUS_OK;
6616 #endif
6618 /****************************************************************************
6619 Deal with SMB_SET_POSIX_LOCK.
6620 ****************************************************************************/
6622 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6623 struct smb_request *req,
6624 const char *pdata,
6625 int total_data,
6626 files_struct *fsp)
6628 uint64_t count;
6629 uint64_t offset;
6630 uint64_t smblctx;
6631 bool blocking_lock = False;
6632 enum brl_type lock_type;
6634 NTSTATUS status = NT_STATUS_OK;
6636 if (fsp == NULL || fsp->fh->fd == -1) {
6637 return NT_STATUS_INVALID_HANDLE;
6640 if (total_data != POSIX_LOCK_DATA_SIZE) {
6641 return NT_STATUS_INVALID_PARAMETER;
6644 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6645 case POSIX_LOCK_TYPE_READ:
6646 lock_type = READ_LOCK;
6647 break;
6648 case POSIX_LOCK_TYPE_WRITE:
6649 /* Return the right POSIX-mappable error code for files opened read-only. */
6650 if (!fsp->can_write) {
6651 return NT_STATUS_INVALID_HANDLE;
6653 lock_type = WRITE_LOCK;
6654 break;
6655 case POSIX_LOCK_TYPE_UNLOCK:
6656 lock_type = UNLOCK_LOCK;
6657 break;
6658 default:
6659 return NT_STATUS_INVALID_PARAMETER;
6662 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6663 blocking_lock = False;
6664 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6665 blocking_lock = True;
6666 } else {
6667 return NT_STATUS_INVALID_PARAMETER;
6670 if (!lp_blocking_locks(SNUM(conn))) {
6671 blocking_lock = False;
6674 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6675 #if defined(HAVE_LONGLONG)
6676 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6677 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6678 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6679 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6680 #else /* HAVE_LONGLONG */
6681 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6682 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6683 #endif /* HAVE_LONGLONG */
6685 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6686 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6687 fsp_str_dbg(fsp),
6688 (unsigned int)lock_type,
6689 (unsigned long long)smblctx,
6690 (double)count,
6691 (double)offset ));
6693 if (lock_type == UNLOCK_LOCK) {
6694 status = do_unlock(req->sconn->msg_ctx,
6695 fsp,
6696 smblctx,
6697 count,
6698 offset,
6699 POSIX_LOCK);
6700 } else {
6701 uint64_t block_smblctx;
6703 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6704 fsp,
6705 smblctx,
6706 count,
6707 offset,
6708 lock_type,
6709 POSIX_LOCK,
6710 blocking_lock,
6711 &status,
6712 &block_smblctx,
6713 NULL);
6715 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6717 * A blocking lock was requested. Package up
6718 * this smb into a queued request and push it
6719 * onto the blocking lock queue.
6721 if(push_blocking_lock_request(br_lck,
6722 req,
6723 fsp,
6724 -1, /* infinite timeout. */
6726 smblctx,
6727 lock_type,
6728 POSIX_LOCK,
6729 offset,
6730 count,
6731 block_smblctx)) {
6732 TALLOC_FREE(br_lck);
6733 return status;
6736 TALLOC_FREE(br_lck);
6739 return status;
6742 /****************************************************************************
6743 Deal with SMB_SET_FILE_BASIC_INFO.
6744 ****************************************************************************/
6746 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6747 const char *pdata,
6748 int total_data,
6749 files_struct *fsp,
6750 const struct smb_filename *smb_fname)
6752 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6753 struct smb_file_time ft;
6754 uint32 dosmode = 0;
6755 NTSTATUS status = NT_STATUS_OK;
6757 ZERO_STRUCT(ft);
6759 if (total_data < 36) {
6760 return NT_STATUS_INVALID_PARAMETER;
6763 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 return status;
6768 /* Set the attributes */
6769 dosmode = IVAL(pdata,32);
6770 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 return status;
6775 /* create time */
6776 ft.create_time = interpret_long_date(pdata);
6778 /* access time */
6779 ft.atime = interpret_long_date(pdata+8);
6781 /* write time. */
6782 ft.mtime = interpret_long_date(pdata+16);
6784 /* change time. */
6785 ft.ctime = interpret_long_date(pdata+24);
6787 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6788 smb_fname_str_dbg(smb_fname)));
6790 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6791 true);
6794 /****************************************************************************
6795 Deal with SMB_INFO_STANDARD.
6796 ****************************************************************************/
6798 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6799 const char *pdata,
6800 int total_data,
6801 files_struct *fsp,
6802 const struct smb_filename *smb_fname)
6804 NTSTATUS status;
6805 struct smb_file_time ft;
6807 ZERO_STRUCT(ft);
6809 if (total_data < 12) {
6810 return NT_STATUS_INVALID_PARAMETER;
6813 /* create time */
6814 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6815 /* access time */
6816 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6817 /* write time */
6818 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6820 DEBUG(10,("smb_set_info_standard: file %s\n",
6821 smb_fname_str_dbg(smb_fname)));
6823 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6824 if (!NT_STATUS_IS_OK(status)) {
6825 return status;
6828 return smb_set_file_time(conn,
6829 fsp,
6830 smb_fname,
6831 &ft,
6832 true);
6835 /****************************************************************************
6836 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6837 ****************************************************************************/
6839 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6840 struct smb_request *req,
6841 const char *pdata,
6842 int total_data,
6843 files_struct *fsp,
6844 struct smb_filename *smb_fname)
6846 uint64_t allocation_size = 0;
6847 NTSTATUS status = NT_STATUS_OK;
6848 files_struct *new_fsp = NULL;
6850 if (!VALID_STAT(smb_fname->st)) {
6851 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6854 if (total_data < 8) {
6855 return NT_STATUS_INVALID_PARAMETER;
6858 allocation_size = (uint64_t)IVAL(pdata,0);
6859 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6860 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6861 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6862 (double)allocation_size));
6864 if (allocation_size) {
6865 allocation_size = smb_roundup(conn, allocation_size);
6868 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6869 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6870 (double)allocation_size));
6872 if (fsp && fsp->fh->fd != -1) {
6873 /* Open file handle. */
6874 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6875 return NT_STATUS_ACCESS_DENIED;
6878 /* Only change if needed. */
6879 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6880 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6881 return map_nt_error_from_unix(errno);
6884 /* But always update the time. */
6886 * This is equivalent to a write. Ensure it's seen immediately
6887 * if there are no pending writes.
6889 trigger_write_time_update_immediate(fsp);
6890 return NT_STATUS_OK;
6893 /* Pathname or stat or directory file. */
6894 status = SMB_VFS_CREATE_FILE(
6895 conn, /* conn */
6896 req, /* req */
6897 0, /* root_dir_fid */
6898 smb_fname, /* fname */
6899 FILE_WRITE_DATA, /* access_mask */
6900 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6901 FILE_SHARE_DELETE),
6902 FILE_OPEN, /* create_disposition*/
6903 0, /* create_options */
6904 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6905 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6906 0, /* allocation_size */
6907 0, /* private_flags */
6908 NULL, /* sd */
6909 NULL, /* ea_list */
6910 &new_fsp, /* result */
6911 NULL); /* pinfo */
6913 if (!NT_STATUS_IS_OK(status)) {
6914 /* NB. We check for open_was_deferred in the caller. */
6915 return status;
6918 /* Only change if needed. */
6919 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6920 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6921 status = map_nt_error_from_unix(errno);
6922 close_file(req, new_fsp, NORMAL_CLOSE);
6923 return status;
6927 /* Changing the allocation size should set the last mod time. */
6929 * This is equivalent to a write. Ensure it's seen immediately
6930 * if there are no pending writes.
6932 trigger_write_time_update_immediate(new_fsp);
6934 close_file(req, new_fsp, NORMAL_CLOSE);
6935 return NT_STATUS_OK;
6938 /****************************************************************************
6939 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6940 ****************************************************************************/
6942 static NTSTATUS smb_set_file_end_of_file_info(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,
6948 bool fail_after_createfile)
6950 off_t size;
6952 if (total_data < 8) {
6953 return NT_STATUS_INVALID_PARAMETER;
6956 size = IVAL(pdata,0);
6957 size |= (((off_t)IVAL(pdata,4)) << 32);
6958 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6959 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6960 (double)size));
6962 return smb_set_file_size(conn, req,
6963 fsp,
6964 smb_fname,
6965 &smb_fname->st,
6966 size,
6967 fail_after_createfile);
6970 /****************************************************************************
6971 Allow a UNIX info mknod.
6972 ****************************************************************************/
6974 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6975 const char *pdata,
6976 int total_data,
6977 const struct smb_filename *smb_fname)
6979 uint32 file_type = IVAL(pdata,56);
6980 #if defined(HAVE_MAKEDEV)
6981 uint32 dev_major = IVAL(pdata,60);
6982 uint32 dev_minor = IVAL(pdata,68);
6983 #endif
6984 SMB_DEV_T dev = (SMB_DEV_T)0;
6985 uint32 raw_unixmode = IVAL(pdata,84);
6986 NTSTATUS status;
6987 mode_t unixmode;
6989 if (total_data < 100) {
6990 return NT_STATUS_INVALID_PARAMETER;
6993 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6994 PERM_NEW_FILE, &unixmode);
6995 if (!NT_STATUS_IS_OK(status)) {
6996 return status;
6999 #if defined(HAVE_MAKEDEV)
7000 dev = makedev(dev_major, dev_minor);
7001 #endif
7003 switch (file_type) {
7004 #if defined(S_IFIFO)
7005 case UNIX_TYPE_FIFO:
7006 unixmode |= S_IFIFO;
7007 break;
7008 #endif
7009 #if defined(S_IFSOCK)
7010 case UNIX_TYPE_SOCKET:
7011 unixmode |= S_IFSOCK;
7012 break;
7013 #endif
7014 #if defined(S_IFCHR)
7015 case UNIX_TYPE_CHARDEV:
7016 unixmode |= S_IFCHR;
7017 break;
7018 #endif
7019 #if defined(S_IFBLK)
7020 case UNIX_TYPE_BLKDEV:
7021 unixmode |= S_IFBLK;
7022 break;
7023 #endif
7024 default:
7025 return NT_STATUS_INVALID_PARAMETER;
7028 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7029 "%.0f mode 0%o for file %s\n", (double)dev,
7030 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7032 /* Ok - do the mknod. */
7033 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7034 return map_nt_error_from_unix(errno);
7037 /* If any of the other "set" calls fail we
7038 * don't want to end up with a half-constructed mknod.
7041 if (lp_inherit_perms(SNUM(conn))) {
7042 char *parent;
7043 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7044 &parent, NULL)) {
7045 return NT_STATUS_NO_MEMORY;
7047 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7048 unixmode);
7049 TALLOC_FREE(parent);
7052 return NT_STATUS_OK;
7055 /****************************************************************************
7056 Deal with SMB_SET_FILE_UNIX_BASIC.
7057 ****************************************************************************/
7059 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7060 struct smb_request *req,
7061 const char *pdata,
7062 int total_data,
7063 files_struct *fsp,
7064 const struct smb_filename *smb_fname)
7066 struct smb_file_time ft;
7067 uint32 raw_unixmode;
7068 mode_t unixmode;
7069 off_t size = 0;
7070 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7071 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7072 NTSTATUS status = NT_STATUS_OK;
7073 bool delete_on_fail = False;
7074 enum perm_type ptype;
7075 files_struct *all_fsps = NULL;
7076 bool modify_mtime = true;
7077 struct file_id id;
7078 struct smb_filename *smb_fname_tmp = NULL;
7079 SMB_STRUCT_STAT sbuf;
7081 ZERO_STRUCT(ft);
7083 if (total_data < 100) {
7084 return NT_STATUS_INVALID_PARAMETER;
7087 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7088 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7089 size=IVAL(pdata,0); /* first 8 Bytes are size */
7090 size |= (((off_t)IVAL(pdata,4)) << 32);
7093 ft.atime = interpret_long_date(pdata+24); /* access_time */
7094 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7095 set_owner = (uid_t)IVAL(pdata,40);
7096 set_grp = (gid_t)IVAL(pdata,48);
7097 raw_unixmode = IVAL(pdata,84);
7099 if (VALID_STAT(smb_fname->st)) {
7100 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7101 ptype = PERM_EXISTING_DIR;
7102 } else {
7103 ptype = PERM_EXISTING_FILE;
7105 } else {
7106 ptype = PERM_NEW_FILE;
7109 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7110 ptype, &unixmode);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 return status;
7115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7116 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7117 smb_fname_str_dbg(smb_fname), (double)size,
7118 (unsigned int)set_owner, (unsigned int)set_grp,
7119 (int)raw_unixmode));
7121 sbuf = smb_fname->st;
7123 if (!VALID_STAT(sbuf)) {
7125 * The only valid use of this is to create character and block
7126 * devices, and named pipes. This is deprecated (IMHO) and
7127 * a new info level should be used for mknod. JRA.
7130 status = smb_unix_mknod(conn,
7131 pdata,
7132 total_data,
7133 smb_fname);
7134 if (!NT_STATUS_IS_OK(status)) {
7135 return status;
7138 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7139 if (smb_fname_tmp == NULL) {
7140 return NT_STATUS_NO_MEMORY;
7143 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7144 status = map_nt_error_from_unix(errno);
7145 TALLOC_FREE(smb_fname_tmp);
7146 SMB_VFS_UNLINK(conn, smb_fname);
7147 return status;
7150 sbuf = smb_fname_tmp->st;
7151 smb_fname = smb_fname_tmp;
7153 /* Ensure we don't try and change anything else. */
7154 raw_unixmode = SMB_MODE_NO_CHANGE;
7155 size = get_file_size_stat(&sbuf);
7156 ft.atime = sbuf.st_ex_atime;
7157 ft.mtime = sbuf.st_ex_mtime;
7159 * We continue here as we might want to change the
7160 * owner uid/gid.
7162 delete_on_fail = True;
7165 #if 1
7166 /* Horrible backwards compatibility hack as an old server bug
7167 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7168 * */
7170 if (!size) {
7171 size = get_file_size_stat(&sbuf);
7173 #endif
7176 * Deal with the UNIX specific mode set.
7179 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7180 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7181 "setting mode 0%o for file %s\n",
7182 (unsigned int)unixmode,
7183 smb_fname_str_dbg(smb_fname)));
7184 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7185 return map_nt_error_from_unix(errno);
7190 * Deal with the UNIX specific uid set.
7193 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7194 (sbuf.st_ex_uid != set_owner)) {
7195 int ret;
7197 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7198 "changing owner %u for path %s\n",
7199 (unsigned int)set_owner,
7200 smb_fname_str_dbg(smb_fname)));
7202 if (S_ISLNK(sbuf.st_ex_mode)) {
7203 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7204 set_owner, (gid_t)-1);
7205 } else {
7206 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7207 set_owner, (gid_t)-1);
7210 if (ret != 0) {
7211 status = map_nt_error_from_unix(errno);
7212 if (delete_on_fail) {
7213 SMB_VFS_UNLINK(conn, smb_fname);
7215 return status;
7220 * Deal with the UNIX specific gid set.
7223 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7224 (sbuf.st_ex_gid != set_grp)) {
7225 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7226 "changing group %u for file %s\n",
7227 (unsigned int)set_owner,
7228 smb_fname_str_dbg(smb_fname)));
7229 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7230 set_grp) != 0) {
7231 status = map_nt_error_from_unix(errno);
7232 if (delete_on_fail) {
7233 SMB_VFS_UNLINK(conn, smb_fname);
7235 return status;
7239 /* Deal with any size changes. */
7241 status = smb_set_file_size(conn, req,
7242 fsp,
7243 smb_fname,
7244 &sbuf,
7245 size,
7246 false);
7247 if (!NT_STATUS_IS_OK(status)) {
7248 return status;
7251 /* Deal with any time changes. */
7252 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7253 /* No change, don't cancel anything. */
7254 return status;
7257 id = vfs_file_id_from_sbuf(conn, &sbuf);
7258 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7259 all_fsps = file_find_di_next(all_fsps)) {
7261 * We're setting the time explicitly for UNIX.
7262 * Cancel any pending changes over all handles.
7264 all_fsps->update_write_time_on_close = false;
7265 TALLOC_FREE(all_fsps->update_write_time_event);
7269 * Override the "setting_write_time"
7270 * parameter here as it almost does what
7271 * we need. Just remember if we modified
7272 * mtime and send the notify ourselves.
7274 if (null_timespec(ft.mtime)) {
7275 modify_mtime = false;
7278 status = smb_set_file_time(conn,
7279 fsp,
7280 smb_fname,
7281 &ft,
7282 false);
7283 if (modify_mtime) {
7284 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7285 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7287 return status;
7290 /****************************************************************************
7291 Deal with SMB_SET_FILE_UNIX_INFO2.
7292 ****************************************************************************/
7294 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7295 struct smb_request *req,
7296 const char *pdata,
7297 int total_data,
7298 files_struct *fsp,
7299 const struct smb_filename *smb_fname)
7301 NTSTATUS status;
7302 uint32 smb_fflags;
7303 uint32 smb_fmask;
7305 if (total_data < 116) {
7306 return NT_STATUS_INVALID_PARAMETER;
7309 /* Start by setting all the fields that are common between UNIX_BASIC
7310 * and UNIX_INFO2.
7312 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7313 fsp, smb_fname);
7314 if (!NT_STATUS_IS_OK(status)) {
7315 return status;
7318 smb_fflags = IVAL(pdata, 108);
7319 smb_fmask = IVAL(pdata, 112);
7321 /* NB: We should only attempt to alter the file flags if the client
7322 * sends a non-zero mask.
7324 if (smb_fmask != 0) {
7325 int stat_fflags = 0;
7327 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7328 smb_fmask, &stat_fflags)) {
7329 /* Client asked to alter a flag we don't understand. */
7330 return NT_STATUS_INVALID_PARAMETER;
7333 if (fsp && fsp->fh->fd != -1) {
7334 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7335 return NT_STATUS_NOT_SUPPORTED;
7336 } else {
7337 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7338 stat_fflags) != 0) {
7339 return map_nt_error_from_unix(errno);
7344 /* XXX: need to add support for changing the create_time here. You
7345 * can do this for paths on Darwin with setattrlist(2). The right way
7346 * to hook this up is probably by extending the VFS utimes interface.
7349 return NT_STATUS_OK;
7352 /****************************************************************************
7353 Create a directory with POSIX semantics.
7354 ****************************************************************************/
7356 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7357 struct smb_request *req,
7358 char **ppdata,
7359 int total_data,
7360 struct smb_filename *smb_fname,
7361 int *pdata_return_size)
7363 NTSTATUS status = NT_STATUS_OK;
7364 uint32 raw_unixmode = 0;
7365 uint32 mod_unixmode = 0;
7366 mode_t unixmode = (mode_t)0;
7367 files_struct *fsp = NULL;
7368 uint16 info_level_return = 0;
7369 int info;
7370 char *pdata = *ppdata;
7372 if (total_data < 18) {
7373 return NT_STATUS_INVALID_PARAMETER;
7376 raw_unixmode = IVAL(pdata,8);
7377 /* Next 4 bytes are not yet defined. */
7379 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7380 PERM_NEW_DIR, &unixmode);
7381 if (!NT_STATUS_IS_OK(status)) {
7382 return status;
7385 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7387 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7388 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7390 status = SMB_VFS_CREATE_FILE(
7391 conn, /* conn */
7392 req, /* req */
7393 0, /* root_dir_fid */
7394 smb_fname, /* fname */
7395 FILE_READ_ATTRIBUTES, /* access_mask */
7396 FILE_SHARE_NONE, /* share_access */
7397 FILE_CREATE, /* create_disposition*/
7398 FILE_DIRECTORY_FILE, /* create_options */
7399 mod_unixmode, /* file_attributes */
7400 0, /* oplock_request */
7401 0, /* allocation_size */
7402 0, /* private_flags */
7403 NULL, /* sd */
7404 NULL, /* ea_list */
7405 &fsp, /* result */
7406 &info); /* pinfo */
7408 if (NT_STATUS_IS_OK(status)) {
7409 close_file(req, fsp, NORMAL_CLOSE);
7412 info_level_return = SVAL(pdata,16);
7414 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7415 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7416 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7417 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7418 } else {
7419 *pdata_return_size = 12;
7422 /* Realloc the data size */
7423 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7424 if (*ppdata == NULL) {
7425 *pdata_return_size = 0;
7426 return NT_STATUS_NO_MEMORY;
7428 pdata = *ppdata;
7430 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7431 SSVAL(pdata,2,0); /* No fnum. */
7432 SIVAL(pdata,4,info); /* Was directory created. */
7434 switch (info_level_return) {
7435 case SMB_QUERY_FILE_UNIX_BASIC:
7436 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7437 SSVAL(pdata,10,0); /* Padding. */
7438 store_file_unix_basic(conn, pdata + 12, fsp,
7439 &smb_fname->st);
7440 break;
7441 case SMB_QUERY_FILE_UNIX_INFO2:
7442 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7443 SSVAL(pdata,10,0); /* Padding. */
7444 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7445 &smb_fname->st);
7446 break;
7447 default:
7448 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7449 SSVAL(pdata,10,0); /* Padding. */
7450 break;
7453 return status;
7456 /****************************************************************************
7457 Open/Create a file with POSIX semantics.
7458 ****************************************************************************/
7460 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7461 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7463 static NTSTATUS smb_posix_open(connection_struct *conn,
7464 struct smb_request *req,
7465 char **ppdata,
7466 int total_data,
7467 struct smb_filename *smb_fname,
7468 int *pdata_return_size)
7470 bool extended_oplock_granted = False;
7471 char *pdata = *ppdata;
7472 uint32 flags = 0;
7473 uint32 wire_open_mode = 0;
7474 uint32 raw_unixmode = 0;
7475 uint32 mod_unixmode = 0;
7476 uint32 create_disp = 0;
7477 uint32 access_mask = 0;
7478 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7479 NTSTATUS status = NT_STATUS_OK;
7480 mode_t unixmode = (mode_t)0;
7481 files_struct *fsp = NULL;
7482 int oplock_request = 0;
7483 int info = 0;
7484 uint16 info_level_return = 0;
7486 if (total_data < 18) {
7487 return NT_STATUS_INVALID_PARAMETER;
7490 flags = IVAL(pdata,0);
7491 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7492 if (oplock_request) {
7493 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7496 wire_open_mode = IVAL(pdata,4);
7498 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7499 return smb_posix_mkdir(conn, req,
7500 ppdata,
7501 total_data,
7502 smb_fname,
7503 pdata_return_size);
7506 switch (wire_open_mode & SMB_ACCMODE) {
7507 case SMB_O_RDONLY:
7508 access_mask = SMB_O_RDONLY_MAPPING;
7509 break;
7510 case SMB_O_WRONLY:
7511 access_mask = SMB_O_WRONLY_MAPPING;
7512 break;
7513 case SMB_O_RDWR:
7514 access_mask = (SMB_O_RDONLY_MAPPING|
7515 SMB_O_WRONLY_MAPPING);
7516 break;
7517 default:
7518 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7519 (unsigned int)wire_open_mode ));
7520 return NT_STATUS_INVALID_PARAMETER;
7523 wire_open_mode &= ~SMB_ACCMODE;
7525 /* First take care of O_CREAT|O_EXCL interactions. */
7526 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7527 case (SMB_O_CREAT | SMB_O_EXCL):
7528 /* File exists fail. File not exist create. */
7529 create_disp = FILE_CREATE;
7530 break;
7531 case SMB_O_CREAT:
7532 /* File exists open. File not exist create. */
7533 create_disp = FILE_OPEN_IF;
7534 break;
7535 case SMB_O_EXCL:
7536 /* O_EXCL on its own without O_CREAT is undefined.
7537 We deliberately ignore it as some versions of
7538 Linux CIFSFS can send a bare O_EXCL on the
7539 wire which other filesystems in the kernel
7540 ignore. See bug 9519 for details. */
7542 /* Fallthrough. */
7544 case 0:
7545 /* File exists open. File not exist fail. */
7546 create_disp = FILE_OPEN;
7547 break;
7548 default:
7549 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7550 (unsigned int)wire_open_mode ));
7551 return NT_STATUS_INVALID_PARAMETER;
7554 /* Next factor in the effects of O_TRUNC. */
7555 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7557 if (wire_open_mode & SMB_O_TRUNC) {
7558 switch (create_disp) {
7559 case FILE_CREATE:
7560 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7561 /* Leave create_disp alone as
7562 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7564 /* File exists fail. File not exist create. */
7565 break;
7566 case FILE_OPEN_IF:
7567 /* SMB_O_CREAT | SMB_O_TRUNC */
7568 /* File exists overwrite. File not exist create. */
7569 create_disp = FILE_OVERWRITE_IF;
7570 break;
7571 case FILE_OPEN:
7572 /* SMB_O_TRUNC */
7573 /* File exists overwrite. File not exist fail. */
7574 create_disp = FILE_OVERWRITE;
7575 break;
7576 default:
7577 /* Cannot get here. */
7578 smb_panic("smb_posix_open: logic error");
7579 return NT_STATUS_INVALID_PARAMETER;
7583 raw_unixmode = IVAL(pdata,8);
7584 /* Next 4 bytes are not yet defined. */
7586 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7587 (VALID_STAT(smb_fname->st) ?
7588 PERM_EXISTING_FILE : PERM_NEW_FILE),
7589 &unixmode);
7591 if (!NT_STATUS_IS_OK(status)) {
7592 return status;
7595 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7597 if (wire_open_mode & SMB_O_SYNC) {
7598 create_options |= FILE_WRITE_THROUGH;
7600 if (wire_open_mode & SMB_O_APPEND) {
7601 access_mask |= FILE_APPEND_DATA;
7603 if (wire_open_mode & SMB_O_DIRECT) {
7604 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7607 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7608 VALID_STAT_OF_DIR(smb_fname->st)) {
7609 if (access_mask != SMB_O_RDONLY_MAPPING) {
7610 return NT_STATUS_FILE_IS_A_DIRECTORY;
7612 create_options &= ~FILE_NON_DIRECTORY_FILE;
7613 create_options |= FILE_DIRECTORY_FILE;
7616 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7617 smb_fname_str_dbg(smb_fname),
7618 (unsigned int)wire_open_mode,
7619 (unsigned int)unixmode ));
7621 status = SMB_VFS_CREATE_FILE(
7622 conn, /* conn */
7623 req, /* req */
7624 0, /* root_dir_fid */
7625 smb_fname, /* fname */
7626 access_mask, /* access_mask */
7627 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7628 FILE_SHARE_DELETE),
7629 create_disp, /* create_disposition*/
7630 create_options, /* create_options */
7631 mod_unixmode, /* file_attributes */
7632 oplock_request, /* oplock_request */
7633 0, /* allocation_size */
7634 0, /* private_flags */
7635 NULL, /* sd */
7636 NULL, /* ea_list */
7637 &fsp, /* result */
7638 &info); /* pinfo */
7640 if (!NT_STATUS_IS_OK(status)) {
7641 return status;
7644 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7645 extended_oplock_granted = True;
7648 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7649 extended_oplock_granted = True;
7652 info_level_return = SVAL(pdata,16);
7654 /* Allocate the correct return size. */
7656 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7657 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7658 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7659 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7660 } else {
7661 *pdata_return_size = 12;
7664 /* Realloc the data size */
7665 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7666 if (*ppdata == NULL) {
7667 close_file(req, fsp, ERROR_CLOSE);
7668 *pdata_return_size = 0;
7669 return NT_STATUS_NO_MEMORY;
7671 pdata = *ppdata;
7673 if (extended_oplock_granted) {
7674 if (flags & REQUEST_BATCH_OPLOCK) {
7675 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7676 } else {
7677 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7679 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7680 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7681 } else {
7682 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7685 SSVAL(pdata,2,fsp->fnum);
7686 SIVAL(pdata,4,info); /* Was file created etc. */
7688 switch (info_level_return) {
7689 case SMB_QUERY_FILE_UNIX_BASIC:
7690 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7691 SSVAL(pdata,10,0); /* padding. */
7692 store_file_unix_basic(conn, pdata + 12, fsp,
7693 &smb_fname->st);
7694 break;
7695 case SMB_QUERY_FILE_UNIX_INFO2:
7696 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7697 SSVAL(pdata,10,0); /* padding. */
7698 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7699 &smb_fname->st);
7700 break;
7701 default:
7702 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7703 SSVAL(pdata,10,0); /* padding. */
7704 break;
7706 return NT_STATUS_OK;
7709 /****************************************************************************
7710 Delete a file with POSIX semantics.
7711 ****************************************************************************/
7713 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7714 struct smb_request *req,
7715 const char *pdata,
7716 int total_data,
7717 struct smb_filename *smb_fname)
7719 NTSTATUS status = NT_STATUS_OK;
7720 files_struct *fsp = NULL;
7721 uint16 flags = 0;
7722 char del = 1;
7723 int info = 0;
7724 int create_options = 0;
7725 int i;
7726 struct share_mode_lock *lck = NULL;
7728 if (total_data < 2) {
7729 return NT_STATUS_INVALID_PARAMETER;
7732 flags = SVAL(pdata,0);
7734 if (!VALID_STAT(smb_fname->st)) {
7735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7738 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7739 !VALID_STAT_OF_DIR(smb_fname->st)) {
7740 return NT_STATUS_NOT_A_DIRECTORY;
7743 DEBUG(10,("smb_posix_unlink: %s %s\n",
7744 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7745 smb_fname_str_dbg(smb_fname)));
7747 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7748 create_options |= FILE_DIRECTORY_FILE;
7751 status = SMB_VFS_CREATE_FILE(
7752 conn, /* conn */
7753 req, /* req */
7754 0, /* root_dir_fid */
7755 smb_fname, /* fname */
7756 DELETE_ACCESS, /* access_mask */
7757 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7758 FILE_SHARE_DELETE),
7759 FILE_OPEN, /* create_disposition*/
7760 create_options, /* create_options */
7761 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7762 0, /* oplock_request */
7763 0, /* allocation_size */
7764 0, /* private_flags */
7765 NULL, /* sd */
7766 NULL, /* ea_list */
7767 &fsp, /* result */
7768 &info); /* pinfo */
7770 if (!NT_STATUS_IS_OK(status)) {
7771 return status;
7775 * Don't lie to client. If we can't really delete due to
7776 * non-POSIX opens return SHARING_VIOLATION.
7779 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7780 if (lck == NULL) {
7781 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7782 "lock for file %s\n", fsp_str_dbg(fsp)));
7783 close_file(req, fsp, NORMAL_CLOSE);
7784 return NT_STATUS_INVALID_PARAMETER;
7788 * See if others still have the file open. If this is the case, then
7789 * don't delete. If all opens are POSIX delete we can set the delete
7790 * on close disposition.
7792 for (i=0; i<lck->data->num_share_modes; i++) {
7793 struct share_mode_entry *e = &lck->data->share_modes[i];
7794 if (is_valid_share_mode_entry(e)) {
7795 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7796 continue;
7798 if (share_mode_stale_pid(lck->data, i)) {
7799 continue;
7801 /* Fail with sharing violation. */
7802 TALLOC_FREE(lck);
7803 close_file(req, fsp, NORMAL_CLOSE);
7804 return NT_STATUS_SHARING_VIOLATION;
7809 * Set the delete on close.
7811 status = smb_set_file_disposition_info(conn,
7812 &del,
7814 fsp,
7815 smb_fname);
7817 TALLOC_FREE(lck);
7819 if (!NT_STATUS_IS_OK(status)) {
7820 close_file(req, fsp, NORMAL_CLOSE);
7821 return status;
7823 return close_file(req, fsp, NORMAL_CLOSE);
7826 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7827 struct smb_request *req,
7828 TALLOC_CTX *mem_ctx,
7829 uint16_t info_level,
7830 files_struct *fsp,
7831 struct smb_filename *smb_fname,
7832 char **ppdata, int total_data,
7833 int *ret_data_size)
7835 char *pdata = *ppdata;
7836 NTSTATUS status = NT_STATUS_OK;
7837 int data_return_size = 0;
7839 *ret_data_size = 0;
7841 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7842 return NT_STATUS_INVALID_LEVEL;
7845 if (!CAN_WRITE(conn)) {
7846 /* Allow POSIX opens. The open path will deny
7847 * any non-readonly opens. */
7848 if (info_level != SMB_POSIX_PATH_OPEN) {
7849 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7853 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7854 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7855 fsp_fnum_dbg(fsp),
7856 info_level, total_data));
7858 switch (info_level) {
7860 case SMB_INFO_STANDARD:
7862 status = smb_set_info_standard(conn,
7863 pdata,
7864 total_data,
7865 fsp,
7866 smb_fname);
7867 break;
7870 case SMB_INFO_SET_EA:
7872 status = smb_info_set_ea(conn,
7873 pdata,
7874 total_data,
7875 fsp,
7876 smb_fname);
7877 break;
7880 case SMB_SET_FILE_BASIC_INFO:
7881 case SMB_FILE_BASIC_INFORMATION:
7883 status = smb_set_file_basic_info(conn,
7884 pdata,
7885 total_data,
7886 fsp,
7887 smb_fname);
7888 break;
7891 case SMB_FILE_ALLOCATION_INFORMATION:
7892 case SMB_SET_FILE_ALLOCATION_INFO:
7894 status = smb_set_file_allocation_info(conn, req,
7895 pdata,
7896 total_data,
7897 fsp,
7898 smb_fname);
7899 break;
7902 case SMB_FILE_END_OF_FILE_INFORMATION:
7903 case SMB_SET_FILE_END_OF_FILE_INFO:
7906 * XP/Win7 both fail after the createfile with
7907 * SMB_SET_FILE_END_OF_FILE_INFO but not
7908 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7909 * The level is known here, so pass it down
7910 * appropriately.
7912 bool should_fail =
7913 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7915 status = smb_set_file_end_of_file_info(conn, req,
7916 pdata,
7917 total_data,
7918 fsp,
7919 smb_fname,
7920 should_fail);
7921 break;
7924 case SMB_FILE_DISPOSITION_INFORMATION:
7925 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7927 #if 0
7928 /* JRA - We used to just ignore this on a path ?
7929 * Shouldn't this be invalid level on a pathname
7930 * based call ?
7932 if (tran_call != TRANSACT2_SETFILEINFO) {
7933 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7935 #endif
7936 status = smb_set_file_disposition_info(conn,
7937 pdata,
7938 total_data,
7939 fsp,
7940 smb_fname);
7941 break;
7944 case SMB_FILE_POSITION_INFORMATION:
7946 status = smb_file_position_information(conn,
7947 pdata,
7948 total_data,
7949 fsp);
7950 break;
7953 case SMB_FILE_FULL_EA_INFORMATION:
7955 status = smb_set_file_full_ea_info(conn,
7956 pdata,
7957 total_data,
7958 fsp);
7959 break;
7962 /* From tridge Samba4 :
7963 * MODE_INFORMATION in setfileinfo (I have no
7964 * idea what "mode information" on a file is - it takes a value of 0,
7965 * 2, 4 or 6. What could it be?).
7968 case SMB_FILE_MODE_INFORMATION:
7970 status = smb_file_mode_information(conn,
7971 pdata,
7972 total_data);
7973 break;
7977 * CIFS UNIX extensions.
7980 case SMB_SET_FILE_UNIX_BASIC:
7982 status = smb_set_file_unix_basic(conn, req,
7983 pdata,
7984 total_data,
7985 fsp,
7986 smb_fname);
7987 break;
7990 case SMB_SET_FILE_UNIX_INFO2:
7992 status = smb_set_file_unix_info2(conn, req,
7993 pdata,
7994 total_data,
7995 fsp,
7996 smb_fname);
7997 break;
8000 case SMB_SET_FILE_UNIX_LINK:
8002 if (fsp) {
8003 /* We must have a pathname for this. */
8004 return NT_STATUS_INVALID_LEVEL;
8006 status = smb_set_file_unix_link(conn, req, pdata,
8007 total_data, smb_fname);
8008 break;
8011 case SMB_SET_FILE_UNIX_HLINK:
8013 if (fsp) {
8014 /* We must have a pathname for this. */
8015 return NT_STATUS_INVALID_LEVEL;
8017 status = smb_set_file_unix_hlink(conn, req,
8018 pdata, total_data,
8019 smb_fname);
8020 break;
8023 case SMB_FILE_RENAME_INFORMATION:
8025 status = smb_file_rename_information(conn, req,
8026 pdata, total_data,
8027 fsp, smb_fname);
8028 break;
8031 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8033 /* SMB2 rename information. */
8034 status = smb2_file_rename_information(conn, req,
8035 pdata, total_data,
8036 fsp, smb_fname);
8037 break;
8040 case SMB_FILE_LINK_INFORMATION:
8042 status = smb_file_link_information(conn, req,
8043 pdata, total_data,
8044 fsp, smb_fname);
8045 break;
8048 #if defined(HAVE_POSIX_ACLS)
8049 case SMB_SET_POSIX_ACL:
8051 status = smb_set_posix_acl(conn,
8052 pdata,
8053 total_data,
8054 fsp,
8055 smb_fname);
8056 break;
8058 #endif
8060 case SMB_SET_POSIX_LOCK:
8062 if (!fsp) {
8063 return NT_STATUS_INVALID_LEVEL;
8065 status = smb_set_posix_lock(conn, req,
8066 pdata, total_data, fsp);
8067 break;
8070 case SMB_POSIX_PATH_OPEN:
8072 if (fsp) {
8073 /* We must have a pathname for this. */
8074 return NT_STATUS_INVALID_LEVEL;
8077 status = smb_posix_open(conn, req,
8078 ppdata,
8079 total_data,
8080 smb_fname,
8081 &data_return_size);
8082 break;
8085 case SMB_POSIX_PATH_UNLINK:
8087 if (fsp) {
8088 /* We must have a pathname for this. */
8089 return NT_STATUS_INVALID_LEVEL;
8092 status = smb_posix_unlink(conn, req,
8093 pdata,
8094 total_data,
8095 smb_fname);
8096 break;
8099 default:
8100 return NT_STATUS_INVALID_LEVEL;
8103 if (!NT_STATUS_IS_OK(status)) {
8104 return status;
8107 *ret_data_size = data_return_size;
8108 return NT_STATUS_OK;
8111 /****************************************************************************
8112 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8113 ****************************************************************************/
8115 static void call_trans2setfilepathinfo(connection_struct *conn,
8116 struct smb_request *req,
8117 unsigned int tran_call,
8118 char **pparams, int total_params,
8119 char **ppdata, int total_data,
8120 unsigned int max_data_bytes)
8122 char *params = *pparams;
8123 char *pdata = *ppdata;
8124 uint16 info_level;
8125 struct smb_filename *smb_fname = NULL;
8126 files_struct *fsp = NULL;
8127 NTSTATUS status = NT_STATUS_OK;
8128 int data_return_size = 0;
8130 if (!params) {
8131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8132 return;
8135 if (tran_call == TRANSACT2_SETFILEINFO) {
8136 if (total_params < 4) {
8137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8138 return;
8141 fsp = file_fsp(req, SVAL(params,0));
8142 /* Basic check for non-null fsp. */
8143 if (!check_fsp_open(conn, req, fsp)) {
8144 return;
8146 info_level = SVAL(params,2);
8148 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8149 if (smb_fname == NULL) {
8150 reply_nterror(req, NT_STATUS_NO_MEMORY);
8151 return;
8154 if(fsp->fh->fd == -1) {
8156 * This is actually a SETFILEINFO on a directory
8157 * handle (returned from an NT SMB). NT5.0 seems
8158 * to do this call. JRA.
8160 if (INFO_LEVEL_IS_UNIX(info_level)) {
8161 /* Always do lstat for UNIX calls. */
8162 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8163 DEBUG(3,("call_trans2setfilepathinfo: "
8164 "SMB_VFS_LSTAT of %s failed "
8165 "(%s)\n",
8166 smb_fname_str_dbg(smb_fname),
8167 strerror(errno)));
8168 reply_nterror(req, map_nt_error_from_unix(errno));
8169 return;
8171 } else {
8172 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8173 DEBUG(3,("call_trans2setfilepathinfo: "
8174 "fileinfo of %s failed (%s)\n",
8175 smb_fname_str_dbg(smb_fname),
8176 strerror(errno)));
8177 reply_nterror(req, map_nt_error_from_unix(errno));
8178 return;
8181 } else if (fsp->print_file) {
8183 * Doing a DELETE_ON_CLOSE should cancel a print job.
8185 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8186 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8188 DEBUG(3,("call_trans2setfilepathinfo: "
8189 "Cancelling print job (%s)\n",
8190 fsp_str_dbg(fsp)));
8192 SSVAL(params,0,0);
8193 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8194 *ppdata, 0,
8195 max_data_bytes);
8196 return;
8197 } else {
8198 reply_nterror(req,
8199 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8200 return;
8202 } else {
8204 * Original code - this is an open file.
8206 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8207 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8208 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8209 strerror(errno)));
8210 reply_nterror(req, map_nt_error_from_unix(errno));
8211 return;
8214 } else {
8215 char *fname = NULL;
8216 uint32_t ucf_flags = 0;
8218 /* set path info */
8219 if (total_params < 7) {
8220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8221 return;
8224 info_level = SVAL(params,0);
8225 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8226 total_params - 6, STR_TERMINATE,
8227 &status);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 reply_nterror(req, status);
8230 return;
8233 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8234 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8235 info_level == SMB_FILE_RENAME_INFORMATION ||
8236 info_level == SMB_POSIX_PATH_UNLINK) {
8237 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8240 status = filename_convert(req, conn,
8241 req->flags2 & FLAGS2_DFS_PATHNAMES,
8242 fname,
8243 ucf_flags,
8244 NULL,
8245 &smb_fname);
8246 if (!NT_STATUS_IS_OK(status)) {
8247 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8248 reply_botherror(req,
8249 NT_STATUS_PATH_NOT_COVERED,
8250 ERRSRV, ERRbadpath);
8251 return;
8253 reply_nterror(req, status);
8254 return;
8257 if (INFO_LEVEL_IS_UNIX(info_level)) {
8259 * For CIFS UNIX extensions the target name may not exist.
8262 /* Always do lstat for UNIX calls. */
8263 SMB_VFS_LSTAT(conn, smb_fname);
8265 } else if (!VALID_STAT(smb_fname->st) &&
8266 SMB_VFS_STAT(conn, smb_fname)) {
8267 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8268 "%s failed (%s)\n",
8269 smb_fname_str_dbg(smb_fname),
8270 strerror(errno)));
8271 reply_nterror(req, map_nt_error_from_unix(errno));
8272 return;
8276 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8277 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8278 fsp_fnum_dbg(fsp),
8279 info_level,total_data));
8281 /* Realloc the parameter size */
8282 *pparams = (char *)SMB_REALLOC(*pparams,2);
8283 if (*pparams == NULL) {
8284 reply_nterror(req, NT_STATUS_NO_MEMORY);
8285 return;
8287 params = *pparams;
8289 SSVAL(params,0,0);
8291 status = smbd_do_setfilepathinfo(conn, req, req,
8292 info_level,
8293 fsp,
8294 smb_fname,
8295 ppdata, total_data,
8296 &data_return_size);
8297 if (!NT_STATUS_IS_OK(status)) {
8298 if (open_was_deferred(req->sconn, req->mid)) {
8299 /* We have re-scheduled this call. */
8300 return;
8302 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8303 /* We have re-scheduled this call. */
8304 return;
8306 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8307 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8308 ERRSRV, ERRbadpath);
8309 return;
8311 if (info_level == SMB_POSIX_PATH_OPEN) {
8312 reply_openerror(req, status);
8313 return;
8317 * Invalid EA name needs to return 2 param bytes,
8318 * not a zero-length error packet.
8320 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8321 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8322 max_data_bytes);
8323 } else {
8324 reply_nterror(req, status);
8326 return;
8329 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8330 max_data_bytes);
8332 return;
8335 /****************************************************************************
8336 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8337 ****************************************************************************/
8339 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8340 char **pparams, int total_params,
8341 char **ppdata, int total_data,
8342 unsigned int max_data_bytes)
8344 struct smb_filename *smb_dname = NULL;
8345 char *params = *pparams;
8346 char *pdata = *ppdata;
8347 char *directory = NULL;
8348 NTSTATUS status = NT_STATUS_OK;
8349 struct ea_list *ea_list = NULL;
8350 TALLOC_CTX *ctx = talloc_tos();
8352 if (!CAN_WRITE(conn)) {
8353 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8354 return;
8357 if (total_params < 5) {
8358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8359 return;
8362 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8363 total_params - 4, STR_TERMINATE,
8364 &status);
8365 if (!NT_STATUS_IS_OK(status)) {
8366 reply_nterror(req, status);
8367 return;
8370 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8372 status = filename_convert(ctx,
8373 conn,
8374 req->flags2 & FLAGS2_DFS_PATHNAMES,
8375 directory,
8377 NULL,
8378 &smb_dname);
8380 if (!NT_STATUS_IS_OK(status)) {
8381 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8382 reply_botherror(req,
8383 NT_STATUS_PATH_NOT_COVERED,
8384 ERRSRV, ERRbadpath);
8385 return;
8387 reply_nterror(req, status);
8388 return;
8392 * OS/2 workplace shell seems to send SET_EA requests of "null"
8393 * length (4 bytes containing IVAL 4).
8394 * They seem to have no effect. Bug #3212. JRA.
8397 if (total_data && (total_data != 4)) {
8398 /* Any data in this call is an EA list. */
8399 if (total_data < 10) {
8400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8401 goto out;
8404 if (IVAL(pdata,0) > total_data) {
8405 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8406 IVAL(pdata,0), (unsigned int)total_data));
8407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8408 goto out;
8411 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8412 total_data - 4);
8413 if (!ea_list) {
8414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8415 goto out;
8418 if (!lp_ea_support(SNUM(conn))) {
8419 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8420 goto out;
8423 /* If total_data == 4 Windows doesn't care what values
8424 * are placed in that field, it just ignores them.
8425 * The System i QNTC IBM SMB client puts bad values here,
8426 * so ignore them. */
8428 status = create_directory(conn, req, smb_dname);
8430 if (!NT_STATUS_IS_OK(status)) {
8431 reply_nterror(req, status);
8432 goto out;
8435 /* Try and set any given EA. */
8436 if (ea_list) {
8437 status = set_ea(conn, NULL, smb_dname, ea_list);
8438 if (!NT_STATUS_IS_OK(status)) {
8439 reply_nterror(req, status);
8440 goto out;
8444 /* Realloc the parameter and data sizes */
8445 *pparams = (char *)SMB_REALLOC(*pparams,2);
8446 if(*pparams == NULL) {
8447 reply_nterror(req, NT_STATUS_NO_MEMORY);
8448 goto out;
8450 params = *pparams;
8452 SSVAL(params,0,0);
8454 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8456 out:
8457 TALLOC_FREE(smb_dname);
8458 return;
8461 /****************************************************************************
8462 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8463 We don't actually do this - we just send a null response.
8464 ****************************************************************************/
8466 static void call_trans2findnotifyfirst(connection_struct *conn,
8467 struct smb_request *req,
8468 char **pparams, int total_params,
8469 char **ppdata, int total_data,
8470 unsigned int max_data_bytes)
8472 char *params = *pparams;
8473 uint16 info_level;
8475 if (total_params < 6) {
8476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8477 return;
8480 info_level = SVAL(params,4);
8481 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8483 switch (info_level) {
8484 case 1:
8485 case 2:
8486 break;
8487 default:
8488 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8489 return;
8492 /* Realloc the parameter and data sizes */
8493 *pparams = (char *)SMB_REALLOC(*pparams,6);
8494 if (*pparams == NULL) {
8495 reply_nterror(req, NT_STATUS_NO_MEMORY);
8496 return;
8498 params = *pparams;
8500 SSVAL(params,0,fnf_handle);
8501 SSVAL(params,2,0); /* No changes */
8502 SSVAL(params,4,0); /* No EA errors */
8504 fnf_handle++;
8506 if(fnf_handle == 0)
8507 fnf_handle = 257;
8509 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8511 return;
8514 /****************************************************************************
8515 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8516 changes). Currently this does nothing.
8517 ****************************************************************************/
8519 static void call_trans2findnotifynext(connection_struct *conn,
8520 struct smb_request *req,
8521 char **pparams, int total_params,
8522 char **ppdata, int total_data,
8523 unsigned int max_data_bytes)
8525 char *params = *pparams;
8527 DEBUG(3,("call_trans2findnotifynext\n"));
8529 /* Realloc the parameter and data sizes */
8530 *pparams = (char *)SMB_REALLOC(*pparams,4);
8531 if (*pparams == NULL) {
8532 reply_nterror(req, NT_STATUS_NO_MEMORY);
8533 return;
8535 params = *pparams;
8537 SSVAL(params,0,0); /* No changes */
8538 SSVAL(params,2,0); /* No EA errors */
8540 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8542 return;
8545 /****************************************************************************
8546 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8547 ****************************************************************************/
8549 static void call_trans2getdfsreferral(connection_struct *conn,
8550 struct smb_request *req,
8551 char **pparams, int total_params,
8552 char **ppdata, int total_data,
8553 unsigned int max_data_bytes)
8555 char *params = *pparams;
8556 char *pathname = NULL;
8557 int reply_size = 0;
8558 int max_referral_level;
8559 NTSTATUS status = NT_STATUS_OK;
8560 TALLOC_CTX *ctx = talloc_tos();
8562 DEBUG(10,("call_trans2getdfsreferral\n"));
8564 if (total_params < 3) {
8565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8566 return;
8569 max_referral_level = SVAL(params,0);
8571 if(!lp_host_msdfs()) {
8572 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8573 return;
8576 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8577 total_params - 2, STR_TERMINATE);
8578 if (!pathname) {
8579 reply_nterror(req, NT_STATUS_NOT_FOUND);
8580 return;
8582 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8583 ppdata,&status)) < 0) {
8584 reply_nterror(req, status);
8585 return;
8588 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8589 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8590 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8592 return;
8595 #define LMCAT_SPL 0x53
8596 #define LMFUNC_GETJOBID 0x60
8598 /****************************************************************************
8599 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8600 ****************************************************************************/
8602 static void call_trans2ioctl(connection_struct *conn,
8603 struct smb_request *req,
8604 char **pparams, int total_params,
8605 char **ppdata, int total_data,
8606 unsigned int max_data_bytes)
8608 char *pdata = *ppdata;
8609 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8611 /* check for an invalid fid before proceeding */
8613 if (!fsp) {
8614 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8615 return;
8618 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8619 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8620 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8621 if (*ppdata == NULL) {
8622 reply_nterror(req, NT_STATUS_NO_MEMORY);
8623 return;
8625 pdata = *ppdata;
8627 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8628 CAN ACCEPT THIS IN UNICODE. JRA. */
8630 /* Job number */
8631 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8633 srvstr_push(pdata, req->flags2, pdata + 2,
8634 lp_netbios_name(), 15,
8635 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8636 srvstr_push(pdata, req->flags2, pdata+18,
8637 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8638 STR_ASCII|STR_TERMINATE); /* Service name */
8639 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8640 max_data_bytes);
8641 return;
8644 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8645 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8648 /****************************************************************************
8649 Reply to a SMBfindclose (stop trans2 directory search).
8650 ****************************************************************************/
8652 void reply_findclose(struct smb_request *req)
8654 int dptr_num;
8655 struct smbd_server_connection *sconn = req->sconn;
8657 START_PROFILE(SMBfindclose);
8659 if (req->wct < 1) {
8660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8661 END_PROFILE(SMBfindclose);
8662 return;
8665 dptr_num = SVALS(req->vwv+0, 0);
8667 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8669 dptr_close(sconn, &dptr_num);
8671 reply_outbuf(req, 0, 0);
8673 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8675 END_PROFILE(SMBfindclose);
8676 return;
8679 /****************************************************************************
8680 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8681 ****************************************************************************/
8683 void reply_findnclose(struct smb_request *req)
8685 int dptr_num;
8687 START_PROFILE(SMBfindnclose);
8689 if (req->wct < 1) {
8690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8691 END_PROFILE(SMBfindnclose);
8692 return;
8695 dptr_num = SVAL(req->vwv+0, 0);
8697 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8699 /* We never give out valid handles for a
8700 findnotifyfirst - so any dptr_num is ok here.
8701 Just ignore it. */
8703 reply_outbuf(req, 0, 0);
8705 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8707 END_PROFILE(SMBfindnclose);
8708 return;
8711 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8712 struct trans_state *state)
8714 if (get_Protocol() >= PROTOCOL_NT1) {
8715 req->flags2 |= 0x40; /* IS_LONG_NAME */
8716 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8719 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8720 if (state->call != TRANSACT2_QFSINFO &&
8721 state->call != TRANSACT2_SETFSINFO) {
8722 DEBUG(0,("handle_trans2: encryption required "
8723 "with call 0x%x\n",
8724 (unsigned int)state->call));
8725 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8726 return;
8730 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8732 /* Now we must call the relevant TRANS2 function */
8733 switch(state->call) {
8734 case TRANSACT2_OPEN:
8736 START_PROFILE(Trans2_open);
8737 call_trans2open(conn, req,
8738 &state->param, state->total_param,
8739 &state->data, state->total_data,
8740 state->max_data_return);
8741 END_PROFILE(Trans2_open);
8742 break;
8745 case TRANSACT2_FINDFIRST:
8747 START_PROFILE(Trans2_findfirst);
8748 call_trans2findfirst(conn, req,
8749 &state->param, state->total_param,
8750 &state->data, state->total_data,
8751 state->max_data_return);
8752 END_PROFILE(Trans2_findfirst);
8753 break;
8756 case TRANSACT2_FINDNEXT:
8758 START_PROFILE(Trans2_findnext);
8759 call_trans2findnext(conn, req,
8760 &state->param, state->total_param,
8761 &state->data, state->total_data,
8762 state->max_data_return);
8763 END_PROFILE(Trans2_findnext);
8764 break;
8767 case TRANSACT2_QFSINFO:
8769 START_PROFILE(Trans2_qfsinfo);
8770 call_trans2qfsinfo(conn, req,
8771 &state->param, state->total_param,
8772 &state->data, state->total_data,
8773 state->max_data_return);
8774 END_PROFILE(Trans2_qfsinfo);
8775 break;
8778 case TRANSACT2_SETFSINFO:
8780 START_PROFILE(Trans2_setfsinfo);
8781 call_trans2setfsinfo(conn, req,
8782 &state->param, state->total_param,
8783 &state->data, state->total_data,
8784 state->max_data_return);
8785 END_PROFILE(Trans2_setfsinfo);
8786 break;
8789 case TRANSACT2_QPATHINFO:
8790 case TRANSACT2_QFILEINFO:
8792 START_PROFILE(Trans2_qpathinfo);
8793 call_trans2qfilepathinfo(conn, req, state->call,
8794 &state->param, state->total_param,
8795 &state->data, state->total_data,
8796 state->max_data_return);
8797 END_PROFILE(Trans2_qpathinfo);
8798 break;
8801 case TRANSACT2_SETPATHINFO:
8802 case TRANSACT2_SETFILEINFO:
8804 START_PROFILE(Trans2_setpathinfo);
8805 call_trans2setfilepathinfo(conn, req, state->call,
8806 &state->param, state->total_param,
8807 &state->data, state->total_data,
8808 state->max_data_return);
8809 END_PROFILE(Trans2_setpathinfo);
8810 break;
8813 case TRANSACT2_FINDNOTIFYFIRST:
8815 START_PROFILE(Trans2_findnotifyfirst);
8816 call_trans2findnotifyfirst(conn, req,
8817 &state->param, state->total_param,
8818 &state->data, state->total_data,
8819 state->max_data_return);
8820 END_PROFILE(Trans2_findnotifyfirst);
8821 break;
8824 case TRANSACT2_FINDNOTIFYNEXT:
8826 START_PROFILE(Trans2_findnotifynext);
8827 call_trans2findnotifynext(conn, req,
8828 &state->param, state->total_param,
8829 &state->data, state->total_data,
8830 state->max_data_return);
8831 END_PROFILE(Trans2_findnotifynext);
8832 break;
8835 case TRANSACT2_MKDIR:
8837 START_PROFILE(Trans2_mkdir);
8838 call_trans2mkdir(conn, req,
8839 &state->param, state->total_param,
8840 &state->data, state->total_data,
8841 state->max_data_return);
8842 END_PROFILE(Trans2_mkdir);
8843 break;
8846 case TRANSACT2_GET_DFS_REFERRAL:
8848 START_PROFILE(Trans2_get_dfs_referral);
8849 call_trans2getdfsreferral(conn, req,
8850 &state->param, state->total_param,
8851 &state->data, state->total_data,
8852 state->max_data_return);
8853 END_PROFILE(Trans2_get_dfs_referral);
8854 break;
8857 case TRANSACT2_IOCTL:
8859 START_PROFILE(Trans2_ioctl);
8860 call_trans2ioctl(conn, req,
8861 &state->param, state->total_param,
8862 &state->data, state->total_data,
8863 state->max_data_return);
8864 END_PROFILE(Trans2_ioctl);
8865 break;
8868 default:
8869 /* Error in request */
8870 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8871 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8875 /****************************************************************************
8876 Reply to a SMBtrans2.
8877 ****************************************************************************/
8879 void reply_trans2(struct smb_request *req)
8881 connection_struct *conn = req->conn;
8882 unsigned int dsoff;
8883 unsigned int dscnt;
8884 unsigned int psoff;
8885 unsigned int pscnt;
8886 unsigned int tran_call;
8887 struct trans_state *state;
8888 NTSTATUS result;
8890 START_PROFILE(SMBtrans2);
8892 if (req->wct < 14) {
8893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8894 END_PROFILE(SMBtrans2);
8895 return;
8898 dsoff = SVAL(req->vwv+12, 0);
8899 dscnt = SVAL(req->vwv+11, 0);
8900 psoff = SVAL(req->vwv+10, 0);
8901 pscnt = SVAL(req->vwv+9, 0);
8902 tran_call = SVAL(req->vwv+14, 0);
8904 result = allow_new_trans(conn->pending_trans, req->mid);
8905 if (!NT_STATUS_IS_OK(result)) {
8906 DEBUG(2, ("Got invalid trans2 request: %s\n",
8907 nt_errstr(result)));
8908 reply_nterror(req, result);
8909 END_PROFILE(SMBtrans2);
8910 return;
8913 if (IS_IPC(conn)) {
8914 switch (tran_call) {
8915 /* List the allowed trans2 calls on IPC$ */
8916 case TRANSACT2_OPEN:
8917 case TRANSACT2_GET_DFS_REFERRAL:
8918 case TRANSACT2_QFILEINFO:
8919 case TRANSACT2_QFSINFO:
8920 case TRANSACT2_SETFSINFO:
8921 break;
8922 default:
8923 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8924 END_PROFILE(SMBtrans2);
8925 return;
8929 if ((state = talloc(conn, struct trans_state)) == NULL) {
8930 DEBUG(0, ("talloc failed\n"));
8931 reply_nterror(req, NT_STATUS_NO_MEMORY);
8932 END_PROFILE(SMBtrans2);
8933 return;
8936 state->cmd = SMBtrans2;
8938 state->mid = req->mid;
8939 state->vuid = req->vuid;
8940 state->setup_count = SVAL(req->vwv+13, 0);
8941 state->setup = NULL;
8942 state->total_param = SVAL(req->vwv+0, 0);
8943 state->param = NULL;
8944 state->total_data = SVAL(req->vwv+1, 0);
8945 state->data = NULL;
8946 state->max_param_return = SVAL(req->vwv+2, 0);
8947 state->max_data_return = SVAL(req->vwv+3, 0);
8948 state->max_setup_return = SVAL(req->vwv+4, 0);
8949 state->close_on_completion = BITSETW(req->vwv+5, 0);
8950 state->one_way = BITSETW(req->vwv+5, 1);
8952 state->call = tran_call;
8954 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8955 is so as a sanity check */
8956 if (state->setup_count != 1) {
8958 * Need to have rc=0 for ioctl to get job id for OS/2.
8959 * Network printing will fail if function is not successful.
8960 * Similar function in reply.c will be used if protocol
8961 * is LANMAN1.0 instead of LM1.2X002.
8962 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8963 * outbuf doesn't have to be set(only job id is used).
8965 if ( (state->setup_count == 4)
8966 && (tran_call == TRANSACT2_IOCTL)
8967 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8968 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8969 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8970 } else {
8971 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8972 DEBUG(2,("Transaction is %d\n",tran_call));
8973 TALLOC_FREE(state);
8974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8975 END_PROFILE(SMBtrans2);
8976 return;
8980 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8981 goto bad_param;
8983 if (state->total_data) {
8985 if (trans_oob(state->total_data, 0, dscnt)
8986 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8987 goto bad_param;
8990 /* Can't use talloc here, the core routines do realloc on the
8991 * params and data. */
8992 state->data = (char *)SMB_MALLOC(state->total_data);
8993 if (state->data == NULL) {
8994 DEBUG(0,("reply_trans2: data malloc fail for %u "
8995 "bytes !\n", (unsigned int)state->total_data));
8996 TALLOC_FREE(state);
8997 reply_nterror(req, NT_STATUS_NO_MEMORY);
8998 END_PROFILE(SMBtrans2);
8999 return;
9002 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9005 if (state->total_param) {
9007 if (trans_oob(state->total_param, 0, pscnt)
9008 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9009 goto bad_param;
9012 /* Can't use talloc here, the core routines do realloc on the
9013 * params and data. */
9014 state->param = (char *)SMB_MALLOC(state->total_param);
9015 if (state->param == NULL) {
9016 DEBUG(0,("reply_trans: param malloc fail for %u "
9017 "bytes !\n", (unsigned int)state->total_param));
9018 SAFE_FREE(state->data);
9019 TALLOC_FREE(state);
9020 reply_nterror(req, NT_STATUS_NO_MEMORY);
9021 END_PROFILE(SMBtrans2);
9022 return;
9025 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9028 state->received_data = dscnt;
9029 state->received_param = pscnt;
9031 if ((state->received_param == state->total_param) &&
9032 (state->received_data == state->total_data)) {
9034 handle_trans2(conn, req, state);
9036 SAFE_FREE(state->data);
9037 SAFE_FREE(state->param);
9038 TALLOC_FREE(state);
9039 END_PROFILE(SMBtrans2);
9040 return;
9043 DLIST_ADD(conn->pending_trans, state);
9045 /* We need to send an interim response then receive the rest
9046 of the parameter/data bytes */
9047 reply_outbuf(req, 0, 0);
9048 show_msg((char *)req->outbuf);
9049 END_PROFILE(SMBtrans2);
9050 return;
9052 bad_param:
9054 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9055 SAFE_FREE(state->data);
9056 SAFE_FREE(state->param);
9057 TALLOC_FREE(state);
9058 END_PROFILE(SMBtrans2);
9059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9063 /****************************************************************************
9064 Reply to a SMBtranss2
9065 ****************************************************************************/
9067 void reply_transs2(struct smb_request *req)
9069 connection_struct *conn = req->conn;
9070 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9071 struct trans_state *state;
9073 START_PROFILE(SMBtranss2);
9075 show_msg((const char *)req->inbuf);
9077 /* Windows clients expect all replies to
9078 a transact secondary (SMBtranss2 0x33)
9079 to have a command code of transact
9080 (SMBtrans2 0x32). See bug #8989
9081 and also [MS-CIFS] section 2.2.4.47.2
9082 for details.
9084 req->cmd = SMBtrans2;
9086 if (req->wct < 8) {
9087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9088 END_PROFILE(SMBtranss2);
9089 return;
9092 for (state = conn->pending_trans; state != NULL;
9093 state = state->next) {
9094 if (state->mid == req->mid) {
9095 break;
9099 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9101 END_PROFILE(SMBtranss2);
9102 return;
9105 /* Revise state->total_param and state->total_data in case they have
9106 changed downwards */
9108 if (SVAL(req->vwv+0, 0) < state->total_param)
9109 state->total_param = SVAL(req->vwv+0, 0);
9110 if (SVAL(req->vwv+1, 0) < state->total_data)
9111 state->total_data = SVAL(req->vwv+1, 0);
9113 pcnt = SVAL(req->vwv+2, 0);
9114 poff = SVAL(req->vwv+3, 0);
9115 pdisp = SVAL(req->vwv+4, 0);
9117 dcnt = SVAL(req->vwv+5, 0);
9118 doff = SVAL(req->vwv+6, 0);
9119 ddisp = SVAL(req->vwv+7, 0);
9121 state->received_param += pcnt;
9122 state->received_data += dcnt;
9124 if ((state->received_data > state->total_data) ||
9125 (state->received_param > state->total_param))
9126 goto bad_param;
9128 if (pcnt) {
9129 if (trans_oob(state->total_param, pdisp, pcnt)
9130 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9131 goto bad_param;
9133 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9136 if (dcnt) {
9137 if (trans_oob(state->total_data, ddisp, dcnt)
9138 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9139 goto bad_param;
9141 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9144 if ((state->received_param < state->total_param) ||
9145 (state->received_data < state->total_data)) {
9146 END_PROFILE(SMBtranss2);
9147 return;
9150 handle_trans2(conn, req, state);
9152 DLIST_REMOVE(conn->pending_trans, state);
9153 SAFE_FREE(state->data);
9154 SAFE_FREE(state->param);
9155 TALLOC_FREE(state);
9157 END_PROFILE(SMBtranss2);
9158 return;
9160 bad_param:
9162 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9163 DLIST_REMOVE(conn->pending_trans, state);
9164 SAFE_FREE(state->data);
9165 SAFE_FREE(state->param);
9166 TALLOC_FREE(state);
9167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9168 END_PROFILE(SMBtranss2);
9169 return;