Fix bug #10097 - MacOSX 10.9 will not follow path-based DFS referrals handed out...
[Samba.git] / source3 / smbd / trans2.c
blob5031442d69a6b94e0fc2249cf69219b916d2f4c3
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 "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
43 #define DIR_ENTRY_SAFETY_MARGIN 4096
45 static char *store_file_unix_basic(connection_struct *conn,
46 char *pdata,
47 files_struct *fsp,
48 const SMB_STRUCT_STAT *psbuf);
50 static char *store_file_unix_basic_info2(connection_struct *conn,
51 char *pdata,
52 files_struct *fsp,
53 const SMB_STRUCT_STAT *psbuf);
55 /********************************************************************
56 The canonical "check access" based on object handle or path function.
57 ********************************************************************/
59 NTSTATUS check_access(connection_struct *conn,
60 files_struct *fsp,
61 const struct smb_filename *smb_fname,
62 uint32_t access_mask)
64 if (fsp) {
65 if (!(fsp->access_mask & access_mask)) {
66 return NT_STATUS_ACCESS_DENIED;
68 } else {
69 NTSTATUS status = smbd_check_access_rights(conn,
70 smb_fname,
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. */
1880 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1881 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1882 } else {
1883 unsigned int ea_size = estimate_ea_size(conn, NULL,
1884 smb_fname);
1885 SIVAL(p,0,ea_size); /* Extended attributes */
1887 p += 4;
1888 /* Clear the short name buffer. This is
1889 * IMPORTANT as not doing so will trigger
1890 * a Win2k client bug. JRA.
1892 if (!was_8_3 && check_mangled_names) {
1893 char mangled_name[13]; /* mangled 8.3 name. */
1894 if (!name_to_8_3(fname,mangled_name,True,
1895 conn->params)) {
1896 /* Error - mangle failed ! */
1897 memset(mangled_name,'\0',12);
1899 mangled_name[12] = 0;
1900 len = srvstr_push(base_data, flags2,
1901 p+2, mangled_name, 24,
1902 STR_UPPER|STR_UNICODE);
1903 if (len < 24) {
1904 memset(p + 2 + len,'\0',24 - len);
1906 SSVAL(p, 0, len);
1907 } else {
1908 memset(p,'\0',26);
1910 p += 2 + 24;
1911 len = srvstr_push(base_data, flags2, p,
1912 fname, PTR_DIFF(end_data, p),
1913 STR_TERMINATE_ASCII);
1914 SIVAL(q,0,len);
1915 p += len;
1917 len = PTR_DIFF(p, pdata);
1918 pad = (len + (align-1)) & ~(align-1);
1920 * offset to the next entry, the caller
1921 * will overwrite it for the last entry
1922 * that's why we always include the padding
1924 SIVAL(pdata,0,pad);
1926 * set padding to zero
1928 if (do_pad) {
1929 memset(p, 0, pad - len);
1930 p = pdata + pad;
1931 } else {
1932 p = pdata + len;
1934 break;
1936 case SMB_FIND_FILE_DIRECTORY_INFO:
1937 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1938 p += 4;
1939 SIVAL(p,0,reskey); p += 4;
1940 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1941 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1942 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1944 SOFF_T(p,0,file_size); p += 8;
1945 SOFF_T(p,0,allocation_size); p += 8;
1946 SIVAL(p,0,mode); p += 4;
1947 len = srvstr_push(base_data, flags2,
1948 p + 4, fname, PTR_DIFF(end_data, p+4),
1949 STR_TERMINATE_ASCII);
1950 SIVAL(p,0,len);
1951 p += 4 + len;
1953 len = PTR_DIFF(p, pdata);
1954 pad = (len + (align-1)) & ~(align-1);
1956 * offset to the next entry, the caller
1957 * will overwrite it for the last entry
1958 * that's why we always include the padding
1960 SIVAL(pdata,0,pad);
1962 * set padding to zero
1964 if (do_pad) {
1965 memset(p, 0, pad - len);
1966 p = pdata + pad;
1967 } else {
1968 p = pdata + len;
1970 break;
1972 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1973 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1974 p += 4;
1975 SIVAL(p,0,reskey); p += 4;
1976 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1977 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1978 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1980 SOFF_T(p,0,file_size); p += 8;
1981 SOFF_T(p,0,allocation_size); p += 8;
1982 SIVAL(p,0,mode); p += 4;
1983 q = p; p += 4; /* q is placeholder for name length. */
1985 unsigned int ea_size = estimate_ea_size(conn, NULL,
1986 smb_fname);
1987 SIVAL(p,0,ea_size); /* Extended attributes */
1988 p +=4;
1990 len = srvstr_push(base_data, flags2, p,
1991 fname, PTR_DIFF(end_data, p),
1992 STR_TERMINATE_ASCII);
1993 SIVAL(q, 0, len);
1994 p += len;
1996 len = PTR_DIFF(p, pdata);
1997 pad = (len + (align-1)) & ~(align-1);
1999 * offset to the next entry, the caller
2000 * will overwrite it for the last entry
2001 * that's why we always include the padding
2003 SIVAL(pdata,0,pad);
2005 * set padding to zero
2007 if (do_pad) {
2008 memset(p, 0, pad - len);
2009 p = pdata + pad;
2010 } else {
2011 p = pdata + len;
2013 break;
2015 case SMB_FIND_FILE_NAMES_INFO:
2016 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2017 p += 4;
2018 SIVAL(p,0,reskey); p += 4;
2019 p += 4;
2020 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2021 acl on a dir (tridge) */
2022 len = srvstr_push(base_data, flags2, p,
2023 fname, PTR_DIFF(end_data, p),
2024 STR_TERMINATE_ASCII);
2025 SIVAL(p, -4, len);
2026 p += len;
2028 len = PTR_DIFF(p, pdata);
2029 pad = (len + (align-1)) & ~(align-1);
2031 * offset to the next entry, the caller
2032 * will overwrite it for the last entry
2033 * that's why we always include the padding
2035 SIVAL(pdata,0,pad);
2037 * set padding to zero
2039 if (do_pad) {
2040 memset(p, 0, pad - len);
2041 p = pdata + pad;
2042 } else {
2043 p = pdata + len;
2045 break;
2047 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2048 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2049 p += 4;
2050 SIVAL(p,0,reskey); p += 4;
2051 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2053 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2054 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2055 SOFF_T(p,0,file_size); p += 8;
2056 SOFF_T(p,0,allocation_size); p += 8;
2057 SIVAL(p,0,mode); p += 4;
2058 q = p; p += 4; /* q is placeholder for name length. */
2059 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2060 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2061 } else {
2062 unsigned int ea_size = estimate_ea_size(conn, NULL,
2063 smb_fname);
2064 SIVAL(p,0,ea_size); /* Extended attributes */
2066 p += 4;
2067 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2068 SBVAL(p,0,file_index); p += 8;
2069 len = srvstr_push(base_data, flags2, p,
2070 fname, PTR_DIFF(end_data, p),
2071 STR_TERMINATE_ASCII);
2072 SIVAL(q, 0, len);
2073 p += len;
2075 len = PTR_DIFF(p, pdata);
2076 pad = (len + (align-1)) & ~(align-1);
2078 * offset to the next entry, the caller
2079 * will overwrite it for the last entry
2080 * that's why we always include the padding
2082 SIVAL(pdata,0,pad);
2084 * set padding to zero
2086 if (do_pad) {
2087 memset(p, 0, pad - len);
2088 p = pdata + pad;
2089 } else {
2090 p = pdata + len;
2092 break;
2094 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2095 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2096 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2097 p += 4;
2098 SIVAL(p,0,reskey); p += 4;
2099 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2100 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2101 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2102 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2103 SOFF_T(p,0,file_size); p += 8;
2104 SOFF_T(p,0,allocation_size); p += 8;
2105 SIVAL(p,0,mode); p += 4;
2106 q = p; p += 4; /* q is placeholder for name length */
2107 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2108 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2109 } else {
2110 unsigned int ea_size = estimate_ea_size(conn, NULL,
2111 smb_fname);
2112 SIVAL(p,0,ea_size); /* Extended attributes */
2114 p += 4;
2115 /* Clear the short name buffer. This is
2116 * IMPORTANT as not doing so will trigger
2117 * a Win2k client bug. JRA.
2119 if (!was_8_3 && check_mangled_names) {
2120 char mangled_name[13]; /* mangled 8.3 name. */
2121 if (!name_to_8_3(fname,mangled_name,True,
2122 conn->params)) {
2123 /* Error - mangle failed ! */
2124 memset(mangled_name,'\0',12);
2126 mangled_name[12] = 0;
2127 len = srvstr_push(base_data, flags2,
2128 p+2, mangled_name, 24,
2129 STR_UPPER|STR_UNICODE);
2130 SSVAL(p, 0, len);
2131 if (len < 24) {
2132 memset(p + 2 + len,'\0',24 - len);
2134 SSVAL(p, 0, len);
2135 } else {
2136 memset(p,'\0',26);
2138 p += 26;
2139 SSVAL(p,0,0); p += 2; /* Reserved ? */
2140 SBVAL(p,0,file_index); p += 8;
2141 len = srvstr_push(base_data, flags2, p,
2142 fname, PTR_DIFF(end_data, p),
2143 STR_TERMINATE_ASCII);
2144 SIVAL(q,0,len);
2145 p += len;
2147 len = PTR_DIFF(p, pdata);
2148 pad = (len + (align-1)) & ~(align-1);
2150 * offset to the next entry, the caller
2151 * will overwrite it for the last entry
2152 * that's why we always include the padding
2154 SIVAL(pdata,0,pad);
2156 * set padding to zero
2158 if (do_pad) {
2159 memset(p, 0, pad - len);
2160 p = pdata + pad;
2161 } else {
2162 p = pdata + len;
2164 break;
2166 /* CIFS UNIX Extension. */
2168 case SMB_FIND_FILE_UNIX:
2169 case SMB_FIND_FILE_UNIX_INFO2:
2170 p+= 4;
2171 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2173 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2175 if (info_level == SMB_FIND_FILE_UNIX) {
2176 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2177 p = store_file_unix_basic(conn, p,
2178 NULL, &smb_fname->st);
2179 len = srvstr_push(base_data, flags2, p,
2180 fname, PTR_DIFF(end_data, p),
2181 STR_TERMINATE);
2182 } else {
2183 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2184 p = store_file_unix_basic_info2(conn, p,
2185 NULL, &smb_fname->st);
2186 nameptr = p;
2187 p += 4;
2188 len = srvstr_push(base_data, flags2, p, fname,
2189 PTR_DIFF(end_data, p), 0);
2190 SIVAL(nameptr, 0, len);
2193 p += len;
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2202 SIVAL(pdata,0,pad);
2204 * set padding to zero
2206 if (do_pad) {
2207 memset(p, 0, pad - len);
2208 p = pdata + pad;
2209 } else {
2210 p = pdata + len;
2212 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2214 break;
2216 default:
2217 return false;
2220 if (PTR_DIFF(p,pdata) > space_remaining) {
2221 *out_of_space = true;
2222 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2223 "(wanted %u, had %d)\n",
2224 (unsigned int)PTR_DIFF(p,pdata),
2225 space_remaining ));
2226 return false; /* Not finished - just out of space */
2229 /* Setup the last entry pointer, as an offset from base_data */
2230 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2231 /* Advance the data pointer to the next slot */
2232 *ppdata = p;
2234 return true;
2237 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2238 connection_struct *conn,
2239 struct dptr_struct *dirptr,
2240 uint16 flags2,
2241 const char *path_mask,
2242 uint32 dirtype,
2243 int info_level,
2244 int requires_resume_key,
2245 bool dont_descend,
2246 bool ask_sharemode,
2247 uint8_t align,
2248 bool do_pad,
2249 char **ppdata,
2250 char *base_data,
2251 char *end_data,
2252 int space_remaining,
2253 bool *out_of_space,
2254 bool *got_exact_match,
2255 int *_last_entry_off,
2256 struct ea_list *name_list)
2258 const char *p;
2259 const char *mask = NULL;
2260 long prev_dirpos = 0;
2261 uint32_t mode = 0;
2262 char *fname = NULL;
2263 struct smb_filename *smb_fname = NULL;
2264 struct smbd_dirptr_lanman2_state state;
2265 bool ok;
2266 uint64_t last_entry_off = 0;
2268 ZERO_STRUCT(state);
2269 state.conn = conn;
2270 state.info_level = info_level;
2271 state.check_mangled_names = lp_manglednames(conn->params);
2272 state.has_wild = dptr_has_wild(dirptr);
2273 state.got_exact_match = false;
2275 *out_of_space = false;
2276 *got_exact_match = false;
2278 p = strrchr_m(path_mask,'/');
2279 if(p != NULL) {
2280 if(p[1] == '\0') {
2281 mask = "*.*";
2282 } else {
2283 mask = p+1;
2285 } else {
2286 mask = path_mask;
2289 ok = smbd_dirptr_get_entry(ctx,
2290 dirptr,
2291 mask,
2292 dirtype,
2293 dont_descend,
2294 ask_sharemode,
2295 smbd_dirptr_lanman2_match_fn,
2296 smbd_dirptr_lanman2_mode_fn,
2297 &state,
2298 &fname,
2299 &smb_fname,
2300 &mode,
2301 &prev_dirpos);
2302 if (!ok) {
2303 return false;
2306 *got_exact_match = state.got_exact_match;
2308 ok = smbd_marshall_dir_entry(ctx,
2309 conn,
2310 flags2,
2311 info_level,
2312 name_list,
2313 state.check_mangled_names,
2314 requires_resume_key,
2315 mode,
2316 fname,
2317 smb_fname,
2318 space_remaining,
2319 align,
2320 do_pad,
2321 base_data,
2322 ppdata,
2323 end_data,
2324 out_of_space,
2325 &last_entry_off);
2326 TALLOC_FREE(fname);
2327 TALLOC_FREE(smb_fname);
2328 if (*out_of_space) {
2329 dptr_SeekDir(dirptr, prev_dirpos);
2330 return false;
2332 if (!ok) {
2333 return false;
2336 *_last_entry_off = last_entry_off;
2337 return true;
2340 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2341 connection_struct *conn,
2342 struct dptr_struct *dirptr,
2343 uint16 flags2,
2344 const char *path_mask,
2345 uint32 dirtype,
2346 int info_level,
2347 bool requires_resume_key,
2348 bool dont_descend,
2349 bool ask_sharemode,
2350 char **ppdata,
2351 char *base_data,
2352 char *end_data,
2353 int space_remaining,
2354 bool *out_of_space,
2355 bool *got_exact_match,
2356 int *last_entry_off,
2357 struct ea_list *name_list)
2359 uint8_t align = 4;
2360 const bool do_pad = true;
2362 if (info_level >= 1 && info_level <= 3) {
2363 /* No alignment on earlier info levels. */
2364 align = 1;
2367 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2368 path_mask, dirtype, info_level,
2369 requires_resume_key, dont_descend, ask_sharemode,
2370 align, do_pad,
2371 ppdata, base_data, end_data,
2372 space_remaining,
2373 out_of_space, got_exact_match,
2374 last_entry_off, name_list);
2377 /****************************************************************************
2378 Reply to a TRANS2_FINDFIRST.
2379 ****************************************************************************/
2381 static void call_trans2findfirst(connection_struct *conn,
2382 struct smb_request *req,
2383 char **pparams, int total_params,
2384 char **ppdata, int total_data,
2385 unsigned int max_data_bytes)
2387 /* We must be careful here that we don't return more than the
2388 allowed number of data bytes. If this means returning fewer than
2389 maxentries then so be it. We assume that the redirector has
2390 enough room for the fixed number of parameter bytes it has
2391 requested. */
2392 struct smb_filename *smb_dname = NULL;
2393 char *params = *pparams;
2394 char *pdata = *ppdata;
2395 char *data_end;
2396 uint32 dirtype;
2397 int maxentries;
2398 uint16 findfirst_flags;
2399 bool close_after_first;
2400 bool close_if_end;
2401 bool requires_resume_key;
2402 int info_level;
2403 char *directory = NULL;
2404 char *mask = NULL;
2405 char *p;
2406 int last_entry_off=0;
2407 int dptr_num = -1;
2408 int numentries = 0;
2409 int i;
2410 bool finished = False;
2411 bool dont_descend = False;
2412 bool out_of_space = False;
2413 int space_remaining;
2414 bool mask_contains_wcard = False;
2415 struct ea_list *ea_list = NULL;
2416 NTSTATUS ntstatus = NT_STATUS_OK;
2417 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2418 TALLOC_CTX *ctx = talloc_tos();
2419 struct dptr_struct *dirptr = NULL;
2420 struct smbd_server_connection *sconn = req->sconn;
2421 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2422 bool backup_priv = false;
2424 if (total_params < 13) {
2425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2426 goto out;
2429 dirtype = SVAL(params,0);
2430 maxentries = SVAL(params,2);
2431 findfirst_flags = SVAL(params,4);
2432 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2433 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2434 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2435 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2436 security_token_has_privilege(get_current_nttok(conn),
2437 SEC_PRIV_BACKUP));
2439 info_level = SVAL(params,6);
2441 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2442 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2443 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2444 (int)backup_priv,
2445 info_level, max_data_bytes));
2447 if (!maxentries) {
2448 /* W2K3 seems to treat zero as 1. */
2449 maxentries = 1;
2452 switch (info_level) {
2453 case SMB_FIND_INFO_STANDARD:
2454 case SMB_FIND_EA_SIZE:
2455 case SMB_FIND_EA_LIST:
2456 case SMB_FIND_FILE_DIRECTORY_INFO:
2457 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2458 case SMB_FIND_FILE_NAMES_INFO:
2459 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2460 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2461 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2462 break;
2463 case SMB_FIND_FILE_UNIX:
2464 case SMB_FIND_FILE_UNIX_INFO2:
2465 /* Always use filesystem for UNIX mtime query. */
2466 ask_sharemode = false;
2467 if (!lp_unix_extensions()) {
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2469 goto out;
2471 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2472 break;
2473 default:
2474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2475 goto out;
2478 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2479 params+12, total_params - 12,
2480 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2481 if (!NT_STATUS_IS_OK(ntstatus)) {
2482 reply_nterror(req, ntstatus);
2483 goto out;
2486 if (backup_priv) {
2487 become_root();
2488 ntstatus = filename_convert_with_privilege(ctx,
2489 conn,
2490 req,
2491 directory,
2492 ucf_flags,
2493 &mask_contains_wcard,
2494 &smb_dname);
2495 } else {
2496 ntstatus = filename_convert(ctx, conn,
2497 req->flags2 & FLAGS2_DFS_PATHNAMES,
2498 directory,
2499 ucf_flags,
2500 &mask_contains_wcard,
2501 &smb_dname);
2504 if (!NT_STATUS_IS_OK(ntstatus)) {
2505 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2506 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2507 ERRSRV, ERRbadpath);
2508 goto out;
2510 reply_nterror(req, ntstatus);
2511 goto out;
2514 mask = smb_dname->original_lcomp;
2516 directory = smb_dname->base_name;
2518 p = strrchr_m(directory,'/');
2519 if(p == NULL) {
2520 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2521 if((directory[0] == '.') && (directory[1] == '\0')) {
2522 mask = talloc_strdup(ctx,"*");
2523 if (!mask) {
2524 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 goto out;
2527 mask_contains_wcard = True;
2529 } else {
2530 *p = 0;
2533 if (p == NULL || p == directory) {
2534 /* Ensure we don't have a directory name of "". */
2535 directory = talloc_strdup(talloc_tos(), ".");
2536 if (!directory) {
2537 reply_nterror(req, NT_STATUS_NO_MEMORY);
2538 goto out;
2542 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2544 if (info_level == SMB_FIND_EA_LIST) {
2545 uint32 ea_size;
2547 if (total_data < 4) {
2548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2549 goto out;
2552 ea_size = IVAL(pdata,0);
2553 if (ea_size != total_data) {
2554 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2555 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2557 goto out;
2560 if (!lp_ea_support(SNUM(conn))) {
2561 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2562 goto out;
2565 /* Pull out the list of names. */
2566 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2567 if (!ea_list) {
2568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2569 goto out;
2573 *ppdata = (char *)SMB_REALLOC(
2574 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2575 if(*ppdata == NULL ) {
2576 reply_nterror(req, NT_STATUS_NO_MEMORY);
2577 goto out;
2579 pdata = *ppdata;
2580 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2582 /* Realloc the params space */
2583 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2584 if (*pparams == NULL) {
2585 reply_nterror(req, NT_STATUS_NO_MEMORY);
2586 goto out;
2588 params = *pparams;
2590 /* Save the wildcard match and attribs we are using on this directory -
2591 needed as lanman2 assumes these are being saved between calls */
2593 ntstatus = dptr_create(conn,
2594 req,
2595 NULL, /* fsp */
2596 directory,
2597 False,
2598 True,
2599 req->smbpid,
2600 mask,
2601 mask_contains_wcard,
2602 dirtype,
2603 &dirptr);
2605 if (!NT_STATUS_IS_OK(ntstatus)) {
2606 reply_nterror(req, ntstatus);
2607 goto out;
2610 if (backup_priv) {
2611 /* Remember this in case we have
2612 to do a findnext. */
2613 dptr_set_priv(dirptr);
2616 dptr_num = dptr_dnum(dirptr);
2617 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2619 /* Initialize per TRANS2_FIND_FIRST operation data */
2620 dptr_init_search_op(dirptr);
2622 /* We don't need to check for VOL here as this is returned by
2623 a different TRANS2 call. */
2625 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2626 directory,lp_dontdescend(ctx, SNUM(conn))));
2627 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2628 dont_descend = True;
2630 p = pdata;
2631 space_remaining = max_data_bytes;
2632 out_of_space = False;
2634 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2635 bool got_exact_match = False;
2637 /* this is a heuristic to avoid seeking the dirptr except when
2638 absolutely necessary. It allows for a filename of about 40 chars */
2639 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2640 out_of_space = True;
2641 finished = False;
2642 } else {
2643 finished = !get_lanman2_dir_entry(ctx,
2644 conn,
2645 dirptr,
2646 req->flags2,
2647 mask,dirtype,info_level,
2648 requires_resume_key,dont_descend,
2649 ask_sharemode,
2650 &p,pdata,data_end,
2651 space_remaining, &out_of_space,
2652 &got_exact_match,
2653 &last_entry_off, ea_list);
2656 if (finished && out_of_space)
2657 finished = False;
2659 if (!finished && !out_of_space)
2660 numentries++;
2663 * As an optimisation if we know we aren't looking
2664 * for a wildcard name (ie. the name matches the wildcard exactly)
2665 * then we can finish on any (first) match.
2666 * This speeds up large directory searches. JRA.
2669 if(got_exact_match)
2670 finished = True;
2672 /* Ensure space_remaining never goes -ve. */
2673 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2674 space_remaining = 0;
2675 out_of_space = true;
2676 } else {
2677 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2681 /* Check if we can close the dirptr */
2682 if(close_after_first || (finished && close_if_end)) {
2683 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2684 dptr_close(sconn, &dptr_num);
2688 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2689 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2690 * the protocol level is less than NT1. Tested with smbclient. JRA.
2691 * This should fix the OS/2 client bug #2335.
2694 if(numentries == 0) {
2695 dptr_close(sconn, &dptr_num);
2696 if (get_Protocol() < PROTOCOL_NT1) {
2697 reply_force_doserror(req, ERRDOS, ERRnofiles);
2698 goto out;
2699 } else {
2700 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2701 ERRDOS, ERRbadfile);
2702 goto out;
2706 /* At this point pdata points to numentries directory entries. */
2708 /* Set up the return parameter block */
2709 SSVAL(params,0,dptr_num);
2710 SSVAL(params,2,numentries);
2711 SSVAL(params,4,finished);
2712 SSVAL(params,6,0); /* Never an EA error */
2713 SSVAL(params,8,last_entry_off);
2715 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2716 max_data_bytes);
2718 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2719 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2720 if (!directory) {
2721 reply_nterror(req, NT_STATUS_NO_MEMORY);
2725 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2726 smb_fn_name(req->cmd),
2727 mask, directory, dirtype, numentries ) );
2730 * Force a name mangle here to ensure that the
2731 * mask as an 8.3 name is top of the mangled cache.
2732 * The reasons for this are subtle. Don't remove
2733 * this code unless you know what you are doing
2734 * (see PR#13758). JRA.
2737 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2738 char mangled_name[13];
2739 name_to_8_3(mask, mangled_name, True, conn->params);
2741 out:
2743 if (backup_priv) {
2744 unbecome_root();
2747 TALLOC_FREE(smb_dname);
2748 return;
2751 /****************************************************************************
2752 Reply to a TRANS2_FINDNEXT.
2753 ****************************************************************************/
2755 static void call_trans2findnext(connection_struct *conn,
2756 struct smb_request *req,
2757 char **pparams, int total_params,
2758 char **ppdata, int total_data,
2759 unsigned int max_data_bytes)
2761 /* We must be careful here that we don't return more than the
2762 allowed number of data bytes. If this means returning fewer than
2763 maxentries then so be it. We assume that the redirector has
2764 enough room for the fixed number of parameter bytes it has
2765 requested. */
2766 char *params = *pparams;
2767 char *pdata = *ppdata;
2768 char *data_end;
2769 int dptr_num;
2770 int maxentries;
2771 uint16 info_level;
2772 uint32 resume_key;
2773 uint16 findnext_flags;
2774 bool close_after_request;
2775 bool close_if_end;
2776 bool requires_resume_key;
2777 bool continue_bit;
2778 bool mask_contains_wcard = False;
2779 char *resume_name = NULL;
2780 const char *mask = NULL;
2781 const char *directory = NULL;
2782 char *p = NULL;
2783 uint16 dirtype;
2784 int numentries = 0;
2785 int i, last_entry_off=0;
2786 bool finished = False;
2787 bool dont_descend = False;
2788 bool out_of_space = False;
2789 int space_remaining;
2790 struct ea_list *ea_list = NULL;
2791 NTSTATUS ntstatus = NT_STATUS_OK;
2792 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2793 TALLOC_CTX *ctx = talloc_tos();
2794 struct dptr_struct *dirptr;
2795 struct smbd_server_connection *sconn = req->sconn;
2796 bool backup_priv = false;
2798 if (total_params < 13) {
2799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2800 return;
2803 dptr_num = SVAL(params,0);
2804 maxentries = SVAL(params,2);
2805 info_level = SVAL(params,4);
2806 resume_key = IVAL(params,6);
2807 findnext_flags = SVAL(params,10);
2808 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2809 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2810 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2811 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2813 if (!continue_bit) {
2814 /* We only need resume_name if continue_bit is zero. */
2815 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2816 params+12,
2817 total_params - 12, STR_TERMINATE, &ntstatus,
2818 &mask_contains_wcard);
2819 if (!NT_STATUS_IS_OK(ntstatus)) {
2820 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2821 complain (it thinks we're asking for the directory above the shared
2822 path or an invalid name). Catch this as the resume name is only compared, never used in
2823 a file access. JRA. */
2824 srvstr_pull_talloc(ctx, params, req->flags2,
2825 &resume_name, params+12,
2826 total_params - 12,
2827 STR_TERMINATE);
2829 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2830 reply_nterror(req, ntstatus);
2831 return;
2836 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2837 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2838 resume_key = %d resume name = %s continue=%d level = %d\n",
2839 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2840 requires_resume_key, resume_key,
2841 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2843 if (!maxentries) {
2844 /* W2K3 seems to treat zero as 1. */
2845 maxentries = 1;
2848 switch (info_level) {
2849 case SMB_FIND_INFO_STANDARD:
2850 case SMB_FIND_EA_SIZE:
2851 case SMB_FIND_EA_LIST:
2852 case SMB_FIND_FILE_DIRECTORY_INFO:
2853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2854 case SMB_FIND_FILE_NAMES_INFO:
2855 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2856 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2857 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2858 break;
2859 case SMB_FIND_FILE_UNIX:
2860 case SMB_FIND_FILE_UNIX_INFO2:
2861 /* Always use filesystem for UNIX mtime query. */
2862 ask_sharemode = false;
2863 if (!lp_unix_extensions()) {
2864 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2865 return;
2867 break;
2868 default:
2869 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2870 return;
2873 if (info_level == SMB_FIND_EA_LIST) {
2874 uint32 ea_size;
2876 if (total_data < 4) {
2877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2878 return;
2881 ea_size = IVAL(pdata,0);
2882 if (ea_size != total_data) {
2883 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2884 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2886 return;
2889 if (!lp_ea_support(SNUM(conn))) {
2890 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2891 return;
2894 /* Pull out the list of names. */
2895 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2896 if (!ea_list) {
2897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2898 return;
2902 *ppdata = (char *)SMB_REALLOC(
2903 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2904 if(*ppdata == NULL) {
2905 reply_nterror(req, NT_STATUS_NO_MEMORY);
2906 return;
2909 pdata = *ppdata;
2910 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2912 /* Realloc the params space */
2913 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2914 if(*pparams == NULL ) {
2915 reply_nterror(req, NT_STATUS_NO_MEMORY);
2916 return;
2919 params = *pparams;
2921 /* Check that the dptr is valid */
2922 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2923 reply_nterror(req, STATUS_NO_MORE_FILES);
2924 return;
2927 directory = dptr_path(sconn, dptr_num);
2929 /* Get the wildcard mask from the dptr */
2930 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2931 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2932 reply_nterror(req, STATUS_NO_MORE_FILES);
2933 return;
2936 /* Get the attr mask from the dptr */
2937 dirtype = dptr_attr(sconn, dptr_num);
2939 backup_priv = dptr_get_priv(dirptr);
2941 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2942 "backup_priv = %d\n",
2943 dptr_num, mask, dirtype,
2944 (long)dirptr,
2945 dptr_TellDir(dirptr),
2946 (int)backup_priv));
2948 /* Initialize per TRANS2_FIND_NEXT operation data */
2949 dptr_init_search_op(dirptr);
2951 /* We don't need to check for VOL here as this is returned by
2952 a different TRANS2 call. */
2954 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2955 directory,lp_dontdescend(ctx, SNUM(conn))));
2956 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2957 dont_descend = True;
2959 p = pdata;
2960 space_remaining = max_data_bytes;
2961 out_of_space = False;
2963 if (backup_priv) {
2964 become_root();
2968 * Seek to the correct position. We no longer use the resume key but
2969 * depend on the last file name instead.
2972 if(!continue_bit && resume_name && *resume_name) {
2973 SMB_STRUCT_STAT st;
2975 long current_pos = 0;
2977 * Remember, name_to_8_3 is called by
2978 * get_lanman2_dir_entry(), so the resume name
2979 * could be mangled. Ensure we check the unmangled name.
2982 if (mangle_is_mangled(resume_name, conn->params)) {
2983 char *new_resume_name = NULL;
2984 mangle_lookup_name_from_8_3(ctx,
2985 resume_name,
2986 &new_resume_name,
2987 conn->params);
2988 if (new_resume_name) {
2989 resume_name = new_resume_name;
2994 * Fix for NT redirector problem triggered by resume key indexes
2995 * changing between directory scans. We now return a resume key of 0
2996 * and instead look for the filename to continue from (also given
2997 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2998 * findfirst/findnext (as is usual) then the directory pointer
2999 * should already be at the correct place.
3002 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3003 } /* end if resume_name && !continue_bit */
3005 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3006 bool got_exact_match = False;
3008 /* this is a heuristic to avoid seeking the dirptr except when
3009 absolutely necessary. It allows for a filename of about 40 chars */
3010 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3011 out_of_space = True;
3012 finished = False;
3013 } else {
3014 finished = !get_lanman2_dir_entry(ctx,
3015 conn,
3016 dirptr,
3017 req->flags2,
3018 mask,dirtype,info_level,
3019 requires_resume_key,dont_descend,
3020 ask_sharemode,
3021 &p,pdata,data_end,
3022 space_remaining, &out_of_space,
3023 &got_exact_match,
3024 &last_entry_off, ea_list);
3027 if (finished && out_of_space)
3028 finished = False;
3030 if (!finished && !out_of_space)
3031 numentries++;
3034 * As an optimisation if we know we aren't looking
3035 * for a wildcard name (ie. the name matches the wildcard exactly)
3036 * then we can finish on any (first) match.
3037 * This speeds up large directory searches. JRA.
3040 if(got_exact_match)
3041 finished = True;
3043 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3046 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3047 smb_fn_name(req->cmd),
3048 mask, directory, dirtype, numentries ) );
3050 /* Check if we can close the dirptr */
3051 if(close_after_request || (finished && close_if_end)) {
3052 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3053 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3056 if (backup_priv) {
3057 unbecome_root();
3060 /* Set up the return parameter block */
3061 SSVAL(params,0,numentries);
3062 SSVAL(params,2,finished);
3063 SSVAL(params,4,0); /* Never an EA error */
3064 SSVAL(params,6,last_entry_off);
3066 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3067 max_data_bytes);
3069 return;
3072 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3074 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3075 return objid;
3078 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3080 SMB_ASSERT(extended_info != NULL);
3082 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3083 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3084 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3085 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3086 #ifdef SAMBA_VERSION_REVISION
3087 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3088 #endif
3089 extended_info->samba_subversion = 0;
3090 #ifdef SAMBA_VERSION_RC_RELEASE
3091 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3092 #else
3093 #ifdef SAMBA_VERSION_PRE_RELEASE
3094 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3095 #endif
3096 #endif
3097 #ifdef SAMBA_VERSION_VENDOR_PATCH
3098 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3099 #endif
3100 extended_info->samba_gitcommitdate = 0;
3101 #ifdef SAMBA_VERSION_COMMIT_TIME
3102 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3103 #endif
3105 memset(extended_info->samba_version_string, 0,
3106 sizeof(extended_info->samba_version_string));
3108 snprintf (extended_info->samba_version_string,
3109 sizeof(extended_info->samba_version_string),
3110 "%s", samba_version_string());
3113 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3114 TALLOC_CTX *mem_ctx,
3115 uint16_t info_level,
3116 uint16_t flags2,
3117 unsigned int max_data_bytes,
3118 struct smb_filename *fname,
3119 char **ppdata,
3120 int *ret_data_len)
3122 char *pdata, *end_data;
3123 int data_len = 0, len;
3124 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3125 int snum = SNUM(conn);
3126 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3127 char *filename = NULL;
3128 uint32 additional_flags = 0;
3129 struct smb_filename smb_fname;
3130 SMB_STRUCT_STAT st;
3132 if (fname == NULL || fname->base_name == NULL) {
3133 filename = ".";
3134 } else {
3135 filename = fname->base_name;
3138 if (IS_IPC(conn)) {
3139 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3140 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3141 "info level (0x%x) on IPC$.\n",
3142 (unsigned int)info_level));
3143 return NT_STATUS_ACCESS_DENIED;
3147 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3149 ZERO_STRUCT(smb_fname);
3150 smb_fname.base_name = discard_const_p(char, filename);
3152 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3153 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3154 return map_nt_error_from_unix(errno);
3157 st = smb_fname.st;
3159 *ppdata = (char *)SMB_REALLOC(
3160 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3161 if (*ppdata == NULL) {
3162 return NT_STATUS_NO_MEMORY;
3165 pdata = *ppdata;
3166 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3167 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3169 switch (info_level) {
3170 case SMB_INFO_ALLOCATION:
3172 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3173 data_len = 18;
3174 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3175 return map_nt_error_from_unix(errno);
3178 block_size = lp_block_size(snum);
3179 if (bsize < block_size) {
3180 uint64_t factor = block_size/bsize;
3181 bsize = block_size;
3182 dsize /= factor;
3183 dfree /= factor;
3185 if (bsize > block_size) {
3186 uint64_t factor = bsize/block_size;
3187 bsize = block_size;
3188 dsize *= factor;
3189 dfree *= factor;
3191 bytes_per_sector = 512;
3192 sectors_per_unit = bsize/bytes_per_sector;
3194 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3195 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3196 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3198 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3199 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3200 SIVAL(pdata,l1_cUnit,dsize);
3201 SIVAL(pdata,l1_cUnitAvail,dfree);
3202 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3203 break;
3206 case SMB_INFO_VOLUME:
3207 /* Return volume name */
3209 * Add volume serial number - hash of a combination of
3210 * the called hostname and the service name.
3212 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3214 * Win2k3 and previous mess this up by sending a name length
3215 * one byte short. I believe only older clients (OS/2 Win9x) use
3216 * this call so try fixing this by adding a terminating null to
3217 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3219 len = srvstr_push(
3220 pdata, flags2,
3221 pdata+l2_vol_szVolLabel, vname,
3222 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3223 STR_NOALIGN|STR_TERMINATE);
3224 SCVAL(pdata,l2_vol_cch,len);
3225 data_len = l2_vol_szVolLabel + len;
3226 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3227 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3228 len, vname));
3229 break;
3231 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3232 case SMB_FS_ATTRIBUTE_INFORMATION:
3234 additional_flags = 0;
3235 #if defined(HAVE_SYS_QUOTAS)
3236 additional_flags |= FILE_VOLUME_QUOTAS;
3237 #endif
3239 if(lp_nt_acl_support(SNUM(conn))) {
3240 additional_flags |= FILE_PERSISTENT_ACLS;
3243 /* Capabilities are filled in at connection time through STATVFS call */
3244 additional_flags |= conn->fs_capabilities;
3245 additional_flags |= lp_parm_int(conn->params->service,
3246 "share", "fake_fscaps",
3249 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3250 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3251 additional_flags); /* FS ATTRIBUTES */
3253 SIVAL(pdata,4,255); /* Max filename component length */
3254 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3255 and will think we can't do long filenames */
3256 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3257 PTR_DIFF(end_data, pdata+12),
3258 STR_UNICODE);
3259 SIVAL(pdata,8,len);
3260 data_len = 12 + len;
3261 break;
3263 case SMB_QUERY_FS_LABEL_INFO:
3264 case SMB_FS_LABEL_INFORMATION:
3265 len = srvstr_push(pdata, flags2, pdata+4, vname,
3266 PTR_DIFF(end_data, pdata+4), 0);
3267 data_len = 4 + len;
3268 SIVAL(pdata,0,len);
3269 break;
3271 case SMB_QUERY_FS_VOLUME_INFO:
3272 case SMB_FS_VOLUME_INFORMATION:
3275 * Add volume serial number - hash of a combination of
3276 * the called hostname and the service name.
3278 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3279 (str_checksum(get_local_machine_name())<<16));
3281 /* Max label len is 32 characters. */
3282 len = srvstr_push(pdata, flags2, pdata+18, vname,
3283 PTR_DIFF(end_data, pdata+18),
3284 STR_UNICODE);
3285 SIVAL(pdata,12,len);
3286 data_len = 18+len;
3288 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3289 (int)strlen(vname),vname,
3290 lp_servicename(talloc_tos(), snum)));
3291 break;
3293 case SMB_QUERY_FS_SIZE_INFO:
3294 case SMB_FS_SIZE_INFORMATION:
3296 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3297 data_len = 24;
3298 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3299 return map_nt_error_from_unix(errno);
3301 block_size = lp_block_size(snum);
3302 if (bsize < block_size) {
3303 uint64_t factor = block_size/bsize;
3304 bsize = block_size;
3305 dsize /= factor;
3306 dfree /= factor;
3308 if (bsize > block_size) {
3309 uint64_t factor = bsize/block_size;
3310 bsize = block_size;
3311 dsize *= factor;
3312 dfree *= factor;
3314 bytes_per_sector = 512;
3315 sectors_per_unit = bsize/bytes_per_sector;
3316 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3317 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3318 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3319 SBIG_UINT(pdata,0,dsize);
3320 SBIG_UINT(pdata,8,dfree);
3321 SIVAL(pdata,16,sectors_per_unit);
3322 SIVAL(pdata,20,bytes_per_sector);
3323 break;
3326 case SMB_FS_FULL_SIZE_INFORMATION:
3328 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3329 data_len = 32;
3330 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3331 return map_nt_error_from_unix(errno);
3333 block_size = lp_block_size(snum);
3334 if (bsize < block_size) {
3335 uint64_t factor = block_size/bsize;
3336 bsize = block_size;
3337 dsize /= factor;
3338 dfree /= factor;
3340 if (bsize > block_size) {
3341 uint64_t factor = bsize/block_size;
3342 bsize = block_size;
3343 dsize *= factor;
3344 dfree *= factor;
3346 bytes_per_sector = 512;
3347 sectors_per_unit = bsize/bytes_per_sector;
3348 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3349 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3350 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3351 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3352 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3353 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3354 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3355 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3356 break;
3359 case SMB_QUERY_FS_DEVICE_INFO:
3360 case SMB_FS_DEVICE_INFORMATION:
3362 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3364 if (!CAN_WRITE(conn)) {
3365 characteristics |= FILE_READ_ONLY_DEVICE;
3367 data_len = 8;
3368 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3369 SIVAL(pdata,4,characteristics);
3370 break;
3373 #ifdef HAVE_SYS_QUOTAS
3374 case SMB_FS_QUOTA_INFORMATION:
3376 * what we have to send --metze:
3378 * Unknown1: 24 NULL bytes
3379 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3380 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3381 * Quota Flags: 2 byte :
3382 * Unknown3: 6 NULL bytes
3384 * 48 bytes total
3386 * details for Quota Flags:
3388 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3389 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3390 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3391 * 0x0001 Enable Quotas: enable quota for this fs
3395 /* we need to fake up a fsp here,
3396 * because its not send in this call
3398 files_struct fsp;
3399 SMB_NTQUOTA_STRUCT quotas;
3401 ZERO_STRUCT(fsp);
3402 ZERO_STRUCT(quotas);
3404 fsp.conn = conn;
3405 fsp.fnum = FNUM_FIELD_INVALID;
3407 /* access check */
3408 if (get_current_uid(conn) != 0) {
3409 DEBUG(0,("set_user_quota: access_denied "
3410 "service [%s] user [%s]\n",
3411 lp_servicename(talloc_tos(), SNUM(conn)),
3412 conn->session_info->unix_info->unix_name));
3413 return NT_STATUS_ACCESS_DENIED;
3416 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3417 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3418 return map_nt_error_from_unix(errno);
3421 data_len = 48;
3423 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3424 lp_servicename(talloc_tos(), SNUM(conn))));
3426 /* Unknown1 24 NULL bytes*/
3427 SBIG_UINT(pdata,0,(uint64_t)0);
3428 SBIG_UINT(pdata,8,(uint64_t)0);
3429 SBIG_UINT(pdata,16,(uint64_t)0);
3431 /* Default Soft Quota 8 bytes */
3432 SBIG_UINT(pdata,24,quotas.softlim);
3434 /* Default Hard Quota 8 bytes */
3435 SBIG_UINT(pdata,32,quotas.hardlim);
3437 /* Quota flag 2 bytes */
3438 SSVAL(pdata,40,quotas.qflags);
3440 /* Unknown3 6 NULL bytes */
3441 SSVAL(pdata,42,0);
3442 SIVAL(pdata,44,0);
3444 break;
3446 #endif /* HAVE_SYS_QUOTAS */
3447 case SMB_FS_OBJECTID_INFORMATION:
3449 unsigned char objid[16];
3450 struct smb_extended_info extended_info;
3451 memcpy(pdata,create_volume_objectid(conn, objid),16);
3452 samba_extended_info_version (&extended_info);
3453 SIVAL(pdata,16,extended_info.samba_magic);
3454 SIVAL(pdata,20,extended_info.samba_version);
3455 SIVAL(pdata,24,extended_info.samba_subversion);
3456 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3457 memcpy(pdata+36,extended_info.samba_version_string,28);
3458 data_len = 64;
3459 break;
3463 * Query the version and capabilities of the CIFS UNIX extensions
3464 * in use.
3467 case SMB_QUERY_CIFS_UNIX_INFO:
3469 bool large_write = lp_min_receive_file_size() &&
3470 !srv_is_signing_active(conn->sconn);
3471 bool large_read = !srv_is_signing_active(conn->sconn);
3472 int encrypt_caps = 0;
3474 if (!lp_unix_extensions()) {
3475 return NT_STATUS_INVALID_LEVEL;
3478 switch (conn->encrypt_level) {
3479 case SMB_SIGNING_OFF:
3480 encrypt_caps = 0;
3481 break;
3482 case SMB_SIGNING_IF_REQUIRED:
3483 case SMB_SIGNING_DEFAULT:
3484 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3485 break;
3486 case SMB_SIGNING_REQUIRED:
3487 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3488 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3489 large_write = false;
3490 large_read = false;
3491 break;
3494 data_len = 12;
3495 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3496 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3498 /* We have POSIX ACLs, pathname, encryption,
3499 * large read/write, and locking capability. */
3501 SBIG_UINT(pdata,4,((uint64_t)(
3502 CIFS_UNIX_POSIX_ACLS_CAP|
3503 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3504 CIFS_UNIX_FCNTL_LOCKS_CAP|
3505 CIFS_UNIX_EXTATTR_CAP|
3506 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3507 encrypt_caps|
3508 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3509 (large_write ?
3510 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3511 break;
3514 case SMB_QUERY_POSIX_FS_INFO:
3516 int rc;
3517 vfs_statvfs_struct svfs;
3519 if (!lp_unix_extensions()) {
3520 return NT_STATUS_INVALID_LEVEL;
3523 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3525 if (!rc) {
3526 data_len = 56;
3527 SIVAL(pdata,0,svfs.OptimalTransferSize);
3528 SIVAL(pdata,4,svfs.BlockSize);
3529 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3530 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3531 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3532 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3533 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3534 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3535 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3536 #ifdef EOPNOTSUPP
3537 } else if (rc == EOPNOTSUPP) {
3538 return NT_STATUS_INVALID_LEVEL;
3539 #endif /* EOPNOTSUPP */
3540 } else {
3541 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3542 return NT_STATUS_DOS(ERRSRV, ERRerror);
3544 break;
3547 case SMB_QUERY_POSIX_WHOAMI:
3549 uint32_t flags = 0;
3550 uint32_t sid_bytes;
3551 int i;
3553 if (!lp_unix_extensions()) {
3554 return NT_STATUS_INVALID_LEVEL;
3557 if (max_data_bytes < 40) {
3558 return NT_STATUS_BUFFER_TOO_SMALL;
3561 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3562 flags |= SMB_WHOAMI_GUEST;
3565 /* NOTE: 8 bytes for UID/GID, irrespective of native
3566 * platform size. This matches
3567 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3569 data_len = 4 /* flags */
3570 + 4 /* flag mask */
3571 + 8 /* uid */
3572 + 8 /* gid */
3573 + 4 /* ngroups */
3574 + 4 /* num_sids */
3575 + 4 /* SID bytes */
3576 + 4 /* pad/reserved */
3577 + (conn->session_info->unix_token->ngroups * 8)
3578 /* groups list */
3579 + (conn->session_info->security_token->num_sids *
3580 SID_MAX_SIZE)
3581 /* SID list */;
3583 SIVAL(pdata, 0, flags);
3584 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3585 SBIG_UINT(pdata, 8,
3586 (uint64_t)conn->session_info->unix_token->uid);
3587 SBIG_UINT(pdata, 16,
3588 (uint64_t)conn->session_info->unix_token->gid);
3591 if (data_len >= max_data_bytes) {
3592 /* Potential overflow, skip the GIDs and SIDs. */
3594 SIVAL(pdata, 24, 0); /* num_groups */
3595 SIVAL(pdata, 28, 0); /* num_sids */
3596 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3597 SIVAL(pdata, 36, 0); /* reserved */
3599 data_len = 40;
3600 break;
3603 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3604 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3606 /* We walk the SID list twice, but this call is fairly
3607 * infrequent, and I don't expect that it's performance
3608 * sensitive -- jpeach
3610 for (i = 0, sid_bytes = 0;
3611 i < conn->session_info->security_token->num_sids; ++i) {
3612 sid_bytes += ndr_size_dom_sid(
3613 &conn->session_info->security_token->sids[i],
3617 /* SID list byte count */
3618 SIVAL(pdata, 32, sid_bytes);
3620 /* 4 bytes pad/reserved - must be zero */
3621 SIVAL(pdata, 36, 0);
3622 data_len = 40;
3624 /* GID list */
3625 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3626 SBIG_UINT(pdata, data_len,
3627 (uint64_t)conn->session_info->unix_token->groups[i]);
3628 data_len += 8;
3631 /* SID list */
3632 for (i = 0;
3633 i < conn->session_info->security_token->num_sids; ++i) {
3634 int sid_len = ndr_size_dom_sid(
3635 &conn->session_info->security_token->sids[i],
3638 sid_linearize(pdata + data_len, sid_len,
3639 &conn->session_info->security_token->sids[i]);
3640 data_len += sid_len;
3643 break;
3646 case SMB_MAC_QUERY_FS_INFO:
3648 * Thursby MAC extension... ONLY on NTFS filesystems
3649 * once we do streams then we don't need this
3651 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3652 data_len = 88;
3653 SIVAL(pdata,84,0x100); /* Don't support mac... */
3654 break;
3656 /* drop through */
3657 default:
3658 return NT_STATUS_INVALID_LEVEL;
3661 *ret_data_len = data_len;
3662 return NT_STATUS_OK;
3665 /****************************************************************************
3666 Reply to a TRANS2_QFSINFO (query filesystem info).
3667 ****************************************************************************/
3669 static void call_trans2qfsinfo(connection_struct *conn,
3670 struct smb_request *req,
3671 char **pparams, int total_params,
3672 char **ppdata, int total_data,
3673 unsigned int max_data_bytes)
3675 char *params = *pparams;
3676 uint16_t info_level;
3677 int data_len = 0;
3678 NTSTATUS status;
3680 if (total_params < 2) {
3681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3682 return;
3685 info_level = SVAL(params,0);
3687 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3688 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3689 DEBUG(0,("call_trans2qfsinfo: encryption required "
3690 "and info level 0x%x sent.\n",
3691 (unsigned int)info_level));
3692 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3693 return;
3697 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3699 status = smbd_do_qfsinfo(conn, req,
3700 info_level,
3701 req->flags2,
3702 max_data_bytes,
3703 NULL,
3704 ppdata, &data_len);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 reply_nterror(req, status);
3707 return;
3710 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3711 max_data_bytes);
3713 DEBUG( 4, ( "%s info_level = %d\n",
3714 smb_fn_name(req->cmd), info_level) );
3716 return;
3719 /****************************************************************************
3720 Reply to a TRANS2_SETFSINFO (set filesystem info).
3721 ****************************************************************************/
3723 static void call_trans2setfsinfo(connection_struct *conn,
3724 struct smb_request *req,
3725 char **pparams, int total_params,
3726 char **ppdata, int total_data,
3727 unsigned int max_data_bytes)
3729 struct smbd_server_connection *sconn = req->sconn;
3730 char *pdata = *ppdata;
3731 char *params = *pparams;
3732 uint16 info_level;
3734 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3735 lp_servicename(talloc_tos(), SNUM(conn))));
3737 /* */
3738 if (total_params < 4) {
3739 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3740 total_params));
3741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3742 return;
3745 info_level = SVAL(params,2);
3747 if (IS_IPC(conn)) {
3748 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3749 info_level != SMB_SET_CIFS_UNIX_INFO) {
3750 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3751 "info level (0x%x) on IPC$.\n",
3752 (unsigned int)info_level));
3753 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3754 return;
3758 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3759 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3760 DEBUG(0,("call_trans2setfsinfo: encryption required "
3761 "and info level 0x%x sent.\n",
3762 (unsigned int)info_level));
3763 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3764 return;
3768 switch(info_level) {
3769 case SMB_SET_CIFS_UNIX_INFO:
3770 if (!lp_unix_extensions()) {
3771 DEBUG(2,("call_trans2setfsinfo: "
3772 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3773 "unix extensions off\n"));
3774 reply_nterror(req,
3775 NT_STATUS_INVALID_LEVEL);
3776 return;
3779 /* There should be 12 bytes of capabilities set. */
3780 if (total_data < 12) {
3781 reply_nterror(
3782 req,
3783 NT_STATUS_INVALID_PARAMETER);
3784 return;
3786 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3787 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3788 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3789 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3790 /* Just print these values for now. */
3791 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3792 "major = %u, minor = %u cap_low = 0x%x, "
3793 "cap_high = 0x%xn",
3794 (unsigned int)sconn->
3795 smb1.unix_info.client_major,
3796 (unsigned int)sconn->
3797 smb1.unix_info.client_minor,
3798 (unsigned int)sconn->
3799 smb1.unix_info.client_cap_low,
3800 (unsigned int)sconn->
3801 smb1.unix_info.client_cap_high));
3803 /* Here is where we must switch to posix pathname processing... */
3804 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3805 lp_set_posix_pathnames();
3806 mangle_change_to_posix();
3809 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3810 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3811 /* Client that knows how to do posix locks,
3812 * but not posix open/mkdir operations. Set a
3813 * default type for read/write checks. */
3815 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3818 break;
3820 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3822 NTSTATUS status;
3823 size_t param_len = 0;
3824 size_t data_len = total_data;
3826 if (!lp_unix_extensions()) {
3827 reply_nterror(
3828 req,
3829 NT_STATUS_INVALID_LEVEL);
3830 return;
3833 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3834 reply_nterror(
3835 req,
3836 NT_STATUS_NOT_SUPPORTED);
3837 return;
3840 if (req->sconn->smb1.echo_handler.trusted_fde) {
3841 DEBUG( 2,("call_trans2setfsinfo: "
3842 "request transport encryption disabled"
3843 "with 'fork echo handler = yes'\n"));
3844 reply_nterror(
3845 req,
3846 NT_STATUS_NOT_SUPPORTED);
3847 return;
3850 DEBUG( 4,("call_trans2setfsinfo: "
3851 "request transport encryption.\n"));
3853 status = srv_request_encryption_setup(conn,
3854 (unsigned char **)ppdata,
3855 &data_len,
3856 (unsigned char **)pparams,
3857 &param_len);
3859 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3860 !NT_STATUS_IS_OK(status)) {
3861 reply_nterror(req, status);
3862 return;
3865 send_trans2_replies(conn, req,
3866 NT_STATUS_OK,
3867 *pparams,
3868 param_len,
3869 *ppdata,
3870 data_len,
3871 max_data_bytes);
3873 if (NT_STATUS_IS_OK(status)) {
3874 /* Server-side transport
3875 * encryption is now *on*. */
3876 status = srv_encryption_start(conn);
3877 if (!NT_STATUS_IS_OK(status)) {
3878 char *reason = talloc_asprintf(talloc_tos(),
3879 "Failure in setting "
3880 "up encrypted transport: %s",
3881 nt_errstr(status));
3882 exit_server_cleanly(reason);
3885 return;
3888 case SMB_FS_QUOTA_INFORMATION:
3890 files_struct *fsp = NULL;
3891 SMB_NTQUOTA_STRUCT quotas;
3893 ZERO_STRUCT(quotas);
3895 /* access check */
3896 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3897 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3898 lp_servicename(talloc_tos(), SNUM(conn)),
3899 conn->session_info->unix_info->unix_name));
3900 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3901 return;
3904 /* note: normaly there're 48 bytes,
3905 * but we didn't use the last 6 bytes for now
3906 * --metze
3908 fsp = file_fsp(req, SVAL(params,0));
3910 if (!check_fsp_ntquota_handle(conn, req,
3911 fsp)) {
3912 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3913 reply_nterror(
3914 req, NT_STATUS_INVALID_HANDLE);
3915 return;
3918 if (total_data < 42) {
3919 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3920 total_data));
3921 reply_nterror(
3922 req,
3923 NT_STATUS_INVALID_PARAMETER);
3924 return;
3927 /* unknown_1 24 NULL bytes in pdata*/
3929 /* the soft quotas 8 bytes (uint64_t)*/
3930 quotas.softlim = BVAL(pdata,24);
3932 /* the hard quotas 8 bytes (uint64_t)*/
3933 quotas.hardlim = BVAL(pdata,32);
3935 /* quota_flags 2 bytes **/
3936 quotas.qflags = SVAL(pdata,40);
3938 /* unknown_2 6 NULL bytes follow*/
3940 /* now set the quotas */
3941 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3942 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3943 reply_nterror(req, map_nt_error_from_unix(errno));
3944 return;
3947 break;
3949 default:
3950 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3951 info_level));
3952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3953 return;
3954 break;
3958 * sending this reply works fine,
3959 * but I'm not sure it's the same
3960 * like windows do...
3961 * --metze
3963 reply_outbuf(req, 10, 0);
3966 #if defined(HAVE_POSIX_ACLS)
3967 /****************************************************************************
3968 Utility function to count the number of entries in a POSIX acl.
3969 ****************************************************************************/
3971 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3973 unsigned int ace_count = 0;
3974 int entry_id = SMB_ACL_FIRST_ENTRY;
3975 SMB_ACL_ENTRY_T entry;
3977 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3978 /* get_next... */
3979 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3980 entry_id = SMB_ACL_NEXT_ENTRY;
3982 ace_count++;
3984 return ace_count;
3987 /****************************************************************************
3988 Utility function to marshall a POSIX acl into wire format.
3989 ****************************************************************************/
3991 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3993 int entry_id = SMB_ACL_FIRST_ENTRY;
3994 SMB_ACL_ENTRY_T entry;
3996 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3997 SMB_ACL_TAG_T tagtype;
3998 SMB_ACL_PERMSET_T permset;
3999 unsigned char perms = 0;
4000 unsigned int own_grp;
4002 /* get_next... */
4003 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4004 entry_id = SMB_ACL_NEXT_ENTRY;
4007 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4008 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4009 return False;
4012 if (sys_acl_get_permset(entry, &permset) == -1) {
4013 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4014 return False;
4017 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4018 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4019 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4021 SCVAL(pdata,1,perms);
4023 switch (tagtype) {
4024 case SMB_ACL_USER_OBJ:
4025 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4026 own_grp = (unsigned int)pst->st_ex_uid;
4027 SIVAL(pdata,2,own_grp);
4028 SIVAL(pdata,6,0);
4029 break;
4030 case SMB_ACL_USER:
4032 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4033 if (!puid) {
4034 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4035 return False;
4037 own_grp = (unsigned int)*puid;
4038 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4039 SIVAL(pdata,2,own_grp);
4040 SIVAL(pdata,6,0);
4041 break;
4043 case SMB_ACL_GROUP_OBJ:
4044 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4045 own_grp = (unsigned int)pst->st_ex_gid;
4046 SIVAL(pdata,2,own_grp);
4047 SIVAL(pdata,6,0);
4048 break;
4049 case SMB_ACL_GROUP:
4051 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4052 if (!pgid) {
4053 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4054 return False;
4056 own_grp = (unsigned int)*pgid;
4057 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4058 SIVAL(pdata,2,own_grp);
4059 SIVAL(pdata,6,0);
4060 break;
4062 case SMB_ACL_MASK:
4063 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4064 SIVAL(pdata,2,0xFFFFFFFF);
4065 SIVAL(pdata,6,0xFFFFFFFF);
4066 break;
4067 case SMB_ACL_OTHER:
4068 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4069 SIVAL(pdata,2,0xFFFFFFFF);
4070 SIVAL(pdata,6,0xFFFFFFFF);
4071 break;
4072 default:
4073 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4074 return False;
4076 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4079 return True;
4081 #endif
4083 /****************************************************************************
4084 Store the FILE_UNIX_BASIC info.
4085 ****************************************************************************/
4087 static char *store_file_unix_basic(connection_struct *conn,
4088 char *pdata,
4089 files_struct *fsp,
4090 const SMB_STRUCT_STAT *psbuf)
4092 uint64_t file_index = get_FileIndex(conn, psbuf);
4093 dev_t devno;
4095 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4096 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4098 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4099 pdata += 8;
4101 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4102 pdata += 8;
4104 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4105 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4106 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4107 pdata += 24;
4109 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4110 SIVAL(pdata,4,0);
4111 pdata += 8;
4113 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4114 SIVAL(pdata,4,0);
4115 pdata += 8;
4117 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4118 pdata += 4;
4120 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4121 devno = psbuf->st_ex_rdev;
4122 } else {
4123 devno = psbuf->st_ex_dev;
4126 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4127 SIVAL(pdata,4,0);
4128 pdata += 8;
4130 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4131 SIVAL(pdata,4,0);
4132 pdata += 8;
4134 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4135 pdata += 8;
4137 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4138 SIVAL(pdata,4,0);
4139 pdata += 8;
4141 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4142 SIVAL(pdata,4,0);
4143 pdata += 8;
4145 return pdata;
4148 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4149 * the chflags(2) (or equivalent) flags.
4151 * XXX: this really should be behind the VFS interface. To do this, we would
4152 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4153 * Each VFS module could then implement its own mapping as appropriate for the
4154 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4156 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4157 info2_flags_map[] =
4159 #ifdef UF_NODUMP
4160 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4161 #endif
4163 #ifdef UF_IMMUTABLE
4164 { UF_IMMUTABLE, EXT_IMMUTABLE },
4165 #endif
4167 #ifdef UF_APPEND
4168 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4169 #endif
4171 #ifdef UF_HIDDEN
4172 { UF_HIDDEN, EXT_HIDDEN },
4173 #endif
4175 /* Do not remove. We need to guarantee that this array has at least one
4176 * entry to build on HP-UX.
4178 { 0, 0 }
4182 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4183 uint32 *smb_fflags, uint32 *smb_fmask)
4185 int i;
4187 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4188 *smb_fmask |= info2_flags_map[i].smb_fflag;
4189 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4190 *smb_fflags |= info2_flags_map[i].smb_fflag;
4195 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4196 const uint32 smb_fflags,
4197 const uint32 smb_fmask,
4198 int *stat_fflags)
4200 uint32 max_fmask = 0;
4201 int i;
4203 *stat_fflags = psbuf->st_ex_flags;
4205 /* For each flags requested in smb_fmask, check the state of the
4206 * corresponding flag in smb_fflags and set or clear the matching
4207 * stat flag.
4210 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4211 max_fmask |= info2_flags_map[i].smb_fflag;
4212 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4213 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4214 *stat_fflags |= info2_flags_map[i].stat_fflag;
4215 } else {
4216 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4221 /* If smb_fmask is asking to set any bits that are not supported by
4222 * our flag mappings, we should fail.
4224 if ((smb_fmask & max_fmask) != smb_fmask) {
4225 return False;
4228 return True;
4232 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4233 * of file flags and birth (create) time.
4235 static char *store_file_unix_basic_info2(connection_struct *conn,
4236 char *pdata,
4237 files_struct *fsp,
4238 const SMB_STRUCT_STAT *psbuf)
4240 uint32 file_flags = 0;
4241 uint32 flags_mask = 0;
4243 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4245 /* Create (birth) time 64 bit */
4246 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4247 pdata += 8;
4249 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4250 SIVAL(pdata, 0, file_flags); /* flags */
4251 SIVAL(pdata, 4, flags_mask); /* mask */
4252 pdata += 8;
4254 return pdata;
4257 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4258 const struct stream_struct *streams,
4259 char *data,
4260 unsigned int max_data_bytes,
4261 unsigned int *data_size)
4263 unsigned int i;
4264 unsigned int ofs = 0;
4266 for (i = 0; i < num_streams; i++) {
4267 unsigned int next_offset;
4268 size_t namelen;
4269 smb_ucs2_t *namebuf;
4271 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4272 streams[i].name, &namelen) ||
4273 namelen <= 2)
4275 return NT_STATUS_INVALID_PARAMETER;
4279 * name_buf is now null-terminated, we need to marshall as not
4280 * terminated
4283 namelen -= 2;
4286 * We cannot overflow ...
4288 if ((ofs + 24 + namelen) > max_data_bytes) {
4289 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4290 i));
4291 TALLOC_FREE(namebuf);
4292 return STATUS_BUFFER_OVERFLOW;
4295 SIVAL(data, ofs+4, namelen);
4296 SOFF_T(data, ofs+8, streams[i].size);
4297 SOFF_T(data, ofs+16, streams[i].alloc_size);
4298 memcpy(data+ofs+24, namebuf, namelen);
4299 TALLOC_FREE(namebuf);
4301 next_offset = ofs + 24 + namelen;
4303 if (i == num_streams-1) {
4304 SIVAL(data, ofs, 0);
4306 else {
4307 unsigned int align = ndr_align_size(next_offset, 8);
4309 if ((next_offset + align) > max_data_bytes) {
4310 DEBUG(10, ("refusing to overflow align "
4311 "reply at stream %u\n",
4312 i));
4313 TALLOC_FREE(namebuf);
4314 return STATUS_BUFFER_OVERFLOW;
4317 memset(data+next_offset, 0, align);
4318 next_offset += align;
4320 SIVAL(data, ofs, next_offset - ofs);
4321 ofs = next_offset;
4324 ofs = next_offset;
4327 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4329 *data_size = ofs;
4331 return NT_STATUS_OK;
4334 /****************************************************************************
4335 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4336 ****************************************************************************/
4338 static void call_trans2qpipeinfo(connection_struct *conn,
4339 struct smb_request *req,
4340 unsigned int tran_call,
4341 char **pparams, int total_params,
4342 char **ppdata, int total_data,
4343 unsigned int max_data_bytes)
4345 char *params = *pparams;
4346 char *pdata = *ppdata;
4347 unsigned int data_size = 0;
4348 unsigned int param_size = 2;
4349 uint16 info_level;
4350 files_struct *fsp;
4352 if (!params) {
4353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4354 return;
4357 if (total_params < 4) {
4358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4359 return;
4362 fsp = file_fsp(req, SVAL(params,0));
4363 if (!fsp_is_np(fsp)) {
4364 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4365 return;
4368 info_level = SVAL(params,2);
4370 *pparams = (char *)SMB_REALLOC(*pparams,2);
4371 if (*pparams == NULL) {
4372 reply_nterror(req, NT_STATUS_NO_MEMORY);
4373 return;
4375 params = *pparams;
4376 SSVAL(params,0,0);
4377 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4378 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4379 if (*ppdata == NULL ) {
4380 reply_nterror(req, NT_STATUS_NO_MEMORY);
4381 return;
4383 pdata = *ppdata;
4385 switch (info_level) {
4386 case SMB_FILE_STANDARD_INFORMATION:
4387 memset(pdata,0,24);
4388 SOFF_T(pdata,0,4096LL);
4389 SIVAL(pdata,16,1);
4390 SIVAL(pdata,20,1);
4391 data_size = 24;
4392 break;
4394 default:
4395 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4396 return;
4399 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4400 max_data_bytes);
4402 return;
4405 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4406 TALLOC_CTX *mem_ctx,
4407 uint16_t info_level,
4408 files_struct *fsp,
4409 struct smb_filename *smb_fname,
4410 bool delete_pending,
4411 struct timespec write_time_ts,
4412 struct ea_list *ea_list,
4413 int lock_data_count,
4414 char *lock_data,
4415 uint16_t flags2,
4416 unsigned int max_data_bytes,
4417 char **ppdata,
4418 unsigned int *pdata_size)
4420 char *pdata = *ppdata;
4421 char *dstart, *dend;
4422 unsigned int data_size;
4423 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4424 time_t create_time, mtime, atime, c_time;
4425 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4426 char *p;
4427 char *base_name;
4428 char *dos_fname;
4429 int mode;
4430 int nlink;
4431 NTSTATUS status;
4432 uint64_t file_size = 0;
4433 uint64_t pos = 0;
4434 uint64_t allocation_size = 0;
4435 uint64_t file_index = 0;
4436 uint32_t access_mask = 0;
4438 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4439 return NT_STATUS_INVALID_LEVEL;
4442 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4443 smb_fname_str_dbg(smb_fname),
4444 fsp_fnum_dbg(fsp),
4445 info_level, max_data_bytes));
4447 mode = dos_mode(conn, smb_fname);
4448 nlink = psbuf->st_ex_nlink;
4450 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4451 nlink = 1;
4454 if ((nlink > 0) && delete_pending) {
4455 nlink -= 1;
4458 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4459 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4460 if (*ppdata == NULL) {
4461 return NT_STATUS_NO_MEMORY;
4463 pdata = *ppdata;
4464 dstart = pdata;
4465 dend = dstart + data_size - 1;
4467 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4468 update_stat_ex_mtime(psbuf, write_time_ts);
4471 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4472 mtime_ts = psbuf->st_ex_mtime;
4473 atime_ts = psbuf->st_ex_atime;
4474 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4476 if (lp_dos_filetime_resolution(SNUM(conn))) {
4477 dos_filetime_timespec(&create_time_ts);
4478 dos_filetime_timespec(&mtime_ts);
4479 dos_filetime_timespec(&atime_ts);
4480 dos_filetime_timespec(&ctime_ts);
4483 create_time = convert_timespec_to_time_t(create_time_ts);
4484 mtime = convert_timespec_to_time_t(mtime_ts);
4485 atime = convert_timespec_to_time_t(atime_ts);
4486 c_time = convert_timespec_to_time_t(ctime_ts);
4488 p = strrchr_m(smb_fname->base_name,'/');
4489 if (!p)
4490 base_name = smb_fname->base_name;
4491 else
4492 base_name = p+1;
4494 /* NT expects the name to be in an exact form of the *full*
4495 filename. See the trans2 torture test */
4496 if (ISDOT(base_name)) {
4497 dos_fname = talloc_strdup(mem_ctx, "\\");
4498 if (!dos_fname) {
4499 return NT_STATUS_NO_MEMORY;
4501 } else {
4502 dos_fname = talloc_asprintf(mem_ctx,
4503 "\\%s",
4504 smb_fname->base_name);
4505 if (!dos_fname) {
4506 return NT_STATUS_NO_MEMORY;
4508 if (is_ntfs_stream_smb_fname(smb_fname)) {
4509 dos_fname = talloc_asprintf(dos_fname, "%s",
4510 smb_fname->stream_name);
4511 if (!dos_fname) {
4512 return NT_STATUS_NO_MEMORY;
4516 string_replace(dos_fname, '/', '\\');
4519 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4521 if (!fsp) {
4522 /* Do we have this path open ? */
4523 files_struct *fsp1;
4524 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4525 fsp1 = file_find_di_first(conn->sconn, fileid);
4526 if (fsp1 && fsp1->initial_allocation_size) {
4527 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4531 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4532 file_size = get_file_size_stat(psbuf);
4535 if (fsp) {
4536 pos = fsp->fh->position_information;
4539 if (fsp) {
4540 access_mask = fsp->access_mask;
4541 } else {
4542 /* GENERIC_EXECUTE mapping from Windows */
4543 access_mask = 0x12019F;
4546 /* This should be an index number - looks like
4547 dev/ino to me :-)
4549 I think this causes us to fail the IFSKIT
4550 BasicFileInformationTest. -tpot */
4551 file_index = get_FileIndex(conn, psbuf);
4553 switch (info_level) {
4554 case SMB_INFO_STANDARD:
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4556 data_size = 22;
4557 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4558 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4559 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4560 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4561 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4562 SSVAL(pdata,l1_attrFile,mode);
4563 break;
4565 case SMB_INFO_QUERY_EA_SIZE:
4567 unsigned int ea_size =
4568 estimate_ea_size(conn, fsp,
4569 smb_fname);
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4571 data_size = 26;
4572 srv_put_dos_date2(pdata,0,create_time);
4573 srv_put_dos_date2(pdata,4,atime);
4574 srv_put_dos_date2(pdata,8,mtime); /* write time */
4575 SIVAL(pdata,12,(uint32)file_size);
4576 SIVAL(pdata,16,(uint32)allocation_size);
4577 SSVAL(pdata,20,mode);
4578 SIVAL(pdata,22,ea_size);
4579 break;
4582 case SMB_INFO_IS_NAME_VALID:
4583 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4584 if (fsp) {
4585 /* os/2 needs this ? really ?*/
4586 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4588 /* This is only reached for qpathinfo */
4589 data_size = 0;
4590 break;
4592 case SMB_INFO_QUERY_EAS_FROM_LIST:
4594 size_t total_ea_len = 0;
4595 struct ea_list *ea_file_list = NULL;
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4598 status =
4599 get_ea_list_from_file(mem_ctx, conn, fsp,
4600 smb_fname,
4601 &total_ea_len, &ea_file_list);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 return status;
4606 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4608 if (!ea_list || (total_ea_len > data_size)) {
4609 data_size = 4;
4610 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4611 break;
4614 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4615 break;
4618 case SMB_INFO_QUERY_ALL_EAS:
4620 /* We have data_size bytes to put EA's into. */
4621 size_t total_ea_len = 0;
4622 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4624 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4625 smb_fname,
4626 &total_ea_len, &ea_list);
4627 if (!NT_STATUS_IS_OK(status)) {
4628 return status;
4631 if (!ea_list || (total_ea_len > data_size)) {
4632 data_size = 4;
4633 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4634 break;
4637 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4638 break;
4641 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4643 /* This is FileFullEaInformation - 0xF which maps to
4644 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4646 /* We have data_size bytes to put EA's into. */
4647 size_t total_ea_len = 0;
4648 struct ea_list *ea_file_list = NULL;
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4652 /*TODO: add filtering and index handling */
4654 status =
4655 get_ea_list_from_file(mem_ctx, conn, fsp,
4656 smb_fname,
4657 &total_ea_len, &ea_file_list);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 return status;
4661 if (!ea_file_list) {
4662 return NT_STATUS_NO_EAS_ON_FILE;
4665 status = fill_ea_chained_buffer(mem_ctx,
4666 pdata,
4667 data_size,
4668 &data_size,
4669 conn, ea_file_list);
4670 if (!NT_STATUS_IS_OK(status)) {
4671 return status;
4673 break;
4676 case SMB_FILE_BASIC_INFORMATION:
4677 case SMB_QUERY_FILE_BASIC_INFO:
4679 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4681 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4682 } else {
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4684 data_size = 40;
4685 SIVAL(pdata,36,0);
4687 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4688 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4689 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4690 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4691 SIVAL(pdata,32,mode);
4693 DEBUG(5,("SMB_QFBI - "));
4694 DEBUG(5,("create: %s ", ctime(&create_time)));
4695 DEBUG(5,("access: %s ", ctime(&atime)));
4696 DEBUG(5,("write: %s ", ctime(&mtime)));
4697 DEBUG(5,("change: %s ", ctime(&c_time)));
4698 DEBUG(5,("mode: %x\n", mode));
4699 break;
4701 case SMB_FILE_STANDARD_INFORMATION:
4702 case SMB_QUERY_FILE_STANDARD_INFO:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4705 data_size = 24;
4706 SOFF_T(pdata,0,allocation_size);
4707 SOFF_T(pdata,8,file_size);
4708 SIVAL(pdata,16,nlink);
4709 SCVAL(pdata,20,delete_pending?1:0);
4710 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4711 SSVAL(pdata,22,0); /* Padding. */
4712 break;
4714 case SMB_FILE_EA_INFORMATION:
4715 case SMB_QUERY_FILE_EA_INFO:
4717 unsigned int ea_size =
4718 estimate_ea_size(conn, fsp, smb_fname);
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4720 data_size = 4;
4721 SIVAL(pdata,0,ea_size);
4722 break;
4725 /* Get the 8.3 name - used if NT SMB was negotiated. */
4726 case SMB_QUERY_FILE_ALT_NAME_INFO:
4727 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4729 int len;
4730 char mangled_name[13];
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4732 if (!name_to_8_3(base_name,mangled_name,
4733 True,conn->params)) {
4734 return NT_STATUS_NO_MEMORY;
4736 len = srvstr_push(dstart, flags2,
4737 pdata+4, mangled_name,
4738 PTR_DIFF(dend, pdata+4),
4739 STR_UNICODE);
4740 data_size = 4 + len;
4741 SIVAL(pdata,0,len);
4742 break;
4745 case SMB_QUERY_FILE_NAME_INFO:
4747 int len;
4749 this must be *exactly* right for ACLs on mapped drives to work
4751 len = srvstr_push(dstart, flags2,
4752 pdata+4, dos_fname,
4753 PTR_DIFF(dend, pdata+4),
4754 STR_UNICODE);
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4756 data_size = 4 + len;
4757 SIVAL(pdata,0,len);
4758 break;
4761 case SMB_FILE_ALLOCATION_INFORMATION:
4762 case SMB_QUERY_FILE_ALLOCATION_INFO:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4764 data_size = 8;
4765 SOFF_T(pdata,0,allocation_size);
4766 break;
4768 case SMB_FILE_END_OF_FILE_INFORMATION:
4769 case SMB_QUERY_FILE_END_OF_FILEINFO:
4770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4771 data_size = 8;
4772 SOFF_T(pdata,0,file_size);
4773 break;
4775 case SMB_QUERY_FILE_ALL_INFO:
4776 case SMB_FILE_ALL_INFORMATION:
4778 int len;
4779 unsigned int ea_size =
4780 estimate_ea_size(conn, fsp, smb_fname);
4781 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4782 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4783 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4784 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4785 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4786 SIVAL(pdata,32,mode);
4787 SIVAL(pdata,36,0); /* padding. */
4788 pdata += 40;
4789 SOFF_T(pdata,0,allocation_size);
4790 SOFF_T(pdata,8,file_size);
4791 SIVAL(pdata,16,nlink);
4792 SCVAL(pdata,20,delete_pending);
4793 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4794 SSVAL(pdata,22,0);
4795 pdata += 24;
4796 SIVAL(pdata,0,ea_size);
4797 pdata += 4; /* EA info */
4798 len = srvstr_push(dstart, flags2,
4799 pdata+4, dos_fname,
4800 PTR_DIFF(dend, pdata+4),
4801 STR_UNICODE);
4802 SIVAL(pdata,0,len);
4803 pdata += 4 + len;
4804 data_size = PTR_DIFF(pdata,(*ppdata));
4805 break;
4808 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4810 int len;
4811 unsigned int ea_size =
4812 estimate_ea_size(conn, fsp, smb_fname);
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4814 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4815 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4816 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4817 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4818 SIVAL(pdata, 0x20, mode);
4819 SIVAL(pdata, 0x24, 0); /* padding. */
4820 SBVAL(pdata, 0x28, allocation_size);
4821 SBVAL(pdata, 0x30, file_size);
4822 SIVAL(pdata, 0x38, nlink);
4823 SCVAL(pdata, 0x3C, delete_pending);
4824 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4825 SSVAL(pdata, 0x3E, 0); /* padding */
4826 SBVAL(pdata, 0x40, file_index);
4827 SIVAL(pdata, 0x48, ea_size);
4828 SIVAL(pdata, 0x4C, access_mask);
4829 SBVAL(pdata, 0x50, pos);
4830 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4831 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4833 pdata += 0x60;
4835 len = srvstr_push(dstart, flags2,
4836 pdata+4, dos_fname,
4837 PTR_DIFF(dend, pdata+4),
4838 STR_UNICODE);
4839 SIVAL(pdata,0,len);
4840 pdata += 4 + len;
4841 data_size = PTR_DIFF(pdata,(*ppdata));
4842 break;
4844 case SMB_FILE_INTERNAL_INFORMATION:
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4847 SBVAL(pdata, 0, file_index);
4848 data_size = 8;
4849 break;
4851 case SMB_FILE_ACCESS_INFORMATION:
4852 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4853 SIVAL(pdata, 0, access_mask);
4854 data_size = 4;
4855 break;
4857 case SMB_FILE_NAME_INFORMATION:
4858 /* Pathname with leading '\'. */
4860 size_t byte_len;
4861 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4862 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4863 SIVAL(pdata,0,byte_len);
4864 data_size = 4 + byte_len;
4865 break;
4868 case SMB_FILE_DISPOSITION_INFORMATION:
4869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4870 data_size = 1;
4871 SCVAL(pdata,0,delete_pending);
4872 break;
4874 case SMB_FILE_POSITION_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4876 data_size = 8;
4877 SOFF_T(pdata,0,pos);
4878 break;
4880 case SMB_FILE_MODE_INFORMATION:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4882 SIVAL(pdata,0,mode);
4883 data_size = 4;
4884 break;
4886 case SMB_FILE_ALIGNMENT_INFORMATION:
4887 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4888 SIVAL(pdata,0,0); /* No alignment needed. */
4889 data_size = 4;
4890 break;
4893 * NT4 server just returns "invalid query" to this - if we try
4894 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4895 * want this. JRA.
4897 /* The first statement above is false - verified using Thursby
4898 * client against NT4 -- gcolley.
4900 case SMB_QUERY_FILE_STREAM_INFO:
4901 case SMB_FILE_STREAM_INFORMATION: {
4902 unsigned int num_streams = 0;
4903 struct stream_struct *streams = NULL;
4905 DEBUG(10,("smbd_do_qfilepathinfo: "
4906 "SMB_FILE_STREAM_INFORMATION\n"));
4908 if (is_ntfs_stream_smb_fname(smb_fname)) {
4909 return NT_STATUS_INVALID_PARAMETER;
4912 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4913 talloc_tos(), &num_streams, &streams);
4915 if (!NT_STATUS_IS_OK(status)) {
4916 DEBUG(10, ("could not get stream info: %s\n",
4917 nt_errstr(status)));
4918 return status;
4921 status = marshall_stream_info(num_streams, streams,
4922 pdata, max_data_bytes,
4923 &data_size);
4925 if (!NT_STATUS_IS_OK(status)) {
4926 DEBUG(10, ("marshall_stream_info failed: %s\n",
4927 nt_errstr(status)));
4928 TALLOC_FREE(streams);
4929 return status;
4932 TALLOC_FREE(streams);
4934 break;
4936 case SMB_QUERY_COMPRESSION_INFO:
4937 case SMB_FILE_COMPRESSION_INFORMATION:
4938 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4939 SOFF_T(pdata,0,file_size);
4940 SIVAL(pdata,8,0); /* ??? */
4941 SIVAL(pdata,12,0); /* ??? */
4942 data_size = 16;
4943 break;
4945 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4946 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4947 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4948 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4949 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4950 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4951 SOFF_T(pdata,32,allocation_size);
4952 SOFF_T(pdata,40,file_size);
4953 SIVAL(pdata,48,mode);
4954 SIVAL(pdata,52,0); /* ??? */
4955 data_size = 56;
4956 break;
4958 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4960 SIVAL(pdata,0,mode);
4961 SIVAL(pdata,4,0);
4962 data_size = 8;
4963 break;
4966 * CIFS UNIX Extensions.
4969 case SMB_QUERY_FILE_UNIX_BASIC:
4971 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4972 data_size = PTR_DIFF(pdata,(*ppdata));
4974 DEBUG(4,("smbd_do_qfilepathinfo: "
4975 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4976 dump_data(4, (uint8_t *)(*ppdata), data_size);
4978 break;
4980 case SMB_QUERY_FILE_UNIX_INFO2:
4982 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4983 data_size = PTR_DIFF(pdata,(*ppdata));
4986 int i;
4987 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4989 for (i=0; i<100; i++)
4990 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4991 DEBUG(4,("\n"));
4994 break;
4996 case SMB_QUERY_FILE_UNIX_LINK:
4998 int len;
4999 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5001 if (!buffer) {
5002 return NT_STATUS_NO_MEMORY;
5005 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5006 #ifdef S_ISLNK
5007 if(!S_ISLNK(psbuf->st_ex_mode)) {
5008 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5010 #else
5011 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5012 #endif
5013 len = SMB_VFS_READLINK(conn,
5014 smb_fname->base_name,
5015 buffer, PATH_MAX);
5016 if (len == -1) {
5017 return map_nt_error_from_unix(errno);
5019 buffer[len] = 0;
5020 len = srvstr_push(dstart, flags2,
5021 pdata, buffer,
5022 PTR_DIFF(dend, pdata),
5023 STR_TERMINATE);
5024 pdata += len;
5025 data_size = PTR_DIFF(pdata,(*ppdata));
5027 break;
5030 #if defined(HAVE_POSIX_ACLS)
5031 case SMB_QUERY_POSIX_ACL:
5033 SMB_ACL_T file_acl = NULL;
5034 SMB_ACL_T def_acl = NULL;
5035 uint16 num_file_acls = 0;
5036 uint16 num_def_acls = 0;
5038 if (fsp && fsp->fh->fd != -1) {
5039 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5040 talloc_tos());
5041 } else {
5042 file_acl =
5043 SMB_VFS_SYS_ACL_GET_FILE(conn,
5044 smb_fname->base_name,
5045 SMB_ACL_TYPE_ACCESS,
5046 talloc_tos());
5049 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5050 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5051 "not implemented on "
5052 "filesystem containing %s\n",
5053 smb_fname->base_name));
5054 return NT_STATUS_NOT_IMPLEMENTED;
5057 if (S_ISDIR(psbuf->st_ex_mode)) {
5058 if (fsp && fsp->is_directory) {
5059 def_acl =
5060 SMB_VFS_SYS_ACL_GET_FILE(
5061 conn,
5062 fsp->fsp_name->base_name,
5063 SMB_ACL_TYPE_DEFAULT,
5064 talloc_tos());
5065 } else {
5066 def_acl =
5067 SMB_VFS_SYS_ACL_GET_FILE(
5068 conn,
5069 smb_fname->base_name,
5070 SMB_ACL_TYPE_DEFAULT,
5071 talloc_tos());
5073 def_acl = free_empty_sys_acl(conn, def_acl);
5076 num_file_acls = count_acl_entries(conn, file_acl);
5077 num_def_acls = count_acl_entries(conn, def_acl);
5079 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5080 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5081 data_size,
5082 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5083 SMB_POSIX_ACL_HEADER_SIZE) ));
5084 if (file_acl) {
5085 TALLOC_FREE(file_acl);
5087 if (def_acl) {
5088 TALLOC_FREE(def_acl);
5090 return NT_STATUS_BUFFER_TOO_SMALL;
5093 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5094 SSVAL(pdata,2,num_file_acls);
5095 SSVAL(pdata,4,num_def_acls);
5096 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5097 if (file_acl) {
5098 TALLOC_FREE(file_acl);
5100 if (def_acl) {
5101 TALLOC_FREE(def_acl);
5103 return NT_STATUS_INTERNAL_ERROR;
5105 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5106 if (file_acl) {
5107 TALLOC_FREE(file_acl);
5109 if (def_acl) {
5110 TALLOC_FREE(def_acl);
5112 return NT_STATUS_INTERNAL_ERROR;
5115 if (file_acl) {
5116 TALLOC_FREE(file_acl);
5118 if (def_acl) {
5119 TALLOC_FREE(def_acl);
5121 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5122 break;
5124 #endif
5127 case SMB_QUERY_POSIX_LOCK:
5129 uint64_t count;
5130 uint64_t offset;
5131 uint64_t smblctx;
5132 enum brl_type lock_type;
5134 /* We need an open file with a real fd for this. */
5135 if (!fsp || fsp->fh->fd == -1) {
5136 return NT_STATUS_INVALID_LEVEL;
5139 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5140 return NT_STATUS_INVALID_PARAMETER;
5143 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5144 case POSIX_LOCK_TYPE_READ:
5145 lock_type = READ_LOCK;
5146 break;
5147 case POSIX_LOCK_TYPE_WRITE:
5148 lock_type = WRITE_LOCK;
5149 break;
5150 case POSIX_LOCK_TYPE_UNLOCK:
5151 default:
5152 /* There's no point in asking for an unlock... */
5153 return NT_STATUS_INVALID_PARAMETER;
5156 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5157 #if defined(HAVE_LONGLONG)
5158 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5159 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5160 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5161 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5162 #else /* HAVE_LONGLONG */
5163 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5164 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5165 #endif /* HAVE_LONGLONG */
5167 status = query_lock(fsp,
5168 &smblctx,
5169 &count,
5170 &offset,
5171 &lock_type,
5172 POSIX_LOCK);
5174 if (ERROR_WAS_LOCK_DENIED(status)) {
5175 /* Here we need to report who has it locked... */
5176 data_size = POSIX_LOCK_DATA_SIZE;
5178 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5179 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5180 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5181 #if defined(HAVE_LONGLONG)
5182 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5183 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5184 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5185 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5186 #else /* HAVE_LONGLONG */
5187 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5188 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5189 #endif /* HAVE_LONGLONG */
5191 } else if (NT_STATUS_IS_OK(status)) {
5192 /* For success we just return a copy of what we sent
5193 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5194 data_size = POSIX_LOCK_DATA_SIZE;
5195 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5196 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5197 } else {
5198 return status;
5200 break;
5203 default:
5204 return NT_STATUS_INVALID_LEVEL;
5207 *pdata_size = data_size;
5208 return NT_STATUS_OK;
5211 /****************************************************************************
5212 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5213 file name or file id).
5214 ****************************************************************************/
5216 static void call_trans2qfilepathinfo(connection_struct *conn,
5217 struct smb_request *req,
5218 unsigned int tran_call,
5219 char **pparams, int total_params,
5220 char **ppdata, int total_data,
5221 unsigned int max_data_bytes)
5223 char *params = *pparams;
5224 char *pdata = *ppdata;
5225 uint16 info_level;
5226 unsigned int data_size = 0;
5227 unsigned int param_size = 2;
5228 struct smb_filename *smb_fname = NULL;
5229 bool delete_pending = False;
5230 struct timespec write_time_ts;
5231 files_struct *fsp = NULL;
5232 struct file_id fileid;
5233 struct ea_list *ea_list = NULL;
5234 int lock_data_count = 0;
5235 char *lock_data = NULL;
5236 NTSTATUS status = NT_STATUS_OK;
5238 if (!params) {
5239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5240 return;
5243 ZERO_STRUCT(write_time_ts);
5245 if (tran_call == TRANSACT2_QFILEINFO) {
5246 if (total_params < 4) {
5247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5248 return;
5251 if (IS_IPC(conn)) {
5252 call_trans2qpipeinfo(conn, req, tran_call,
5253 pparams, total_params,
5254 ppdata, total_data,
5255 max_data_bytes);
5256 return;
5259 fsp = file_fsp(req, SVAL(params,0));
5260 info_level = SVAL(params,2);
5262 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5264 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5266 return;
5269 /* Initial check for valid fsp ptr. */
5270 if (!check_fsp_open(conn, req, fsp)) {
5271 return;
5274 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5275 &smb_fname);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 reply_nterror(req, status);
5278 return;
5281 if(fsp->fake_file_handle) {
5283 * This is actually for the QUOTA_FAKE_FILE --metze
5286 /* We know this name is ok, it's already passed the checks. */
5288 } else if(fsp->fh->fd == -1) {
5290 * This is actually a QFILEINFO on a directory
5291 * handle (returned from an NT SMB). NT5.0 seems
5292 * to do this call. JRA.
5295 if (INFO_LEVEL_IS_UNIX(info_level)) {
5296 /* Always do lstat for UNIX calls. */
5297 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "SMB_VFS_LSTAT of %s failed "
5300 "(%s)\n",
5301 smb_fname_str_dbg(smb_fname),
5302 strerror(errno)));
5303 reply_nterror(req,
5304 map_nt_error_from_unix(errno));
5305 return;
5307 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5308 DEBUG(3,("call_trans2qfilepathinfo: "
5309 "SMB_VFS_STAT of %s failed (%s)\n",
5310 smb_fname_str_dbg(smb_fname),
5311 strerror(errno)));
5312 reply_nterror(req,
5313 map_nt_error_from_unix(errno));
5314 return;
5317 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5318 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5319 } else {
5321 * Original code - this is an open file.
5323 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5324 DEBUG(3, ("fstat of %s failed (%s)\n",
5325 fsp_fnum_dbg(fsp), strerror(errno)));
5326 reply_nterror(req,
5327 map_nt_error_from_unix(errno));
5328 return;
5330 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5331 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5334 } else {
5335 uint32_t name_hash;
5336 char *fname = NULL;
5337 uint32_t ucf_flags = 0;
5339 /* qpathinfo */
5340 if (total_params < 7) {
5341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5342 return;
5345 info_level = SVAL(params,0);
5347 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5349 if (INFO_LEVEL_IS_UNIX(info_level)) {
5350 if (!lp_unix_extensions()) {
5351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5352 return;
5354 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5355 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5356 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5357 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5361 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5362 total_params - 6,
5363 STR_TERMINATE, &status);
5364 if (!NT_STATUS_IS_OK(status)) {
5365 reply_nterror(req, status);
5366 return;
5369 status = filename_convert(req,
5370 conn,
5371 req->flags2 & FLAGS2_DFS_PATHNAMES,
5372 fname,
5373 ucf_flags,
5374 NULL,
5375 &smb_fname);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5378 reply_botherror(req,
5379 NT_STATUS_PATH_NOT_COVERED,
5380 ERRSRV, ERRbadpath);
5381 return;
5383 reply_nterror(req, status);
5384 return;
5387 /* If this is a stream, check if there is a delete_pending. */
5388 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5389 && is_ntfs_stream_smb_fname(smb_fname)) {
5390 struct smb_filename *smb_fname_base = NULL;
5392 /* Create an smb_filename with stream_name == NULL. */
5393 status =
5394 create_synthetic_smb_fname(talloc_tos(),
5395 smb_fname->base_name,
5396 NULL, NULL,
5397 &smb_fname_base);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 reply_nterror(req, status);
5400 return;
5403 if (INFO_LEVEL_IS_UNIX(info_level)) {
5404 /* Always do lstat for UNIX calls. */
5405 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5406 DEBUG(3,("call_trans2qfilepathinfo: "
5407 "SMB_VFS_LSTAT of %s failed "
5408 "(%s)\n",
5409 smb_fname_str_dbg(smb_fname_base),
5410 strerror(errno)));
5411 TALLOC_FREE(smb_fname_base);
5412 reply_nterror(req,
5413 map_nt_error_from_unix(errno));
5414 return;
5416 } else {
5417 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5418 DEBUG(3,("call_trans2qfilepathinfo: "
5419 "fileinfo of %s failed "
5420 "(%s)\n",
5421 smb_fname_str_dbg(smb_fname_base),
5422 strerror(errno)));
5423 TALLOC_FREE(smb_fname_base);
5424 reply_nterror(req,
5425 map_nt_error_from_unix(errno));
5426 return;
5430 status = file_name_hash(conn,
5431 smb_fname_str_dbg(smb_fname_base),
5432 &name_hash);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 TALLOC_FREE(smb_fname_base);
5435 reply_nterror(req, status);
5436 return;
5439 fileid = vfs_file_id_from_sbuf(conn,
5440 &smb_fname_base->st);
5441 TALLOC_FREE(smb_fname_base);
5442 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5443 if (delete_pending) {
5444 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5445 return;
5449 if (INFO_LEVEL_IS_UNIX(info_level)) {
5450 /* Always do lstat for UNIX calls. */
5451 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5452 DEBUG(3,("call_trans2qfilepathinfo: "
5453 "SMB_VFS_LSTAT of %s failed (%s)\n",
5454 smb_fname_str_dbg(smb_fname),
5455 strerror(errno)));
5456 reply_nterror(req,
5457 map_nt_error_from_unix(errno));
5458 return;
5461 } else {
5462 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5463 DEBUG(3,("call_trans2qfilepathinfo: "
5464 "SMB_VFS_STAT of %s failed (%s)\n",
5465 smb_fname_str_dbg(smb_fname),
5466 strerror(errno)));
5467 reply_nterror(req,
5468 map_nt_error_from_unix(errno));
5469 return;
5473 status = file_name_hash(conn,
5474 smb_fname_str_dbg(smb_fname),
5475 &name_hash);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 reply_nterror(req, status);
5478 return;
5481 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5482 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5483 if (delete_pending) {
5484 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5485 return;
5489 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5490 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5491 fsp_fnum_dbg(fsp),
5492 info_level,tran_call,total_data));
5494 /* Pull out any data sent here before we realloc. */
5495 switch (info_level) {
5496 case SMB_INFO_QUERY_EAS_FROM_LIST:
5498 /* Pull any EA list from the data portion. */
5499 uint32 ea_size;
5501 if (total_data < 4) {
5502 reply_nterror(
5503 req, NT_STATUS_INVALID_PARAMETER);
5504 return;
5506 ea_size = IVAL(pdata,0);
5508 if (total_data > 0 && ea_size != total_data) {
5509 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5510 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5511 reply_nterror(
5512 req, NT_STATUS_INVALID_PARAMETER);
5513 return;
5516 if (!lp_ea_support(SNUM(conn))) {
5517 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5518 return;
5521 /* Pull out the list of names. */
5522 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5523 if (!ea_list) {
5524 reply_nterror(
5525 req, NT_STATUS_INVALID_PARAMETER);
5526 return;
5528 break;
5531 case SMB_QUERY_POSIX_LOCK:
5533 if (fsp == NULL || fsp->fh->fd == -1) {
5534 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5535 return;
5538 if (total_data != POSIX_LOCK_DATA_SIZE) {
5539 reply_nterror(
5540 req, NT_STATUS_INVALID_PARAMETER);
5541 return;
5544 /* Copy the lock range data. */
5545 lock_data = (char *)talloc_memdup(
5546 req, pdata, total_data);
5547 if (!lock_data) {
5548 reply_nterror(req, NT_STATUS_NO_MEMORY);
5549 return;
5551 lock_data_count = total_data;
5553 default:
5554 break;
5557 *pparams = (char *)SMB_REALLOC(*pparams,2);
5558 if (*pparams == NULL) {
5559 reply_nterror(req, NT_STATUS_NO_MEMORY);
5560 return;
5562 params = *pparams;
5563 SSVAL(params,0,0);
5566 * draft-leach-cifs-v1-spec-02.txt
5567 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5568 * says:
5570 * The requested information is placed in the Data portion of the
5571 * transaction response. For the information levels greater than 0x100,
5572 * the transaction response has 1 parameter word which should be
5573 * ignored by the client.
5575 * However Windows only follows this rule for the IS_NAME_VALID call.
5577 switch (info_level) {
5578 case SMB_INFO_IS_NAME_VALID:
5579 param_size = 0;
5580 break;
5583 if ((info_level & 0xFF00) == 0xFF00) {
5585 * We use levels that start with 0xFF00
5586 * internally to represent SMB2 specific levels
5588 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5589 return;
5592 status = smbd_do_qfilepathinfo(conn, req, info_level,
5593 fsp, smb_fname,
5594 delete_pending, write_time_ts,
5595 ea_list,
5596 lock_data_count, lock_data,
5597 req->flags2, max_data_bytes,
5598 ppdata, &data_size);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 reply_nterror(req, status);
5601 return;
5604 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5605 max_data_bytes);
5607 return;
5610 /****************************************************************************
5611 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5612 code.
5613 ****************************************************************************/
5615 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5616 connection_struct *conn,
5617 struct smb_request *req,
5618 bool overwrite_if_exists,
5619 const struct smb_filename *smb_fname_old,
5620 struct smb_filename *smb_fname_new)
5622 NTSTATUS status = NT_STATUS_OK;
5624 /* source must already exist. */
5625 if (!VALID_STAT(smb_fname_old->st)) {
5626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5629 if (VALID_STAT(smb_fname_new->st)) {
5630 if (overwrite_if_exists) {
5631 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5632 return NT_STATUS_FILE_IS_A_DIRECTORY;
5634 status = unlink_internals(conn,
5635 req,
5636 FILE_ATTRIBUTE_NORMAL,
5637 smb_fname_new,
5638 false);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 return status;
5642 } else {
5643 /* Disallow if newname already exists. */
5644 return NT_STATUS_OBJECT_NAME_COLLISION;
5648 /* No links from a directory. */
5649 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5650 return NT_STATUS_FILE_IS_A_DIRECTORY;
5653 /* Setting a hardlink to/from a stream isn't currently supported. */
5654 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5655 is_ntfs_stream_smb_fname(smb_fname_new)) {
5656 return NT_STATUS_INVALID_PARAMETER;
5659 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5660 smb_fname_old->base_name, smb_fname_new->base_name));
5662 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5663 smb_fname_new->base_name) != 0) {
5664 status = map_nt_error_from_unix(errno);
5665 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5666 nt_errstr(status), smb_fname_old->base_name,
5667 smb_fname_new->base_name));
5669 return status;
5672 /****************************************************************************
5673 Deal with setting the time from any of the setfilepathinfo functions.
5674 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5675 calling this function.
5676 ****************************************************************************/
5678 NTSTATUS smb_set_file_time(connection_struct *conn,
5679 files_struct *fsp,
5680 const struct smb_filename *smb_fname,
5681 struct smb_file_time *ft,
5682 bool setting_write_time)
5684 struct smb_filename smb_fname_base;
5685 uint32 action =
5686 FILE_NOTIFY_CHANGE_LAST_ACCESS
5687 |FILE_NOTIFY_CHANGE_LAST_WRITE
5688 |FILE_NOTIFY_CHANGE_CREATION;
5690 if (!VALID_STAT(smb_fname->st)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5694 /* get some defaults (no modifications) if any info is zero or -1. */
5695 if (null_timespec(ft->create_time)) {
5696 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5699 if (null_timespec(ft->atime)) {
5700 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5703 if (null_timespec(ft->mtime)) {
5704 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5707 if (!setting_write_time) {
5708 /* ft->mtime comes from change time, not write time. */
5709 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5712 /* Ensure the resolution is the correct for
5713 * what we can store on this filesystem. */
5715 round_timespec(conn->ts_res, &ft->create_time);
5716 round_timespec(conn->ts_res, &ft->ctime);
5717 round_timespec(conn->ts_res, &ft->atime);
5718 round_timespec(conn->ts_res, &ft->mtime);
5720 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5721 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5722 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5723 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5724 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5725 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5726 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5727 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5729 if (setting_write_time) {
5731 * This was a Windows setfileinfo on an open file.
5732 * NT does this a lot. We also need to
5733 * set the time here, as it can be read by
5734 * FindFirst/FindNext and with the patch for bug #2045
5735 * in smbd/fileio.c it ensures that this timestamp is
5736 * kept sticky even after a write. We save the request
5737 * away and will set it on file close and after a write. JRA.
5740 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5741 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5743 if (fsp != NULL) {
5744 if (fsp->base_fsp) {
5745 set_sticky_write_time_fsp(fsp->base_fsp,
5746 ft->mtime);
5747 } else {
5748 set_sticky_write_time_fsp(fsp, ft->mtime);
5750 } else {
5751 set_sticky_write_time_path(
5752 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5753 ft->mtime);
5757 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5759 /* Always call ntimes on the base, even if a stream was passed in. */
5760 smb_fname_base = *smb_fname;
5761 smb_fname_base.stream_name = NULL;
5763 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5764 return map_nt_error_from_unix(errno);
5767 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5768 smb_fname->base_name);
5769 return NT_STATUS_OK;
5772 /****************************************************************************
5773 Deal with setting the dosmode from any of the setfilepathinfo functions.
5774 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5775 done before calling this function.
5776 ****************************************************************************/
5778 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5779 const struct smb_filename *smb_fname,
5780 uint32 dosmode)
5782 struct smb_filename *smb_fname_base = NULL;
5783 NTSTATUS status;
5785 if (!VALID_STAT(smb_fname->st)) {
5786 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789 /* Always operate on the base_name, even if a stream was passed in. */
5790 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5791 NULL, &smb_fname->st,
5792 &smb_fname_base);
5793 if (!NT_STATUS_IS_OK(status)) {
5794 return status;
5797 if (dosmode) {
5798 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5799 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5800 } else {
5801 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5805 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5807 /* check the mode isn't different, before changing it */
5808 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5809 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5810 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5811 (unsigned int)dosmode));
5813 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5814 false)) {
5815 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5816 "%s failed (%s)\n",
5817 smb_fname_str_dbg(smb_fname_base),
5818 strerror(errno)));
5819 status = map_nt_error_from_unix(errno);
5820 goto out;
5823 status = NT_STATUS_OK;
5824 out:
5825 TALLOC_FREE(smb_fname_base);
5826 return status;
5829 /****************************************************************************
5830 Deal with setting the size from any of the setfilepathinfo functions.
5831 ****************************************************************************/
5833 static NTSTATUS smb_set_file_size(connection_struct *conn,
5834 struct smb_request *req,
5835 files_struct *fsp,
5836 const struct smb_filename *smb_fname,
5837 const SMB_STRUCT_STAT *psbuf,
5838 off_t size,
5839 bool fail_after_createfile)
5841 NTSTATUS status = NT_STATUS_OK;
5842 struct smb_filename *smb_fname_tmp = NULL;
5843 files_struct *new_fsp = NULL;
5845 if (!VALID_STAT(*psbuf)) {
5846 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5849 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5851 if (size == get_file_size_stat(psbuf)) {
5852 return NT_STATUS_OK;
5855 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5856 smb_fname_str_dbg(smb_fname), (double)size));
5858 if (fsp && fsp->fh->fd != -1) {
5859 /* Handle based call. */
5860 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5861 return NT_STATUS_ACCESS_DENIED;
5864 if (vfs_set_filelen(fsp, size) == -1) {
5865 return map_nt_error_from_unix(errno);
5867 trigger_write_time_update_immediate(fsp);
5868 return NT_STATUS_OK;
5871 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 return status;
5876 smb_fname_tmp->st = *psbuf;
5878 status = SMB_VFS_CREATE_FILE(
5879 conn, /* conn */
5880 req, /* req */
5881 0, /* root_dir_fid */
5882 smb_fname_tmp, /* fname */
5883 FILE_WRITE_DATA, /* access_mask */
5884 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5885 FILE_SHARE_DELETE),
5886 FILE_OPEN, /* create_disposition*/
5887 0, /* create_options */
5888 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5889 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5890 0, /* allocation_size */
5891 0, /* private_flags */
5892 NULL, /* sd */
5893 NULL, /* ea_list */
5894 &new_fsp, /* result */
5895 NULL); /* pinfo */
5897 TALLOC_FREE(smb_fname_tmp);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 /* NB. We check for open_was_deferred in the caller. */
5901 return status;
5904 /* See RAW-SFILEINFO-END-OF-FILE */
5905 if (fail_after_createfile) {
5906 close_file(req, new_fsp,NORMAL_CLOSE);
5907 return NT_STATUS_INVALID_LEVEL;
5910 if (vfs_set_filelen(new_fsp, size) == -1) {
5911 status = map_nt_error_from_unix(errno);
5912 close_file(req, new_fsp,NORMAL_CLOSE);
5913 return status;
5916 trigger_write_time_update_immediate(new_fsp);
5917 close_file(req, new_fsp,NORMAL_CLOSE);
5918 return NT_STATUS_OK;
5921 /****************************************************************************
5922 Deal with SMB_INFO_SET_EA.
5923 ****************************************************************************/
5925 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5926 const char *pdata,
5927 int total_data,
5928 files_struct *fsp,
5929 const struct smb_filename *smb_fname)
5931 struct ea_list *ea_list = NULL;
5932 TALLOC_CTX *ctx = NULL;
5933 NTSTATUS status = NT_STATUS_OK;
5935 if (total_data < 10) {
5937 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5938 length. They seem to have no effect. Bug #3212. JRA */
5940 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5941 /* We're done. We only get EA info in this call. */
5942 return NT_STATUS_OK;
5945 return NT_STATUS_INVALID_PARAMETER;
5948 if (IVAL(pdata,0) > total_data) {
5949 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5950 IVAL(pdata,0), (unsigned int)total_data));
5951 return NT_STATUS_INVALID_PARAMETER;
5954 ctx = talloc_tos();
5955 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5956 if (!ea_list) {
5957 return NT_STATUS_INVALID_PARAMETER;
5960 status = set_ea(conn, fsp, smb_fname, ea_list);
5962 return status;
5965 /****************************************************************************
5966 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5967 ****************************************************************************/
5969 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5970 const char *pdata,
5971 int total_data,
5972 files_struct *fsp)
5974 struct ea_list *ea_list = NULL;
5975 NTSTATUS status;
5977 if (!fsp) {
5978 return NT_STATUS_INVALID_HANDLE;
5981 if (!lp_ea_support(SNUM(conn))) {
5982 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5983 "EA's not supported.\n",
5984 (unsigned int)total_data));
5985 return NT_STATUS_EAS_NOT_SUPPORTED;
5988 if (total_data < 10) {
5989 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5990 "too small.\n",
5991 (unsigned int)total_data));
5992 return NT_STATUS_INVALID_PARAMETER;
5995 ea_list = read_nttrans_ea_list(talloc_tos(),
5996 pdata,
5997 total_data);
5999 if (!ea_list) {
6000 return NT_STATUS_INVALID_PARAMETER;
6003 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6005 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6006 smb_fname_str_dbg(fsp->fsp_name),
6007 nt_errstr(status) ));
6009 return status;
6013 /****************************************************************************
6014 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6015 ****************************************************************************/
6017 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6018 const char *pdata,
6019 int total_data,
6020 files_struct *fsp,
6021 struct smb_filename *smb_fname)
6023 NTSTATUS status = NT_STATUS_OK;
6024 bool delete_on_close;
6025 uint32 dosmode = 0;
6027 if (total_data < 1) {
6028 return NT_STATUS_INVALID_PARAMETER;
6031 if (fsp == NULL) {
6032 return NT_STATUS_INVALID_HANDLE;
6035 delete_on_close = (CVAL(pdata,0) ? True : False);
6036 dosmode = dos_mode(conn, smb_fname);
6038 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6039 "delete_on_close = %u\n",
6040 smb_fname_str_dbg(smb_fname),
6041 (unsigned int)dosmode,
6042 (unsigned int)delete_on_close ));
6044 if (delete_on_close) {
6045 status = can_set_delete_on_close(fsp, dosmode);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 return status;
6051 /* The set is across all open files on this dev/inode pair. */
6052 if (!set_delete_on_close(fsp, delete_on_close,
6053 conn->session_info->security_token,
6054 conn->session_info->unix_token)) {
6055 return NT_STATUS_ACCESS_DENIED;
6057 return NT_STATUS_OK;
6060 /****************************************************************************
6061 Deal with SMB_FILE_POSITION_INFORMATION.
6062 ****************************************************************************/
6064 static NTSTATUS smb_file_position_information(connection_struct *conn,
6065 const char *pdata,
6066 int total_data,
6067 files_struct *fsp)
6069 uint64_t position_information;
6071 if (total_data < 8) {
6072 return NT_STATUS_INVALID_PARAMETER;
6075 if (fsp == NULL) {
6076 /* Ignore on pathname based set. */
6077 return NT_STATUS_OK;
6080 position_information = (uint64_t)IVAL(pdata,0);
6081 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6083 DEBUG(10,("smb_file_position_information: Set file position "
6084 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6085 (double)position_information));
6086 fsp->fh->position_information = position_information;
6087 return NT_STATUS_OK;
6090 /****************************************************************************
6091 Deal with SMB_FILE_MODE_INFORMATION.
6092 ****************************************************************************/
6094 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6095 const char *pdata,
6096 int total_data)
6098 uint32 mode;
6100 if (total_data < 4) {
6101 return NT_STATUS_INVALID_PARAMETER;
6103 mode = IVAL(pdata,0);
6104 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6105 return NT_STATUS_INVALID_PARAMETER;
6107 return NT_STATUS_OK;
6110 /****************************************************************************
6111 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6112 ****************************************************************************/
6114 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6115 struct smb_request *req,
6116 const char *pdata,
6117 int total_data,
6118 const struct smb_filename *smb_fname)
6120 char *link_target = NULL;
6121 const char *newname = smb_fname->base_name;
6122 TALLOC_CTX *ctx = talloc_tos();
6124 /* Set a symbolic link. */
6125 /* Don't allow this if follow links is false. */
6127 if (total_data == 0) {
6128 return NT_STATUS_INVALID_PARAMETER;
6131 if (!lp_symlinks(SNUM(conn))) {
6132 return NT_STATUS_ACCESS_DENIED;
6135 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6136 total_data, STR_TERMINATE);
6138 if (!link_target) {
6139 return NT_STATUS_INVALID_PARAMETER;
6142 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6143 newname, link_target ));
6145 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6146 return map_nt_error_from_unix(errno);
6149 return NT_STATUS_OK;
6152 /****************************************************************************
6153 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6154 ****************************************************************************/
6156 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6157 struct smb_request *req,
6158 const char *pdata, int total_data,
6159 struct smb_filename *smb_fname_new)
6161 char *oldname = NULL;
6162 struct smb_filename *smb_fname_old = NULL;
6163 TALLOC_CTX *ctx = talloc_tos();
6164 NTSTATUS status = NT_STATUS_OK;
6166 /* Set a hard link. */
6167 if (total_data == 0) {
6168 return NT_STATUS_INVALID_PARAMETER;
6171 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6172 total_data, STR_TERMINATE, &status);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 return status;
6177 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6178 smb_fname_str_dbg(smb_fname_new), oldname));
6180 status = filename_convert(ctx,
6181 conn,
6182 req->flags2 & FLAGS2_DFS_PATHNAMES,
6183 oldname,
6185 NULL,
6186 &smb_fname_old);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 return status;
6191 return hardlink_internals(ctx, conn, req, false,
6192 smb_fname_old, smb_fname_new);
6195 /****************************************************************************
6196 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6197 ****************************************************************************/
6199 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6200 struct smb_request *req,
6201 const char *pdata,
6202 int total_data,
6203 files_struct *fsp,
6204 struct smb_filename *smb_fname_src)
6206 bool overwrite;
6207 uint32_t len;
6208 char *newname = NULL;
6209 struct smb_filename *smb_fname_dst = NULL;
6210 NTSTATUS status = NT_STATUS_OK;
6211 TALLOC_CTX *ctx = talloc_tos();
6213 if (!fsp) {
6214 return NT_STATUS_INVALID_HANDLE;
6217 if (total_data < 20) {
6218 return NT_STATUS_INVALID_PARAMETER;
6221 overwrite = (CVAL(pdata,0) ? True : False);
6222 len = IVAL(pdata,16);
6224 if (len > (total_data - 20) || (len == 0)) {
6225 return NT_STATUS_INVALID_PARAMETER;
6228 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6229 &pdata[20], len, STR_TERMINATE,
6230 &status);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 return status;
6235 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6236 newname));
6238 status = filename_convert(ctx,
6239 conn,
6240 req->flags2 & FLAGS2_DFS_PATHNAMES,
6241 newname,
6242 UCF_SAVE_LCOMP,
6243 NULL,
6244 &smb_fname_dst);
6245 if (!NT_STATUS_IS_OK(status)) {
6246 return status;
6249 if (fsp->base_fsp) {
6250 /* newname must be a stream name. */
6251 if (newname[0] != ':') {
6252 return NT_STATUS_NOT_SUPPORTED;
6255 /* Create an smb_fname to call rename_internals_fsp() with. */
6256 status = create_synthetic_smb_fname(talloc_tos(),
6257 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6258 &smb_fname_dst);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 goto out;
6264 * Set the original last component, since
6265 * rename_internals_fsp() requires it.
6267 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6268 newname);
6269 if (smb_fname_dst->original_lcomp == NULL) {
6270 status = NT_STATUS_NO_MEMORY;
6271 goto out;
6276 DEBUG(10,("smb2_file_rename_information: "
6277 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6278 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6279 smb_fname_str_dbg(smb_fname_dst)));
6280 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6281 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6282 overwrite);
6284 out:
6285 TALLOC_FREE(smb_fname_dst);
6286 return status;
6289 static NTSTATUS smb_file_link_information(connection_struct *conn,
6290 struct smb_request *req,
6291 const char *pdata,
6292 int total_data,
6293 files_struct *fsp,
6294 struct smb_filename *smb_fname_src)
6296 bool overwrite;
6297 uint32_t len;
6298 char *newname = NULL;
6299 struct smb_filename *smb_fname_dst = NULL;
6300 NTSTATUS status = NT_STATUS_OK;
6301 TALLOC_CTX *ctx = talloc_tos();
6303 if (!fsp) {
6304 return NT_STATUS_INVALID_HANDLE;
6307 if (total_data < 20) {
6308 return NT_STATUS_INVALID_PARAMETER;
6311 overwrite = (CVAL(pdata,0) ? true : false);
6312 len = IVAL(pdata,16);
6314 if (len > (total_data - 20) || (len == 0)) {
6315 return NT_STATUS_INVALID_PARAMETER;
6318 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6319 &pdata[20], len, STR_TERMINATE,
6320 &status);
6321 if (!NT_STATUS_IS_OK(status)) {
6322 return status;
6325 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6326 newname));
6328 status = filename_convert(ctx,
6329 conn,
6330 req->flags2 & FLAGS2_DFS_PATHNAMES,
6331 newname,
6332 UCF_SAVE_LCOMP,
6333 NULL,
6334 &smb_fname_dst);
6335 if (!NT_STATUS_IS_OK(status)) {
6336 return status;
6339 if (fsp->base_fsp) {
6340 /* No stream names. */
6341 return NT_STATUS_NOT_SUPPORTED;
6344 DEBUG(10,("smb_file_link_information: "
6345 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6346 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6347 smb_fname_str_dbg(smb_fname_dst)));
6348 status = hardlink_internals(ctx,
6349 conn,
6350 req,
6351 overwrite,
6352 fsp->fsp_name,
6353 smb_fname_dst);
6355 TALLOC_FREE(smb_fname_dst);
6356 return status;
6359 /****************************************************************************
6360 Deal with SMB_FILE_RENAME_INFORMATION.
6361 ****************************************************************************/
6363 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6364 struct smb_request *req,
6365 const char *pdata,
6366 int total_data,
6367 files_struct *fsp,
6368 struct smb_filename *smb_fname_src)
6370 bool overwrite;
6371 uint32 root_fid;
6372 uint32 len;
6373 char *newname = NULL;
6374 struct smb_filename *smb_fname_dst = NULL;
6375 bool dest_has_wcard = False;
6376 NTSTATUS status = NT_STATUS_OK;
6377 char *p;
6378 TALLOC_CTX *ctx = talloc_tos();
6380 if (total_data < 13) {
6381 return NT_STATUS_INVALID_PARAMETER;
6384 overwrite = (CVAL(pdata,0) ? True : False);
6385 root_fid = IVAL(pdata,4);
6386 len = IVAL(pdata,8);
6388 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6389 return NT_STATUS_INVALID_PARAMETER;
6392 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6393 len, 0, &status,
6394 &dest_has_wcard);
6395 if (!NT_STATUS_IS_OK(status)) {
6396 return status;
6399 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6400 newname));
6402 status = resolve_dfspath_wcard(ctx, conn,
6403 req->flags2 & FLAGS2_DFS_PATHNAMES,
6404 newname,
6405 true,
6406 !conn->sconn->using_smb2,
6407 &newname,
6408 &dest_has_wcard);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 return status;
6413 /* Check the new name has no '/' characters. */
6414 if (strchr_m(newname, '/')) {
6415 return NT_STATUS_NOT_SUPPORTED;
6418 if (fsp && fsp->base_fsp) {
6419 /* newname must be a stream name. */
6420 if (newname[0] != ':') {
6421 return NT_STATUS_NOT_SUPPORTED;
6424 /* Create an smb_fname to call rename_internals_fsp() with. */
6425 status = create_synthetic_smb_fname(talloc_tos(),
6426 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6427 &smb_fname_dst);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 goto out;
6433 * Set the original last component, since
6434 * rename_internals_fsp() requires it.
6436 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6437 newname);
6438 if (smb_fname_dst->original_lcomp == NULL) {
6439 status = NT_STATUS_NO_MEMORY;
6440 goto out;
6443 } else {
6445 * Build up an smb_fname_dst based on the filename passed in.
6446 * We basically just strip off the last component, and put on
6447 * the newname instead.
6449 char *base_name = NULL;
6451 /* newname must *not* be a stream name. */
6452 if (newname[0] == ':') {
6453 return NT_STATUS_NOT_SUPPORTED;
6457 * Strip off the last component (filename) of the path passed
6458 * in.
6460 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6461 if (!base_name) {
6462 return NT_STATUS_NO_MEMORY;
6464 p = strrchr_m(base_name, '/');
6465 if (p) {
6466 p[1] = '\0';
6467 } else {
6468 base_name = talloc_strdup(ctx, "");
6469 if (!base_name) {
6470 return NT_STATUS_NO_MEMORY;
6473 /* Append the new name. */
6474 base_name = talloc_asprintf_append(base_name,
6475 "%s",
6476 newname);
6477 if (!base_name) {
6478 return NT_STATUS_NO_MEMORY;
6481 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6482 (UCF_SAVE_LCOMP |
6483 (dest_has_wcard ?
6484 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6485 0)));
6487 /* If an error we expect this to be
6488 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6490 if (!NT_STATUS_IS_OK(status)) {
6491 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6492 status)) {
6493 goto out;
6495 /* Create an smb_fname to call rename_internals_fsp() */
6496 status = create_synthetic_smb_fname(ctx,
6497 base_name, NULL,
6498 NULL,
6499 &smb_fname_dst);
6500 if (!NT_STATUS_IS_OK(status)) {
6501 goto out;
6506 if (fsp) {
6507 DEBUG(10,("smb_file_rename_information: "
6508 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6509 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6510 smb_fname_str_dbg(smb_fname_dst)));
6511 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6512 overwrite);
6513 } else {
6514 DEBUG(10,("smb_file_rename_information: "
6515 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6516 smb_fname_str_dbg(smb_fname_src),
6517 smb_fname_str_dbg(smb_fname_dst)));
6518 status = rename_internals(ctx, conn, req, smb_fname_src,
6519 smb_fname_dst, 0, overwrite, false,
6520 dest_has_wcard,
6521 FILE_WRITE_ATTRIBUTES);
6523 out:
6524 TALLOC_FREE(smb_fname_dst);
6525 return status;
6528 /****************************************************************************
6529 Deal with SMB_SET_POSIX_ACL.
6530 ****************************************************************************/
6532 #if defined(HAVE_POSIX_ACLS)
6533 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6534 const char *pdata,
6535 int total_data,
6536 files_struct *fsp,
6537 const struct smb_filename *smb_fname)
6539 uint16 posix_acl_version;
6540 uint16 num_file_acls;
6541 uint16 num_def_acls;
6542 bool valid_file_acls = True;
6543 bool valid_def_acls = True;
6545 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6546 return NT_STATUS_INVALID_PARAMETER;
6548 posix_acl_version = SVAL(pdata,0);
6549 num_file_acls = SVAL(pdata,2);
6550 num_def_acls = SVAL(pdata,4);
6552 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6553 valid_file_acls = False;
6554 num_file_acls = 0;
6557 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6558 valid_def_acls = False;
6559 num_def_acls = 0;
6562 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6563 return NT_STATUS_INVALID_PARAMETER;
6566 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6567 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6572 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6573 (unsigned int)num_file_acls,
6574 (unsigned int)num_def_acls));
6576 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6577 smb_fname->base_name, num_file_acls,
6578 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6579 return map_nt_error_from_unix(errno);
6582 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6583 smb_fname->base_name, &smb_fname->st, num_def_acls,
6584 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6585 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6586 return map_nt_error_from_unix(errno);
6588 return NT_STATUS_OK;
6590 #endif
6592 /****************************************************************************
6593 Deal with SMB_SET_POSIX_LOCK.
6594 ****************************************************************************/
6596 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6597 struct smb_request *req,
6598 const char *pdata,
6599 int total_data,
6600 files_struct *fsp)
6602 uint64_t count;
6603 uint64_t offset;
6604 uint64_t smblctx;
6605 bool blocking_lock = False;
6606 enum brl_type lock_type;
6608 NTSTATUS status = NT_STATUS_OK;
6610 if (fsp == NULL || fsp->fh->fd == -1) {
6611 return NT_STATUS_INVALID_HANDLE;
6614 if (total_data != POSIX_LOCK_DATA_SIZE) {
6615 return NT_STATUS_INVALID_PARAMETER;
6618 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6619 case POSIX_LOCK_TYPE_READ:
6620 lock_type = READ_LOCK;
6621 break;
6622 case POSIX_LOCK_TYPE_WRITE:
6623 /* Return the right POSIX-mappable error code for files opened read-only. */
6624 if (!fsp->can_write) {
6625 return NT_STATUS_INVALID_HANDLE;
6627 lock_type = WRITE_LOCK;
6628 break;
6629 case POSIX_LOCK_TYPE_UNLOCK:
6630 lock_type = UNLOCK_LOCK;
6631 break;
6632 default:
6633 return NT_STATUS_INVALID_PARAMETER;
6636 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6637 blocking_lock = False;
6638 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6639 blocking_lock = True;
6640 } else {
6641 return NT_STATUS_INVALID_PARAMETER;
6644 if (!lp_blocking_locks(SNUM(conn))) {
6645 blocking_lock = False;
6648 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6649 #if defined(HAVE_LONGLONG)
6650 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6651 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6652 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6653 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6654 #else /* HAVE_LONGLONG */
6655 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6656 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6657 #endif /* HAVE_LONGLONG */
6659 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6660 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6661 fsp_str_dbg(fsp),
6662 (unsigned int)lock_type,
6663 (unsigned long long)smblctx,
6664 (double)count,
6665 (double)offset ));
6667 if (lock_type == UNLOCK_LOCK) {
6668 status = do_unlock(req->sconn->msg_ctx,
6669 fsp,
6670 smblctx,
6671 count,
6672 offset,
6673 POSIX_LOCK);
6674 } else {
6675 uint64_t block_smblctx;
6677 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6678 fsp,
6679 smblctx,
6680 count,
6681 offset,
6682 lock_type,
6683 POSIX_LOCK,
6684 blocking_lock,
6685 &status,
6686 &block_smblctx,
6687 NULL);
6689 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6691 * A blocking lock was requested. Package up
6692 * this smb into a queued request and push it
6693 * onto the blocking lock queue.
6695 if(push_blocking_lock_request(br_lck,
6696 req,
6697 fsp,
6698 -1, /* infinite timeout. */
6700 smblctx,
6701 lock_type,
6702 POSIX_LOCK,
6703 offset,
6704 count,
6705 block_smblctx)) {
6706 TALLOC_FREE(br_lck);
6707 return status;
6710 TALLOC_FREE(br_lck);
6713 return status;
6716 /****************************************************************************
6717 Deal with SMB_SET_FILE_BASIC_INFO.
6718 ****************************************************************************/
6720 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6721 const char *pdata,
6722 int total_data,
6723 files_struct *fsp,
6724 const struct smb_filename *smb_fname)
6726 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6727 struct smb_file_time ft;
6728 uint32 dosmode = 0;
6729 NTSTATUS status = NT_STATUS_OK;
6731 ZERO_STRUCT(ft);
6733 if (total_data < 36) {
6734 return NT_STATUS_INVALID_PARAMETER;
6737 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6738 if (!NT_STATUS_IS_OK(status)) {
6739 return status;
6742 /* Set the attributes */
6743 dosmode = IVAL(pdata,32);
6744 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 return status;
6749 /* create time */
6750 ft.create_time = interpret_long_date(pdata);
6752 /* access time */
6753 ft.atime = interpret_long_date(pdata+8);
6755 /* write time. */
6756 ft.mtime = interpret_long_date(pdata+16);
6758 /* change time. */
6759 ft.ctime = interpret_long_date(pdata+24);
6761 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6762 smb_fname_str_dbg(smb_fname)));
6764 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6765 true);
6768 /****************************************************************************
6769 Deal with SMB_INFO_STANDARD.
6770 ****************************************************************************/
6772 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6773 const char *pdata,
6774 int total_data,
6775 files_struct *fsp,
6776 const struct smb_filename *smb_fname)
6778 NTSTATUS status;
6779 struct smb_file_time ft;
6781 ZERO_STRUCT(ft);
6783 if (total_data < 12) {
6784 return NT_STATUS_INVALID_PARAMETER;
6787 /* create time */
6788 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6789 /* access time */
6790 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6791 /* write time */
6792 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6794 DEBUG(10,("smb_set_info_standard: file %s\n",
6795 smb_fname_str_dbg(smb_fname)));
6797 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 return status;
6802 return smb_set_file_time(conn,
6803 fsp,
6804 smb_fname,
6805 &ft,
6806 true);
6809 /****************************************************************************
6810 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6811 ****************************************************************************/
6813 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6814 struct smb_request *req,
6815 const char *pdata,
6816 int total_data,
6817 files_struct *fsp,
6818 struct smb_filename *smb_fname)
6820 uint64_t allocation_size = 0;
6821 NTSTATUS status = NT_STATUS_OK;
6822 files_struct *new_fsp = NULL;
6824 if (!VALID_STAT(smb_fname->st)) {
6825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6828 if (total_data < 8) {
6829 return NT_STATUS_INVALID_PARAMETER;
6832 allocation_size = (uint64_t)IVAL(pdata,0);
6833 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6834 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6835 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6836 (double)allocation_size));
6838 if (allocation_size) {
6839 allocation_size = smb_roundup(conn, allocation_size);
6842 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6843 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6844 (double)allocation_size));
6846 if (fsp && fsp->fh->fd != -1) {
6847 /* Open file handle. */
6848 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6849 return NT_STATUS_ACCESS_DENIED;
6852 /* Only change if needed. */
6853 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6854 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6855 return map_nt_error_from_unix(errno);
6858 /* But always update the time. */
6860 * This is equivalent to a write. Ensure it's seen immediately
6861 * if there are no pending writes.
6863 trigger_write_time_update_immediate(fsp);
6864 return NT_STATUS_OK;
6867 /* Pathname or stat or directory file. */
6868 status = SMB_VFS_CREATE_FILE(
6869 conn, /* conn */
6870 req, /* req */
6871 0, /* root_dir_fid */
6872 smb_fname, /* fname */
6873 FILE_WRITE_DATA, /* access_mask */
6874 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6875 FILE_SHARE_DELETE),
6876 FILE_OPEN, /* create_disposition*/
6877 0, /* create_options */
6878 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6879 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6880 0, /* allocation_size */
6881 0, /* private_flags */
6882 NULL, /* sd */
6883 NULL, /* ea_list */
6884 &new_fsp, /* result */
6885 NULL); /* pinfo */
6887 if (!NT_STATUS_IS_OK(status)) {
6888 /* NB. We check for open_was_deferred in the caller. */
6889 return status;
6892 /* Only change if needed. */
6893 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6894 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6895 status = map_nt_error_from_unix(errno);
6896 close_file(req, new_fsp, NORMAL_CLOSE);
6897 return status;
6901 /* Changing the allocation size should set the last mod time. */
6903 * This is equivalent to a write. Ensure it's seen immediately
6904 * if there are no pending writes.
6906 trigger_write_time_update_immediate(new_fsp);
6908 close_file(req, new_fsp, NORMAL_CLOSE);
6909 return NT_STATUS_OK;
6912 /****************************************************************************
6913 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6914 ****************************************************************************/
6916 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6917 struct smb_request *req,
6918 const char *pdata,
6919 int total_data,
6920 files_struct *fsp,
6921 const struct smb_filename *smb_fname,
6922 bool fail_after_createfile)
6924 off_t size;
6926 if (total_data < 8) {
6927 return NT_STATUS_INVALID_PARAMETER;
6930 size = IVAL(pdata,0);
6931 size |= (((off_t)IVAL(pdata,4)) << 32);
6932 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6933 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6934 (double)size));
6936 return smb_set_file_size(conn, req,
6937 fsp,
6938 smb_fname,
6939 &smb_fname->st,
6940 size,
6941 fail_after_createfile);
6944 /****************************************************************************
6945 Allow a UNIX info mknod.
6946 ****************************************************************************/
6948 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6949 const char *pdata,
6950 int total_data,
6951 const struct smb_filename *smb_fname)
6953 uint32 file_type = IVAL(pdata,56);
6954 #if defined(HAVE_MAKEDEV)
6955 uint32 dev_major = IVAL(pdata,60);
6956 uint32 dev_minor = IVAL(pdata,68);
6957 #endif
6958 SMB_DEV_T dev = (SMB_DEV_T)0;
6959 uint32 raw_unixmode = IVAL(pdata,84);
6960 NTSTATUS status;
6961 mode_t unixmode;
6963 if (total_data < 100) {
6964 return NT_STATUS_INVALID_PARAMETER;
6967 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6968 PERM_NEW_FILE, &unixmode);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 return status;
6973 #if defined(HAVE_MAKEDEV)
6974 dev = makedev(dev_major, dev_minor);
6975 #endif
6977 switch (file_type) {
6978 #if defined(S_IFIFO)
6979 case UNIX_TYPE_FIFO:
6980 unixmode |= S_IFIFO;
6981 break;
6982 #endif
6983 #if defined(S_IFSOCK)
6984 case UNIX_TYPE_SOCKET:
6985 unixmode |= S_IFSOCK;
6986 break;
6987 #endif
6988 #if defined(S_IFCHR)
6989 case UNIX_TYPE_CHARDEV:
6990 unixmode |= S_IFCHR;
6991 break;
6992 #endif
6993 #if defined(S_IFBLK)
6994 case UNIX_TYPE_BLKDEV:
6995 unixmode |= S_IFBLK;
6996 break;
6997 #endif
6998 default:
6999 return NT_STATUS_INVALID_PARAMETER;
7002 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7003 "%.0f mode 0%o for file %s\n", (double)dev,
7004 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7006 /* Ok - do the mknod. */
7007 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7008 return map_nt_error_from_unix(errno);
7011 /* If any of the other "set" calls fail we
7012 * don't want to end up with a half-constructed mknod.
7015 if (lp_inherit_perms(SNUM(conn))) {
7016 char *parent;
7017 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7018 &parent, NULL)) {
7019 return NT_STATUS_NO_MEMORY;
7021 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7022 unixmode);
7023 TALLOC_FREE(parent);
7026 return NT_STATUS_OK;
7029 /****************************************************************************
7030 Deal with SMB_SET_FILE_UNIX_BASIC.
7031 ****************************************************************************/
7033 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7034 struct smb_request *req,
7035 const char *pdata,
7036 int total_data,
7037 files_struct *fsp,
7038 const struct smb_filename *smb_fname)
7040 struct smb_file_time ft;
7041 uint32 raw_unixmode;
7042 mode_t unixmode;
7043 off_t size = 0;
7044 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7045 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7046 NTSTATUS status = NT_STATUS_OK;
7047 bool delete_on_fail = False;
7048 enum perm_type ptype;
7049 files_struct *all_fsps = NULL;
7050 bool modify_mtime = true;
7051 struct file_id id;
7052 struct smb_filename *smb_fname_tmp = NULL;
7053 SMB_STRUCT_STAT sbuf;
7055 ZERO_STRUCT(ft);
7057 if (total_data < 100) {
7058 return NT_STATUS_INVALID_PARAMETER;
7061 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7062 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7063 size=IVAL(pdata,0); /* first 8 Bytes are size */
7064 size |= (((off_t)IVAL(pdata,4)) << 32);
7067 ft.atime = interpret_long_date(pdata+24); /* access_time */
7068 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7069 set_owner = (uid_t)IVAL(pdata,40);
7070 set_grp = (gid_t)IVAL(pdata,48);
7071 raw_unixmode = IVAL(pdata,84);
7073 if (VALID_STAT(smb_fname->st)) {
7074 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7075 ptype = PERM_EXISTING_DIR;
7076 } else {
7077 ptype = PERM_EXISTING_FILE;
7079 } else {
7080 ptype = PERM_NEW_FILE;
7083 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7084 ptype, &unixmode);
7085 if (!NT_STATUS_IS_OK(status)) {
7086 return status;
7089 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7090 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7091 smb_fname_str_dbg(smb_fname), (double)size,
7092 (unsigned int)set_owner, (unsigned int)set_grp,
7093 (int)raw_unixmode));
7095 sbuf = smb_fname->st;
7097 if (!VALID_STAT(sbuf)) {
7099 * The only valid use of this is to create character and block
7100 * devices, and named pipes. This is deprecated (IMHO) and
7101 * a new info level should be used for mknod. JRA.
7104 status = smb_unix_mknod(conn,
7105 pdata,
7106 total_data,
7107 smb_fname);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 return status;
7112 status = copy_smb_filename(talloc_tos(), smb_fname,
7113 &smb_fname_tmp);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 return status;
7118 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7119 status = map_nt_error_from_unix(errno);
7120 TALLOC_FREE(smb_fname_tmp);
7121 SMB_VFS_UNLINK(conn, smb_fname);
7122 return status;
7125 sbuf = smb_fname_tmp->st;
7126 smb_fname = smb_fname_tmp;
7128 /* Ensure we don't try and change anything else. */
7129 raw_unixmode = SMB_MODE_NO_CHANGE;
7130 size = get_file_size_stat(&sbuf);
7131 ft.atime = sbuf.st_ex_atime;
7132 ft.mtime = sbuf.st_ex_mtime;
7134 * We continue here as we might want to change the
7135 * owner uid/gid.
7137 delete_on_fail = True;
7140 #if 1
7141 /* Horrible backwards compatibility hack as an old server bug
7142 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7143 * */
7145 if (!size) {
7146 size = get_file_size_stat(&sbuf);
7148 #endif
7151 * Deal with the UNIX specific mode set.
7154 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7155 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7156 "setting mode 0%o for file %s\n",
7157 (unsigned int)unixmode,
7158 smb_fname_str_dbg(smb_fname)));
7159 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7160 return map_nt_error_from_unix(errno);
7165 * Deal with the UNIX specific uid set.
7168 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7169 (sbuf.st_ex_uid != set_owner)) {
7170 int ret;
7172 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7173 "changing owner %u for path %s\n",
7174 (unsigned int)set_owner,
7175 smb_fname_str_dbg(smb_fname)));
7177 if (S_ISLNK(sbuf.st_ex_mode)) {
7178 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7179 set_owner, (gid_t)-1);
7180 } else {
7181 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7182 set_owner, (gid_t)-1);
7185 if (ret != 0) {
7186 status = map_nt_error_from_unix(errno);
7187 if (delete_on_fail) {
7188 SMB_VFS_UNLINK(conn, smb_fname);
7190 return status;
7195 * Deal with the UNIX specific gid set.
7198 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7199 (sbuf.st_ex_gid != set_grp)) {
7200 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7201 "changing group %u for file %s\n",
7202 (unsigned int)set_owner,
7203 smb_fname_str_dbg(smb_fname)));
7204 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7205 set_grp) != 0) {
7206 status = map_nt_error_from_unix(errno);
7207 if (delete_on_fail) {
7208 SMB_VFS_UNLINK(conn, smb_fname);
7210 return status;
7214 /* Deal with any size changes. */
7216 status = smb_set_file_size(conn, req,
7217 fsp,
7218 smb_fname,
7219 &sbuf,
7220 size,
7221 false);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 return status;
7226 /* Deal with any time changes. */
7227 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7228 /* No change, don't cancel anything. */
7229 return status;
7232 id = vfs_file_id_from_sbuf(conn, &sbuf);
7233 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7234 all_fsps = file_find_di_next(all_fsps)) {
7236 * We're setting the time explicitly for UNIX.
7237 * Cancel any pending changes over all handles.
7239 all_fsps->update_write_time_on_close = false;
7240 TALLOC_FREE(all_fsps->update_write_time_event);
7244 * Override the "setting_write_time"
7245 * parameter here as it almost does what
7246 * we need. Just remember if we modified
7247 * mtime and send the notify ourselves.
7249 if (null_timespec(ft.mtime)) {
7250 modify_mtime = false;
7253 status = smb_set_file_time(conn,
7254 fsp,
7255 smb_fname,
7256 &ft,
7257 false);
7258 if (modify_mtime) {
7259 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7260 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7262 return status;
7265 /****************************************************************************
7266 Deal with SMB_SET_FILE_UNIX_INFO2.
7267 ****************************************************************************/
7269 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7270 struct smb_request *req,
7271 const char *pdata,
7272 int total_data,
7273 files_struct *fsp,
7274 const struct smb_filename *smb_fname)
7276 NTSTATUS status;
7277 uint32 smb_fflags;
7278 uint32 smb_fmask;
7280 if (total_data < 116) {
7281 return NT_STATUS_INVALID_PARAMETER;
7284 /* Start by setting all the fields that are common between UNIX_BASIC
7285 * and UNIX_INFO2.
7287 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7288 fsp, smb_fname);
7289 if (!NT_STATUS_IS_OK(status)) {
7290 return status;
7293 smb_fflags = IVAL(pdata, 108);
7294 smb_fmask = IVAL(pdata, 112);
7296 /* NB: We should only attempt to alter the file flags if the client
7297 * sends a non-zero mask.
7299 if (smb_fmask != 0) {
7300 int stat_fflags = 0;
7302 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7303 smb_fmask, &stat_fflags)) {
7304 /* Client asked to alter a flag we don't understand. */
7305 return NT_STATUS_INVALID_PARAMETER;
7308 if (fsp && fsp->fh->fd != -1) {
7309 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7310 return NT_STATUS_NOT_SUPPORTED;
7311 } else {
7312 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7313 stat_fflags) != 0) {
7314 return map_nt_error_from_unix(errno);
7319 /* XXX: need to add support for changing the create_time here. You
7320 * can do this for paths on Darwin with setattrlist(2). The right way
7321 * to hook this up is probably by extending the VFS utimes interface.
7324 return NT_STATUS_OK;
7327 /****************************************************************************
7328 Create a directory with POSIX semantics.
7329 ****************************************************************************/
7331 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7332 struct smb_request *req,
7333 char **ppdata,
7334 int total_data,
7335 struct smb_filename *smb_fname,
7336 int *pdata_return_size)
7338 NTSTATUS status = NT_STATUS_OK;
7339 uint32 raw_unixmode = 0;
7340 uint32 mod_unixmode = 0;
7341 mode_t unixmode = (mode_t)0;
7342 files_struct *fsp = NULL;
7343 uint16 info_level_return = 0;
7344 int info;
7345 char *pdata = *ppdata;
7347 if (total_data < 18) {
7348 return NT_STATUS_INVALID_PARAMETER;
7351 raw_unixmode = IVAL(pdata,8);
7352 /* Next 4 bytes are not yet defined. */
7354 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7355 PERM_NEW_DIR, &unixmode);
7356 if (!NT_STATUS_IS_OK(status)) {
7357 return status;
7360 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7362 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7363 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7365 status = SMB_VFS_CREATE_FILE(
7366 conn, /* conn */
7367 req, /* req */
7368 0, /* root_dir_fid */
7369 smb_fname, /* fname */
7370 FILE_READ_ATTRIBUTES, /* access_mask */
7371 FILE_SHARE_NONE, /* share_access */
7372 FILE_CREATE, /* create_disposition*/
7373 FILE_DIRECTORY_FILE, /* create_options */
7374 mod_unixmode, /* file_attributes */
7375 0, /* oplock_request */
7376 0, /* allocation_size */
7377 0, /* private_flags */
7378 NULL, /* sd */
7379 NULL, /* ea_list */
7380 &fsp, /* result */
7381 &info); /* pinfo */
7383 if (NT_STATUS_IS_OK(status)) {
7384 close_file(req, fsp, NORMAL_CLOSE);
7387 info_level_return = SVAL(pdata,16);
7389 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7390 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7391 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7392 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7393 } else {
7394 *pdata_return_size = 12;
7397 /* Realloc the data size */
7398 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7399 if (*ppdata == NULL) {
7400 *pdata_return_size = 0;
7401 return NT_STATUS_NO_MEMORY;
7403 pdata = *ppdata;
7405 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7406 SSVAL(pdata,2,0); /* No fnum. */
7407 SIVAL(pdata,4,info); /* Was directory created. */
7409 switch (info_level_return) {
7410 case SMB_QUERY_FILE_UNIX_BASIC:
7411 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7412 SSVAL(pdata,10,0); /* Padding. */
7413 store_file_unix_basic(conn, pdata + 12, fsp,
7414 &smb_fname->st);
7415 break;
7416 case SMB_QUERY_FILE_UNIX_INFO2:
7417 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7418 SSVAL(pdata,10,0); /* Padding. */
7419 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7420 &smb_fname->st);
7421 break;
7422 default:
7423 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7424 SSVAL(pdata,10,0); /* Padding. */
7425 break;
7428 return status;
7431 /****************************************************************************
7432 Open/Create a file with POSIX semantics.
7433 ****************************************************************************/
7435 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7436 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7438 static NTSTATUS smb_posix_open(connection_struct *conn,
7439 struct smb_request *req,
7440 char **ppdata,
7441 int total_data,
7442 struct smb_filename *smb_fname,
7443 int *pdata_return_size)
7445 bool extended_oplock_granted = False;
7446 char *pdata = *ppdata;
7447 uint32 flags = 0;
7448 uint32 wire_open_mode = 0;
7449 uint32 raw_unixmode = 0;
7450 uint32 mod_unixmode = 0;
7451 uint32 create_disp = 0;
7452 uint32 access_mask = 0;
7453 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7454 NTSTATUS status = NT_STATUS_OK;
7455 mode_t unixmode = (mode_t)0;
7456 files_struct *fsp = NULL;
7457 int oplock_request = 0;
7458 int info = 0;
7459 uint16 info_level_return = 0;
7461 if (total_data < 18) {
7462 return NT_STATUS_INVALID_PARAMETER;
7465 flags = IVAL(pdata,0);
7466 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7467 if (oplock_request) {
7468 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7471 wire_open_mode = IVAL(pdata,4);
7473 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7474 return smb_posix_mkdir(conn, req,
7475 ppdata,
7476 total_data,
7477 smb_fname,
7478 pdata_return_size);
7481 switch (wire_open_mode & SMB_ACCMODE) {
7482 case SMB_O_RDONLY:
7483 access_mask = SMB_O_RDONLY_MAPPING;
7484 break;
7485 case SMB_O_WRONLY:
7486 access_mask = SMB_O_WRONLY_MAPPING;
7487 break;
7488 case SMB_O_RDWR:
7489 access_mask = (SMB_O_RDONLY_MAPPING|
7490 SMB_O_WRONLY_MAPPING);
7491 break;
7492 default:
7493 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7494 (unsigned int)wire_open_mode ));
7495 return NT_STATUS_INVALID_PARAMETER;
7498 wire_open_mode &= ~SMB_ACCMODE;
7500 /* First take care of O_CREAT|O_EXCL interactions. */
7501 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7502 case (SMB_O_CREAT | SMB_O_EXCL):
7503 /* File exists fail. File not exist create. */
7504 create_disp = FILE_CREATE;
7505 break;
7506 case SMB_O_CREAT:
7507 /* File exists open. File not exist create. */
7508 create_disp = FILE_OPEN_IF;
7509 break;
7510 case SMB_O_EXCL:
7511 /* O_EXCL on its own without O_CREAT is undefined.
7512 We deliberately ignore it as some versions of
7513 Linux CIFSFS can send a bare O_EXCL on the
7514 wire which other filesystems in the kernel
7515 ignore. See bug 9519 for details. */
7517 /* Fallthrough. */
7519 case 0:
7520 /* File exists open. File not exist fail. */
7521 create_disp = FILE_OPEN;
7522 break;
7523 default:
7524 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7525 (unsigned int)wire_open_mode ));
7526 return NT_STATUS_INVALID_PARAMETER;
7529 /* Next factor in the effects of O_TRUNC. */
7530 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7532 if (wire_open_mode & SMB_O_TRUNC) {
7533 switch (create_disp) {
7534 case FILE_CREATE:
7535 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7536 /* Leave create_disp alone as
7537 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7539 /* File exists fail. File not exist create. */
7540 break;
7541 case FILE_OPEN_IF:
7542 /* SMB_O_CREAT | SMB_O_TRUNC */
7543 /* File exists overwrite. File not exist create. */
7544 create_disp = FILE_OVERWRITE_IF;
7545 break;
7546 case FILE_OPEN:
7547 /* SMB_O_TRUNC */
7548 /* File exists overwrite. File not exist fail. */
7549 create_disp = FILE_OVERWRITE;
7550 break;
7551 default:
7552 /* Cannot get here. */
7553 smb_panic("smb_posix_open: logic error");
7554 return NT_STATUS_INVALID_PARAMETER;
7558 raw_unixmode = IVAL(pdata,8);
7559 /* Next 4 bytes are not yet defined. */
7561 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7562 (VALID_STAT(smb_fname->st) ?
7563 PERM_EXISTING_FILE : PERM_NEW_FILE),
7564 &unixmode);
7566 if (!NT_STATUS_IS_OK(status)) {
7567 return status;
7570 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7572 if (wire_open_mode & SMB_O_SYNC) {
7573 create_options |= FILE_WRITE_THROUGH;
7575 if (wire_open_mode & SMB_O_APPEND) {
7576 access_mask |= FILE_APPEND_DATA;
7578 if (wire_open_mode & SMB_O_DIRECT) {
7579 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7582 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7583 VALID_STAT_OF_DIR(smb_fname->st)) {
7584 if (access_mask != SMB_O_RDONLY_MAPPING) {
7585 return NT_STATUS_FILE_IS_A_DIRECTORY;
7587 create_options &= ~FILE_NON_DIRECTORY_FILE;
7588 create_options |= FILE_DIRECTORY_FILE;
7591 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7592 smb_fname_str_dbg(smb_fname),
7593 (unsigned int)wire_open_mode,
7594 (unsigned int)unixmode ));
7596 status = SMB_VFS_CREATE_FILE(
7597 conn, /* conn */
7598 req, /* req */
7599 0, /* root_dir_fid */
7600 smb_fname, /* fname */
7601 access_mask, /* access_mask */
7602 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7603 FILE_SHARE_DELETE),
7604 create_disp, /* create_disposition*/
7605 create_options, /* create_options */
7606 mod_unixmode, /* file_attributes */
7607 oplock_request, /* oplock_request */
7608 0, /* allocation_size */
7609 0, /* private_flags */
7610 NULL, /* sd */
7611 NULL, /* ea_list */
7612 &fsp, /* result */
7613 &info); /* pinfo */
7615 if (!NT_STATUS_IS_OK(status)) {
7616 return status;
7619 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7620 extended_oplock_granted = True;
7623 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7624 extended_oplock_granted = True;
7627 info_level_return = SVAL(pdata,16);
7629 /* Allocate the correct return size. */
7631 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7632 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7633 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7634 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7635 } else {
7636 *pdata_return_size = 12;
7639 /* Realloc the data size */
7640 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7641 if (*ppdata == NULL) {
7642 close_file(req, fsp, ERROR_CLOSE);
7643 *pdata_return_size = 0;
7644 return NT_STATUS_NO_MEMORY;
7646 pdata = *ppdata;
7648 if (extended_oplock_granted) {
7649 if (flags & REQUEST_BATCH_OPLOCK) {
7650 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7651 } else {
7652 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7654 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7655 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7656 } else {
7657 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7660 SSVAL(pdata,2,fsp->fnum);
7661 SIVAL(pdata,4,info); /* Was file created etc. */
7663 switch (info_level_return) {
7664 case SMB_QUERY_FILE_UNIX_BASIC:
7665 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7666 SSVAL(pdata,10,0); /* padding. */
7667 store_file_unix_basic(conn, pdata + 12, fsp,
7668 &smb_fname->st);
7669 break;
7670 case SMB_QUERY_FILE_UNIX_INFO2:
7671 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7672 SSVAL(pdata,10,0); /* padding. */
7673 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7674 &smb_fname->st);
7675 break;
7676 default:
7677 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7678 SSVAL(pdata,10,0); /* padding. */
7679 break;
7681 return NT_STATUS_OK;
7684 /****************************************************************************
7685 Delete a file with POSIX semantics.
7686 ****************************************************************************/
7688 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7689 struct smb_request *req,
7690 const char *pdata,
7691 int total_data,
7692 struct smb_filename *smb_fname)
7694 NTSTATUS status = NT_STATUS_OK;
7695 files_struct *fsp = NULL;
7696 uint16 flags = 0;
7697 char del = 1;
7698 int info = 0;
7699 int create_options = 0;
7700 int i;
7701 struct share_mode_lock *lck = NULL;
7703 if (total_data < 2) {
7704 return NT_STATUS_INVALID_PARAMETER;
7707 flags = SVAL(pdata,0);
7709 if (!VALID_STAT(smb_fname->st)) {
7710 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7713 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7714 !VALID_STAT_OF_DIR(smb_fname->st)) {
7715 return NT_STATUS_NOT_A_DIRECTORY;
7718 DEBUG(10,("smb_posix_unlink: %s %s\n",
7719 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7720 smb_fname_str_dbg(smb_fname)));
7722 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7723 create_options |= FILE_DIRECTORY_FILE;
7726 status = SMB_VFS_CREATE_FILE(
7727 conn, /* conn */
7728 req, /* req */
7729 0, /* root_dir_fid */
7730 smb_fname, /* fname */
7731 DELETE_ACCESS, /* access_mask */
7732 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7733 FILE_SHARE_DELETE),
7734 FILE_OPEN, /* create_disposition*/
7735 create_options, /* create_options */
7736 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7737 0, /* oplock_request */
7738 0, /* allocation_size */
7739 0, /* private_flags */
7740 NULL, /* sd */
7741 NULL, /* ea_list */
7742 &fsp, /* result */
7743 &info); /* pinfo */
7745 if (!NT_STATUS_IS_OK(status)) {
7746 return status;
7750 * Don't lie to client. If we can't really delete due to
7751 * non-POSIX opens return SHARING_VIOLATION.
7754 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7755 if (lck == NULL) {
7756 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7757 "lock for file %s\n", fsp_str_dbg(fsp)));
7758 close_file(req, fsp, NORMAL_CLOSE);
7759 return NT_STATUS_INVALID_PARAMETER;
7763 * See if others still have the file open. If this is the case, then
7764 * don't delete. If all opens are POSIX delete we can set the delete
7765 * on close disposition.
7767 for (i=0; i<lck->data->num_share_modes; i++) {
7768 struct share_mode_entry *e = &lck->data->share_modes[i];
7769 if (is_valid_share_mode_entry(e)) {
7770 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7771 continue;
7773 if (share_mode_stale_pid(lck->data, i)) {
7774 continue;
7776 /* Fail with sharing violation. */
7777 TALLOC_FREE(lck);
7778 close_file(req, fsp, NORMAL_CLOSE);
7779 return NT_STATUS_SHARING_VIOLATION;
7784 * Set the delete on close.
7786 status = smb_set_file_disposition_info(conn,
7787 &del,
7789 fsp,
7790 smb_fname);
7792 TALLOC_FREE(lck);
7794 if (!NT_STATUS_IS_OK(status)) {
7795 close_file(req, fsp, NORMAL_CLOSE);
7796 return status;
7798 return close_file(req, fsp, NORMAL_CLOSE);
7801 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7802 struct smb_request *req,
7803 TALLOC_CTX *mem_ctx,
7804 uint16_t info_level,
7805 files_struct *fsp,
7806 struct smb_filename *smb_fname,
7807 char **ppdata, int total_data,
7808 int *ret_data_size)
7810 char *pdata = *ppdata;
7811 NTSTATUS status = NT_STATUS_OK;
7812 int data_return_size = 0;
7814 *ret_data_size = 0;
7816 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7817 return NT_STATUS_INVALID_LEVEL;
7820 if (!CAN_WRITE(conn)) {
7821 /* Allow POSIX opens. The open path will deny
7822 * any non-readonly opens. */
7823 if (info_level != SMB_POSIX_PATH_OPEN) {
7824 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7828 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7829 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7830 fsp_fnum_dbg(fsp),
7831 info_level, total_data));
7833 switch (info_level) {
7835 case SMB_INFO_STANDARD:
7837 status = smb_set_info_standard(conn,
7838 pdata,
7839 total_data,
7840 fsp,
7841 smb_fname);
7842 break;
7845 case SMB_INFO_SET_EA:
7847 status = smb_info_set_ea(conn,
7848 pdata,
7849 total_data,
7850 fsp,
7851 smb_fname);
7852 break;
7855 case SMB_SET_FILE_BASIC_INFO:
7856 case SMB_FILE_BASIC_INFORMATION:
7858 status = smb_set_file_basic_info(conn,
7859 pdata,
7860 total_data,
7861 fsp,
7862 smb_fname);
7863 break;
7866 case SMB_FILE_ALLOCATION_INFORMATION:
7867 case SMB_SET_FILE_ALLOCATION_INFO:
7869 status = smb_set_file_allocation_info(conn, req,
7870 pdata,
7871 total_data,
7872 fsp,
7873 smb_fname);
7874 break;
7877 case SMB_FILE_END_OF_FILE_INFORMATION:
7878 case SMB_SET_FILE_END_OF_FILE_INFO:
7881 * XP/Win7 both fail after the createfile with
7882 * SMB_SET_FILE_END_OF_FILE_INFO but not
7883 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7884 * The level is known here, so pass it down
7885 * appropriately.
7887 bool should_fail =
7888 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7890 status = smb_set_file_end_of_file_info(conn, req,
7891 pdata,
7892 total_data,
7893 fsp,
7894 smb_fname,
7895 should_fail);
7896 break;
7899 case SMB_FILE_DISPOSITION_INFORMATION:
7900 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7902 #if 0
7903 /* JRA - We used to just ignore this on a path ?
7904 * Shouldn't this be invalid level on a pathname
7905 * based call ?
7907 if (tran_call != TRANSACT2_SETFILEINFO) {
7908 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7910 #endif
7911 status = smb_set_file_disposition_info(conn,
7912 pdata,
7913 total_data,
7914 fsp,
7915 smb_fname);
7916 break;
7919 case SMB_FILE_POSITION_INFORMATION:
7921 status = smb_file_position_information(conn,
7922 pdata,
7923 total_data,
7924 fsp);
7925 break;
7928 case SMB_FILE_FULL_EA_INFORMATION:
7930 status = smb_set_file_full_ea_info(conn,
7931 pdata,
7932 total_data,
7933 fsp);
7934 break;
7937 /* From tridge Samba4 :
7938 * MODE_INFORMATION in setfileinfo (I have no
7939 * idea what "mode information" on a file is - it takes a value of 0,
7940 * 2, 4 or 6. What could it be?).
7943 case SMB_FILE_MODE_INFORMATION:
7945 status = smb_file_mode_information(conn,
7946 pdata,
7947 total_data);
7948 break;
7952 * CIFS UNIX extensions.
7955 case SMB_SET_FILE_UNIX_BASIC:
7957 status = smb_set_file_unix_basic(conn, req,
7958 pdata,
7959 total_data,
7960 fsp,
7961 smb_fname);
7962 break;
7965 case SMB_SET_FILE_UNIX_INFO2:
7967 status = smb_set_file_unix_info2(conn, req,
7968 pdata,
7969 total_data,
7970 fsp,
7971 smb_fname);
7972 break;
7975 case SMB_SET_FILE_UNIX_LINK:
7977 if (fsp) {
7978 /* We must have a pathname for this. */
7979 return NT_STATUS_INVALID_LEVEL;
7981 status = smb_set_file_unix_link(conn, req, pdata,
7982 total_data, smb_fname);
7983 break;
7986 case SMB_SET_FILE_UNIX_HLINK:
7988 if (fsp) {
7989 /* We must have a pathname for this. */
7990 return NT_STATUS_INVALID_LEVEL;
7992 status = smb_set_file_unix_hlink(conn, req,
7993 pdata, total_data,
7994 smb_fname);
7995 break;
7998 case SMB_FILE_RENAME_INFORMATION:
8000 status = smb_file_rename_information(conn, req,
8001 pdata, total_data,
8002 fsp, smb_fname);
8003 break;
8006 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8008 /* SMB2 rename information. */
8009 status = smb2_file_rename_information(conn, req,
8010 pdata, total_data,
8011 fsp, smb_fname);
8012 break;
8015 case SMB_FILE_LINK_INFORMATION:
8017 status = smb_file_link_information(conn, req,
8018 pdata, total_data,
8019 fsp, smb_fname);
8020 break;
8023 #if defined(HAVE_POSIX_ACLS)
8024 case SMB_SET_POSIX_ACL:
8026 status = smb_set_posix_acl(conn,
8027 pdata,
8028 total_data,
8029 fsp,
8030 smb_fname);
8031 break;
8033 #endif
8035 case SMB_SET_POSIX_LOCK:
8037 if (!fsp) {
8038 return NT_STATUS_INVALID_LEVEL;
8040 status = smb_set_posix_lock(conn, req,
8041 pdata, total_data, fsp);
8042 break;
8045 case SMB_POSIX_PATH_OPEN:
8047 if (fsp) {
8048 /* We must have a pathname for this. */
8049 return NT_STATUS_INVALID_LEVEL;
8052 status = smb_posix_open(conn, req,
8053 ppdata,
8054 total_data,
8055 smb_fname,
8056 &data_return_size);
8057 break;
8060 case SMB_POSIX_PATH_UNLINK:
8062 if (fsp) {
8063 /* We must have a pathname for this. */
8064 return NT_STATUS_INVALID_LEVEL;
8067 status = smb_posix_unlink(conn, req,
8068 pdata,
8069 total_data,
8070 smb_fname);
8071 break;
8074 default:
8075 return NT_STATUS_INVALID_LEVEL;
8078 if (!NT_STATUS_IS_OK(status)) {
8079 return status;
8082 *ret_data_size = data_return_size;
8083 return NT_STATUS_OK;
8086 /****************************************************************************
8087 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8088 ****************************************************************************/
8090 static void call_trans2setfilepathinfo(connection_struct *conn,
8091 struct smb_request *req,
8092 unsigned int tran_call,
8093 char **pparams, int total_params,
8094 char **ppdata, int total_data,
8095 unsigned int max_data_bytes)
8097 char *params = *pparams;
8098 char *pdata = *ppdata;
8099 uint16 info_level;
8100 struct smb_filename *smb_fname = NULL;
8101 files_struct *fsp = NULL;
8102 NTSTATUS status = NT_STATUS_OK;
8103 int data_return_size = 0;
8105 if (!params) {
8106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8107 return;
8110 if (tran_call == TRANSACT2_SETFILEINFO) {
8111 if (total_params < 4) {
8112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8113 return;
8116 fsp = file_fsp(req, SVAL(params,0));
8117 /* Basic check for non-null fsp. */
8118 if (!check_fsp_open(conn, req, fsp)) {
8119 return;
8121 info_level = SVAL(params,2);
8123 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8124 &smb_fname);
8125 if (!NT_STATUS_IS_OK(status)) {
8126 reply_nterror(req, status);
8127 return;
8130 if(fsp->fh->fd == -1) {
8132 * This is actually a SETFILEINFO on a directory
8133 * handle (returned from an NT SMB). NT5.0 seems
8134 * to do this call. JRA.
8136 if (INFO_LEVEL_IS_UNIX(info_level)) {
8137 /* Always do lstat for UNIX calls. */
8138 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8139 DEBUG(3,("call_trans2setfilepathinfo: "
8140 "SMB_VFS_LSTAT of %s failed "
8141 "(%s)\n",
8142 smb_fname_str_dbg(smb_fname),
8143 strerror(errno)));
8144 reply_nterror(req, map_nt_error_from_unix(errno));
8145 return;
8147 } else {
8148 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8149 DEBUG(3,("call_trans2setfilepathinfo: "
8150 "fileinfo of %s failed (%s)\n",
8151 smb_fname_str_dbg(smb_fname),
8152 strerror(errno)));
8153 reply_nterror(req, map_nt_error_from_unix(errno));
8154 return;
8157 } else if (fsp->print_file) {
8159 * Doing a DELETE_ON_CLOSE should cancel a print job.
8161 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8162 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8164 DEBUG(3,("call_trans2setfilepathinfo: "
8165 "Cancelling print job (%s)\n",
8166 fsp_str_dbg(fsp)));
8168 SSVAL(params,0,0);
8169 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8170 *ppdata, 0,
8171 max_data_bytes);
8172 return;
8173 } else {
8174 reply_nterror(req,
8175 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8176 return;
8178 } else {
8180 * Original code - this is an open file.
8182 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8183 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8184 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8185 strerror(errno)));
8186 reply_nterror(req, map_nt_error_from_unix(errno));
8187 return;
8190 } else {
8191 char *fname = NULL;
8192 uint32_t ucf_flags = 0;
8194 /* set path info */
8195 if (total_params < 7) {
8196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8197 return;
8200 info_level = SVAL(params,0);
8201 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8202 total_params - 6, STR_TERMINATE,
8203 &status);
8204 if (!NT_STATUS_IS_OK(status)) {
8205 reply_nterror(req, status);
8206 return;
8209 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8210 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8211 info_level == SMB_FILE_RENAME_INFORMATION ||
8212 info_level == SMB_POSIX_PATH_UNLINK) {
8213 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8216 status = filename_convert(req, conn,
8217 req->flags2 & FLAGS2_DFS_PATHNAMES,
8218 fname,
8219 ucf_flags,
8220 NULL,
8221 &smb_fname);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8224 reply_botherror(req,
8225 NT_STATUS_PATH_NOT_COVERED,
8226 ERRSRV, ERRbadpath);
8227 return;
8229 reply_nterror(req, status);
8230 return;
8233 if (INFO_LEVEL_IS_UNIX(info_level)) {
8235 * For CIFS UNIX extensions the target name may not exist.
8238 /* Always do lstat for UNIX calls. */
8239 SMB_VFS_LSTAT(conn, smb_fname);
8241 } else if (!VALID_STAT(smb_fname->st) &&
8242 SMB_VFS_STAT(conn, smb_fname)) {
8243 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8244 "%s failed (%s)\n",
8245 smb_fname_str_dbg(smb_fname),
8246 strerror(errno)));
8247 reply_nterror(req, map_nt_error_from_unix(errno));
8248 return;
8252 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8253 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8254 fsp_fnum_dbg(fsp),
8255 info_level,total_data));
8257 /* Realloc the parameter size */
8258 *pparams = (char *)SMB_REALLOC(*pparams,2);
8259 if (*pparams == NULL) {
8260 reply_nterror(req, NT_STATUS_NO_MEMORY);
8261 return;
8263 params = *pparams;
8265 SSVAL(params,0,0);
8267 status = smbd_do_setfilepathinfo(conn, req, req,
8268 info_level,
8269 fsp,
8270 smb_fname,
8271 ppdata, total_data,
8272 &data_return_size);
8273 if (!NT_STATUS_IS_OK(status)) {
8274 if (open_was_deferred(req->sconn, req->mid)) {
8275 /* We have re-scheduled this call. */
8276 return;
8278 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8279 /* We have re-scheduled this call. */
8280 return;
8282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8283 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8284 ERRSRV, ERRbadpath);
8285 return;
8287 if (info_level == SMB_POSIX_PATH_OPEN) {
8288 reply_openerror(req, status);
8289 return;
8293 * Invalid EA name needs to return 2 param bytes,
8294 * not a zero-length error packet.
8296 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8297 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8298 max_data_bytes);
8299 } else {
8300 reply_nterror(req, status);
8302 return;
8305 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8306 max_data_bytes);
8308 return;
8311 /****************************************************************************
8312 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8313 ****************************************************************************/
8315 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8316 char **pparams, int total_params,
8317 char **ppdata, int total_data,
8318 unsigned int max_data_bytes)
8320 struct smb_filename *smb_dname = NULL;
8321 char *params = *pparams;
8322 char *pdata = *ppdata;
8323 char *directory = NULL;
8324 NTSTATUS status = NT_STATUS_OK;
8325 struct ea_list *ea_list = NULL;
8326 TALLOC_CTX *ctx = talloc_tos();
8328 if (!CAN_WRITE(conn)) {
8329 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8330 return;
8333 if (total_params < 5) {
8334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8335 return;
8338 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8339 total_params - 4, STR_TERMINATE,
8340 &status);
8341 if (!NT_STATUS_IS_OK(status)) {
8342 reply_nterror(req, status);
8343 return;
8346 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8348 status = filename_convert(ctx,
8349 conn,
8350 req->flags2 & FLAGS2_DFS_PATHNAMES,
8351 directory,
8353 NULL,
8354 &smb_dname);
8356 if (!NT_STATUS_IS_OK(status)) {
8357 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8358 reply_botherror(req,
8359 NT_STATUS_PATH_NOT_COVERED,
8360 ERRSRV, ERRbadpath);
8361 return;
8363 reply_nterror(req, status);
8364 return;
8368 * OS/2 workplace shell seems to send SET_EA requests of "null"
8369 * length (4 bytes containing IVAL 4).
8370 * They seem to have no effect. Bug #3212. JRA.
8373 if (total_data && (total_data != 4)) {
8374 /* Any data in this call is an EA list. */
8375 if (total_data < 10) {
8376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8377 goto out;
8380 if (IVAL(pdata,0) > total_data) {
8381 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8382 IVAL(pdata,0), (unsigned int)total_data));
8383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8384 goto out;
8387 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8388 total_data - 4);
8389 if (!ea_list) {
8390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8391 goto out;
8394 if (!lp_ea_support(SNUM(conn))) {
8395 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8396 goto out;
8399 /* If total_data == 4 Windows doesn't care what values
8400 * are placed in that field, it just ignores them.
8401 * The System i QNTC IBM SMB client puts bad values here,
8402 * so ignore them. */
8404 status = create_directory(conn, req, smb_dname);
8406 if (!NT_STATUS_IS_OK(status)) {
8407 reply_nterror(req, status);
8408 goto out;
8411 /* Try and set any given EA. */
8412 if (ea_list) {
8413 status = set_ea(conn, NULL, smb_dname, ea_list);
8414 if (!NT_STATUS_IS_OK(status)) {
8415 reply_nterror(req, status);
8416 goto out;
8420 /* Realloc the parameter and data sizes */
8421 *pparams = (char *)SMB_REALLOC(*pparams,2);
8422 if(*pparams == NULL) {
8423 reply_nterror(req, NT_STATUS_NO_MEMORY);
8424 goto out;
8426 params = *pparams;
8428 SSVAL(params,0,0);
8430 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8432 out:
8433 TALLOC_FREE(smb_dname);
8434 return;
8437 /****************************************************************************
8438 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8439 We don't actually do this - we just send a null response.
8440 ****************************************************************************/
8442 static void call_trans2findnotifyfirst(connection_struct *conn,
8443 struct smb_request *req,
8444 char **pparams, int total_params,
8445 char **ppdata, int total_data,
8446 unsigned int max_data_bytes)
8448 char *params = *pparams;
8449 uint16 info_level;
8451 if (total_params < 6) {
8452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8453 return;
8456 info_level = SVAL(params,4);
8457 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8459 switch (info_level) {
8460 case 1:
8461 case 2:
8462 break;
8463 default:
8464 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8465 return;
8468 /* Realloc the parameter and data sizes */
8469 *pparams = (char *)SMB_REALLOC(*pparams,6);
8470 if (*pparams == NULL) {
8471 reply_nterror(req, NT_STATUS_NO_MEMORY);
8472 return;
8474 params = *pparams;
8476 SSVAL(params,0,fnf_handle);
8477 SSVAL(params,2,0); /* No changes */
8478 SSVAL(params,4,0); /* No EA errors */
8480 fnf_handle++;
8482 if(fnf_handle == 0)
8483 fnf_handle = 257;
8485 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8487 return;
8490 /****************************************************************************
8491 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8492 changes). Currently this does nothing.
8493 ****************************************************************************/
8495 static void call_trans2findnotifynext(connection_struct *conn,
8496 struct smb_request *req,
8497 char **pparams, int total_params,
8498 char **ppdata, int total_data,
8499 unsigned int max_data_bytes)
8501 char *params = *pparams;
8503 DEBUG(3,("call_trans2findnotifynext\n"));
8505 /* Realloc the parameter and data sizes */
8506 *pparams = (char *)SMB_REALLOC(*pparams,4);
8507 if (*pparams == NULL) {
8508 reply_nterror(req, NT_STATUS_NO_MEMORY);
8509 return;
8511 params = *pparams;
8513 SSVAL(params,0,0); /* No changes */
8514 SSVAL(params,2,0); /* No EA errors */
8516 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8518 return;
8521 /****************************************************************************
8522 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8523 ****************************************************************************/
8525 static void call_trans2getdfsreferral(connection_struct *conn,
8526 struct smb_request *req,
8527 char **pparams, int total_params,
8528 char **ppdata, int total_data,
8529 unsigned int max_data_bytes)
8531 char *params = *pparams;
8532 char *pathname = NULL;
8533 int reply_size = 0;
8534 int max_referral_level;
8535 NTSTATUS status = NT_STATUS_OK;
8536 TALLOC_CTX *ctx = talloc_tos();
8538 DEBUG(10,("call_trans2getdfsreferral\n"));
8540 if (total_params < 3) {
8541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8542 return;
8545 max_referral_level = SVAL(params,0);
8547 if(!lp_host_msdfs()) {
8548 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8549 return;
8552 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8553 total_params - 2, STR_TERMINATE);
8554 if (!pathname) {
8555 reply_nterror(req, NT_STATUS_NOT_FOUND);
8556 return;
8558 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8559 ppdata,&status)) < 0) {
8560 reply_nterror(req, status);
8561 return;
8564 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8565 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8566 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8568 return;
8571 #define LMCAT_SPL 0x53
8572 #define LMFUNC_GETJOBID 0x60
8574 /****************************************************************************
8575 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8576 ****************************************************************************/
8578 static void call_trans2ioctl(connection_struct *conn,
8579 struct smb_request *req,
8580 char **pparams, int total_params,
8581 char **ppdata, int total_data,
8582 unsigned int max_data_bytes)
8584 char *pdata = *ppdata;
8585 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8587 /* check for an invalid fid before proceeding */
8589 if (!fsp) {
8590 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8591 return;
8594 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8595 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8596 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8597 if (*ppdata == NULL) {
8598 reply_nterror(req, NT_STATUS_NO_MEMORY);
8599 return;
8601 pdata = *ppdata;
8603 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8604 CAN ACCEPT THIS IN UNICODE. JRA. */
8606 /* Job number */
8607 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8609 srvstr_push(pdata, req->flags2, pdata + 2,
8610 lp_netbios_name(), 15,
8611 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8612 srvstr_push(pdata, req->flags2, pdata+18,
8613 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8614 STR_ASCII|STR_TERMINATE); /* Service name */
8615 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8616 max_data_bytes);
8617 return;
8620 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8621 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8624 /****************************************************************************
8625 Reply to a SMBfindclose (stop trans2 directory search).
8626 ****************************************************************************/
8628 void reply_findclose(struct smb_request *req)
8630 int dptr_num;
8631 struct smbd_server_connection *sconn = req->sconn;
8633 START_PROFILE(SMBfindclose);
8635 if (req->wct < 1) {
8636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8637 END_PROFILE(SMBfindclose);
8638 return;
8641 dptr_num = SVALS(req->vwv+0, 0);
8643 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8645 dptr_close(sconn, &dptr_num);
8647 reply_outbuf(req, 0, 0);
8649 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8651 END_PROFILE(SMBfindclose);
8652 return;
8655 /****************************************************************************
8656 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8657 ****************************************************************************/
8659 void reply_findnclose(struct smb_request *req)
8661 int dptr_num;
8663 START_PROFILE(SMBfindnclose);
8665 if (req->wct < 1) {
8666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8667 END_PROFILE(SMBfindnclose);
8668 return;
8671 dptr_num = SVAL(req->vwv+0, 0);
8673 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8675 /* We never give out valid handles for a
8676 findnotifyfirst - so any dptr_num is ok here.
8677 Just ignore it. */
8679 reply_outbuf(req, 0, 0);
8681 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8683 END_PROFILE(SMBfindnclose);
8684 return;
8687 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8688 struct trans_state *state)
8690 if (get_Protocol() >= PROTOCOL_NT1) {
8691 req->flags2 |= 0x40; /* IS_LONG_NAME */
8692 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8695 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8696 if (state->call != TRANSACT2_QFSINFO &&
8697 state->call != TRANSACT2_SETFSINFO) {
8698 DEBUG(0,("handle_trans2: encryption required "
8699 "with call 0x%x\n",
8700 (unsigned int)state->call));
8701 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8702 return;
8706 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8708 /* Now we must call the relevant TRANS2 function */
8709 switch(state->call) {
8710 case TRANSACT2_OPEN:
8712 START_PROFILE(Trans2_open);
8713 call_trans2open(conn, req,
8714 &state->param, state->total_param,
8715 &state->data, state->total_data,
8716 state->max_data_return);
8717 END_PROFILE(Trans2_open);
8718 break;
8721 case TRANSACT2_FINDFIRST:
8723 START_PROFILE(Trans2_findfirst);
8724 call_trans2findfirst(conn, req,
8725 &state->param, state->total_param,
8726 &state->data, state->total_data,
8727 state->max_data_return);
8728 END_PROFILE(Trans2_findfirst);
8729 break;
8732 case TRANSACT2_FINDNEXT:
8734 START_PROFILE(Trans2_findnext);
8735 call_trans2findnext(conn, req,
8736 &state->param, state->total_param,
8737 &state->data, state->total_data,
8738 state->max_data_return);
8739 END_PROFILE(Trans2_findnext);
8740 break;
8743 case TRANSACT2_QFSINFO:
8745 START_PROFILE(Trans2_qfsinfo);
8746 call_trans2qfsinfo(conn, req,
8747 &state->param, state->total_param,
8748 &state->data, state->total_data,
8749 state->max_data_return);
8750 END_PROFILE(Trans2_qfsinfo);
8751 break;
8754 case TRANSACT2_SETFSINFO:
8756 START_PROFILE(Trans2_setfsinfo);
8757 call_trans2setfsinfo(conn, req,
8758 &state->param, state->total_param,
8759 &state->data, state->total_data,
8760 state->max_data_return);
8761 END_PROFILE(Trans2_setfsinfo);
8762 break;
8765 case TRANSACT2_QPATHINFO:
8766 case TRANSACT2_QFILEINFO:
8768 START_PROFILE(Trans2_qpathinfo);
8769 call_trans2qfilepathinfo(conn, req, state->call,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_qpathinfo);
8774 break;
8777 case TRANSACT2_SETPATHINFO:
8778 case TRANSACT2_SETFILEINFO:
8780 START_PROFILE(Trans2_setpathinfo);
8781 call_trans2setfilepathinfo(conn, req, state->call,
8782 &state->param, state->total_param,
8783 &state->data, state->total_data,
8784 state->max_data_return);
8785 END_PROFILE(Trans2_setpathinfo);
8786 break;
8789 case TRANSACT2_FINDNOTIFYFIRST:
8791 START_PROFILE(Trans2_findnotifyfirst);
8792 call_trans2findnotifyfirst(conn, req,
8793 &state->param, state->total_param,
8794 &state->data, state->total_data,
8795 state->max_data_return);
8796 END_PROFILE(Trans2_findnotifyfirst);
8797 break;
8800 case TRANSACT2_FINDNOTIFYNEXT:
8802 START_PROFILE(Trans2_findnotifynext);
8803 call_trans2findnotifynext(conn, req,
8804 &state->param, state->total_param,
8805 &state->data, state->total_data,
8806 state->max_data_return);
8807 END_PROFILE(Trans2_findnotifynext);
8808 break;
8811 case TRANSACT2_MKDIR:
8813 START_PROFILE(Trans2_mkdir);
8814 call_trans2mkdir(conn, req,
8815 &state->param, state->total_param,
8816 &state->data, state->total_data,
8817 state->max_data_return);
8818 END_PROFILE(Trans2_mkdir);
8819 break;
8822 case TRANSACT2_GET_DFS_REFERRAL:
8824 START_PROFILE(Trans2_get_dfs_referral);
8825 call_trans2getdfsreferral(conn, req,
8826 &state->param, state->total_param,
8827 &state->data, state->total_data,
8828 state->max_data_return);
8829 END_PROFILE(Trans2_get_dfs_referral);
8830 break;
8833 case TRANSACT2_IOCTL:
8835 START_PROFILE(Trans2_ioctl);
8836 call_trans2ioctl(conn, req,
8837 &state->param, state->total_param,
8838 &state->data, state->total_data,
8839 state->max_data_return);
8840 END_PROFILE(Trans2_ioctl);
8841 break;
8844 default:
8845 /* Error in request */
8846 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8847 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8851 /****************************************************************************
8852 Reply to a SMBtrans2.
8853 ****************************************************************************/
8855 void reply_trans2(struct smb_request *req)
8857 connection_struct *conn = req->conn;
8858 unsigned int dsoff;
8859 unsigned int dscnt;
8860 unsigned int psoff;
8861 unsigned int pscnt;
8862 unsigned int tran_call;
8863 struct trans_state *state;
8864 NTSTATUS result;
8866 START_PROFILE(SMBtrans2);
8868 if (req->wct < 14) {
8869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8870 END_PROFILE(SMBtrans2);
8871 return;
8874 dsoff = SVAL(req->vwv+12, 0);
8875 dscnt = SVAL(req->vwv+11, 0);
8876 psoff = SVAL(req->vwv+10, 0);
8877 pscnt = SVAL(req->vwv+9, 0);
8878 tran_call = SVAL(req->vwv+14, 0);
8880 result = allow_new_trans(conn->pending_trans, req->mid);
8881 if (!NT_STATUS_IS_OK(result)) {
8882 DEBUG(2, ("Got invalid trans2 request: %s\n",
8883 nt_errstr(result)));
8884 reply_nterror(req, result);
8885 END_PROFILE(SMBtrans2);
8886 return;
8889 if (IS_IPC(conn)) {
8890 switch (tran_call) {
8891 /* List the allowed trans2 calls on IPC$ */
8892 case TRANSACT2_OPEN:
8893 case TRANSACT2_GET_DFS_REFERRAL:
8894 case TRANSACT2_QFILEINFO:
8895 case TRANSACT2_QFSINFO:
8896 case TRANSACT2_SETFSINFO:
8897 break;
8898 default:
8899 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8900 END_PROFILE(SMBtrans2);
8901 return;
8905 if ((state = talloc(conn, struct trans_state)) == NULL) {
8906 DEBUG(0, ("talloc failed\n"));
8907 reply_nterror(req, NT_STATUS_NO_MEMORY);
8908 END_PROFILE(SMBtrans2);
8909 return;
8912 state->cmd = SMBtrans2;
8914 state->mid = req->mid;
8915 state->vuid = req->vuid;
8916 state->setup_count = SVAL(req->vwv+13, 0);
8917 state->setup = NULL;
8918 state->total_param = SVAL(req->vwv+0, 0);
8919 state->param = NULL;
8920 state->total_data = SVAL(req->vwv+1, 0);
8921 state->data = NULL;
8922 state->max_param_return = SVAL(req->vwv+2, 0);
8923 state->max_data_return = SVAL(req->vwv+3, 0);
8924 state->max_setup_return = SVAL(req->vwv+4, 0);
8925 state->close_on_completion = BITSETW(req->vwv+5, 0);
8926 state->one_way = BITSETW(req->vwv+5, 1);
8928 state->call = tran_call;
8930 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8931 is so as a sanity check */
8932 if (state->setup_count != 1) {
8934 * Need to have rc=0 for ioctl to get job id for OS/2.
8935 * Network printing will fail if function is not successful.
8936 * Similar function in reply.c will be used if protocol
8937 * is LANMAN1.0 instead of LM1.2X002.
8938 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8939 * outbuf doesn't have to be set(only job id is used).
8941 if ( (state->setup_count == 4)
8942 && (tran_call == TRANSACT2_IOCTL)
8943 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8944 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8945 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8946 } else {
8947 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8948 DEBUG(2,("Transaction is %d\n",tran_call));
8949 TALLOC_FREE(state);
8950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8951 END_PROFILE(SMBtrans2);
8952 return;
8956 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8957 goto bad_param;
8959 if (state->total_data) {
8961 if (trans_oob(state->total_data, 0, dscnt)
8962 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8963 goto bad_param;
8966 /* Can't use talloc here, the core routines do realloc on the
8967 * params and data. */
8968 state->data = (char *)SMB_MALLOC(state->total_data);
8969 if (state->data == NULL) {
8970 DEBUG(0,("reply_trans2: data malloc fail for %u "
8971 "bytes !\n", (unsigned int)state->total_data));
8972 TALLOC_FREE(state);
8973 reply_nterror(req, NT_STATUS_NO_MEMORY);
8974 END_PROFILE(SMBtrans2);
8975 return;
8978 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8981 if (state->total_param) {
8983 if (trans_oob(state->total_param, 0, pscnt)
8984 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8985 goto bad_param;
8988 /* Can't use talloc here, the core routines do realloc on the
8989 * params and data. */
8990 state->param = (char *)SMB_MALLOC(state->total_param);
8991 if (state->param == NULL) {
8992 DEBUG(0,("reply_trans: param malloc fail for %u "
8993 "bytes !\n", (unsigned int)state->total_param));
8994 SAFE_FREE(state->data);
8995 TALLOC_FREE(state);
8996 reply_nterror(req, NT_STATUS_NO_MEMORY);
8997 END_PROFILE(SMBtrans2);
8998 return;
9001 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9004 state->received_data = dscnt;
9005 state->received_param = pscnt;
9007 if ((state->received_param == state->total_param) &&
9008 (state->received_data == state->total_data)) {
9010 handle_trans2(conn, req, state);
9012 SAFE_FREE(state->data);
9013 SAFE_FREE(state->param);
9014 TALLOC_FREE(state);
9015 END_PROFILE(SMBtrans2);
9016 return;
9019 DLIST_ADD(conn->pending_trans, state);
9021 /* We need to send an interim response then receive the rest
9022 of the parameter/data bytes */
9023 reply_outbuf(req, 0, 0);
9024 show_msg((char *)req->outbuf);
9025 END_PROFILE(SMBtrans2);
9026 return;
9028 bad_param:
9030 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9031 SAFE_FREE(state->data);
9032 SAFE_FREE(state->param);
9033 TALLOC_FREE(state);
9034 END_PROFILE(SMBtrans2);
9035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9039 /****************************************************************************
9040 Reply to a SMBtranss2
9041 ****************************************************************************/
9043 void reply_transs2(struct smb_request *req)
9045 connection_struct *conn = req->conn;
9046 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9047 struct trans_state *state;
9049 START_PROFILE(SMBtranss2);
9051 show_msg((const char *)req->inbuf);
9053 /* Windows clients expect all replies to
9054 a transact secondary (SMBtranss2 0x33)
9055 to have a command code of transact
9056 (SMBtrans2 0x32). See bug #8989
9057 and also [MS-CIFS] section 2.2.4.47.2
9058 for details.
9060 req->cmd = SMBtrans2;
9062 if (req->wct < 8) {
9063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9064 END_PROFILE(SMBtranss2);
9065 return;
9068 for (state = conn->pending_trans; state != NULL;
9069 state = state->next) {
9070 if (state->mid == req->mid) {
9071 break;
9075 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9077 END_PROFILE(SMBtranss2);
9078 return;
9081 /* Revise state->total_param and state->total_data in case they have
9082 changed downwards */
9084 if (SVAL(req->vwv+0, 0) < state->total_param)
9085 state->total_param = SVAL(req->vwv+0, 0);
9086 if (SVAL(req->vwv+1, 0) < state->total_data)
9087 state->total_data = SVAL(req->vwv+1, 0);
9089 pcnt = SVAL(req->vwv+2, 0);
9090 poff = SVAL(req->vwv+3, 0);
9091 pdisp = SVAL(req->vwv+4, 0);
9093 dcnt = SVAL(req->vwv+5, 0);
9094 doff = SVAL(req->vwv+6, 0);
9095 ddisp = SVAL(req->vwv+7, 0);
9097 state->received_param += pcnt;
9098 state->received_data += dcnt;
9100 if ((state->received_data > state->total_data) ||
9101 (state->received_param > state->total_param))
9102 goto bad_param;
9104 if (pcnt) {
9105 if (trans_oob(state->total_param, pdisp, pcnt)
9106 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9107 goto bad_param;
9109 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9112 if (dcnt) {
9113 if (trans_oob(state->total_data, ddisp, dcnt)
9114 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9115 goto bad_param;
9117 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9120 if ((state->received_param < state->total_param) ||
9121 (state->received_data < state->total_data)) {
9122 END_PROFILE(SMBtranss2);
9123 return;
9126 handle_trans2(conn, req, state);
9128 DLIST_REMOVE(conn->pending_trans, state);
9129 SAFE_FREE(state->data);
9130 SAFE_FREE(state->param);
9131 TALLOC_FREE(state);
9133 END_PROFILE(SMBtranss2);
9134 return;
9136 bad_param:
9138 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9139 DLIST_REMOVE(conn->pending_trans, state);
9140 SAFE_FREE(state->data);
9141 SAFE_FREE(state->param);
9142 TALLOC_FREE(state);
9143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9144 END_PROFILE(SMBtranss2);
9145 return;