smbd: Rename parameter "i" to "idx"
[Samba.git] / source3 / smbd / trans2.c
blobf23192e87f5f29fbe7d1229a797a01a27ace4e9f
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 if (ptype == PERM_NEW_FILE) {
1456 * "create mask"/"force create mode" are
1457 * only applied to new files, not existing ones.
1459 ret &= lp_create_mask(SNUM(conn));
1460 /* Add in force bits */
1461 ret |= lp_force_create_mode(SNUM(conn));
1462 } else if (ptype == PERM_NEW_DIR) {
1464 * "directory mask"/"force directory mode" are
1465 * only applied to new directories, not existing ones.
1467 ret &= lp_dir_mask(SNUM(conn));
1468 /* Add in force bits */
1469 ret |= lp_force_dir_mode(SNUM(conn));
1472 *ret_perms = ret;
1473 return NT_STATUS_OK;
1476 /****************************************************************************
1477 Needed to show the msdfs symlinks as directories. Modifies psbuf
1478 to be a directory if it's a msdfs link.
1479 ****************************************************************************/
1481 static bool check_msdfs_link(connection_struct *conn,
1482 const char *pathname,
1483 SMB_STRUCT_STAT *psbuf)
1485 int saved_errno = errno;
1486 if(lp_host_msdfs() &&
1487 lp_msdfs_root(SNUM(conn)) &&
1488 is_msdfs_link(conn, pathname, psbuf)) {
1490 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1491 "as a directory\n",
1492 pathname));
1493 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1494 errno = saved_errno;
1495 return true;
1497 errno = saved_errno;
1498 return false;
1502 /****************************************************************************
1503 Get a level dependent lanman2 dir entry.
1504 ****************************************************************************/
1506 struct smbd_dirptr_lanman2_state {
1507 connection_struct *conn;
1508 uint32_t info_level;
1509 bool check_mangled_names;
1510 bool has_wild;
1511 bool got_exact_match;
1514 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1515 void *private_data,
1516 const char *dname,
1517 const char *mask,
1518 char **_fname)
1520 struct smbd_dirptr_lanman2_state *state =
1521 (struct smbd_dirptr_lanman2_state *)private_data;
1522 bool ok;
1523 char mangled_name[13]; /* mangled 8.3 name. */
1524 bool got_match;
1525 const char *fname;
1527 /* Mangle fname if it's an illegal name. */
1528 if (mangle_must_mangle(dname, state->conn->params)) {
1529 ok = name_to_8_3(dname, mangled_name,
1530 true, state->conn->params);
1531 if (!ok) {
1532 return false;
1534 fname = mangled_name;
1535 } else {
1536 fname = dname;
1539 got_match = exact_match(state->has_wild,
1540 state->conn->case_sensitive,
1541 fname, mask);
1542 state->got_exact_match = got_match;
1543 if (!got_match) {
1544 got_match = mask_match(fname, mask,
1545 state->conn->case_sensitive);
1548 if(!got_match && state->check_mangled_names &&
1549 !mangle_is_8_3(fname, false, state->conn->params)) {
1551 * It turns out that NT matches wildcards against
1552 * both long *and* short names. This may explain some
1553 * of the wildcard wierdness from old DOS clients
1554 * that some people have been seeing.... JRA.
1556 /* Force the mangling into 8.3. */
1557 ok = name_to_8_3(fname, mangled_name,
1558 false, state->conn->params);
1559 if (!ok) {
1560 return false;
1563 got_match = exact_match(state->has_wild,
1564 state->conn->case_sensitive,
1565 mangled_name, mask);
1566 state->got_exact_match = got_match;
1567 if (!got_match) {
1568 got_match = mask_match(mangled_name, mask,
1569 state->conn->case_sensitive);
1573 if (!got_match) {
1574 return false;
1577 *_fname = talloc_strdup(ctx, fname);
1578 if (*_fname == NULL) {
1579 return false;
1582 return true;
1585 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1586 void *private_data,
1587 struct smb_filename *smb_fname,
1588 uint32_t *_mode)
1590 struct smbd_dirptr_lanman2_state *state =
1591 (struct smbd_dirptr_lanman2_state *)private_data;
1592 bool ms_dfs_link = false;
1593 uint32_t mode = 0;
1595 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1596 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1597 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1598 "Couldn't lstat [%s] (%s)\n",
1599 smb_fname_str_dbg(smb_fname),
1600 strerror(errno)));
1601 return false;
1603 } else if (!VALID_STAT(smb_fname->st) &&
1604 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1605 /* Needed to show the msdfs symlinks as
1606 * directories */
1608 ms_dfs_link = check_msdfs_link(state->conn,
1609 smb_fname->base_name,
1610 &smb_fname->st);
1611 if (!ms_dfs_link) {
1612 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1613 "Couldn't stat [%s] (%s)\n",
1614 smb_fname_str_dbg(smb_fname),
1615 strerror(errno)));
1616 return false;
1620 if (ms_dfs_link) {
1621 mode = dos_mode_msdfs(state->conn, smb_fname);
1622 } else {
1623 mode = dos_mode(state->conn, smb_fname);
1626 *_mode = mode;
1627 return true;
1630 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1631 connection_struct *conn,
1632 uint16_t flags2,
1633 uint32_t info_level,
1634 struct ea_list *name_list,
1635 bool check_mangled_names,
1636 bool requires_resume_key,
1637 uint32_t mode,
1638 const char *fname,
1639 const struct smb_filename *smb_fname,
1640 int space_remaining,
1641 uint8_t align,
1642 bool do_pad,
1643 char *base_data,
1644 char **ppdata,
1645 char *end_data,
1646 bool *out_of_space,
1647 uint64_t *last_entry_off)
1649 char *p, *q, *pdata = *ppdata;
1650 uint32_t reskey=0;
1651 uint64_t file_size = 0;
1652 uint64_t allocation_size = 0;
1653 uint64_t file_index = 0;
1654 uint32_t len;
1655 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1656 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1657 char *nameptr;
1658 char *last_entry_ptr;
1659 bool was_8_3;
1660 int off;
1661 int pad = 0;
1663 *out_of_space = false;
1665 ZERO_STRUCT(mdate_ts);
1666 ZERO_STRUCT(adate_ts);
1667 ZERO_STRUCT(create_date_ts);
1668 ZERO_STRUCT(cdate_ts);
1670 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1671 file_size = get_file_size_stat(&smb_fname->st);
1673 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1675 file_index = get_FileIndex(conn, &smb_fname->st);
1677 mdate_ts = smb_fname->st.st_ex_mtime;
1678 adate_ts = smb_fname->st.st_ex_atime;
1679 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1680 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1682 if (lp_dos_filetime_resolution(SNUM(conn))) {
1683 dos_filetime_timespec(&create_date_ts);
1684 dos_filetime_timespec(&mdate_ts);
1685 dos_filetime_timespec(&adate_ts);
1686 dos_filetime_timespec(&cdate_ts);
1689 create_date = convert_timespec_to_time_t(create_date_ts);
1690 mdate = convert_timespec_to_time_t(mdate_ts);
1691 adate = convert_timespec_to_time_t(adate_ts);
1693 /* align the record */
1694 SMB_ASSERT(align >= 1);
1696 off = (int)PTR_DIFF(pdata, base_data);
1697 pad = (off + (align-1)) & ~(align-1);
1698 pad -= off;
1700 if (pad && pad > space_remaining) {
1701 *out_of_space = true;
1702 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1703 "for padding (wanted %u, had %d)\n",
1704 (unsigned int)pad,
1705 space_remaining ));
1706 return false; /* Not finished - just out of space */
1709 off += pad;
1710 /* initialize padding to 0 */
1711 if (pad) {
1712 memset(pdata, 0, pad);
1714 space_remaining -= pad;
1716 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1717 space_remaining ));
1719 pdata += pad;
1720 p = pdata;
1721 last_entry_ptr = p;
1723 pad = 0;
1724 off = 0;
1726 switch (info_level) {
1727 case SMB_FIND_INFO_STANDARD:
1728 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1729 if(requires_resume_key) {
1730 SIVAL(p,0,reskey);
1731 p += 4;
1733 srv_put_dos_date2(p,0,create_date);
1734 srv_put_dos_date2(p,4,adate);
1735 srv_put_dos_date2(p,8,mdate);
1736 SIVAL(p,12,(uint32)file_size);
1737 SIVAL(p,16,(uint32)allocation_size);
1738 SSVAL(p,20,mode);
1739 p += 23;
1740 nameptr = p;
1741 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1742 p += ucs2_align(base_data, p, 0);
1744 len = srvstr_push(base_data, flags2, p,
1745 fname, PTR_DIFF(end_data, p),
1746 STR_TERMINATE);
1747 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1748 if (len > 2) {
1749 SCVAL(nameptr, -1, len - 2);
1750 } else {
1751 SCVAL(nameptr, -1, 0);
1753 } else {
1754 if (len > 1) {
1755 SCVAL(nameptr, -1, len - 1);
1756 } else {
1757 SCVAL(nameptr, -1, 0);
1760 p += len;
1761 break;
1763 case SMB_FIND_EA_SIZE:
1764 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1765 if (requires_resume_key) {
1766 SIVAL(p,0,reskey);
1767 p += 4;
1769 srv_put_dos_date2(p,0,create_date);
1770 srv_put_dos_date2(p,4,adate);
1771 srv_put_dos_date2(p,8,mdate);
1772 SIVAL(p,12,(uint32)file_size);
1773 SIVAL(p,16,(uint32)allocation_size);
1774 SSVAL(p,20,mode);
1776 unsigned int ea_size = estimate_ea_size(conn, NULL,
1777 smb_fname);
1778 SIVAL(p,22,ea_size); /* Extended attributes */
1780 p += 27;
1781 nameptr = p - 1;
1782 len = srvstr_push(base_data, flags2,
1783 p, fname, PTR_DIFF(end_data, p),
1784 STR_TERMINATE | STR_NOALIGN);
1785 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1786 if (len > 2) {
1787 len -= 2;
1788 } else {
1789 len = 0;
1791 } else {
1792 if (len > 1) {
1793 len -= 1;
1794 } else {
1795 len = 0;
1798 SCVAL(nameptr,0,len);
1799 p += len;
1800 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1801 break;
1803 case SMB_FIND_EA_LIST:
1805 struct ea_list *file_list = NULL;
1806 size_t ea_len = 0;
1807 NTSTATUS status;
1809 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1810 if (!name_list) {
1811 return false;
1813 if (requires_resume_key) {
1814 SIVAL(p,0,reskey);
1815 p += 4;
1817 srv_put_dos_date2(p,0,create_date);
1818 srv_put_dos_date2(p,4,adate);
1819 srv_put_dos_date2(p,8,mdate);
1820 SIVAL(p,12,(uint32)file_size);
1821 SIVAL(p,16,(uint32)allocation_size);
1822 SSVAL(p,20,mode);
1823 p += 22; /* p now points to the EA area. */
1825 status = get_ea_list_from_file(ctx, conn, NULL,
1826 smb_fname,
1827 &ea_len, &file_list);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 file_list = NULL;
1831 name_list = ea_list_union(name_list, file_list, &ea_len);
1833 /* We need to determine if this entry will fit in the space available. */
1834 /* Max string size is 255 bytes. */
1835 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1836 *out_of_space = true;
1837 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1838 "(wanted %u, had %d)\n",
1839 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1840 space_remaining ));
1841 return False; /* Not finished - just out of space */
1844 /* Push the ea_data followed by the name. */
1845 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1846 nameptr = p;
1847 len = srvstr_push(base_data, flags2,
1848 p + 1, fname, PTR_DIFF(end_data, p+1),
1849 STR_TERMINATE | STR_NOALIGN);
1850 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1851 if (len > 2) {
1852 len -= 2;
1853 } else {
1854 len = 0;
1856 } else {
1857 if (len > 1) {
1858 len -= 1;
1859 } else {
1860 len = 0;
1863 SCVAL(nameptr,0,len);
1864 p += len + 1;
1865 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1866 break;
1869 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1871 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1872 p += 4;
1873 SIVAL(p,0,reskey); p += 4;
1874 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1878 SOFF_T(p,0,file_size); p += 8;
1879 SOFF_T(p,0,allocation_size); p += 8;
1880 SIVAL(p,0,mode); p += 4;
1881 q = p; p += 4; /* q is placeholder for name length. */
1882 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1883 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1884 } else {
1885 unsigned int ea_size = estimate_ea_size(conn, NULL,
1886 smb_fname);
1887 SIVAL(p,0,ea_size); /* Extended attributes */
1889 p += 4;
1890 /* Clear the short name buffer. This is
1891 * IMPORTANT as not doing so will trigger
1892 * a Win2k client bug. JRA.
1894 if (!was_8_3 && check_mangled_names) {
1895 char mangled_name[13]; /* mangled 8.3 name. */
1896 if (!name_to_8_3(fname,mangled_name,True,
1897 conn->params)) {
1898 /* Error - mangle failed ! */
1899 memset(mangled_name,'\0',12);
1901 mangled_name[12] = 0;
1902 len = srvstr_push(base_data, flags2,
1903 p+2, mangled_name, 24,
1904 STR_UPPER|STR_UNICODE);
1905 if (len < 24) {
1906 memset(p + 2 + len,'\0',24 - len);
1908 SSVAL(p, 0, len);
1909 } else {
1910 memset(p,'\0',26);
1912 p += 2 + 24;
1913 len = srvstr_push(base_data, flags2, p,
1914 fname, PTR_DIFF(end_data, p),
1915 STR_TERMINATE_ASCII);
1916 SIVAL(q,0,len);
1917 p += len;
1919 len = PTR_DIFF(p, pdata);
1920 pad = (len + (align-1)) & ~(align-1);
1922 * offset to the next entry, the caller
1923 * will overwrite it for the last entry
1924 * that's why we always include the padding
1926 SIVAL(pdata,0,pad);
1928 * set padding to zero
1930 if (do_pad) {
1931 memset(p, 0, pad - len);
1932 p = pdata + pad;
1933 } else {
1934 p = pdata + len;
1936 break;
1938 case SMB_FIND_FILE_DIRECTORY_INFO:
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1940 p += 4;
1941 SIVAL(p,0,reskey); p += 4;
1942 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1945 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1946 SOFF_T(p,0,file_size); p += 8;
1947 SOFF_T(p,0,allocation_size); p += 8;
1948 SIVAL(p,0,mode); p += 4;
1949 len = srvstr_push(base_data, flags2,
1950 p + 4, fname, PTR_DIFF(end_data, p+4),
1951 STR_TERMINATE_ASCII);
1952 SIVAL(p,0,len);
1953 p += 4 + len;
1955 len = PTR_DIFF(p, pdata);
1956 pad = (len + (align-1)) & ~(align-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1962 SIVAL(pdata,0,pad);
1964 * set padding to zero
1966 if (do_pad) {
1967 memset(p, 0, pad - len);
1968 p = pdata + pad;
1969 } else {
1970 p = pdata + len;
1972 break;
1974 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1976 p += 4;
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length. */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1990 p +=4;
1992 len = srvstr_push(base_data, flags2, p,
1993 fname, PTR_DIFF(end_data, p),
1994 STR_TERMINATE_ASCII);
1995 SIVAL(q, 0, len);
1996 p += len;
1998 len = PTR_DIFF(p, pdata);
1999 pad = (len + (align-1)) & ~(align-1);
2001 * offset to the next entry, the caller
2002 * will overwrite it for the last entry
2003 * that's why we always include the padding
2005 SIVAL(pdata,0,pad);
2007 * set padding to zero
2009 if (do_pad) {
2010 memset(p, 0, pad - len);
2011 p = pdata + pad;
2012 } else {
2013 p = pdata + len;
2015 break;
2017 case SMB_FIND_FILE_NAMES_INFO:
2018 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2019 p += 4;
2020 SIVAL(p,0,reskey); p += 4;
2021 p += 4;
2022 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2023 acl on a dir (tridge) */
2024 len = srvstr_push(base_data, flags2, p,
2025 fname, PTR_DIFF(end_data, p),
2026 STR_TERMINATE_ASCII);
2027 SIVAL(p, -4, len);
2028 p += len;
2030 len = PTR_DIFF(p, pdata);
2031 pad = (len + (align-1)) & ~(align-1);
2033 * offset to the next entry, the caller
2034 * will overwrite it for the last entry
2035 * that's why we always include the padding
2037 SIVAL(pdata,0,pad);
2039 * set padding to zero
2041 if (do_pad) {
2042 memset(p, 0, pad - len);
2043 p = pdata + pad;
2044 } else {
2045 p = pdata + len;
2047 break;
2049 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2050 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2051 p += 4;
2052 SIVAL(p,0,reskey); p += 4;
2053 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2054 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2055 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2056 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2057 SOFF_T(p,0,file_size); p += 8;
2058 SOFF_T(p,0,allocation_size); p += 8;
2059 SIVAL(p,0,mode); p += 4;
2060 q = p; p += 4; /* q is placeholder for name length. */
2061 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2062 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2063 } else {
2064 unsigned int ea_size = estimate_ea_size(conn, NULL,
2065 smb_fname);
2066 SIVAL(p,0,ea_size); /* Extended attributes */
2068 p += 4;
2069 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2070 SBVAL(p,0,file_index); p += 8;
2071 len = srvstr_push(base_data, flags2, p,
2072 fname, PTR_DIFF(end_data, p),
2073 STR_TERMINATE_ASCII);
2074 SIVAL(q, 0, len);
2075 p += len;
2077 len = PTR_DIFF(p, pdata);
2078 pad = (len + (align-1)) & ~(align-1);
2080 * offset to the next entry, the caller
2081 * will overwrite it for the last entry
2082 * that's why we always include the padding
2084 SIVAL(pdata,0,pad);
2086 * set padding to zero
2088 if (do_pad) {
2089 memset(p, 0, pad - len);
2090 p = pdata + pad;
2091 } else {
2092 p = pdata + len;
2094 break;
2096 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2097 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2098 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2099 p += 4;
2100 SIVAL(p,0,reskey); p += 4;
2101 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2102 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2103 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2105 SOFF_T(p,0,file_size); p += 8;
2106 SOFF_T(p,0,allocation_size); p += 8;
2107 SIVAL(p,0,mode); p += 4;
2108 q = p; p += 4; /* q is placeholder for name length */
2109 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2110 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2111 } else {
2112 unsigned int ea_size = estimate_ea_size(conn, NULL,
2113 smb_fname);
2114 SIVAL(p,0,ea_size); /* Extended attributes */
2116 p += 4;
2117 /* Clear the short name buffer. This is
2118 * IMPORTANT as not doing so will trigger
2119 * a Win2k client bug. JRA.
2121 if (!was_8_3 && check_mangled_names) {
2122 char mangled_name[13]; /* mangled 8.3 name. */
2123 if (!name_to_8_3(fname,mangled_name,True,
2124 conn->params)) {
2125 /* Error - mangle failed ! */
2126 memset(mangled_name,'\0',12);
2128 mangled_name[12] = 0;
2129 len = srvstr_push(base_data, flags2,
2130 p+2, mangled_name, 24,
2131 STR_UPPER|STR_UNICODE);
2132 SSVAL(p, 0, len);
2133 if (len < 24) {
2134 memset(p + 2 + len,'\0',24 - len);
2136 SSVAL(p, 0, len);
2137 } else {
2138 memset(p,'\0',26);
2140 p += 26;
2141 SSVAL(p,0,0); p += 2; /* Reserved ? */
2142 SBVAL(p,0,file_index); p += 8;
2143 len = srvstr_push(base_data, flags2, p,
2144 fname, PTR_DIFF(end_data, p),
2145 STR_TERMINATE_ASCII);
2146 SIVAL(q,0,len);
2147 p += len;
2149 len = PTR_DIFF(p, pdata);
2150 pad = (len + (align-1)) & ~(align-1);
2152 * offset to the next entry, the caller
2153 * will overwrite it for the last entry
2154 * that's why we always include the padding
2156 SIVAL(pdata,0,pad);
2158 * set padding to zero
2160 if (do_pad) {
2161 memset(p, 0, pad - len);
2162 p = pdata + pad;
2163 } else {
2164 p = pdata + len;
2166 break;
2168 /* CIFS UNIX Extension. */
2170 case SMB_FIND_FILE_UNIX:
2171 case SMB_FIND_FILE_UNIX_INFO2:
2172 p+= 4;
2173 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2175 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2177 if (info_level == SMB_FIND_FILE_UNIX) {
2178 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2179 p = store_file_unix_basic(conn, p,
2180 NULL, &smb_fname->st);
2181 len = srvstr_push(base_data, flags2, p,
2182 fname, PTR_DIFF(end_data, p),
2183 STR_TERMINATE);
2184 } else {
2185 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2186 p = store_file_unix_basic_info2(conn, p,
2187 NULL, &smb_fname->st);
2188 nameptr = p;
2189 p += 4;
2190 len = srvstr_push(base_data, flags2, p, fname,
2191 PTR_DIFF(end_data, p), 0);
2192 SIVAL(nameptr, 0, len);
2195 p += len;
2197 len = PTR_DIFF(p, pdata);
2198 pad = (len + (align-1)) & ~(align-1);
2200 * offset to the next entry, the caller
2201 * will overwrite it for the last entry
2202 * that's why we always include the padding
2204 SIVAL(pdata,0,pad);
2206 * set padding to zero
2208 if (do_pad) {
2209 memset(p, 0, pad - len);
2210 p = pdata + pad;
2211 } else {
2212 p = pdata + len;
2214 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2216 break;
2218 default:
2219 return false;
2222 if (PTR_DIFF(p,pdata) > space_remaining) {
2223 *out_of_space = true;
2224 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2225 "(wanted %u, had %d)\n",
2226 (unsigned int)PTR_DIFF(p,pdata),
2227 space_remaining ));
2228 return false; /* Not finished - just out of space */
2231 /* Setup the last entry pointer, as an offset from base_data */
2232 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2233 /* Advance the data pointer to the next slot */
2234 *ppdata = p;
2236 return true;
2239 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2240 connection_struct *conn,
2241 struct dptr_struct *dirptr,
2242 uint16 flags2,
2243 const char *path_mask,
2244 uint32 dirtype,
2245 int info_level,
2246 int requires_resume_key,
2247 bool dont_descend,
2248 bool ask_sharemode,
2249 uint8_t align,
2250 bool do_pad,
2251 char **ppdata,
2252 char *base_data,
2253 char *end_data,
2254 int space_remaining,
2255 bool *out_of_space,
2256 bool *got_exact_match,
2257 int *_last_entry_off,
2258 struct ea_list *name_list)
2260 const char *p;
2261 const char *mask = NULL;
2262 long prev_dirpos = 0;
2263 uint32_t mode = 0;
2264 char *fname = NULL;
2265 struct smb_filename *smb_fname = NULL;
2266 struct smbd_dirptr_lanman2_state state;
2267 bool ok;
2268 uint64_t last_entry_off = 0;
2270 ZERO_STRUCT(state);
2271 state.conn = conn;
2272 state.info_level = info_level;
2273 state.check_mangled_names = lp_manglednames(conn->params);
2274 state.has_wild = dptr_has_wild(dirptr);
2275 state.got_exact_match = false;
2277 *out_of_space = false;
2278 *got_exact_match = false;
2280 p = strrchr_m(path_mask,'/');
2281 if(p != NULL) {
2282 if(p[1] == '\0') {
2283 mask = "*.*";
2284 } else {
2285 mask = p+1;
2287 } else {
2288 mask = path_mask;
2291 ok = smbd_dirptr_get_entry(ctx,
2292 dirptr,
2293 mask,
2294 dirtype,
2295 dont_descend,
2296 ask_sharemode,
2297 smbd_dirptr_lanman2_match_fn,
2298 smbd_dirptr_lanman2_mode_fn,
2299 &state,
2300 &fname,
2301 &smb_fname,
2302 &mode,
2303 &prev_dirpos);
2304 if (!ok) {
2305 return false;
2308 *got_exact_match = state.got_exact_match;
2310 ok = smbd_marshall_dir_entry(ctx,
2311 conn,
2312 flags2,
2313 info_level,
2314 name_list,
2315 state.check_mangled_names,
2316 requires_resume_key,
2317 mode,
2318 fname,
2319 smb_fname,
2320 space_remaining,
2321 align,
2322 do_pad,
2323 base_data,
2324 ppdata,
2325 end_data,
2326 out_of_space,
2327 &last_entry_off);
2328 TALLOC_FREE(fname);
2329 TALLOC_FREE(smb_fname);
2330 if (*out_of_space) {
2331 dptr_SeekDir(dirptr, prev_dirpos);
2332 return false;
2334 if (!ok) {
2335 return false;
2338 *_last_entry_off = last_entry_off;
2339 return true;
2342 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2343 connection_struct *conn,
2344 struct dptr_struct *dirptr,
2345 uint16 flags2,
2346 const char *path_mask,
2347 uint32 dirtype,
2348 int info_level,
2349 bool requires_resume_key,
2350 bool dont_descend,
2351 bool ask_sharemode,
2352 char **ppdata,
2353 char *base_data,
2354 char *end_data,
2355 int space_remaining,
2356 bool *out_of_space,
2357 bool *got_exact_match,
2358 int *last_entry_off,
2359 struct ea_list *name_list)
2361 uint8_t align = 4;
2362 const bool do_pad = true;
2364 if (info_level >= 1 && info_level <= 3) {
2365 /* No alignment on earlier info levels. */
2366 align = 1;
2369 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2370 path_mask, dirtype, info_level,
2371 requires_resume_key, dont_descend, ask_sharemode,
2372 align, do_pad,
2373 ppdata, base_data, end_data,
2374 space_remaining,
2375 out_of_space, got_exact_match,
2376 last_entry_off, name_list);
2379 /****************************************************************************
2380 Reply to a TRANS2_FINDFIRST.
2381 ****************************************************************************/
2383 static void call_trans2findfirst(connection_struct *conn,
2384 struct smb_request *req,
2385 char **pparams, int total_params,
2386 char **ppdata, int total_data,
2387 unsigned int max_data_bytes)
2389 /* We must be careful here that we don't return more than the
2390 allowed number of data bytes. If this means returning fewer than
2391 maxentries then so be it. We assume that the redirector has
2392 enough room for the fixed number of parameter bytes it has
2393 requested. */
2394 struct smb_filename *smb_dname = NULL;
2395 char *params = *pparams;
2396 char *pdata = *ppdata;
2397 char *data_end;
2398 uint32 dirtype;
2399 int maxentries;
2400 uint16 findfirst_flags;
2401 bool close_after_first;
2402 bool close_if_end;
2403 bool requires_resume_key;
2404 int info_level;
2405 char *directory = NULL;
2406 char *mask = NULL;
2407 char *p;
2408 int last_entry_off=0;
2409 int dptr_num = -1;
2410 int numentries = 0;
2411 int i;
2412 bool finished = False;
2413 bool dont_descend = False;
2414 bool out_of_space = False;
2415 int space_remaining;
2416 bool mask_contains_wcard = False;
2417 struct ea_list *ea_list = NULL;
2418 NTSTATUS ntstatus = NT_STATUS_OK;
2419 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2420 TALLOC_CTX *ctx = talloc_tos();
2421 struct dptr_struct *dirptr = NULL;
2422 struct smbd_server_connection *sconn = req->sconn;
2423 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2424 bool backup_priv = false;
2426 if (total_params < 13) {
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2428 goto out;
2431 dirtype = SVAL(params,0);
2432 maxentries = SVAL(params,2);
2433 findfirst_flags = SVAL(params,4);
2434 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2435 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2436 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2437 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2438 security_token_has_privilege(get_current_nttok(conn),
2439 SEC_PRIV_BACKUP));
2441 info_level = SVAL(params,6);
2443 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2444 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2445 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2446 (int)backup_priv,
2447 info_level, max_data_bytes));
2449 if (!maxentries) {
2450 /* W2K3 seems to treat zero as 1. */
2451 maxentries = 1;
2454 switch (info_level) {
2455 case SMB_FIND_INFO_STANDARD:
2456 case SMB_FIND_EA_SIZE:
2457 case SMB_FIND_EA_LIST:
2458 case SMB_FIND_FILE_DIRECTORY_INFO:
2459 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2460 case SMB_FIND_FILE_NAMES_INFO:
2461 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2462 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2463 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2464 break;
2465 case SMB_FIND_FILE_UNIX:
2466 case SMB_FIND_FILE_UNIX_INFO2:
2467 /* Always use filesystem for UNIX mtime query. */
2468 ask_sharemode = false;
2469 if (!lp_unix_extensions()) {
2470 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2471 goto out;
2473 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2474 break;
2475 default:
2476 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2477 goto out;
2480 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2481 params+12, total_params - 12,
2482 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2483 if (!NT_STATUS_IS_OK(ntstatus)) {
2484 reply_nterror(req, ntstatus);
2485 goto out;
2488 if (backup_priv) {
2489 become_root();
2490 ntstatus = filename_convert_with_privilege(ctx,
2491 conn,
2492 req,
2493 directory,
2494 ucf_flags,
2495 &mask_contains_wcard,
2496 &smb_dname);
2497 } else {
2498 ntstatus = filename_convert(ctx, conn,
2499 req->flags2 & FLAGS2_DFS_PATHNAMES,
2500 directory,
2501 ucf_flags,
2502 &mask_contains_wcard,
2503 &smb_dname);
2506 if (!NT_STATUS_IS_OK(ntstatus)) {
2507 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2508 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2509 ERRSRV, ERRbadpath);
2510 goto out;
2512 reply_nterror(req, ntstatus);
2513 goto out;
2516 mask = smb_dname->original_lcomp;
2518 directory = smb_dname->base_name;
2520 p = strrchr_m(directory,'/');
2521 if(p == NULL) {
2522 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2523 if((directory[0] == '.') && (directory[1] == '\0')) {
2524 mask = talloc_strdup(ctx,"*");
2525 if (!mask) {
2526 reply_nterror(req, NT_STATUS_NO_MEMORY);
2527 goto out;
2529 mask_contains_wcard = True;
2531 } else {
2532 *p = 0;
2535 if (p == NULL || p == directory) {
2536 /* Ensure we don't have a directory name of "". */
2537 directory = talloc_strdup(talloc_tos(), ".");
2538 if (!directory) {
2539 reply_nterror(req, NT_STATUS_NO_MEMORY);
2540 goto out;
2544 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2546 if (info_level == SMB_FIND_EA_LIST) {
2547 uint32 ea_size;
2549 if (total_data < 4) {
2550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2551 goto out;
2554 ea_size = IVAL(pdata,0);
2555 if (ea_size != total_data) {
2556 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2557 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559 goto out;
2562 if (!lp_ea_support(SNUM(conn))) {
2563 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2564 goto out;
2567 /* Pull out the list of names. */
2568 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2569 if (!ea_list) {
2570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2571 goto out;
2575 *ppdata = (char *)SMB_REALLOC(
2576 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2577 if(*ppdata == NULL ) {
2578 reply_nterror(req, NT_STATUS_NO_MEMORY);
2579 goto out;
2581 pdata = *ppdata;
2582 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2584 /* Realloc the params space */
2585 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2586 if (*pparams == NULL) {
2587 reply_nterror(req, NT_STATUS_NO_MEMORY);
2588 goto out;
2590 params = *pparams;
2592 /* Save the wildcard match and attribs we are using on this directory -
2593 needed as lanman2 assumes these are being saved between calls */
2595 ntstatus = dptr_create(conn,
2596 req,
2597 NULL, /* fsp */
2598 directory,
2599 False,
2600 True,
2601 req->smbpid,
2602 mask,
2603 mask_contains_wcard,
2604 dirtype,
2605 &dirptr);
2607 if (!NT_STATUS_IS_OK(ntstatus)) {
2608 reply_nterror(req, ntstatus);
2609 goto out;
2612 if (backup_priv) {
2613 /* Remember this in case we have
2614 to do a findnext. */
2615 dptr_set_priv(dirptr);
2618 dptr_num = dptr_dnum(dirptr);
2619 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2621 /* Initialize per TRANS2_FIND_FIRST operation data */
2622 dptr_init_search_op(dirptr);
2624 /* We don't need to check for VOL here as this is returned by
2625 a different TRANS2 call. */
2627 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2628 directory,lp_dontdescend(ctx, SNUM(conn))));
2629 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2630 dont_descend = True;
2632 p = pdata;
2633 space_remaining = max_data_bytes;
2634 out_of_space = False;
2636 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2637 bool got_exact_match = False;
2639 /* this is a heuristic to avoid seeking the dirptr except when
2640 absolutely necessary. It allows for a filename of about 40 chars */
2641 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2642 out_of_space = True;
2643 finished = False;
2644 } else {
2645 finished = !get_lanman2_dir_entry(ctx,
2646 conn,
2647 dirptr,
2648 req->flags2,
2649 mask,dirtype,info_level,
2650 requires_resume_key,dont_descend,
2651 ask_sharemode,
2652 &p,pdata,data_end,
2653 space_remaining, &out_of_space,
2654 &got_exact_match,
2655 &last_entry_off, ea_list);
2658 if (finished && out_of_space)
2659 finished = False;
2661 if (!finished && !out_of_space)
2662 numentries++;
2665 * As an optimisation if we know we aren't looking
2666 * for a wildcard name (ie. the name matches the wildcard exactly)
2667 * then we can finish on any (first) match.
2668 * This speeds up large directory searches. JRA.
2671 if(got_exact_match)
2672 finished = True;
2674 /* Ensure space_remaining never goes -ve. */
2675 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2676 space_remaining = 0;
2677 out_of_space = true;
2678 } else {
2679 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2683 /* Check if we can close the dirptr */
2684 if(close_after_first || (finished && close_if_end)) {
2685 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2686 dptr_close(sconn, &dptr_num);
2690 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2691 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2692 * the protocol level is less than NT1. Tested with smbclient. JRA.
2693 * This should fix the OS/2 client bug #2335.
2696 if(numentries == 0) {
2697 dptr_close(sconn, &dptr_num);
2698 if (get_Protocol() < PROTOCOL_NT1) {
2699 reply_force_doserror(req, ERRDOS, ERRnofiles);
2700 goto out;
2701 } else {
2702 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2703 ERRDOS, ERRbadfile);
2704 goto out;
2708 /* At this point pdata points to numentries directory entries. */
2710 /* Set up the return parameter block */
2711 SSVAL(params,0,dptr_num);
2712 SSVAL(params,2,numentries);
2713 SSVAL(params,4,finished);
2714 SSVAL(params,6,0); /* Never an EA error */
2715 SSVAL(params,8,last_entry_off);
2717 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2718 max_data_bytes);
2720 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2721 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2722 if (!directory) {
2723 reply_nterror(req, NT_STATUS_NO_MEMORY);
2727 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2728 smb_fn_name(req->cmd),
2729 mask, directory, dirtype, numentries ) );
2732 * Force a name mangle here to ensure that the
2733 * mask as an 8.3 name is top of the mangled cache.
2734 * The reasons for this are subtle. Don't remove
2735 * this code unless you know what you are doing
2736 * (see PR#13758). JRA.
2739 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2740 char mangled_name[13];
2741 name_to_8_3(mask, mangled_name, True, conn->params);
2743 out:
2745 if (backup_priv) {
2746 unbecome_root();
2749 TALLOC_FREE(smb_dname);
2750 return;
2753 /****************************************************************************
2754 Reply to a TRANS2_FINDNEXT.
2755 ****************************************************************************/
2757 static void call_trans2findnext(connection_struct *conn,
2758 struct smb_request *req,
2759 char **pparams, int total_params,
2760 char **ppdata, int total_data,
2761 unsigned int max_data_bytes)
2763 /* We must be careful here that we don't return more than the
2764 allowed number of data bytes. If this means returning fewer than
2765 maxentries then so be it. We assume that the redirector has
2766 enough room for the fixed number of parameter bytes it has
2767 requested. */
2768 char *params = *pparams;
2769 char *pdata = *ppdata;
2770 char *data_end;
2771 int dptr_num;
2772 int maxentries;
2773 uint16 info_level;
2774 uint32 resume_key;
2775 uint16 findnext_flags;
2776 bool close_after_request;
2777 bool close_if_end;
2778 bool requires_resume_key;
2779 bool continue_bit;
2780 bool mask_contains_wcard = False;
2781 char *resume_name = NULL;
2782 const char *mask = NULL;
2783 const char *directory = NULL;
2784 char *p = NULL;
2785 uint16 dirtype;
2786 int numentries = 0;
2787 int i, last_entry_off=0;
2788 bool finished = False;
2789 bool dont_descend = False;
2790 bool out_of_space = False;
2791 int space_remaining;
2792 struct ea_list *ea_list = NULL;
2793 NTSTATUS ntstatus = NT_STATUS_OK;
2794 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2795 TALLOC_CTX *ctx = talloc_tos();
2796 struct dptr_struct *dirptr;
2797 struct smbd_server_connection *sconn = req->sconn;
2798 bool backup_priv = false;
2800 if (total_params < 13) {
2801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 return;
2805 dptr_num = SVAL(params,0);
2806 maxentries = SVAL(params,2);
2807 info_level = SVAL(params,4);
2808 resume_key = IVAL(params,6);
2809 findnext_flags = SVAL(params,10);
2810 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2811 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2812 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2813 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2815 if (!continue_bit) {
2816 /* We only need resume_name if continue_bit is zero. */
2817 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2818 params+12,
2819 total_params - 12, STR_TERMINATE, &ntstatus,
2820 &mask_contains_wcard);
2821 if (!NT_STATUS_IS_OK(ntstatus)) {
2822 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2823 complain (it thinks we're asking for the directory above the shared
2824 path or an invalid name). Catch this as the resume name is only compared, never used in
2825 a file access. JRA. */
2826 srvstr_pull_talloc(ctx, params, req->flags2,
2827 &resume_name, params+12,
2828 total_params - 12,
2829 STR_TERMINATE);
2831 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2832 reply_nterror(req, ntstatus);
2833 return;
2838 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2839 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2840 resume_key = %d resume name = %s continue=%d level = %d\n",
2841 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2842 requires_resume_key, resume_key,
2843 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2845 if (!maxentries) {
2846 /* W2K3 seems to treat zero as 1. */
2847 maxentries = 1;
2850 switch (info_level) {
2851 case SMB_FIND_INFO_STANDARD:
2852 case SMB_FIND_EA_SIZE:
2853 case SMB_FIND_EA_LIST:
2854 case SMB_FIND_FILE_DIRECTORY_INFO:
2855 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2856 case SMB_FIND_FILE_NAMES_INFO:
2857 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2858 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2859 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2860 break;
2861 case SMB_FIND_FILE_UNIX:
2862 case SMB_FIND_FILE_UNIX_INFO2:
2863 /* Always use filesystem for UNIX mtime query. */
2864 ask_sharemode = false;
2865 if (!lp_unix_extensions()) {
2866 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2867 return;
2869 break;
2870 default:
2871 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2872 return;
2875 if (info_level == SMB_FIND_EA_LIST) {
2876 uint32 ea_size;
2878 if (total_data < 4) {
2879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2880 return;
2883 ea_size = IVAL(pdata,0);
2884 if (ea_size != total_data) {
2885 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2886 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2888 return;
2891 if (!lp_ea_support(SNUM(conn))) {
2892 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2893 return;
2896 /* Pull out the list of names. */
2897 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2898 if (!ea_list) {
2899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2900 return;
2904 *ppdata = (char *)SMB_REALLOC(
2905 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2906 if(*ppdata == NULL) {
2907 reply_nterror(req, NT_STATUS_NO_MEMORY);
2908 return;
2911 pdata = *ppdata;
2912 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2914 /* Realloc the params space */
2915 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2916 if(*pparams == NULL ) {
2917 reply_nterror(req, NT_STATUS_NO_MEMORY);
2918 return;
2921 params = *pparams;
2923 /* Check that the dptr is valid */
2924 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2925 reply_nterror(req, STATUS_NO_MORE_FILES);
2926 return;
2929 directory = dptr_path(sconn, dptr_num);
2931 /* Get the wildcard mask from the dptr */
2932 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2933 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2934 reply_nterror(req, STATUS_NO_MORE_FILES);
2935 return;
2938 /* Get the attr mask from the dptr */
2939 dirtype = dptr_attr(sconn, dptr_num);
2941 backup_priv = dptr_get_priv(dirptr);
2943 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2944 "backup_priv = %d\n",
2945 dptr_num, mask, dirtype,
2946 (long)dirptr,
2947 dptr_TellDir(dirptr),
2948 (int)backup_priv));
2950 /* Initialize per TRANS2_FIND_NEXT operation data */
2951 dptr_init_search_op(dirptr);
2953 /* We don't need to check for VOL here as this is returned by
2954 a different TRANS2 call. */
2956 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2957 directory,lp_dontdescend(ctx, SNUM(conn))));
2958 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2959 dont_descend = True;
2961 p = pdata;
2962 space_remaining = max_data_bytes;
2963 out_of_space = False;
2965 if (backup_priv) {
2966 become_root();
2970 * Seek to the correct position. We no longer use the resume key but
2971 * depend on the last file name instead.
2974 if(!continue_bit && resume_name && *resume_name) {
2975 SMB_STRUCT_STAT st;
2977 long current_pos = 0;
2979 * Remember, name_to_8_3 is called by
2980 * get_lanman2_dir_entry(), so the resume name
2981 * could be mangled. Ensure we check the unmangled name.
2984 if (mangle_is_mangled(resume_name, conn->params)) {
2985 char *new_resume_name = NULL;
2986 mangle_lookup_name_from_8_3(ctx,
2987 resume_name,
2988 &new_resume_name,
2989 conn->params);
2990 if (new_resume_name) {
2991 resume_name = new_resume_name;
2996 * Fix for NT redirector problem triggered by resume key indexes
2997 * changing between directory scans. We now return a resume key of 0
2998 * and instead look for the filename to continue from (also given
2999 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3000 * findfirst/findnext (as is usual) then the directory pointer
3001 * should already be at the correct place.
3004 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3005 } /* end if resume_name && !continue_bit */
3007 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3008 bool got_exact_match = False;
3010 /* this is a heuristic to avoid seeking the dirptr except when
3011 absolutely necessary. It allows for a filename of about 40 chars */
3012 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3013 out_of_space = True;
3014 finished = False;
3015 } else {
3016 finished = !get_lanman2_dir_entry(ctx,
3017 conn,
3018 dirptr,
3019 req->flags2,
3020 mask,dirtype,info_level,
3021 requires_resume_key,dont_descend,
3022 ask_sharemode,
3023 &p,pdata,data_end,
3024 space_remaining, &out_of_space,
3025 &got_exact_match,
3026 &last_entry_off, ea_list);
3029 if (finished && out_of_space)
3030 finished = False;
3032 if (!finished && !out_of_space)
3033 numentries++;
3036 * As an optimisation if we know we aren't looking
3037 * for a wildcard name (ie. the name matches the wildcard exactly)
3038 * then we can finish on any (first) match.
3039 * This speeds up large directory searches. JRA.
3042 if(got_exact_match)
3043 finished = True;
3045 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3048 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3049 smb_fn_name(req->cmd),
3050 mask, directory, dirtype, numentries ) );
3052 /* Check if we can close the dirptr */
3053 if(close_after_request || (finished && close_if_end)) {
3054 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3055 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3058 if (backup_priv) {
3059 unbecome_root();
3062 /* Set up the return parameter block */
3063 SSVAL(params,0,numentries);
3064 SSVAL(params,2,finished);
3065 SSVAL(params,4,0); /* Never an EA error */
3066 SSVAL(params,6,last_entry_off);
3068 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3069 max_data_bytes);
3071 return;
3074 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3076 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3077 return objid;
3080 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3082 SMB_ASSERT(extended_info != NULL);
3084 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3085 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3086 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3087 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3088 #ifdef SAMBA_VERSION_REVISION
3089 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3090 #endif
3091 extended_info->samba_subversion = 0;
3092 #ifdef SAMBA_VERSION_RC_RELEASE
3093 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3094 #else
3095 #ifdef SAMBA_VERSION_PRE_RELEASE
3096 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3097 #endif
3098 #endif
3099 #ifdef SAMBA_VERSION_VENDOR_PATCH
3100 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3101 #endif
3102 extended_info->samba_gitcommitdate = 0;
3103 #ifdef SAMBA_VERSION_COMMIT_TIME
3104 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3105 #endif
3107 memset(extended_info->samba_version_string, 0,
3108 sizeof(extended_info->samba_version_string));
3110 snprintf (extended_info->samba_version_string,
3111 sizeof(extended_info->samba_version_string),
3112 "%s", samba_version_string());
3115 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3116 TALLOC_CTX *mem_ctx,
3117 uint16_t info_level,
3118 uint16_t flags2,
3119 unsigned int max_data_bytes,
3120 size_t *fixed_portion,
3121 struct smb_filename *fname,
3122 char **ppdata,
3123 int *ret_data_len)
3125 char *pdata, *end_data;
3126 int data_len = 0, len;
3127 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3128 int snum = SNUM(conn);
3129 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3130 char *filename = NULL;
3131 uint32 additional_flags = 0;
3132 struct smb_filename smb_fname;
3133 SMB_STRUCT_STAT st;
3134 NTSTATUS status = NT_STATUS_OK;
3136 if (fname == NULL || fname->base_name == NULL) {
3137 filename = ".";
3138 } else {
3139 filename = fname->base_name;
3142 if (IS_IPC(conn)) {
3143 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3144 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3145 "info level (0x%x) on IPC$.\n",
3146 (unsigned int)info_level));
3147 return NT_STATUS_ACCESS_DENIED;
3151 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3153 ZERO_STRUCT(smb_fname);
3154 smb_fname.base_name = discard_const_p(char, filename);
3156 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3157 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3158 return map_nt_error_from_unix(errno);
3161 st = smb_fname.st;
3163 *ppdata = (char *)SMB_REALLOC(
3164 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3165 if (*ppdata == NULL) {
3166 return NT_STATUS_NO_MEMORY;
3169 pdata = *ppdata;
3170 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3171 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3173 *fixed_portion = 0;
3175 switch (info_level) {
3176 case SMB_INFO_ALLOCATION:
3178 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3179 data_len = 18;
3180 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3181 return map_nt_error_from_unix(errno);
3184 block_size = lp_block_size(snum);
3185 if (bsize < block_size) {
3186 uint64_t factor = block_size/bsize;
3187 bsize = block_size;
3188 dsize /= factor;
3189 dfree /= factor;
3191 if (bsize > block_size) {
3192 uint64_t factor = bsize/block_size;
3193 bsize = block_size;
3194 dsize *= factor;
3195 dfree *= factor;
3197 bytes_per_sector = 512;
3198 sectors_per_unit = bsize/bytes_per_sector;
3200 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3201 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3202 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3204 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3205 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3206 SIVAL(pdata,l1_cUnit,dsize);
3207 SIVAL(pdata,l1_cUnitAvail,dfree);
3208 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3209 break;
3212 case SMB_INFO_VOLUME:
3213 /* Return volume name */
3215 * Add volume serial number - hash of a combination of
3216 * the called hostname and the service name.
3218 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3220 * Win2k3 and previous mess this up by sending a name length
3221 * one byte short. I believe only older clients (OS/2 Win9x) use
3222 * this call so try fixing this by adding a terminating null to
3223 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3225 len = srvstr_push(
3226 pdata, flags2,
3227 pdata+l2_vol_szVolLabel, vname,
3228 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3229 STR_NOALIGN|STR_TERMINATE);
3230 SCVAL(pdata,l2_vol_cch,len);
3231 data_len = l2_vol_szVolLabel + len;
3232 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3233 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3234 len, vname));
3235 break;
3237 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3238 case SMB_FS_ATTRIBUTE_INFORMATION:
3240 additional_flags = 0;
3241 #if defined(HAVE_SYS_QUOTAS)
3242 additional_flags |= FILE_VOLUME_QUOTAS;
3243 #endif
3245 if(lp_nt_acl_support(SNUM(conn))) {
3246 additional_flags |= FILE_PERSISTENT_ACLS;
3249 /* Capabilities are filled in at connection time through STATVFS call */
3250 additional_flags |= conn->fs_capabilities;
3251 additional_flags |= lp_parm_int(conn->params->service,
3252 "share", "fake_fscaps",
3255 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3256 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3257 additional_flags); /* FS ATTRIBUTES */
3259 SIVAL(pdata,4,255); /* Max filename component length */
3260 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3261 and will think we can't do long filenames */
3262 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3263 PTR_DIFF(end_data, pdata+12),
3264 STR_UNICODE);
3265 SIVAL(pdata,8,len);
3266 data_len = 12 + len;
3267 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3268 /* the client only requested a portion of the
3269 file system name */
3270 data_len = max_data_bytes;
3271 status = STATUS_BUFFER_OVERFLOW;
3273 *fixed_portion = 16;
3274 break;
3276 case SMB_QUERY_FS_LABEL_INFO:
3277 case SMB_FS_LABEL_INFORMATION:
3278 len = srvstr_push(pdata, flags2, pdata+4, vname,
3279 PTR_DIFF(end_data, pdata+4), 0);
3280 data_len = 4 + len;
3281 SIVAL(pdata,0,len);
3282 break;
3284 case SMB_QUERY_FS_VOLUME_INFO:
3285 case SMB_FS_VOLUME_INFORMATION:
3288 * Add volume serial number - hash of a combination of
3289 * the called hostname and the service name.
3291 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3292 (str_checksum(get_local_machine_name())<<16));
3294 /* Max label len is 32 characters. */
3295 len = srvstr_push(pdata, flags2, pdata+18, vname,
3296 PTR_DIFF(end_data, pdata+18),
3297 STR_UNICODE);
3298 SIVAL(pdata,12,len);
3299 data_len = 18+len;
3301 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3302 (int)strlen(vname),vname,
3303 lp_servicename(talloc_tos(), snum)));
3304 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3305 /* the client only requested a portion of the
3306 volume label */
3307 data_len = max_data_bytes;
3308 status = STATUS_BUFFER_OVERFLOW;
3310 *fixed_portion = 24;
3311 break;
3313 case SMB_QUERY_FS_SIZE_INFO:
3314 case SMB_FS_SIZE_INFORMATION:
3316 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3317 data_len = 24;
3318 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3319 return map_nt_error_from_unix(errno);
3321 block_size = lp_block_size(snum);
3322 if (bsize < block_size) {
3323 uint64_t factor = block_size/bsize;
3324 bsize = block_size;
3325 dsize /= factor;
3326 dfree /= factor;
3328 if (bsize > block_size) {
3329 uint64_t factor = bsize/block_size;
3330 bsize = block_size;
3331 dsize *= factor;
3332 dfree *= factor;
3334 bytes_per_sector = 512;
3335 sectors_per_unit = bsize/bytes_per_sector;
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3337 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3338 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3339 SBIG_UINT(pdata,0,dsize);
3340 SBIG_UINT(pdata,8,dfree);
3341 SIVAL(pdata,16,sectors_per_unit);
3342 SIVAL(pdata,20,bytes_per_sector);
3343 *fixed_portion = 24;
3344 break;
3347 case SMB_FS_FULL_SIZE_INFORMATION:
3349 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3350 data_len = 32;
3351 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3352 return map_nt_error_from_unix(errno);
3354 block_size = lp_block_size(snum);
3355 if (bsize < block_size) {
3356 uint64_t factor = block_size/bsize;
3357 bsize = block_size;
3358 dsize /= factor;
3359 dfree /= factor;
3361 if (bsize > block_size) {
3362 uint64_t factor = bsize/block_size;
3363 bsize = block_size;
3364 dsize *= factor;
3365 dfree *= factor;
3367 bytes_per_sector = 512;
3368 sectors_per_unit = bsize/bytes_per_sector;
3369 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3370 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3371 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3372 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3373 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3374 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3375 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3376 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3377 *fixed_portion = 32;
3378 break;
3381 case SMB_QUERY_FS_DEVICE_INFO:
3382 case SMB_FS_DEVICE_INFORMATION:
3384 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3386 if (!CAN_WRITE(conn)) {
3387 characteristics |= FILE_READ_ONLY_DEVICE;
3389 data_len = 8;
3390 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3391 SIVAL(pdata,4,characteristics);
3392 *fixed_portion = 8;
3393 break;
3396 #ifdef HAVE_SYS_QUOTAS
3397 case SMB_FS_QUOTA_INFORMATION:
3399 * what we have to send --metze:
3401 * Unknown1: 24 NULL bytes
3402 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3403 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3404 * Quota Flags: 2 byte :
3405 * Unknown3: 6 NULL bytes
3407 * 48 bytes total
3409 * details for Quota Flags:
3411 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3412 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3413 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3414 * 0x0001 Enable Quotas: enable quota for this fs
3418 /* we need to fake up a fsp here,
3419 * because its not send in this call
3421 files_struct fsp;
3422 SMB_NTQUOTA_STRUCT quotas;
3424 ZERO_STRUCT(fsp);
3425 ZERO_STRUCT(quotas);
3427 fsp.conn = conn;
3428 fsp.fnum = FNUM_FIELD_INVALID;
3430 /* access check */
3431 if (get_current_uid(conn) != 0) {
3432 DEBUG(0,("set_user_quota: access_denied "
3433 "service [%s] user [%s]\n",
3434 lp_servicename(talloc_tos(), SNUM(conn)),
3435 conn->session_info->unix_info->unix_name));
3436 return NT_STATUS_ACCESS_DENIED;
3439 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3440 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3441 return map_nt_error_from_unix(errno);
3444 data_len = 48;
3446 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3447 lp_servicename(talloc_tos(), SNUM(conn))));
3449 /* Unknown1 24 NULL bytes*/
3450 SBIG_UINT(pdata,0,(uint64_t)0);
3451 SBIG_UINT(pdata,8,(uint64_t)0);
3452 SBIG_UINT(pdata,16,(uint64_t)0);
3454 /* Default Soft Quota 8 bytes */
3455 SBIG_UINT(pdata,24,quotas.softlim);
3457 /* Default Hard Quota 8 bytes */
3458 SBIG_UINT(pdata,32,quotas.hardlim);
3460 /* Quota flag 2 bytes */
3461 SSVAL(pdata,40,quotas.qflags);
3463 /* Unknown3 6 NULL bytes */
3464 SSVAL(pdata,42,0);
3465 SIVAL(pdata,44,0);
3467 break;
3469 #endif /* HAVE_SYS_QUOTAS */
3470 case SMB_FS_OBJECTID_INFORMATION:
3472 unsigned char objid[16];
3473 struct smb_extended_info extended_info;
3474 memcpy(pdata,create_volume_objectid(conn, objid),16);
3475 samba_extended_info_version (&extended_info);
3476 SIVAL(pdata,16,extended_info.samba_magic);
3477 SIVAL(pdata,20,extended_info.samba_version);
3478 SIVAL(pdata,24,extended_info.samba_subversion);
3479 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3480 memcpy(pdata+36,extended_info.samba_version_string,28);
3481 data_len = 64;
3482 break;
3486 * Query the version and capabilities of the CIFS UNIX extensions
3487 * in use.
3490 case SMB_QUERY_CIFS_UNIX_INFO:
3492 bool large_write = lp_min_receive_file_size() &&
3493 !srv_is_signing_active(conn->sconn);
3494 bool large_read = !srv_is_signing_active(conn->sconn);
3495 int encrypt_caps = 0;
3497 if (!lp_unix_extensions()) {
3498 return NT_STATUS_INVALID_LEVEL;
3501 switch (conn->encrypt_level) {
3502 case SMB_SIGNING_OFF:
3503 encrypt_caps = 0;
3504 break;
3505 case SMB_SIGNING_IF_REQUIRED:
3506 case SMB_SIGNING_DEFAULT:
3507 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3508 break;
3509 case SMB_SIGNING_REQUIRED:
3510 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3511 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3512 large_write = false;
3513 large_read = false;
3514 break;
3517 data_len = 12;
3518 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3519 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3521 /* We have POSIX ACLs, pathname, encryption,
3522 * large read/write, and locking capability. */
3524 SBIG_UINT(pdata,4,((uint64_t)(
3525 CIFS_UNIX_POSIX_ACLS_CAP|
3526 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3527 CIFS_UNIX_FCNTL_LOCKS_CAP|
3528 CIFS_UNIX_EXTATTR_CAP|
3529 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3530 encrypt_caps|
3531 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3532 (large_write ?
3533 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3534 break;
3537 case SMB_QUERY_POSIX_FS_INFO:
3539 int rc;
3540 vfs_statvfs_struct svfs;
3542 if (!lp_unix_extensions()) {
3543 return NT_STATUS_INVALID_LEVEL;
3546 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3548 if (!rc) {
3549 data_len = 56;
3550 SIVAL(pdata,0,svfs.OptimalTransferSize);
3551 SIVAL(pdata,4,svfs.BlockSize);
3552 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3553 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3554 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3555 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3556 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3557 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3558 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3559 #ifdef EOPNOTSUPP
3560 } else if (rc == EOPNOTSUPP) {
3561 return NT_STATUS_INVALID_LEVEL;
3562 #endif /* EOPNOTSUPP */
3563 } else {
3564 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3565 return NT_STATUS_DOS(ERRSRV, ERRerror);
3567 break;
3570 case SMB_QUERY_POSIX_WHOAMI:
3572 uint32_t flags = 0;
3573 uint32_t sid_bytes;
3574 int i;
3576 if (!lp_unix_extensions()) {
3577 return NT_STATUS_INVALID_LEVEL;
3580 if (max_data_bytes < 40) {
3581 return NT_STATUS_BUFFER_TOO_SMALL;
3584 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3585 flags |= SMB_WHOAMI_GUEST;
3588 /* NOTE: 8 bytes for UID/GID, irrespective of native
3589 * platform size. This matches
3590 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3592 data_len = 4 /* flags */
3593 + 4 /* flag mask */
3594 + 8 /* uid */
3595 + 8 /* gid */
3596 + 4 /* ngroups */
3597 + 4 /* num_sids */
3598 + 4 /* SID bytes */
3599 + 4 /* pad/reserved */
3600 + (conn->session_info->unix_token->ngroups * 8)
3601 /* groups list */
3602 + (conn->session_info->security_token->num_sids *
3603 SID_MAX_SIZE)
3604 /* SID list */;
3606 SIVAL(pdata, 0, flags);
3607 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3608 SBIG_UINT(pdata, 8,
3609 (uint64_t)conn->session_info->unix_token->uid);
3610 SBIG_UINT(pdata, 16,
3611 (uint64_t)conn->session_info->unix_token->gid);
3614 if (data_len >= max_data_bytes) {
3615 /* Potential overflow, skip the GIDs and SIDs. */
3617 SIVAL(pdata, 24, 0); /* num_groups */
3618 SIVAL(pdata, 28, 0); /* num_sids */
3619 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3620 SIVAL(pdata, 36, 0); /* reserved */
3622 data_len = 40;
3623 break;
3626 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3627 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3629 /* We walk the SID list twice, but this call is fairly
3630 * infrequent, and I don't expect that it's performance
3631 * sensitive -- jpeach
3633 for (i = 0, sid_bytes = 0;
3634 i < conn->session_info->security_token->num_sids; ++i) {
3635 sid_bytes += ndr_size_dom_sid(
3636 &conn->session_info->security_token->sids[i],
3640 /* SID list byte count */
3641 SIVAL(pdata, 32, sid_bytes);
3643 /* 4 bytes pad/reserved - must be zero */
3644 SIVAL(pdata, 36, 0);
3645 data_len = 40;
3647 /* GID list */
3648 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3649 SBIG_UINT(pdata, data_len,
3650 (uint64_t)conn->session_info->unix_token->groups[i]);
3651 data_len += 8;
3654 /* SID list */
3655 for (i = 0;
3656 i < conn->session_info->security_token->num_sids; ++i) {
3657 int sid_len = ndr_size_dom_sid(
3658 &conn->session_info->security_token->sids[i],
3661 sid_linearize(pdata + data_len, sid_len,
3662 &conn->session_info->security_token->sids[i]);
3663 data_len += sid_len;
3666 break;
3669 case SMB_MAC_QUERY_FS_INFO:
3671 * Thursby MAC extension... ONLY on NTFS filesystems
3672 * once we do streams then we don't need this
3674 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3675 data_len = 88;
3676 SIVAL(pdata,84,0x100); /* Don't support mac... */
3677 break;
3679 /* drop through */
3680 default:
3681 return NT_STATUS_INVALID_LEVEL;
3684 *ret_data_len = data_len;
3685 return status;
3688 /****************************************************************************
3689 Reply to a TRANS2_QFSINFO (query filesystem info).
3690 ****************************************************************************/
3692 static void call_trans2qfsinfo(connection_struct *conn,
3693 struct smb_request *req,
3694 char **pparams, int total_params,
3695 char **ppdata, int total_data,
3696 unsigned int max_data_bytes)
3698 char *params = *pparams;
3699 uint16_t info_level;
3700 int data_len = 0;
3701 size_t fixed_portion;
3702 NTSTATUS status;
3704 if (total_params < 2) {
3705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3706 return;
3709 info_level = SVAL(params,0);
3711 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3712 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3713 DEBUG(0,("call_trans2qfsinfo: encryption required "
3714 "and info level 0x%x sent.\n",
3715 (unsigned int)info_level));
3716 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3717 return;
3721 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3723 status = smbd_do_qfsinfo(conn, req,
3724 info_level,
3725 req->flags2,
3726 max_data_bytes,
3727 &fixed_portion,
3728 NULL,
3729 ppdata, &data_len);
3730 if (!NT_STATUS_IS_OK(status)) {
3731 reply_nterror(req, status);
3732 return;
3735 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3736 max_data_bytes);
3738 DEBUG( 4, ( "%s info_level = %d\n",
3739 smb_fn_name(req->cmd), info_level) );
3741 return;
3744 /****************************************************************************
3745 Reply to a TRANS2_SETFSINFO (set filesystem info).
3746 ****************************************************************************/
3748 static void call_trans2setfsinfo(connection_struct *conn,
3749 struct smb_request *req,
3750 char **pparams, int total_params,
3751 char **ppdata, int total_data,
3752 unsigned int max_data_bytes)
3754 struct smbd_server_connection *sconn = req->sconn;
3755 char *pdata = *ppdata;
3756 char *params = *pparams;
3757 uint16 info_level;
3759 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3760 lp_servicename(talloc_tos(), SNUM(conn))));
3762 /* */
3763 if (total_params < 4) {
3764 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3765 total_params));
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 return;
3770 info_level = SVAL(params,2);
3772 if (IS_IPC(conn)) {
3773 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3774 info_level != SMB_SET_CIFS_UNIX_INFO) {
3775 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3776 "info level (0x%x) on IPC$.\n",
3777 (unsigned int)info_level));
3778 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3779 return;
3783 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3784 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3785 DEBUG(0,("call_trans2setfsinfo: encryption required "
3786 "and info level 0x%x sent.\n",
3787 (unsigned int)info_level));
3788 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3789 return;
3793 switch(info_level) {
3794 case SMB_SET_CIFS_UNIX_INFO:
3795 if (!lp_unix_extensions()) {
3796 DEBUG(2,("call_trans2setfsinfo: "
3797 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3798 "unix extensions off\n"));
3799 reply_nterror(req,
3800 NT_STATUS_INVALID_LEVEL);
3801 return;
3804 /* There should be 12 bytes of capabilities set. */
3805 if (total_data < 12) {
3806 reply_nterror(
3807 req,
3808 NT_STATUS_INVALID_PARAMETER);
3809 return;
3811 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3812 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3813 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3814 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3815 /* Just print these values for now. */
3816 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3817 "major = %u, minor = %u cap_low = 0x%x, "
3818 "cap_high = 0x%xn",
3819 (unsigned int)sconn->
3820 smb1.unix_info.client_major,
3821 (unsigned int)sconn->
3822 smb1.unix_info.client_minor,
3823 (unsigned int)sconn->
3824 smb1.unix_info.client_cap_low,
3825 (unsigned int)sconn->
3826 smb1.unix_info.client_cap_high));
3828 /* Here is where we must switch to posix pathname processing... */
3829 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3830 lp_set_posix_pathnames();
3831 mangle_change_to_posix();
3834 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3835 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3836 /* Client that knows how to do posix locks,
3837 * but not posix open/mkdir operations. Set a
3838 * default type for read/write checks. */
3840 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3843 break;
3845 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3847 NTSTATUS status;
3848 size_t param_len = 0;
3849 size_t data_len = total_data;
3851 if (!lp_unix_extensions()) {
3852 reply_nterror(
3853 req,
3854 NT_STATUS_INVALID_LEVEL);
3855 return;
3858 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3859 reply_nterror(
3860 req,
3861 NT_STATUS_NOT_SUPPORTED);
3862 return;
3865 if (req->sconn->smb1.echo_handler.trusted_fde) {
3866 DEBUG( 2,("call_trans2setfsinfo: "
3867 "request transport encryption disabled"
3868 "with 'fork echo handler = yes'\n"));
3869 reply_nterror(
3870 req,
3871 NT_STATUS_NOT_SUPPORTED);
3872 return;
3875 DEBUG( 4,("call_trans2setfsinfo: "
3876 "request transport encryption.\n"));
3878 status = srv_request_encryption_setup(conn,
3879 (unsigned char **)ppdata,
3880 &data_len,
3881 (unsigned char **)pparams,
3882 &param_len);
3884 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3885 !NT_STATUS_IS_OK(status)) {
3886 reply_nterror(req, status);
3887 return;
3890 send_trans2_replies(conn, req,
3891 NT_STATUS_OK,
3892 *pparams,
3893 param_len,
3894 *ppdata,
3895 data_len,
3896 max_data_bytes);
3898 if (NT_STATUS_IS_OK(status)) {
3899 /* Server-side transport
3900 * encryption is now *on*. */
3901 status = srv_encryption_start(conn);
3902 if (!NT_STATUS_IS_OK(status)) {
3903 char *reason = talloc_asprintf(talloc_tos(),
3904 "Failure in setting "
3905 "up encrypted transport: %s",
3906 nt_errstr(status));
3907 exit_server_cleanly(reason);
3910 return;
3913 case SMB_FS_QUOTA_INFORMATION:
3915 files_struct *fsp = NULL;
3916 SMB_NTQUOTA_STRUCT quotas;
3918 ZERO_STRUCT(quotas);
3920 /* access check */
3921 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3922 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3923 lp_servicename(talloc_tos(), SNUM(conn)),
3924 conn->session_info->unix_info->unix_name));
3925 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3926 return;
3929 /* note: normaly there're 48 bytes,
3930 * but we didn't use the last 6 bytes for now
3931 * --metze
3933 fsp = file_fsp(req, SVAL(params,0));
3935 if (!check_fsp_ntquota_handle(conn, req,
3936 fsp)) {
3937 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3938 reply_nterror(
3939 req, NT_STATUS_INVALID_HANDLE);
3940 return;
3943 if (total_data < 42) {
3944 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3945 total_data));
3946 reply_nterror(
3947 req,
3948 NT_STATUS_INVALID_PARAMETER);
3949 return;
3952 /* unknown_1 24 NULL bytes in pdata*/
3954 /* the soft quotas 8 bytes (uint64_t)*/
3955 quotas.softlim = BVAL(pdata,24);
3957 /* the hard quotas 8 bytes (uint64_t)*/
3958 quotas.hardlim = BVAL(pdata,32);
3960 /* quota_flags 2 bytes **/
3961 quotas.qflags = SVAL(pdata,40);
3963 /* unknown_2 6 NULL bytes follow*/
3965 /* now set the quotas */
3966 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3967 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3968 reply_nterror(req, map_nt_error_from_unix(errno));
3969 return;
3972 break;
3974 default:
3975 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3976 info_level));
3977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3978 return;
3979 break;
3983 * sending this reply works fine,
3984 * but I'm not sure it's the same
3985 * like windows do...
3986 * --metze
3988 reply_outbuf(req, 10, 0);
3991 #if defined(HAVE_POSIX_ACLS)
3992 /****************************************************************************
3993 Utility function to count the number of entries in a POSIX acl.
3994 ****************************************************************************/
3996 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3998 unsigned int ace_count = 0;
3999 int entry_id = SMB_ACL_FIRST_ENTRY;
4000 SMB_ACL_ENTRY_T entry;
4002 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4003 /* get_next... */
4004 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4005 entry_id = SMB_ACL_NEXT_ENTRY;
4007 ace_count++;
4009 return ace_count;
4012 /****************************************************************************
4013 Utility function to marshall a POSIX acl into wire format.
4014 ****************************************************************************/
4016 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4018 int entry_id = SMB_ACL_FIRST_ENTRY;
4019 SMB_ACL_ENTRY_T entry;
4021 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4022 SMB_ACL_TAG_T tagtype;
4023 SMB_ACL_PERMSET_T permset;
4024 unsigned char perms = 0;
4025 unsigned int own_grp;
4027 /* get_next... */
4028 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4029 entry_id = SMB_ACL_NEXT_ENTRY;
4032 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4033 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4034 return False;
4037 if (sys_acl_get_permset(entry, &permset) == -1) {
4038 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4039 return False;
4042 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4043 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4044 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4046 SCVAL(pdata,1,perms);
4048 switch (tagtype) {
4049 case SMB_ACL_USER_OBJ:
4050 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4051 own_grp = (unsigned int)pst->st_ex_uid;
4052 SIVAL(pdata,2,own_grp);
4053 SIVAL(pdata,6,0);
4054 break;
4055 case SMB_ACL_USER:
4057 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4058 if (!puid) {
4059 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4060 return False;
4062 own_grp = (unsigned int)*puid;
4063 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4064 SIVAL(pdata,2,own_grp);
4065 SIVAL(pdata,6,0);
4066 break;
4068 case SMB_ACL_GROUP_OBJ:
4069 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4070 own_grp = (unsigned int)pst->st_ex_gid;
4071 SIVAL(pdata,2,own_grp);
4072 SIVAL(pdata,6,0);
4073 break;
4074 case SMB_ACL_GROUP:
4076 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4077 if (!pgid) {
4078 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4079 return False;
4081 own_grp = (unsigned int)*pgid;
4082 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4083 SIVAL(pdata,2,own_grp);
4084 SIVAL(pdata,6,0);
4085 break;
4087 case SMB_ACL_MASK:
4088 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4089 SIVAL(pdata,2,0xFFFFFFFF);
4090 SIVAL(pdata,6,0xFFFFFFFF);
4091 break;
4092 case SMB_ACL_OTHER:
4093 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4094 SIVAL(pdata,2,0xFFFFFFFF);
4095 SIVAL(pdata,6,0xFFFFFFFF);
4096 break;
4097 default:
4098 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4099 return False;
4101 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4104 return True;
4106 #endif
4108 /****************************************************************************
4109 Store the FILE_UNIX_BASIC info.
4110 ****************************************************************************/
4112 static char *store_file_unix_basic(connection_struct *conn,
4113 char *pdata,
4114 files_struct *fsp,
4115 const SMB_STRUCT_STAT *psbuf)
4117 uint64_t file_index = get_FileIndex(conn, psbuf);
4118 dev_t devno;
4120 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4121 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4123 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4124 pdata += 8;
4126 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4127 pdata += 8;
4129 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4130 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4131 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4132 pdata += 24;
4134 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4135 SIVAL(pdata,4,0);
4136 pdata += 8;
4138 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4139 SIVAL(pdata,4,0);
4140 pdata += 8;
4142 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4143 pdata += 4;
4145 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4146 devno = psbuf->st_ex_rdev;
4147 } else {
4148 devno = psbuf->st_ex_dev;
4151 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4152 SIVAL(pdata,4,0);
4153 pdata += 8;
4155 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4156 SIVAL(pdata,4,0);
4157 pdata += 8;
4159 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4160 pdata += 8;
4162 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4163 SIVAL(pdata,4,0);
4164 pdata += 8;
4166 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4167 SIVAL(pdata,4,0);
4168 pdata += 8;
4170 return pdata;
4173 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4174 * the chflags(2) (or equivalent) flags.
4176 * XXX: this really should be behind the VFS interface. To do this, we would
4177 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4178 * Each VFS module could then implement its own mapping as appropriate for the
4179 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4181 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4182 info2_flags_map[] =
4184 #ifdef UF_NODUMP
4185 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4186 #endif
4188 #ifdef UF_IMMUTABLE
4189 { UF_IMMUTABLE, EXT_IMMUTABLE },
4190 #endif
4192 #ifdef UF_APPEND
4193 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4194 #endif
4196 #ifdef UF_HIDDEN
4197 { UF_HIDDEN, EXT_HIDDEN },
4198 #endif
4200 /* Do not remove. We need to guarantee that this array has at least one
4201 * entry to build on HP-UX.
4203 { 0, 0 }
4207 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4208 uint32 *smb_fflags, uint32 *smb_fmask)
4210 int i;
4212 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4213 *smb_fmask |= info2_flags_map[i].smb_fflag;
4214 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4215 *smb_fflags |= info2_flags_map[i].smb_fflag;
4220 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4221 const uint32 smb_fflags,
4222 const uint32 smb_fmask,
4223 int *stat_fflags)
4225 uint32 max_fmask = 0;
4226 int i;
4228 *stat_fflags = psbuf->st_ex_flags;
4230 /* For each flags requested in smb_fmask, check the state of the
4231 * corresponding flag in smb_fflags and set or clear the matching
4232 * stat flag.
4235 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4236 max_fmask |= info2_flags_map[i].smb_fflag;
4237 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4238 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4239 *stat_fflags |= info2_flags_map[i].stat_fflag;
4240 } else {
4241 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4246 /* If smb_fmask is asking to set any bits that are not supported by
4247 * our flag mappings, we should fail.
4249 if ((smb_fmask & max_fmask) != smb_fmask) {
4250 return False;
4253 return True;
4257 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4258 * of file flags and birth (create) time.
4260 static char *store_file_unix_basic_info2(connection_struct *conn,
4261 char *pdata,
4262 files_struct *fsp,
4263 const SMB_STRUCT_STAT *psbuf)
4265 uint32 file_flags = 0;
4266 uint32 flags_mask = 0;
4268 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4270 /* Create (birth) time 64 bit */
4271 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4272 pdata += 8;
4274 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4275 SIVAL(pdata, 0, file_flags); /* flags */
4276 SIVAL(pdata, 4, flags_mask); /* mask */
4277 pdata += 8;
4279 return pdata;
4282 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4283 const struct stream_struct *streams,
4284 char *data,
4285 unsigned int max_data_bytes,
4286 unsigned int *data_size)
4288 unsigned int i;
4289 unsigned int ofs = 0;
4291 if (max_data_bytes < 32) {
4292 return NT_STATUS_INFO_LENGTH_MISMATCH;
4295 for (i = 0; i < num_streams; i++) {
4296 unsigned int next_offset;
4297 size_t namelen;
4298 smb_ucs2_t *namebuf;
4300 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4301 streams[i].name, &namelen) ||
4302 namelen <= 2)
4304 return NT_STATUS_INVALID_PARAMETER;
4308 * name_buf is now null-terminated, we need to marshall as not
4309 * terminated
4312 namelen -= 2;
4315 * We cannot overflow ...
4317 if ((ofs + 24 + namelen) > max_data_bytes) {
4318 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4319 i));
4320 TALLOC_FREE(namebuf);
4321 return STATUS_BUFFER_OVERFLOW;
4324 SIVAL(data, ofs+4, namelen);
4325 SOFF_T(data, ofs+8, streams[i].size);
4326 SOFF_T(data, ofs+16, streams[i].alloc_size);
4327 memcpy(data+ofs+24, namebuf, namelen);
4328 TALLOC_FREE(namebuf);
4330 next_offset = ofs + 24 + namelen;
4332 if (i == num_streams-1) {
4333 SIVAL(data, ofs, 0);
4335 else {
4336 unsigned int align = ndr_align_size(next_offset, 8);
4338 if ((next_offset + align) > max_data_bytes) {
4339 DEBUG(10, ("refusing to overflow align "
4340 "reply at stream %u\n",
4341 i));
4342 TALLOC_FREE(namebuf);
4343 return STATUS_BUFFER_OVERFLOW;
4346 memset(data+next_offset, 0, align);
4347 next_offset += align;
4349 SIVAL(data, ofs, next_offset - ofs);
4350 ofs = next_offset;
4353 ofs = next_offset;
4356 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4358 *data_size = ofs;
4360 return NT_STATUS_OK;
4363 /****************************************************************************
4364 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4365 ****************************************************************************/
4367 static void call_trans2qpipeinfo(connection_struct *conn,
4368 struct smb_request *req,
4369 unsigned int tran_call,
4370 char **pparams, int total_params,
4371 char **ppdata, int total_data,
4372 unsigned int max_data_bytes)
4374 char *params = *pparams;
4375 char *pdata = *ppdata;
4376 unsigned int data_size = 0;
4377 unsigned int param_size = 2;
4378 uint16 info_level;
4379 files_struct *fsp;
4381 if (!params) {
4382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4383 return;
4386 if (total_params < 4) {
4387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4388 return;
4391 fsp = file_fsp(req, SVAL(params,0));
4392 if (!fsp_is_np(fsp)) {
4393 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4394 return;
4397 info_level = SVAL(params,2);
4399 *pparams = (char *)SMB_REALLOC(*pparams,2);
4400 if (*pparams == NULL) {
4401 reply_nterror(req, NT_STATUS_NO_MEMORY);
4402 return;
4404 params = *pparams;
4405 SSVAL(params,0,0);
4406 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4407 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4408 if (*ppdata == NULL ) {
4409 reply_nterror(req, NT_STATUS_NO_MEMORY);
4410 return;
4412 pdata = *ppdata;
4414 switch (info_level) {
4415 case SMB_FILE_STANDARD_INFORMATION:
4416 memset(pdata,0,24);
4417 SOFF_T(pdata,0,4096LL);
4418 SIVAL(pdata,16,1);
4419 SIVAL(pdata,20,1);
4420 data_size = 24;
4421 break;
4423 default:
4424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4425 return;
4428 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4429 max_data_bytes);
4431 return;
4434 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4435 TALLOC_CTX *mem_ctx,
4436 uint16_t info_level,
4437 files_struct *fsp,
4438 struct smb_filename *smb_fname,
4439 bool delete_pending,
4440 struct timespec write_time_ts,
4441 struct ea_list *ea_list,
4442 int lock_data_count,
4443 char *lock_data,
4444 uint16_t flags2,
4445 unsigned int max_data_bytes,
4446 size_t *fixed_portion,
4447 char **ppdata,
4448 unsigned int *pdata_size)
4450 char *pdata = *ppdata;
4451 char *dstart, *dend;
4452 unsigned int data_size;
4453 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4454 time_t create_time, mtime, atime, c_time;
4455 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4456 char *p;
4457 char *base_name;
4458 char *dos_fname;
4459 int mode;
4460 int nlink;
4461 NTSTATUS status;
4462 uint64_t file_size = 0;
4463 uint64_t pos = 0;
4464 uint64_t allocation_size = 0;
4465 uint64_t file_index = 0;
4466 uint32_t access_mask = 0;
4468 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4469 return NT_STATUS_INVALID_LEVEL;
4472 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4473 smb_fname_str_dbg(smb_fname),
4474 fsp_fnum_dbg(fsp),
4475 info_level, max_data_bytes));
4477 mode = dos_mode(conn, smb_fname);
4478 nlink = psbuf->st_ex_nlink;
4480 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4481 nlink = 1;
4484 if ((nlink > 0) && delete_pending) {
4485 nlink -= 1;
4488 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4489 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4490 if (*ppdata == NULL) {
4491 return NT_STATUS_NO_MEMORY;
4493 pdata = *ppdata;
4494 dstart = pdata;
4495 dend = dstart + data_size - 1;
4497 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4498 update_stat_ex_mtime(psbuf, write_time_ts);
4501 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4502 mtime_ts = psbuf->st_ex_mtime;
4503 atime_ts = psbuf->st_ex_atime;
4504 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4506 if (lp_dos_filetime_resolution(SNUM(conn))) {
4507 dos_filetime_timespec(&create_time_ts);
4508 dos_filetime_timespec(&mtime_ts);
4509 dos_filetime_timespec(&atime_ts);
4510 dos_filetime_timespec(&ctime_ts);
4513 create_time = convert_timespec_to_time_t(create_time_ts);
4514 mtime = convert_timespec_to_time_t(mtime_ts);
4515 atime = convert_timespec_to_time_t(atime_ts);
4516 c_time = convert_timespec_to_time_t(ctime_ts);
4518 p = strrchr_m(smb_fname->base_name,'/');
4519 if (!p)
4520 base_name = smb_fname->base_name;
4521 else
4522 base_name = p+1;
4524 /* NT expects the name to be in an exact form of the *full*
4525 filename. See the trans2 torture test */
4526 if (ISDOT(base_name)) {
4527 dos_fname = talloc_strdup(mem_ctx, "\\");
4528 if (!dos_fname) {
4529 return NT_STATUS_NO_MEMORY;
4531 } else {
4532 dos_fname = talloc_asprintf(mem_ctx,
4533 "\\%s",
4534 smb_fname->base_name);
4535 if (!dos_fname) {
4536 return NT_STATUS_NO_MEMORY;
4538 if (is_ntfs_stream_smb_fname(smb_fname)) {
4539 dos_fname = talloc_asprintf(dos_fname, "%s",
4540 smb_fname->stream_name);
4541 if (!dos_fname) {
4542 return NT_STATUS_NO_MEMORY;
4546 string_replace(dos_fname, '/', '\\');
4549 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4551 if (!fsp) {
4552 /* Do we have this path open ? */
4553 files_struct *fsp1;
4554 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4555 fsp1 = file_find_di_first(conn->sconn, fileid);
4556 if (fsp1 && fsp1->initial_allocation_size) {
4557 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4561 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4562 file_size = get_file_size_stat(psbuf);
4565 if (fsp) {
4566 pos = fsp->fh->position_information;
4569 if (fsp) {
4570 access_mask = fsp->access_mask;
4571 } else {
4572 /* GENERIC_EXECUTE mapping from Windows */
4573 access_mask = 0x12019F;
4576 /* This should be an index number - looks like
4577 dev/ino to me :-)
4579 I think this causes us to fail the IFSKIT
4580 BasicFileInformationTest. -tpot */
4581 file_index = get_FileIndex(conn, psbuf);
4583 *fixed_portion = 0;
4585 switch (info_level) {
4586 case SMB_INFO_STANDARD:
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4588 data_size = 22;
4589 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4590 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4591 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4592 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4593 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4594 SSVAL(pdata,l1_attrFile,mode);
4595 break;
4597 case SMB_INFO_QUERY_EA_SIZE:
4599 unsigned int ea_size =
4600 estimate_ea_size(conn, fsp,
4601 smb_fname);
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4603 data_size = 26;
4604 srv_put_dos_date2(pdata,0,create_time);
4605 srv_put_dos_date2(pdata,4,atime);
4606 srv_put_dos_date2(pdata,8,mtime); /* write time */
4607 SIVAL(pdata,12,(uint32)file_size);
4608 SIVAL(pdata,16,(uint32)allocation_size);
4609 SSVAL(pdata,20,mode);
4610 SIVAL(pdata,22,ea_size);
4611 break;
4614 case SMB_INFO_IS_NAME_VALID:
4615 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4616 if (fsp) {
4617 /* os/2 needs this ? really ?*/
4618 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4620 /* This is only reached for qpathinfo */
4621 data_size = 0;
4622 break;
4624 case SMB_INFO_QUERY_EAS_FROM_LIST:
4626 size_t total_ea_len = 0;
4627 struct ea_list *ea_file_list = NULL;
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4630 status =
4631 get_ea_list_from_file(mem_ctx, conn, fsp,
4632 smb_fname,
4633 &total_ea_len, &ea_file_list);
4634 if (!NT_STATUS_IS_OK(status)) {
4635 return status;
4638 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4640 if (!ea_list || (total_ea_len > data_size)) {
4641 data_size = 4;
4642 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4643 break;
4646 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4647 break;
4650 case SMB_INFO_QUERY_ALL_EAS:
4652 /* We have data_size bytes to put EA's into. */
4653 size_t total_ea_len = 0;
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4656 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4657 smb_fname,
4658 &total_ea_len, &ea_list);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 return status;
4663 if (!ea_list || (total_ea_len > data_size)) {
4664 data_size = 4;
4665 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4666 break;
4669 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4670 break;
4673 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4675 /* This is FileFullEaInformation - 0xF which maps to
4676 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4678 /* We have data_size bytes to put EA's into. */
4679 size_t total_ea_len = 0;
4680 struct ea_list *ea_file_list = NULL;
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4684 /*TODO: add filtering and index handling */
4686 status =
4687 get_ea_list_from_file(mem_ctx, conn, fsp,
4688 smb_fname,
4689 &total_ea_len, &ea_file_list);
4690 if (!NT_STATUS_IS_OK(status)) {
4691 return status;
4693 if (!ea_file_list) {
4694 return NT_STATUS_NO_EAS_ON_FILE;
4697 status = fill_ea_chained_buffer(mem_ctx,
4698 pdata,
4699 data_size,
4700 &data_size,
4701 conn, ea_file_list);
4702 if (!NT_STATUS_IS_OK(status)) {
4703 return status;
4705 break;
4708 case SMB_FILE_BASIC_INFORMATION:
4709 case SMB_QUERY_FILE_BASIC_INFO:
4711 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4713 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4714 } else {
4715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4716 data_size = 40;
4717 SIVAL(pdata,36,0);
4719 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4722 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4723 SIVAL(pdata,32,mode);
4725 DEBUG(5,("SMB_QFBI - "));
4726 DEBUG(5,("create: %s ", ctime(&create_time)));
4727 DEBUG(5,("access: %s ", ctime(&atime)));
4728 DEBUG(5,("write: %s ", ctime(&mtime)));
4729 DEBUG(5,("change: %s ", ctime(&c_time)));
4730 DEBUG(5,("mode: %x\n", mode));
4731 *fixed_portion = data_size;
4732 break;
4734 case SMB_FILE_STANDARD_INFORMATION:
4735 case SMB_QUERY_FILE_STANDARD_INFO:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4738 data_size = 24;
4739 SOFF_T(pdata,0,allocation_size);
4740 SOFF_T(pdata,8,file_size);
4741 SIVAL(pdata,16,nlink);
4742 SCVAL(pdata,20,delete_pending?1:0);
4743 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4744 SSVAL(pdata,22,0); /* Padding. */
4745 *fixed_portion = 24;
4746 break;
4748 case SMB_FILE_EA_INFORMATION:
4749 case SMB_QUERY_FILE_EA_INFO:
4751 unsigned int ea_size =
4752 estimate_ea_size(conn, fsp, smb_fname);
4753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4754 data_size = 4;
4755 *fixed_portion = 4;
4756 SIVAL(pdata,0,ea_size);
4757 break;
4760 /* Get the 8.3 name - used if NT SMB was negotiated. */
4761 case SMB_QUERY_FILE_ALT_NAME_INFO:
4762 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4764 int len;
4765 char mangled_name[13];
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4767 if (!name_to_8_3(base_name,mangled_name,
4768 True,conn->params)) {
4769 return NT_STATUS_NO_MEMORY;
4771 len = srvstr_push(dstart, flags2,
4772 pdata+4, mangled_name,
4773 PTR_DIFF(dend, pdata+4),
4774 STR_UNICODE);
4775 data_size = 4 + len;
4776 SIVAL(pdata,0,len);
4777 *fixed_portion = 8;
4778 break;
4781 case SMB_QUERY_FILE_NAME_INFO:
4783 int len;
4785 this must be *exactly* right for ACLs on mapped drives to work
4787 len = srvstr_push(dstart, flags2,
4788 pdata+4, dos_fname,
4789 PTR_DIFF(dend, pdata+4),
4790 STR_UNICODE);
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4792 data_size = 4 + len;
4793 SIVAL(pdata,0,len);
4794 break;
4797 case SMB_FILE_ALLOCATION_INFORMATION:
4798 case SMB_QUERY_FILE_ALLOCATION_INFO:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4800 data_size = 8;
4801 SOFF_T(pdata,0,allocation_size);
4802 break;
4804 case SMB_FILE_END_OF_FILE_INFORMATION:
4805 case SMB_QUERY_FILE_END_OF_FILEINFO:
4806 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4807 data_size = 8;
4808 SOFF_T(pdata,0,file_size);
4809 break;
4811 case SMB_QUERY_FILE_ALL_INFO:
4812 case SMB_FILE_ALL_INFORMATION:
4814 int len;
4815 unsigned int ea_size =
4816 estimate_ea_size(conn, fsp, smb_fname);
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4818 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4819 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4820 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4821 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4822 SIVAL(pdata,32,mode);
4823 SIVAL(pdata,36,0); /* padding. */
4824 pdata += 40;
4825 SOFF_T(pdata,0,allocation_size);
4826 SOFF_T(pdata,8,file_size);
4827 SIVAL(pdata,16,nlink);
4828 SCVAL(pdata,20,delete_pending);
4829 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4830 SSVAL(pdata,22,0);
4831 pdata += 24;
4832 SIVAL(pdata,0,ea_size);
4833 pdata += 4; /* EA info */
4834 len = srvstr_push(dstart, flags2,
4835 pdata+4, dos_fname,
4836 PTR_DIFF(dend, pdata+4),
4837 STR_UNICODE);
4838 SIVAL(pdata,0,len);
4839 pdata += 4 + len;
4840 data_size = PTR_DIFF(pdata,(*ppdata));
4841 *fixed_portion = 10;
4842 break;
4845 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4847 int len;
4848 unsigned int ea_size =
4849 estimate_ea_size(conn, fsp, smb_fname);
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4851 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4852 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4853 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4854 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4855 SIVAL(pdata, 0x20, mode);
4856 SIVAL(pdata, 0x24, 0); /* padding. */
4857 SBVAL(pdata, 0x28, allocation_size);
4858 SBVAL(pdata, 0x30, file_size);
4859 SIVAL(pdata, 0x38, nlink);
4860 SCVAL(pdata, 0x3C, delete_pending);
4861 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4862 SSVAL(pdata, 0x3E, 0); /* padding */
4863 SBVAL(pdata, 0x40, file_index);
4864 SIVAL(pdata, 0x48, ea_size);
4865 SIVAL(pdata, 0x4C, access_mask);
4866 SBVAL(pdata, 0x50, pos);
4867 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4868 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4870 pdata += 0x60;
4872 len = srvstr_push(dstart, flags2,
4873 pdata+4, dos_fname,
4874 PTR_DIFF(dend, pdata+4),
4875 STR_UNICODE);
4876 SIVAL(pdata,0,len);
4877 pdata += 4 + len;
4878 data_size = PTR_DIFF(pdata,(*ppdata));
4879 *fixed_portion = 104;
4880 break;
4882 case SMB_FILE_INTERNAL_INFORMATION:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4885 SBVAL(pdata, 0, file_index);
4886 data_size = 8;
4887 *fixed_portion = 8;
4888 break;
4890 case SMB_FILE_ACCESS_INFORMATION:
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4892 SIVAL(pdata, 0, access_mask);
4893 data_size = 4;
4894 *fixed_portion = 4;
4895 break;
4897 case SMB_FILE_NAME_INFORMATION:
4898 /* Pathname with leading '\'. */
4900 size_t byte_len;
4901 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4902 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4903 SIVAL(pdata,0,byte_len);
4904 data_size = 4 + byte_len;
4905 break;
4908 case SMB_FILE_DISPOSITION_INFORMATION:
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4910 data_size = 1;
4911 SCVAL(pdata,0,delete_pending);
4912 *fixed_portion = 1;
4913 break;
4915 case SMB_FILE_POSITION_INFORMATION:
4916 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4917 data_size = 8;
4918 SOFF_T(pdata,0,pos);
4919 *fixed_portion = 8;
4920 break;
4922 case SMB_FILE_MODE_INFORMATION:
4923 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4924 SIVAL(pdata,0,mode);
4925 data_size = 4;
4926 *fixed_portion = 4;
4927 break;
4929 case SMB_FILE_ALIGNMENT_INFORMATION:
4930 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4931 SIVAL(pdata,0,0); /* No alignment needed. */
4932 data_size = 4;
4933 *fixed_portion = 4;
4934 break;
4937 * NT4 server just returns "invalid query" to this - if we try
4938 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4939 * want this. JRA.
4941 /* The first statement above is false - verified using Thursby
4942 * client against NT4 -- gcolley.
4944 case SMB_QUERY_FILE_STREAM_INFO:
4945 case SMB_FILE_STREAM_INFORMATION: {
4946 unsigned int num_streams = 0;
4947 struct stream_struct *streams = NULL;
4949 DEBUG(10,("smbd_do_qfilepathinfo: "
4950 "SMB_FILE_STREAM_INFORMATION\n"));
4952 if (is_ntfs_stream_smb_fname(smb_fname)) {
4953 return NT_STATUS_INVALID_PARAMETER;
4956 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4957 talloc_tos(), &num_streams, &streams);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 DEBUG(10, ("could not get stream info: %s\n",
4961 nt_errstr(status)));
4962 return status;
4965 status = marshall_stream_info(num_streams, streams,
4966 pdata, max_data_bytes,
4967 &data_size);
4969 if (!NT_STATUS_IS_OK(status)) {
4970 DEBUG(10, ("marshall_stream_info failed: %s\n",
4971 nt_errstr(status)));
4972 TALLOC_FREE(streams);
4973 return status;
4976 TALLOC_FREE(streams);
4978 *fixed_portion = 32;
4980 break;
4982 case SMB_QUERY_COMPRESSION_INFO:
4983 case SMB_FILE_COMPRESSION_INFORMATION:
4984 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4985 SOFF_T(pdata,0,file_size);
4986 SIVAL(pdata,8,0); /* ??? */
4987 SIVAL(pdata,12,0); /* ??? */
4988 data_size = 16;
4989 *fixed_portion = 16;
4990 break;
4992 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4993 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4994 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4995 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4996 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4997 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4998 SOFF_T(pdata,32,allocation_size);
4999 SOFF_T(pdata,40,file_size);
5000 SIVAL(pdata,48,mode);
5001 SIVAL(pdata,52,0); /* ??? */
5002 data_size = 56;
5003 *fixed_portion = 56;
5004 break;
5006 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5007 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5008 SIVAL(pdata,0,mode);
5009 SIVAL(pdata,4,0);
5010 data_size = 8;
5011 *fixed_portion = 8;
5012 break;
5015 * CIFS UNIX Extensions.
5018 case SMB_QUERY_FILE_UNIX_BASIC:
5020 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5021 data_size = PTR_DIFF(pdata,(*ppdata));
5023 DEBUG(4,("smbd_do_qfilepathinfo: "
5024 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5025 dump_data(4, (uint8_t *)(*ppdata), data_size);
5027 break;
5029 case SMB_QUERY_FILE_UNIX_INFO2:
5031 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5032 data_size = PTR_DIFF(pdata,(*ppdata));
5035 int i;
5036 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5038 for (i=0; i<100; i++)
5039 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5040 DEBUG(4,("\n"));
5043 break;
5045 case SMB_QUERY_FILE_UNIX_LINK:
5047 int len;
5048 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5050 if (!buffer) {
5051 return NT_STATUS_NO_MEMORY;
5054 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5055 #ifdef S_ISLNK
5056 if(!S_ISLNK(psbuf->st_ex_mode)) {
5057 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5059 #else
5060 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5061 #endif
5062 len = SMB_VFS_READLINK(conn,
5063 smb_fname->base_name,
5064 buffer, PATH_MAX);
5065 if (len == -1) {
5066 return map_nt_error_from_unix(errno);
5068 buffer[len] = 0;
5069 len = srvstr_push(dstart, flags2,
5070 pdata, buffer,
5071 PTR_DIFF(dend, pdata),
5072 STR_TERMINATE);
5073 pdata += len;
5074 data_size = PTR_DIFF(pdata,(*ppdata));
5076 break;
5079 #if defined(HAVE_POSIX_ACLS)
5080 case SMB_QUERY_POSIX_ACL:
5082 SMB_ACL_T file_acl = NULL;
5083 SMB_ACL_T def_acl = NULL;
5084 uint16 num_file_acls = 0;
5085 uint16 num_def_acls = 0;
5087 if (fsp && fsp->fh->fd != -1) {
5088 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5089 talloc_tos());
5090 } else {
5091 file_acl =
5092 SMB_VFS_SYS_ACL_GET_FILE(conn,
5093 smb_fname->base_name,
5094 SMB_ACL_TYPE_ACCESS,
5095 talloc_tos());
5098 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5099 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5100 "not implemented on "
5101 "filesystem containing %s\n",
5102 smb_fname->base_name));
5103 return NT_STATUS_NOT_IMPLEMENTED;
5106 if (S_ISDIR(psbuf->st_ex_mode)) {
5107 if (fsp && fsp->is_directory) {
5108 def_acl =
5109 SMB_VFS_SYS_ACL_GET_FILE(
5110 conn,
5111 fsp->fsp_name->base_name,
5112 SMB_ACL_TYPE_DEFAULT,
5113 talloc_tos());
5114 } else {
5115 def_acl =
5116 SMB_VFS_SYS_ACL_GET_FILE(
5117 conn,
5118 smb_fname->base_name,
5119 SMB_ACL_TYPE_DEFAULT,
5120 talloc_tos());
5122 def_acl = free_empty_sys_acl(conn, def_acl);
5125 num_file_acls = count_acl_entries(conn, file_acl);
5126 num_def_acls = count_acl_entries(conn, def_acl);
5128 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5129 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5130 data_size,
5131 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5132 SMB_POSIX_ACL_HEADER_SIZE) ));
5133 if (file_acl) {
5134 TALLOC_FREE(file_acl);
5136 if (def_acl) {
5137 TALLOC_FREE(def_acl);
5139 return NT_STATUS_BUFFER_TOO_SMALL;
5142 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5143 SSVAL(pdata,2,num_file_acls);
5144 SSVAL(pdata,4,num_def_acls);
5145 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5146 if (file_acl) {
5147 TALLOC_FREE(file_acl);
5149 if (def_acl) {
5150 TALLOC_FREE(def_acl);
5152 return NT_STATUS_INTERNAL_ERROR;
5154 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5155 if (file_acl) {
5156 TALLOC_FREE(file_acl);
5158 if (def_acl) {
5159 TALLOC_FREE(def_acl);
5161 return NT_STATUS_INTERNAL_ERROR;
5164 if (file_acl) {
5165 TALLOC_FREE(file_acl);
5167 if (def_acl) {
5168 TALLOC_FREE(def_acl);
5170 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5171 break;
5173 #endif
5176 case SMB_QUERY_POSIX_LOCK:
5178 uint64_t count;
5179 uint64_t offset;
5180 uint64_t smblctx;
5181 enum brl_type lock_type;
5183 /* We need an open file with a real fd for this. */
5184 if (!fsp || fsp->fh->fd == -1) {
5185 return NT_STATUS_INVALID_LEVEL;
5188 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5189 return NT_STATUS_INVALID_PARAMETER;
5192 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5193 case POSIX_LOCK_TYPE_READ:
5194 lock_type = READ_LOCK;
5195 break;
5196 case POSIX_LOCK_TYPE_WRITE:
5197 lock_type = WRITE_LOCK;
5198 break;
5199 case POSIX_LOCK_TYPE_UNLOCK:
5200 default:
5201 /* There's no point in asking for an unlock... */
5202 return NT_STATUS_INVALID_PARAMETER;
5205 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5206 #if defined(HAVE_LONGLONG)
5207 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5208 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5209 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5210 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5211 #else /* HAVE_LONGLONG */
5212 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5213 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5214 #endif /* HAVE_LONGLONG */
5216 status = query_lock(fsp,
5217 &smblctx,
5218 &count,
5219 &offset,
5220 &lock_type,
5221 POSIX_LOCK);
5223 if (ERROR_WAS_LOCK_DENIED(status)) {
5224 /* Here we need to report who has it locked... */
5225 data_size = POSIX_LOCK_DATA_SIZE;
5227 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5228 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5229 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5230 #if defined(HAVE_LONGLONG)
5231 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5232 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5233 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5234 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5235 #else /* HAVE_LONGLONG */
5236 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5237 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5238 #endif /* HAVE_LONGLONG */
5240 } else if (NT_STATUS_IS_OK(status)) {
5241 /* For success we just return a copy of what we sent
5242 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5243 data_size = POSIX_LOCK_DATA_SIZE;
5244 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5245 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5246 } else {
5247 return status;
5249 break;
5252 default:
5253 return NT_STATUS_INVALID_LEVEL;
5256 *pdata_size = data_size;
5257 return NT_STATUS_OK;
5260 /****************************************************************************
5261 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5262 file name or file id).
5263 ****************************************************************************/
5265 static void call_trans2qfilepathinfo(connection_struct *conn,
5266 struct smb_request *req,
5267 unsigned int tran_call,
5268 char **pparams, int total_params,
5269 char **ppdata, int total_data,
5270 unsigned int max_data_bytes)
5272 char *params = *pparams;
5273 char *pdata = *ppdata;
5274 uint16 info_level;
5275 unsigned int data_size = 0;
5276 unsigned int param_size = 2;
5277 struct smb_filename *smb_fname = NULL;
5278 bool delete_pending = False;
5279 struct timespec write_time_ts;
5280 files_struct *fsp = NULL;
5281 struct file_id fileid;
5282 struct ea_list *ea_list = NULL;
5283 int lock_data_count = 0;
5284 char *lock_data = NULL;
5285 size_t fixed_portion;
5286 NTSTATUS status = NT_STATUS_OK;
5288 if (!params) {
5289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5290 return;
5293 ZERO_STRUCT(write_time_ts);
5295 if (tran_call == TRANSACT2_QFILEINFO) {
5296 if (total_params < 4) {
5297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5298 return;
5301 if (IS_IPC(conn)) {
5302 call_trans2qpipeinfo(conn, req, tran_call,
5303 pparams, total_params,
5304 ppdata, total_data,
5305 max_data_bytes);
5306 return;
5309 fsp = file_fsp(req, SVAL(params,0));
5310 info_level = SVAL(params,2);
5312 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5314 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5316 return;
5319 /* Initial check for valid fsp ptr. */
5320 if (!check_fsp_open(conn, req, fsp)) {
5321 return;
5324 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5325 &smb_fname);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 reply_nterror(req, status);
5328 return;
5331 if(fsp->fake_file_handle) {
5333 * This is actually for the QUOTA_FAKE_FILE --metze
5336 /* We know this name is ok, it's already passed the checks. */
5338 } else if(fsp->fh->fd == -1) {
5340 * This is actually a QFILEINFO on a directory
5341 * handle (returned from an NT SMB). NT5.0 seems
5342 * to do this call. JRA.
5345 if (INFO_LEVEL_IS_UNIX(info_level)) {
5346 /* Always do lstat for UNIX calls. */
5347 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5348 DEBUG(3,("call_trans2qfilepathinfo: "
5349 "SMB_VFS_LSTAT of %s failed "
5350 "(%s)\n",
5351 smb_fname_str_dbg(smb_fname),
5352 strerror(errno)));
5353 reply_nterror(req,
5354 map_nt_error_from_unix(errno));
5355 return;
5357 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5358 DEBUG(3,("call_trans2qfilepathinfo: "
5359 "SMB_VFS_STAT of %s failed (%s)\n",
5360 smb_fname_str_dbg(smb_fname),
5361 strerror(errno)));
5362 reply_nterror(req,
5363 map_nt_error_from_unix(errno));
5364 return;
5367 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5368 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5369 } else {
5371 * Original code - this is an open file.
5373 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5374 DEBUG(3, ("fstat of %s failed (%s)\n",
5375 fsp_fnum_dbg(fsp), strerror(errno)));
5376 reply_nterror(req,
5377 map_nt_error_from_unix(errno));
5378 return;
5380 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5381 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5384 } else {
5385 uint32_t name_hash;
5386 char *fname = NULL;
5387 uint32_t ucf_flags = 0;
5389 /* qpathinfo */
5390 if (total_params < 7) {
5391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5392 return;
5395 info_level = SVAL(params,0);
5397 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5399 if (INFO_LEVEL_IS_UNIX(info_level)) {
5400 if (!lp_unix_extensions()) {
5401 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5402 return;
5404 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5405 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5406 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5407 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5411 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5412 total_params - 6,
5413 STR_TERMINATE, &status);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 reply_nterror(req, status);
5416 return;
5419 status = filename_convert(req,
5420 conn,
5421 req->flags2 & FLAGS2_DFS_PATHNAMES,
5422 fname,
5423 ucf_flags,
5424 NULL,
5425 &smb_fname);
5426 if (!NT_STATUS_IS_OK(status)) {
5427 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5428 reply_botherror(req,
5429 NT_STATUS_PATH_NOT_COVERED,
5430 ERRSRV, ERRbadpath);
5431 return;
5433 reply_nterror(req, status);
5434 return;
5437 /* If this is a stream, check if there is a delete_pending. */
5438 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5439 && is_ntfs_stream_smb_fname(smb_fname)) {
5440 struct smb_filename *smb_fname_base = NULL;
5442 /* Create an smb_filename with stream_name == NULL. */
5443 status =
5444 create_synthetic_smb_fname(talloc_tos(),
5445 smb_fname->base_name,
5446 NULL, NULL,
5447 &smb_fname_base);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 reply_nterror(req, status);
5450 return;
5453 if (INFO_LEVEL_IS_UNIX(info_level)) {
5454 /* Always do lstat for UNIX calls. */
5455 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5456 DEBUG(3,("call_trans2qfilepathinfo: "
5457 "SMB_VFS_LSTAT of %s failed "
5458 "(%s)\n",
5459 smb_fname_str_dbg(smb_fname_base),
5460 strerror(errno)));
5461 TALLOC_FREE(smb_fname_base);
5462 reply_nterror(req,
5463 map_nt_error_from_unix(errno));
5464 return;
5466 } else {
5467 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5468 DEBUG(3,("call_trans2qfilepathinfo: "
5469 "fileinfo of %s failed "
5470 "(%s)\n",
5471 smb_fname_str_dbg(smb_fname_base),
5472 strerror(errno)));
5473 TALLOC_FREE(smb_fname_base);
5474 reply_nterror(req,
5475 map_nt_error_from_unix(errno));
5476 return;
5480 status = file_name_hash(conn,
5481 smb_fname_str_dbg(smb_fname_base),
5482 &name_hash);
5483 if (!NT_STATUS_IS_OK(status)) {
5484 TALLOC_FREE(smb_fname_base);
5485 reply_nterror(req, status);
5486 return;
5489 fileid = vfs_file_id_from_sbuf(conn,
5490 &smb_fname_base->st);
5491 TALLOC_FREE(smb_fname_base);
5492 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5493 if (delete_pending) {
5494 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5495 return;
5499 if (INFO_LEVEL_IS_UNIX(info_level)) {
5500 /* Always do lstat for UNIX calls. */
5501 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5502 DEBUG(3,("call_trans2qfilepathinfo: "
5503 "SMB_VFS_LSTAT of %s failed (%s)\n",
5504 smb_fname_str_dbg(smb_fname),
5505 strerror(errno)));
5506 reply_nterror(req,
5507 map_nt_error_from_unix(errno));
5508 return;
5511 } else {
5512 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5513 DEBUG(3,("call_trans2qfilepathinfo: "
5514 "SMB_VFS_STAT of %s failed (%s)\n",
5515 smb_fname_str_dbg(smb_fname),
5516 strerror(errno)));
5517 reply_nterror(req,
5518 map_nt_error_from_unix(errno));
5519 return;
5523 status = file_name_hash(conn,
5524 smb_fname_str_dbg(smb_fname),
5525 &name_hash);
5526 if (!NT_STATUS_IS_OK(status)) {
5527 reply_nterror(req, status);
5528 return;
5531 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5532 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5533 if (delete_pending) {
5534 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5535 return;
5539 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5540 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5541 fsp_fnum_dbg(fsp),
5542 info_level,tran_call,total_data));
5544 /* Pull out any data sent here before we realloc. */
5545 switch (info_level) {
5546 case SMB_INFO_QUERY_EAS_FROM_LIST:
5548 /* Pull any EA list from the data portion. */
5549 uint32 ea_size;
5551 if (total_data < 4) {
5552 reply_nterror(
5553 req, NT_STATUS_INVALID_PARAMETER);
5554 return;
5556 ea_size = IVAL(pdata,0);
5558 if (total_data > 0 && ea_size != total_data) {
5559 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5560 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5561 reply_nterror(
5562 req, NT_STATUS_INVALID_PARAMETER);
5563 return;
5566 if (!lp_ea_support(SNUM(conn))) {
5567 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5568 return;
5571 /* Pull out the list of names. */
5572 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5573 if (!ea_list) {
5574 reply_nterror(
5575 req, NT_STATUS_INVALID_PARAMETER);
5576 return;
5578 break;
5581 case SMB_QUERY_POSIX_LOCK:
5583 if (fsp == NULL || fsp->fh->fd == -1) {
5584 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5585 return;
5588 if (total_data != POSIX_LOCK_DATA_SIZE) {
5589 reply_nterror(
5590 req, NT_STATUS_INVALID_PARAMETER);
5591 return;
5594 /* Copy the lock range data. */
5595 lock_data = (char *)talloc_memdup(
5596 req, pdata, total_data);
5597 if (!lock_data) {
5598 reply_nterror(req, NT_STATUS_NO_MEMORY);
5599 return;
5601 lock_data_count = total_data;
5603 default:
5604 break;
5607 *pparams = (char *)SMB_REALLOC(*pparams,2);
5608 if (*pparams == NULL) {
5609 reply_nterror(req, NT_STATUS_NO_MEMORY);
5610 return;
5612 params = *pparams;
5613 SSVAL(params,0,0);
5616 * draft-leach-cifs-v1-spec-02.txt
5617 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5618 * says:
5620 * The requested information is placed in the Data portion of the
5621 * transaction response. For the information levels greater than 0x100,
5622 * the transaction response has 1 parameter word which should be
5623 * ignored by the client.
5625 * However Windows only follows this rule for the IS_NAME_VALID call.
5627 switch (info_level) {
5628 case SMB_INFO_IS_NAME_VALID:
5629 param_size = 0;
5630 break;
5633 if ((info_level & 0xFF00) == 0xFF00) {
5635 * We use levels that start with 0xFF00
5636 * internally to represent SMB2 specific levels
5638 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5639 return;
5642 status = smbd_do_qfilepathinfo(conn, req, info_level,
5643 fsp, smb_fname,
5644 delete_pending, write_time_ts,
5645 ea_list,
5646 lock_data_count, lock_data,
5647 req->flags2, max_data_bytes,
5648 &fixed_portion,
5649 ppdata, &data_size);
5650 if (!NT_STATUS_IS_OK(status)) {
5651 reply_nterror(req, status);
5652 return;
5654 if (fixed_portion > max_data_bytes) {
5655 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5656 return;
5659 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5660 max_data_bytes);
5662 return;
5665 /****************************************************************************
5666 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5667 code.
5668 ****************************************************************************/
5670 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5671 connection_struct *conn,
5672 struct smb_request *req,
5673 bool overwrite_if_exists,
5674 const struct smb_filename *smb_fname_old,
5675 struct smb_filename *smb_fname_new)
5677 NTSTATUS status = NT_STATUS_OK;
5679 /* source must already exist. */
5680 if (!VALID_STAT(smb_fname_old->st)) {
5681 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5684 if (VALID_STAT(smb_fname_new->st)) {
5685 if (overwrite_if_exists) {
5686 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5687 return NT_STATUS_FILE_IS_A_DIRECTORY;
5689 status = unlink_internals(conn,
5690 req,
5691 FILE_ATTRIBUTE_NORMAL,
5692 smb_fname_new,
5693 false);
5694 if (!NT_STATUS_IS_OK(status)) {
5695 return status;
5697 } else {
5698 /* Disallow if newname already exists. */
5699 return NT_STATUS_OBJECT_NAME_COLLISION;
5703 /* No links from a directory. */
5704 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5705 return NT_STATUS_FILE_IS_A_DIRECTORY;
5708 /* Setting a hardlink to/from a stream isn't currently supported. */
5709 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5710 is_ntfs_stream_smb_fname(smb_fname_new)) {
5711 return NT_STATUS_INVALID_PARAMETER;
5714 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5715 smb_fname_old->base_name, smb_fname_new->base_name));
5717 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5718 smb_fname_new->base_name) != 0) {
5719 status = map_nt_error_from_unix(errno);
5720 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5721 nt_errstr(status), smb_fname_old->base_name,
5722 smb_fname_new->base_name));
5724 return status;
5727 /****************************************************************************
5728 Deal with setting the time from any of the setfilepathinfo functions.
5729 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5730 calling this function.
5731 ****************************************************************************/
5733 NTSTATUS smb_set_file_time(connection_struct *conn,
5734 files_struct *fsp,
5735 const struct smb_filename *smb_fname,
5736 struct smb_file_time *ft,
5737 bool setting_write_time)
5739 struct smb_filename smb_fname_base;
5740 uint32 action =
5741 FILE_NOTIFY_CHANGE_LAST_ACCESS
5742 |FILE_NOTIFY_CHANGE_LAST_WRITE
5743 |FILE_NOTIFY_CHANGE_CREATION;
5745 if (!VALID_STAT(smb_fname->st)) {
5746 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5749 /* get some defaults (no modifications) if any info is zero or -1. */
5750 if (null_timespec(ft->create_time)) {
5751 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5754 if (null_timespec(ft->atime)) {
5755 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5758 if (null_timespec(ft->mtime)) {
5759 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5762 if (!setting_write_time) {
5763 /* ft->mtime comes from change time, not write time. */
5764 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5767 /* Ensure the resolution is the correct for
5768 * what we can store on this filesystem. */
5770 round_timespec(conn->ts_res, &ft->create_time);
5771 round_timespec(conn->ts_res, &ft->ctime);
5772 round_timespec(conn->ts_res, &ft->atime);
5773 round_timespec(conn->ts_res, &ft->mtime);
5775 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5776 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5777 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5778 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5779 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5780 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5781 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5782 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5784 if (setting_write_time) {
5786 * This was a Windows setfileinfo on an open file.
5787 * NT does this a lot. We also need to
5788 * set the time here, as it can be read by
5789 * FindFirst/FindNext and with the patch for bug #2045
5790 * in smbd/fileio.c it ensures that this timestamp is
5791 * kept sticky even after a write. We save the request
5792 * away and will set it on file close and after a write. JRA.
5795 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5796 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5798 if (fsp != NULL) {
5799 if (fsp->base_fsp) {
5800 set_sticky_write_time_fsp(fsp->base_fsp,
5801 ft->mtime);
5802 } else {
5803 set_sticky_write_time_fsp(fsp, ft->mtime);
5805 } else {
5806 set_sticky_write_time_path(
5807 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5808 ft->mtime);
5812 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5814 /* Always call ntimes on the base, even if a stream was passed in. */
5815 smb_fname_base = *smb_fname;
5816 smb_fname_base.stream_name = NULL;
5818 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5819 return map_nt_error_from_unix(errno);
5822 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5823 smb_fname->base_name);
5824 return NT_STATUS_OK;
5827 /****************************************************************************
5828 Deal with setting the dosmode from any of the setfilepathinfo functions.
5829 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5830 done before calling this function.
5831 ****************************************************************************/
5833 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5834 const struct smb_filename *smb_fname,
5835 uint32 dosmode)
5837 struct smb_filename *smb_fname_base = NULL;
5838 NTSTATUS status;
5840 if (!VALID_STAT(smb_fname->st)) {
5841 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5844 /* Always operate on the base_name, even if a stream was passed in. */
5845 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5846 NULL, &smb_fname->st,
5847 &smb_fname_base);
5848 if (!NT_STATUS_IS_OK(status)) {
5849 return status;
5852 if (dosmode) {
5853 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5854 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5855 } else {
5856 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5860 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5862 /* check the mode isn't different, before changing it */
5863 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5864 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5865 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5866 (unsigned int)dosmode));
5868 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5869 false)) {
5870 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5871 "%s failed (%s)\n",
5872 smb_fname_str_dbg(smb_fname_base),
5873 strerror(errno)));
5874 status = map_nt_error_from_unix(errno);
5875 goto out;
5878 status = NT_STATUS_OK;
5879 out:
5880 TALLOC_FREE(smb_fname_base);
5881 return status;
5884 /****************************************************************************
5885 Deal with setting the size from any of the setfilepathinfo functions.
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_file_size(connection_struct *conn,
5889 struct smb_request *req,
5890 files_struct *fsp,
5891 const struct smb_filename *smb_fname,
5892 const SMB_STRUCT_STAT *psbuf,
5893 off_t size,
5894 bool fail_after_createfile)
5896 NTSTATUS status = NT_STATUS_OK;
5897 struct smb_filename *smb_fname_tmp = NULL;
5898 files_struct *new_fsp = NULL;
5900 if (!VALID_STAT(*psbuf)) {
5901 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5904 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5906 if (size == get_file_size_stat(psbuf)) {
5907 return NT_STATUS_OK;
5910 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5911 smb_fname_str_dbg(smb_fname), (double)size));
5913 if (fsp && fsp->fh->fd != -1) {
5914 /* Handle based call. */
5915 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5916 return NT_STATUS_ACCESS_DENIED;
5919 if (vfs_set_filelen(fsp, size) == -1) {
5920 return map_nt_error_from_unix(errno);
5922 trigger_write_time_update_immediate(fsp);
5923 return NT_STATUS_OK;
5926 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5927 if (!NT_STATUS_IS_OK(status)) {
5928 return status;
5931 smb_fname_tmp->st = *psbuf;
5933 status = SMB_VFS_CREATE_FILE(
5934 conn, /* conn */
5935 req, /* req */
5936 0, /* root_dir_fid */
5937 smb_fname_tmp, /* fname */
5938 FILE_WRITE_DATA, /* access_mask */
5939 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5940 FILE_SHARE_DELETE),
5941 FILE_OPEN, /* create_disposition*/
5942 0, /* create_options */
5943 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5944 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5945 0, /* allocation_size */
5946 0, /* private_flags */
5947 NULL, /* sd */
5948 NULL, /* ea_list */
5949 &new_fsp, /* result */
5950 NULL); /* pinfo */
5952 TALLOC_FREE(smb_fname_tmp);
5954 if (!NT_STATUS_IS_OK(status)) {
5955 /* NB. We check for open_was_deferred in the caller. */
5956 return status;
5959 /* See RAW-SFILEINFO-END-OF-FILE */
5960 if (fail_after_createfile) {
5961 close_file(req, new_fsp,NORMAL_CLOSE);
5962 return NT_STATUS_INVALID_LEVEL;
5965 if (vfs_set_filelen(new_fsp, size) == -1) {
5966 status = map_nt_error_from_unix(errno);
5967 close_file(req, new_fsp,NORMAL_CLOSE);
5968 return status;
5971 trigger_write_time_update_immediate(new_fsp);
5972 close_file(req, new_fsp,NORMAL_CLOSE);
5973 return NT_STATUS_OK;
5976 /****************************************************************************
5977 Deal with SMB_INFO_SET_EA.
5978 ****************************************************************************/
5980 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5981 const char *pdata,
5982 int total_data,
5983 files_struct *fsp,
5984 const struct smb_filename *smb_fname)
5986 struct ea_list *ea_list = NULL;
5987 TALLOC_CTX *ctx = NULL;
5988 NTSTATUS status = NT_STATUS_OK;
5990 if (total_data < 10) {
5992 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5993 length. They seem to have no effect. Bug #3212. JRA */
5995 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5996 /* We're done. We only get EA info in this call. */
5997 return NT_STATUS_OK;
6000 return NT_STATUS_INVALID_PARAMETER;
6003 if (IVAL(pdata,0) > total_data) {
6004 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6005 IVAL(pdata,0), (unsigned int)total_data));
6006 return NT_STATUS_INVALID_PARAMETER;
6009 ctx = talloc_tos();
6010 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6011 if (!ea_list) {
6012 return NT_STATUS_INVALID_PARAMETER;
6015 status = set_ea(conn, fsp, smb_fname, ea_list);
6017 return status;
6020 /****************************************************************************
6021 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6022 ****************************************************************************/
6024 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6025 const char *pdata,
6026 int total_data,
6027 files_struct *fsp)
6029 struct ea_list *ea_list = NULL;
6030 NTSTATUS status;
6032 if (!fsp) {
6033 return NT_STATUS_INVALID_HANDLE;
6036 if (!lp_ea_support(SNUM(conn))) {
6037 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6038 "EA's not supported.\n",
6039 (unsigned int)total_data));
6040 return NT_STATUS_EAS_NOT_SUPPORTED;
6043 if (total_data < 10) {
6044 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6045 "too small.\n",
6046 (unsigned int)total_data));
6047 return NT_STATUS_INVALID_PARAMETER;
6050 ea_list = read_nttrans_ea_list(talloc_tos(),
6051 pdata,
6052 total_data);
6054 if (!ea_list) {
6055 return NT_STATUS_INVALID_PARAMETER;
6058 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6060 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6061 smb_fname_str_dbg(fsp->fsp_name),
6062 nt_errstr(status) ));
6064 return status;
6068 /****************************************************************************
6069 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6070 ****************************************************************************/
6072 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6073 const char *pdata,
6074 int total_data,
6075 files_struct *fsp,
6076 struct smb_filename *smb_fname)
6078 NTSTATUS status = NT_STATUS_OK;
6079 bool delete_on_close;
6080 uint32 dosmode = 0;
6082 if (total_data < 1) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 if (fsp == NULL) {
6087 return NT_STATUS_INVALID_HANDLE;
6090 delete_on_close = (CVAL(pdata,0) ? True : False);
6091 dosmode = dos_mode(conn, smb_fname);
6093 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6094 "delete_on_close = %u\n",
6095 smb_fname_str_dbg(smb_fname),
6096 (unsigned int)dosmode,
6097 (unsigned int)delete_on_close ));
6099 if (delete_on_close) {
6100 status = can_set_delete_on_close(fsp, dosmode);
6101 if (!NT_STATUS_IS_OK(status)) {
6102 return status;
6106 /* The set is across all open files on this dev/inode pair. */
6107 if (!set_delete_on_close(fsp, delete_on_close,
6108 conn->session_info->security_token,
6109 conn->session_info->unix_token)) {
6110 return NT_STATUS_ACCESS_DENIED;
6112 return NT_STATUS_OK;
6115 /****************************************************************************
6116 Deal with SMB_FILE_POSITION_INFORMATION.
6117 ****************************************************************************/
6119 static NTSTATUS smb_file_position_information(connection_struct *conn,
6120 const char *pdata,
6121 int total_data,
6122 files_struct *fsp)
6124 uint64_t position_information;
6126 if (total_data < 8) {
6127 return NT_STATUS_INVALID_PARAMETER;
6130 if (fsp == NULL) {
6131 /* Ignore on pathname based set. */
6132 return NT_STATUS_OK;
6135 position_information = (uint64_t)IVAL(pdata,0);
6136 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6138 DEBUG(10,("smb_file_position_information: Set file position "
6139 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6140 (double)position_information));
6141 fsp->fh->position_information = position_information;
6142 return NT_STATUS_OK;
6145 /****************************************************************************
6146 Deal with SMB_FILE_MODE_INFORMATION.
6147 ****************************************************************************/
6149 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6150 const char *pdata,
6151 int total_data)
6153 uint32 mode;
6155 if (total_data < 4) {
6156 return NT_STATUS_INVALID_PARAMETER;
6158 mode = IVAL(pdata,0);
6159 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6160 return NT_STATUS_INVALID_PARAMETER;
6162 return NT_STATUS_OK;
6165 /****************************************************************************
6166 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6167 ****************************************************************************/
6169 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6170 struct smb_request *req,
6171 const char *pdata,
6172 int total_data,
6173 const struct smb_filename *smb_fname)
6175 char *link_target = NULL;
6176 const char *newname = smb_fname->base_name;
6177 TALLOC_CTX *ctx = talloc_tos();
6179 /* Set a symbolic link. */
6180 /* Don't allow this if follow links is false. */
6182 if (total_data == 0) {
6183 return NT_STATUS_INVALID_PARAMETER;
6186 if (!lp_symlinks(SNUM(conn))) {
6187 return NT_STATUS_ACCESS_DENIED;
6190 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6191 total_data, STR_TERMINATE);
6193 if (!link_target) {
6194 return NT_STATUS_INVALID_PARAMETER;
6197 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6198 newname, link_target ));
6200 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6201 return map_nt_error_from_unix(errno);
6204 return NT_STATUS_OK;
6207 /****************************************************************************
6208 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6209 ****************************************************************************/
6211 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6212 struct smb_request *req,
6213 const char *pdata, int total_data,
6214 struct smb_filename *smb_fname_new)
6216 char *oldname = NULL;
6217 struct smb_filename *smb_fname_old = NULL;
6218 TALLOC_CTX *ctx = talloc_tos();
6219 NTSTATUS status = NT_STATUS_OK;
6221 /* Set a hard link. */
6222 if (total_data == 0) {
6223 return NT_STATUS_INVALID_PARAMETER;
6226 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6227 total_data, STR_TERMINATE, &status);
6228 if (!NT_STATUS_IS_OK(status)) {
6229 return status;
6232 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6233 smb_fname_str_dbg(smb_fname_new), oldname));
6235 status = filename_convert(ctx,
6236 conn,
6237 req->flags2 & FLAGS2_DFS_PATHNAMES,
6238 oldname,
6240 NULL,
6241 &smb_fname_old);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 return status;
6246 return hardlink_internals(ctx, conn, req, false,
6247 smb_fname_old, smb_fname_new);
6250 /****************************************************************************
6251 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6252 ****************************************************************************/
6254 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6255 struct smb_request *req,
6256 const char *pdata,
6257 int total_data,
6258 files_struct *fsp,
6259 struct smb_filename *smb_fname_src)
6261 bool overwrite;
6262 uint32_t len;
6263 char *newname = NULL;
6264 struct smb_filename *smb_fname_dst = NULL;
6265 NTSTATUS status = NT_STATUS_OK;
6266 TALLOC_CTX *ctx = talloc_tos();
6268 if (!fsp) {
6269 return NT_STATUS_INVALID_HANDLE;
6272 if (total_data < 20) {
6273 return NT_STATUS_INVALID_PARAMETER;
6276 overwrite = (CVAL(pdata,0) ? True : False);
6277 len = IVAL(pdata,16);
6279 if (len > (total_data - 20) || (len == 0)) {
6280 return NT_STATUS_INVALID_PARAMETER;
6283 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6284 &pdata[20], len, STR_TERMINATE,
6285 &status);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 return status;
6290 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6291 newname));
6293 status = filename_convert(ctx,
6294 conn,
6295 req->flags2 & FLAGS2_DFS_PATHNAMES,
6296 newname,
6297 UCF_SAVE_LCOMP,
6298 NULL,
6299 &smb_fname_dst);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 return status;
6304 if (fsp->base_fsp) {
6305 /* newname must be a stream name. */
6306 if (newname[0] != ':') {
6307 return NT_STATUS_NOT_SUPPORTED;
6310 /* Create an smb_fname to call rename_internals_fsp() with. */
6311 status = create_synthetic_smb_fname(talloc_tos(),
6312 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6313 &smb_fname_dst);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 goto out;
6319 * Set the original last component, since
6320 * rename_internals_fsp() requires it.
6322 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6323 newname);
6324 if (smb_fname_dst->original_lcomp == NULL) {
6325 status = NT_STATUS_NO_MEMORY;
6326 goto out;
6331 DEBUG(10,("smb2_file_rename_information: "
6332 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6333 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6334 smb_fname_str_dbg(smb_fname_dst)));
6335 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6336 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6337 overwrite);
6339 out:
6340 TALLOC_FREE(smb_fname_dst);
6341 return status;
6344 static NTSTATUS smb_file_link_information(connection_struct *conn,
6345 struct smb_request *req,
6346 const char *pdata,
6347 int total_data,
6348 files_struct *fsp,
6349 struct smb_filename *smb_fname_src)
6351 bool overwrite;
6352 uint32_t len;
6353 char *newname = NULL;
6354 struct smb_filename *smb_fname_dst = NULL;
6355 NTSTATUS status = NT_STATUS_OK;
6356 TALLOC_CTX *ctx = talloc_tos();
6358 if (!fsp) {
6359 return NT_STATUS_INVALID_HANDLE;
6362 if (total_data < 20) {
6363 return NT_STATUS_INVALID_PARAMETER;
6366 overwrite = (CVAL(pdata,0) ? true : false);
6367 len = IVAL(pdata,16);
6369 if (len > (total_data - 20) || (len == 0)) {
6370 return NT_STATUS_INVALID_PARAMETER;
6373 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6374 &pdata[20], len, STR_TERMINATE,
6375 &status);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 return status;
6380 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6381 newname));
6383 status = filename_convert(ctx,
6384 conn,
6385 req->flags2 & FLAGS2_DFS_PATHNAMES,
6386 newname,
6387 UCF_SAVE_LCOMP,
6388 NULL,
6389 &smb_fname_dst);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 return status;
6394 if (fsp->base_fsp) {
6395 /* No stream names. */
6396 return NT_STATUS_NOT_SUPPORTED;
6399 DEBUG(10,("smb_file_link_information: "
6400 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6401 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6402 smb_fname_str_dbg(smb_fname_dst)));
6403 status = hardlink_internals(ctx,
6404 conn,
6405 req,
6406 overwrite,
6407 fsp->fsp_name,
6408 smb_fname_dst);
6410 TALLOC_FREE(smb_fname_dst);
6411 return status;
6414 /****************************************************************************
6415 Deal with SMB_FILE_RENAME_INFORMATION.
6416 ****************************************************************************/
6418 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6419 struct smb_request *req,
6420 const char *pdata,
6421 int total_data,
6422 files_struct *fsp,
6423 struct smb_filename *smb_fname_src)
6425 bool overwrite;
6426 uint32 root_fid;
6427 uint32 len;
6428 char *newname = NULL;
6429 struct smb_filename *smb_fname_dst = NULL;
6430 bool dest_has_wcard = False;
6431 NTSTATUS status = NT_STATUS_OK;
6432 char *p;
6433 TALLOC_CTX *ctx = talloc_tos();
6435 if (total_data < 13) {
6436 return NT_STATUS_INVALID_PARAMETER;
6439 overwrite = (CVAL(pdata,0) ? True : False);
6440 root_fid = IVAL(pdata,4);
6441 len = IVAL(pdata,8);
6443 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6444 return NT_STATUS_INVALID_PARAMETER;
6447 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6448 len, 0, &status,
6449 &dest_has_wcard);
6450 if (!NT_STATUS_IS_OK(status)) {
6451 return status;
6454 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6455 newname));
6457 status = resolve_dfspath_wcard(ctx, conn,
6458 req->flags2 & FLAGS2_DFS_PATHNAMES,
6459 newname,
6460 true,
6461 !conn->sconn->using_smb2,
6462 &newname,
6463 &dest_has_wcard);
6464 if (!NT_STATUS_IS_OK(status)) {
6465 return status;
6468 /* Check the new name has no '/' characters. */
6469 if (strchr_m(newname, '/')) {
6470 return NT_STATUS_NOT_SUPPORTED;
6473 if (fsp && fsp->base_fsp) {
6474 /* newname must be a stream name. */
6475 if (newname[0] != ':') {
6476 return NT_STATUS_NOT_SUPPORTED;
6479 /* Create an smb_fname to call rename_internals_fsp() with. */
6480 status = create_synthetic_smb_fname(talloc_tos(),
6481 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6482 &smb_fname_dst);
6483 if (!NT_STATUS_IS_OK(status)) {
6484 goto out;
6488 * Set the original last component, since
6489 * rename_internals_fsp() requires it.
6491 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6492 newname);
6493 if (smb_fname_dst->original_lcomp == NULL) {
6494 status = NT_STATUS_NO_MEMORY;
6495 goto out;
6498 } else {
6500 * Build up an smb_fname_dst based on the filename passed in.
6501 * We basically just strip off the last component, and put on
6502 * the newname instead.
6504 char *base_name = NULL;
6506 /* newname must *not* be a stream name. */
6507 if (newname[0] == ':') {
6508 return NT_STATUS_NOT_SUPPORTED;
6512 * Strip off the last component (filename) of the path passed
6513 * in.
6515 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6516 if (!base_name) {
6517 return NT_STATUS_NO_MEMORY;
6519 p = strrchr_m(base_name, '/');
6520 if (p) {
6521 p[1] = '\0';
6522 } else {
6523 base_name = talloc_strdup(ctx, "");
6524 if (!base_name) {
6525 return NT_STATUS_NO_MEMORY;
6528 /* Append the new name. */
6529 base_name = talloc_asprintf_append(base_name,
6530 "%s",
6531 newname);
6532 if (!base_name) {
6533 return NT_STATUS_NO_MEMORY;
6536 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6537 (UCF_SAVE_LCOMP |
6538 (dest_has_wcard ?
6539 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6540 0)));
6542 /* If an error we expect this to be
6543 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6545 if (!NT_STATUS_IS_OK(status)) {
6546 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6547 status)) {
6548 goto out;
6550 /* Create an smb_fname to call rename_internals_fsp() */
6551 status = create_synthetic_smb_fname(ctx,
6552 base_name, NULL,
6553 NULL,
6554 &smb_fname_dst);
6555 if (!NT_STATUS_IS_OK(status)) {
6556 goto out;
6561 if (fsp) {
6562 DEBUG(10,("smb_file_rename_information: "
6563 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6564 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6565 smb_fname_str_dbg(smb_fname_dst)));
6566 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6567 overwrite);
6568 } else {
6569 DEBUG(10,("smb_file_rename_information: "
6570 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6571 smb_fname_str_dbg(smb_fname_src),
6572 smb_fname_str_dbg(smb_fname_dst)));
6573 status = rename_internals(ctx, conn, req, smb_fname_src,
6574 smb_fname_dst, 0, overwrite, false,
6575 dest_has_wcard,
6576 FILE_WRITE_ATTRIBUTES);
6578 out:
6579 TALLOC_FREE(smb_fname_dst);
6580 return status;
6583 /****************************************************************************
6584 Deal with SMB_SET_POSIX_ACL.
6585 ****************************************************************************/
6587 #if defined(HAVE_POSIX_ACLS)
6588 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6589 const char *pdata,
6590 int total_data,
6591 files_struct *fsp,
6592 const struct smb_filename *smb_fname)
6594 uint16 posix_acl_version;
6595 uint16 num_file_acls;
6596 uint16 num_def_acls;
6597 bool valid_file_acls = True;
6598 bool valid_def_acls = True;
6600 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6601 return NT_STATUS_INVALID_PARAMETER;
6603 posix_acl_version = SVAL(pdata,0);
6604 num_file_acls = SVAL(pdata,2);
6605 num_def_acls = SVAL(pdata,4);
6607 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6608 valid_file_acls = False;
6609 num_file_acls = 0;
6612 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6613 valid_def_acls = False;
6614 num_def_acls = 0;
6617 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6622 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6623 return NT_STATUS_INVALID_PARAMETER;
6626 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6627 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6628 (unsigned int)num_file_acls,
6629 (unsigned int)num_def_acls));
6631 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6632 smb_fname->base_name, num_file_acls,
6633 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6634 return map_nt_error_from_unix(errno);
6637 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6638 smb_fname->base_name, &smb_fname->st, num_def_acls,
6639 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6640 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6641 return map_nt_error_from_unix(errno);
6643 return NT_STATUS_OK;
6645 #endif
6647 /****************************************************************************
6648 Deal with SMB_SET_POSIX_LOCK.
6649 ****************************************************************************/
6651 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6652 struct smb_request *req,
6653 const char *pdata,
6654 int total_data,
6655 files_struct *fsp)
6657 uint64_t count;
6658 uint64_t offset;
6659 uint64_t smblctx;
6660 bool blocking_lock = False;
6661 enum brl_type lock_type;
6663 NTSTATUS status = NT_STATUS_OK;
6665 if (fsp == NULL || fsp->fh->fd == -1) {
6666 return NT_STATUS_INVALID_HANDLE;
6669 if (total_data != POSIX_LOCK_DATA_SIZE) {
6670 return NT_STATUS_INVALID_PARAMETER;
6673 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6674 case POSIX_LOCK_TYPE_READ:
6675 lock_type = READ_LOCK;
6676 break;
6677 case POSIX_LOCK_TYPE_WRITE:
6678 /* Return the right POSIX-mappable error code for files opened read-only. */
6679 if (!fsp->can_write) {
6680 return NT_STATUS_INVALID_HANDLE;
6682 lock_type = WRITE_LOCK;
6683 break;
6684 case POSIX_LOCK_TYPE_UNLOCK:
6685 lock_type = UNLOCK_LOCK;
6686 break;
6687 default:
6688 return NT_STATUS_INVALID_PARAMETER;
6691 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6692 blocking_lock = False;
6693 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6694 blocking_lock = True;
6695 } else {
6696 return NT_STATUS_INVALID_PARAMETER;
6699 if (!lp_blocking_locks(SNUM(conn))) {
6700 blocking_lock = False;
6703 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6704 #if defined(HAVE_LONGLONG)
6705 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6706 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6707 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6708 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6709 #else /* HAVE_LONGLONG */
6710 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6711 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6712 #endif /* HAVE_LONGLONG */
6714 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6715 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6716 fsp_str_dbg(fsp),
6717 (unsigned int)lock_type,
6718 (unsigned long long)smblctx,
6719 (double)count,
6720 (double)offset ));
6722 if (lock_type == UNLOCK_LOCK) {
6723 status = do_unlock(req->sconn->msg_ctx,
6724 fsp,
6725 smblctx,
6726 count,
6727 offset,
6728 POSIX_LOCK);
6729 } else {
6730 uint64_t block_smblctx;
6732 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6733 fsp,
6734 smblctx,
6735 count,
6736 offset,
6737 lock_type,
6738 POSIX_LOCK,
6739 blocking_lock,
6740 &status,
6741 &block_smblctx,
6742 NULL);
6744 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6746 * A blocking lock was requested. Package up
6747 * this smb into a queued request and push it
6748 * onto the blocking lock queue.
6750 if(push_blocking_lock_request(br_lck,
6751 req,
6752 fsp,
6753 -1, /* infinite timeout. */
6755 smblctx,
6756 lock_type,
6757 POSIX_LOCK,
6758 offset,
6759 count,
6760 block_smblctx)) {
6761 TALLOC_FREE(br_lck);
6762 return status;
6765 TALLOC_FREE(br_lck);
6768 return status;
6771 /****************************************************************************
6772 Deal with SMB_SET_FILE_BASIC_INFO.
6773 ****************************************************************************/
6775 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6776 const char *pdata,
6777 int total_data,
6778 files_struct *fsp,
6779 const struct smb_filename *smb_fname)
6781 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6782 struct smb_file_time ft;
6783 uint32 dosmode = 0;
6784 NTSTATUS status = NT_STATUS_OK;
6786 ZERO_STRUCT(ft);
6788 if (total_data < 36) {
6789 return NT_STATUS_INVALID_PARAMETER;
6792 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6793 if (!NT_STATUS_IS_OK(status)) {
6794 return status;
6797 /* Set the attributes */
6798 dosmode = IVAL(pdata,32);
6799 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6800 if (!NT_STATUS_IS_OK(status)) {
6801 return status;
6804 /* create time */
6805 ft.create_time = interpret_long_date(pdata);
6807 /* access time */
6808 ft.atime = interpret_long_date(pdata+8);
6810 /* write time. */
6811 ft.mtime = interpret_long_date(pdata+16);
6813 /* change time. */
6814 ft.ctime = interpret_long_date(pdata+24);
6816 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6817 smb_fname_str_dbg(smb_fname)));
6819 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6820 true);
6823 /****************************************************************************
6824 Deal with SMB_INFO_STANDARD.
6825 ****************************************************************************/
6827 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6828 const char *pdata,
6829 int total_data,
6830 files_struct *fsp,
6831 const struct smb_filename *smb_fname)
6833 NTSTATUS status;
6834 struct smb_file_time ft;
6836 ZERO_STRUCT(ft);
6838 if (total_data < 12) {
6839 return NT_STATUS_INVALID_PARAMETER;
6842 /* create time */
6843 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6844 /* access time */
6845 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6846 /* write time */
6847 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6849 DEBUG(10,("smb_set_info_standard: file %s\n",
6850 smb_fname_str_dbg(smb_fname)));
6852 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6853 if (!NT_STATUS_IS_OK(status)) {
6854 return status;
6857 return smb_set_file_time(conn,
6858 fsp,
6859 smb_fname,
6860 &ft,
6861 true);
6864 /****************************************************************************
6865 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6866 ****************************************************************************/
6868 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6869 struct smb_request *req,
6870 const char *pdata,
6871 int total_data,
6872 files_struct *fsp,
6873 struct smb_filename *smb_fname)
6875 uint64_t allocation_size = 0;
6876 NTSTATUS status = NT_STATUS_OK;
6877 files_struct *new_fsp = NULL;
6879 if (!VALID_STAT(smb_fname->st)) {
6880 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6883 if (total_data < 8) {
6884 return NT_STATUS_INVALID_PARAMETER;
6887 allocation_size = (uint64_t)IVAL(pdata,0);
6888 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6889 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6890 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6891 (double)allocation_size));
6893 if (allocation_size) {
6894 allocation_size = smb_roundup(conn, allocation_size);
6897 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6898 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6899 (double)allocation_size));
6901 if (fsp && fsp->fh->fd != -1) {
6902 /* Open file handle. */
6903 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6904 return NT_STATUS_ACCESS_DENIED;
6907 /* Only change if needed. */
6908 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6909 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6910 return map_nt_error_from_unix(errno);
6913 /* But always update the time. */
6915 * This is equivalent to a write. Ensure it's seen immediately
6916 * if there are no pending writes.
6918 trigger_write_time_update_immediate(fsp);
6919 return NT_STATUS_OK;
6922 /* Pathname or stat or directory file. */
6923 status = SMB_VFS_CREATE_FILE(
6924 conn, /* conn */
6925 req, /* req */
6926 0, /* root_dir_fid */
6927 smb_fname, /* fname */
6928 FILE_WRITE_DATA, /* access_mask */
6929 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6930 FILE_SHARE_DELETE),
6931 FILE_OPEN, /* create_disposition*/
6932 0, /* create_options */
6933 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6934 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6935 0, /* allocation_size */
6936 0, /* private_flags */
6937 NULL, /* sd */
6938 NULL, /* ea_list */
6939 &new_fsp, /* result */
6940 NULL); /* pinfo */
6942 if (!NT_STATUS_IS_OK(status)) {
6943 /* NB. We check for open_was_deferred in the caller. */
6944 return status;
6947 /* Only change if needed. */
6948 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6949 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6950 status = map_nt_error_from_unix(errno);
6951 close_file(req, new_fsp, NORMAL_CLOSE);
6952 return status;
6956 /* Changing the allocation size should set the last mod time. */
6958 * This is equivalent to a write. Ensure it's seen immediately
6959 * if there are no pending writes.
6961 trigger_write_time_update_immediate(new_fsp);
6963 close_file(req, new_fsp, NORMAL_CLOSE);
6964 return NT_STATUS_OK;
6967 /****************************************************************************
6968 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6969 ****************************************************************************/
6971 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6972 struct smb_request *req,
6973 const char *pdata,
6974 int total_data,
6975 files_struct *fsp,
6976 const struct smb_filename *smb_fname,
6977 bool fail_after_createfile)
6979 off_t size;
6981 if (total_data < 8) {
6982 return NT_STATUS_INVALID_PARAMETER;
6985 size = IVAL(pdata,0);
6986 size |= (((off_t)IVAL(pdata,4)) << 32);
6987 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6988 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6989 (double)size));
6991 return smb_set_file_size(conn, req,
6992 fsp,
6993 smb_fname,
6994 &smb_fname->st,
6995 size,
6996 fail_after_createfile);
6999 /****************************************************************************
7000 Allow a UNIX info mknod.
7001 ****************************************************************************/
7003 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7004 const char *pdata,
7005 int total_data,
7006 const struct smb_filename *smb_fname)
7008 uint32 file_type = IVAL(pdata,56);
7009 #if defined(HAVE_MAKEDEV)
7010 uint32 dev_major = IVAL(pdata,60);
7011 uint32 dev_minor = IVAL(pdata,68);
7012 #endif
7013 SMB_DEV_T dev = (SMB_DEV_T)0;
7014 uint32 raw_unixmode = IVAL(pdata,84);
7015 NTSTATUS status;
7016 mode_t unixmode;
7018 if (total_data < 100) {
7019 return NT_STATUS_INVALID_PARAMETER;
7022 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7023 PERM_NEW_FILE, &unixmode);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 return status;
7028 #if defined(HAVE_MAKEDEV)
7029 dev = makedev(dev_major, dev_minor);
7030 #endif
7032 switch (file_type) {
7033 #if defined(S_IFIFO)
7034 case UNIX_TYPE_FIFO:
7035 unixmode |= S_IFIFO;
7036 break;
7037 #endif
7038 #if defined(S_IFSOCK)
7039 case UNIX_TYPE_SOCKET:
7040 unixmode |= S_IFSOCK;
7041 break;
7042 #endif
7043 #if defined(S_IFCHR)
7044 case UNIX_TYPE_CHARDEV:
7045 unixmode |= S_IFCHR;
7046 break;
7047 #endif
7048 #if defined(S_IFBLK)
7049 case UNIX_TYPE_BLKDEV:
7050 unixmode |= S_IFBLK;
7051 break;
7052 #endif
7053 default:
7054 return NT_STATUS_INVALID_PARAMETER;
7057 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7058 "%.0f mode 0%o for file %s\n", (double)dev,
7059 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7061 /* Ok - do the mknod. */
7062 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7063 return map_nt_error_from_unix(errno);
7066 /* If any of the other "set" calls fail we
7067 * don't want to end up with a half-constructed mknod.
7070 if (lp_inherit_perms(SNUM(conn))) {
7071 char *parent;
7072 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7073 &parent, NULL)) {
7074 return NT_STATUS_NO_MEMORY;
7076 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7077 unixmode);
7078 TALLOC_FREE(parent);
7081 return NT_STATUS_OK;
7084 /****************************************************************************
7085 Deal with SMB_SET_FILE_UNIX_BASIC.
7086 ****************************************************************************/
7088 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7089 struct smb_request *req,
7090 const char *pdata,
7091 int total_data,
7092 files_struct *fsp,
7093 const struct smb_filename *smb_fname)
7095 struct smb_file_time ft;
7096 uint32 raw_unixmode;
7097 mode_t unixmode;
7098 off_t size = 0;
7099 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7100 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7101 NTSTATUS status = NT_STATUS_OK;
7102 bool delete_on_fail = False;
7103 enum perm_type ptype;
7104 files_struct *all_fsps = NULL;
7105 bool modify_mtime = true;
7106 struct file_id id;
7107 struct smb_filename *smb_fname_tmp = NULL;
7108 SMB_STRUCT_STAT sbuf;
7110 ZERO_STRUCT(ft);
7112 if (total_data < 100) {
7113 return NT_STATUS_INVALID_PARAMETER;
7116 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7117 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7118 size=IVAL(pdata,0); /* first 8 Bytes are size */
7119 size |= (((off_t)IVAL(pdata,4)) << 32);
7122 ft.atime = interpret_long_date(pdata+24); /* access_time */
7123 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7124 set_owner = (uid_t)IVAL(pdata,40);
7125 set_grp = (gid_t)IVAL(pdata,48);
7126 raw_unixmode = IVAL(pdata,84);
7128 if (VALID_STAT(smb_fname->st)) {
7129 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7130 ptype = PERM_EXISTING_DIR;
7131 } else {
7132 ptype = PERM_EXISTING_FILE;
7134 } else {
7135 ptype = PERM_NEW_FILE;
7138 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7139 ptype, &unixmode);
7140 if (!NT_STATUS_IS_OK(status)) {
7141 return status;
7144 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7145 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7146 smb_fname_str_dbg(smb_fname), (double)size,
7147 (unsigned int)set_owner, (unsigned int)set_grp,
7148 (int)raw_unixmode));
7150 sbuf = smb_fname->st;
7152 if (!VALID_STAT(sbuf)) {
7154 * The only valid use of this is to create character and block
7155 * devices, and named pipes. This is deprecated (IMHO) and
7156 * a new info level should be used for mknod. JRA.
7159 status = smb_unix_mknod(conn,
7160 pdata,
7161 total_data,
7162 smb_fname);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 return status;
7167 status = copy_smb_filename(talloc_tos(), smb_fname,
7168 &smb_fname_tmp);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 return status;
7173 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7174 status = map_nt_error_from_unix(errno);
7175 TALLOC_FREE(smb_fname_tmp);
7176 SMB_VFS_UNLINK(conn, smb_fname);
7177 return status;
7180 sbuf = smb_fname_tmp->st;
7181 smb_fname = smb_fname_tmp;
7183 /* Ensure we don't try and change anything else. */
7184 raw_unixmode = SMB_MODE_NO_CHANGE;
7185 size = get_file_size_stat(&sbuf);
7186 ft.atime = sbuf.st_ex_atime;
7187 ft.mtime = sbuf.st_ex_mtime;
7189 * We continue here as we might want to change the
7190 * owner uid/gid.
7192 delete_on_fail = True;
7195 #if 1
7196 /* Horrible backwards compatibility hack as an old server bug
7197 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7198 * */
7200 if (!size) {
7201 size = get_file_size_stat(&sbuf);
7203 #endif
7206 * Deal with the UNIX specific mode set.
7209 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7210 int ret;
7212 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7213 "setting mode 0%o for file %s\n",
7214 (unsigned int)unixmode,
7215 smb_fname_str_dbg(smb_fname)));
7216 if (fsp && fsp->fh->fd != -1) {
7217 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7218 } else {
7219 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7221 if (ret != 0) {
7222 return map_nt_error_from_unix(errno);
7227 * Deal with the UNIX specific uid set.
7230 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7231 (sbuf.st_ex_uid != set_owner)) {
7232 int ret;
7234 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7235 "changing owner %u for path %s\n",
7236 (unsigned int)set_owner,
7237 smb_fname_str_dbg(smb_fname)));
7239 if (fsp && fsp->fh->fd != -1) {
7240 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7241 } else {
7243 * UNIX extensions calls must always operate
7244 * on symlinks.
7246 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7247 set_owner, (gid_t)-1);
7250 if (ret != 0) {
7251 status = map_nt_error_from_unix(errno);
7252 if (delete_on_fail) {
7253 SMB_VFS_UNLINK(conn, smb_fname);
7255 return status;
7260 * Deal with the UNIX specific gid set.
7263 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7264 (sbuf.st_ex_gid != set_grp)) {
7265 int ret;
7267 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7268 "changing group %u for file %s\n",
7269 (unsigned int)set_owner,
7270 smb_fname_str_dbg(smb_fname)));
7271 if (fsp && fsp->fh->fd != -1) {
7272 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7273 } else {
7275 * UNIX extensions calls must always operate
7276 * on symlinks.
7278 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7279 set_grp);
7281 if (ret != 0) {
7282 status = map_nt_error_from_unix(errno);
7283 if (delete_on_fail) {
7284 SMB_VFS_UNLINK(conn, smb_fname);
7286 return status;
7290 /* Deal with any size changes. */
7292 status = smb_set_file_size(conn, req,
7293 fsp,
7294 smb_fname,
7295 &sbuf,
7296 size,
7297 false);
7298 if (!NT_STATUS_IS_OK(status)) {
7299 return status;
7302 /* Deal with any time changes. */
7303 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7304 /* No change, don't cancel anything. */
7305 return status;
7308 id = vfs_file_id_from_sbuf(conn, &sbuf);
7309 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7310 all_fsps = file_find_di_next(all_fsps)) {
7312 * We're setting the time explicitly for UNIX.
7313 * Cancel any pending changes over all handles.
7315 all_fsps->update_write_time_on_close = false;
7316 TALLOC_FREE(all_fsps->update_write_time_event);
7320 * Override the "setting_write_time"
7321 * parameter here as it almost does what
7322 * we need. Just remember if we modified
7323 * mtime and send the notify ourselves.
7325 if (null_timespec(ft.mtime)) {
7326 modify_mtime = false;
7329 status = smb_set_file_time(conn,
7330 fsp,
7331 smb_fname,
7332 &ft,
7333 false);
7334 if (modify_mtime) {
7335 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7336 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7338 return status;
7341 /****************************************************************************
7342 Deal with SMB_SET_FILE_UNIX_INFO2.
7343 ****************************************************************************/
7345 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7346 struct smb_request *req,
7347 const char *pdata,
7348 int total_data,
7349 files_struct *fsp,
7350 const struct smb_filename *smb_fname)
7352 NTSTATUS status;
7353 uint32 smb_fflags;
7354 uint32 smb_fmask;
7356 if (total_data < 116) {
7357 return NT_STATUS_INVALID_PARAMETER;
7360 /* Start by setting all the fields that are common between UNIX_BASIC
7361 * and UNIX_INFO2.
7363 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7364 fsp, smb_fname);
7365 if (!NT_STATUS_IS_OK(status)) {
7366 return status;
7369 smb_fflags = IVAL(pdata, 108);
7370 smb_fmask = IVAL(pdata, 112);
7372 /* NB: We should only attempt to alter the file flags if the client
7373 * sends a non-zero mask.
7375 if (smb_fmask != 0) {
7376 int stat_fflags = 0;
7378 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7379 smb_fmask, &stat_fflags)) {
7380 /* Client asked to alter a flag we don't understand. */
7381 return NT_STATUS_INVALID_PARAMETER;
7384 if (fsp && fsp->fh->fd != -1) {
7385 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7386 return NT_STATUS_NOT_SUPPORTED;
7387 } else {
7388 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7389 stat_fflags) != 0) {
7390 return map_nt_error_from_unix(errno);
7395 /* XXX: need to add support for changing the create_time here. You
7396 * can do this for paths on Darwin with setattrlist(2). The right way
7397 * to hook this up is probably by extending the VFS utimes interface.
7400 return NT_STATUS_OK;
7403 /****************************************************************************
7404 Create a directory with POSIX semantics.
7405 ****************************************************************************/
7407 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7408 struct smb_request *req,
7409 char **ppdata,
7410 int total_data,
7411 struct smb_filename *smb_fname,
7412 int *pdata_return_size)
7414 NTSTATUS status = NT_STATUS_OK;
7415 uint32 raw_unixmode = 0;
7416 uint32 mod_unixmode = 0;
7417 mode_t unixmode = (mode_t)0;
7418 files_struct *fsp = NULL;
7419 uint16 info_level_return = 0;
7420 int info;
7421 char *pdata = *ppdata;
7423 if (total_data < 18) {
7424 return NT_STATUS_INVALID_PARAMETER;
7427 raw_unixmode = IVAL(pdata,8);
7428 /* Next 4 bytes are not yet defined. */
7430 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7431 PERM_NEW_DIR, &unixmode);
7432 if (!NT_STATUS_IS_OK(status)) {
7433 return status;
7436 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7438 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7439 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7441 status = SMB_VFS_CREATE_FILE(
7442 conn, /* conn */
7443 req, /* req */
7444 0, /* root_dir_fid */
7445 smb_fname, /* fname */
7446 FILE_READ_ATTRIBUTES, /* access_mask */
7447 FILE_SHARE_NONE, /* share_access */
7448 FILE_CREATE, /* create_disposition*/
7449 FILE_DIRECTORY_FILE, /* create_options */
7450 mod_unixmode, /* file_attributes */
7451 0, /* oplock_request */
7452 0, /* allocation_size */
7453 0, /* private_flags */
7454 NULL, /* sd */
7455 NULL, /* ea_list */
7456 &fsp, /* result */
7457 &info); /* pinfo */
7459 if (NT_STATUS_IS_OK(status)) {
7460 close_file(req, fsp, NORMAL_CLOSE);
7463 info_level_return = SVAL(pdata,16);
7465 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7466 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7467 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7468 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7469 } else {
7470 *pdata_return_size = 12;
7473 /* Realloc the data size */
7474 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7475 if (*ppdata == NULL) {
7476 *pdata_return_size = 0;
7477 return NT_STATUS_NO_MEMORY;
7479 pdata = *ppdata;
7481 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7482 SSVAL(pdata,2,0); /* No fnum. */
7483 SIVAL(pdata,4,info); /* Was directory created. */
7485 switch (info_level_return) {
7486 case SMB_QUERY_FILE_UNIX_BASIC:
7487 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7488 SSVAL(pdata,10,0); /* Padding. */
7489 store_file_unix_basic(conn, pdata + 12, fsp,
7490 &smb_fname->st);
7491 break;
7492 case SMB_QUERY_FILE_UNIX_INFO2:
7493 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7494 SSVAL(pdata,10,0); /* Padding. */
7495 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7496 &smb_fname->st);
7497 break;
7498 default:
7499 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7500 SSVAL(pdata,10,0); /* Padding. */
7501 break;
7504 return status;
7507 /****************************************************************************
7508 Open/Create a file with POSIX semantics.
7509 ****************************************************************************/
7511 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7512 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7514 static NTSTATUS smb_posix_open(connection_struct *conn,
7515 struct smb_request *req,
7516 char **ppdata,
7517 int total_data,
7518 struct smb_filename *smb_fname,
7519 int *pdata_return_size)
7521 bool extended_oplock_granted = False;
7522 char *pdata = *ppdata;
7523 uint32 flags = 0;
7524 uint32 wire_open_mode = 0;
7525 uint32 raw_unixmode = 0;
7526 uint32 mod_unixmode = 0;
7527 uint32 create_disp = 0;
7528 uint32 access_mask = 0;
7529 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7530 NTSTATUS status = NT_STATUS_OK;
7531 mode_t unixmode = (mode_t)0;
7532 files_struct *fsp = NULL;
7533 int oplock_request = 0;
7534 int info = 0;
7535 uint16 info_level_return = 0;
7537 if (total_data < 18) {
7538 return NT_STATUS_INVALID_PARAMETER;
7541 flags = IVAL(pdata,0);
7542 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7543 if (oplock_request) {
7544 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7547 wire_open_mode = IVAL(pdata,4);
7549 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7550 return smb_posix_mkdir(conn, req,
7551 ppdata,
7552 total_data,
7553 smb_fname,
7554 pdata_return_size);
7557 switch (wire_open_mode & SMB_ACCMODE) {
7558 case SMB_O_RDONLY:
7559 access_mask = SMB_O_RDONLY_MAPPING;
7560 break;
7561 case SMB_O_WRONLY:
7562 access_mask = SMB_O_WRONLY_MAPPING;
7563 break;
7564 case SMB_O_RDWR:
7565 access_mask = (SMB_O_RDONLY_MAPPING|
7566 SMB_O_WRONLY_MAPPING);
7567 break;
7568 default:
7569 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7570 (unsigned int)wire_open_mode ));
7571 return NT_STATUS_INVALID_PARAMETER;
7574 wire_open_mode &= ~SMB_ACCMODE;
7576 /* First take care of O_CREAT|O_EXCL interactions. */
7577 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7578 case (SMB_O_CREAT | SMB_O_EXCL):
7579 /* File exists fail. File not exist create. */
7580 create_disp = FILE_CREATE;
7581 break;
7582 case SMB_O_CREAT:
7583 /* File exists open. File not exist create. */
7584 create_disp = FILE_OPEN_IF;
7585 break;
7586 case SMB_O_EXCL:
7587 /* O_EXCL on its own without O_CREAT is undefined.
7588 We deliberately ignore it as some versions of
7589 Linux CIFSFS can send a bare O_EXCL on the
7590 wire which other filesystems in the kernel
7591 ignore. See bug 9519 for details. */
7593 /* Fallthrough. */
7595 case 0:
7596 /* File exists open. File not exist fail. */
7597 create_disp = FILE_OPEN;
7598 break;
7599 default:
7600 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7601 (unsigned int)wire_open_mode ));
7602 return NT_STATUS_INVALID_PARAMETER;
7605 /* Next factor in the effects of O_TRUNC. */
7606 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7608 if (wire_open_mode & SMB_O_TRUNC) {
7609 switch (create_disp) {
7610 case FILE_CREATE:
7611 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7612 /* Leave create_disp alone as
7613 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7615 /* File exists fail. File not exist create. */
7616 break;
7617 case FILE_OPEN_IF:
7618 /* SMB_O_CREAT | SMB_O_TRUNC */
7619 /* File exists overwrite. File not exist create. */
7620 create_disp = FILE_OVERWRITE_IF;
7621 break;
7622 case FILE_OPEN:
7623 /* SMB_O_TRUNC */
7624 /* File exists overwrite. File not exist fail. */
7625 create_disp = FILE_OVERWRITE;
7626 break;
7627 default:
7628 /* Cannot get here. */
7629 smb_panic("smb_posix_open: logic error");
7630 return NT_STATUS_INVALID_PARAMETER;
7634 raw_unixmode = IVAL(pdata,8);
7635 /* Next 4 bytes are not yet defined. */
7637 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7638 (VALID_STAT(smb_fname->st) ?
7639 PERM_EXISTING_FILE : PERM_NEW_FILE),
7640 &unixmode);
7642 if (!NT_STATUS_IS_OK(status)) {
7643 return status;
7646 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7648 if (wire_open_mode & SMB_O_SYNC) {
7649 create_options |= FILE_WRITE_THROUGH;
7651 if (wire_open_mode & SMB_O_APPEND) {
7652 access_mask |= FILE_APPEND_DATA;
7654 if (wire_open_mode & SMB_O_DIRECT) {
7655 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7658 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7659 VALID_STAT_OF_DIR(smb_fname->st)) {
7660 if (access_mask != SMB_O_RDONLY_MAPPING) {
7661 return NT_STATUS_FILE_IS_A_DIRECTORY;
7663 create_options &= ~FILE_NON_DIRECTORY_FILE;
7664 create_options |= FILE_DIRECTORY_FILE;
7667 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7668 smb_fname_str_dbg(smb_fname),
7669 (unsigned int)wire_open_mode,
7670 (unsigned int)unixmode ));
7672 status = SMB_VFS_CREATE_FILE(
7673 conn, /* conn */
7674 req, /* req */
7675 0, /* root_dir_fid */
7676 smb_fname, /* fname */
7677 access_mask, /* access_mask */
7678 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7679 FILE_SHARE_DELETE),
7680 create_disp, /* create_disposition*/
7681 create_options, /* create_options */
7682 mod_unixmode, /* file_attributes */
7683 oplock_request, /* oplock_request */
7684 0, /* allocation_size */
7685 0, /* private_flags */
7686 NULL, /* sd */
7687 NULL, /* ea_list */
7688 &fsp, /* result */
7689 &info); /* pinfo */
7691 if (!NT_STATUS_IS_OK(status)) {
7692 return status;
7695 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7696 extended_oplock_granted = True;
7699 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7700 extended_oplock_granted = True;
7703 info_level_return = SVAL(pdata,16);
7705 /* Allocate the correct return size. */
7707 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7708 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7709 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7710 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7711 } else {
7712 *pdata_return_size = 12;
7715 /* Realloc the data size */
7716 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7717 if (*ppdata == NULL) {
7718 close_file(req, fsp, ERROR_CLOSE);
7719 *pdata_return_size = 0;
7720 return NT_STATUS_NO_MEMORY;
7722 pdata = *ppdata;
7724 if (extended_oplock_granted) {
7725 if (flags & REQUEST_BATCH_OPLOCK) {
7726 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7727 } else {
7728 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7730 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7731 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7732 } else {
7733 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7736 SSVAL(pdata,2,fsp->fnum);
7737 SIVAL(pdata,4,info); /* Was file created etc. */
7739 switch (info_level_return) {
7740 case SMB_QUERY_FILE_UNIX_BASIC:
7741 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7742 SSVAL(pdata,10,0); /* padding. */
7743 store_file_unix_basic(conn, pdata + 12, fsp,
7744 &smb_fname->st);
7745 break;
7746 case SMB_QUERY_FILE_UNIX_INFO2:
7747 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7748 SSVAL(pdata,10,0); /* padding. */
7749 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7750 &smb_fname->st);
7751 break;
7752 default:
7753 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7754 SSVAL(pdata,10,0); /* padding. */
7755 break;
7757 return NT_STATUS_OK;
7760 /****************************************************************************
7761 Delete a file with POSIX semantics.
7762 ****************************************************************************/
7764 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7765 struct smb_request *req,
7766 const char *pdata,
7767 int total_data,
7768 struct smb_filename *smb_fname)
7770 NTSTATUS status = NT_STATUS_OK;
7771 files_struct *fsp = NULL;
7772 uint16 flags = 0;
7773 char del = 1;
7774 int info = 0;
7775 int create_options = 0;
7776 int i;
7777 struct share_mode_lock *lck = NULL;
7779 if (total_data < 2) {
7780 return NT_STATUS_INVALID_PARAMETER;
7783 flags = SVAL(pdata,0);
7785 if (!VALID_STAT(smb_fname->st)) {
7786 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7789 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7790 !VALID_STAT_OF_DIR(smb_fname->st)) {
7791 return NT_STATUS_NOT_A_DIRECTORY;
7794 DEBUG(10,("smb_posix_unlink: %s %s\n",
7795 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7796 smb_fname_str_dbg(smb_fname)));
7798 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7799 create_options |= FILE_DIRECTORY_FILE;
7802 status = SMB_VFS_CREATE_FILE(
7803 conn, /* conn */
7804 req, /* req */
7805 0, /* root_dir_fid */
7806 smb_fname, /* fname */
7807 DELETE_ACCESS, /* access_mask */
7808 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7809 FILE_SHARE_DELETE),
7810 FILE_OPEN, /* create_disposition*/
7811 create_options, /* create_options */
7812 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7813 0, /* oplock_request */
7814 0, /* allocation_size */
7815 0, /* private_flags */
7816 NULL, /* sd */
7817 NULL, /* ea_list */
7818 &fsp, /* result */
7819 &info); /* pinfo */
7821 if (!NT_STATUS_IS_OK(status)) {
7822 return status;
7826 * Don't lie to client. If we can't really delete due to
7827 * non-POSIX opens return SHARING_VIOLATION.
7830 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7831 if (lck == NULL) {
7832 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7833 "lock for file %s\n", fsp_str_dbg(fsp)));
7834 close_file(req, fsp, NORMAL_CLOSE);
7835 return NT_STATUS_INVALID_PARAMETER;
7839 * See if others still have the file open. If this is the case, then
7840 * don't delete. If all opens are POSIX delete we can set the delete
7841 * on close disposition.
7843 for (i=0; i<lck->data->num_share_modes; i++) {
7844 struct share_mode_entry *e = &lck->data->share_modes[i];
7845 if (is_valid_share_mode_entry(e)) {
7846 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7847 continue;
7849 if (share_mode_stale_pid(lck->data, i)) {
7850 continue;
7852 /* Fail with sharing violation. */
7853 TALLOC_FREE(lck);
7854 close_file(req, fsp, NORMAL_CLOSE);
7855 return NT_STATUS_SHARING_VIOLATION;
7860 * Set the delete on close.
7862 status = smb_set_file_disposition_info(conn,
7863 &del,
7865 fsp,
7866 smb_fname);
7868 TALLOC_FREE(lck);
7870 if (!NT_STATUS_IS_OK(status)) {
7871 close_file(req, fsp, NORMAL_CLOSE);
7872 return status;
7874 return close_file(req, fsp, NORMAL_CLOSE);
7877 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7878 struct smb_request *req,
7879 TALLOC_CTX *mem_ctx,
7880 uint16_t info_level,
7881 files_struct *fsp,
7882 struct smb_filename *smb_fname,
7883 char **ppdata, int total_data,
7884 int *ret_data_size)
7886 char *pdata = *ppdata;
7887 NTSTATUS status = NT_STATUS_OK;
7888 int data_return_size = 0;
7890 *ret_data_size = 0;
7892 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7893 return NT_STATUS_INVALID_LEVEL;
7896 if (!CAN_WRITE(conn)) {
7897 /* Allow POSIX opens. The open path will deny
7898 * any non-readonly opens. */
7899 if (info_level != SMB_POSIX_PATH_OPEN) {
7900 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7904 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7905 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7906 fsp_fnum_dbg(fsp),
7907 info_level, total_data));
7909 switch (info_level) {
7911 case SMB_INFO_STANDARD:
7913 status = smb_set_info_standard(conn,
7914 pdata,
7915 total_data,
7916 fsp,
7917 smb_fname);
7918 break;
7921 case SMB_INFO_SET_EA:
7923 status = smb_info_set_ea(conn,
7924 pdata,
7925 total_data,
7926 fsp,
7927 smb_fname);
7928 break;
7931 case SMB_SET_FILE_BASIC_INFO:
7932 case SMB_FILE_BASIC_INFORMATION:
7934 status = smb_set_file_basic_info(conn,
7935 pdata,
7936 total_data,
7937 fsp,
7938 smb_fname);
7939 break;
7942 case SMB_FILE_ALLOCATION_INFORMATION:
7943 case SMB_SET_FILE_ALLOCATION_INFO:
7945 status = smb_set_file_allocation_info(conn, req,
7946 pdata,
7947 total_data,
7948 fsp,
7949 smb_fname);
7950 break;
7953 case SMB_FILE_END_OF_FILE_INFORMATION:
7954 case SMB_SET_FILE_END_OF_FILE_INFO:
7957 * XP/Win7 both fail after the createfile with
7958 * SMB_SET_FILE_END_OF_FILE_INFO but not
7959 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7960 * The level is known here, so pass it down
7961 * appropriately.
7963 bool should_fail =
7964 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7966 status = smb_set_file_end_of_file_info(conn, req,
7967 pdata,
7968 total_data,
7969 fsp,
7970 smb_fname,
7971 should_fail);
7972 break;
7975 case SMB_FILE_DISPOSITION_INFORMATION:
7976 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7978 #if 0
7979 /* JRA - We used to just ignore this on a path ?
7980 * Shouldn't this be invalid level on a pathname
7981 * based call ?
7983 if (tran_call != TRANSACT2_SETFILEINFO) {
7984 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7986 #endif
7987 status = smb_set_file_disposition_info(conn,
7988 pdata,
7989 total_data,
7990 fsp,
7991 smb_fname);
7992 break;
7995 case SMB_FILE_POSITION_INFORMATION:
7997 status = smb_file_position_information(conn,
7998 pdata,
7999 total_data,
8000 fsp);
8001 break;
8004 case SMB_FILE_FULL_EA_INFORMATION:
8006 status = smb_set_file_full_ea_info(conn,
8007 pdata,
8008 total_data,
8009 fsp);
8010 break;
8013 /* From tridge Samba4 :
8014 * MODE_INFORMATION in setfileinfo (I have no
8015 * idea what "mode information" on a file is - it takes a value of 0,
8016 * 2, 4 or 6. What could it be?).
8019 case SMB_FILE_MODE_INFORMATION:
8021 status = smb_file_mode_information(conn,
8022 pdata,
8023 total_data);
8024 break;
8028 * CIFS UNIX extensions.
8031 case SMB_SET_FILE_UNIX_BASIC:
8033 status = smb_set_file_unix_basic(conn, req,
8034 pdata,
8035 total_data,
8036 fsp,
8037 smb_fname);
8038 break;
8041 case SMB_SET_FILE_UNIX_INFO2:
8043 status = smb_set_file_unix_info2(conn, req,
8044 pdata,
8045 total_data,
8046 fsp,
8047 smb_fname);
8048 break;
8051 case SMB_SET_FILE_UNIX_LINK:
8053 if (fsp) {
8054 /* We must have a pathname for this. */
8055 return NT_STATUS_INVALID_LEVEL;
8057 status = smb_set_file_unix_link(conn, req, pdata,
8058 total_data, smb_fname);
8059 break;
8062 case SMB_SET_FILE_UNIX_HLINK:
8064 if (fsp) {
8065 /* We must have a pathname for this. */
8066 return NT_STATUS_INVALID_LEVEL;
8068 status = smb_set_file_unix_hlink(conn, req,
8069 pdata, total_data,
8070 smb_fname);
8071 break;
8074 case SMB_FILE_RENAME_INFORMATION:
8076 status = smb_file_rename_information(conn, req,
8077 pdata, total_data,
8078 fsp, smb_fname);
8079 break;
8082 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8084 /* SMB2 rename information. */
8085 status = smb2_file_rename_information(conn, req,
8086 pdata, total_data,
8087 fsp, smb_fname);
8088 break;
8091 case SMB_FILE_LINK_INFORMATION:
8093 status = smb_file_link_information(conn, req,
8094 pdata, total_data,
8095 fsp, smb_fname);
8096 break;
8099 #if defined(HAVE_POSIX_ACLS)
8100 case SMB_SET_POSIX_ACL:
8102 status = smb_set_posix_acl(conn,
8103 pdata,
8104 total_data,
8105 fsp,
8106 smb_fname);
8107 break;
8109 #endif
8111 case SMB_SET_POSIX_LOCK:
8113 if (!fsp) {
8114 return NT_STATUS_INVALID_LEVEL;
8116 status = smb_set_posix_lock(conn, req,
8117 pdata, total_data, fsp);
8118 break;
8121 case SMB_POSIX_PATH_OPEN:
8123 if (fsp) {
8124 /* We must have a pathname for this. */
8125 return NT_STATUS_INVALID_LEVEL;
8128 status = smb_posix_open(conn, req,
8129 ppdata,
8130 total_data,
8131 smb_fname,
8132 &data_return_size);
8133 break;
8136 case SMB_POSIX_PATH_UNLINK:
8138 if (fsp) {
8139 /* We must have a pathname for this. */
8140 return NT_STATUS_INVALID_LEVEL;
8143 status = smb_posix_unlink(conn, req,
8144 pdata,
8145 total_data,
8146 smb_fname);
8147 break;
8150 default:
8151 return NT_STATUS_INVALID_LEVEL;
8154 if (!NT_STATUS_IS_OK(status)) {
8155 return status;
8158 *ret_data_size = data_return_size;
8159 return NT_STATUS_OK;
8162 /****************************************************************************
8163 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8164 ****************************************************************************/
8166 static void call_trans2setfilepathinfo(connection_struct *conn,
8167 struct smb_request *req,
8168 unsigned int tran_call,
8169 char **pparams, int total_params,
8170 char **ppdata, int total_data,
8171 unsigned int max_data_bytes)
8173 char *params = *pparams;
8174 char *pdata = *ppdata;
8175 uint16 info_level;
8176 struct smb_filename *smb_fname = NULL;
8177 files_struct *fsp = NULL;
8178 NTSTATUS status = NT_STATUS_OK;
8179 int data_return_size = 0;
8181 if (!params) {
8182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8183 return;
8186 if (tran_call == TRANSACT2_SETFILEINFO) {
8187 if (total_params < 4) {
8188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8189 return;
8192 fsp = file_fsp(req, SVAL(params,0));
8193 /* Basic check for non-null fsp. */
8194 if (!check_fsp_open(conn, req, fsp)) {
8195 return;
8197 info_level = SVAL(params,2);
8199 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8200 &smb_fname);
8201 if (!NT_STATUS_IS_OK(status)) {
8202 reply_nterror(req, status);
8203 return;
8206 if(fsp->fh->fd == -1) {
8208 * This is actually a SETFILEINFO on a directory
8209 * handle (returned from an NT SMB). NT5.0 seems
8210 * to do this call. JRA.
8212 if (INFO_LEVEL_IS_UNIX(info_level)) {
8213 /* Always do lstat for UNIX calls. */
8214 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8215 DEBUG(3,("call_trans2setfilepathinfo: "
8216 "SMB_VFS_LSTAT of %s failed "
8217 "(%s)\n",
8218 smb_fname_str_dbg(smb_fname),
8219 strerror(errno)));
8220 reply_nterror(req, map_nt_error_from_unix(errno));
8221 return;
8223 } else {
8224 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8225 DEBUG(3,("call_trans2setfilepathinfo: "
8226 "fileinfo of %s failed (%s)\n",
8227 smb_fname_str_dbg(smb_fname),
8228 strerror(errno)));
8229 reply_nterror(req, map_nt_error_from_unix(errno));
8230 return;
8233 } else if (fsp->print_file) {
8235 * Doing a DELETE_ON_CLOSE should cancel a print job.
8237 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8238 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8240 DEBUG(3,("call_trans2setfilepathinfo: "
8241 "Cancelling print job (%s)\n",
8242 fsp_str_dbg(fsp)));
8244 SSVAL(params,0,0);
8245 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8246 *ppdata, 0,
8247 max_data_bytes);
8248 return;
8249 } else {
8250 reply_nterror(req,
8251 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8252 return;
8254 } else {
8256 * Original code - this is an open file.
8258 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8259 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8260 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8261 strerror(errno)));
8262 reply_nterror(req, map_nt_error_from_unix(errno));
8263 return;
8266 } else {
8267 char *fname = NULL;
8268 uint32_t ucf_flags = 0;
8270 /* set path info */
8271 if (total_params < 7) {
8272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8273 return;
8276 info_level = SVAL(params,0);
8277 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8278 total_params - 6, STR_TERMINATE,
8279 &status);
8280 if (!NT_STATUS_IS_OK(status)) {
8281 reply_nterror(req, status);
8282 return;
8285 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8286 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8287 info_level == SMB_FILE_RENAME_INFORMATION ||
8288 info_level == SMB_POSIX_PATH_UNLINK) {
8289 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8292 status = filename_convert(req, conn,
8293 req->flags2 & FLAGS2_DFS_PATHNAMES,
8294 fname,
8295 ucf_flags,
8296 NULL,
8297 &smb_fname);
8298 if (!NT_STATUS_IS_OK(status)) {
8299 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8300 reply_botherror(req,
8301 NT_STATUS_PATH_NOT_COVERED,
8302 ERRSRV, ERRbadpath);
8303 return;
8305 reply_nterror(req, status);
8306 return;
8309 if (INFO_LEVEL_IS_UNIX(info_level)) {
8311 * For CIFS UNIX extensions the target name may not exist.
8314 /* Always do lstat for UNIX calls. */
8315 SMB_VFS_LSTAT(conn, smb_fname);
8317 } else if (!VALID_STAT(smb_fname->st) &&
8318 SMB_VFS_STAT(conn, smb_fname)) {
8319 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8320 "%s failed (%s)\n",
8321 smb_fname_str_dbg(smb_fname),
8322 strerror(errno)));
8323 reply_nterror(req, map_nt_error_from_unix(errno));
8324 return;
8328 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8329 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8330 fsp_fnum_dbg(fsp),
8331 info_level,total_data));
8333 /* Realloc the parameter size */
8334 *pparams = (char *)SMB_REALLOC(*pparams,2);
8335 if (*pparams == NULL) {
8336 reply_nterror(req, NT_STATUS_NO_MEMORY);
8337 return;
8339 params = *pparams;
8341 SSVAL(params,0,0);
8343 status = smbd_do_setfilepathinfo(conn, req, req,
8344 info_level,
8345 fsp,
8346 smb_fname,
8347 ppdata, total_data,
8348 &data_return_size);
8349 if (!NT_STATUS_IS_OK(status)) {
8350 if (open_was_deferred(req->sconn, req->mid)) {
8351 /* We have re-scheduled this call. */
8352 return;
8354 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8355 /* We have re-scheduled this call. */
8356 return;
8358 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8359 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8360 ERRSRV, ERRbadpath);
8361 return;
8363 if (info_level == SMB_POSIX_PATH_OPEN) {
8364 reply_openerror(req, status);
8365 return;
8369 * Invalid EA name needs to return 2 param bytes,
8370 * not a zero-length error packet.
8372 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8373 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8374 max_data_bytes);
8375 } else {
8376 reply_nterror(req, status);
8378 return;
8381 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8382 max_data_bytes);
8384 return;
8387 /****************************************************************************
8388 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8389 ****************************************************************************/
8391 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8392 char **pparams, int total_params,
8393 char **ppdata, int total_data,
8394 unsigned int max_data_bytes)
8396 struct smb_filename *smb_dname = NULL;
8397 char *params = *pparams;
8398 char *pdata = *ppdata;
8399 char *directory = NULL;
8400 NTSTATUS status = NT_STATUS_OK;
8401 struct ea_list *ea_list = NULL;
8402 TALLOC_CTX *ctx = talloc_tos();
8404 if (!CAN_WRITE(conn)) {
8405 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8406 return;
8409 if (total_params < 5) {
8410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8411 return;
8414 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8415 total_params - 4, STR_TERMINATE,
8416 &status);
8417 if (!NT_STATUS_IS_OK(status)) {
8418 reply_nterror(req, status);
8419 return;
8422 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8424 status = filename_convert(ctx,
8425 conn,
8426 req->flags2 & FLAGS2_DFS_PATHNAMES,
8427 directory,
8429 NULL,
8430 &smb_dname);
8432 if (!NT_STATUS_IS_OK(status)) {
8433 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8434 reply_botherror(req,
8435 NT_STATUS_PATH_NOT_COVERED,
8436 ERRSRV, ERRbadpath);
8437 return;
8439 reply_nterror(req, status);
8440 return;
8444 * OS/2 workplace shell seems to send SET_EA requests of "null"
8445 * length (4 bytes containing IVAL 4).
8446 * They seem to have no effect. Bug #3212. JRA.
8449 if (total_data && (total_data != 4)) {
8450 /* Any data in this call is an EA list. */
8451 if (total_data < 10) {
8452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8453 goto out;
8456 if (IVAL(pdata,0) > total_data) {
8457 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8458 IVAL(pdata,0), (unsigned int)total_data));
8459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8460 goto out;
8463 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8464 total_data - 4);
8465 if (!ea_list) {
8466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8467 goto out;
8470 if (!lp_ea_support(SNUM(conn))) {
8471 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8472 goto out;
8475 /* If total_data == 4 Windows doesn't care what values
8476 * are placed in that field, it just ignores them.
8477 * The System i QNTC IBM SMB client puts bad values here,
8478 * so ignore them. */
8480 status = create_directory(conn, req, smb_dname);
8482 if (!NT_STATUS_IS_OK(status)) {
8483 reply_nterror(req, status);
8484 goto out;
8487 /* Try and set any given EA. */
8488 if (ea_list) {
8489 status = set_ea(conn, NULL, smb_dname, ea_list);
8490 if (!NT_STATUS_IS_OK(status)) {
8491 reply_nterror(req, status);
8492 goto out;
8496 /* Realloc the parameter and data sizes */
8497 *pparams = (char *)SMB_REALLOC(*pparams,2);
8498 if(*pparams == NULL) {
8499 reply_nterror(req, NT_STATUS_NO_MEMORY);
8500 goto out;
8502 params = *pparams;
8504 SSVAL(params,0,0);
8506 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8508 out:
8509 TALLOC_FREE(smb_dname);
8510 return;
8513 /****************************************************************************
8514 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8515 We don't actually do this - we just send a null response.
8516 ****************************************************************************/
8518 static void call_trans2findnotifyfirst(connection_struct *conn,
8519 struct smb_request *req,
8520 char **pparams, int total_params,
8521 char **ppdata, int total_data,
8522 unsigned int max_data_bytes)
8524 char *params = *pparams;
8525 uint16 info_level;
8527 if (total_params < 6) {
8528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8529 return;
8532 info_level = SVAL(params,4);
8533 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8535 switch (info_level) {
8536 case 1:
8537 case 2:
8538 break;
8539 default:
8540 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8541 return;
8544 /* Realloc the parameter and data sizes */
8545 *pparams = (char *)SMB_REALLOC(*pparams,6);
8546 if (*pparams == NULL) {
8547 reply_nterror(req, NT_STATUS_NO_MEMORY);
8548 return;
8550 params = *pparams;
8552 SSVAL(params,0,fnf_handle);
8553 SSVAL(params,2,0); /* No changes */
8554 SSVAL(params,4,0); /* No EA errors */
8556 fnf_handle++;
8558 if(fnf_handle == 0)
8559 fnf_handle = 257;
8561 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8563 return;
8566 /****************************************************************************
8567 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8568 changes). Currently this does nothing.
8569 ****************************************************************************/
8571 static void call_trans2findnotifynext(connection_struct *conn,
8572 struct smb_request *req,
8573 char **pparams, int total_params,
8574 char **ppdata, int total_data,
8575 unsigned int max_data_bytes)
8577 char *params = *pparams;
8579 DEBUG(3,("call_trans2findnotifynext\n"));
8581 /* Realloc the parameter and data sizes */
8582 *pparams = (char *)SMB_REALLOC(*pparams,4);
8583 if (*pparams == NULL) {
8584 reply_nterror(req, NT_STATUS_NO_MEMORY);
8585 return;
8587 params = *pparams;
8589 SSVAL(params,0,0); /* No changes */
8590 SSVAL(params,2,0); /* No EA errors */
8592 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8594 return;
8597 /****************************************************************************
8598 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8599 ****************************************************************************/
8601 static void call_trans2getdfsreferral(connection_struct *conn,
8602 struct smb_request *req,
8603 char **pparams, int total_params,
8604 char **ppdata, int total_data,
8605 unsigned int max_data_bytes)
8607 char *params = *pparams;
8608 char *pathname = NULL;
8609 int reply_size = 0;
8610 int max_referral_level;
8611 NTSTATUS status = NT_STATUS_OK;
8612 TALLOC_CTX *ctx = talloc_tos();
8614 DEBUG(10,("call_trans2getdfsreferral\n"));
8616 if (total_params < 3) {
8617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8618 return;
8621 max_referral_level = SVAL(params,0);
8623 if(!lp_host_msdfs()) {
8624 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8625 return;
8628 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8629 total_params - 2, STR_TERMINATE);
8630 if (!pathname) {
8631 reply_nterror(req, NT_STATUS_NOT_FOUND);
8632 return;
8634 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8635 ppdata,&status)) < 0) {
8636 reply_nterror(req, status);
8637 return;
8640 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8641 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8642 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8644 return;
8647 #define LMCAT_SPL 0x53
8648 #define LMFUNC_GETJOBID 0x60
8650 /****************************************************************************
8651 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8652 ****************************************************************************/
8654 static void call_trans2ioctl(connection_struct *conn,
8655 struct smb_request *req,
8656 char **pparams, int total_params,
8657 char **ppdata, int total_data,
8658 unsigned int max_data_bytes)
8660 char *pdata = *ppdata;
8661 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8663 /* check for an invalid fid before proceeding */
8665 if (!fsp) {
8666 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8667 return;
8670 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8671 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8672 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8673 if (*ppdata == NULL) {
8674 reply_nterror(req, NT_STATUS_NO_MEMORY);
8675 return;
8677 pdata = *ppdata;
8679 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8680 CAN ACCEPT THIS IN UNICODE. JRA. */
8682 /* Job number */
8683 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8685 srvstr_push(pdata, req->flags2, pdata + 2,
8686 lp_netbios_name(), 15,
8687 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8688 srvstr_push(pdata, req->flags2, pdata+18,
8689 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8690 STR_ASCII|STR_TERMINATE); /* Service name */
8691 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8692 max_data_bytes);
8693 return;
8696 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8697 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8700 /****************************************************************************
8701 Reply to a SMBfindclose (stop trans2 directory search).
8702 ****************************************************************************/
8704 void reply_findclose(struct smb_request *req)
8706 int dptr_num;
8707 struct smbd_server_connection *sconn = req->sconn;
8709 START_PROFILE(SMBfindclose);
8711 if (req->wct < 1) {
8712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8713 END_PROFILE(SMBfindclose);
8714 return;
8717 dptr_num = SVALS(req->vwv+0, 0);
8719 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8721 dptr_close(sconn, &dptr_num);
8723 reply_outbuf(req, 0, 0);
8725 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8727 END_PROFILE(SMBfindclose);
8728 return;
8731 /****************************************************************************
8732 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8733 ****************************************************************************/
8735 void reply_findnclose(struct smb_request *req)
8737 int dptr_num;
8739 START_PROFILE(SMBfindnclose);
8741 if (req->wct < 1) {
8742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8743 END_PROFILE(SMBfindnclose);
8744 return;
8747 dptr_num = SVAL(req->vwv+0, 0);
8749 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8751 /* We never give out valid handles for a
8752 findnotifyfirst - so any dptr_num is ok here.
8753 Just ignore it. */
8755 reply_outbuf(req, 0, 0);
8757 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8759 END_PROFILE(SMBfindnclose);
8760 return;
8763 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8764 struct trans_state *state)
8766 if (get_Protocol() >= PROTOCOL_NT1) {
8767 req->flags2 |= 0x40; /* IS_LONG_NAME */
8768 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8771 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8772 if (state->call != TRANSACT2_QFSINFO &&
8773 state->call != TRANSACT2_SETFSINFO) {
8774 DEBUG(0,("handle_trans2: encryption required "
8775 "with call 0x%x\n",
8776 (unsigned int)state->call));
8777 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8778 return;
8782 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8784 /* Now we must call the relevant TRANS2 function */
8785 switch(state->call) {
8786 case TRANSACT2_OPEN:
8788 START_PROFILE(Trans2_open);
8789 call_trans2open(conn, req,
8790 &state->param, state->total_param,
8791 &state->data, state->total_data,
8792 state->max_data_return);
8793 END_PROFILE(Trans2_open);
8794 break;
8797 case TRANSACT2_FINDFIRST:
8799 START_PROFILE(Trans2_findfirst);
8800 call_trans2findfirst(conn, req,
8801 &state->param, state->total_param,
8802 &state->data, state->total_data,
8803 state->max_data_return);
8804 END_PROFILE(Trans2_findfirst);
8805 break;
8808 case TRANSACT2_FINDNEXT:
8810 START_PROFILE(Trans2_findnext);
8811 call_trans2findnext(conn, req,
8812 &state->param, state->total_param,
8813 &state->data, state->total_data,
8814 state->max_data_return);
8815 END_PROFILE(Trans2_findnext);
8816 break;
8819 case TRANSACT2_QFSINFO:
8821 START_PROFILE(Trans2_qfsinfo);
8822 call_trans2qfsinfo(conn, req,
8823 &state->param, state->total_param,
8824 &state->data, state->total_data,
8825 state->max_data_return);
8826 END_PROFILE(Trans2_qfsinfo);
8827 break;
8830 case TRANSACT2_SETFSINFO:
8832 START_PROFILE(Trans2_setfsinfo);
8833 call_trans2setfsinfo(conn, req,
8834 &state->param, state->total_param,
8835 &state->data, state->total_data,
8836 state->max_data_return);
8837 END_PROFILE(Trans2_setfsinfo);
8838 break;
8841 case TRANSACT2_QPATHINFO:
8842 case TRANSACT2_QFILEINFO:
8844 START_PROFILE(Trans2_qpathinfo);
8845 call_trans2qfilepathinfo(conn, req, state->call,
8846 &state->param, state->total_param,
8847 &state->data, state->total_data,
8848 state->max_data_return);
8849 END_PROFILE(Trans2_qpathinfo);
8850 break;
8853 case TRANSACT2_SETPATHINFO:
8854 case TRANSACT2_SETFILEINFO:
8856 START_PROFILE(Trans2_setpathinfo);
8857 call_trans2setfilepathinfo(conn, req, state->call,
8858 &state->param, state->total_param,
8859 &state->data, state->total_data,
8860 state->max_data_return);
8861 END_PROFILE(Trans2_setpathinfo);
8862 break;
8865 case TRANSACT2_FINDNOTIFYFIRST:
8867 START_PROFILE(Trans2_findnotifyfirst);
8868 call_trans2findnotifyfirst(conn, req,
8869 &state->param, state->total_param,
8870 &state->data, state->total_data,
8871 state->max_data_return);
8872 END_PROFILE(Trans2_findnotifyfirst);
8873 break;
8876 case TRANSACT2_FINDNOTIFYNEXT:
8878 START_PROFILE(Trans2_findnotifynext);
8879 call_trans2findnotifynext(conn, req,
8880 &state->param, state->total_param,
8881 &state->data, state->total_data,
8882 state->max_data_return);
8883 END_PROFILE(Trans2_findnotifynext);
8884 break;
8887 case TRANSACT2_MKDIR:
8889 START_PROFILE(Trans2_mkdir);
8890 call_trans2mkdir(conn, req,
8891 &state->param, state->total_param,
8892 &state->data, state->total_data,
8893 state->max_data_return);
8894 END_PROFILE(Trans2_mkdir);
8895 break;
8898 case TRANSACT2_GET_DFS_REFERRAL:
8900 START_PROFILE(Trans2_get_dfs_referral);
8901 call_trans2getdfsreferral(conn, req,
8902 &state->param, state->total_param,
8903 &state->data, state->total_data,
8904 state->max_data_return);
8905 END_PROFILE(Trans2_get_dfs_referral);
8906 break;
8909 case TRANSACT2_IOCTL:
8911 START_PROFILE(Trans2_ioctl);
8912 call_trans2ioctl(conn, req,
8913 &state->param, state->total_param,
8914 &state->data, state->total_data,
8915 state->max_data_return);
8916 END_PROFILE(Trans2_ioctl);
8917 break;
8920 default:
8921 /* Error in request */
8922 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8923 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8927 /****************************************************************************
8928 Reply to a SMBtrans2.
8929 ****************************************************************************/
8931 void reply_trans2(struct smb_request *req)
8933 connection_struct *conn = req->conn;
8934 unsigned int dsoff;
8935 unsigned int dscnt;
8936 unsigned int psoff;
8937 unsigned int pscnt;
8938 unsigned int tran_call;
8939 struct trans_state *state;
8940 NTSTATUS result;
8942 START_PROFILE(SMBtrans2);
8944 if (req->wct < 14) {
8945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8946 END_PROFILE(SMBtrans2);
8947 return;
8950 dsoff = SVAL(req->vwv+12, 0);
8951 dscnt = SVAL(req->vwv+11, 0);
8952 psoff = SVAL(req->vwv+10, 0);
8953 pscnt = SVAL(req->vwv+9, 0);
8954 tran_call = SVAL(req->vwv+14, 0);
8956 result = allow_new_trans(conn->pending_trans, req->mid);
8957 if (!NT_STATUS_IS_OK(result)) {
8958 DEBUG(2, ("Got invalid trans2 request: %s\n",
8959 nt_errstr(result)));
8960 reply_nterror(req, result);
8961 END_PROFILE(SMBtrans2);
8962 return;
8965 if (IS_IPC(conn)) {
8966 switch (tran_call) {
8967 /* List the allowed trans2 calls on IPC$ */
8968 case TRANSACT2_OPEN:
8969 case TRANSACT2_GET_DFS_REFERRAL:
8970 case TRANSACT2_QFILEINFO:
8971 case TRANSACT2_QFSINFO:
8972 case TRANSACT2_SETFSINFO:
8973 break;
8974 default:
8975 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8976 END_PROFILE(SMBtrans2);
8977 return;
8981 if ((state = talloc(conn, struct trans_state)) == NULL) {
8982 DEBUG(0, ("talloc failed\n"));
8983 reply_nterror(req, NT_STATUS_NO_MEMORY);
8984 END_PROFILE(SMBtrans2);
8985 return;
8988 state->cmd = SMBtrans2;
8990 state->mid = req->mid;
8991 state->vuid = req->vuid;
8992 state->setup_count = SVAL(req->vwv+13, 0);
8993 state->setup = NULL;
8994 state->total_param = SVAL(req->vwv+0, 0);
8995 state->param = NULL;
8996 state->total_data = SVAL(req->vwv+1, 0);
8997 state->data = NULL;
8998 state->max_param_return = SVAL(req->vwv+2, 0);
8999 state->max_data_return = SVAL(req->vwv+3, 0);
9000 state->max_setup_return = SVAL(req->vwv+4, 0);
9001 state->close_on_completion = BITSETW(req->vwv+5, 0);
9002 state->one_way = BITSETW(req->vwv+5, 1);
9004 state->call = tran_call;
9006 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9007 is so as a sanity check */
9008 if (state->setup_count != 1) {
9010 * Need to have rc=0 for ioctl to get job id for OS/2.
9011 * Network printing will fail if function is not successful.
9012 * Similar function in reply.c will be used if protocol
9013 * is LANMAN1.0 instead of LM1.2X002.
9014 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9015 * outbuf doesn't have to be set(only job id is used).
9017 if ( (state->setup_count == 4)
9018 && (tran_call == TRANSACT2_IOCTL)
9019 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9020 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9021 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9022 } else {
9023 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9024 DEBUG(2,("Transaction is %d\n",tran_call));
9025 TALLOC_FREE(state);
9026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9027 END_PROFILE(SMBtrans2);
9028 return;
9032 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9033 goto bad_param;
9035 if (state->total_data) {
9037 if (trans_oob(state->total_data, 0, dscnt)
9038 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9039 goto bad_param;
9042 /* Can't use talloc here, the core routines do realloc on the
9043 * params and data. */
9044 state->data = (char *)SMB_MALLOC(state->total_data);
9045 if (state->data == NULL) {
9046 DEBUG(0,("reply_trans2: data malloc fail for %u "
9047 "bytes !\n", (unsigned int)state->total_data));
9048 TALLOC_FREE(state);
9049 reply_nterror(req, NT_STATUS_NO_MEMORY);
9050 END_PROFILE(SMBtrans2);
9051 return;
9054 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9057 if (state->total_param) {
9059 if (trans_oob(state->total_param, 0, pscnt)
9060 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9061 goto bad_param;
9064 /* Can't use talloc here, the core routines do realloc on the
9065 * params and data. */
9066 state->param = (char *)SMB_MALLOC(state->total_param);
9067 if (state->param == NULL) {
9068 DEBUG(0,("reply_trans: param malloc fail for %u "
9069 "bytes !\n", (unsigned int)state->total_param));
9070 SAFE_FREE(state->data);
9071 TALLOC_FREE(state);
9072 reply_nterror(req, NT_STATUS_NO_MEMORY);
9073 END_PROFILE(SMBtrans2);
9074 return;
9077 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9080 state->received_data = dscnt;
9081 state->received_param = pscnt;
9083 if ((state->received_param == state->total_param) &&
9084 (state->received_data == state->total_data)) {
9086 handle_trans2(conn, req, state);
9088 SAFE_FREE(state->data);
9089 SAFE_FREE(state->param);
9090 TALLOC_FREE(state);
9091 END_PROFILE(SMBtrans2);
9092 return;
9095 DLIST_ADD(conn->pending_trans, state);
9097 /* We need to send an interim response then receive the rest
9098 of the parameter/data bytes */
9099 reply_outbuf(req, 0, 0);
9100 show_msg((char *)req->outbuf);
9101 END_PROFILE(SMBtrans2);
9102 return;
9104 bad_param:
9106 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9107 SAFE_FREE(state->data);
9108 SAFE_FREE(state->param);
9109 TALLOC_FREE(state);
9110 END_PROFILE(SMBtrans2);
9111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9115 /****************************************************************************
9116 Reply to a SMBtranss2
9117 ****************************************************************************/
9119 void reply_transs2(struct smb_request *req)
9121 connection_struct *conn = req->conn;
9122 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9123 struct trans_state *state;
9125 START_PROFILE(SMBtranss2);
9127 show_msg((const char *)req->inbuf);
9129 /* Windows clients expect all replies to
9130 a transact secondary (SMBtranss2 0x33)
9131 to have a command code of transact
9132 (SMBtrans2 0x32). See bug #8989
9133 and also [MS-CIFS] section 2.2.4.47.2
9134 for details.
9136 req->cmd = SMBtrans2;
9138 if (req->wct < 8) {
9139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9140 END_PROFILE(SMBtranss2);
9141 return;
9144 for (state = conn->pending_trans; state != NULL;
9145 state = state->next) {
9146 if (state->mid == req->mid) {
9147 break;
9151 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9153 END_PROFILE(SMBtranss2);
9154 return;
9157 /* Revise state->total_param and state->total_data in case they have
9158 changed downwards */
9160 if (SVAL(req->vwv+0, 0) < state->total_param)
9161 state->total_param = SVAL(req->vwv+0, 0);
9162 if (SVAL(req->vwv+1, 0) < state->total_data)
9163 state->total_data = SVAL(req->vwv+1, 0);
9165 pcnt = SVAL(req->vwv+2, 0);
9166 poff = SVAL(req->vwv+3, 0);
9167 pdisp = SVAL(req->vwv+4, 0);
9169 dcnt = SVAL(req->vwv+5, 0);
9170 doff = SVAL(req->vwv+6, 0);
9171 ddisp = SVAL(req->vwv+7, 0);
9173 state->received_param += pcnt;
9174 state->received_data += dcnt;
9176 if ((state->received_data > state->total_data) ||
9177 (state->received_param > state->total_param))
9178 goto bad_param;
9180 if (pcnt) {
9181 if (trans_oob(state->total_param, pdisp, pcnt)
9182 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9183 goto bad_param;
9185 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9188 if (dcnt) {
9189 if (trans_oob(state->total_data, ddisp, dcnt)
9190 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9191 goto bad_param;
9193 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9196 if ((state->received_param < state->total_param) ||
9197 (state->received_data < state->total_data)) {
9198 END_PROFILE(SMBtranss2);
9199 return;
9202 handle_trans2(conn, req, state);
9204 DLIST_REMOVE(conn->pending_trans, state);
9205 SAFE_FREE(state->data);
9206 SAFE_FREE(state->param);
9207 TALLOC_FREE(state);
9209 END_PROFILE(SMBtranss2);
9210 return;
9212 bad_param:
9214 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9215 DLIST_REMOVE(conn->pending_trans, state);
9216 SAFE_FREE(state->data);
9217 SAFE_FREE(state->param);
9218 TALLOC_FREE(state);
9219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9220 END_PROFILE(SMBtranss2);
9221 return;