s3:smbd: allow status code in smbd_do_qfsinfo() to be set by information class handler
[Samba.git] / source3 / smbd / trans2.c
blob86c19f14702ed783f81b3dd3e916532ce4f110b1
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 struct smb_filename *fname,
3121 char **ppdata,
3122 int *ret_data_len)
3124 char *pdata, *end_data;
3125 int data_len = 0, len;
3126 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3127 int snum = SNUM(conn);
3128 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3129 char *filename = NULL;
3130 uint32 additional_flags = 0;
3131 struct smb_filename smb_fname;
3132 SMB_STRUCT_STAT st;
3133 NTSTATUS status = NT_STATUS_OK;
3135 if (fname == NULL || fname->base_name == NULL) {
3136 filename = ".";
3137 } else {
3138 filename = fname->base_name;
3141 if (IS_IPC(conn)) {
3142 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3143 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3144 "info level (0x%x) on IPC$.\n",
3145 (unsigned int)info_level));
3146 return NT_STATUS_ACCESS_DENIED;
3150 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3152 ZERO_STRUCT(smb_fname);
3153 smb_fname.base_name = discard_const_p(char, filename);
3155 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3156 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3157 return map_nt_error_from_unix(errno);
3160 st = smb_fname.st;
3162 *ppdata = (char *)SMB_REALLOC(
3163 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3164 if (*ppdata == NULL) {
3165 return NT_STATUS_NO_MEMORY;
3168 pdata = *ppdata;
3169 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3170 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3172 switch (info_level) {
3173 case SMB_INFO_ALLOCATION:
3175 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3176 data_len = 18;
3177 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3178 return map_nt_error_from_unix(errno);
3181 block_size = lp_block_size(snum);
3182 if (bsize < block_size) {
3183 uint64_t factor = block_size/bsize;
3184 bsize = block_size;
3185 dsize /= factor;
3186 dfree /= factor;
3188 if (bsize > block_size) {
3189 uint64_t factor = bsize/block_size;
3190 bsize = block_size;
3191 dsize *= factor;
3192 dfree *= factor;
3194 bytes_per_sector = 512;
3195 sectors_per_unit = bsize/bytes_per_sector;
3197 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3198 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3199 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3201 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3202 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3203 SIVAL(pdata,l1_cUnit,dsize);
3204 SIVAL(pdata,l1_cUnitAvail,dfree);
3205 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3206 break;
3209 case SMB_INFO_VOLUME:
3210 /* Return volume name */
3212 * Add volume serial number - hash of a combination of
3213 * the called hostname and the service name.
3215 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3217 * Win2k3 and previous mess this up by sending a name length
3218 * one byte short. I believe only older clients (OS/2 Win9x) use
3219 * this call so try fixing this by adding a terminating null to
3220 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3222 len = srvstr_push(
3223 pdata, flags2,
3224 pdata+l2_vol_szVolLabel, vname,
3225 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3226 STR_NOALIGN|STR_TERMINATE);
3227 SCVAL(pdata,l2_vol_cch,len);
3228 data_len = l2_vol_szVolLabel + len;
3229 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3230 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3231 len, vname));
3232 break;
3234 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3235 case SMB_FS_ATTRIBUTE_INFORMATION:
3237 additional_flags = 0;
3238 #if defined(HAVE_SYS_QUOTAS)
3239 additional_flags |= FILE_VOLUME_QUOTAS;
3240 #endif
3242 if(lp_nt_acl_support(SNUM(conn))) {
3243 additional_flags |= FILE_PERSISTENT_ACLS;
3246 /* Capabilities are filled in at connection time through STATVFS call */
3247 additional_flags |= conn->fs_capabilities;
3248 additional_flags |= lp_parm_int(conn->params->service,
3249 "share", "fake_fscaps",
3252 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3253 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3254 additional_flags); /* FS ATTRIBUTES */
3256 SIVAL(pdata,4,255); /* Max filename component length */
3257 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3258 and will think we can't do long filenames */
3259 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3260 PTR_DIFF(end_data, pdata+12),
3261 STR_UNICODE);
3262 SIVAL(pdata,8,len);
3263 data_len = 12 + len;
3264 break;
3266 case SMB_QUERY_FS_LABEL_INFO:
3267 case SMB_FS_LABEL_INFORMATION:
3268 len = srvstr_push(pdata, flags2, pdata+4, vname,
3269 PTR_DIFF(end_data, pdata+4), 0);
3270 data_len = 4 + len;
3271 SIVAL(pdata,0,len);
3272 break;
3274 case SMB_QUERY_FS_VOLUME_INFO:
3275 case SMB_FS_VOLUME_INFORMATION:
3278 * Add volume serial number - hash of a combination of
3279 * the called hostname and the service name.
3281 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3282 (str_checksum(get_local_machine_name())<<16));
3284 /* Max label len is 32 characters. */
3285 len = srvstr_push(pdata, flags2, pdata+18, vname,
3286 PTR_DIFF(end_data, pdata+18),
3287 STR_UNICODE);
3288 SIVAL(pdata,12,len);
3289 data_len = 18+len;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3292 (int)strlen(vname),vname,
3293 lp_servicename(talloc_tos(), snum)));
3294 break;
3296 case SMB_QUERY_FS_SIZE_INFO:
3297 case SMB_FS_SIZE_INFORMATION:
3299 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3300 data_len = 24;
3301 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3302 return map_nt_error_from_unix(errno);
3304 block_size = lp_block_size(snum);
3305 if (bsize < block_size) {
3306 uint64_t factor = block_size/bsize;
3307 bsize = block_size;
3308 dsize /= factor;
3309 dfree /= factor;
3311 if (bsize > block_size) {
3312 uint64_t factor = bsize/block_size;
3313 bsize = block_size;
3314 dsize *= factor;
3315 dfree *= factor;
3317 bytes_per_sector = 512;
3318 sectors_per_unit = bsize/bytes_per_sector;
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3322 SBIG_UINT(pdata,0,dsize);
3323 SBIG_UINT(pdata,8,dfree);
3324 SIVAL(pdata,16,sectors_per_unit);
3325 SIVAL(pdata,20,bytes_per_sector);
3326 break;
3329 case SMB_FS_FULL_SIZE_INFORMATION:
3331 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3332 data_len = 32;
3333 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3334 return map_nt_error_from_unix(errno);
3336 block_size = lp_block_size(snum);
3337 if (bsize < block_size) {
3338 uint64_t factor = block_size/bsize;
3339 bsize = block_size;
3340 dsize /= factor;
3341 dfree /= factor;
3343 if (bsize > block_size) {
3344 uint64_t factor = bsize/block_size;
3345 bsize = block_size;
3346 dsize *= factor;
3347 dfree *= factor;
3349 bytes_per_sector = 512;
3350 sectors_per_unit = bsize/bytes_per_sector;
3351 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3352 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3353 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3354 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3355 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3356 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3357 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3358 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3359 break;
3362 case SMB_QUERY_FS_DEVICE_INFO:
3363 case SMB_FS_DEVICE_INFORMATION:
3365 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3367 if (!CAN_WRITE(conn)) {
3368 characteristics |= FILE_READ_ONLY_DEVICE;
3370 data_len = 8;
3371 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3372 SIVAL(pdata,4,characteristics);
3373 break;
3376 #ifdef HAVE_SYS_QUOTAS
3377 case SMB_FS_QUOTA_INFORMATION:
3379 * what we have to send --metze:
3381 * Unknown1: 24 NULL bytes
3382 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3383 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3384 * Quota Flags: 2 byte :
3385 * Unknown3: 6 NULL bytes
3387 * 48 bytes total
3389 * details for Quota Flags:
3391 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3392 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3393 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3394 * 0x0001 Enable Quotas: enable quota for this fs
3398 /* we need to fake up a fsp here,
3399 * because its not send in this call
3401 files_struct fsp;
3402 SMB_NTQUOTA_STRUCT quotas;
3404 ZERO_STRUCT(fsp);
3405 ZERO_STRUCT(quotas);
3407 fsp.conn = conn;
3408 fsp.fnum = FNUM_FIELD_INVALID;
3410 /* access check */
3411 if (get_current_uid(conn) != 0) {
3412 DEBUG(0,("set_user_quota: access_denied "
3413 "service [%s] user [%s]\n",
3414 lp_servicename(talloc_tos(), SNUM(conn)),
3415 conn->session_info->unix_info->unix_name));
3416 return NT_STATUS_ACCESS_DENIED;
3419 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3420 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3421 return map_nt_error_from_unix(errno);
3424 data_len = 48;
3426 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3427 lp_servicename(talloc_tos(), SNUM(conn))));
3429 /* Unknown1 24 NULL bytes*/
3430 SBIG_UINT(pdata,0,(uint64_t)0);
3431 SBIG_UINT(pdata,8,(uint64_t)0);
3432 SBIG_UINT(pdata,16,(uint64_t)0);
3434 /* Default Soft Quota 8 bytes */
3435 SBIG_UINT(pdata,24,quotas.softlim);
3437 /* Default Hard Quota 8 bytes */
3438 SBIG_UINT(pdata,32,quotas.hardlim);
3440 /* Quota flag 2 bytes */
3441 SSVAL(pdata,40,quotas.qflags);
3443 /* Unknown3 6 NULL bytes */
3444 SSVAL(pdata,42,0);
3445 SIVAL(pdata,44,0);
3447 break;
3449 #endif /* HAVE_SYS_QUOTAS */
3450 case SMB_FS_OBJECTID_INFORMATION:
3452 unsigned char objid[16];
3453 struct smb_extended_info extended_info;
3454 memcpy(pdata,create_volume_objectid(conn, objid),16);
3455 samba_extended_info_version (&extended_info);
3456 SIVAL(pdata,16,extended_info.samba_magic);
3457 SIVAL(pdata,20,extended_info.samba_version);
3458 SIVAL(pdata,24,extended_info.samba_subversion);
3459 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3460 memcpy(pdata+36,extended_info.samba_version_string,28);
3461 data_len = 64;
3462 break;
3466 * Query the version and capabilities of the CIFS UNIX extensions
3467 * in use.
3470 case SMB_QUERY_CIFS_UNIX_INFO:
3472 bool large_write = lp_min_receive_file_size() &&
3473 !srv_is_signing_active(conn->sconn);
3474 bool large_read = !srv_is_signing_active(conn->sconn);
3475 int encrypt_caps = 0;
3477 if (!lp_unix_extensions()) {
3478 return NT_STATUS_INVALID_LEVEL;
3481 switch (conn->encrypt_level) {
3482 case SMB_SIGNING_OFF:
3483 encrypt_caps = 0;
3484 break;
3485 case SMB_SIGNING_IF_REQUIRED:
3486 case SMB_SIGNING_DEFAULT:
3487 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3488 break;
3489 case SMB_SIGNING_REQUIRED:
3490 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3491 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3492 large_write = false;
3493 large_read = false;
3494 break;
3497 data_len = 12;
3498 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3499 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3501 /* We have POSIX ACLs, pathname, encryption,
3502 * large read/write, and locking capability. */
3504 SBIG_UINT(pdata,4,((uint64_t)(
3505 CIFS_UNIX_POSIX_ACLS_CAP|
3506 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3507 CIFS_UNIX_FCNTL_LOCKS_CAP|
3508 CIFS_UNIX_EXTATTR_CAP|
3509 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3510 encrypt_caps|
3511 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3512 (large_write ?
3513 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3514 break;
3517 case SMB_QUERY_POSIX_FS_INFO:
3519 int rc;
3520 vfs_statvfs_struct svfs;
3522 if (!lp_unix_extensions()) {
3523 return NT_STATUS_INVALID_LEVEL;
3526 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3528 if (!rc) {
3529 data_len = 56;
3530 SIVAL(pdata,0,svfs.OptimalTransferSize);
3531 SIVAL(pdata,4,svfs.BlockSize);
3532 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3533 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3534 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3535 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3536 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3537 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3538 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3539 #ifdef EOPNOTSUPP
3540 } else if (rc == EOPNOTSUPP) {
3541 return NT_STATUS_INVALID_LEVEL;
3542 #endif /* EOPNOTSUPP */
3543 } else {
3544 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3545 return NT_STATUS_DOS(ERRSRV, ERRerror);
3547 break;
3550 case SMB_QUERY_POSIX_WHOAMI:
3552 uint32_t flags = 0;
3553 uint32_t sid_bytes;
3554 int i;
3556 if (!lp_unix_extensions()) {
3557 return NT_STATUS_INVALID_LEVEL;
3560 if (max_data_bytes < 40) {
3561 return NT_STATUS_BUFFER_TOO_SMALL;
3564 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3565 flags |= SMB_WHOAMI_GUEST;
3568 /* NOTE: 8 bytes for UID/GID, irrespective of native
3569 * platform size. This matches
3570 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3572 data_len = 4 /* flags */
3573 + 4 /* flag mask */
3574 + 8 /* uid */
3575 + 8 /* gid */
3576 + 4 /* ngroups */
3577 + 4 /* num_sids */
3578 + 4 /* SID bytes */
3579 + 4 /* pad/reserved */
3580 + (conn->session_info->unix_token->ngroups * 8)
3581 /* groups list */
3582 + (conn->session_info->security_token->num_sids *
3583 SID_MAX_SIZE)
3584 /* SID list */;
3586 SIVAL(pdata, 0, flags);
3587 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3588 SBIG_UINT(pdata, 8,
3589 (uint64_t)conn->session_info->unix_token->uid);
3590 SBIG_UINT(pdata, 16,
3591 (uint64_t)conn->session_info->unix_token->gid);
3594 if (data_len >= max_data_bytes) {
3595 /* Potential overflow, skip the GIDs and SIDs. */
3597 SIVAL(pdata, 24, 0); /* num_groups */
3598 SIVAL(pdata, 28, 0); /* num_sids */
3599 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3600 SIVAL(pdata, 36, 0); /* reserved */
3602 data_len = 40;
3603 break;
3606 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3607 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3609 /* We walk the SID list twice, but this call is fairly
3610 * infrequent, and I don't expect that it's performance
3611 * sensitive -- jpeach
3613 for (i = 0, sid_bytes = 0;
3614 i < conn->session_info->security_token->num_sids; ++i) {
3615 sid_bytes += ndr_size_dom_sid(
3616 &conn->session_info->security_token->sids[i],
3620 /* SID list byte count */
3621 SIVAL(pdata, 32, sid_bytes);
3623 /* 4 bytes pad/reserved - must be zero */
3624 SIVAL(pdata, 36, 0);
3625 data_len = 40;
3627 /* GID list */
3628 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3629 SBIG_UINT(pdata, data_len,
3630 (uint64_t)conn->session_info->unix_token->groups[i]);
3631 data_len += 8;
3634 /* SID list */
3635 for (i = 0;
3636 i < conn->session_info->security_token->num_sids; ++i) {
3637 int sid_len = ndr_size_dom_sid(
3638 &conn->session_info->security_token->sids[i],
3641 sid_linearize(pdata + data_len, sid_len,
3642 &conn->session_info->security_token->sids[i]);
3643 data_len += sid_len;
3646 break;
3649 case SMB_MAC_QUERY_FS_INFO:
3651 * Thursby MAC extension... ONLY on NTFS filesystems
3652 * once we do streams then we don't need this
3654 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3655 data_len = 88;
3656 SIVAL(pdata,84,0x100); /* Don't support mac... */
3657 break;
3659 /* drop through */
3660 default:
3661 return NT_STATUS_INVALID_LEVEL;
3664 *ret_data_len = data_len;
3665 return status;
3668 /****************************************************************************
3669 Reply to a TRANS2_QFSINFO (query filesystem info).
3670 ****************************************************************************/
3672 static void call_trans2qfsinfo(connection_struct *conn,
3673 struct smb_request *req,
3674 char **pparams, int total_params,
3675 char **ppdata, int total_data,
3676 unsigned int max_data_bytes)
3678 char *params = *pparams;
3679 uint16_t info_level;
3680 int data_len = 0;
3681 NTSTATUS status;
3683 if (total_params < 2) {
3684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3685 return;
3688 info_level = SVAL(params,0);
3690 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3691 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3692 DEBUG(0,("call_trans2qfsinfo: encryption required "
3693 "and info level 0x%x sent.\n",
3694 (unsigned int)info_level));
3695 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3696 return;
3700 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3702 status = smbd_do_qfsinfo(conn, req,
3703 info_level,
3704 req->flags2,
3705 max_data_bytes,
3706 NULL,
3707 ppdata, &data_len);
3708 if (!NT_STATUS_IS_OK(status)) {
3709 reply_nterror(req, status);
3710 return;
3713 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3714 max_data_bytes);
3716 DEBUG( 4, ( "%s info_level = %d\n",
3717 smb_fn_name(req->cmd), info_level) );
3719 return;
3722 /****************************************************************************
3723 Reply to a TRANS2_SETFSINFO (set filesystem info).
3724 ****************************************************************************/
3726 static void call_trans2setfsinfo(connection_struct *conn,
3727 struct smb_request *req,
3728 char **pparams, int total_params,
3729 char **ppdata, int total_data,
3730 unsigned int max_data_bytes)
3732 struct smbd_server_connection *sconn = req->sconn;
3733 char *pdata = *ppdata;
3734 char *params = *pparams;
3735 uint16 info_level;
3737 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3738 lp_servicename(talloc_tos(), SNUM(conn))));
3740 /* */
3741 if (total_params < 4) {
3742 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3743 total_params));
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 return;
3748 info_level = SVAL(params,2);
3750 if (IS_IPC(conn)) {
3751 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3752 info_level != SMB_SET_CIFS_UNIX_INFO) {
3753 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3754 "info level (0x%x) on IPC$.\n",
3755 (unsigned int)info_level));
3756 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3757 return;
3761 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3762 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3763 DEBUG(0,("call_trans2setfsinfo: encryption required "
3764 "and info level 0x%x sent.\n",
3765 (unsigned int)info_level));
3766 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3767 return;
3771 switch(info_level) {
3772 case SMB_SET_CIFS_UNIX_INFO:
3773 if (!lp_unix_extensions()) {
3774 DEBUG(2,("call_trans2setfsinfo: "
3775 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3776 "unix extensions off\n"));
3777 reply_nterror(req,
3778 NT_STATUS_INVALID_LEVEL);
3779 return;
3782 /* There should be 12 bytes of capabilities set. */
3783 if (total_data < 12) {
3784 reply_nterror(
3785 req,
3786 NT_STATUS_INVALID_PARAMETER);
3787 return;
3789 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3790 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3791 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3792 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3793 /* Just print these values for now. */
3794 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3795 "major = %u, minor = %u cap_low = 0x%x, "
3796 "cap_high = 0x%xn",
3797 (unsigned int)sconn->
3798 smb1.unix_info.client_major,
3799 (unsigned int)sconn->
3800 smb1.unix_info.client_minor,
3801 (unsigned int)sconn->
3802 smb1.unix_info.client_cap_low,
3803 (unsigned int)sconn->
3804 smb1.unix_info.client_cap_high));
3806 /* Here is where we must switch to posix pathname processing... */
3807 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3808 lp_set_posix_pathnames();
3809 mangle_change_to_posix();
3812 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3813 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3814 /* Client that knows how to do posix locks,
3815 * but not posix open/mkdir operations. Set a
3816 * default type for read/write checks. */
3818 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3821 break;
3823 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3825 NTSTATUS status;
3826 size_t param_len = 0;
3827 size_t data_len = total_data;
3829 if (!lp_unix_extensions()) {
3830 reply_nterror(
3831 req,
3832 NT_STATUS_INVALID_LEVEL);
3833 return;
3836 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3837 reply_nterror(
3838 req,
3839 NT_STATUS_NOT_SUPPORTED);
3840 return;
3843 if (req->sconn->smb1.echo_handler.trusted_fde) {
3844 DEBUG( 2,("call_trans2setfsinfo: "
3845 "request transport encryption disabled"
3846 "with 'fork echo handler = yes'\n"));
3847 reply_nterror(
3848 req,
3849 NT_STATUS_NOT_SUPPORTED);
3850 return;
3853 DEBUG( 4,("call_trans2setfsinfo: "
3854 "request transport encryption.\n"));
3856 status = srv_request_encryption_setup(conn,
3857 (unsigned char **)ppdata,
3858 &data_len,
3859 (unsigned char **)pparams,
3860 &param_len);
3862 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3863 !NT_STATUS_IS_OK(status)) {
3864 reply_nterror(req, status);
3865 return;
3868 send_trans2_replies(conn, req,
3869 NT_STATUS_OK,
3870 *pparams,
3871 param_len,
3872 *ppdata,
3873 data_len,
3874 max_data_bytes);
3876 if (NT_STATUS_IS_OK(status)) {
3877 /* Server-side transport
3878 * encryption is now *on*. */
3879 status = srv_encryption_start(conn);
3880 if (!NT_STATUS_IS_OK(status)) {
3881 char *reason = talloc_asprintf(talloc_tos(),
3882 "Failure in setting "
3883 "up encrypted transport: %s",
3884 nt_errstr(status));
3885 exit_server_cleanly(reason);
3888 return;
3891 case SMB_FS_QUOTA_INFORMATION:
3893 files_struct *fsp = NULL;
3894 SMB_NTQUOTA_STRUCT quotas;
3896 ZERO_STRUCT(quotas);
3898 /* access check */
3899 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3900 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3901 lp_servicename(talloc_tos(), SNUM(conn)),
3902 conn->session_info->unix_info->unix_name));
3903 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3904 return;
3907 /* note: normaly there're 48 bytes,
3908 * but we didn't use the last 6 bytes for now
3909 * --metze
3911 fsp = file_fsp(req, SVAL(params,0));
3913 if (!check_fsp_ntquota_handle(conn, req,
3914 fsp)) {
3915 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3916 reply_nterror(
3917 req, NT_STATUS_INVALID_HANDLE);
3918 return;
3921 if (total_data < 42) {
3922 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3923 total_data));
3924 reply_nterror(
3925 req,
3926 NT_STATUS_INVALID_PARAMETER);
3927 return;
3930 /* unknown_1 24 NULL bytes in pdata*/
3932 /* the soft quotas 8 bytes (uint64_t)*/
3933 quotas.softlim = BVAL(pdata,24);
3935 /* the hard quotas 8 bytes (uint64_t)*/
3936 quotas.hardlim = BVAL(pdata,32);
3938 /* quota_flags 2 bytes **/
3939 quotas.qflags = SVAL(pdata,40);
3941 /* unknown_2 6 NULL bytes follow*/
3943 /* now set the quotas */
3944 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3945 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3946 reply_nterror(req, map_nt_error_from_unix(errno));
3947 return;
3950 break;
3952 default:
3953 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3954 info_level));
3955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3956 return;
3957 break;
3961 * sending this reply works fine,
3962 * but I'm not sure it's the same
3963 * like windows do...
3964 * --metze
3966 reply_outbuf(req, 10, 0);
3969 #if defined(HAVE_POSIX_ACLS)
3970 /****************************************************************************
3971 Utility function to count the number of entries in a POSIX acl.
3972 ****************************************************************************/
3974 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3976 unsigned int ace_count = 0;
3977 int entry_id = SMB_ACL_FIRST_ENTRY;
3978 SMB_ACL_ENTRY_T entry;
3980 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3981 /* get_next... */
3982 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3983 entry_id = SMB_ACL_NEXT_ENTRY;
3985 ace_count++;
3987 return ace_count;
3990 /****************************************************************************
3991 Utility function to marshall a POSIX acl into wire format.
3992 ****************************************************************************/
3994 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3996 int entry_id = SMB_ACL_FIRST_ENTRY;
3997 SMB_ACL_ENTRY_T entry;
3999 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4000 SMB_ACL_TAG_T tagtype;
4001 SMB_ACL_PERMSET_T permset;
4002 unsigned char perms = 0;
4003 unsigned int own_grp;
4005 /* get_next... */
4006 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4007 entry_id = SMB_ACL_NEXT_ENTRY;
4010 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4011 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4012 return False;
4015 if (sys_acl_get_permset(entry, &permset) == -1) {
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4017 return False;
4020 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4021 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4022 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4024 SCVAL(pdata,1,perms);
4026 switch (tagtype) {
4027 case SMB_ACL_USER_OBJ:
4028 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4029 own_grp = (unsigned int)pst->st_ex_uid;
4030 SIVAL(pdata,2,own_grp);
4031 SIVAL(pdata,6,0);
4032 break;
4033 case SMB_ACL_USER:
4035 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4036 if (!puid) {
4037 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4038 return False;
4040 own_grp = (unsigned int)*puid;
4041 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4042 SIVAL(pdata,2,own_grp);
4043 SIVAL(pdata,6,0);
4044 break;
4046 case SMB_ACL_GROUP_OBJ:
4047 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4048 own_grp = (unsigned int)pst->st_ex_gid;
4049 SIVAL(pdata,2,own_grp);
4050 SIVAL(pdata,6,0);
4051 break;
4052 case SMB_ACL_GROUP:
4054 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4055 if (!pgid) {
4056 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4057 return False;
4059 own_grp = (unsigned int)*pgid;
4060 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4061 SIVAL(pdata,2,own_grp);
4062 SIVAL(pdata,6,0);
4063 break;
4065 case SMB_ACL_MASK:
4066 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4067 SIVAL(pdata,2,0xFFFFFFFF);
4068 SIVAL(pdata,6,0xFFFFFFFF);
4069 break;
4070 case SMB_ACL_OTHER:
4071 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4072 SIVAL(pdata,2,0xFFFFFFFF);
4073 SIVAL(pdata,6,0xFFFFFFFF);
4074 break;
4075 default:
4076 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4077 return False;
4079 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4082 return True;
4084 #endif
4086 /****************************************************************************
4087 Store the FILE_UNIX_BASIC info.
4088 ****************************************************************************/
4090 static char *store_file_unix_basic(connection_struct *conn,
4091 char *pdata,
4092 files_struct *fsp,
4093 const SMB_STRUCT_STAT *psbuf)
4095 uint64_t file_index = get_FileIndex(conn, psbuf);
4096 dev_t devno;
4098 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4099 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4101 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4102 pdata += 8;
4104 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4105 pdata += 8;
4107 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4108 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4109 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4110 pdata += 24;
4112 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4113 SIVAL(pdata,4,0);
4114 pdata += 8;
4116 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4117 SIVAL(pdata,4,0);
4118 pdata += 8;
4120 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4121 pdata += 4;
4123 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4124 devno = psbuf->st_ex_rdev;
4125 } else {
4126 devno = psbuf->st_ex_dev;
4129 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4130 SIVAL(pdata,4,0);
4131 pdata += 8;
4133 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4134 SIVAL(pdata,4,0);
4135 pdata += 8;
4137 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4138 pdata += 8;
4140 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4141 SIVAL(pdata,4,0);
4142 pdata += 8;
4144 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4145 SIVAL(pdata,4,0);
4146 pdata += 8;
4148 return pdata;
4151 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4152 * the chflags(2) (or equivalent) flags.
4154 * XXX: this really should be behind the VFS interface. To do this, we would
4155 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4156 * Each VFS module could then implement its own mapping as appropriate for the
4157 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4159 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4160 info2_flags_map[] =
4162 #ifdef UF_NODUMP
4163 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4164 #endif
4166 #ifdef UF_IMMUTABLE
4167 { UF_IMMUTABLE, EXT_IMMUTABLE },
4168 #endif
4170 #ifdef UF_APPEND
4171 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4172 #endif
4174 #ifdef UF_HIDDEN
4175 { UF_HIDDEN, EXT_HIDDEN },
4176 #endif
4178 /* Do not remove. We need to guarantee that this array has at least one
4179 * entry to build on HP-UX.
4181 { 0, 0 }
4185 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4186 uint32 *smb_fflags, uint32 *smb_fmask)
4188 int i;
4190 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4191 *smb_fmask |= info2_flags_map[i].smb_fflag;
4192 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4193 *smb_fflags |= info2_flags_map[i].smb_fflag;
4198 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4199 const uint32 smb_fflags,
4200 const uint32 smb_fmask,
4201 int *stat_fflags)
4203 uint32 max_fmask = 0;
4204 int i;
4206 *stat_fflags = psbuf->st_ex_flags;
4208 /* For each flags requested in smb_fmask, check the state of the
4209 * corresponding flag in smb_fflags and set or clear the matching
4210 * stat flag.
4213 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4214 max_fmask |= info2_flags_map[i].smb_fflag;
4215 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4216 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4217 *stat_fflags |= info2_flags_map[i].stat_fflag;
4218 } else {
4219 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4224 /* If smb_fmask is asking to set any bits that are not supported by
4225 * our flag mappings, we should fail.
4227 if ((smb_fmask & max_fmask) != smb_fmask) {
4228 return False;
4231 return True;
4235 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4236 * of file flags and birth (create) time.
4238 static char *store_file_unix_basic_info2(connection_struct *conn,
4239 char *pdata,
4240 files_struct *fsp,
4241 const SMB_STRUCT_STAT *psbuf)
4243 uint32 file_flags = 0;
4244 uint32 flags_mask = 0;
4246 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4248 /* Create (birth) time 64 bit */
4249 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4250 pdata += 8;
4252 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4253 SIVAL(pdata, 0, file_flags); /* flags */
4254 SIVAL(pdata, 4, flags_mask); /* mask */
4255 pdata += 8;
4257 return pdata;
4260 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4261 const struct stream_struct *streams,
4262 char *data,
4263 unsigned int max_data_bytes,
4264 unsigned int *data_size)
4266 unsigned int i;
4267 unsigned int ofs = 0;
4269 for (i = 0; i < num_streams; i++) {
4270 unsigned int next_offset;
4271 size_t namelen;
4272 smb_ucs2_t *namebuf;
4274 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4275 streams[i].name, &namelen) ||
4276 namelen <= 2)
4278 return NT_STATUS_INVALID_PARAMETER;
4282 * name_buf is now null-terminated, we need to marshall as not
4283 * terminated
4286 namelen -= 2;
4289 * We cannot overflow ...
4291 if ((ofs + 24 + namelen) > max_data_bytes) {
4292 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4293 i));
4294 TALLOC_FREE(namebuf);
4295 return STATUS_BUFFER_OVERFLOW;
4298 SIVAL(data, ofs+4, namelen);
4299 SOFF_T(data, ofs+8, streams[i].size);
4300 SOFF_T(data, ofs+16, streams[i].alloc_size);
4301 memcpy(data+ofs+24, namebuf, namelen);
4302 TALLOC_FREE(namebuf);
4304 next_offset = ofs + 24 + namelen;
4306 if (i == num_streams-1) {
4307 SIVAL(data, ofs, 0);
4309 else {
4310 unsigned int align = ndr_align_size(next_offset, 8);
4312 if ((next_offset + align) > max_data_bytes) {
4313 DEBUG(10, ("refusing to overflow align "
4314 "reply at stream %u\n",
4315 i));
4316 TALLOC_FREE(namebuf);
4317 return STATUS_BUFFER_OVERFLOW;
4320 memset(data+next_offset, 0, align);
4321 next_offset += align;
4323 SIVAL(data, ofs, next_offset - ofs);
4324 ofs = next_offset;
4327 ofs = next_offset;
4330 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4332 *data_size = ofs;
4334 return NT_STATUS_OK;
4337 /****************************************************************************
4338 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4339 ****************************************************************************/
4341 static void call_trans2qpipeinfo(connection_struct *conn,
4342 struct smb_request *req,
4343 unsigned int tran_call,
4344 char **pparams, int total_params,
4345 char **ppdata, int total_data,
4346 unsigned int max_data_bytes)
4348 char *params = *pparams;
4349 char *pdata = *ppdata;
4350 unsigned int data_size = 0;
4351 unsigned int param_size = 2;
4352 uint16 info_level;
4353 files_struct *fsp;
4355 if (!params) {
4356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4357 return;
4360 if (total_params < 4) {
4361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4362 return;
4365 fsp = file_fsp(req, SVAL(params,0));
4366 if (!fsp_is_np(fsp)) {
4367 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4368 return;
4371 info_level = SVAL(params,2);
4373 *pparams = (char *)SMB_REALLOC(*pparams,2);
4374 if (*pparams == NULL) {
4375 reply_nterror(req, NT_STATUS_NO_MEMORY);
4376 return;
4378 params = *pparams;
4379 SSVAL(params,0,0);
4380 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4381 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4382 if (*ppdata == NULL ) {
4383 reply_nterror(req, NT_STATUS_NO_MEMORY);
4384 return;
4386 pdata = *ppdata;
4388 switch (info_level) {
4389 case SMB_FILE_STANDARD_INFORMATION:
4390 memset(pdata,0,24);
4391 SOFF_T(pdata,0,4096LL);
4392 SIVAL(pdata,16,1);
4393 SIVAL(pdata,20,1);
4394 data_size = 24;
4395 break;
4397 default:
4398 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4399 return;
4402 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4403 max_data_bytes);
4405 return;
4408 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4409 TALLOC_CTX *mem_ctx,
4410 uint16_t info_level,
4411 files_struct *fsp,
4412 struct smb_filename *smb_fname,
4413 bool delete_pending,
4414 struct timespec write_time_ts,
4415 struct ea_list *ea_list,
4416 int lock_data_count,
4417 char *lock_data,
4418 uint16_t flags2,
4419 unsigned int max_data_bytes,
4420 char **ppdata,
4421 unsigned int *pdata_size)
4423 char *pdata = *ppdata;
4424 char *dstart, *dend;
4425 unsigned int data_size;
4426 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4427 time_t create_time, mtime, atime, c_time;
4428 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4429 char *p;
4430 char *base_name;
4431 char *dos_fname;
4432 int mode;
4433 int nlink;
4434 NTSTATUS status;
4435 uint64_t file_size = 0;
4436 uint64_t pos = 0;
4437 uint64_t allocation_size = 0;
4438 uint64_t file_index = 0;
4439 uint32_t access_mask = 0;
4441 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4442 return NT_STATUS_INVALID_LEVEL;
4445 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4446 smb_fname_str_dbg(smb_fname),
4447 fsp_fnum_dbg(fsp),
4448 info_level, max_data_bytes));
4450 mode = dos_mode(conn, smb_fname);
4451 nlink = psbuf->st_ex_nlink;
4453 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4454 nlink = 1;
4457 if ((nlink > 0) && delete_pending) {
4458 nlink -= 1;
4461 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4462 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4463 if (*ppdata == NULL) {
4464 return NT_STATUS_NO_MEMORY;
4466 pdata = *ppdata;
4467 dstart = pdata;
4468 dend = dstart + data_size - 1;
4470 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4471 update_stat_ex_mtime(psbuf, write_time_ts);
4474 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4475 mtime_ts = psbuf->st_ex_mtime;
4476 atime_ts = psbuf->st_ex_atime;
4477 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4479 if (lp_dos_filetime_resolution(SNUM(conn))) {
4480 dos_filetime_timespec(&create_time_ts);
4481 dos_filetime_timespec(&mtime_ts);
4482 dos_filetime_timespec(&atime_ts);
4483 dos_filetime_timespec(&ctime_ts);
4486 create_time = convert_timespec_to_time_t(create_time_ts);
4487 mtime = convert_timespec_to_time_t(mtime_ts);
4488 atime = convert_timespec_to_time_t(atime_ts);
4489 c_time = convert_timespec_to_time_t(ctime_ts);
4491 p = strrchr_m(smb_fname->base_name,'/');
4492 if (!p)
4493 base_name = smb_fname->base_name;
4494 else
4495 base_name = p+1;
4497 /* NT expects the name to be in an exact form of the *full*
4498 filename. See the trans2 torture test */
4499 if (ISDOT(base_name)) {
4500 dos_fname = talloc_strdup(mem_ctx, "\\");
4501 if (!dos_fname) {
4502 return NT_STATUS_NO_MEMORY;
4504 } else {
4505 dos_fname = talloc_asprintf(mem_ctx,
4506 "\\%s",
4507 smb_fname->base_name);
4508 if (!dos_fname) {
4509 return NT_STATUS_NO_MEMORY;
4511 if (is_ntfs_stream_smb_fname(smb_fname)) {
4512 dos_fname = talloc_asprintf(dos_fname, "%s",
4513 smb_fname->stream_name);
4514 if (!dos_fname) {
4515 return NT_STATUS_NO_MEMORY;
4519 string_replace(dos_fname, '/', '\\');
4522 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4524 if (!fsp) {
4525 /* Do we have this path open ? */
4526 files_struct *fsp1;
4527 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4528 fsp1 = file_find_di_first(conn->sconn, fileid);
4529 if (fsp1 && fsp1->initial_allocation_size) {
4530 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4534 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4535 file_size = get_file_size_stat(psbuf);
4538 if (fsp) {
4539 pos = fsp->fh->position_information;
4542 if (fsp) {
4543 access_mask = fsp->access_mask;
4544 } else {
4545 /* GENERIC_EXECUTE mapping from Windows */
4546 access_mask = 0x12019F;
4549 /* This should be an index number - looks like
4550 dev/ino to me :-)
4552 I think this causes us to fail the IFSKIT
4553 BasicFileInformationTest. -tpot */
4554 file_index = get_FileIndex(conn, psbuf);
4556 switch (info_level) {
4557 case SMB_INFO_STANDARD:
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4559 data_size = 22;
4560 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4561 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4562 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4563 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4564 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4565 SSVAL(pdata,l1_attrFile,mode);
4566 break;
4568 case SMB_INFO_QUERY_EA_SIZE:
4570 unsigned int ea_size =
4571 estimate_ea_size(conn, fsp,
4572 smb_fname);
4573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4574 data_size = 26;
4575 srv_put_dos_date2(pdata,0,create_time);
4576 srv_put_dos_date2(pdata,4,atime);
4577 srv_put_dos_date2(pdata,8,mtime); /* write time */
4578 SIVAL(pdata,12,(uint32)file_size);
4579 SIVAL(pdata,16,(uint32)allocation_size);
4580 SSVAL(pdata,20,mode);
4581 SIVAL(pdata,22,ea_size);
4582 break;
4585 case SMB_INFO_IS_NAME_VALID:
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4587 if (fsp) {
4588 /* os/2 needs this ? really ?*/
4589 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4591 /* This is only reached for qpathinfo */
4592 data_size = 0;
4593 break;
4595 case SMB_INFO_QUERY_EAS_FROM_LIST:
4597 size_t total_ea_len = 0;
4598 struct ea_list *ea_file_list = NULL;
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4601 status =
4602 get_ea_list_from_file(mem_ctx, conn, fsp,
4603 smb_fname,
4604 &total_ea_len, &ea_file_list);
4605 if (!NT_STATUS_IS_OK(status)) {
4606 return status;
4609 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4611 if (!ea_list || (total_ea_len > data_size)) {
4612 data_size = 4;
4613 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4614 break;
4617 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4618 break;
4621 case SMB_INFO_QUERY_ALL_EAS:
4623 /* We have data_size bytes to put EA's into. */
4624 size_t total_ea_len = 0;
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4627 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4628 smb_fname,
4629 &total_ea_len, &ea_list);
4630 if (!NT_STATUS_IS_OK(status)) {
4631 return status;
4634 if (!ea_list || (total_ea_len > data_size)) {
4635 data_size = 4;
4636 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4637 break;
4640 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4641 break;
4644 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4646 /* This is FileFullEaInformation - 0xF which maps to
4647 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4649 /* We have data_size bytes to put EA's into. */
4650 size_t total_ea_len = 0;
4651 struct ea_list *ea_file_list = NULL;
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4655 /*TODO: add filtering and index handling */
4657 status =
4658 get_ea_list_from_file(mem_ctx, conn, fsp,
4659 smb_fname,
4660 &total_ea_len, &ea_file_list);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 return status;
4664 if (!ea_file_list) {
4665 return NT_STATUS_NO_EAS_ON_FILE;
4668 status = fill_ea_chained_buffer(mem_ctx,
4669 pdata,
4670 data_size,
4671 &data_size,
4672 conn, ea_file_list);
4673 if (!NT_STATUS_IS_OK(status)) {
4674 return status;
4676 break;
4679 case SMB_FILE_BASIC_INFORMATION:
4680 case SMB_QUERY_FILE_BASIC_INFO:
4682 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4684 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4685 } else {
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4687 data_size = 40;
4688 SIVAL(pdata,36,0);
4690 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4691 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4692 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4693 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4694 SIVAL(pdata,32,mode);
4696 DEBUG(5,("SMB_QFBI - "));
4697 DEBUG(5,("create: %s ", ctime(&create_time)));
4698 DEBUG(5,("access: %s ", ctime(&atime)));
4699 DEBUG(5,("write: %s ", ctime(&mtime)));
4700 DEBUG(5,("change: %s ", ctime(&c_time)));
4701 DEBUG(5,("mode: %x\n", mode));
4702 break;
4704 case SMB_FILE_STANDARD_INFORMATION:
4705 case SMB_QUERY_FILE_STANDARD_INFO:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4708 data_size = 24;
4709 SOFF_T(pdata,0,allocation_size);
4710 SOFF_T(pdata,8,file_size);
4711 SIVAL(pdata,16,nlink);
4712 SCVAL(pdata,20,delete_pending?1:0);
4713 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4714 SSVAL(pdata,22,0); /* Padding. */
4715 break;
4717 case SMB_FILE_EA_INFORMATION:
4718 case SMB_QUERY_FILE_EA_INFO:
4720 unsigned int ea_size =
4721 estimate_ea_size(conn, fsp, smb_fname);
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4723 data_size = 4;
4724 SIVAL(pdata,0,ea_size);
4725 break;
4728 /* Get the 8.3 name - used if NT SMB was negotiated. */
4729 case SMB_QUERY_FILE_ALT_NAME_INFO:
4730 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4732 int len;
4733 char mangled_name[13];
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4735 if (!name_to_8_3(base_name,mangled_name,
4736 True,conn->params)) {
4737 return NT_STATUS_NO_MEMORY;
4739 len = srvstr_push(dstart, flags2,
4740 pdata+4, mangled_name,
4741 PTR_DIFF(dend, pdata+4),
4742 STR_UNICODE);
4743 data_size = 4 + len;
4744 SIVAL(pdata,0,len);
4745 break;
4748 case SMB_QUERY_FILE_NAME_INFO:
4750 int len;
4752 this must be *exactly* right for ACLs on mapped drives to work
4754 len = srvstr_push(dstart, flags2,
4755 pdata+4, dos_fname,
4756 PTR_DIFF(dend, pdata+4),
4757 STR_UNICODE);
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4759 data_size = 4 + len;
4760 SIVAL(pdata,0,len);
4761 break;
4764 case SMB_FILE_ALLOCATION_INFORMATION:
4765 case SMB_QUERY_FILE_ALLOCATION_INFO:
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4767 data_size = 8;
4768 SOFF_T(pdata,0,allocation_size);
4769 break;
4771 case SMB_FILE_END_OF_FILE_INFORMATION:
4772 case SMB_QUERY_FILE_END_OF_FILEINFO:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4774 data_size = 8;
4775 SOFF_T(pdata,0,file_size);
4776 break;
4778 case SMB_QUERY_FILE_ALL_INFO:
4779 case SMB_FILE_ALL_INFORMATION:
4781 int len;
4782 unsigned int ea_size =
4783 estimate_ea_size(conn, fsp, smb_fname);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4786 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4787 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4788 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4789 SIVAL(pdata,32,mode);
4790 SIVAL(pdata,36,0); /* padding. */
4791 pdata += 40;
4792 SOFF_T(pdata,0,allocation_size);
4793 SOFF_T(pdata,8,file_size);
4794 SIVAL(pdata,16,nlink);
4795 SCVAL(pdata,20,delete_pending);
4796 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4797 SSVAL(pdata,22,0);
4798 pdata += 24;
4799 SIVAL(pdata,0,ea_size);
4800 pdata += 4; /* EA info */
4801 len = srvstr_push(dstart, flags2,
4802 pdata+4, dos_fname,
4803 PTR_DIFF(dend, pdata+4),
4804 STR_UNICODE);
4805 SIVAL(pdata,0,len);
4806 pdata += 4 + len;
4807 data_size = PTR_DIFF(pdata,(*ppdata));
4808 break;
4811 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4813 int len;
4814 unsigned int ea_size =
4815 estimate_ea_size(conn, fsp, smb_fname);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4817 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4818 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4819 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4820 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4821 SIVAL(pdata, 0x20, mode);
4822 SIVAL(pdata, 0x24, 0); /* padding. */
4823 SBVAL(pdata, 0x28, allocation_size);
4824 SBVAL(pdata, 0x30, file_size);
4825 SIVAL(pdata, 0x38, nlink);
4826 SCVAL(pdata, 0x3C, delete_pending);
4827 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4828 SSVAL(pdata, 0x3E, 0); /* padding */
4829 SBVAL(pdata, 0x40, file_index);
4830 SIVAL(pdata, 0x48, ea_size);
4831 SIVAL(pdata, 0x4C, access_mask);
4832 SBVAL(pdata, 0x50, pos);
4833 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4834 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4836 pdata += 0x60;
4838 len = srvstr_push(dstart, flags2,
4839 pdata+4, dos_fname,
4840 PTR_DIFF(dend, pdata+4),
4841 STR_UNICODE);
4842 SIVAL(pdata,0,len);
4843 pdata += 4 + len;
4844 data_size = PTR_DIFF(pdata,(*ppdata));
4845 break;
4847 case SMB_FILE_INTERNAL_INFORMATION:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4850 SBVAL(pdata, 0, file_index);
4851 data_size = 8;
4852 break;
4854 case SMB_FILE_ACCESS_INFORMATION:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4856 SIVAL(pdata, 0, access_mask);
4857 data_size = 4;
4858 break;
4860 case SMB_FILE_NAME_INFORMATION:
4861 /* Pathname with leading '\'. */
4863 size_t byte_len;
4864 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4866 SIVAL(pdata,0,byte_len);
4867 data_size = 4 + byte_len;
4868 break;
4871 case SMB_FILE_DISPOSITION_INFORMATION:
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4873 data_size = 1;
4874 SCVAL(pdata,0,delete_pending);
4875 break;
4877 case SMB_FILE_POSITION_INFORMATION:
4878 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4879 data_size = 8;
4880 SOFF_T(pdata,0,pos);
4881 break;
4883 case SMB_FILE_MODE_INFORMATION:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4885 SIVAL(pdata,0,mode);
4886 data_size = 4;
4887 break;
4889 case SMB_FILE_ALIGNMENT_INFORMATION:
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4891 SIVAL(pdata,0,0); /* No alignment needed. */
4892 data_size = 4;
4893 break;
4896 * NT4 server just returns "invalid query" to this - if we try
4897 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4898 * want this. JRA.
4900 /* The first statement above is false - verified using Thursby
4901 * client against NT4 -- gcolley.
4903 case SMB_QUERY_FILE_STREAM_INFO:
4904 case SMB_FILE_STREAM_INFORMATION: {
4905 unsigned int num_streams = 0;
4906 struct stream_struct *streams = NULL;
4908 DEBUG(10,("smbd_do_qfilepathinfo: "
4909 "SMB_FILE_STREAM_INFORMATION\n"));
4911 if (is_ntfs_stream_smb_fname(smb_fname)) {
4912 return NT_STATUS_INVALID_PARAMETER;
4915 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4916 talloc_tos(), &num_streams, &streams);
4918 if (!NT_STATUS_IS_OK(status)) {
4919 DEBUG(10, ("could not get stream info: %s\n",
4920 nt_errstr(status)));
4921 return status;
4924 status = marshall_stream_info(num_streams, streams,
4925 pdata, max_data_bytes,
4926 &data_size);
4928 if (!NT_STATUS_IS_OK(status)) {
4929 DEBUG(10, ("marshall_stream_info failed: %s\n",
4930 nt_errstr(status)));
4931 TALLOC_FREE(streams);
4932 return status;
4935 TALLOC_FREE(streams);
4937 break;
4939 case SMB_QUERY_COMPRESSION_INFO:
4940 case SMB_FILE_COMPRESSION_INFORMATION:
4941 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4942 SOFF_T(pdata,0,file_size);
4943 SIVAL(pdata,8,0); /* ??? */
4944 SIVAL(pdata,12,0); /* ??? */
4945 data_size = 16;
4946 break;
4948 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4950 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4951 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4952 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4953 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4954 SOFF_T(pdata,32,allocation_size);
4955 SOFF_T(pdata,40,file_size);
4956 SIVAL(pdata,48,mode);
4957 SIVAL(pdata,52,0); /* ??? */
4958 data_size = 56;
4959 break;
4961 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4963 SIVAL(pdata,0,mode);
4964 SIVAL(pdata,4,0);
4965 data_size = 8;
4966 break;
4969 * CIFS UNIX Extensions.
4972 case SMB_QUERY_FILE_UNIX_BASIC:
4974 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4975 data_size = PTR_DIFF(pdata,(*ppdata));
4977 DEBUG(4,("smbd_do_qfilepathinfo: "
4978 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4979 dump_data(4, (uint8_t *)(*ppdata), data_size);
4981 break;
4983 case SMB_QUERY_FILE_UNIX_INFO2:
4985 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4986 data_size = PTR_DIFF(pdata,(*ppdata));
4989 int i;
4990 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4992 for (i=0; i<100; i++)
4993 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4994 DEBUG(4,("\n"));
4997 break;
4999 case SMB_QUERY_FILE_UNIX_LINK:
5001 int len;
5002 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5004 if (!buffer) {
5005 return NT_STATUS_NO_MEMORY;
5008 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5009 #ifdef S_ISLNK
5010 if(!S_ISLNK(psbuf->st_ex_mode)) {
5011 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5013 #else
5014 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5015 #endif
5016 len = SMB_VFS_READLINK(conn,
5017 smb_fname->base_name,
5018 buffer, PATH_MAX);
5019 if (len == -1) {
5020 return map_nt_error_from_unix(errno);
5022 buffer[len] = 0;
5023 len = srvstr_push(dstart, flags2,
5024 pdata, buffer,
5025 PTR_DIFF(dend, pdata),
5026 STR_TERMINATE);
5027 pdata += len;
5028 data_size = PTR_DIFF(pdata,(*ppdata));
5030 break;
5033 #if defined(HAVE_POSIX_ACLS)
5034 case SMB_QUERY_POSIX_ACL:
5036 SMB_ACL_T file_acl = NULL;
5037 SMB_ACL_T def_acl = NULL;
5038 uint16 num_file_acls = 0;
5039 uint16 num_def_acls = 0;
5041 if (fsp && fsp->fh->fd != -1) {
5042 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5043 talloc_tos());
5044 } else {
5045 file_acl =
5046 SMB_VFS_SYS_ACL_GET_FILE(conn,
5047 smb_fname->base_name,
5048 SMB_ACL_TYPE_ACCESS,
5049 talloc_tos());
5052 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5053 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5054 "not implemented on "
5055 "filesystem containing %s\n",
5056 smb_fname->base_name));
5057 return NT_STATUS_NOT_IMPLEMENTED;
5060 if (S_ISDIR(psbuf->st_ex_mode)) {
5061 if (fsp && fsp->is_directory) {
5062 def_acl =
5063 SMB_VFS_SYS_ACL_GET_FILE(
5064 conn,
5065 fsp->fsp_name->base_name,
5066 SMB_ACL_TYPE_DEFAULT,
5067 talloc_tos());
5068 } else {
5069 def_acl =
5070 SMB_VFS_SYS_ACL_GET_FILE(
5071 conn,
5072 smb_fname->base_name,
5073 SMB_ACL_TYPE_DEFAULT,
5074 talloc_tos());
5076 def_acl = free_empty_sys_acl(conn, def_acl);
5079 num_file_acls = count_acl_entries(conn, file_acl);
5080 num_def_acls = count_acl_entries(conn, def_acl);
5082 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5083 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5084 data_size,
5085 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5086 SMB_POSIX_ACL_HEADER_SIZE) ));
5087 if (file_acl) {
5088 TALLOC_FREE(file_acl);
5090 if (def_acl) {
5091 TALLOC_FREE(def_acl);
5093 return NT_STATUS_BUFFER_TOO_SMALL;
5096 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5097 SSVAL(pdata,2,num_file_acls);
5098 SSVAL(pdata,4,num_def_acls);
5099 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5100 if (file_acl) {
5101 TALLOC_FREE(file_acl);
5103 if (def_acl) {
5104 TALLOC_FREE(def_acl);
5106 return NT_STATUS_INTERNAL_ERROR;
5108 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5109 if (file_acl) {
5110 TALLOC_FREE(file_acl);
5112 if (def_acl) {
5113 TALLOC_FREE(def_acl);
5115 return NT_STATUS_INTERNAL_ERROR;
5118 if (file_acl) {
5119 TALLOC_FREE(file_acl);
5121 if (def_acl) {
5122 TALLOC_FREE(def_acl);
5124 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5125 break;
5127 #endif
5130 case SMB_QUERY_POSIX_LOCK:
5132 uint64_t count;
5133 uint64_t offset;
5134 uint64_t smblctx;
5135 enum brl_type lock_type;
5137 /* We need an open file with a real fd for this. */
5138 if (!fsp || fsp->fh->fd == -1) {
5139 return NT_STATUS_INVALID_LEVEL;
5142 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5143 return NT_STATUS_INVALID_PARAMETER;
5146 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5147 case POSIX_LOCK_TYPE_READ:
5148 lock_type = READ_LOCK;
5149 break;
5150 case POSIX_LOCK_TYPE_WRITE:
5151 lock_type = WRITE_LOCK;
5152 break;
5153 case POSIX_LOCK_TYPE_UNLOCK:
5154 default:
5155 /* There's no point in asking for an unlock... */
5156 return NT_STATUS_INVALID_PARAMETER;
5159 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5160 #if defined(HAVE_LONGLONG)
5161 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5162 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5163 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5164 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5165 #else /* HAVE_LONGLONG */
5166 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5167 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5168 #endif /* HAVE_LONGLONG */
5170 status = query_lock(fsp,
5171 &smblctx,
5172 &count,
5173 &offset,
5174 &lock_type,
5175 POSIX_LOCK);
5177 if (ERROR_WAS_LOCK_DENIED(status)) {
5178 /* Here we need to report who has it locked... */
5179 data_size = POSIX_LOCK_DATA_SIZE;
5181 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5182 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5183 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5184 #if defined(HAVE_LONGLONG)
5185 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5186 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5187 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5188 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5189 #else /* HAVE_LONGLONG */
5190 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5191 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5192 #endif /* HAVE_LONGLONG */
5194 } else if (NT_STATUS_IS_OK(status)) {
5195 /* For success we just return a copy of what we sent
5196 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5197 data_size = POSIX_LOCK_DATA_SIZE;
5198 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5199 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5200 } else {
5201 return status;
5203 break;
5206 default:
5207 return NT_STATUS_INVALID_LEVEL;
5210 *pdata_size = data_size;
5211 return NT_STATUS_OK;
5214 /****************************************************************************
5215 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5216 file name or file id).
5217 ****************************************************************************/
5219 static void call_trans2qfilepathinfo(connection_struct *conn,
5220 struct smb_request *req,
5221 unsigned int tran_call,
5222 char **pparams, int total_params,
5223 char **ppdata, int total_data,
5224 unsigned int max_data_bytes)
5226 char *params = *pparams;
5227 char *pdata = *ppdata;
5228 uint16 info_level;
5229 unsigned int data_size = 0;
5230 unsigned int param_size = 2;
5231 struct smb_filename *smb_fname = NULL;
5232 bool delete_pending = False;
5233 struct timespec write_time_ts;
5234 files_struct *fsp = NULL;
5235 struct file_id fileid;
5236 struct ea_list *ea_list = NULL;
5237 int lock_data_count = 0;
5238 char *lock_data = NULL;
5239 NTSTATUS status = NT_STATUS_OK;
5241 if (!params) {
5242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5243 return;
5246 ZERO_STRUCT(write_time_ts);
5248 if (tran_call == TRANSACT2_QFILEINFO) {
5249 if (total_params < 4) {
5250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5251 return;
5254 if (IS_IPC(conn)) {
5255 call_trans2qpipeinfo(conn, req, tran_call,
5256 pparams, total_params,
5257 ppdata, total_data,
5258 max_data_bytes);
5259 return;
5262 fsp = file_fsp(req, SVAL(params,0));
5263 info_level = SVAL(params,2);
5265 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5267 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5269 return;
5272 /* Initial check for valid fsp ptr. */
5273 if (!check_fsp_open(conn, req, fsp)) {
5274 return;
5277 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5278 &smb_fname);
5279 if (!NT_STATUS_IS_OK(status)) {
5280 reply_nterror(req, status);
5281 return;
5284 if(fsp->fake_file_handle) {
5286 * This is actually for the QUOTA_FAKE_FILE --metze
5289 /* We know this name is ok, it's already passed the checks. */
5291 } else if(fsp->fh->fd == -1) {
5293 * This is actually a QFILEINFO on a directory
5294 * handle (returned from an NT SMB). NT5.0 seems
5295 * to do this call. JRA.
5298 if (INFO_LEVEL_IS_UNIX(info_level)) {
5299 /* Always do lstat for UNIX calls. */
5300 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5301 DEBUG(3,("call_trans2qfilepathinfo: "
5302 "SMB_VFS_LSTAT of %s failed "
5303 "(%s)\n",
5304 smb_fname_str_dbg(smb_fname),
5305 strerror(errno)));
5306 reply_nterror(req,
5307 map_nt_error_from_unix(errno));
5308 return;
5310 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "SMB_VFS_STAT of %s failed (%s)\n",
5313 smb_fname_str_dbg(smb_fname),
5314 strerror(errno)));
5315 reply_nterror(req,
5316 map_nt_error_from_unix(errno));
5317 return;
5320 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5321 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5322 } else {
5324 * Original code - this is an open file.
5326 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5327 DEBUG(3, ("fstat of %s failed (%s)\n",
5328 fsp_fnum_dbg(fsp), strerror(errno)));
5329 reply_nterror(req,
5330 map_nt_error_from_unix(errno));
5331 return;
5333 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5334 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5337 } else {
5338 uint32_t name_hash;
5339 char *fname = NULL;
5340 uint32_t ucf_flags = 0;
5342 /* qpathinfo */
5343 if (total_params < 7) {
5344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5345 return;
5348 info_level = SVAL(params,0);
5350 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5352 if (INFO_LEVEL_IS_UNIX(info_level)) {
5353 if (!lp_unix_extensions()) {
5354 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5355 return;
5357 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5358 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5359 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5360 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5364 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5365 total_params - 6,
5366 STR_TERMINATE, &status);
5367 if (!NT_STATUS_IS_OK(status)) {
5368 reply_nterror(req, status);
5369 return;
5372 status = filename_convert(req,
5373 conn,
5374 req->flags2 & FLAGS2_DFS_PATHNAMES,
5375 fname,
5376 ucf_flags,
5377 NULL,
5378 &smb_fname);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5381 reply_botherror(req,
5382 NT_STATUS_PATH_NOT_COVERED,
5383 ERRSRV, ERRbadpath);
5384 return;
5386 reply_nterror(req, status);
5387 return;
5390 /* If this is a stream, check if there is a delete_pending. */
5391 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5392 && is_ntfs_stream_smb_fname(smb_fname)) {
5393 struct smb_filename *smb_fname_base = NULL;
5395 /* Create an smb_filename with stream_name == NULL. */
5396 status =
5397 create_synthetic_smb_fname(talloc_tos(),
5398 smb_fname->base_name,
5399 NULL, NULL,
5400 &smb_fname_base);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 reply_nterror(req, status);
5403 return;
5406 if (INFO_LEVEL_IS_UNIX(info_level)) {
5407 /* Always do lstat for UNIX calls. */
5408 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5409 DEBUG(3,("call_trans2qfilepathinfo: "
5410 "SMB_VFS_LSTAT of %s failed "
5411 "(%s)\n",
5412 smb_fname_str_dbg(smb_fname_base),
5413 strerror(errno)));
5414 TALLOC_FREE(smb_fname_base);
5415 reply_nterror(req,
5416 map_nt_error_from_unix(errno));
5417 return;
5419 } else {
5420 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5421 DEBUG(3,("call_trans2qfilepathinfo: "
5422 "fileinfo of %s failed "
5423 "(%s)\n",
5424 smb_fname_str_dbg(smb_fname_base),
5425 strerror(errno)));
5426 TALLOC_FREE(smb_fname_base);
5427 reply_nterror(req,
5428 map_nt_error_from_unix(errno));
5429 return;
5433 status = file_name_hash(conn,
5434 smb_fname_str_dbg(smb_fname_base),
5435 &name_hash);
5436 if (!NT_STATUS_IS_OK(status)) {
5437 TALLOC_FREE(smb_fname_base);
5438 reply_nterror(req, status);
5439 return;
5442 fileid = vfs_file_id_from_sbuf(conn,
5443 &smb_fname_base->st);
5444 TALLOC_FREE(smb_fname_base);
5445 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5446 if (delete_pending) {
5447 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5448 return;
5452 if (INFO_LEVEL_IS_UNIX(info_level)) {
5453 /* Always do lstat for UNIX calls. */
5454 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5455 DEBUG(3,("call_trans2qfilepathinfo: "
5456 "SMB_VFS_LSTAT of %s failed (%s)\n",
5457 smb_fname_str_dbg(smb_fname),
5458 strerror(errno)));
5459 reply_nterror(req,
5460 map_nt_error_from_unix(errno));
5461 return;
5464 } else {
5465 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5466 DEBUG(3,("call_trans2qfilepathinfo: "
5467 "SMB_VFS_STAT of %s failed (%s)\n",
5468 smb_fname_str_dbg(smb_fname),
5469 strerror(errno)));
5470 reply_nterror(req,
5471 map_nt_error_from_unix(errno));
5472 return;
5476 status = file_name_hash(conn,
5477 smb_fname_str_dbg(smb_fname),
5478 &name_hash);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 reply_nterror(req, status);
5481 return;
5484 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5485 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5486 if (delete_pending) {
5487 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5488 return;
5492 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5493 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5494 fsp_fnum_dbg(fsp),
5495 info_level,tran_call,total_data));
5497 /* Pull out any data sent here before we realloc. */
5498 switch (info_level) {
5499 case SMB_INFO_QUERY_EAS_FROM_LIST:
5501 /* Pull any EA list from the data portion. */
5502 uint32 ea_size;
5504 if (total_data < 4) {
5505 reply_nterror(
5506 req, NT_STATUS_INVALID_PARAMETER);
5507 return;
5509 ea_size = IVAL(pdata,0);
5511 if (total_data > 0 && ea_size != total_data) {
5512 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5513 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5514 reply_nterror(
5515 req, NT_STATUS_INVALID_PARAMETER);
5516 return;
5519 if (!lp_ea_support(SNUM(conn))) {
5520 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5521 return;
5524 /* Pull out the list of names. */
5525 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5526 if (!ea_list) {
5527 reply_nterror(
5528 req, NT_STATUS_INVALID_PARAMETER);
5529 return;
5531 break;
5534 case SMB_QUERY_POSIX_LOCK:
5536 if (fsp == NULL || fsp->fh->fd == -1) {
5537 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5538 return;
5541 if (total_data != POSIX_LOCK_DATA_SIZE) {
5542 reply_nterror(
5543 req, NT_STATUS_INVALID_PARAMETER);
5544 return;
5547 /* Copy the lock range data. */
5548 lock_data = (char *)talloc_memdup(
5549 req, pdata, total_data);
5550 if (!lock_data) {
5551 reply_nterror(req, NT_STATUS_NO_MEMORY);
5552 return;
5554 lock_data_count = total_data;
5556 default:
5557 break;
5560 *pparams = (char *)SMB_REALLOC(*pparams,2);
5561 if (*pparams == NULL) {
5562 reply_nterror(req, NT_STATUS_NO_MEMORY);
5563 return;
5565 params = *pparams;
5566 SSVAL(params,0,0);
5569 * draft-leach-cifs-v1-spec-02.txt
5570 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5571 * says:
5573 * The requested information is placed in the Data portion of the
5574 * transaction response. For the information levels greater than 0x100,
5575 * the transaction response has 1 parameter word which should be
5576 * ignored by the client.
5578 * However Windows only follows this rule for the IS_NAME_VALID call.
5580 switch (info_level) {
5581 case SMB_INFO_IS_NAME_VALID:
5582 param_size = 0;
5583 break;
5586 if ((info_level & 0xFF00) == 0xFF00) {
5588 * We use levels that start with 0xFF00
5589 * internally to represent SMB2 specific levels
5591 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5592 return;
5595 status = smbd_do_qfilepathinfo(conn, req, info_level,
5596 fsp, smb_fname,
5597 delete_pending, write_time_ts,
5598 ea_list,
5599 lock_data_count, lock_data,
5600 req->flags2, max_data_bytes,
5601 ppdata, &data_size);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 reply_nterror(req, status);
5604 return;
5607 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5608 max_data_bytes);
5610 return;
5613 /****************************************************************************
5614 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5615 code.
5616 ****************************************************************************/
5618 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5619 connection_struct *conn,
5620 struct smb_request *req,
5621 bool overwrite_if_exists,
5622 const struct smb_filename *smb_fname_old,
5623 struct smb_filename *smb_fname_new)
5625 NTSTATUS status = NT_STATUS_OK;
5627 /* source must already exist. */
5628 if (!VALID_STAT(smb_fname_old->st)) {
5629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5632 if (VALID_STAT(smb_fname_new->st)) {
5633 if (overwrite_if_exists) {
5634 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5635 return NT_STATUS_FILE_IS_A_DIRECTORY;
5637 status = unlink_internals(conn,
5638 req,
5639 FILE_ATTRIBUTE_NORMAL,
5640 smb_fname_new,
5641 false);
5642 if (!NT_STATUS_IS_OK(status)) {
5643 return status;
5645 } else {
5646 /* Disallow if newname already exists. */
5647 return NT_STATUS_OBJECT_NAME_COLLISION;
5651 /* No links from a directory. */
5652 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5653 return NT_STATUS_FILE_IS_A_DIRECTORY;
5656 /* Setting a hardlink to/from a stream isn't currently supported. */
5657 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5658 is_ntfs_stream_smb_fname(smb_fname_new)) {
5659 return NT_STATUS_INVALID_PARAMETER;
5662 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5663 smb_fname_old->base_name, smb_fname_new->base_name));
5665 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5666 smb_fname_new->base_name) != 0) {
5667 status = map_nt_error_from_unix(errno);
5668 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5669 nt_errstr(status), smb_fname_old->base_name,
5670 smb_fname_new->base_name));
5672 return status;
5675 /****************************************************************************
5676 Deal with setting the time from any of the setfilepathinfo functions.
5677 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5678 calling this function.
5679 ****************************************************************************/
5681 NTSTATUS smb_set_file_time(connection_struct *conn,
5682 files_struct *fsp,
5683 const struct smb_filename *smb_fname,
5684 struct smb_file_time *ft,
5685 bool setting_write_time)
5687 struct smb_filename smb_fname_base;
5688 uint32 action =
5689 FILE_NOTIFY_CHANGE_LAST_ACCESS
5690 |FILE_NOTIFY_CHANGE_LAST_WRITE
5691 |FILE_NOTIFY_CHANGE_CREATION;
5693 if (!VALID_STAT(smb_fname->st)) {
5694 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5697 /* get some defaults (no modifications) if any info is zero or -1. */
5698 if (null_timespec(ft->create_time)) {
5699 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5702 if (null_timespec(ft->atime)) {
5703 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5706 if (null_timespec(ft->mtime)) {
5707 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5710 if (!setting_write_time) {
5711 /* ft->mtime comes from change time, not write time. */
5712 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5715 /* Ensure the resolution is the correct for
5716 * what we can store on this filesystem. */
5718 round_timespec(conn->ts_res, &ft->create_time);
5719 round_timespec(conn->ts_res, &ft->ctime);
5720 round_timespec(conn->ts_res, &ft->atime);
5721 round_timespec(conn->ts_res, &ft->mtime);
5723 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5724 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5725 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5726 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5727 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5728 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5729 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5730 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5732 if (setting_write_time) {
5734 * This was a Windows setfileinfo on an open file.
5735 * NT does this a lot. We also need to
5736 * set the time here, as it can be read by
5737 * FindFirst/FindNext and with the patch for bug #2045
5738 * in smbd/fileio.c it ensures that this timestamp is
5739 * kept sticky even after a write. We save the request
5740 * away and will set it on file close and after a write. JRA.
5743 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5744 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5746 if (fsp != NULL) {
5747 if (fsp->base_fsp) {
5748 set_sticky_write_time_fsp(fsp->base_fsp,
5749 ft->mtime);
5750 } else {
5751 set_sticky_write_time_fsp(fsp, ft->mtime);
5753 } else {
5754 set_sticky_write_time_path(
5755 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5756 ft->mtime);
5760 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5762 /* Always call ntimes on the base, even if a stream was passed in. */
5763 smb_fname_base = *smb_fname;
5764 smb_fname_base.stream_name = NULL;
5766 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5767 return map_nt_error_from_unix(errno);
5770 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5771 smb_fname->base_name);
5772 return NT_STATUS_OK;
5775 /****************************************************************************
5776 Deal with setting the dosmode from any of the setfilepathinfo functions.
5777 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5778 done before calling this function.
5779 ****************************************************************************/
5781 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5782 const struct smb_filename *smb_fname,
5783 uint32 dosmode)
5785 struct smb_filename *smb_fname_base = NULL;
5786 NTSTATUS status;
5788 if (!VALID_STAT(smb_fname->st)) {
5789 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5792 /* Always operate on the base_name, even if a stream was passed in. */
5793 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5794 NULL, &smb_fname->st,
5795 &smb_fname_base);
5796 if (!NT_STATUS_IS_OK(status)) {
5797 return status;
5800 if (dosmode) {
5801 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5802 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5803 } else {
5804 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5808 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5810 /* check the mode isn't different, before changing it */
5811 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5812 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5813 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5814 (unsigned int)dosmode));
5816 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5817 false)) {
5818 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5819 "%s failed (%s)\n",
5820 smb_fname_str_dbg(smb_fname_base),
5821 strerror(errno)));
5822 status = map_nt_error_from_unix(errno);
5823 goto out;
5826 status = NT_STATUS_OK;
5827 out:
5828 TALLOC_FREE(smb_fname_base);
5829 return status;
5832 /****************************************************************************
5833 Deal with setting the size from any of the setfilepathinfo functions.
5834 ****************************************************************************/
5836 static NTSTATUS smb_set_file_size(connection_struct *conn,
5837 struct smb_request *req,
5838 files_struct *fsp,
5839 const struct smb_filename *smb_fname,
5840 const SMB_STRUCT_STAT *psbuf,
5841 off_t size,
5842 bool fail_after_createfile)
5844 NTSTATUS status = NT_STATUS_OK;
5845 struct smb_filename *smb_fname_tmp = NULL;
5846 files_struct *new_fsp = NULL;
5848 if (!VALID_STAT(*psbuf)) {
5849 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5852 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5854 if (size == get_file_size_stat(psbuf)) {
5855 return NT_STATUS_OK;
5858 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5859 smb_fname_str_dbg(smb_fname), (double)size));
5861 if (fsp && fsp->fh->fd != -1) {
5862 /* Handle based call. */
5863 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5864 return NT_STATUS_ACCESS_DENIED;
5867 if (vfs_set_filelen(fsp, size) == -1) {
5868 return map_nt_error_from_unix(errno);
5870 trigger_write_time_update_immediate(fsp);
5871 return NT_STATUS_OK;
5874 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5875 if (!NT_STATUS_IS_OK(status)) {
5876 return status;
5879 smb_fname_tmp->st = *psbuf;
5881 status = SMB_VFS_CREATE_FILE(
5882 conn, /* conn */
5883 req, /* req */
5884 0, /* root_dir_fid */
5885 smb_fname_tmp, /* fname */
5886 FILE_WRITE_DATA, /* access_mask */
5887 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5888 FILE_SHARE_DELETE),
5889 FILE_OPEN, /* create_disposition*/
5890 0, /* create_options */
5891 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5892 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5893 0, /* allocation_size */
5894 0, /* private_flags */
5895 NULL, /* sd */
5896 NULL, /* ea_list */
5897 &new_fsp, /* result */
5898 NULL); /* pinfo */
5900 TALLOC_FREE(smb_fname_tmp);
5902 if (!NT_STATUS_IS_OK(status)) {
5903 /* NB. We check for open_was_deferred in the caller. */
5904 return status;
5907 /* See RAW-SFILEINFO-END-OF-FILE */
5908 if (fail_after_createfile) {
5909 close_file(req, new_fsp,NORMAL_CLOSE);
5910 return NT_STATUS_INVALID_LEVEL;
5913 if (vfs_set_filelen(new_fsp, size) == -1) {
5914 status = map_nt_error_from_unix(errno);
5915 close_file(req, new_fsp,NORMAL_CLOSE);
5916 return status;
5919 trigger_write_time_update_immediate(new_fsp);
5920 close_file(req, new_fsp,NORMAL_CLOSE);
5921 return NT_STATUS_OK;
5924 /****************************************************************************
5925 Deal with SMB_INFO_SET_EA.
5926 ****************************************************************************/
5928 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5929 const char *pdata,
5930 int total_data,
5931 files_struct *fsp,
5932 const struct smb_filename *smb_fname)
5934 struct ea_list *ea_list = NULL;
5935 TALLOC_CTX *ctx = NULL;
5936 NTSTATUS status = NT_STATUS_OK;
5938 if (total_data < 10) {
5940 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5941 length. They seem to have no effect. Bug #3212. JRA */
5943 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5944 /* We're done. We only get EA info in this call. */
5945 return NT_STATUS_OK;
5948 return NT_STATUS_INVALID_PARAMETER;
5951 if (IVAL(pdata,0) > total_data) {
5952 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5953 IVAL(pdata,0), (unsigned int)total_data));
5954 return NT_STATUS_INVALID_PARAMETER;
5957 ctx = talloc_tos();
5958 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5959 if (!ea_list) {
5960 return NT_STATUS_INVALID_PARAMETER;
5963 status = set_ea(conn, fsp, smb_fname, ea_list);
5965 return status;
5968 /****************************************************************************
5969 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5970 ****************************************************************************/
5972 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5973 const char *pdata,
5974 int total_data,
5975 files_struct *fsp)
5977 struct ea_list *ea_list = NULL;
5978 NTSTATUS status;
5980 if (!fsp) {
5981 return NT_STATUS_INVALID_HANDLE;
5984 if (!lp_ea_support(SNUM(conn))) {
5985 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5986 "EA's not supported.\n",
5987 (unsigned int)total_data));
5988 return NT_STATUS_EAS_NOT_SUPPORTED;
5991 if (total_data < 10) {
5992 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5993 "too small.\n",
5994 (unsigned int)total_data));
5995 return NT_STATUS_INVALID_PARAMETER;
5998 ea_list = read_nttrans_ea_list(talloc_tos(),
5999 pdata,
6000 total_data);
6002 if (!ea_list) {
6003 return NT_STATUS_INVALID_PARAMETER;
6006 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6008 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6009 smb_fname_str_dbg(fsp->fsp_name),
6010 nt_errstr(status) ));
6012 return status;
6016 /****************************************************************************
6017 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6018 ****************************************************************************/
6020 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6021 const char *pdata,
6022 int total_data,
6023 files_struct *fsp,
6024 struct smb_filename *smb_fname)
6026 NTSTATUS status = NT_STATUS_OK;
6027 bool delete_on_close;
6028 uint32 dosmode = 0;
6030 if (total_data < 1) {
6031 return NT_STATUS_INVALID_PARAMETER;
6034 if (fsp == NULL) {
6035 return NT_STATUS_INVALID_HANDLE;
6038 delete_on_close = (CVAL(pdata,0) ? True : False);
6039 dosmode = dos_mode(conn, smb_fname);
6041 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6042 "delete_on_close = %u\n",
6043 smb_fname_str_dbg(smb_fname),
6044 (unsigned int)dosmode,
6045 (unsigned int)delete_on_close ));
6047 if (delete_on_close) {
6048 status = can_set_delete_on_close(fsp, dosmode);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 return status;
6054 /* The set is across all open files on this dev/inode pair. */
6055 if (!set_delete_on_close(fsp, delete_on_close,
6056 conn->session_info->security_token,
6057 conn->session_info->unix_token)) {
6058 return NT_STATUS_ACCESS_DENIED;
6060 return NT_STATUS_OK;
6063 /****************************************************************************
6064 Deal with SMB_FILE_POSITION_INFORMATION.
6065 ****************************************************************************/
6067 static NTSTATUS smb_file_position_information(connection_struct *conn,
6068 const char *pdata,
6069 int total_data,
6070 files_struct *fsp)
6072 uint64_t position_information;
6074 if (total_data < 8) {
6075 return NT_STATUS_INVALID_PARAMETER;
6078 if (fsp == NULL) {
6079 /* Ignore on pathname based set. */
6080 return NT_STATUS_OK;
6083 position_information = (uint64_t)IVAL(pdata,0);
6084 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6086 DEBUG(10,("smb_file_position_information: Set file position "
6087 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6088 (double)position_information));
6089 fsp->fh->position_information = position_information;
6090 return NT_STATUS_OK;
6093 /****************************************************************************
6094 Deal with SMB_FILE_MODE_INFORMATION.
6095 ****************************************************************************/
6097 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6098 const char *pdata,
6099 int total_data)
6101 uint32 mode;
6103 if (total_data < 4) {
6104 return NT_STATUS_INVALID_PARAMETER;
6106 mode = IVAL(pdata,0);
6107 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6108 return NT_STATUS_INVALID_PARAMETER;
6110 return NT_STATUS_OK;
6113 /****************************************************************************
6114 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6115 ****************************************************************************/
6117 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6118 struct smb_request *req,
6119 const char *pdata,
6120 int total_data,
6121 const struct smb_filename *smb_fname)
6123 char *link_target = NULL;
6124 const char *newname = smb_fname->base_name;
6125 TALLOC_CTX *ctx = talloc_tos();
6127 /* Set a symbolic link. */
6128 /* Don't allow this if follow links is false. */
6130 if (total_data == 0) {
6131 return NT_STATUS_INVALID_PARAMETER;
6134 if (!lp_symlinks(SNUM(conn))) {
6135 return NT_STATUS_ACCESS_DENIED;
6138 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6139 total_data, STR_TERMINATE);
6141 if (!link_target) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6146 newname, link_target ));
6148 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6149 return map_nt_error_from_unix(errno);
6152 return NT_STATUS_OK;
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6157 ****************************************************************************/
6159 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6160 struct smb_request *req,
6161 const char *pdata, int total_data,
6162 struct smb_filename *smb_fname_new)
6164 char *oldname = NULL;
6165 struct smb_filename *smb_fname_old = NULL;
6166 TALLOC_CTX *ctx = talloc_tos();
6167 NTSTATUS status = NT_STATUS_OK;
6169 /* Set a hard link. */
6170 if (total_data == 0) {
6171 return NT_STATUS_INVALID_PARAMETER;
6174 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6175 total_data, STR_TERMINATE, &status);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 return status;
6180 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6181 smb_fname_str_dbg(smb_fname_new), oldname));
6183 status = filename_convert(ctx,
6184 conn,
6185 req->flags2 & FLAGS2_DFS_PATHNAMES,
6186 oldname,
6188 NULL,
6189 &smb_fname_old);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 return status;
6194 return hardlink_internals(ctx, conn, req, false,
6195 smb_fname_old, smb_fname_new);
6198 /****************************************************************************
6199 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6200 ****************************************************************************/
6202 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6203 struct smb_request *req,
6204 const char *pdata,
6205 int total_data,
6206 files_struct *fsp,
6207 struct smb_filename *smb_fname_src)
6209 bool overwrite;
6210 uint32_t len;
6211 char *newname = NULL;
6212 struct smb_filename *smb_fname_dst = NULL;
6213 NTSTATUS status = NT_STATUS_OK;
6214 TALLOC_CTX *ctx = talloc_tos();
6216 if (!fsp) {
6217 return NT_STATUS_INVALID_HANDLE;
6220 if (total_data < 20) {
6221 return NT_STATUS_INVALID_PARAMETER;
6224 overwrite = (CVAL(pdata,0) ? True : False);
6225 len = IVAL(pdata,16);
6227 if (len > (total_data - 20) || (len == 0)) {
6228 return NT_STATUS_INVALID_PARAMETER;
6231 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6232 &pdata[20], len, STR_TERMINATE,
6233 &status);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 return status;
6238 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6239 newname));
6241 status = filename_convert(ctx,
6242 conn,
6243 req->flags2 & FLAGS2_DFS_PATHNAMES,
6244 newname,
6245 UCF_SAVE_LCOMP,
6246 NULL,
6247 &smb_fname_dst);
6248 if (!NT_STATUS_IS_OK(status)) {
6249 return status;
6252 if (fsp->base_fsp) {
6253 /* newname must be a stream name. */
6254 if (newname[0] != ':') {
6255 return NT_STATUS_NOT_SUPPORTED;
6258 /* Create an smb_fname to call rename_internals_fsp() with. */
6259 status = create_synthetic_smb_fname(talloc_tos(),
6260 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6261 &smb_fname_dst);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 goto out;
6267 * Set the original last component, since
6268 * rename_internals_fsp() requires it.
6270 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6271 newname);
6272 if (smb_fname_dst->original_lcomp == NULL) {
6273 status = NT_STATUS_NO_MEMORY;
6274 goto out;
6279 DEBUG(10,("smb2_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6281 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6282 smb_fname_str_dbg(smb_fname_dst)));
6283 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6284 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6285 overwrite);
6287 out:
6288 TALLOC_FREE(smb_fname_dst);
6289 return status;
6292 static NTSTATUS smb_file_link_information(connection_struct *conn,
6293 struct smb_request *req,
6294 const char *pdata,
6295 int total_data,
6296 files_struct *fsp,
6297 struct smb_filename *smb_fname_src)
6299 bool overwrite;
6300 uint32_t len;
6301 char *newname = NULL;
6302 struct smb_filename *smb_fname_dst = NULL;
6303 NTSTATUS status = NT_STATUS_OK;
6304 TALLOC_CTX *ctx = talloc_tos();
6306 if (!fsp) {
6307 return NT_STATUS_INVALID_HANDLE;
6310 if (total_data < 20) {
6311 return NT_STATUS_INVALID_PARAMETER;
6314 overwrite = (CVAL(pdata,0) ? true : false);
6315 len = IVAL(pdata,16);
6317 if (len > (total_data - 20) || (len == 0)) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6322 &pdata[20], len, STR_TERMINATE,
6323 &status);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 return status;
6328 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6329 newname));
6331 status = filename_convert(ctx,
6332 conn,
6333 req->flags2 & FLAGS2_DFS_PATHNAMES,
6334 newname,
6335 UCF_SAVE_LCOMP,
6336 NULL,
6337 &smb_fname_dst);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 return status;
6342 if (fsp->base_fsp) {
6343 /* No stream names. */
6344 return NT_STATUS_NOT_SUPPORTED;
6347 DEBUG(10,("smb_file_link_information: "
6348 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6349 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6350 smb_fname_str_dbg(smb_fname_dst)));
6351 status = hardlink_internals(ctx,
6352 conn,
6353 req,
6354 overwrite,
6355 fsp->fsp_name,
6356 smb_fname_dst);
6358 TALLOC_FREE(smb_fname_dst);
6359 return status;
6362 /****************************************************************************
6363 Deal with SMB_FILE_RENAME_INFORMATION.
6364 ****************************************************************************/
6366 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6367 struct smb_request *req,
6368 const char *pdata,
6369 int total_data,
6370 files_struct *fsp,
6371 struct smb_filename *smb_fname_src)
6373 bool overwrite;
6374 uint32 root_fid;
6375 uint32 len;
6376 char *newname = NULL;
6377 struct smb_filename *smb_fname_dst = NULL;
6378 bool dest_has_wcard = False;
6379 NTSTATUS status = NT_STATUS_OK;
6380 char *p;
6381 TALLOC_CTX *ctx = talloc_tos();
6383 if (total_data < 13) {
6384 return NT_STATUS_INVALID_PARAMETER;
6387 overwrite = (CVAL(pdata,0) ? True : False);
6388 root_fid = IVAL(pdata,4);
6389 len = IVAL(pdata,8);
6391 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6392 return NT_STATUS_INVALID_PARAMETER;
6395 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6396 len, 0, &status,
6397 &dest_has_wcard);
6398 if (!NT_STATUS_IS_OK(status)) {
6399 return status;
6402 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6403 newname));
6405 status = resolve_dfspath_wcard(ctx, conn,
6406 req->flags2 & FLAGS2_DFS_PATHNAMES,
6407 newname,
6408 true,
6409 !conn->sconn->using_smb2,
6410 &newname,
6411 &dest_has_wcard);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 return status;
6416 /* Check the new name has no '/' characters. */
6417 if (strchr_m(newname, '/')) {
6418 return NT_STATUS_NOT_SUPPORTED;
6421 if (fsp && fsp->base_fsp) {
6422 /* newname must be a stream name. */
6423 if (newname[0] != ':') {
6424 return NT_STATUS_NOT_SUPPORTED;
6427 /* Create an smb_fname to call rename_internals_fsp() with. */
6428 status = create_synthetic_smb_fname(talloc_tos(),
6429 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6430 &smb_fname_dst);
6431 if (!NT_STATUS_IS_OK(status)) {
6432 goto out;
6436 * Set the original last component, since
6437 * rename_internals_fsp() requires it.
6439 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6440 newname);
6441 if (smb_fname_dst->original_lcomp == NULL) {
6442 status = NT_STATUS_NO_MEMORY;
6443 goto out;
6446 } else {
6448 * Build up an smb_fname_dst based on the filename passed in.
6449 * We basically just strip off the last component, and put on
6450 * the newname instead.
6452 char *base_name = NULL;
6454 /* newname must *not* be a stream name. */
6455 if (newname[0] == ':') {
6456 return NT_STATUS_NOT_SUPPORTED;
6460 * Strip off the last component (filename) of the path passed
6461 * in.
6463 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6464 if (!base_name) {
6465 return NT_STATUS_NO_MEMORY;
6467 p = strrchr_m(base_name, '/');
6468 if (p) {
6469 p[1] = '\0';
6470 } else {
6471 base_name = talloc_strdup(ctx, "");
6472 if (!base_name) {
6473 return NT_STATUS_NO_MEMORY;
6476 /* Append the new name. */
6477 base_name = talloc_asprintf_append(base_name,
6478 "%s",
6479 newname);
6480 if (!base_name) {
6481 return NT_STATUS_NO_MEMORY;
6484 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6485 (UCF_SAVE_LCOMP |
6486 (dest_has_wcard ?
6487 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6488 0)));
6490 /* If an error we expect this to be
6491 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6493 if (!NT_STATUS_IS_OK(status)) {
6494 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6495 status)) {
6496 goto out;
6498 /* Create an smb_fname to call rename_internals_fsp() */
6499 status = create_synthetic_smb_fname(ctx,
6500 base_name, NULL,
6501 NULL,
6502 &smb_fname_dst);
6503 if (!NT_STATUS_IS_OK(status)) {
6504 goto out;
6509 if (fsp) {
6510 DEBUG(10,("smb_file_rename_information: "
6511 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6512 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6513 smb_fname_str_dbg(smb_fname_dst)));
6514 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6515 overwrite);
6516 } else {
6517 DEBUG(10,("smb_file_rename_information: "
6518 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6519 smb_fname_str_dbg(smb_fname_src),
6520 smb_fname_str_dbg(smb_fname_dst)));
6521 status = rename_internals(ctx, conn, req, smb_fname_src,
6522 smb_fname_dst, 0, overwrite, false,
6523 dest_has_wcard,
6524 FILE_WRITE_ATTRIBUTES);
6526 out:
6527 TALLOC_FREE(smb_fname_dst);
6528 return status;
6531 /****************************************************************************
6532 Deal with SMB_SET_POSIX_ACL.
6533 ****************************************************************************/
6535 #if defined(HAVE_POSIX_ACLS)
6536 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6537 const char *pdata,
6538 int total_data,
6539 files_struct *fsp,
6540 const struct smb_filename *smb_fname)
6542 uint16 posix_acl_version;
6543 uint16 num_file_acls;
6544 uint16 num_def_acls;
6545 bool valid_file_acls = True;
6546 bool valid_def_acls = True;
6548 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6549 return NT_STATUS_INVALID_PARAMETER;
6551 posix_acl_version = SVAL(pdata,0);
6552 num_file_acls = SVAL(pdata,2);
6553 num_def_acls = SVAL(pdata,4);
6555 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6556 valid_file_acls = False;
6557 num_file_acls = 0;
6560 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6561 valid_def_acls = False;
6562 num_def_acls = 0;
6565 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6570 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6571 return NT_STATUS_INVALID_PARAMETER;
6574 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6575 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6576 (unsigned int)num_file_acls,
6577 (unsigned int)num_def_acls));
6579 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6580 smb_fname->base_name, num_file_acls,
6581 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6582 return map_nt_error_from_unix(errno);
6585 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6586 smb_fname->base_name, &smb_fname->st, num_def_acls,
6587 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6588 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6589 return map_nt_error_from_unix(errno);
6591 return NT_STATUS_OK;
6593 #endif
6595 /****************************************************************************
6596 Deal with SMB_SET_POSIX_LOCK.
6597 ****************************************************************************/
6599 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6600 struct smb_request *req,
6601 const char *pdata,
6602 int total_data,
6603 files_struct *fsp)
6605 uint64_t count;
6606 uint64_t offset;
6607 uint64_t smblctx;
6608 bool blocking_lock = False;
6609 enum brl_type lock_type;
6611 NTSTATUS status = NT_STATUS_OK;
6613 if (fsp == NULL || fsp->fh->fd == -1) {
6614 return NT_STATUS_INVALID_HANDLE;
6617 if (total_data != POSIX_LOCK_DATA_SIZE) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6622 case POSIX_LOCK_TYPE_READ:
6623 lock_type = READ_LOCK;
6624 break;
6625 case POSIX_LOCK_TYPE_WRITE:
6626 /* Return the right POSIX-mappable error code for files opened read-only. */
6627 if (!fsp->can_write) {
6628 return NT_STATUS_INVALID_HANDLE;
6630 lock_type = WRITE_LOCK;
6631 break;
6632 case POSIX_LOCK_TYPE_UNLOCK:
6633 lock_type = UNLOCK_LOCK;
6634 break;
6635 default:
6636 return NT_STATUS_INVALID_PARAMETER;
6639 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6640 blocking_lock = False;
6641 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6642 blocking_lock = True;
6643 } else {
6644 return NT_STATUS_INVALID_PARAMETER;
6647 if (!lp_blocking_locks(SNUM(conn))) {
6648 blocking_lock = False;
6651 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6652 #if defined(HAVE_LONGLONG)
6653 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6654 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6655 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6656 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6657 #else /* HAVE_LONGLONG */
6658 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6659 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6660 #endif /* HAVE_LONGLONG */
6662 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6663 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6664 fsp_str_dbg(fsp),
6665 (unsigned int)lock_type,
6666 (unsigned long long)smblctx,
6667 (double)count,
6668 (double)offset ));
6670 if (lock_type == UNLOCK_LOCK) {
6671 status = do_unlock(req->sconn->msg_ctx,
6672 fsp,
6673 smblctx,
6674 count,
6675 offset,
6676 POSIX_LOCK);
6677 } else {
6678 uint64_t block_smblctx;
6680 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6681 fsp,
6682 smblctx,
6683 count,
6684 offset,
6685 lock_type,
6686 POSIX_LOCK,
6687 blocking_lock,
6688 &status,
6689 &block_smblctx,
6690 NULL);
6692 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6694 * A blocking lock was requested. Package up
6695 * this smb into a queued request and push it
6696 * onto the blocking lock queue.
6698 if(push_blocking_lock_request(br_lck,
6699 req,
6700 fsp,
6701 -1, /* infinite timeout. */
6703 smblctx,
6704 lock_type,
6705 POSIX_LOCK,
6706 offset,
6707 count,
6708 block_smblctx)) {
6709 TALLOC_FREE(br_lck);
6710 return status;
6713 TALLOC_FREE(br_lck);
6716 return status;
6719 /****************************************************************************
6720 Deal with SMB_SET_FILE_BASIC_INFO.
6721 ****************************************************************************/
6723 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6724 const char *pdata,
6725 int total_data,
6726 files_struct *fsp,
6727 const struct smb_filename *smb_fname)
6729 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6730 struct smb_file_time ft;
6731 uint32 dosmode = 0;
6732 NTSTATUS status = NT_STATUS_OK;
6734 ZERO_STRUCT(ft);
6736 if (total_data < 36) {
6737 return NT_STATUS_INVALID_PARAMETER;
6740 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6741 if (!NT_STATUS_IS_OK(status)) {
6742 return status;
6745 /* Set the attributes */
6746 dosmode = IVAL(pdata,32);
6747 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6748 if (!NT_STATUS_IS_OK(status)) {
6749 return status;
6752 /* create time */
6753 ft.create_time = interpret_long_date(pdata);
6755 /* access time */
6756 ft.atime = interpret_long_date(pdata+8);
6758 /* write time. */
6759 ft.mtime = interpret_long_date(pdata+16);
6761 /* change time. */
6762 ft.ctime = interpret_long_date(pdata+24);
6764 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6765 smb_fname_str_dbg(smb_fname)));
6767 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6768 true);
6771 /****************************************************************************
6772 Deal with SMB_INFO_STANDARD.
6773 ****************************************************************************/
6775 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6776 const char *pdata,
6777 int total_data,
6778 files_struct *fsp,
6779 const struct smb_filename *smb_fname)
6781 NTSTATUS status;
6782 struct smb_file_time ft;
6784 ZERO_STRUCT(ft);
6786 if (total_data < 12) {
6787 return NT_STATUS_INVALID_PARAMETER;
6790 /* create time */
6791 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6792 /* access time */
6793 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6794 /* write time */
6795 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6797 DEBUG(10,("smb_set_info_standard: file %s\n",
6798 smb_fname_str_dbg(smb_fname)));
6800 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 return status;
6805 return smb_set_file_time(conn,
6806 fsp,
6807 smb_fname,
6808 &ft,
6809 true);
6812 /****************************************************************************
6813 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6814 ****************************************************************************/
6816 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6817 struct smb_request *req,
6818 const char *pdata,
6819 int total_data,
6820 files_struct *fsp,
6821 struct smb_filename *smb_fname)
6823 uint64_t allocation_size = 0;
6824 NTSTATUS status = NT_STATUS_OK;
6825 files_struct *new_fsp = NULL;
6827 if (!VALID_STAT(smb_fname->st)) {
6828 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6831 if (total_data < 8) {
6832 return NT_STATUS_INVALID_PARAMETER;
6835 allocation_size = (uint64_t)IVAL(pdata,0);
6836 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6837 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6838 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6839 (double)allocation_size));
6841 if (allocation_size) {
6842 allocation_size = smb_roundup(conn, allocation_size);
6845 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6846 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6847 (double)allocation_size));
6849 if (fsp && fsp->fh->fd != -1) {
6850 /* Open file handle. */
6851 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6852 return NT_STATUS_ACCESS_DENIED;
6855 /* Only change if needed. */
6856 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6857 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6858 return map_nt_error_from_unix(errno);
6861 /* But always update the time. */
6863 * This is equivalent to a write. Ensure it's seen immediately
6864 * if there are no pending writes.
6866 trigger_write_time_update_immediate(fsp);
6867 return NT_STATUS_OK;
6870 /* Pathname or stat or directory file. */
6871 status = SMB_VFS_CREATE_FILE(
6872 conn, /* conn */
6873 req, /* req */
6874 0, /* root_dir_fid */
6875 smb_fname, /* fname */
6876 FILE_WRITE_DATA, /* access_mask */
6877 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6878 FILE_SHARE_DELETE),
6879 FILE_OPEN, /* create_disposition*/
6880 0, /* create_options */
6881 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6882 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6883 0, /* allocation_size */
6884 0, /* private_flags */
6885 NULL, /* sd */
6886 NULL, /* ea_list */
6887 &new_fsp, /* result */
6888 NULL); /* pinfo */
6890 if (!NT_STATUS_IS_OK(status)) {
6891 /* NB. We check for open_was_deferred in the caller. */
6892 return status;
6895 /* Only change if needed. */
6896 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6897 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6898 status = map_nt_error_from_unix(errno);
6899 close_file(req, new_fsp, NORMAL_CLOSE);
6900 return status;
6904 /* Changing the allocation size should set the last mod time. */
6906 * This is equivalent to a write. Ensure it's seen immediately
6907 * if there are no pending writes.
6909 trigger_write_time_update_immediate(new_fsp);
6911 close_file(req, new_fsp, NORMAL_CLOSE);
6912 return NT_STATUS_OK;
6915 /****************************************************************************
6916 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6917 ****************************************************************************/
6919 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6920 struct smb_request *req,
6921 const char *pdata,
6922 int total_data,
6923 files_struct *fsp,
6924 const struct smb_filename *smb_fname,
6925 bool fail_after_createfile)
6927 off_t size;
6929 if (total_data < 8) {
6930 return NT_STATUS_INVALID_PARAMETER;
6933 size = IVAL(pdata,0);
6934 size |= (((off_t)IVAL(pdata,4)) << 32);
6935 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6936 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6937 (double)size));
6939 return smb_set_file_size(conn, req,
6940 fsp,
6941 smb_fname,
6942 &smb_fname->st,
6943 size,
6944 fail_after_createfile);
6947 /****************************************************************************
6948 Allow a UNIX info mknod.
6949 ****************************************************************************/
6951 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6952 const char *pdata,
6953 int total_data,
6954 const struct smb_filename *smb_fname)
6956 uint32 file_type = IVAL(pdata,56);
6957 #if defined(HAVE_MAKEDEV)
6958 uint32 dev_major = IVAL(pdata,60);
6959 uint32 dev_minor = IVAL(pdata,68);
6960 #endif
6961 SMB_DEV_T dev = (SMB_DEV_T)0;
6962 uint32 raw_unixmode = IVAL(pdata,84);
6963 NTSTATUS status;
6964 mode_t unixmode;
6966 if (total_data < 100) {
6967 return NT_STATUS_INVALID_PARAMETER;
6970 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6971 PERM_NEW_FILE, &unixmode);
6972 if (!NT_STATUS_IS_OK(status)) {
6973 return status;
6976 #if defined(HAVE_MAKEDEV)
6977 dev = makedev(dev_major, dev_minor);
6978 #endif
6980 switch (file_type) {
6981 #if defined(S_IFIFO)
6982 case UNIX_TYPE_FIFO:
6983 unixmode |= S_IFIFO;
6984 break;
6985 #endif
6986 #if defined(S_IFSOCK)
6987 case UNIX_TYPE_SOCKET:
6988 unixmode |= S_IFSOCK;
6989 break;
6990 #endif
6991 #if defined(S_IFCHR)
6992 case UNIX_TYPE_CHARDEV:
6993 unixmode |= S_IFCHR;
6994 break;
6995 #endif
6996 #if defined(S_IFBLK)
6997 case UNIX_TYPE_BLKDEV:
6998 unixmode |= S_IFBLK;
6999 break;
7000 #endif
7001 default:
7002 return NT_STATUS_INVALID_PARAMETER;
7005 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7006 "%.0f mode 0%o for file %s\n", (double)dev,
7007 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7009 /* Ok - do the mknod. */
7010 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7011 return map_nt_error_from_unix(errno);
7014 /* If any of the other "set" calls fail we
7015 * don't want to end up with a half-constructed mknod.
7018 if (lp_inherit_perms(SNUM(conn))) {
7019 char *parent;
7020 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7021 &parent, NULL)) {
7022 return NT_STATUS_NO_MEMORY;
7024 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7025 unixmode);
7026 TALLOC_FREE(parent);
7029 return NT_STATUS_OK;
7032 /****************************************************************************
7033 Deal with SMB_SET_FILE_UNIX_BASIC.
7034 ****************************************************************************/
7036 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7037 struct smb_request *req,
7038 const char *pdata,
7039 int total_data,
7040 files_struct *fsp,
7041 const struct smb_filename *smb_fname)
7043 struct smb_file_time ft;
7044 uint32 raw_unixmode;
7045 mode_t unixmode;
7046 off_t size = 0;
7047 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7048 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7049 NTSTATUS status = NT_STATUS_OK;
7050 bool delete_on_fail = False;
7051 enum perm_type ptype;
7052 files_struct *all_fsps = NULL;
7053 bool modify_mtime = true;
7054 struct file_id id;
7055 struct smb_filename *smb_fname_tmp = NULL;
7056 SMB_STRUCT_STAT sbuf;
7058 ZERO_STRUCT(ft);
7060 if (total_data < 100) {
7061 return NT_STATUS_INVALID_PARAMETER;
7064 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7065 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7066 size=IVAL(pdata,0); /* first 8 Bytes are size */
7067 size |= (((off_t)IVAL(pdata,4)) << 32);
7070 ft.atime = interpret_long_date(pdata+24); /* access_time */
7071 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7072 set_owner = (uid_t)IVAL(pdata,40);
7073 set_grp = (gid_t)IVAL(pdata,48);
7074 raw_unixmode = IVAL(pdata,84);
7076 if (VALID_STAT(smb_fname->st)) {
7077 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7078 ptype = PERM_EXISTING_DIR;
7079 } else {
7080 ptype = PERM_EXISTING_FILE;
7082 } else {
7083 ptype = PERM_NEW_FILE;
7086 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7087 ptype, &unixmode);
7088 if (!NT_STATUS_IS_OK(status)) {
7089 return status;
7092 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7093 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7094 smb_fname_str_dbg(smb_fname), (double)size,
7095 (unsigned int)set_owner, (unsigned int)set_grp,
7096 (int)raw_unixmode));
7098 sbuf = smb_fname->st;
7100 if (!VALID_STAT(sbuf)) {
7102 * The only valid use of this is to create character and block
7103 * devices, and named pipes. This is deprecated (IMHO) and
7104 * a new info level should be used for mknod. JRA.
7107 status = smb_unix_mknod(conn,
7108 pdata,
7109 total_data,
7110 smb_fname);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 return status;
7115 status = copy_smb_filename(talloc_tos(), smb_fname,
7116 &smb_fname_tmp);
7117 if (!NT_STATUS_IS_OK(status)) {
7118 return status;
7121 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7122 status = map_nt_error_from_unix(errno);
7123 TALLOC_FREE(smb_fname_tmp);
7124 SMB_VFS_UNLINK(conn, smb_fname);
7125 return status;
7128 sbuf = smb_fname_tmp->st;
7129 smb_fname = smb_fname_tmp;
7131 /* Ensure we don't try and change anything else. */
7132 raw_unixmode = SMB_MODE_NO_CHANGE;
7133 size = get_file_size_stat(&sbuf);
7134 ft.atime = sbuf.st_ex_atime;
7135 ft.mtime = sbuf.st_ex_mtime;
7137 * We continue here as we might want to change the
7138 * owner uid/gid.
7140 delete_on_fail = True;
7143 #if 1
7144 /* Horrible backwards compatibility hack as an old server bug
7145 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7146 * */
7148 if (!size) {
7149 size = get_file_size_stat(&sbuf);
7151 #endif
7154 * Deal with the UNIX specific mode set.
7157 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7158 int ret;
7160 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7161 "setting mode 0%o for file %s\n",
7162 (unsigned int)unixmode,
7163 smb_fname_str_dbg(smb_fname)));
7164 if (fsp && fsp->fh->fd != -1) {
7165 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7166 } else {
7167 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7169 if (ret != 0) {
7170 return map_nt_error_from_unix(errno);
7175 * Deal with the UNIX specific uid set.
7178 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7179 (sbuf.st_ex_uid != set_owner)) {
7180 int ret;
7182 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7183 "changing owner %u for path %s\n",
7184 (unsigned int)set_owner,
7185 smb_fname_str_dbg(smb_fname)));
7187 if (fsp && fsp->fh->fd != -1) {
7188 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7189 } else {
7191 * UNIX extensions calls must always operate
7192 * on symlinks.
7194 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7195 set_owner, (gid_t)-1);
7198 if (ret != 0) {
7199 status = map_nt_error_from_unix(errno);
7200 if (delete_on_fail) {
7201 SMB_VFS_UNLINK(conn, smb_fname);
7203 return status;
7208 * Deal with the UNIX specific gid set.
7211 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7212 (sbuf.st_ex_gid != set_grp)) {
7213 int ret;
7215 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7216 "changing group %u for file %s\n",
7217 (unsigned int)set_owner,
7218 smb_fname_str_dbg(smb_fname)));
7219 if (fsp && fsp->fh->fd != -1) {
7220 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7221 } else {
7223 * UNIX extensions calls must always operate
7224 * on symlinks.
7226 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7227 set_grp);
7229 if (ret != 0) {
7230 status = map_nt_error_from_unix(errno);
7231 if (delete_on_fail) {
7232 SMB_VFS_UNLINK(conn, smb_fname);
7234 return status;
7238 /* Deal with any size changes. */
7240 status = smb_set_file_size(conn, req,
7241 fsp,
7242 smb_fname,
7243 &sbuf,
7244 size,
7245 false);
7246 if (!NT_STATUS_IS_OK(status)) {
7247 return status;
7250 /* Deal with any time changes. */
7251 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7252 /* No change, don't cancel anything. */
7253 return status;
7256 id = vfs_file_id_from_sbuf(conn, &sbuf);
7257 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7258 all_fsps = file_find_di_next(all_fsps)) {
7260 * We're setting the time explicitly for UNIX.
7261 * Cancel any pending changes over all handles.
7263 all_fsps->update_write_time_on_close = false;
7264 TALLOC_FREE(all_fsps->update_write_time_event);
7268 * Override the "setting_write_time"
7269 * parameter here as it almost does what
7270 * we need. Just remember if we modified
7271 * mtime and send the notify ourselves.
7273 if (null_timespec(ft.mtime)) {
7274 modify_mtime = false;
7277 status = smb_set_file_time(conn,
7278 fsp,
7279 smb_fname,
7280 &ft,
7281 false);
7282 if (modify_mtime) {
7283 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7284 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7286 return status;
7289 /****************************************************************************
7290 Deal with SMB_SET_FILE_UNIX_INFO2.
7291 ****************************************************************************/
7293 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7294 struct smb_request *req,
7295 const char *pdata,
7296 int total_data,
7297 files_struct *fsp,
7298 const struct smb_filename *smb_fname)
7300 NTSTATUS status;
7301 uint32 smb_fflags;
7302 uint32 smb_fmask;
7304 if (total_data < 116) {
7305 return NT_STATUS_INVALID_PARAMETER;
7308 /* Start by setting all the fields that are common between UNIX_BASIC
7309 * and UNIX_INFO2.
7311 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7312 fsp, smb_fname);
7313 if (!NT_STATUS_IS_OK(status)) {
7314 return status;
7317 smb_fflags = IVAL(pdata, 108);
7318 smb_fmask = IVAL(pdata, 112);
7320 /* NB: We should only attempt to alter the file flags if the client
7321 * sends a non-zero mask.
7323 if (smb_fmask != 0) {
7324 int stat_fflags = 0;
7326 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7327 smb_fmask, &stat_fflags)) {
7328 /* Client asked to alter a flag we don't understand. */
7329 return NT_STATUS_INVALID_PARAMETER;
7332 if (fsp && fsp->fh->fd != -1) {
7333 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7334 return NT_STATUS_NOT_SUPPORTED;
7335 } else {
7336 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7337 stat_fflags) != 0) {
7338 return map_nt_error_from_unix(errno);
7343 /* XXX: need to add support for changing the create_time here. You
7344 * can do this for paths on Darwin with setattrlist(2). The right way
7345 * to hook this up is probably by extending the VFS utimes interface.
7348 return NT_STATUS_OK;
7351 /****************************************************************************
7352 Create a directory with POSIX semantics.
7353 ****************************************************************************/
7355 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7356 struct smb_request *req,
7357 char **ppdata,
7358 int total_data,
7359 struct smb_filename *smb_fname,
7360 int *pdata_return_size)
7362 NTSTATUS status = NT_STATUS_OK;
7363 uint32 raw_unixmode = 0;
7364 uint32 mod_unixmode = 0;
7365 mode_t unixmode = (mode_t)0;
7366 files_struct *fsp = NULL;
7367 uint16 info_level_return = 0;
7368 int info;
7369 char *pdata = *ppdata;
7371 if (total_data < 18) {
7372 return NT_STATUS_INVALID_PARAMETER;
7375 raw_unixmode = IVAL(pdata,8);
7376 /* Next 4 bytes are not yet defined. */
7378 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7379 PERM_NEW_DIR, &unixmode);
7380 if (!NT_STATUS_IS_OK(status)) {
7381 return status;
7384 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7386 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7387 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7389 status = SMB_VFS_CREATE_FILE(
7390 conn, /* conn */
7391 req, /* req */
7392 0, /* root_dir_fid */
7393 smb_fname, /* fname */
7394 FILE_READ_ATTRIBUTES, /* access_mask */
7395 FILE_SHARE_NONE, /* share_access */
7396 FILE_CREATE, /* create_disposition*/
7397 FILE_DIRECTORY_FILE, /* create_options */
7398 mod_unixmode, /* file_attributes */
7399 0, /* oplock_request */
7400 0, /* allocation_size */
7401 0, /* private_flags */
7402 NULL, /* sd */
7403 NULL, /* ea_list */
7404 &fsp, /* result */
7405 &info); /* pinfo */
7407 if (NT_STATUS_IS_OK(status)) {
7408 close_file(req, fsp, NORMAL_CLOSE);
7411 info_level_return = SVAL(pdata,16);
7413 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7414 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7415 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7416 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7417 } else {
7418 *pdata_return_size = 12;
7421 /* Realloc the data size */
7422 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7423 if (*ppdata == NULL) {
7424 *pdata_return_size = 0;
7425 return NT_STATUS_NO_MEMORY;
7427 pdata = *ppdata;
7429 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7430 SSVAL(pdata,2,0); /* No fnum. */
7431 SIVAL(pdata,4,info); /* Was directory created. */
7433 switch (info_level_return) {
7434 case SMB_QUERY_FILE_UNIX_BASIC:
7435 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7436 SSVAL(pdata,10,0); /* Padding. */
7437 store_file_unix_basic(conn, pdata + 12, fsp,
7438 &smb_fname->st);
7439 break;
7440 case SMB_QUERY_FILE_UNIX_INFO2:
7441 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7442 SSVAL(pdata,10,0); /* Padding. */
7443 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7444 &smb_fname->st);
7445 break;
7446 default:
7447 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7448 SSVAL(pdata,10,0); /* Padding. */
7449 break;
7452 return status;
7455 /****************************************************************************
7456 Open/Create a file with POSIX semantics.
7457 ****************************************************************************/
7459 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7460 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7462 static NTSTATUS smb_posix_open(connection_struct *conn,
7463 struct smb_request *req,
7464 char **ppdata,
7465 int total_data,
7466 struct smb_filename *smb_fname,
7467 int *pdata_return_size)
7469 bool extended_oplock_granted = False;
7470 char *pdata = *ppdata;
7471 uint32 flags = 0;
7472 uint32 wire_open_mode = 0;
7473 uint32 raw_unixmode = 0;
7474 uint32 mod_unixmode = 0;
7475 uint32 create_disp = 0;
7476 uint32 access_mask = 0;
7477 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7478 NTSTATUS status = NT_STATUS_OK;
7479 mode_t unixmode = (mode_t)0;
7480 files_struct *fsp = NULL;
7481 int oplock_request = 0;
7482 int info = 0;
7483 uint16 info_level_return = 0;
7485 if (total_data < 18) {
7486 return NT_STATUS_INVALID_PARAMETER;
7489 flags = IVAL(pdata,0);
7490 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7491 if (oplock_request) {
7492 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7495 wire_open_mode = IVAL(pdata,4);
7497 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7498 return smb_posix_mkdir(conn, req,
7499 ppdata,
7500 total_data,
7501 smb_fname,
7502 pdata_return_size);
7505 switch (wire_open_mode & SMB_ACCMODE) {
7506 case SMB_O_RDONLY:
7507 access_mask = SMB_O_RDONLY_MAPPING;
7508 break;
7509 case SMB_O_WRONLY:
7510 access_mask = SMB_O_WRONLY_MAPPING;
7511 break;
7512 case SMB_O_RDWR:
7513 access_mask = (SMB_O_RDONLY_MAPPING|
7514 SMB_O_WRONLY_MAPPING);
7515 break;
7516 default:
7517 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7518 (unsigned int)wire_open_mode ));
7519 return NT_STATUS_INVALID_PARAMETER;
7522 wire_open_mode &= ~SMB_ACCMODE;
7524 /* First take care of O_CREAT|O_EXCL interactions. */
7525 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7526 case (SMB_O_CREAT | SMB_O_EXCL):
7527 /* File exists fail. File not exist create. */
7528 create_disp = FILE_CREATE;
7529 break;
7530 case SMB_O_CREAT:
7531 /* File exists open. File not exist create. */
7532 create_disp = FILE_OPEN_IF;
7533 break;
7534 case SMB_O_EXCL:
7535 /* O_EXCL on its own without O_CREAT is undefined.
7536 We deliberately ignore it as some versions of
7537 Linux CIFSFS can send a bare O_EXCL on the
7538 wire which other filesystems in the kernel
7539 ignore. See bug 9519 for details. */
7541 /* Fallthrough. */
7543 case 0:
7544 /* File exists open. File not exist fail. */
7545 create_disp = FILE_OPEN;
7546 break;
7547 default:
7548 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7549 (unsigned int)wire_open_mode ));
7550 return NT_STATUS_INVALID_PARAMETER;
7553 /* Next factor in the effects of O_TRUNC. */
7554 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7556 if (wire_open_mode & SMB_O_TRUNC) {
7557 switch (create_disp) {
7558 case FILE_CREATE:
7559 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7560 /* Leave create_disp alone as
7561 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7563 /* File exists fail. File not exist create. */
7564 break;
7565 case FILE_OPEN_IF:
7566 /* SMB_O_CREAT | SMB_O_TRUNC */
7567 /* File exists overwrite. File not exist create. */
7568 create_disp = FILE_OVERWRITE_IF;
7569 break;
7570 case FILE_OPEN:
7571 /* SMB_O_TRUNC */
7572 /* File exists overwrite. File not exist fail. */
7573 create_disp = FILE_OVERWRITE;
7574 break;
7575 default:
7576 /* Cannot get here. */
7577 smb_panic("smb_posix_open: logic error");
7578 return NT_STATUS_INVALID_PARAMETER;
7582 raw_unixmode = IVAL(pdata,8);
7583 /* Next 4 bytes are not yet defined. */
7585 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7586 (VALID_STAT(smb_fname->st) ?
7587 PERM_EXISTING_FILE : PERM_NEW_FILE),
7588 &unixmode);
7590 if (!NT_STATUS_IS_OK(status)) {
7591 return status;
7594 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7596 if (wire_open_mode & SMB_O_SYNC) {
7597 create_options |= FILE_WRITE_THROUGH;
7599 if (wire_open_mode & SMB_O_APPEND) {
7600 access_mask |= FILE_APPEND_DATA;
7602 if (wire_open_mode & SMB_O_DIRECT) {
7603 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7606 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7607 VALID_STAT_OF_DIR(smb_fname->st)) {
7608 if (access_mask != SMB_O_RDONLY_MAPPING) {
7609 return NT_STATUS_FILE_IS_A_DIRECTORY;
7611 create_options &= ~FILE_NON_DIRECTORY_FILE;
7612 create_options |= FILE_DIRECTORY_FILE;
7615 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7616 smb_fname_str_dbg(smb_fname),
7617 (unsigned int)wire_open_mode,
7618 (unsigned int)unixmode ));
7620 status = SMB_VFS_CREATE_FILE(
7621 conn, /* conn */
7622 req, /* req */
7623 0, /* root_dir_fid */
7624 smb_fname, /* fname */
7625 access_mask, /* access_mask */
7626 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7627 FILE_SHARE_DELETE),
7628 create_disp, /* create_disposition*/
7629 create_options, /* create_options */
7630 mod_unixmode, /* file_attributes */
7631 oplock_request, /* oplock_request */
7632 0, /* allocation_size */
7633 0, /* private_flags */
7634 NULL, /* sd */
7635 NULL, /* ea_list */
7636 &fsp, /* result */
7637 &info); /* pinfo */
7639 if (!NT_STATUS_IS_OK(status)) {
7640 return status;
7643 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7644 extended_oplock_granted = True;
7647 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7648 extended_oplock_granted = True;
7651 info_level_return = SVAL(pdata,16);
7653 /* Allocate the correct return size. */
7655 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7656 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7657 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7658 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7659 } else {
7660 *pdata_return_size = 12;
7663 /* Realloc the data size */
7664 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7665 if (*ppdata == NULL) {
7666 close_file(req, fsp, ERROR_CLOSE);
7667 *pdata_return_size = 0;
7668 return NT_STATUS_NO_MEMORY;
7670 pdata = *ppdata;
7672 if (extended_oplock_granted) {
7673 if (flags & REQUEST_BATCH_OPLOCK) {
7674 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7675 } else {
7676 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7678 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7679 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7680 } else {
7681 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7684 SSVAL(pdata,2,fsp->fnum);
7685 SIVAL(pdata,4,info); /* Was file created etc. */
7687 switch (info_level_return) {
7688 case SMB_QUERY_FILE_UNIX_BASIC:
7689 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7690 SSVAL(pdata,10,0); /* padding. */
7691 store_file_unix_basic(conn, pdata + 12, fsp,
7692 &smb_fname->st);
7693 break;
7694 case SMB_QUERY_FILE_UNIX_INFO2:
7695 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7696 SSVAL(pdata,10,0); /* padding. */
7697 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7698 &smb_fname->st);
7699 break;
7700 default:
7701 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7702 SSVAL(pdata,10,0); /* padding. */
7703 break;
7705 return NT_STATUS_OK;
7708 /****************************************************************************
7709 Delete a file with POSIX semantics.
7710 ****************************************************************************/
7712 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7713 struct smb_request *req,
7714 const char *pdata,
7715 int total_data,
7716 struct smb_filename *smb_fname)
7718 NTSTATUS status = NT_STATUS_OK;
7719 files_struct *fsp = NULL;
7720 uint16 flags = 0;
7721 char del = 1;
7722 int info = 0;
7723 int create_options = 0;
7724 int i;
7725 struct share_mode_lock *lck = NULL;
7727 if (total_data < 2) {
7728 return NT_STATUS_INVALID_PARAMETER;
7731 flags = SVAL(pdata,0);
7733 if (!VALID_STAT(smb_fname->st)) {
7734 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7737 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7738 !VALID_STAT_OF_DIR(smb_fname->st)) {
7739 return NT_STATUS_NOT_A_DIRECTORY;
7742 DEBUG(10,("smb_posix_unlink: %s %s\n",
7743 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7744 smb_fname_str_dbg(smb_fname)));
7746 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7747 create_options |= FILE_DIRECTORY_FILE;
7750 status = SMB_VFS_CREATE_FILE(
7751 conn, /* conn */
7752 req, /* req */
7753 0, /* root_dir_fid */
7754 smb_fname, /* fname */
7755 DELETE_ACCESS, /* access_mask */
7756 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7757 FILE_SHARE_DELETE),
7758 FILE_OPEN, /* create_disposition*/
7759 create_options, /* create_options */
7760 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7761 0, /* oplock_request */
7762 0, /* allocation_size */
7763 0, /* private_flags */
7764 NULL, /* sd */
7765 NULL, /* ea_list */
7766 &fsp, /* result */
7767 &info); /* pinfo */
7769 if (!NT_STATUS_IS_OK(status)) {
7770 return status;
7774 * Don't lie to client. If we can't really delete due to
7775 * non-POSIX opens return SHARING_VIOLATION.
7778 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7779 if (lck == NULL) {
7780 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7781 "lock for file %s\n", fsp_str_dbg(fsp)));
7782 close_file(req, fsp, NORMAL_CLOSE);
7783 return NT_STATUS_INVALID_PARAMETER;
7787 * See if others still have the file open. If this is the case, then
7788 * don't delete. If all opens are POSIX delete we can set the delete
7789 * on close disposition.
7791 for (i=0; i<lck->data->num_share_modes; i++) {
7792 struct share_mode_entry *e = &lck->data->share_modes[i];
7793 if (is_valid_share_mode_entry(e)) {
7794 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7795 continue;
7797 if (share_mode_stale_pid(lck->data, i)) {
7798 continue;
7800 /* Fail with sharing violation. */
7801 TALLOC_FREE(lck);
7802 close_file(req, fsp, NORMAL_CLOSE);
7803 return NT_STATUS_SHARING_VIOLATION;
7808 * Set the delete on close.
7810 status = smb_set_file_disposition_info(conn,
7811 &del,
7813 fsp,
7814 smb_fname);
7816 TALLOC_FREE(lck);
7818 if (!NT_STATUS_IS_OK(status)) {
7819 close_file(req, fsp, NORMAL_CLOSE);
7820 return status;
7822 return close_file(req, fsp, NORMAL_CLOSE);
7825 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7826 struct smb_request *req,
7827 TALLOC_CTX *mem_ctx,
7828 uint16_t info_level,
7829 files_struct *fsp,
7830 struct smb_filename *smb_fname,
7831 char **ppdata, int total_data,
7832 int *ret_data_size)
7834 char *pdata = *ppdata;
7835 NTSTATUS status = NT_STATUS_OK;
7836 int data_return_size = 0;
7838 *ret_data_size = 0;
7840 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7841 return NT_STATUS_INVALID_LEVEL;
7844 if (!CAN_WRITE(conn)) {
7845 /* Allow POSIX opens. The open path will deny
7846 * any non-readonly opens. */
7847 if (info_level != SMB_POSIX_PATH_OPEN) {
7848 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7852 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7853 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7854 fsp_fnum_dbg(fsp),
7855 info_level, total_data));
7857 switch (info_level) {
7859 case SMB_INFO_STANDARD:
7861 status = smb_set_info_standard(conn,
7862 pdata,
7863 total_data,
7864 fsp,
7865 smb_fname);
7866 break;
7869 case SMB_INFO_SET_EA:
7871 status = smb_info_set_ea(conn,
7872 pdata,
7873 total_data,
7874 fsp,
7875 smb_fname);
7876 break;
7879 case SMB_SET_FILE_BASIC_INFO:
7880 case SMB_FILE_BASIC_INFORMATION:
7882 status = smb_set_file_basic_info(conn,
7883 pdata,
7884 total_data,
7885 fsp,
7886 smb_fname);
7887 break;
7890 case SMB_FILE_ALLOCATION_INFORMATION:
7891 case SMB_SET_FILE_ALLOCATION_INFO:
7893 status = smb_set_file_allocation_info(conn, req,
7894 pdata,
7895 total_data,
7896 fsp,
7897 smb_fname);
7898 break;
7901 case SMB_FILE_END_OF_FILE_INFORMATION:
7902 case SMB_SET_FILE_END_OF_FILE_INFO:
7905 * XP/Win7 both fail after the createfile with
7906 * SMB_SET_FILE_END_OF_FILE_INFO but not
7907 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7908 * The level is known here, so pass it down
7909 * appropriately.
7911 bool should_fail =
7912 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7914 status = smb_set_file_end_of_file_info(conn, req,
7915 pdata,
7916 total_data,
7917 fsp,
7918 smb_fname,
7919 should_fail);
7920 break;
7923 case SMB_FILE_DISPOSITION_INFORMATION:
7924 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7926 #if 0
7927 /* JRA - We used to just ignore this on a path ?
7928 * Shouldn't this be invalid level on a pathname
7929 * based call ?
7931 if (tran_call != TRANSACT2_SETFILEINFO) {
7932 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7934 #endif
7935 status = smb_set_file_disposition_info(conn,
7936 pdata,
7937 total_data,
7938 fsp,
7939 smb_fname);
7940 break;
7943 case SMB_FILE_POSITION_INFORMATION:
7945 status = smb_file_position_information(conn,
7946 pdata,
7947 total_data,
7948 fsp);
7949 break;
7952 case SMB_FILE_FULL_EA_INFORMATION:
7954 status = smb_set_file_full_ea_info(conn,
7955 pdata,
7956 total_data,
7957 fsp);
7958 break;
7961 /* From tridge Samba4 :
7962 * MODE_INFORMATION in setfileinfo (I have no
7963 * idea what "mode information" on a file is - it takes a value of 0,
7964 * 2, 4 or 6. What could it be?).
7967 case SMB_FILE_MODE_INFORMATION:
7969 status = smb_file_mode_information(conn,
7970 pdata,
7971 total_data);
7972 break;
7976 * CIFS UNIX extensions.
7979 case SMB_SET_FILE_UNIX_BASIC:
7981 status = smb_set_file_unix_basic(conn, req,
7982 pdata,
7983 total_data,
7984 fsp,
7985 smb_fname);
7986 break;
7989 case SMB_SET_FILE_UNIX_INFO2:
7991 status = smb_set_file_unix_info2(conn, req,
7992 pdata,
7993 total_data,
7994 fsp,
7995 smb_fname);
7996 break;
7999 case SMB_SET_FILE_UNIX_LINK:
8001 if (fsp) {
8002 /* We must have a pathname for this. */
8003 return NT_STATUS_INVALID_LEVEL;
8005 status = smb_set_file_unix_link(conn, req, pdata,
8006 total_data, smb_fname);
8007 break;
8010 case SMB_SET_FILE_UNIX_HLINK:
8012 if (fsp) {
8013 /* We must have a pathname for this. */
8014 return NT_STATUS_INVALID_LEVEL;
8016 status = smb_set_file_unix_hlink(conn, req,
8017 pdata, total_data,
8018 smb_fname);
8019 break;
8022 case SMB_FILE_RENAME_INFORMATION:
8024 status = smb_file_rename_information(conn, req,
8025 pdata, total_data,
8026 fsp, smb_fname);
8027 break;
8030 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8032 /* SMB2 rename information. */
8033 status = smb2_file_rename_information(conn, req,
8034 pdata, total_data,
8035 fsp, smb_fname);
8036 break;
8039 case SMB_FILE_LINK_INFORMATION:
8041 status = smb_file_link_information(conn, req,
8042 pdata, total_data,
8043 fsp, smb_fname);
8044 break;
8047 #if defined(HAVE_POSIX_ACLS)
8048 case SMB_SET_POSIX_ACL:
8050 status = smb_set_posix_acl(conn,
8051 pdata,
8052 total_data,
8053 fsp,
8054 smb_fname);
8055 break;
8057 #endif
8059 case SMB_SET_POSIX_LOCK:
8061 if (!fsp) {
8062 return NT_STATUS_INVALID_LEVEL;
8064 status = smb_set_posix_lock(conn, req,
8065 pdata, total_data, fsp);
8066 break;
8069 case SMB_POSIX_PATH_OPEN:
8071 if (fsp) {
8072 /* We must have a pathname for this. */
8073 return NT_STATUS_INVALID_LEVEL;
8076 status = smb_posix_open(conn, req,
8077 ppdata,
8078 total_data,
8079 smb_fname,
8080 &data_return_size);
8081 break;
8084 case SMB_POSIX_PATH_UNLINK:
8086 if (fsp) {
8087 /* We must have a pathname for this. */
8088 return NT_STATUS_INVALID_LEVEL;
8091 status = smb_posix_unlink(conn, req,
8092 pdata,
8093 total_data,
8094 smb_fname);
8095 break;
8098 default:
8099 return NT_STATUS_INVALID_LEVEL;
8102 if (!NT_STATUS_IS_OK(status)) {
8103 return status;
8106 *ret_data_size = data_return_size;
8107 return NT_STATUS_OK;
8110 /****************************************************************************
8111 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8112 ****************************************************************************/
8114 static void call_trans2setfilepathinfo(connection_struct *conn,
8115 struct smb_request *req,
8116 unsigned int tran_call,
8117 char **pparams, int total_params,
8118 char **ppdata, int total_data,
8119 unsigned int max_data_bytes)
8121 char *params = *pparams;
8122 char *pdata = *ppdata;
8123 uint16 info_level;
8124 struct smb_filename *smb_fname = NULL;
8125 files_struct *fsp = NULL;
8126 NTSTATUS status = NT_STATUS_OK;
8127 int data_return_size = 0;
8129 if (!params) {
8130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8131 return;
8134 if (tran_call == TRANSACT2_SETFILEINFO) {
8135 if (total_params < 4) {
8136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8137 return;
8140 fsp = file_fsp(req, SVAL(params,0));
8141 /* Basic check for non-null fsp. */
8142 if (!check_fsp_open(conn, req, fsp)) {
8143 return;
8145 info_level = SVAL(params,2);
8147 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8148 &smb_fname);
8149 if (!NT_STATUS_IS_OK(status)) {
8150 reply_nterror(req, status);
8151 return;
8154 if(fsp->fh->fd == -1) {
8156 * This is actually a SETFILEINFO on a directory
8157 * handle (returned from an NT SMB). NT5.0 seems
8158 * to do this call. JRA.
8160 if (INFO_LEVEL_IS_UNIX(info_level)) {
8161 /* Always do lstat for UNIX calls. */
8162 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8163 DEBUG(3,("call_trans2setfilepathinfo: "
8164 "SMB_VFS_LSTAT of %s failed "
8165 "(%s)\n",
8166 smb_fname_str_dbg(smb_fname),
8167 strerror(errno)));
8168 reply_nterror(req, map_nt_error_from_unix(errno));
8169 return;
8171 } else {
8172 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8173 DEBUG(3,("call_trans2setfilepathinfo: "
8174 "fileinfo of %s failed (%s)\n",
8175 smb_fname_str_dbg(smb_fname),
8176 strerror(errno)));
8177 reply_nterror(req, map_nt_error_from_unix(errno));
8178 return;
8181 } else if (fsp->print_file) {
8183 * Doing a DELETE_ON_CLOSE should cancel a print job.
8185 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8186 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8188 DEBUG(3,("call_trans2setfilepathinfo: "
8189 "Cancelling print job (%s)\n",
8190 fsp_str_dbg(fsp)));
8192 SSVAL(params,0,0);
8193 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8194 *ppdata, 0,
8195 max_data_bytes);
8196 return;
8197 } else {
8198 reply_nterror(req,
8199 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8200 return;
8202 } else {
8204 * Original code - this is an open file.
8206 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8207 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8208 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8209 strerror(errno)));
8210 reply_nterror(req, map_nt_error_from_unix(errno));
8211 return;
8214 } else {
8215 char *fname = NULL;
8216 uint32_t ucf_flags = 0;
8218 /* set path info */
8219 if (total_params < 7) {
8220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8221 return;
8224 info_level = SVAL(params,0);
8225 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8226 total_params - 6, STR_TERMINATE,
8227 &status);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 reply_nterror(req, status);
8230 return;
8233 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8234 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8235 info_level == SMB_FILE_RENAME_INFORMATION ||
8236 info_level == SMB_POSIX_PATH_UNLINK) {
8237 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8240 status = filename_convert(req, conn,
8241 req->flags2 & FLAGS2_DFS_PATHNAMES,
8242 fname,
8243 ucf_flags,
8244 NULL,
8245 &smb_fname);
8246 if (!NT_STATUS_IS_OK(status)) {
8247 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8248 reply_botherror(req,
8249 NT_STATUS_PATH_NOT_COVERED,
8250 ERRSRV, ERRbadpath);
8251 return;
8253 reply_nterror(req, status);
8254 return;
8257 if (INFO_LEVEL_IS_UNIX(info_level)) {
8259 * For CIFS UNIX extensions the target name may not exist.
8262 /* Always do lstat for UNIX calls. */
8263 SMB_VFS_LSTAT(conn, smb_fname);
8265 } else if (!VALID_STAT(smb_fname->st) &&
8266 SMB_VFS_STAT(conn, smb_fname)) {
8267 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8268 "%s failed (%s)\n",
8269 smb_fname_str_dbg(smb_fname),
8270 strerror(errno)));
8271 reply_nterror(req, map_nt_error_from_unix(errno));
8272 return;
8276 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8277 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8278 fsp_fnum_dbg(fsp),
8279 info_level,total_data));
8281 /* Realloc the parameter size */
8282 *pparams = (char *)SMB_REALLOC(*pparams,2);
8283 if (*pparams == NULL) {
8284 reply_nterror(req, NT_STATUS_NO_MEMORY);
8285 return;
8287 params = *pparams;
8289 SSVAL(params,0,0);
8291 status = smbd_do_setfilepathinfo(conn, req, req,
8292 info_level,
8293 fsp,
8294 smb_fname,
8295 ppdata, total_data,
8296 &data_return_size);
8297 if (!NT_STATUS_IS_OK(status)) {
8298 if (open_was_deferred(req->sconn, req->mid)) {
8299 /* We have re-scheduled this call. */
8300 return;
8302 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8303 /* We have re-scheduled this call. */
8304 return;
8306 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8307 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8308 ERRSRV, ERRbadpath);
8309 return;
8311 if (info_level == SMB_POSIX_PATH_OPEN) {
8312 reply_openerror(req, status);
8313 return;
8317 * Invalid EA name needs to return 2 param bytes,
8318 * not a zero-length error packet.
8320 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8321 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8322 max_data_bytes);
8323 } else {
8324 reply_nterror(req, status);
8326 return;
8329 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8330 max_data_bytes);
8332 return;
8335 /****************************************************************************
8336 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8337 ****************************************************************************/
8339 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8340 char **pparams, int total_params,
8341 char **ppdata, int total_data,
8342 unsigned int max_data_bytes)
8344 struct smb_filename *smb_dname = NULL;
8345 char *params = *pparams;
8346 char *pdata = *ppdata;
8347 char *directory = NULL;
8348 NTSTATUS status = NT_STATUS_OK;
8349 struct ea_list *ea_list = NULL;
8350 TALLOC_CTX *ctx = talloc_tos();
8352 if (!CAN_WRITE(conn)) {
8353 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8354 return;
8357 if (total_params < 5) {
8358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8359 return;
8362 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8363 total_params - 4, STR_TERMINATE,
8364 &status);
8365 if (!NT_STATUS_IS_OK(status)) {
8366 reply_nterror(req, status);
8367 return;
8370 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8372 status = filename_convert(ctx,
8373 conn,
8374 req->flags2 & FLAGS2_DFS_PATHNAMES,
8375 directory,
8377 NULL,
8378 &smb_dname);
8380 if (!NT_STATUS_IS_OK(status)) {
8381 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8382 reply_botherror(req,
8383 NT_STATUS_PATH_NOT_COVERED,
8384 ERRSRV, ERRbadpath);
8385 return;
8387 reply_nterror(req, status);
8388 return;
8392 * OS/2 workplace shell seems to send SET_EA requests of "null"
8393 * length (4 bytes containing IVAL 4).
8394 * They seem to have no effect. Bug #3212. JRA.
8397 if (total_data && (total_data != 4)) {
8398 /* Any data in this call is an EA list. */
8399 if (total_data < 10) {
8400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8401 goto out;
8404 if (IVAL(pdata,0) > total_data) {
8405 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8406 IVAL(pdata,0), (unsigned int)total_data));
8407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8408 goto out;
8411 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8412 total_data - 4);
8413 if (!ea_list) {
8414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8415 goto out;
8418 if (!lp_ea_support(SNUM(conn))) {
8419 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8420 goto out;
8423 /* If total_data == 4 Windows doesn't care what values
8424 * are placed in that field, it just ignores them.
8425 * The System i QNTC IBM SMB client puts bad values here,
8426 * so ignore them. */
8428 status = create_directory(conn, req, smb_dname);
8430 if (!NT_STATUS_IS_OK(status)) {
8431 reply_nterror(req, status);
8432 goto out;
8435 /* Try and set any given EA. */
8436 if (ea_list) {
8437 status = set_ea(conn, NULL, smb_dname, ea_list);
8438 if (!NT_STATUS_IS_OK(status)) {
8439 reply_nterror(req, status);
8440 goto out;
8444 /* Realloc the parameter and data sizes */
8445 *pparams = (char *)SMB_REALLOC(*pparams,2);
8446 if(*pparams == NULL) {
8447 reply_nterror(req, NT_STATUS_NO_MEMORY);
8448 goto out;
8450 params = *pparams;
8452 SSVAL(params,0,0);
8454 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8456 out:
8457 TALLOC_FREE(smb_dname);
8458 return;
8461 /****************************************************************************
8462 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8463 We don't actually do this - we just send a null response.
8464 ****************************************************************************/
8466 static void call_trans2findnotifyfirst(connection_struct *conn,
8467 struct smb_request *req,
8468 char **pparams, int total_params,
8469 char **ppdata, int total_data,
8470 unsigned int max_data_bytes)
8472 char *params = *pparams;
8473 uint16 info_level;
8475 if (total_params < 6) {
8476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8477 return;
8480 info_level = SVAL(params,4);
8481 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8483 switch (info_level) {
8484 case 1:
8485 case 2:
8486 break;
8487 default:
8488 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8489 return;
8492 /* Realloc the parameter and data sizes */
8493 *pparams = (char *)SMB_REALLOC(*pparams,6);
8494 if (*pparams == NULL) {
8495 reply_nterror(req, NT_STATUS_NO_MEMORY);
8496 return;
8498 params = *pparams;
8500 SSVAL(params,0,fnf_handle);
8501 SSVAL(params,2,0); /* No changes */
8502 SSVAL(params,4,0); /* No EA errors */
8504 fnf_handle++;
8506 if(fnf_handle == 0)
8507 fnf_handle = 257;
8509 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8511 return;
8514 /****************************************************************************
8515 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8516 changes). Currently this does nothing.
8517 ****************************************************************************/
8519 static void call_trans2findnotifynext(connection_struct *conn,
8520 struct smb_request *req,
8521 char **pparams, int total_params,
8522 char **ppdata, int total_data,
8523 unsigned int max_data_bytes)
8525 char *params = *pparams;
8527 DEBUG(3,("call_trans2findnotifynext\n"));
8529 /* Realloc the parameter and data sizes */
8530 *pparams = (char *)SMB_REALLOC(*pparams,4);
8531 if (*pparams == NULL) {
8532 reply_nterror(req, NT_STATUS_NO_MEMORY);
8533 return;
8535 params = *pparams;
8537 SSVAL(params,0,0); /* No changes */
8538 SSVAL(params,2,0); /* No EA errors */
8540 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8542 return;
8545 /****************************************************************************
8546 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8547 ****************************************************************************/
8549 static void call_trans2getdfsreferral(connection_struct *conn,
8550 struct smb_request *req,
8551 char **pparams, int total_params,
8552 char **ppdata, int total_data,
8553 unsigned int max_data_bytes)
8555 char *params = *pparams;
8556 char *pathname = NULL;
8557 int reply_size = 0;
8558 int max_referral_level;
8559 NTSTATUS status = NT_STATUS_OK;
8560 TALLOC_CTX *ctx = talloc_tos();
8562 DEBUG(10,("call_trans2getdfsreferral\n"));
8564 if (total_params < 3) {
8565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8566 return;
8569 max_referral_level = SVAL(params,0);
8571 if(!lp_host_msdfs()) {
8572 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8573 return;
8576 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8577 total_params - 2, STR_TERMINATE);
8578 if (!pathname) {
8579 reply_nterror(req, NT_STATUS_NOT_FOUND);
8580 return;
8582 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8583 ppdata,&status)) < 0) {
8584 reply_nterror(req, status);
8585 return;
8588 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8589 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8590 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8592 return;
8595 #define LMCAT_SPL 0x53
8596 #define LMFUNC_GETJOBID 0x60
8598 /****************************************************************************
8599 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8600 ****************************************************************************/
8602 static void call_trans2ioctl(connection_struct *conn,
8603 struct smb_request *req,
8604 char **pparams, int total_params,
8605 char **ppdata, int total_data,
8606 unsigned int max_data_bytes)
8608 char *pdata = *ppdata;
8609 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8611 /* check for an invalid fid before proceeding */
8613 if (!fsp) {
8614 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8615 return;
8618 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8619 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8620 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8621 if (*ppdata == NULL) {
8622 reply_nterror(req, NT_STATUS_NO_MEMORY);
8623 return;
8625 pdata = *ppdata;
8627 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8628 CAN ACCEPT THIS IN UNICODE. JRA. */
8630 /* Job number */
8631 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8633 srvstr_push(pdata, req->flags2, pdata + 2,
8634 lp_netbios_name(), 15,
8635 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8636 srvstr_push(pdata, req->flags2, pdata+18,
8637 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8638 STR_ASCII|STR_TERMINATE); /* Service name */
8639 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8640 max_data_bytes);
8641 return;
8644 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8645 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8648 /****************************************************************************
8649 Reply to a SMBfindclose (stop trans2 directory search).
8650 ****************************************************************************/
8652 void reply_findclose(struct smb_request *req)
8654 int dptr_num;
8655 struct smbd_server_connection *sconn = req->sconn;
8657 START_PROFILE(SMBfindclose);
8659 if (req->wct < 1) {
8660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8661 END_PROFILE(SMBfindclose);
8662 return;
8665 dptr_num = SVALS(req->vwv+0, 0);
8667 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8669 dptr_close(sconn, &dptr_num);
8671 reply_outbuf(req, 0, 0);
8673 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8675 END_PROFILE(SMBfindclose);
8676 return;
8679 /****************************************************************************
8680 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8681 ****************************************************************************/
8683 void reply_findnclose(struct smb_request *req)
8685 int dptr_num;
8687 START_PROFILE(SMBfindnclose);
8689 if (req->wct < 1) {
8690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8691 END_PROFILE(SMBfindnclose);
8692 return;
8695 dptr_num = SVAL(req->vwv+0, 0);
8697 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8699 /* We never give out valid handles for a
8700 findnotifyfirst - so any dptr_num is ok here.
8701 Just ignore it. */
8703 reply_outbuf(req, 0, 0);
8705 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8707 END_PROFILE(SMBfindnclose);
8708 return;
8711 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8712 struct trans_state *state)
8714 if (get_Protocol() >= PROTOCOL_NT1) {
8715 req->flags2 |= 0x40; /* IS_LONG_NAME */
8716 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8719 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8720 if (state->call != TRANSACT2_QFSINFO &&
8721 state->call != TRANSACT2_SETFSINFO) {
8722 DEBUG(0,("handle_trans2: encryption required "
8723 "with call 0x%x\n",
8724 (unsigned int)state->call));
8725 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8726 return;
8730 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8732 /* Now we must call the relevant TRANS2 function */
8733 switch(state->call) {
8734 case TRANSACT2_OPEN:
8736 START_PROFILE(Trans2_open);
8737 call_trans2open(conn, req,
8738 &state->param, state->total_param,
8739 &state->data, state->total_data,
8740 state->max_data_return);
8741 END_PROFILE(Trans2_open);
8742 break;
8745 case TRANSACT2_FINDFIRST:
8747 START_PROFILE(Trans2_findfirst);
8748 call_trans2findfirst(conn, req,
8749 &state->param, state->total_param,
8750 &state->data, state->total_data,
8751 state->max_data_return);
8752 END_PROFILE(Trans2_findfirst);
8753 break;
8756 case TRANSACT2_FINDNEXT:
8758 START_PROFILE(Trans2_findnext);
8759 call_trans2findnext(conn, req,
8760 &state->param, state->total_param,
8761 &state->data, state->total_data,
8762 state->max_data_return);
8763 END_PROFILE(Trans2_findnext);
8764 break;
8767 case TRANSACT2_QFSINFO:
8769 START_PROFILE(Trans2_qfsinfo);
8770 call_trans2qfsinfo(conn, req,
8771 &state->param, state->total_param,
8772 &state->data, state->total_data,
8773 state->max_data_return);
8774 END_PROFILE(Trans2_qfsinfo);
8775 break;
8778 case TRANSACT2_SETFSINFO:
8780 START_PROFILE(Trans2_setfsinfo);
8781 call_trans2setfsinfo(conn, req,
8782 &state->param, state->total_param,
8783 &state->data, state->total_data,
8784 state->max_data_return);
8785 END_PROFILE(Trans2_setfsinfo);
8786 break;
8789 case TRANSACT2_QPATHINFO:
8790 case TRANSACT2_QFILEINFO:
8792 START_PROFILE(Trans2_qpathinfo);
8793 call_trans2qfilepathinfo(conn, req, state->call,
8794 &state->param, state->total_param,
8795 &state->data, state->total_data,
8796 state->max_data_return);
8797 END_PROFILE(Trans2_qpathinfo);
8798 break;
8801 case TRANSACT2_SETPATHINFO:
8802 case TRANSACT2_SETFILEINFO:
8804 START_PROFILE(Trans2_setpathinfo);
8805 call_trans2setfilepathinfo(conn, req, state->call,
8806 &state->param, state->total_param,
8807 &state->data, state->total_data,
8808 state->max_data_return);
8809 END_PROFILE(Trans2_setpathinfo);
8810 break;
8813 case TRANSACT2_FINDNOTIFYFIRST:
8815 START_PROFILE(Trans2_findnotifyfirst);
8816 call_trans2findnotifyfirst(conn, req,
8817 &state->param, state->total_param,
8818 &state->data, state->total_data,
8819 state->max_data_return);
8820 END_PROFILE(Trans2_findnotifyfirst);
8821 break;
8824 case TRANSACT2_FINDNOTIFYNEXT:
8826 START_PROFILE(Trans2_findnotifynext);
8827 call_trans2findnotifynext(conn, req,
8828 &state->param, state->total_param,
8829 &state->data, state->total_data,
8830 state->max_data_return);
8831 END_PROFILE(Trans2_findnotifynext);
8832 break;
8835 case TRANSACT2_MKDIR:
8837 START_PROFILE(Trans2_mkdir);
8838 call_trans2mkdir(conn, req,
8839 &state->param, state->total_param,
8840 &state->data, state->total_data,
8841 state->max_data_return);
8842 END_PROFILE(Trans2_mkdir);
8843 break;
8846 case TRANSACT2_GET_DFS_REFERRAL:
8848 START_PROFILE(Trans2_get_dfs_referral);
8849 call_trans2getdfsreferral(conn, req,
8850 &state->param, state->total_param,
8851 &state->data, state->total_data,
8852 state->max_data_return);
8853 END_PROFILE(Trans2_get_dfs_referral);
8854 break;
8857 case TRANSACT2_IOCTL:
8859 START_PROFILE(Trans2_ioctl);
8860 call_trans2ioctl(conn, req,
8861 &state->param, state->total_param,
8862 &state->data, state->total_data,
8863 state->max_data_return);
8864 END_PROFILE(Trans2_ioctl);
8865 break;
8868 default:
8869 /* Error in request */
8870 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8871 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8875 /****************************************************************************
8876 Reply to a SMBtrans2.
8877 ****************************************************************************/
8879 void reply_trans2(struct smb_request *req)
8881 connection_struct *conn = req->conn;
8882 unsigned int dsoff;
8883 unsigned int dscnt;
8884 unsigned int psoff;
8885 unsigned int pscnt;
8886 unsigned int tran_call;
8887 struct trans_state *state;
8888 NTSTATUS result;
8890 START_PROFILE(SMBtrans2);
8892 if (req->wct < 14) {
8893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8894 END_PROFILE(SMBtrans2);
8895 return;
8898 dsoff = SVAL(req->vwv+12, 0);
8899 dscnt = SVAL(req->vwv+11, 0);
8900 psoff = SVAL(req->vwv+10, 0);
8901 pscnt = SVAL(req->vwv+9, 0);
8902 tran_call = SVAL(req->vwv+14, 0);
8904 result = allow_new_trans(conn->pending_trans, req->mid);
8905 if (!NT_STATUS_IS_OK(result)) {
8906 DEBUG(2, ("Got invalid trans2 request: %s\n",
8907 nt_errstr(result)));
8908 reply_nterror(req, result);
8909 END_PROFILE(SMBtrans2);
8910 return;
8913 if (IS_IPC(conn)) {
8914 switch (tran_call) {
8915 /* List the allowed trans2 calls on IPC$ */
8916 case TRANSACT2_OPEN:
8917 case TRANSACT2_GET_DFS_REFERRAL:
8918 case TRANSACT2_QFILEINFO:
8919 case TRANSACT2_QFSINFO:
8920 case TRANSACT2_SETFSINFO:
8921 break;
8922 default:
8923 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8924 END_PROFILE(SMBtrans2);
8925 return;
8929 if ((state = talloc(conn, struct trans_state)) == NULL) {
8930 DEBUG(0, ("talloc failed\n"));
8931 reply_nterror(req, NT_STATUS_NO_MEMORY);
8932 END_PROFILE(SMBtrans2);
8933 return;
8936 state->cmd = SMBtrans2;
8938 state->mid = req->mid;
8939 state->vuid = req->vuid;
8940 state->setup_count = SVAL(req->vwv+13, 0);
8941 state->setup = NULL;
8942 state->total_param = SVAL(req->vwv+0, 0);
8943 state->param = NULL;
8944 state->total_data = SVAL(req->vwv+1, 0);
8945 state->data = NULL;
8946 state->max_param_return = SVAL(req->vwv+2, 0);
8947 state->max_data_return = SVAL(req->vwv+3, 0);
8948 state->max_setup_return = SVAL(req->vwv+4, 0);
8949 state->close_on_completion = BITSETW(req->vwv+5, 0);
8950 state->one_way = BITSETW(req->vwv+5, 1);
8952 state->call = tran_call;
8954 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8955 is so as a sanity check */
8956 if (state->setup_count != 1) {
8958 * Need to have rc=0 for ioctl to get job id for OS/2.
8959 * Network printing will fail if function is not successful.
8960 * Similar function in reply.c will be used if protocol
8961 * is LANMAN1.0 instead of LM1.2X002.
8962 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8963 * outbuf doesn't have to be set(only job id is used).
8965 if ( (state->setup_count == 4)
8966 && (tran_call == TRANSACT2_IOCTL)
8967 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8968 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8969 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8970 } else {
8971 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8972 DEBUG(2,("Transaction is %d\n",tran_call));
8973 TALLOC_FREE(state);
8974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8975 END_PROFILE(SMBtrans2);
8976 return;
8980 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8981 goto bad_param;
8983 if (state->total_data) {
8985 if (trans_oob(state->total_data, 0, dscnt)
8986 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8987 goto bad_param;
8990 /* Can't use talloc here, the core routines do realloc on the
8991 * params and data. */
8992 state->data = (char *)SMB_MALLOC(state->total_data);
8993 if (state->data == NULL) {
8994 DEBUG(0,("reply_trans2: data malloc fail for %u "
8995 "bytes !\n", (unsigned int)state->total_data));
8996 TALLOC_FREE(state);
8997 reply_nterror(req, NT_STATUS_NO_MEMORY);
8998 END_PROFILE(SMBtrans2);
8999 return;
9002 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9005 if (state->total_param) {
9007 if (trans_oob(state->total_param, 0, pscnt)
9008 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9009 goto bad_param;
9012 /* Can't use talloc here, the core routines do realloc on the
9013 * params and data. */
9014 state->param = (char *)SMB_MALLOC(state->total_param);
9015 if (state->param == NULL) {
9016 DEBUG(0,("reply_trans: param malloc fail for %u "
9017 "bytes !\n", (unsigned int)state->total_param));
9018 SAFE_FREE(state->data);
9019 TALLOC_FREE(state);
9020 reply_nterror(req, NT_STATUS_NO_MEMORY);
9021 END_PROFILE(SMBtrans2);
9022 return;
9025 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9028 state->received_data = dscnt;
9029 state->received_param = pscnt;
9031 if ((state->received_param == state->total_param) &&
9032 (state->received_data == state->total_data)) {
9034 handle_trans2(conn, req, state);
9036 SAFE_FREE(state->data);
9037 SAFE_FREE(state->param);
9038 TALLOC_FREE(state);
9039 END_PROFILE(SMBtrans2);
9040 return;
9043 DLIST_ADD(conn->pending_trans, state);
9045 /* We need to send an interim response then receive the rest
9046 of the parameter/data bytes */
9047 reply_outbuf(req, 0, 0);
9048 show_msg((char *)req->outbuf);
9049 END_PROFILE(SMBtrans2);
9050 return;
9052 bad_param:
9054 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9055 SAFE_FREE(state->data);
9056 SAFE_FREE(state->param);
9057 TALLOC_FREE(state);
9058 END_PROFILE(SMBtrans2);
9059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9063 /****************************************************************************
9064 Reply to a SMBtranss2
9065 ****************************************************************************/
9067 void reply_transs2(struct smb_request *req)
9069 connection_struct *conn = req->conn;
9070 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9071 struct trans_state *state;
9073 START_PROFILE(SMBtranss2);
9075 show_msg((const char *)req->inbuf);
9077 /* Windows clients expect all replies to
9078 a transact secondary (SMBtranss2 0x33)
9079 to have a command code of transact
9080 (SMBtrans2 0x32). See bug #8989
9081 and also [MS-CIFS] section 2.2.4.47.2
9082 for details.
9084 req->cmd = SMBtrans2;
9086 if (req->wct < 8) {
9087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9088 END_PROFILE(SMBtranss2);
9089 return;
9092 for (state = conn->pending_trans; state != NULL;
9093 state = state->next) {
9094 if (state->mid == req->mid) {
9095 break;
9099 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9101 END_PROFILE(SMBtranss2);
9102 return;
9105 /* Revise state->total_param and state->total_data in case they have
9106 changed downwards */
9108 if (SVAL(req->vwv+0, 0) < state->total_param)
9109 state->total_param = SVAL(req->vwv+0, 0);
9110 if (SVAL(req->vwv+1, 0) < state->total_data)
9111 state->total_data = SVAL(req->vwv+1, 0);
9113 pcnt = SVAL(req->vwv+2, 0);
9114 poff = SVAL(req->vwv+3, 0);
9115 pdisp = SVAL(req->vwv+4, 0);
9117 dcnt = SVAL(req->vwv+5, 0);
9118 doff = SVAL(req->vwv+6, 0);
9119 ddisp = SVAL(req->vwv+7, 0);
9121 state->received_param += pcnt;
9122 state->received_data += dcnt;
9124 if ((state->received_data > state->total_data) ||
9125 (state->received_param > state->total_param))
9126 goto bad_param;
9128 if (pcnt) {
9129 if (trans_oob(state->total_param, pdisp, pcnt)
9130 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9131 goto bad_param;
9133 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9136 if (dcnt) {
9137 if (trans_oob(state->total_data, ddisp, dcnt)
9138 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9139 goto bad_param;
9141 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9144 if ((state->received_param < state->total_param) ||
9145 (state->received_data < state->total_data)) {
9146 END_PROFILE(SMBtranss2);
9147 return;
9150 handle_trans2(conn, req, state);
9152 DLIST_REMOVE(conn->pending_trans, state);
9153 SAFE_FREE(state->data);
9154 SAFE_FREE(state->param);
9155 TALLOC_FREE(state);
9157 END_PROFILE(SMBtranss2);
9158 return;
9160 bad_param:
9162 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9163 DLIST_REMOVE(conn->pending_trans, state);
9164 SAFE_FREE(state->data);
9165 SAFE_FREE(state->param);
9166 TALLOC_FREE(state);
9167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9168 END_PROFILE(SMBtranss2);
9169 return;