Reply with correct trans2 message on a setpathinfo with a bad EA name.
[Samba.git] / source3 / smbd / trans2.c
bloba216f15cd3833cc60c9c35506b8cf8afc16b627e
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
326 *ea_list = NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 &names, &num_names);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 if (num_names == 0) {
336 *ea_list = NULL;
337 return NT_STATUS_OK;
340 for (i=0; i<num_names; i++) {
341 struct ea_list *listp;
342 fstring dos_ea_name;
344 if (strnequal(names[i], "system.", 7)
345 || samba_private_attr_name(names[i]))
346 continue;
349 * Filter out any underlying POSIX EA names
350 * that a Windows client can't handle.
352 if (!lp_posix_pathnames() &&
353 is_invalid_windows_ea_name(names[i])) {
354 continue;
357 listp = talloc(mem_ctx, struct ea_list);
358 if (listp == NULL) {
359 return NT_STATUS_NO_MEMORY;
362 status = get_ea_value(listp, conn, fsp,
363 fname, names[i],
364 &listp->ea);
366 if (!NT_STATUS_IS_OK(status)) {
367 TALLOC_FREE(listp);
368 return status;
371 if (listp->ea.value.length == 0) {
373 * We can never return a zero length EA.
374 * Windows reports the EA's as corrupted.
376 TALLOC_FREE(listp);
377 continue;
380 push_ascii_fstring(dos_ea_name, listp->ea.name);
382 *pea_total_len +=
383 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
385 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
386 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
387 (unsigned int)listp->ea.value.length));
389 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
393 /* Add on 4 for total length. */
394 if (*pea_total_len) {
395 *pea_total_len += 4;
398 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
399 (unsigned int)*pea_total_len));
401 *ea_list = ea_list_head;
402 return NT_STATUS_OK;
405 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
406 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
408 *pea_total_len = 0;
409 *ea_list = NULL;
411 if (!lp_ea_support(SNUM(conn))) {
412 return NT_STATUS_OK;
415 if (is_ntfs_stream_smb_fname(smb_fname)) {
416 return NT_STATUS_INVALID_PARAMETER;
419 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
422 /****************************************************************************
423 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
424 that was filled.
425 ****************************************************************************/
427 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
428 connection_struct *conn, struct ea_list *ea_list)
430 unsigned int ret_data_size = 4;
431 char *p = pdata;
433 SMB_ASSERT(total_data_size >= 4);
435 if (!lp_ea_support(SNUM(conn))) {
436 SIVAL(pdata,4,0);
437 return 4;
440 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
441 size_t dos_namelen;
442 fstring dos_ea_name;
443 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
444 dos_namelen = strlen(dos_ea_name);
445 if (dos_namelen > 255 || dos_namelen == 0) {
446 break;
448 if (ea_list->ea.value.length > 65535) {
449 break;
451 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
452 break;
455 /* We know we have room. */
456 SCVAL(p,0,ea_list->ea.flags);
457 SCVAL(p,1,dos_namelen);
458 SSVAL(p,2,ea_list->ea.value.length);
459 strlcpy(p+4, dos_ea_name, dos_namelen+1);
460 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
462 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
463 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 ret_data_size = PTR_DIFF(p, pdata);
467 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
468 SIVAL(pdata,0,ret_data_size);
469 return ret_data_size;
472 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
473 char *pdata,
474 unsigned int total_data_size,
475 unsigned int *ret_data_size,
476 connection_struct *conn,
477 struct ea_list *ea_list)
479 uint8_t *p = (uint8_t *)pdata;
480 uint8_t *last_start = NULL;
481 bool do_store_data = (pdata != NULL);
483 *ret_data_size = 0;
485 if (!lp_ea_support(SNUM(conn))) {
486 return NT_STATUS_NO_EAS_ON_FILE;
489 for (; ea_list; ea_list = ea_list->next) {
490 size_t dos_namelen;
491 fstring dos_ea_name;
492 size_t this_size;
493 size_t pad = 0;
495 if (last_start != NULL && do_store_data) {
496 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
498 last_start = p;
500 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
501 dos_namelen = strlen(dos_ea_name);
502 if (dos_namelen > 255 || dos_namelen == 0) {
503 return NT_STATUS_INTERNAL_ERROR;
505 if (ea_list->ea.value.length > 65535) {
506 return NT_STATUS_INTERNAL_ERROR;
509 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
511 if (ea_list->next) {
512 pad = (4 - (this_size % 4)) % 4;
513 this_size += pad;
516 if (do_store_data) {
517 if (this_size > total_data_size) {
518 return NT_STATUS_INFO_LENGTH_MISMATCH;
521 /* We know we have room. */
522 SIVAL(p, 0x00, 0); /* next offset */
523 SCVAL(p, 0x04, ea_list->ea.flags);
524 SCVAL(p, 0x05, dos_namelen);
525 SSVAL(p, 0x06, ea_list->ea.value.length);
526 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
527 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
528 if (pad) {
529 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
530 '\0',
531 pad);
533 total_data_size -= this_size;
536 p += this_size;
539 *ret_data_size = PTR_DIFF(p, pdata);
540 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
541 return NT_STATUS_OK;
544 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
546 size_t total_ea_len = 0;
547 TALLOC_CTX *mem_ctx;
548 struct ea_list *ea_list = NULL;
550 if (!lp_ea_support(SNUM(conn))) {
551 return 0;
553 mem_ctx = talloc_stackframe();
555 /* If this is a stream fsp, then we need to instead find the
556 * estimated ea len from the main file, not the stream
557 * (streams cannot have EAs), but the estimate isn't just 0 in
558 * this case! */
559 if (is_ntfs_stream_smb_fname(smb_fname)) {
560 fsp = NULL;
562 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
563 if(conn->sconn->using_smb2) {
564 NTSTATUS status;
565 unsigned int ret_data_size;
567 * We're going to be using fill_ea_chained_buffer() to
568 * marshall EA's - this size is significantly larger
569 * than the SMB1 buffer. Re-calculate the size without
570 * marshalling.
572 status = fill_ea_chained_buffer(mem_ctx,
573 NULL,
575 &ret_data_size,
576 conn,
577 ea_list);
578 if (!NT_STATUS_IS_OK(status)) {
579 ret_data_size = 0;
581 total_ea_len = ret_data_size;
583 TALLOC_FREE(mem_ctx);
584 return total_ea_len;
587 /****************************************************************************
588 Ensure the EA name is case insensitive by matching any existing EA name.
589 ****************************************************************************/
591 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
593 size_t total_ea_len;
594 TALLOC_CTX *mem_ctx = talloc_tos();
595 struct ea_list *ea_list;
596 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
597 if (!NT_STATUS_IS_OK(status)) {
598 return;
601 for (; ea_list; ea_list = ea_list->next) {
602 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
603 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
604 &unix_ea_name[5], ea_list->ea.name));
605 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
606 break;
611 /****************************************************************************
612 Set or delete an extended attribute.
613 ****************************************************************************/
615 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
616 const struct smb_filename *smb_fname, struct ea_list *ea_list)
618 NTSTATUS status;
619 char *fname = NULL;
621 if (!lp_ea_support(SNUM(conn))) {
622 return NT_STATUS_EAS_NOT_SUPPORTED;
625 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
626 if (!NT_STATUS_IS_OK(status)) {
627 return status;
630 /* Setting EAs on streams isn't supported. */
631 if (is_ntfs_stream_smb_fname(smb_fname)) {
632 return NT_STATUS_INVALID_PARAMETER;
636 * Filter out invalid Windows EA names - before
637 * we set *any* of them.
640 if (ea_list_has_invalid_name(ea_list)) {
641 return STATUS_INVALID_EA_NAME;
644 fname = smb_fname->base_name;
646 for (;ea_list; ea_list = ea_list->next) {
647 int ret;
648 fstring unix_ea_name;
650 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
651 fstrcat(unix_ea_name, ea_list->ea.name);
653 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
655 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
657 if (samba_private_attr_name(unix_ea_name)) {
658 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
659 return NT_STATUS_ACCESS_DENIED;
662 if (ea_list->ea.value.length == 0) {
663 /* Remove the attribute. */
664 if (fsp && (fsp->fh->fd != -1)) {
665 DEBUG(10,("set_ea: deleting ea name %s on "
666 "file %s by file descriptor.\n",
667 unix_ea_name, fsp_str_dbg(fsp)));
668 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
669 } else {
670 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
671 unix_ea_name, fname));
672 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
674 #ifdef ENOATTR
675 /* Removing a non existent attribute always succeeds. */
676 if (ret == -1 && errno == ENOATTR) {
677 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
678 unix_ea_name));
679 ret = 0;
681 #endif
682 } else {
683 if (fsp && (fsp->fh->fd != -1)) {
684 DEBUG(10,("set_ea: setting ea name %s on file "
685 "%s by file descriptor.\n",
686 unix_ea_name, fsp_str_dbg(fsp)));
687 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
688 ea_list->ea.value.data, ea_list->ea.value.length, 0);
689 } else {
690 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
691 unix_ea_name, fname));
692 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
693 ea_list->ea.value.data, ea_list->ea.value.length, 0);
697 if (ret == -1) {
698 #ifdef ENOTSUP
699 if (errno == ENOTSUP) {
700 return NT_STATUS_EAS_NOT_SUPPORTED;
702 #endif
703 return map_nt_error_from_unix(errno);
707 return NT_STATUS_OK;
709 /****************************************************************************
710 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
711 ****************************************************************************/
713 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
715 struct ea_list *ea_list_head = NULL;
716 size_t converted_size, offset = 0;
718 while (offset + 2 < data_size) {
719 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
720 unsigned int namelen = CVAL(pdata,offset);
722 offset++; /* Go past the namelen byte. */
724 /* integer wrap paranioa. */
725 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
726 (offset > data_size) || (namelen > data_size) ||
727 (offset + namelen >= data_size)) {
728 break;
730 /* Ensure the name is null terminated. */
731 if (pdata[offset + namelen] != '\0') {
732 return NULL;
734 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
735 &converted_size)) {
736 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
737 "failed: %s", strerror(errno)));
739 if (!eal->ea.name) {
740 return NULL;
743 offset += (namelen + 1); /* Go past the name + terminating zero. */
744 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
745 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
748 return ea_list_head;
751 /****************************************************************************
752 Read one EA list entry from the buffer.
753 ****************************************************************************/
755 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
757 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
758 uint16 val_len;
759 unsigned int namelen;
760 size_t converted_size;
762 if (!eal) {
763 return NULL;
766 if (data_size < 6) {
767 return NULL;
770 eal->ea.flags = CVAL(pdata,0);
771 namelen = CVAL(pdata,1);
772 val_len = SVAL(pdata,2);
774 if (4 + namelen + 1 + val_len > data_size) {
775 return NULL;
778 /* Ensure the name is null terminated. */
779 if (pdata[namelen + 4] != '\0') {
780 return NULL;
782 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
783 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
784 strerror(errno)));
786 if (!eal->ea.name) {
787 return NULL;
790 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
791 if (!eal->ea.value.data) {
792 return NULL;
795 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
797 /* Ensure we're null terminated just in case we print the value. */
798 eal->ea.value.data[val_len] = '\0';
799 /* But don't count the null. */
800 eal->ea.value.length--;
802 if (pbytes_used) {
803 *pbytes_used = 4 + namelen + 1 + val_len;
806 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
807 dump_data(10, eal->ea.value.data, eal->ea.value.length);
809 return eal;
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
818 struct ea_list *ea_list_head = NULL;
819 size_t offset = 0;
820 size_t bytes_used = 0;
822 while (offset < data_size) {
823 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
825 if (!eal) {
826 return NULL;
829 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
830 offset += bytes_used;
833 return ea_list_head;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list *ealist)
842 fstring dos_ea_name;
843 struct ea_list *listp;
844 size_t ret = 0;
846 for (listp = ealist; listp; listp = listp->next) {
847 push_ascii_fstring(dos_ea_name, listp->ea.name);
848 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
850 /* Add on 4 for total length. */
851 if (ret) {
852 ret += 4;
855 return ret;
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
866 struct ea_list *nlistp, *flistp;
868 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
869 for (flistp = file_list; flistp; flistp = flistp->next) {
870 if (strequal(nlistp->ea.name, flistp->ea.name)) {
871 break;
875 if (flistp) {
876 /* Copy the data from this entry. */
877 nlistp->ea.flags = flistp->ea.flags;
878 nlistp->ea.value = flistp->ea.value;
879 } else {
880 /* Null entry. */
881 nlistp->ea.flags = 0;
882 ZERO_STRUCT(nlistp->ea.value);
886 *total_ea_len = ea_list_size(name_list);
887 return name_list;
890 /****************************************************************************
891 Send the required number of replies back.
892 We assume all fields other than the data fields are
893 set correctly for the type of call.
894 HACK ! Always assumes smb_setup field is zero.
895 ****************************************************************************/
897 void send_trans2_replies(connection_struct *conn,
898 struct smb_request *req,
899 NTSTATUS status,
900 const char *params,
901 int paramsize,
902 const char *pdata,
903 int datasize,
904 int max_data_bytes)
906 /* As we are using a protocol > LANMAN1 then the max_send
907 variable must have been set in the sessetupX call.
908 This takes precedence over the max_xmit field in the
909 global struct. These different max_xmit variables should
910 be merged as this is now too confusing */
912 int data_to_send = datasize;
913 int params_to_send = paramsize;
914 int useable_space;
915 const char *pp = params;
916 const char *pd = pdata;
917 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
918 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
919 int data_alignment_offset = 0;
920 bool overflow = False;
921 struct smbd_server_connection *sconn = req->sconn;
922 int max_send = sconn->smb1.sessions.max_send;
924 /* Modify the data_to_send and datasize and set the error if
925 we're trying to send more than max_data_bytes. We still send
926 the part of the packet(s) that fit. Strange, but needed
927 for OS/2. */
929 if (max_data_bytes > 0 && datasize > max_data_bytes) {
930 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
931 max_data_bytes, datasize ));
932 datasize = data_to_send = max_data_bytes;
933 overflow = True;
936 /* If there genuinely are no parameters or data to send just send the empty packet */
938 if(params_to_send == 0 && data_to_send == 0) {
939 reply_outbuf(req, 10, 0);
940 if (NT_STATUS_V(status)) {
941 uint8_t eclass;
942 uint32_t ecode;
943 ntstatus_to_dos(status, &eclass, &ecode);
944 error_packet_set((char *)req->outbuf,
945 eclass, ecode, status,
946 __LINE__,__FILE__);
948 show_msg((char *)req->outbuf);
949 if (!srv_send_smb(sconn,
950 (char *)req->outbuf,
951 true, req->seqnum+1,
952 IS_CONN_ENCRYPTED(conn),
953 &req->pcd)) {
954 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
956 TALLOC_FREE(req->outbuf);
957 return;
960 /* When sending params and data ensure that both are nicely aligned */
961 /* Only do this alignment when there is also data to send - else
962 can cause NT redirector problems. */
964 if (((params_to_send % 4) != 0) && (data_to_send != 0))
965 data_alignment_offset = 4 - (params_to_send % 4);
967 /* Space is bufsize minus Netbios over TCP header minus SMB header */
968 /* The alignment_offset is to align the param bytes on an even byte
969 boundary. NT 4.0 Beta needs this to work correctly. */
971 useable_space = max_send - (smb_size
972 + 2 * 10 /* wct */
973 + alignment_offset
974 + data_alignment_offset);
976 if (useable_space < 0) {
977 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
978 "= %d!!!", useable_space));
979 exit_server_cleanly("send_trans2_replies: Not enough space");
982 while (params_to_send || data_to_send) {
983 /* Calculate whether we will totally or partially fill this packet */
985 total_sent_thistime = params_to_send + data_to_send;
987 /* We can never send more than useable_space */
989 * Note that 'useable_space' does not include the alignment offsets,
990 * but we must include the alignment offsets in the calculation of
991 * the length of the data we send over the wire, as the alignment offsets
992 * are sent here. Fix from Marc_Jacobsen@hp.com.
995 total_sent_thistime = MIN(total_sent_thistime, useable_space);
997 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
998 + data_alignment_offset);
1000 /* Set total params and data to be sent */
1001 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1002 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1004 /* Calculate how many parameters and data we can fit into
1005 * this packet. Parameters get precedence
1008 params_sent_thistime = MIN(params_to_send,useable_space);
1009 data_sent_thistime = useable_space - params_sent_thistime;
1010 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1012 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1014 /* smb_proff is the offset from the start of the SMB header to the
1015 parameter bytes, however the first 4 bytes of outbuf are
1016 the Netbios over TCP header. Thus use smb_base() to subtract
1017 them from the calculation */
1019 SSVAL(req->outbuf,smb_proff,
1020 ((smb_buf(req->outbuf)+alignment_offset)
1021 - smb_base(req->outbuf)));
1023 if(params_sent_thistime == 0)
1024 SSVAL(req->outbuf,smb_prdisp,0);
1025 else
1026 /* Absolute displacement of param bytes sent in this packet */
1027 SSVAL(req->outbuf,smb_prdisp,pp - params);
1029 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1030 if(data_sent_thistime == 0) {
1031 SSVAL(req->outbuf,smb_droff,0);
1032 SSVAL(req->outbuf,smb_drdisp, 0);
1033 } else {
1034 /* The offset of the data bytes is the offset of the
1035 parameter bytes plus the number of parameters being sent this time */
1036 SSVAL(req->outbuf, smb_droff,
1037 ((smb_buf(req->outbuf)+alignment_offset)
1038 - smb_base(req->outbuf))
1039 + params_sent_thistime + data_alignment_offset);
1040 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1043 /* Initialize the padding for alignment */
1045 if (alignment_offset != 0) {
1046 memset(smb_buf(req->outbuf), 0, alignment_offset);
1049 /* Copy the param bytes into the packet */
1051 if(params_sent_thistime) {
1052 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1053 params_sent_thistime);
1056 /* Copy in the data bytes */
1057 if(data_sent_thistime) {
1058 if (data_alignment_offset != 0) {
1059 memset((smb_buf(req->outbuf)+alignment_offset+
1060 params_sent_thistime), 0,
1061 data_alignment_offset);
1063 memcpy(smb_buf(req->outbuf)+alignment_offset
1064 +params_sent_thistime+data_alignment_offset,
1065 pd,data_sent_thistime);
1068 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1069 params_sent_thistime, data_sent_thistime, useable_space));
1070 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1071 params_to_send, data_to_send, paramsize, datasize));
1073 if (overflow) {
1074 error_packet_set((char *)req->outbuf,
1075 ERRDOS,ERRbufferoverflow,
1076 STATUS_BUFFER_OVERFLOW,
1077 __LINE__,__FILE__);
1078 } else if (NT_STATUS_V(status)) {
1079 uint8_t eclass;
1080 uint32_t ecode;
1081 ntstatus_to_dos(status, &eclass, &ecode);
1082 error_packet_set((char *)req->outbuf,
1083 eclass, ecode, status,
1084 __LINE__,__FILE__);
1087 /* Send the packet */
1088 show_msg((char *)req->outbuf);
1089 if (!srv_send_smb(sconn,
1090 (char *)req->outbuf,
1091 true, req->seqnum+1,
1092 IS_CONN_ENCRYPTED(conn),
1093 &req->pcd))
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req->outbuf);
1098 pp += params_sent_thistime;
1099 pd += data_sent_thistime;
1101 params_to_send -= params_sent_thistime;
1102 data_to_send -= data_sent_thistime;
1104 /* Sanity check */
1105 if(params_to_send < 0 || data_to_send < 0) {
1106 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1107 params_to_send, data_to_send));
1108 return;
1112 return;
1115 /****************************************************************************
1116 Reply to a TRANSACT2_OPEN.
1117 ****************************************************************************/
1119 static void call_trans2open(connection_struct *conn,
1120 struct smb_request *req,
1121 char **pparams, int total_params,
1122 char **ppdata, int total_data,
1123 unsigned int max_data_bytes)
1125 struct smb_filename *smb_fname = NULL;
1126 char *params = *pparams;
1127 char *pdata = *ppdata;
1128 int deny_mode;
1129 int32 open_attr;
1130 bool oplock_request;
1131 #if 0
1132 bool return_additional_info;
1133 int16 open_sattr;
1134 time_t open_time;
1135 #endif
1136 int open_ofun;
1137 uint32 open_size;
1138 char *pname;
1139 char *fname = NULL;
1140 off_t size=0;
1141 int fattr=0,mtime=0;
1142 SMB_INO_T inode = 0;
1143 int smb_action = 0;
1144 files_struct *fsp;
1145 struct ea_list *ea_list = NULL;
1146 uint16 flags = 0;
1147 NTSTATUS status;
1148 uint32 access_mask;
1149 uint32 share_mode;
1150 uint32 create_disposition;
1151 uint32 create_options = 0;
1152 uint32_t private_flags = 0;
1153 TALLOC_CTX *ctx = talloc_tos();
1156 * Ensure we have enough parameters to perform the operation.
1159 if (total_params < 29) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 goto out;
1164 flags = SVAL(params, 0);
1165 deny_mode = SVAL(params, 2);
1166 open_attr = SVAL(params,6);
1167 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1168 if (oplock_request) {
1169 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1172 #if 0
1173 return_additional_info = BITSETW(params,0);
1174 open_sattr = SVAL(params, 4);
1175 open_time = make_unix_date3(params+8);
1176 #endif
1177 open_ofun = SVAL(params,12);
1178 open_size = IVAL(params,14);
1179 pname = &params[28];
1181 if (IS_IPC(conn)) {
1182 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1183 goto out;
1186 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1187 total_params - 28, STR_TERMINATE,
1188 &status);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 reply_nterror(req, status);
1191 goto out;
1194 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1195 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1196 (unsigned int)open_ofun, open_size));
1198 status = filename_convert(ctx,
1199 conn,
1200 req->flags2 & FLAGS2_DFS_PATHNAMES,
1201 fname,
1203 NULL,
1204 &smb_fname);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1207 reply_botherror(req,
1208 NT_STATUS_PATH_NOT_COVERED,
1209 ERRSRV, ERRbadpath);
1210 goto out;
1212 reply_nterror(req, status);
1213 goto out;
1216 if (open_ofun == 0) {
1217 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1218 goto out;
1221 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1222 open_ofun,
1223 &access_mask, &share_mode,
1224 &create_disposition,
1225 &create_options,
1226 &private_flags)) {
1227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1228 goto out;
1231 /* Any data in this call is an EA list. */
1232 if (total_data && (total_data != 4)) {
1233 if (total_data < 10) {
1234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1235 goto out;
1238 if (IVAL(pdata,0) > total_data) {
1239 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1240 IVAL(pdata,0), (unsigned int)total_data));
1241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1242 goto out;
1245 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1246 total_data - 4);
1247 if (!ea_list) {
1248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1249 goto out;
1252 if (!lp_ea_support(SNUM(conn))) {
1253 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1254 goto out;
1257 if (ea_list_has_invalid_name(ea_list)) {
1258 int param_len = 30;
1259 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1260 if(*pparams == NULL ) {
1261 reply_nterror(req, NT_STATUS_NO_MEMORY);
1262 goto out;
1264 params = *pparams;
1265 memset(params, '\0', param_len);
1266 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1267 params, param_len, NULL, 0, max_data_bytes);
1268 goto out;
1272 status = SMB_VFS_CREATE_FILE(
1273 conn, /* conn */
1274 req, /* req */
1275 0, /* root_dir_fid */
1276 smb_fname, /* fname */
1277 access_mask, /* access_mask */
1278 share_mode, /* share_access */
1279 create_disposition, /* create_disposition*/
1280 create_options, /* create_options */
1281 open_attr, /* file_attributes */
1282 oplock_request, /* oplock_request */
1283 open_size, /* allocation_size */
1284 private_flags,
1285 NULL, /* sd */
1286 ea_list, /* ea_list */
1287 &fsp, /* result */
1288 &smb_action); /* psbuf */
1290 if (!NT_STATUS_IS_OK(status)) {
1291 if (open_was_deferred(req->sconn, req->mid)) {
1292 /* We have re-scheduled this call. */
1293 goto out;
1295 reply_openerror(req, status);
1296 goto out;
1299 size = get_file_size_stat(&smb_fname->st);
1300 fattr = dos_mode(conn, smb_fname);
1301 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1302 inode = smb_fname->st.st_ex_ino;
1303 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1304 close_file(req, fsp, ERROR_CLOSE);
1305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1306 goto out;
1309 /* Realloc the size of parameters and data we will return */
1310 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1311 if(*pparams == NULL ) {
1312 reply_nterror(req, NT_STATUS_NO_MEMORY);
1313 goto out;
1315 params = *pparams;
1317 SSVAL(params,0,fsp->fnum);
1318 SSVAL(params,2,fattr);
1319 srv_put_dos_date2(params,4, mtime);
1320 SIVAL(params,8, (uint32)size);
1321 SSVAL(params,12,deny_mode);
1322 SSVAL(params,14,0); /* open_type - file or directory. */
1323 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1325 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1326 smb_action |= EXTENDED_OPLOCK_GRANTED;
1329 SSVAL(params,18,smb_action);
1332 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1334 SIVAL(params,20,inode);
1335 SSVAL(params,24,0); /* Padding. */
1336 if (flags & 8) {
1337 uint32 ea_size = estimate_ea_size(conn, fsp,
1338 smb_fname);
1339 SIVAL(params, 26, ea_size);
1340 } else {
1341 SIVAL(params, 26, 0);
1344 /* Send the required number of replies */
1345 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1346 out:
1347 TALLOC_FREE(smb_fname);
1350 /*********************************************************
1351 Routine to check if a given string matches exactly.
1352 as a special case a mask of "." does NOT match. That
1353 is required for correct wildcard semantics
1354 Case can be significant or not.
1355 **********************************************************/
1357 static bool exact_match(bool has_wild,
1358 bool case_sensitive,
1359 const char *str,
1360 const char *mask)
1362 if (mask[0] == '.' && mask[1] == 0) {
1363 return false;
1366 if (has_wild) {
1367 return false;
1370 if (case_sensitive) {
1371 return strcmp(str,mask)==0;
1372 } else {
1373 return strcasecmp_m(str,mask) == 0;
1377 /****************************************************************************
1378 Return the filetype for UNIX extensions.
1379 ****************************************************************************/
1381 static uint32 unix_filetype(mode_t mode)
1383 if(S_ISREG(mode))
1384 return UNIX_TYPE_FILE;
1385 else if(S_ISDIR(mode))
1386 return UNIX_TYPE_DIR;
1387 #ifdef S_ISLNK
1388 else if(S_ISLNK(mode))
1389 return UNIX_TYPE_SYMLINK;
1390 #endif
1391 #ifdef S_ISCHR
1392 else if(S_ISCHR(mode))
1393 return UNIX_TYPE_CHARDEV;
1394 #endif
1395 #ifdef S_ISBLK
1396 else if(S_ISBLK(mode))
1397 return UNIX_TYPE_BLKDEV;
1398 #endif
1399 #ifdef S_ISFIFO
1400 else if(S_ISFIFO(mode))
1401 return UNIX_TYPE_FIFO;
1402 #endif
1403 #ifdef S_ISSOCK
1404 else if(S_ISSOCK(mode))
1405 return UNIX_TYPE_SOCKET;
1406 #endif
1408 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1409 return UNIX_TYPE_UNKNOWN;
1412 /****************************************************************************
1413 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1414 ****************************************************************************/
1416 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1418 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1419 const SMB_STRUCT_STAT *psbuf,
1420 uint32 perms,
1421 enum perm_type ptype,
1422 mode_t *ret_perms)
1424 mode_t ret = 0;
1426 if (perms == SMB_MODE_NO_CHANGE) {
1427 if (!VALID_STAT(*psbuf)) {
1428 return NT_STATUS_INVALID_PARAMETER;
1429 } else {
1430 *ret_perms = psbuf->st_ex_mode;
1431 return NT_STATUS_OK;
1435 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1436 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1437 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1438 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1439 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1440 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1441 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1442 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1443 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1444 #ifdef S_ISVTX
1445 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1446 #endif
1447 #ifdef S_ISGID
1448 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1449 #endif
1450 #ifdef S_ISUID
1451 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1452 #endif
1454 switch (ptype) {
1455 case PERM_NEW_FILE:
1456 case PERM_EXISTING_FILE:
1457 /* Apply mode mask */
1458 ret &= lp_create_mask(SNUM(conn));
1459 /* Add in force bits */
1460 ret |= lp_force_create_mode(SNUM(conn));
1461 break;
1462 case PERM_NEW_DIR:
1463 case PERM_EXISTING_DIR:
1464 ret &= lp_dir_mask(SNUM(conn));
1465 /* Add in force bits */
1466 ret |= lp_force_dir_mode(SNUM(conn));
1467 break;
1470 *ret_perms = ret;
1471 return NT_STATUS_OK;
1474 /****************************************************************************
1475 Needed to show the msdfs symlinks as directories. Modifies psbuf
1476 to be a directory if it's a msdfs link.
1477 ****************************************************************************/
1479 static bool check_msdfs_link(connection_struct *conn,
1480 const char *pathname,
1481 SMB_STRUCT_STAT *psbuf)
1483 int saved_errno = errno;
1484 if(lp_host_msdfs() &&
1485 lp_msdfs_root(SNUM(conn)) &&
1486 is_msdfs_link(conn, pathname, psbuf)) {
1488 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1489 "as a directory\n",
1490 pathname));
1491 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1492 errno = saved_errno;
1493 return true;
1495 errno = saved_errno;
1496 return false;
1500 /****************************************************************************
1501 Get a level dependent lanman2 dir entry.
1502 ****************************************************************************/
1504 struct smbd_dirptr_lanman2_state {
1505 connection_struct *conn;
1506 uint32_t info_level;
1507 bool check_mangled_names;
1508 bool has_wild;
1509 bool got_exact_match;
1512 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1513 void *private_data,
1514 const char *dname,
1515 const char *mask,
1516 char **_fname)
1518 struct smbd_dirptr_lanman2_state *state =
1519 (struct smbd_dirptr_lanman2_state *)private_data;
1520 bool ok;
1521 char mangled_name[13]; /* mangled 8.3 name. */
1522 bool got_match;
1523 const char *fname;
1525 /* Mangle fname if it's an illegal name. */
1526 if (mangle_must_mangle(dname, state->conn->params)) {
1527 ok = name_to_8_3(dname, mangled_name,
1528 true, state->conn->params);
1529 if (!ok) {
1530 return false;
1532 fname = mangled_name;
1533 } else {
1534 fname = dname;
1537 got_match = exact_match(state->has_wild,
1538 state->conn->case_sensitive,
1539 fname, mask);
1540 state->got_exact_match = got_match;
1541 if (!got_match) {
1542 got_match = mask_match(fname, mask,
1543 state->conn->case_sensitive);
1546 if(!got_match && state->check_mangled_names &&
1547 !mangle_is_8_3(fname, false, state->conn->params)) {
1549 * It turns out that NT matches wildcards against
1550 * both long *and* short names. This may explain some
1551 * of the wildcard wierdness from old DOS clients
1552 * that some people have been seeing.... JRA.
1554 /* Force the mangling into 8.3. */
1555 ok = name_to_8_3(fname, mangled_name,
1556 false, state->conn->params);
1557 if (!ok) {
1558 return false;
1561 got_match = exact_match(state->has_wild,
1562 state->conn->case_sensitive,
1563 mangled_name, mask);
1564 state->got_exact_match = got_match;
1565 if (!got_match) {
1566 got_match = mask_match(mangled_name, mask,
1567 state->conn->case_sensitive);
1571 if (!got_match) {
1572 return false;
1575 *_fname = talloc_strdup(ctx, fname);
1576 if (*_fname == NULL) {
1577 return false;
1580 return true;
1583 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1584 void *private_data,
1585 struct smb_filename *smb_fname,
1586 uint32_t *_mode)
1588 struct smbd_dirptr_lanman2_state *state =
1589 (struct smbd_dirptr_lanman2_state *)private_data;
1590 bool ms_dfs_link = false;
1591 uint32_t mode = 0;
1593 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1594 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1595 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1596 "Couldn't lstat [%s] (%s)\n",
1597 smb_fname_str_dbg(smb_fname),
1598 strerror(errno)));
1599 return false;
1601 } else if (!VALID_STAT(smb_fname->st) &&
1602 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1603 /* Needed to show the msdfs symlinks as
1604 * directories */
1606 ms_dfs_link = check_msdfs_link(state->conn,
1607 smb_fname->base_name,
1608 &smb_fname->st);
1609 if (!ms_dfs_link) {
1610 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1611 "Couldn't stat [%s] (%s)\n",
1612 smb_fname_str_dbg(smb_fname),
1613 strerror(errno)));
1614 return false;
1618 if (ms_dfs_link) {
1619 mode = dos_mode_msdfs(state->conn, smb_fname);
1620 } else {
1621 mode = dos_mode(state->conn, smb_fname);
1624 *_mode = mode;
1625 return true;
1628 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1629 connection_struct *conn,
1630 uint16_t flags2,
1631 uint32_t info_level,
1632 struct ea_list *name_list,
1633 bool check_mangled_names,
1634 bool requires_resume_key,
1635 uint32_t mode,
1636 const char *fname,
1637 const struct smb_filename *smb_fname,
1638 int space_remaining,
1639 uint8_t align,
1640 bool do_pad,
1641 char *base_data,
1642 char **ppdata,
1643 char *end_data,
1644 bool *out_of_space,
1645 uint64_t *last_entry_off)
1647 char *p, *q, *pdata = *ppdata;
1648 uint32_t reskey=0;
1649 uint64_t file_size = 0;
1650 uint64_t allocation_size = 0;
1651 uint64_t file_index = 0;
1652 uint32_t len;
1653 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1654 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1655 char *nameptr;
1656 char *last_entry_ptr;
1657 bool was_8_3;
1658 int off;
1659 int pad = 0;
1661 *out_of_space = false;
1663 ZERO_STRUCT(mdate_ts);
1664 ZERO_STRUCT(adate_ts);
1665 ZERO_STRUCT(create_date_ts);
1666 ZERO_STRUCT(cdate_ts);
1668 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1669 file_size = get_file_size_stat(&smb_fname->st);
1671 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1673 file_index = get_FileIndex(conn, &smb_fname->st);
1675 mdate_ts = smb_fname->st.st_ex_mtime;
1676 adate_ts = smb_fname->st.st_ex_atime;
1677 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1678 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1680 if (lp_dos_filetime_resolution(SNUM(conn))) {
1681 dos_filetime_timespec(&create_date_ts);
1682 dos_filetime_timespec(&mdate_ts);
1683 dos_filetime_timespec(&adate_ts);
1684 dos_filetime_timespec(&cdate_ts);
1687 create_date = convert_timespec_to_time_t(create_date_ts);
1688 mdate = convert_timespec_to_time_t(mdate_ts);
1689 adate = convert_timespec_to_time_t(adate_ts);
1691 /* align the record */
1692 SMB_ASSERT(align >= 1);
1694 off = (int)PTR_DIFF(pdata, base_data);
1695 pad = (off + (align-1)) & ~(align-1);
1696 pad -= off;
1698 if (pad && pad > space_remaining) {
1699 *out_of_space = true;
1700 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1701 "for padding (wanted %u, had %d)\n",
1702 (unsigned int)pad,
1703 space_remaining ));
1704 return false; /* Not finished - just out of space */
1707 off += pad;
1708 /* initialize padding to 0 */
1709 if (pad) {
1710 memset(pdata, 0, pad);
1712 space_remaining -= pad;
1714 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1715 space_remaining ));
1717 pdata += pad;
1718 p = pdata;
1719 last_entry_ptr = p;
1721 pad = 0;
1722 off = 0;
1724 switch (info_level) {
1725 case SMB_FIND_INFO_STANDARD:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1727 if(requires_resume_key) {
1728 SIVAL(p,0,reskey);
1729 p += 4;
1731 srv_put_dos_date2(p,0,create_date);
1732 srv_put_dos_date2(p,4,adate);
1733 srv_put_dos_date2(p,8,mdate);
1734 SIVAL(p,12,(uint32)file_size);
1735 SIVAL(p,16,(uint32)allocation_size);
1736 SSVAL(p,20,mode);
1737 p += 23;
1738 nameptr = p;
1739 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1740 p += ucs2_align(base_data, p, 0);
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE);
1745 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1746 if (len > 2) {
1747 SCVAL(nameptr, -1, len - 2);
1748 } else {
1749 SCVAL(nameptr, -1, 0);
1751 } else {
1752 if (len > 1) {
1753 SCVAL(nameptr, -1, len - 1);
1754 } else {
1755 SCVAL(nameptr, -1, 0);
1758 p += len;
1759 break;
1761 case SMB_FIND_EA_SIZE:
1762 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1763 if (requires_resume_key) {
1764 SIVAL(p,0,reskey);
1765 p += 4;
1767 srv_put_dos_date2(p,0,create_date);
1768 srv_put_dos_date2(p,4,adate);
1769 srv_put_dos_date2(p,8,mdate);
1770 SIVAL(p,12,(uint32)file_size);
1771 SIVAL(p,16,(uint32)allocation_size);
1772 SSVAL(p,20,mode);
1774 unsigned int ea_size = estimate_ea_size(conn, NULL,
1775 smb_fname);
1776 SIVAL(p,22,ea_size); /* Extended attributes */
1778 p += 27;
1779 nameptr = p - 1;
1780 len = srvstr_push(base_data, flags2,
1781 p, fname, PTR_DIFF(end_data, p),
1782 STR_TERMINATE | STR_NOALIGN);
1783 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1784 if (len > 2) {
1785 len -= 2;
1786 } else {
1787 len = 0;
1789 } else {
1790 if (len > 1) {
1791 len -= 1;
1792 } else {
1793 len = 0;
1796 SCVAL(nameptr,0,len);
1797 p += len;
1798 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1799 break;
1801 case SMB_FIND_EA_LIST:
1803 struct ea_list *file_list = NULL;
1804 size_t ea_len = 0;
1805 NTSTATUS status;
1807 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1808 if (!name_list) {
1809 return false;
1811 if (requires_resume_key) {
1812 SIVAL(p,0,reskey);
1813 p += 4;
1815 srv_put_dos_date2(p,0,create_date);
1816 srv_put_dos_date2(p,4,adate);
1817 srv_put_dos_date2(p,8,mdate);
1818 SIVAL(p,12,(uint32)file_size);
1819 SIVAL(p,16,(uint32)allocation_size);
1820 SSVAL(p,20,mode);
1821 p += 22; /* p now points to the EA area. */
1823 status = get_ea_list_from_file(ctx, conn, NULL,
1824 smb_fname,
1825 &ea_len, &file_list);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 file_list = NULL;
1829 name_list = ea_list_union(name_list, file_list, &ea_len);
1831 /* We need to determine if this entry will fit in the space available. */
1832 /* Max string size is 255 bytes. */
1833 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1834 *out_of_space = true;
1835 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1836 "(wanted %u, had %d)\n",
1837 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1838 space_remaining ));
1839 return False; /* Not finished - just out of space */
1842 /* Push the ea_data followed by the name. */
1843 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1844 nameptr = p;
1845 len = srvstr_push(base_data, flags2,
1846 p + 1, fname, PTR_DIFF(end_data, p+1),
1847 STR_TERMINATE | STR_NOALIGN);
1848 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1849 if (len > 2) {
1850 len -= 2;
1851 } else {
1852 len = 0;
1854 } else {
1855 if (len > 1) {
1856 len -= 1;
1857 } else {
1858 len = 0;
1861 SCVAL(nameptr,0,len);
1862 p += len + 1;
1863 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1864 break;
1867 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1868 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1869 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1870 p += 4;
1871 SIVAL(p,0,reskey); p += 4;
1872 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1876 SOFF_T(p,0,file_size); p += 8;
1877 SOFF_T(p,0,allocation_size); p += 8;
1878 SIVAL(p,0,mode); p += 4;
1879 q = p; p += 4; /* q is placeholder for name length. */
1881 unsigned int ea_size = estimate_ea_size(conn, NULL,
1882 smb_fname);
1883 SIVAL(p,0,ea_size); /* Extended attributes */
1884 p += 4;
1886 /* Clear the short name buffer. This is
1887 * IMPORTANT as not doing so will trigger
1888 * a Win2k client bug. JRA.
1890 if (!was_8_3 && check_mangled_names) {
1891 char mangled_name[13]; /* mangled 8.3 name. */
1892 if (!name_to_8_3(fname,mangled_name,True,
1893 conn->params)) {
1894 /* Error - mangle failed ! */
1895 memset(mangled_name,'\0',12);
1897 mangled_name[12] = 0;
1898 len = srvstr_push(base_data, flags2,
1899 p+2, mangled_name, 24,
1900 STR_UPPER|STR_UNICODE);
1901 if (len < 24) {
1902 memset(p + 2 + len,'\0',24 - len);
1904 SSVAL(p, 0, len);
1905 } else {
1906 memset(p,'\0',26);
1908 p += 2 + 24;
1909 len = srvstr_push(base_data, flags2, p,
1910 fname, PTR_DIFF(end_data, p),
1911 STR_TERMINATE_ASCII);
1912 SIVAL(q,0,len);
1913 p += len;
1915 len = PTR_DIFF(p, pdata);
1916 pad = (len + (align-1)) & ~(align-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1922 SIVAL(pdata,0,pad);
1924 * set padding to zero
1926 if (do_pad) {
1927 memset(p, 0, pad - len);
1928 p = pdata + pad;
1929 } else {
1930 p = pdata + len;
1932 break;
1934 case SMB_FIND_FILE_DIRECTORY_INFO:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1936 p += 4;
1937 SIVAL(p,0,reskey); p += 4;
1938 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1939 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1940 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1941 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1942 SOFF_T(p,0,file_size); p += 8;
1943 SOFF_T(p,0,allocation_size); p += 8;
1944 SIVAL(p,0,mode); p += 4;
1945 len = srvstr_push(base_data, flags2,
1946 p + 4, fname, PTR_DIFF(end_data, p+4),
1947 STR_TERMINATE_ASCII);
1948 SIVAL(p,0,len);
1949 p += 4 + len;
1951 len = PTR_DIFF(p, pdata);
1952 pad = (len + (align-1)) & ~(align-1);
1954 * offset to the next entry, the caller
1955 * will overwrite it for the last entry
1956 * that's why we always include the padding
1958 SIVAL(pdata,0,pad);
1960 * set padding to zero
1962 if (do_pad) {
1963 memset(p, 0, pad - len);
1964 p = pdata + pad;
1965 } else {
1966 p = pdata + len;
1968 break;
1970 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1971 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1972 p += 4;
1973 SIVAL(p,0,reskey); p += 4;
1974 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1975 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1976 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1977 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1978 SOFF_T(p,0,file_size); p += 8;
1979 SOFF_T(p,0,allocation_size); p += 8;
1980 SIVAL(p,0,mode); p += 4;
1981 q = p; p += 4; /* q is placeholder for name length. */
1983 unsigned int ea_size = estimate_ea_size(conn, NULL,
1984 smb_fname);
1985 SIVAL(p,0,ea_size); /* Extended attributes */
1986 p +=4;
1988 len = srvstr_push(base_data, flags2, p,
1989 fname, PTR_DIFF(end_data, p),
1990 STR_TERMINATE_ASCII);
1991 SIVAL(q, 0, len);
1992 p += len;
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2001 SIVAL(pdata,0,pad);
2003 * set padding to zero
2005 if (do_pad) {
2006 memset(p, 0, pad - len);
2007 p = pdata + pad;
2008 } else {
2009 p = pdata + len;
2011 break;
2013 case SMB_FIND_FILE_NAMES_INFO:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2015 p += 4;
2016 SIVAL(p,0,reskey); p += 4;
2017 p += 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 len = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2022 STR_TERMINATE_ASCII);
2023 SIVAL(p, -4, len);
2024 p += len;
2026 len = PTR_DIFF(p, pdata);
2027 pad = (len + (align-1)) & ~(align-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2033 SIVAL(pdata,0,pad);
2035 * set padding to zero
2037 if (do_pad) {
2038 memset(p, 0, pad - len);
2039 p = pdata + pad;
2040 } else {
2041 p = pdata + len;
2043 break;
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2047 p += 4;
2048 SIVAL(p,0,reskey); p += 4;
2049 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2051 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2053 SOFF_T(p,0,file_size); p += 8;
2054 SOFF_T(p,0,allocation_size); p += 8;
2055 SIVAL(p,0,mode); p += 4;
2056 q = p; p += 4; /* q is placeholder for name length. */
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2059 smb_fname);
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2061 p +=4;
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 len = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII);
2068 SIVAL(q, 0, len);
2069 p += len;
2071 len = PTR_DIFF(p, pdata);
2072 pad = (len + (align-1)) & ~(align-1);
2074 * offset to the next entry, the caller
2075 * will overwrite it for the last entry
2076 * that's why we always include the padding
2078 SIVAL(pdata,0,pad);
2080 * set padding to zero
2082 if (do_pad) {
2083 memset(p, 0, pad - len);
2084 p = pdata + pad;
2085 } else {
2086 p = pdata + len;
2088 break;
2090 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2092 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2093 p += 4;
2094 SIVAL(p,0,reskey); p += 4;
2095 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2096 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2097 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2098 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2099 SOFF_T(p,0,file_size); p += 8;
2100 SOFF_T(p,0,allocation_size); p += 8;
2101 SIVAL(p,0,mode); p += 4;
2102 q = p; p += 4; /* q is placeholder for name length */
2104 unsigned int ea_size = estimate_ea_size(conn, NULL,
2105 smb_fname);
2106 SIVAL(p,0,ea_size); /* Extended attributes */
2107 p +=4;
2109 /* Clear the short name buffer. This is
2110 * IMPORTANT as not doing so will trigger
2111 * a Win2k client bug. JRA.
2113 if (!was_8_3 && check_mangled_names) {
2114 char mangled_name[13]; /* mangled 8.3 name. */
2115 if (!name_to_8_3(fname,mangled_name,True,
2116 conn->params)) {
2117 /* Error - mangle failed ! */
2118 memset(mangled_name,'\0',12);
2120 mangled_name[12] = 0;
2121 len = srvstr_push(base_data, flags2,
2122 p+2, mangled_name, 24,
2123 STR_UPPER|STR_UNICODE);
2124 SSVAL(p, 0, len);
2125 if (len < 24) {
2126 memset(p + 2 + len,'\0',24 - len);
2128 SSVAL(p, 0, len);
2129 } else {
2130 memset(p,'\0',26);
2132 p += 26;
2133 SSVAL(p,0,0); p += 2; /* Reserved ? */
2134 SBVAL(p,0,file_index); p += 8;
2135 len = srvstr_push(base_data, flags2, p,
2136 fname, PTR_DIFF(end_data, p),
2137 STR_TERMINATE_ASCII);
2138 SIVAL(q,0,len);
2139 p += len;
2141 len = PTR_DIFF(p, pdata);
2142 pad = (len + (align-1)) & ~(align-1);
2144 * offset to the next entry, the caller
2145 * will overwrite it for the last entry
2146 * that's why we always include the padding
2148 SIVAL(pdata,0,pad);
2150 * set padding to zero
2152 if (do_pad) {
2153 memset(p, 0, pad - len);
2154 p = pdata + pad;
2155 } else {
2156 p = pdata + len;
2158 break;
2160 /* CIFS UNIX Extension. */
2162 case SMB_FIND_FILE_UNIX:
2163 case SMB_FIND_FILE_UNIX_INFO2:
2164 p+= 4;
2165 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2167 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2169 if (info_level == SMB_FIND_FILE_UNIX) {
2170 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2171 p = store_file_unix_basic(conn, p,
2172 NULL, &smb_fname->st);
2173 len = srvstr_push(base_data, flags2, p,
2174 fname, PTR_DIFF(end_data, p),
2175 STR_TERMINATE);
2176 } else {
2177 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2178 p = store_file_unix_basic_info2(conn, p,
2179 NULL, &smb_fname->st);
2180 nameptr = p;
2181 p += 4;
2182 len = srvstr_push(base_data, flags2, p, fname,
2183 PTR_DIFF(end_data, p), 0);
2184 SIVAL(nameptr, 0, len);
2187 p += len;
2189 len = PTR_DIFF(p, pdata);
2190 pad = (len + (align-1)) & ~(align-1);
2192 * offset to the next entry, the caller
2193 * will overwrite it for the last entry
2194 * that's why we always include the padding
2196 SIVAL(pdata,0,pad);
2198 * set padding to zero
2200 if (do_pad) {
2201 memset(p, 0, pad - len);
2202 p = pdata + pad;
2203 } else {
2204 p = pdata + len;
2206 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2208 break;
2210 default:
2211 return false;
2214 if (PTR_DIFF(p,pdata) > space_remaining) {
2215 *out_of_space = true;
2216 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2217 "(wanted %u, had %d)\n",
2218 (unsigned int)PTR_DIFF(p,pdata),
2219 space_remaining ));
2220 return false; /* Not finished - just out of space */
2223 /* Setup the last entry pointer, as an offset from base_data */
2224 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2225 /* Advance the data pointer to the next slot */
2226 *ppdata = p;
2228 return true;
2231 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2232 connection_struct *conn,
2233 struct dptr_struct *dirptr,
2234 uint16 flags2,
2235 const char *path_mask,
2236 uint32 dirtype,
2237 int info_level,
2238 int requires_resume_key,
2239 bool dont_descend,
2240 bool ask_sharemode,
2241 uint8_t align,
2242 bool do_pad,
2243 char **ppdata,
2244 char *base_data,
2245 char *end_data,
2246 int space_remaining,
2247 bool *out_of_space,
2248 bool *got_exact_match,
2249 int *_last_entry_off,
2250 struct ea_list *name_list)
2252 const char *p;
2253 const char *mask = NULL;
2254 long prev_dirpos = 0;
2255 uint32_t mode = 0;
2256 char *fname = NULL;
2257 struct smb_filename *smb_fname = NULL;
2258 struct smbd_dirptr_lanman2_state state;
2259 bool ok;
2260 uint64_t last_entry_off = 0;
2262 ZERO_STRUCT(state);
2263 state.conn = conn;
2264 state.info_level = info_level;
2265 state.check_mangled_names = lp_manglednames(conn->params);
2266 state.has_wild = dptr_has_wild(dirptr);
2267 state.got_exact_match = false;
2269 *out_of_space = false;
2270 *got_exact_match = false;
2272 p = strrchr_m(path_mask,'/');
2273 if(p != NULL) {
2274 if(p[1] == '\0') {
2275 mask = "*.*";
2276 } else {
2277 mask = p+1;
2279 } else {
2280 mask = path_mask;
2283 ok = smbd_dirptr_get_entry(ctx,
2284 dirptr,
2285 mask,
2286 dirtype,
2287 dont_descend,
2288 ask_sharemode,
2289 smbd_dirptr_lanman2_match_fn,
2290 smbd_dirptr_lanman2_mode_fn,
2291 &state,
2292 &fname,
2293 &smb_fname,
2294 &mode,
2295 &prev_dirpos);
2296 if (!ok) {
2297 return false;
2300 *got_exact_match = state.got_exact_match;
2302 ok = smbd_marshall_dir_entry(ctx,
2303 conn,
2304 flags2,
2305 info_level,
2306 name_list,
2307 state.check_mangled_names,
2308 requires_resume_key,
2309 mode,
2310 fname,
2311 smb_fname,
2312 space_remaining,
2313 align,
2314 do_pad,
2315 base_data,
2316 ppdata,
2317 end_data,
2318 out_of_space,
2319 &last_entry_off);
2320 TALLOC_FREE(fname);
2321 TALLOC_FREE(smb_fname);
2322 if (*out_of_space) {
2323 dptr_SeekDir(dirptr, prev_dirpos);
2324 return false;
2326 if (!ok) {
2327 return false;
2330 *_last_entry_off = last_entry_off;
2331 return true;
2334 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2335 connection_struct *conn,
2336 struct dptr_struct *dirptr,
2337 uint16 flags2,
2338 const char *path_mask,
2339 uint32 dirtype,
2340 int info_level,
2341 bool requires_resume_key,
2342 bool dont_descend,
2343 bool ask_sharemode,
2344 char **ppdata,
2345 char *base_data,
2346 char *end_data,
2347 int space_remaining,
2348 bool *out_of_space,
2349 bool *got_exact_match,
2350 int *last_entry_off,
2351 struct ea_list *name_list)
2353 uint8_t align = 4;
2354 const bool do_pad = true;
2356 if (info_level >= 1 && info_level <= 3) {
2357 /* No alignment on earlier info levels. */
2358 align = 1;
2361 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2362 path_mask, dirtype, info_level,
2363 requires_resume_key, dont_descend, ask_sharemode,
2364 align, do_pad,
2365 ppdata, base_data, end_data,
2366 space_remaining,
2367 out_of_space, got_exact_match,
2368 last_entry_off, name_list);
2371 /****************************************************************************
2372 Reply to a TRANS2_FINDFIRST.
2373 ****************************************************************************/
2375 static void call_trans2findfirst(connection_struct *conn,
2376 struct smb_request *req,
2377 char **pparams, int total_params,
2378 char **ppdata, int total_data,
2379 unsigned int max_data_bytes)
2381 /* We must be careful here that we don't return more than the
2382 allowed number of data bytes. If this means returning fewer than
2383 maxentries then so be it. We assume that the redirector has
2384 enough room for the fixed number of parameter bytes it has
2385 requested. */
2386 struct smb_filename *smb_dname = NULL;
2387 char *params = *pparams;
2388 char *pdata = *ppdata;
2389 char *data_end;
2390 uint32 dirtype;
2391 int maxentries;
2392 uint16 findfirst_flags;
2393 bool close_after_first;
2394 bool close_if_end;
2395 bool requires_resume_key;
2396 int info_level;
2397 char *directory = NULL;
2398 char *mask = NULL;
2399 char *p;
2400 int last_entry_off=0;
2401 int dptr_num = -1;
2402 int numentries = 0;
2403 int i;
2404 bool finished = False;
2405 bool dont_descend = False;
2406 bool out_of_space = False;
2407 int space_remaining;
2408 bool mask_contains_wcard = False;
2409 struct ea_list *ea_list = NULL;
2410 NTSTATUS ntstatus = NT_STATUS_OK;
2411 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2412 TALLOC_CTX *ctx = talloc_tos();
2413 struct dptr_struct *dirptr = NULL;
2414 struct smbd_server_connection *sconn = req->sconn;
2415 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2416 bool backup_priv = false;
2418 if (total_params < 13) {
2419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2420 goto out;
2423 dirtype = SVAL(params,0);
2424 maxentries = SVAL(params,2);
2425 findfirst_flags = SVAL(params,4);
2426 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2427 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2428 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2429 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2430 security_token_has_privilege(get_current_nttok(conn),
2431 SEC_PRIV_BACKUP));
2433 info_level = SVAL(params,6);
2435 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2436 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2437 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2438 (int)backup_priv,
2439 info_level, max_data_bytes));
2441 if (!maxentries) {
2442 /* W2K3 seems to treat zero as 1. */
2443 maxentries = 1;
2446 switch (info_level) {
2447 case SMB_FIND_INFO_STANDARD:
2448 case SMB_FIND_EA_SIZE:
2449 case SMB_FIND_EA_LIST:
2450 case SMB_FIND_FILE_DIRECTORY_INFO:
2451 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2452 case SMB_FIND_FILE_NAMES_INFO:
2453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2454 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2455 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2456 break;
2457 case SMB_FIND_FILE_UNIX:
2458 case SMB_FIND_FILE_UNIX_INFO2:
2459 /* Always use filesystem for UNIX mtime query. */
2460 ask_sharemode = false;
2461 if (!lp_unix_extensions()) {
2462 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2463 goto out;
2465 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2466 break;
2467 default:
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2469 goto out;
2472 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2473 params+12, total_params - 12,
2474 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2475 if (!NT_STATUS_IS_OK(ntstatus)) {
2476 reply_nterror(req, ntstatus);
2477 goto out;
2480 if (backup_priv) {
2481 become_root();
2482 ntstatus = filename_convert_with_privilege(ctx,
2483 conn,
2484 req,
2485 directory,
2486 ucf_flags,
2487 &mask_contains_wcard,
2488 &smb_dname);
2489 } else {
2490 ntstatus = filename_convert(ctx, conn,
2491 req->flags2 & FLAGS2_DFS_PATHNAMES,
2492 directory,
2493 ucf_flags,
2494 &mask_contains_wcard,
2495 &smb_dname);
2498 if (!NT_STATUS_IS_OK(ntstatus)) {
2499 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2501 ERRSRV, ERRbadpath);
2502 goto out;
2504 reply_nterror(req, ntstatus);
2505 goto out;
2508 mask = smb_dname->original_lcomp;
2510 directory = smb_dname->base_name;
2512 p = strrchr_m(directory,'/');
2513 if(p == NULL) {
2514 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2515 if((directory[0] == '.') && (directory[1] == '\0')) {
2516 mask = talloc_strdup(ctx,"*");
2517 if (!mask) {
2518 reply_nterror(req, NT_STATUS_NO_MEMORY);
2519 goto out;
2521 mask_contains_wcard = True;
2523 } else {
2524 *p = 0;
2527 if (p == NULL || p == directory) {
2528 /* Ensure we don't have a directory name of "". */
2529 directory = talloc_strdup(talloc_tos(), ".");
2530 if (!directory) {
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2532 goto out;
2536 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2538 if (info_level == SMB_FIND_EA_LIST) {
2539 uint32 ea_size;
2541 if (total_data < 4) {
2542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2543 goto out;
2546 ea_size = IVAL(pdata,0);
2547 if (ea_size != total_data) {
2548 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2549 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2551 goto out;
2554 if (!lp_ea_support(SNUM(conn))) {
2555 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2556 goto out;
2559 /* Pull out the list of names. */
2560 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2561 if (!ea_list) {
2562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2563 goto out;
2567 *ppdata = (char *)SMB_REALLOC(
2568 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2569 if(*ppdata == NULL ) {
2570 reply_nterror(req, NT_STATUS_NO_MEMORY);
2571 goto out;
2573 pdata = *ppdata;
2574 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2576 /* Realloc the params space */
2577 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2578 if (*pparams == NULL) {
2579 reply_nterror(req, NT_STATUS_NO_MEMORY);
2580 goto out;
2582 params = *pparams;
2584 /* Save the wildcard match and attribs we are using on this directory -
2585 needed as lanman2 assumes these are being saved between calls */
2587 ntstatus = dptr_create(conn,
2588 req,
2589 NULL, /* fsp */
2590 directory,
2591 False,
2592 True,
2593 req->smbpid,
2594 mask,
2595 mask_contains_wcard,
2596 dirtype,
2597 &dirptr);
2599 if (!NT_STATUS_IS_OK(ntstatus)) {
2600 reply_nterror(req, ntstatus);
2601 goto out;
2604 if (backup_priv) {
2605 /* Remember this in case we have
2606 to do a findnext. */
2607 dptr_set_priv(dirptr);
2610 dptr_num = dptr_dnum(dirptr);
2611 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2613 /* Initialize per TRANS2_FIND_FIRST operation data */
2614 dptr_init_search_op(dirptr);
2616 /* We don't need to check for VOL here as this is returned by
2617 a different TRANS2 call. */
2619 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2620 directory,lp_dontdescend(ctx, SNUM(conn))));
2621 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2622 dont_descend = True;
2624 p = pdata;
2625 space_remaining = max_data_bytes;
2626 out_of_space = False;
2628 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2629 bool got_exact_match = False;
2631 /* this is a heuristic to avoid seeking the dirptr except when
2632 absolutely necessary. It allows for a filename of about 40 chars */
2633 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2634 out_of_space = True;
2635 finished = False;
2636 } else {
2637 finished = !get_lanman2_dir_entry(ctx,
2638 conn,
2639 dirptr,
2640 req->flags2,
2641 mask,dirtype,info_level,
2642 requires_resume_key,dont_descend,
2643 ask_sharemode,
2644 &p,pdata,data_end,
2645 space_remaining, &out_of_space,
2646 &got_exact_match,
2647 &last_entry_off, ea_list);
2650 if (finished && out_of_space)
2651 finished = False;
2653 if (!finished && !out_of_space)
2654 numentries++;
2657 * As an optimisation if we know we aren't looking
2658 * for a wildcard name (ie. the name matches the wildcard exactly)
2659 * then we can finish on any (first) match.
2660 * This speeds up large directory searches. JRA.
2663 if(got_exact_match)
2664 finished = True;
2666 /* Ensure space_remaining never goes -ve. */
2667 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2668 space_remaining = 0;
2669 out_of_space = true;
2670 } else {
2671 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2675 /* Check if we can close the dirptr */
2676 if(close_after_first || (finished && close_if_end)) {
2677 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2678 dptr_close(sconn, &dptr_num);
2682 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2683 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2684 * the protocol level is less than NT1. Tested with smbclient. JRA.
2685 * This should fix the OS/2 client bug #2335.
2688 if(numentries == 0) {
2689 dptr_close(sconn, &dptr_num);
2690 if (get_Protocol() < PROTOCOL_NT1) {
2691 reply_force_doserror(req, ERRDOS, ERRnofiles);
2692 goto out;
2693 } else {
2694 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2695 ERRDOS, ERRbadfile);
2696 goto out;
2700 /* At this point pdata points to numentries directory entries. */
2702 /* Set up the return parameter block */
2703 SSVAL(params,0,dptr_num);
2704 SSVAL(params,2,numentries);
2705 SSVAL(params,4,finished);
2706 SSVAL(params,6,0); /* Never an EA error */
2707 SSVAL(params,8,last_entry_off);
2709 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2710 max_data_bytes);
2712 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2713 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2714 if (!directory) {
2715 reply_nterror(req, NT_STATUS_NO_MEMORY);
2719 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2720 smb_fn_name(req->cmd),
2721 mask, directory, dirtype, numentries ) );
2724 * Force a name mangle here to ensure that the
2725 * mask as an 8.3 name is top of the mangled cache.
2726 * The reasons for this are subtle. Don't remove
2727 * this code unless you know what you are doing
2728 * (see PR#13758). JRA.
2731 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2732 char mangled_name[13];
2733 name_to_8_3(mask, mangled_name, True, conn->params);
2735 out:
2737 if (backup_priv) {
2738 unbecome_root();
2741 TALLOC_FREE(smb_dname);
2742 return;
2745 /****************************************************************************
2746 Reply to a TRANS2_FINDNEXT.
2747 ****************************************************************************/
2749 static void call_trans2findnext(connection_struct *conn,
2750 struct smb_request *req,
2751 char **pparams, int total_params,
2752 char **ppdata, int total_data,
2753 unsigned int max_data_bytes)
2755 /* We must be careful here that we don't return more than the
2756 allowed number of data bytes. If this means returning fewer than
2757 maxentries then so be it. We assume that the redirector has
2758 enough room for the fixed number of parameter bytes it has
2759 requested. */
2760 char *params = *pparams;
2761 char *pdata = *ppdata;
2762 char *data_end;
2763 int dptr_num;
2764 int maxentries;
2765 uint16 info_level;
2766 uint32 resume_key;
2767 uint16 findnext_flags;
2768 bool close_after_request;
2769 bool close_if_end;
2770 bool requires_resume_key;
2771 bool continue_bit;
2772 bool mask_contains_wcard = False;
2773 char *resume_name = NULL;
2774 const char *mask = NULL;
2775 const char *directory = NULL;
2776 char *p = NULL;
2777 uint16 dirtype;
2778 int numentries = 0;
2779 int i, last_entry_off=0;
2780 bool finished = False;
2781 bool dont_descend = False;
2782 bool out_of_space = False;
2783 int space_remaining;
2784 struct ea_list *ea_list = NULL;
2785 NTSTATUS ntstatus = NT_STATUS_OK;
2786 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2787 TALLOC_CTX *ctx = talloc_tos();
2788 struct dptr_struct *dirptr;
2789 struct smbd_server_connection *sconn = req->sconn;
2790 bool backup_priv = false;
2792 if (total_params < 13) {
2793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 return;
2797 dptr_num = SVAL(params,0);
2798 maxentries = SVAL(params,2);
2799 info_level = SVAL(params,4);
2800 resume_key = IVAL(params,6);
2801 findnext_flags = SVAL(params,10);
2802 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2803 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2804 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2805 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2807 if (!continue_bit) {
2808 /* We only need resume_name if continue_bit is zero. */
2809 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2810 params+12,
2811 total_params - 12, STR_TERMINATE, &ntstatus,
2812 &mask_contains_wcard);
2813 if (!NT_STATUS_IS_OK(ntstatus)) {
2814 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2815 complain (it thinks we're asking for the directory above the shared
2816 path or an invalid name). Catch this as the resume name is only compared, never used in
2817 a file access. JRA. */
2818 srvstr_pull_talloc(ctx, params, req->flags2,
2819 &resume_name, params+12,
2820 total_params - 12,
2821 STR_TERMINATE);
2823 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2824 reply_nterror(req, ntstatus);
2825 return;
2830 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2831 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2832 resume_key = %d resume name = %s continue=%d level = %d\n",
2833 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2834 requires_resume_key, resume_key,
2835 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2837 if (!maxentries) {
2838 /* W2K3 seems to treat zero as 1. */
2839 maxentries = 1;
2842 switch (info_level) {
2843 case SMB_FIND_INFO_STANDARD:
2844 case SMB_FIND_EA_SIZE:
2845 case SMB_FIND_EA_LIST:
2846 case SMB_FIND_FILE_DIRECTORY_INFO:
2847 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2848 case SMB_FIND_FILE_NAMES_INFO:
2849 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2850 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2851 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2852 break;
2853 case SMB_FIND_FILE_UNIX:
2854 case SMB_FIND_FILE_UNIX_INFO2:
2855 /* Always use filesystem for UNIX mtime query. */
2856 ask_sharemode = false;
2857 if (!lp_unix_extensions()) {
2858 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2859 return;
2861 break;
2862 default:
2863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2864 return;
2867 if (info_level == SMB_FIND_EA_LIST) {
2868 uint32 ea_size;
2870 if (total_data < 4) {
2871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2872 return;
2875 ea_size = IVAL(pdata,0);
2876 if (ea_size != total_data) {
2877 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2878 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2880 return;
2883 if (!lp_ea_support(SNUM(conn))) {
2884 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2885 return;
2888 /* Pull out the list of names. */
2889 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2890 if (!ea_list) {
2891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2892 return;
2896 *ppdata = (char *)SMB_REALLOC(
2897 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2898 if(*ppdata == NULL) {
2899 reply_nterror(req, NT_STATUS_NO_MEMORY);
2900 return;
2903 pdata = *ppdata;
2904 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2906 /* Realloc the params space */
2907 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2908 if(*pparams == NULL ) {
2909 reply_nterror(req, NT_STATUS_NO_MEMORY);
2910 return;
2913 params = *pparams;
2915 /* Check that the dptr is valid */
2916 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2917 reply_nterror(req, STATUS_NO_MORE_FILES);
2918 return;
2921 directory = dptr_path(sconn, dptr_num);
2923 /* Get the wildcard mask from the dptr */
2924 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2925 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2926 reply_nterror(req, STATUS_NO_MORE_FILES);
2927 return;
2930 /* Get the attr mask from the dptr */
2931 dirtype = dptr_attr(sconn, dptr_num);
2933 backup_priv = dptr_get_priv(dirptr);
2935 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2936 "backup_priv = %d\n",
2937 dptr_num, mask, dirtype,
2938 (long)dirptr,
2939 dptr_TellDir(dirptr),
2940 (int)backup_priv));
2942 /* Initialize per TRANS2_FIND_NEXT operation data */
2943 dptr_init_search_op(dirptr);
2945 /* We don't need to check for VOL here as this is returned by
2946 a different TRANS2 call. */
2948 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2949 directory,lp_dontdescend(ctx, SNUM(conn))));
2950 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2951 dont_descend = True;
2953 p = pdata;
2954 space_remaining = max_data_bytes;
2955 out_of_space = False;
2957 if (backup_priv) {
2958 become_root();
2962 * Seek to the correct position. We no longer use the resume key but
2963 * depend on the last file name instead.
2966 if(!continue_bit && resume_name && *resume_name) {
2967 SMB_STRUCT_STAT st;
2969 long current_pos = 0;
2971 * Remember, name_to_8_3 is called by
2972 * get_lanman2_dir_entry(), so the resume name
2973 * could be mangled. Ensure we check the unmangled name.
2976 if (mangle_is_mangled(resume_name, conn->params)) {
2977 char *new_resume_name = NULL;
2978 mangle_lookup_name_from_8_3(ctx,
2979 resume_name,
2980 &new_resume_name,
2981 conn->params);
2982 if (new_resume_name) {
2983 resume_name = new_resume_name;
2988 * Fix for NT redirector problem triggered by resume key indexes
2989 * changing between directory scans. We now return a resume key of 0
2990 * and instead look for the filename to continue from (also given
2991 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2992 * findfirst/findnext (as is usual) then the directory pointer
2993 * should already be at the correct place.
2996 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2997 } /* end if resume_name && !continue_bit */
2999 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3000 bool got_exact_match = False;
3002 /* this is a heuristic to avoid seeking the dirptr except when
3003 absolutely necessary. It allows for a filename of about 40 chars */
3004 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3005 out_of_space = True;
3006 finished = False;
3007 } else {
3008 finished = !get_lanman2_dir_entry(ctx,
3009 conn,
3010 dirptr,
3011 req->flags2,
3012 mask,dirtype,info_level,
3013 requires_resume_key,dont_descend,
3014 ask_sharemode,
3015 &p,pdata,data_end,
3016 space_remaining, &out_of_space,
3017 &got_exact_match,
3018 &last_entry_off, ea_list);
3021 if (finished && out_of_space)
3022 finished = False;
3024 if (!finished && !out_of_space)
3025 numentries++;
3028 * As an optimisation if we know we aren't looking
3029 * for a wildcard name (ie. the name matches the wildcard exactly)
3030 * then we can finish on any (first) match.
3031 * This speeds up large directory searches. JRA.
3034 if(got_exact_match)
3035 finished = True;
3037 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3040 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3041 smb_fn_name(req->cmd),
3042 mask, directory, dirtype, numentries ) );
3044 /* Check if we can close the dirptr */
3045 if(close_after_request || (finished && close_if_end)) {
3046 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3047 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3050 if (backup_priv) {
3051 unbecome_root();
3054 /* Set up the return parameter block */
3055 SSVAL(params,0,numentries);
3056 SSVAL(params,2,finished);
3057 SSVAL(params,4,0); /* Never an EA error */
3058 SSVAL(params,6,last_entry_off);
3060 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3061 max_data_bytes);
3063 return;
3066 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3068 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3069 return objid;
3072 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3074 SMB_ASSERT(extended_info != NULL);
3076 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3077 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3078 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3079 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3080 #ifdef SAMBA_VERSION_REVISION
3081 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3082 #endif
3083 extended_info->samba_subversion = 0;
3084 #ifdef SAMBA_VERSION_RC_RELEASE
3085 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3086 #else
3087 #ifdef SAMBA_VERSION_PRE_RELEASE
3088 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3089 #endif
3090 #endif
3091 #ifdef SAMBA_VERSION_VENDOR_PATCH
3092 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3093 #endif
3094 extended_info->samba_gitcommitdate = 0;
3095 #ifdef SAMBA_VERSION_COMMIT_TIME
3096 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3097 #endif
3099 memset(extended_info->samba_version_string, 0,
3100 sizeof(extended_info->samba_version_string));
3102 snprintf (extended_info->samba_version_string,
3103 sizeof(extended_info->samba_version_string),
3104 "%s", samba_version_string());
3107 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3108 TALLOC_CTX *mem_ctx,
3109 uint16_t info_level,
3110 uint16_t flags2,
3111 unsigned int max_data_bytes,
3112 struct smb_filename *fname,
3113 char **ppdata,
3114 int *ret_data_len)
3116 char *pdata, *end_data;
3117 int data_len = 0, len;
3118 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3119 int snum = SNUM(conn);
3120 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3121 char *filename = NULL;
3122 uint32 additional_flags = 0;
3123 struct smb_filename smb_fname;
3124 SMB_STRUCT_STAT st;
3126 if (fname == NULL || fname->base_name == NULL) {
3127 filename = ".";
3128 } else {
3129 filename = fname->base_name;
3132 if (IS_IPC(conn)) {
3133 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3134 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3135 "info level (0x%x) on IPC$.\n",
3136 (unsigned int)info_level));
3137 return NT_STATUS_ACCESS_DENIED;
3141 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3143 ZERO_STRUCT(smb_fname);
3144 smb_fname.base_name = discard_const_p(char, filename);
3146 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3147 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3148 return map_nt_error_from_unix(errno);
3151 st = smb_fname.st;
3153 *ppdata = (char *)SMB_REALLOC(
3154 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3155 if (*ppdata == NULL) {
3156 return NT_STATUS_NO_MEMORY;
3159 pdata = *ppdata;
3160 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3161 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3163 switch (info_level) {
3164 case SMB_INFO_ALLOCATION:
3166 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3167 data_len = 18;
3168 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3169 return map_nt_error_from_unix(errno);
3172 block_size = lp_block_size(snum);
3173 if (bsize < block_size) {
3174 uint64_t factor = block_size/bsize;
3175 bsize = block_size;
3176 dsize /= factor;
3177 dfree /= factor;
3179 if (bsize > block_size) {
3180 uint64_t factor = bsize/block_size;
3181 bsize = block_size;
3182 dsize *= factor;
3183 dfree *= factor;
3185 bytes_per_sector = 512;
3186 sectors_per_unit = bsize/bytes_per_sector;
3188 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3189 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3190 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3192 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3193 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3194 SIVAL(pdata,l1_cUnit,dsize);
3195 SIVAL(pdata,l1_cUnitAvail,dfree);
3196 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3197 break;
3200 case SMB_INFO_VOLUME:
3201 /* Return volume name */
3203 * Add volume serial number - hash of a combination of
3204 * the called hostname and the service name.
3206 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3208 * Win2k3 and previous mess this up by sending a name length
3209 * one byte short. I believe only older clients (OS/2 Win9x) use
3210 * this call so try fixing this by adding a terminating null to
3211 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3213 len = srvstr_push(
3214 pdata, flags2,
3215 pdata+l2_vol_szVolLabel, vname,
3216 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3217 STR_NOALIGN|STR_TERMINATE);
3218 SCVAL(pdata,l2_vol_cch,len);
3219 data_len = l2_vol_szVolLabel + len;
3220 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3221 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3222 len, vname));
3223 break;
3225 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3226 case SMB_FS_ATTRIBUTE_INFORMATION:
3228 additional_flags = 0;
3229 #if defined(HAVE_SYS_QUOTAS)
3230 additional_flags |= FILE_VOLUME_QUOTAS;
3231 #endif
3233 if(lp_nt_acl_support(SNUM(conn))) {
3234 additional_flags |= FILE_PERSISTENT_ACLS;
3237 /* Capabilities are filled in at connection time through STATVFS call */
3238 additional_flags |= conn->fs_capabilities;
3239 additional_flags |= lp_parm_int(conn->params->service,
3240 "share", "fake_fscaps",
3243 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3244 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3245 additional_flags); /* FS ATTRIBUTES */
3247 SIVAL(pdata,4,255); /* Max filename component length */
3248 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3249 and will think we can't do long filenames */
3250 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3251 PTR_DIFF(end_data, pdata+12),
3252 STR_UNICODE);
3253 SIVAL(pdata,8,len);
3254 data_len = 12 + len;
3255 break;
3257 case SMB_QUERY_FS_LABEL_INFO:
3258 case SMB_FS_LABEL_INFORMATION:
3259 len = srvstr_push(pdata, flags2, pdata+4, vname,
3260 PTR_DIFF(end_data, pdata+4), 0);
3261 data_len = 4 + len;
3262 SIVAL(pdata,0,len);
3263 break;
3265 case SMB_QUERY_FS_VOLUME_INFO:
3266 case SMB_FS_VOLUME_INFORMATION:
3269 * Add volume serial number - hash of a combination of
3270 * the called hostname and the service name.
3272 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3273 (str_checksum(get_local_machine_name())<<16));
3275 /* Max label len is 32 characters. */
3276 len = srvstr_push(pdata, flags2, pdata+18, vname,
3277 PTR_DIFF(end_data, pdata+18),
3278 STR_UNICODE);
3279 SIVAL(pdata,12,len);
3280 data_len = 18+len;
3282 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3283 (int)strlen(vname),vname,
3284 lp_servicename(talloc_tos(), snum)));
3285 break;
3287 case SMB_QUERY_FS_SIZE_INFO:
3288 case SMB_FS_SIZE_INFORMATION:
3290 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3291 data_len = 24;
3292 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3293 return map_nt_error_from_unix(errno);
3295 block_size = lp_block_size(snum);
3296 if (bsize < block_size) {
3297 uint64_t factor = block_size/bsize;
3298 bsize = block_size;
3299 dsize /= factor;
3300 dfree /= factor;
3302 if (bsize > block_size) {
3303 uint64_t factor = bsize/block_size;
3304 bsize = block_size;
3305 dsize *= factor;
3306 dfree *= factor;
3308 bytes_per_sector = 512;
3309 sectors_per_unit = bsize/bytes_per_sector;
3310 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3311 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3312 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3313 SBIG_UINT(pdata,0,dsize);
3314 SBIG_UINT(pdata,8,dfree);
3315 SIVAL(pdata,16,sectors_per_unit);
3316 SIVAL(pdata,20,bytes_per_sector);
3317 break;
3320 case SMB_FS_FULL_SIZE_INFORMATION:
3322 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3323 data_len = 32;
3324 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3325 return map_nt_error_from_unix(errno);
3327 block_size = lp_block_size(snum);
3328 if (bsize < block_size) {
3329 uint64_t factor = block_size/bsize;
3330 bsize = block_size;
3331 dsize /= factor;
3332 dfree /= factor;
3334 if (bsize > block_size) {
3335 uint64_t factor = bsize/block_size;
3336 bsize = block_size;
3337 dsize *= factor;
3338 dfree *= factor;
3340 bytes_per_sector = 512;
3341 sectors_per_unit = bsize/bytes_per_sector;
3342 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3343 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3344 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3345 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3346 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3347 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3348 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3349 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3350 break;
3353 case SMB_QUERY_FS_DEVICE_INFO:
3354 case SMB_FS_DEVICE_INFORMATION:
3356 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3358 if (!CAN_WRITE(conn)) {
3359 characteristics |= FILE_READ_ONLY_DEVICE;
3361 data_len = 8;
3362 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3363 SIVAL(pdata,4,characteristics);
3364 break;
3367 #ifdef HAVE_SYS_QUOTAS
3368 case SMB_FS_QUOTA_INFORMATION:
3370 * what we have to send --metze:
3372 * Unknown1: 24 NULL bytes
3373 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3374 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3375 * Quota Flags: 2 byte :
3376 * Unknown3: 6 NULL bytes
3378 * 48 bytes total
3380 * details for Quota Flags:
3382 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3383 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3384 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3385 * 0x0001 Enable Quotas: enable quota for this fs
3389 /* we need to fake up a fsp here,
3390 * because its not send in this call
3392 files_struct fsp;
3393 SMB_NTQUOTA_STRUCT quotas;
3395 ZERO_STRUCT(fsp);
3396 ZERO_STRUCT(quotas);
3398 fsp.conn = conn;
3399 fsp.fnum = FNUM_FIELD_INVALID;
3401 /* access check */
3402 if (get_current_uid(conn) != 0) {
3403 DEBUG(0,("set_user_quota: access_denied "
3404 "service [%s] user [%s]\n",
3405 lp_servicename(talloc_tos(), SNUM(conn)),
3406 conn->session_info->unix_info->unix_name));
3407 return NT_STATUS_ACCESS_DENIED;
3410 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3411 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3412 return map_nt_error_from_unix(errno);
3415 data_len = 48;
3417 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3418 lp_servicename(talloc_tos(), SNUM(conn))));
3420 /* Unknown1 24 NULL bytes*/
3421 SBIG_UINT(pdata,0,(uint64_t)0);
3422 SBIG_UINT(pdata,8,(uint64_t)0);
3423 SBIG_UINT(pdata,16,(uint64_t)0);
3425 /* Default Soft Quota 8 bytes */
3426 SBIG_UINT(pdata,24,quotas.softlim);
3428 /* Default Hard Quota 8 bytes */
3429 SBIG_UINT(pdata,32,quotas.hardlim);
3431 /* Quota flag 2 bytes */
3432 SSVAL(pdata,40,quotas.qflags);
3434 /* Unknown3 6 NULL bytes */
3435 SSVAL(pdata,42,0);
3436 SIVAL(pdata,44,0);
3438 break;
3440 #endif /* HAVE_SYS_QUOTAS */
3441 case SMB_FS_OBJECTID_INFORMATION:
3443 unsigned char objid[16];
3444 struct smb_extended_info extended_info;
3445 memcpy(pdata,create_volume_objectid(conn, objid),16);
3446 samba_extended_info_version (&extended_info);
3447 SIVAL(pdata,16,extended_info.samba_magic);
3448 SIVAL(pdata,20,extended_info.samba_version);
3449 SIVAL(pdata,24,extended_info.samba_subversion);
3450 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3451 memcpy(pdata+36,extended_info.samba_version_string,28);
3452 data_len = 64;
3453 break;
3457 * Query the version and capabilities of the CIFS UNIX extensions
3458 * in use.
3461 case SMB_QUERY_CIFS_UNIX_INFO:
3463 bool large_write = lp_min_receive_file_size() &&
3464 !srv_is_signing_active(conn->sconn);
3465 bool large_read = !srv_is_signing_active(conn->sconn);
3466 int encrypt_caps = 0;
3468 if (!lp_unix_extensions()) {
3469 return NT_STATUS_INVALID_LEVEL;
3472 switch (conn->encrypt_level) {
3473 case SMB_SIGNING_OFF:
3474 encrypt_caps = 0;
3475 break;
3476 case SMB_SIGNING_IF_REQUIRED:
3477 case SMB_SIGNING_DEFAULT:
3478 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3479 break;
3480 case SMB_SIGNING_REQUIRED:
3481 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3482 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3483 large_write = false;
3484 large_read = false;
3485 break;
3488 data_len = 12;
3489 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3490 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3492 /* We have POSIX ACLs, pathname, encryption,
3493 * large read/write, and locking capability. */
3495 SBIG_UINT(pdata,4,((uint64_t)(
3496 CIFS_UNIX_POSIX_ACLS_CAP|
3497 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3498 CIFS_UNIX_FCNTL_LOCKS_CAP|
3499 CIFS_UNIX_EXTATTR_CAP|
3500 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3501 encrypt_caps|
3502 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3503 (large_write ?
3504 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3505 break;
3508 case SMB_QUERY_POSIX_FS_INFO:
3510 int rc;
3511 vfs_statvfs_struct svfs;
3513 if (!lp_unix_extensions()) {
3514 return NT_STATUS_INVALID_LEVEL;
3517 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3519 if (!rc) {
3520 data_len = 56;
3521 SIVAL(pdata,0,svfs.OptimalTransferSize);
3522 SIVAL(pdata,4,svfs.BlockSize);
3523 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3524 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3525 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3526 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3527 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3528 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3529 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3530 #ifdef EOPNOTSUPP
3531 } else if (rc == EOPNOTSUPP) {
3532 return NT_STATUS_INVALID_LEVEL;
3533 #endif /* EOPNOTSUPP */
3534 } else {
3535 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3536 return NT_STATUS_DOS(ERRSRV, ERRerror);
3538 break;
3541 case SMB_QUERY_POSIX_WHOAMI:
3543 uint32_t flags = 0;
3544 uint32_t sid_bytes;
3545 int i;
3547 if (!lp_unix_extensions()) {
3548 return NT_STATUS_INVALID_LEVEL;
3551 if (max_data_bytes < 40) {
3552 return NT_STATUS_BUFFER_TOO_SMALL;
3555 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3556 flags |= SMB_WHOAMI_GUEST;
3559 /* NOTE: 8 bytes for UID/GID, irrespective of native
3560 * platform size. This matches
3561 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3563 data_len = 4 /* flags */
3564 + 4 /* flag mask */
3565 + 8 /* uid */
3566 + 8 /* gid */
3567 + 4 /* ngroups */
3568 + 4 /* num_sids */
3569 + 4 /* SID bytes */
3570 + 4 /* pad/reserved */
3571 + (conn->session_info->unix_token->ngroups * 8)
3572 /* groups list */
3573 + (conn->session_info->security_token->num_sids *
3574 SID_MAX_SIZE)
3575 /* SID list */;
3577 SIVAL(pdata, 0, flags);
3578 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3579 SBIG_UINT(pdata, 8,
3580 (uint64_t)conn->session_info->unix_token->uid);
3581 SBIG_UINT(pdata, 16,
3582 (uint64_t)conn->session_info->unix_token->gid);
3585 if (data_len >= max_data_bytes) {
3586 /* Potential overflow, skip the GIDs and SIDs. */
3588 SIVAL(pdata, 24, 0); /* num_groups */
3589 SIVAL(pdata, 28, 0); /* num_sids */
3590 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3591 SIVAL(pdata, 36, 0); /* reserved */
3593 data_len = 40;
3594 break;
3597 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3598 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3600 /* We walk the SID list twice, but this call is fairly
3601 * infrequent, and I don't expect that it's performance
3602 * sensitive -- jpeach
3604 for (i = 0, sid_bytes = 0;
3605 i < conn->session_info->security_token->num_sids; ++i) {
3606 sid_bytes += ndr_size_dom_sid(
3607 &conn->session_info->security_token->sids[i],
3611 /* SID list byte count */
3612 SIVAL(pdata, 32, sid_bytes);
3614 /* 4 bytes pad/reserved - must be zero */
3615 SIVAL(pdata, 36, 0);
3616 data_len = 40;
3618 /* GID list */
3619 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3620 SBIG_UINT(pdata, data_len,
3621 (uint64_t)conn->session_info->unix_token->groups[i]);
3622 data_len += 8;
3625 /* SID list */
3626 for (i = 0;
3627 i < conn->session_info->security_token->num_sids; ++i) {
3628 int sid_len = ndr_size_dom_sid(
3629 &conn->session_info->security_token->sids[i],
3632 sid_linearize(pdata + data_len, sid_len,
3633 &conn->session_info->security_token->sids[i]);
3634 data_len += sid_len;
3637 break;
3640 case SMB_MAC_QUERY_FS_INFO:
3642 * Thursby MAC extension... ONLY on NTFS filesystems
3643 * once we do streams then we don't need this
3645 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3646 data_len = 88;
3647 SIVAL(pdata,84,0x100); /* Don't support mac... */
3648 break;
3650 /* drop through */
3651 default:
3652 return NT_STATUS_INVALID_LEVEL;
3655 *ret_data_len = data_len;
3656 return NT_STATUS_OK;
3659 /****************************************************************************
3660 Reply to a TRANS2_QFSINFO (query filesystem info).
3661 ****************************************************************************/
3663 static void call_trans2qfsinfo(connection_struct *conn,
3664 struct smb_request *req,
3665 char **pparams, int total_params,
3666 char **ppdata, int total_data,
3667 unsigned int max_data_bytes)
3669 char *params = *pparams;
3670 uint16_t info_level;
3671 int data_len = 0;
3672 NTSTATUS status;
3674 if (total_params < 2) {
3675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3676 return;
3679 info_level = SVAL(params,0);
3681 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3682 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3683 DEBUG(0,("call_trans2qfsinfo: encryption required "
3684 "and info level 0x%x sent.\n",
3685 (unsigned int)info_level));
3686 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3687 return;
3691 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3693 status = smbd_do_qfsinfo(conn, req,
3694 info_level,
3695 req->flags2,
3696 max_data_bytes,
3697 NULL,
3698 ppdata, &data_len);
3699 if (!NT_STATUS_IS_OK(status)) {
3700 reply_nterror(req, status);
3701 return;
3704 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3705 max_data_bytes);
3707 DEBUG( 4, ( "%s info_level = %d\n",
3708 smb_fn_name(req->cmd), info_level) );
3710 return;
3713 /****************************************************************************
3714 Reply to a TRANS2_SETFSINFO (set filesystem info).
3715 ****************************************************************************/
3717 static void call_trans2setfsinfo(connection_struct *conn,
3718 struct smb_request *req,
3719 char **pparams, int total_params,
3720 char **ppdata, int total_data,
3721 unsigned int max_data_bytes)
3723 struct smbd_server_connection *sconn = req->sconn;
3724 char *pdata = *ppdata;
3725 char *params = *pparams;
3726 uint16 info_level;
3728 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3729 lp_servicename(talloc_tos(), SNUM(conn))));
3731 /* */
3732 if (total_params < 4) {
3733 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3734 total_params));
3735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3736 return;
3739 info_level = SVAL(params,2);
3741 if (IS_IPC(conn)) {
3742 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3743 info_level != SMB_SET_CIFS_UNIX_INFO) {
3744 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3745 "info level (0x%x) on IPC$.\n",
3746 (unsigned int)info_level));
3747 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3748 return;
3752 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3753 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3754 DEBUG(0,("call_trans2setfsinfo: encryption required "
3755 "and info level 0x%x sent.\n",
3756 (unsigned int)info_level));
3757 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3758 return;
3762 switch(info_level) {
3763 case SMB_SET_CIFS_UNIX_INFO:
3764 if (!lp_unix_extensions()) {
3765 DEBUG(2,("call_trans2setfsinfo: "
3766 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3767 "unix extensions off\n"));
3768 reply_nterror(req,
3769 NT_STATUS_INVALID_LEVEL);
3770 return;
3773 /* There should be 12 bytes of capabilities set. */
3774 if (total_data < 12) {
3775 reply_nterror(
3776 req,
3777 NT_STATUS_INVALID_PARAMETER);
3778 return;
3780 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3781 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3782 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3783 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3784 /* Just print these values for now. */
3785 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3786 "major = %u, minor = %u cap_low = 0x%x, "
3787 "cap_high = 0x%xn",
3788 (unsigned int)sconn->
3789 smb1.unix_info.client_major,
3790 (unsigned int)sconn->
3791 smb1.unix_info.client_minor,
3792 (unsigned int)sconn->
3793 smb1.unix_info.client_cap_low,
3794 (unsigned int)sconn->
3795 smb1.unix_info.client_cap_high));
3797 /* Here is where we must switch to posix pathname processing... */
3798 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3799 lp_set_posix_pathnames();
3800 mangle_change_to_posix();
3803 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3804 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3805 /* Client that knows how to do posix locks,
3806 * but not posix open/mkdir operations. Set a
3807 * default type for read/write checks. */
3809 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3812 break;
3814 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3816 NTSTATUS status;
3817 size_t param_len = 0;
3818 size_t data_len = total_data;
3820 if (!lp_unix_extensions()) {
3821 reply_nterror(
3822 req,
3823 NT_STATUS_INVALID_LEVEL);
3824 return;
3827 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3828 reply_nterror(
3829 req,
3830 NT_STATUS_NOT_SUPPORTED);
3831 return;
3834 if (req->sconn->smb1.echo_handler.trusted_fde) {
3835 DEBUG( 2,("call_trans2setfsinfo: "
3836 "request transport encryption disabled"
3837 "with 'fork echo handler = yes'\n"));
3838 reply_nterror(
3839 req,
3840 NT_STATUS_NOT_SUPPORTED);
3841 return;
3844 DEBUG( 4,("call_trans2setfsinfo: "
3845 "request transport encryption.\n"));
3847 status = srv_request_encryption_setup(conn,
3848 (unsigned char **)ppdata,
3849 &data_len,
3850 (unsigned char **)pparams,
3851 &param_len);
3853 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3854 !NT_STATUS_IS_OK(status)) {
3855 reply_nterror(req, status);
3856 return;
3859 send_trans2_replies(conn, req,
3860 NT_STATUS_OK,
3861 *pparams,
3862 param_len,
3863 *ppdata,
3864 data_len,
3865 max_data_bytes);
3867 if (NT_STATUS_IS_OK(status)) {
3868 /* Server-side transport
3869 * encryption is now *on*. */
3870 status = srv_encryption_start(conn);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 char *reason = talloc_asprintf(talloc_tos(),
3873 "Failure in setting "
3874 "up encrypted transport: %s",
3875 nt_errstr(status));
3876 exit_server_cleanly(reason);
3879 return;
3882 case SMB_FS_QUOTA_INFORMATION:
3884 files_struct *fsp = NULL;
3885 SMB_NTQUOTA_STRUCT quotas;
3887 ZERO_STRUCT(quotas);
3889 /* access check */
3890 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3891 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3892 lp_servicename(talloc_tos(), SNUM(conn)),
3893 conn->session_info->unix_info->unix_name));
3894 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3895 return;
3898 /* note: normaly there're 48 bytes,
3899 * but we didn't use the last 6 bytes for now
3900 * --metze
3902 fsp = file_fsp(req, SVAL(params,0));
3904 if (!check_fsp_ntquota_handle(conn, req,
3905 fsp)) {
3906 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3907 reply_nterror(
3908 req, NT_STATUS_INVALID_HANDLE);
3909 return;
3912 if (total_data < 42) {
3913 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3914 total_data));
3915 reply_nterror(
3916 req,
3917 NT_STATUS_INVALID_PARAMETER);
3918 return;
3921 /* unknown_1 24 NULL bytes in pdata*/
3923 /* the soft quotas 8 bytes (uint64_t)*/
3924 quotas.softlim = BVAL(pdata,24);
3926 /* the hard quotas 8 bytes (uint64_t)*/
3927 quotas.hardlim = BVAL(pdata,32);
3929 /* quota_flags 2 bytes **/
3930 quotas.qflags = SVAL(pdata,40);
3932 /* unknown_2 6 NULL bytes follow*/
3934 /* now set the quotas */
3935 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3936 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3937 reply_nterror(req, map_nt_error_from_unix(errno));
3938 return;
3941 break;
3943 default:
3944 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3945 info_level));
3946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3947 return;
3948 break;
3952 * sending this reply works fine,
3953 * but I'm not sure it's the same
3954 * like windows do...
3955 * --metze
3957 reply_outbuf(req, 10, 0);
3960 #if defined(HAVE_POSIX_ACLS)
3961 /****************************************************************************
3962 Utility function to count the number of entries in a POSIX acl.
3963 ****************************************************************************/
3965 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3967 unsigned int ace_count = 0;
3968 int entry_id = SMB_ACL_FIRST_ENTRY;
3969 SMB_ACL_ENTRY_T entry;
3971 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3972 /* get_next... */
3973 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3974 entry_id = SMB_ACL_NEXT_ENTRY;
3976 ace_count++;
3978 return ace_count;
3981 /****************************************************************************
3982 Utility function to marshall a POSIX acl into wire format.
3983 ****************************************************************************/
3985 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3987 int entry_id = SMB_ACL_FIRST_ENTRY;
3988 SMB_ACL_ENTRY_T entry;
3990 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3991 SMB_ACL_TAG_T tagtype;
3992 SMB_ACL_PERMSET_T permset;
3993 unsigned char perms = 0;
3994 unsigned int own_grp;
3996 /* get_next... */
3997 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3998 entry_id = SMB_ACL_NEXT_ENTRY;
4001 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4002 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4003 return False;
4006 if (sys_acl_get_permset(entry, &permset) == -1) {
4007 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4008 return False;
4011 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4012 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4013 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4015 SCVAL(pdata,1,perms);
4017 switch (tagtype) {
4018 case SMB_ACL_USER_OBJ:
4019 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4020 own_grp = (unsigned int)pst->st_ex_uid;
4021 SIVAL(pdata,2,own_grp);
4022 SIVAL(pdata,6,0);
4023 break;
4024 case SMB_ACL_USER:
4026 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4027 if (!puid) {
4028 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4029 return False;
4031 own_grp = (unsigned int)*puid;
4032 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4033 SIVAL(pdata,2,own_grp);
4034 SIVAL(pdata,6,0);
4035 break;
4037 case SMB_ACL_GROUP_OBJ:
4038 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4039 own_grp = (unsigned int)pst->st_ex_gid;
4040 SIVAL(pdata,2,own_grp);
4041 SIVAL(pdata,6,0);
4042 break;
4043 case SMB_ACL_GROUP:
4045 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4046 if (!pgid) {
4047 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4048 return False;
4050 own_grp = (unsigned int)*pgid;
4051 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4052 SIVAL(pdata,2,own_grp);
4053 SIVAL(pdata,6,0);
4054 break;
4056 case SMB_ACL_MASK:
4057 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4058 SIVAL(pdata,2,0xFFFFFFFF);
4059 SIVAL(pdata,6,0xFFFFFFFF);
4060 break;
4061 case SMB_ACL_OTHER:
4062 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4063 SIVAL(pdata,2,0xFFFFFFFF);
4064 SIVAL(pdata,6,0xFFFFFFFF);
4065 break;
4066 default:
4067 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4068 return False;
4070 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4073 return True;
4075 #endif
4077 /****************************************************************************
4078 Store the FILE_UNIX_BASIC info.
4079 ****************************************************************************/
4081 static char *store_file_unix_basic(connection_struct *conn,
4082 char *pdata,
4083 files_struct *fsp,
4084 const SMB_STRUCT_STAT *psbuf)
4086 uint64_t file_index = get_FileIndex(conn, psbuf);
4087 dev_t devno;
4089 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4090 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4092 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4093 pdata += 8;
4095 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4096 pdata += 8;
4098 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4099 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4100 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4101 pdata += 24;
4103 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4104 SIVAL(pdata,4,0);
4105 pdata += 8;
4107 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4108 SIVAL(pdata,4,0);
4109 pdata += 8;
4111 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4112 pdata += 4;
4114 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4115 devno = psbuf->st_ex_rdev;
4116 } else {
4117 devno = psbuf->st_ex_dev;
4120 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4121 SIVAL(pdata,4,0);
4122 pdata += 8;
4124 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4125 SIVAL(pdata,4,0);
4126 pdata += 8;
4128 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4129 pdata += 8;
4131 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4132 SIVAL(pdata,4,0);
4133 pdata += 8;
4135 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4136 SIVAL(pdata,4,0);
4137 pdata += 8;
4139 return pdata;
4142 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4143 * the chflags(2) (or equivalent) flags.
4145 * XXX: this really should be behind the VFS interface. To do this, we would
4146 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4147 * Each VFS module could then implement its own mapping as appropriate for the
4148 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4150 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4151 info2_flags_map[] =
4153 #ifdef UF_NODUMP
4154 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4155 #endif
4157 #ifdef UF_IMMUTABLE
4158 { UF_IMMUTABLE, EXT_IMMUTABLE },
4159 #endif
4161 #ifdef UF_APPEND
4162 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4163 #endif
4165 #ifdef UF_HIDDEN
4166 { UF_HIDDEN, EXT_HIDDEN },
4167 #endif
4169 /* Do not remove. We need to guarantee that this array has at least one
4170 * entry to build on HP-UX.
4172 { 0, 0 }
4176 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4177 uint32 *smb_fflags, uint32 *smb_fmask)
4179 int i;
4181 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4182 *smb_fmask |= info2_flags_map[i].smb_fflag;
4183 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4184 *smb_fflags |= info2_flags_map[i].smb_fflag;
4189 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4190 const uint32 smb_fflags,
4191 const uint32 smb_fmask,
4192 int *stat_fflags)
4194 uint32 max_fmask = 0;
4195 int i;
4197 *stat_fflags = psbuf->st_ex_flags;
4199 /* For each flags requested in smb_fmask, check the state of the
4200 * corresponding flag in smb_fflags and set or clear the matching
4201 * stat flag.
4204 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4205 max_fmask |= info2_flags_map[i].smb_fflag;
4206 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4207 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4208 *stat_fflags |= info2_flags_map[i].stat_fflag;
4209 } else {
4210 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4215 /* If smb_fmask is asking to set any bits that are not supported by
4216 * our flag mappings, we should fail.
4218 if ((smb_fmask & max_fmask) != smb_fmask) {
4219 return False;
4222 return True;
4226 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4227 * of file flags and birth (create) time.
4229 static char *store_file_unix_basic_info2(connection_struct *conn,
4230 char *pdata,
4231 files_struct *fsp,
4232 const SMB_STRUCT_STAT *psbuf)
4234 uint32 file_flags = 0;
4235 uint32 flags_mask = 0;
4237 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4239 /* Create (birth) time 64 bit */
4240 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4241 pdata += 8;
4243 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4244 SIVAL(pdata, 0, file_flags); /* flags */
4245 SIVAL(pdata, 4, flags_mask); /* mask */
4246 pdata += 8;
4248 return pdata;
4251 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4252 const struct stream_struct *streams,
4253 char *data,
4254 unsigned int max_data_bytes,
4255 unsigned int *data_size)
4257 unsigned int i;
4258 unsigned int ofs = 0;
4260 for (i = 0; i < num_streams; i++) {
4261 unsigned int next_offset;
4262 size_t namelen;
4263 smb_ucs2_t *namebuf;
4265 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4266 streams[i].name, &namelen) ||
4267 namelen <= 2)
4269 return NT_STATUS_INVALID_PARAMETER;
4273 * name_buf is now null-terminated, we need to marshall as not
4274 * terminated
4277 namelen -= 2;
4280 * We cannot overflow ...
4282 if ((ofs + 24 + namelen) > max_data_bytes) {
4283 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4284 i));
4285 TALLOC_FREE(namebuf);
4286 return STATUS_BUFFER_OVERFLOW;
4289 SIVAL(data, ofs+4, namelen);
4290 SOFF_T(data, ofs+8, streams[i].size);
4291 SOFF_T(data, ofs+16, streams[i].alloc_size);
4292 memcpy(data+ofs+24, namebuf, namelen);
4293 TALLOC_FREE(namebuf);
4295 next_offset = ofs + 24 + namelen;
4297 if (i == num_streams-1) {
4298 SIVAL(data, ofs, 0);
4300 else {
4301 unsigned int align = ndr_align_size(next_offset, 8);
4303 if ((next_offset + align) > max_data_bytes) {
4304 DEBUG(10, ("refusing to overflow align "
4305 "reply at stream %u\n",
4306 i));
4307 TALLOC_FREE(namebuf);
4308 return STATUS_BUFFER_OVERFLOW;
4311 memset(data+next_offset, 0, align);
4312 next_offset += align;
4314 SIVAL(data, ofs, next_offset - ofs);
4315 ofs = next_offset;
4318 ofs = next_offset;
4321 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4323 *data_size = ofs;
4325 return NT_STATUS_OK;
4328 /****************************************************************************
4329 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4330 ****************************************************************************/
4332 static void call_trans2qpipeinfo(connection_struct *conn,
4333 struct smb_request *req,
4334 unsigned int tran_call,
4335 char **pparams, int total_params,
4336 char **ppdata, int total_data,
4337 unsigned int max_data_bytes)
4339 char *params = *pparams;
4340 char *pdata = *ppdata;
4341 unsigned int data_size = 0;
4342 unsigned int param_size = 2;
4343 uint16 info_level;
4344 files_struct *fsp;
4346 if (!params) {
4347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4348 return;
4351 if (total_params < 4) {
4352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4353 return;
4356 fsp = file_fsp(req, SVAL(params,0));
4357 if (!fsp_is_np(fsp)) {
4358 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4359 return;
4362 info_level = SVAL(params,2);
4364 *pparams = (char *)SMB_REALLOC(*pparams,2);
4365 if (*pparams == NULL) {
4366 reply_nterror(req, NT_STATUS_NO_MEMORY);
4367 return;
4369 params = *pparams;
4370 SSVAL(params,0,0);
4371 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4372 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4373 if (*ppdata == NULL ) {
4374 reply_nterror(req, NT_STATUS_NO_MEMORY);
4375 return;
4377 pdata = *ppdata;
4379 switch (info_level) {
4380 case SMB_FILE_STANDARD_INFORMATION:
4381 memset(pdata,0,24);
4382 SOFF_T(pdata,0,4096LL);
4383 SIVAL(pdata,16,1);
4384 SIVAL(pdata,20,1);
4385 data_size = 24;
4386 break;
4388 default:
4389 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4390 return;
4393 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4394 max_data_bytes);
4396 return;
4399 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4400 TALLOC_CTX *mem_ctx,
4401 uint16_t info_level,
4402 files_struct *fsp,
4403 struct smb_filename *smb_fname,
4404 bool delete_pending,
4405 struct timespec write_time_ts,
4406 struct ea_list *ea_list,
4407 int lock_data_count,
4408 char *lock_data,
4409 uint16_t flags2,
4410 unsigned int max_data_bytes,
4411 char **ppdata,
4412 unsigned int *pdata_size)
4414 char *pdata = *ppdata;
4415 char *dstart, *dend;
4416 unsigned int data_size;
4417 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4418 time_t create_time, mtime, atime, c_time;
4419 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4420 char *p;
4421 char *base_name;
4422 char *dos_fname;
4423 int mode;
4424 int nlink;
4425 NTSTATUS status;
4426 uint64_t file_size = 0;
4427 uint64_t pos = 0;
4428 uint64_t allocation_size = 0;
4429 uint64_t file_index = 0;
4430 uint32_t access_mask = 0;
4432 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4433 return NT_STATUS_INVALID_LEVEL;
4436 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4437 smb_fname_str_dbg(smb_fname),
4438 fsp_fnum_dbg(fsp),
4439 info_level, max_data_bytes));
4441 mode = dos_mode(conn, smb_fname);
4442 nlink = psbuf->st_ex_nlink;
4444 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4445 nlink = 1;
4448 if ((nlink > 0) && delete_pending) {
4449 nlink -= 1;
4452 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4453 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4454 if (*ppdata == NULL) {
4455 return NT_STATUS_NO_MEMORY;
4457 pdata = *ppdata;
4458 dstart = pdata;
4459 dend = dstart + data_size - 1;
4461 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4462 update_stat_ex_mtime(psbuf, write_time_ts);
4465 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4466 mtime_ts = psbuf->st_ex_mtime;
4467 atime_ts = psbuf->st_ex_atime;
4468 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4470 if (lp_dos_filetime_resolution(SNUM(conn))) {
4471 dos_filetime_timespec(&create_time_ts);
4472 dos_filetime_timespec(&mtime_ts);
4473 dos_filetime_timespec(&atime_ts);
4474 dos_filetime_timespec(&ctime_ts);
4477 create_time = convert_timespec_to_time_t(create_time_ts);
4478 mtime = convert_timespec_to_time_t(mtime_ts);
4479 atime = convert_timespec_to_time_t(atime_ts);
4480 c_time = convert_timespec_to_time_t(ctime_ts);
4482 p = strrchr_m(smb_fname->base_name,'/');
4483 if (!p)
4484 base_name = smb_fname->base_name;
4485 else
4486 base_name = p+1;
4488 /* NT expects the name to be in an exact form of the *full*
4489 filename. See the trans2 torture test */
4490 if (ISDOT(base_name)) {
4491 dos_fname = talloc_strdup(mem_ctx, "\\");
4492 if (!dos_fname) {
4493 return NT_STATUS_NO_MEMORY;
4495 } else {
4496 dos_fname = talloc_asprintf(mem_ctx,
4497 "\\%s",
4498 smb_fname->base_name);
4499 if (!dos_fname) {
4500 return NT_STATUS_NO_MEMORY;
4502 if (is_ntfs_stream_smb_fname(smb_fname)) {
4503 dos_fname = talloc_asprintf(dos_fname, "%s",
4504 smb_fname->stream_name);
4505 if (!dos_fname) {
4506 return NT_STATUS_NO_MEMORY;
4510 string_replace(dos_fname, '/', '\\');
4513 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4515 if (!fsp) {
4516 /* Do we have this path open ? */
4517 files_struct *fsp1;
4518 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4519 fsp1 = file_find_di_first(conn->sconn, fileid);
4520 if (fsp1 && fsp1->initial_allocation_size) {
4521 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4525 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4526 file_size = get_file_size_stat(psbuf);
4529 if (fsp) {
4530 pos = fsp->fh->position_information;
4533 if (fsp) {
4534 access_mask = fsp->access_mask;
4535 } else {
4536 /* GENERIC_EXECUTE mapping from Windows */
4537 access_mask = 0x12019F;
4540 /* This should be an index number - looks like
4541 dev/ino to me :-)
4543 I think this causes us to fail the IFSKIT
4544 BasicFileInformationTest. -tpot */
4545 file_index = get_FileIndex(conn, psbuf);
4547 switch (info_level) {
4548 case SMB_INFO_STANDARD:
4549 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4550 data_size = 22;
4551 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4552 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4553 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4554 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4555 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4556 SSVAL(pdata,l1_attrFile,mode);
4557 break;
4559 case SMB_INFO_QUERY_EA_SIZE:
4561 unsigned int ea_size =
4562 estimate_ea_size(conn, fsp,
4563 smb_fname);
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4565 data_size = 26;
4566 srv_put_dos_date2(pdata,0,create_time);
4567 srv_put_dos_date2(pdata,4,atime);
4568 srv_put_dos_date2(pdata,8,mtime); /* write time */
4569 SIVAL(pdata,12,(uint32)file_size);
4570 SIVAL(pdata,16,(uint32)allocation_size);
4571 SSVAL(pdata,20,mode);
4572 SIVAL(pdata,22,ea_size);
4573 break;
4576 case SMB_INFO_IS_NAME_VALID:
4577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4578 if (fsp) {
4579 /* os/2 needs this ? really ?*/
4580 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4582 /* This is only reached for qpathinfo */
4583 data_size = 0;
4584 break;
4586 case SMB_INFO_QUERY_EAS_FROM_LIST:
4588 size_t total_ea_len = 0;
4589 struct ea_list *ea_file_list = NULL;
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4592 status =
4593 get_ea_list_from_file(mem_ctx, conn, fsp,
4594 smb_fname,
4595 &total_ea_len, &ea_file_list);
4596 if (!NT_STATUS_IS_OK(status)) {
4597 return status;
4600 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4602 if (!ea_list || (total_ea_len > data_size)) {
4603 data_size = 4;
4604 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4605 break;
4608 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4609 break;
4612 case SMB_INFO_QUERY_ALL_EAS:
4614 /* We have data_size bytes to put EA's into. */
4615 size_t total_ea_len = 0;
4616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4618 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4619 smb_fname,
4620 &total_ea_len, &ea_list);
4621 if (!NT_STATUS_IS_OK(status)) {
4622 return status;
4625 if (!ea_list || (total_ea_len > data_size)) {
4626 data_size = 4;
4627 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4628 break;
4631 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4632 break;
4635 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4637 /* This is FileFullEaInformation - 0xF which maps to
4638 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4640 /* We have data_size bytes to put EA's into. */
4641 size_t total_ea_len = 0;
4642 struct ea_list *ea_file_list = NULL;
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4646 /*TODO: add filtering and index handling */
4648 status =
4649 get_ea_list_from_file(mem_ctx, conn, fsp,
4650 smb_fname,
4651 &total_ea_len, &ea_file_list);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 return status;
4655 if (!ea_file_list) {
4656 return NT_STATUS_NO_EAS_ON_FILE;
4659 status = fill_ea_chained_buffer(mem_ctx,
4660 pdata,
4661 data_size,
4662 &data_size,
4663 conn, ea_file_list);
4664 if (!NT_STATUS_IS_OK(status)) {
4665 return status;
4667 break;
4670 case SMB_FILE_BASIC_INFORMATION:
4671 case SMB_QUERY_FILE_BASIC_INFO:
4673 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4675 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4676 } else {
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4678 data_size = 40;
4679 SIVAL(pdata,36,0);
4681 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4682 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4683 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4684 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4685 SIVAL(pdata,32,mode);
4687 DEBUG(5,("SMB_QFBI - "));
4688 DEBUG(5,("create: %s ", ctime(&create_time)));
4689 DEBUG(5,("access: %s ", ctime(&atime)));
4690 DEBUG(5,("write: %s ", ctime(&mtime)));
4691 DEBUG(5,("change: %s ", ctime(&c_time)));
4692 DEBUG(5,("mode: %x\n", mode));
4693 break;
4695 case SMB_FILE_STANDARD_INFORMATION:
4696 case SMB_QUERY_FILE_STANDARD_INFO:
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4699 data_size = 24;
4700 SOFF_T(pdata,0,allocation_size);
4701 SOFF_T(pdata,8,file_size);
4702 SIVAL(pdata,16,nlink);
4703 SCVAL(pdata,20,delete_pending?1:0);
4704 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4705 SSVAL(pdata,22,0); /* Padding. */
4706 break;
4708 case SMB_FILE_EA_INFORMATION:
4709 case SMB_QUERY_FILE_EA_INFO:
4711 unsigned int ea_size =
4712 estimate_ea_size(conn, fsp, smb_fname);
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4714 data_size = 4;
4715 SIVAL(pdata,0,ea_size);
4716 break;
4719 /* Get the 8.3 name - used if NT SMB was negotiated. */
4720 case SMB_QUERY_FILE_ALT_NAME_INFO:
4721 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4723 int len;
4724 char mangled_name[13];
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4726 if (!name_to_8_3(base_name,mangled_name,
4727 True,conn->params)) {
4728 return NT_STATUS_NO_MEMORY;
4730 len = srvstr_push(dstart, flags2,
4731 pdata+4, mangled_name,
4732 PTR_DIFF(dend, pdata+4),
4733 STR_UNICODE);
4734 data_size = 4 + len;
4735 SIVAL(pdata,0,len);
4736 break;
4739 case SMB_QUERY_FILE_NAME_INFO:
4741 int len;
4743 this must be *exactly* right for ACLs on mapped drives to work
4745 len = srvstr_push(dstart, flags2,
4746 pdata+4, dos_fname,
4747 PTR_DIFF(dend, pdata+4),
4748 STR_UNICODE);
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4750 data_size = 4 + len;
4751 SIVAL(pdata,0,len);
4752 break;
4755 case SMB_FILE_ALLOCATION_INFORMATION:
4756 case SMB_QUERY_FILE_ALLOCATION_INFO:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4758 data_size = 8;
4759 SOFF_T(pdata,0,allocation_size);
4760 break;
4762 case SMB_FILE_END_OF_FILE_INFORMATION:
4763 case SMB_QUERY_FILE_END_OF_FILEINFO:
4764 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4765 data_size = 8;
4766 SOFF_T(pdata,0,file_size);
4767 break;
4769 case SMB_QUERY_FILE_ALL_INFO:
4770 case SMB_FILE_ALL_INFORMATION:
4772 int len;
4773 unsigned int ea_size =
4774 estimate_ea_size(conn, fsp, smb_fname);
4775 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4776 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4777 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4778 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4779 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4780 SIVAL(pdata,32,mode);
4781 SIVAL(pdata,36,0); /* padding. */
4782 pdata += 40;
4783 SOFF_T(pdata,0,allocation_size);
4784 SOFF_T(pdata,8,file_size);
4785 SIVAL(pdata,16,nlink);
4786 SCVAL(pdata,20,delete_pending);
4787 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4788 SSVAL(pdata,22,0);
4789 pdata += 24;
4790 SIVAL(pdata,0,ea_size);
4791 pdata += 4; /* EA info */
4792 len = srvstr_push(dstart, flags2,
4793 pdata+4, dos_fname,
4794 PTR_DIFF(dend, pdata+4),
4795 STR_UNICODE);
4796 SIVAL(pdata,0,len);
4797 pdata += 4 + len;
4798 data_size = PTR_DIFF(pdata,(*ppdata));
4799 break;
4802 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4804 int len;
4805 unsigned int ea_size =
4806 estimate_ea_size(conn, fsp, smb_fname);
4807 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4808 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4809 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4810 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4811 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4812 SIVAL(pdata, 0x20, mode);
4813 SIVAL(pdata, 0x24, 0); /* padding. */
4814 SBVAL(pdata, 0x28, allocation_size);
4815 SBVAL(pdata, 0x30, file_size);
4816 SIVAL(pdata, 0x38, nlink);
4817 SCVAL(pdata, 0x3C, delete_pending);
4818 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4819 SSVAL(pdata, 0x3E, 0); /* padding */
4820 SBVAL(pdata, 0x40, file_index);
4821 SIVAL(pdata, 0x48, ea_size);
4822 SIVAL(pdata, 0x4C, access_mask);
4823 SBVAL(pdata, 0x50, pos);
4824 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4825 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4827 pdata += 0x60;
4829 len = srvstr_push(dstart, flags2,
4830 pdata+4, dos_fname,
4831 PTR_DIFF(dend, pdata+4),
4832 STR_UNICODE);
4833 SIVAL(pdata,0,len);
4834 pdata += 4 + len;
4835 data_size = PTR_DIFF(pdata,(*ppdata));
4836 break;
4838 case SMB_FILE_INTERNAL_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4841 SBVAL(pdata, 0, file_index);
4842 data_size = 8;
4843 break;
4845 case SMB_FILE_ACCESS_INFORMATION:
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4847 SIVAL(pdata, 0, access_mask);
4848 data_size = 4;
4849 break;
4851 case SMB_FILE_NAME_INFORMATION:
4852 /* Pathname with leading '\'. */
4854 size_t byte_len;
4855 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4856 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4857 SIVAL(pdata,0,byte_len);
4858 data_size = 4 + byte_len;
4859 break;
4862 case SMB_FILE_DISPOSITION_INFORMATION:
4863 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4864 data_size = 1;
4865 SCVAL(pdata,0,delete_pending);
4866 break;
4868 case SMB_FILE_POSITION_INFORMATION:
4869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4870 data_size = 8;
4871 SOFF_T(pdata,0,pos);
4872 break;
4874 case SMB_FILE_MODE_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4876 SIVAL(pdata,0,mode);
4877 data_size = 4;
4878 break;
4880 case SMB_FILE_ALIGNMENT_INFORMATION:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4882 SIVAL(pdata,0,0); /* No alignment needed. */
4883 data_size = 4;
4884 break;
4887 * NT4 server just returns "invalid query" to this - if we try
4888 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4889 * want this. JRA.
4891 /* The first statement above is false - verified using Thursby
4892 * client against NT4 -- gcolley.
4894 case SMB_QUERY_FILE_STREAM_INFO:
4895 case SMB_FILE_STREAM_INFORMATION: {
4896 unsigned int num_streams = 0;
4897 struct stream_struct *streams = NULL;
4899 DEBUG(10,("smbd_do_qfilepathinfo: "
4900 "SMB_FILE_STREAM_INFORMATION\n"));
4902 if (is_ntfs_stream_smb_fname(smb_fname)) {
4903 return NT_STATUS_INVALID_PARAMETER;
4906 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4907 talloc_tos(), &num_streams, &streams);
4909 if (!NT_STATUS_IS_OK(status)) {
4910 DEBUG(10, ("could not get stream info: %s\n",
4911 nt_errstr(status)));
4912 return status;
4915 status = marshall_stream_info(num_streams, streams,
4916 pdata, max_data_bytes,
4917 &data_size);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 DEBUG(10, ("marshall_stream_info failed: %s\n",
4921 nt_errstr(status)));
4922 TALLOC_FREE(streams);
4923 return status;
4926 TALLOC_FREE(streams);
4928 break;
4930 case SMB_QUERY_COMPRESSION_INFO:
4931 case SMB_FILE_COMPRESSION_INFORMATION:
4932 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4933 SOFF_T(pdata,0,file_size);
4934 SIVAL(pdata,8,0); /* ??? */
4935 SIVAL(pdata,12,0); /* ??? */
4936 data_size = 16;
4937 break;
4939 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4940 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4941 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4942 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4943 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4944 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4945 SOFF_T(pdata,32,allocation_size);
4946 SOFF_T(pdata,40,file_size);
4947 SIVAL(pdata,48,mode);
4948 SIVAL(pdata,52,0); /* ??? */
4949 data_size = 56;
4950 break;
4952 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4953 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4954 SIVAL(pdata,0,mode);
4955 SIVAL(pdata,4,0);
4956 data_size = 8;
4957 break;
4960 * CIFS UNIX Extensions.
4963 case SMB_QUERY_FILE_UNIX_BASIC:
4965 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4966 data_size = PTR_DIFF(pdata,(*ppdata));
4968 DEBUG(4,("smbd_do_qfilepathinfo: "
4969 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4970 dump_data(4, (uint8_t *)(*ppdata), data_size);
4972 break;
4974 case SMB_QUERY_FILE_UNIX_INFO2:
4976 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4977 data_size = PTR_DIFF(pdata,(*ppdata));
4980 int i;
4981 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4983 for (i=0; i<100; i++)
4984 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4985 DEBUG(4,("\n"));
4988 break;
4990 case SMB_QUERY_FILE_UNIX_LINK:
4992 int len;
4993 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4995 if (!buffer) {
4996 return NT_STATUS_NO_MEMORY;
4999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5000 #ifdef S_ISLNK
5001 if(!S_ISLNK(psbuf->st_ex_mode)) {
5002 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5004 #else
5005 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5006 #endif
5007 len = SMB_VFS_READLINK(conn,
5008 smb_fname->base_name,
5009 buffer, PATH_MAX);
5010 if (len == -1) {
5011 return map_nt_error_from_unix(errno);
5013 buffer[len] = 0;
5014 len = srvstr_push(dstart, flags2,
5015 pdata, buffer,
5016 PTR_DIFF(dend, pdata),
5017 STR_TERMINATE);
5018 pdata += len;
5019 data_size = PTR_DIFF(pdata,(*ppdata));
5021 break;
5024 #if defined(HAVE_POSIX_ACLS)
5025 case SMB_QUERY_POSIX_ACL:
5027 SMB_ACL_T file_acl = NULL;
5028 SMB_ACL_T def_acl = NULL;
5029 uint16 num_file_acls = 0;
5030 uint16 num_def_acls = 0;
5032 if (fsp && fsp->fh->fd != -1) {
5033 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5034 talloc_tos());
5035 } else {
5036 file_acl =
5037 SMB_VFS_SYS_ACL_GET_FILE(conn,
5038 smb_fname->base_name,
5039 SMB_ACL_TYPE_ACCESS,
5040 talloc_tos());
5043 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5044 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5045 "not implemented on "
5046 "filesystem containing %s\n",
5047 smb_fname->base_name));
5048 return NT_STATUS_NOT_IMPLEMENTED;
5051 if (S_ISDIR(psbuf->st_ex_mode)) {
5052 if (fsp && fsp->is_directory) {
5053 def_acl =
5054 SMB_VFS_SYS_ACL_GET_FILE(
5055 conn,
5056 fsp->fsp_name->base_name,
5057 SMB_ACL_TYPE_DEFAULT,
5058 talloc_tos());
5059 } else {
5060 def_acl =
5061 SMB_VFS_SYS_ACL_GET_FILE(
5062 conn,
5063 smb_fname->base_name,
5064 SMB_ACL_TYPE_DEFAULT,
5065 talloc_tos());
5067 def_acl = free_empty_sys_acl(conn, def_acl);
5070 num_file_acls = count_acl_entries(conn, file_acl);
5071 num_def_acls = count_acl_entries(conn, def_acl);
5073 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5074 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5075 data_size,
5076 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5077 SMB_POSIX_ACL_HEADER_SIZE) ));
5078 if (file_acl) {
5079 TALLOC_FREE(file_acl);
5081 if (def_acl) {
5082 TALLOC_FREE(def_acl);
5084 return NT_STATUS_BUFFER_TOO_SMALL;
5087 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5088 SSVAL(pdata,2,num_file_acls);
5089 SSVAL(pdata,4,num_def_acls);
5090 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5091 if (file_acl) {
5092 TALLOC_FREE(file_acl);
5094 if (def_acl) {
5095 TALLOC_FREE(def_acl);
5097 return NT_STATUS_INTERNAL_ERROR;
5099 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_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;
5109 if (file_acl) {
5110 TALLOC_FREE(file_acl);
5112 if (def_acl) {
5113 TALLOC_FREE(def_acl);
5115 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5116 break;
5118 #endif
5121 case SMB_QUERY_POSIX_LOCK:
5123 uint64_t count;
5124 uint64_t offset;
5125 uint64_t smblctx;
5126 enum brl_type lock_type;
5128 /* We need an open file with a real fd for this. */
5129 if (!fsp || fsp->fh->fd == -1) {
5130 return NT_STATUS_INVALID_LEVEL;
5133 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5134 return NT_STATUS_INVALID_PARAMETER;
5137 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5138 case POSIX_LOCK_TYPE_READ:
5139 lock_type = READ_LOCK;
5140 break;
5141 case POSIX_LOCK_TYPE_WRITE:
5142 lock_type = WRITE_LOCK;
5143 break;
5144 case POSIX_LOCK_TYPE_UNLOCK:
5145 default:
5146 /* There's no point in asking for an unlock... */
5147 return NT_STATUS_INVALID_PARAMETER;
5150 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5151 #if defined(HAVE_LONGLONG)
5152 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5153 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5154 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5155 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5156 #else /* HAVE_LONGLONG */
5157 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5158 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5159 #endif /* HAVE_LONGLONG */
5161 status = query_lock(fsp,
5162 &smblctx,
5163 &count,
5164 &offset,
5165 &lock_type,
5166 POSIX_LOCK);
5168 if (ERROR_WAS_LOCK_DENIED(status)) {
5169 /* Here we need to report who has it locked... */
5170 data_size = POSIX_LOCK_DATA_SIZE;
5172 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5173 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5174 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5175 #if defined(HAVE_LONGLONG)
5176 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5177 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5178 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5179 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5180 #else /* HAVE_LONGLONG */
5181 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5182 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5183 #endif /* HAVE_LONGLONG */
5185 } else if (NT_STATUS_IS_OK(status)) {
5186 /* For success we just return a copy of what we sent
5187 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5188 data_size = POSIX_LOCK_DATA_SIZE;
5189 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5190 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5191 } else {
5192 return status;
5194 break;
5197 default:
5198 return NT_STATUS_INVALID_LEVEL;
5201 *pdata_size = data_size;
5202 return NT_STATUS_OK;
5205 /****************************************************************************
5206 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5207 file name or file id).
5208 ****************************************************************************/
5210 static void call_trans2qfilepathinfo(connection_struct *conn,
5211 struct smb_request *req,
5212 unsigned int tran_call,
5213 char **pparams, int total_params,
5214 char **ppdata, int total_data,
5215 unsigned int max_data_bytes)
5217 char *params = *pparams;
5218 char *pdata = *ppdata;
5219 uint16 info_level;
5220 unsigned int data_size = 0;
5221 unsigned int param_size = 2;
5222 struct smb_filename *smb_fname = NULL;
5223 bool delete_pending = False;
5224 struct timespec write_time_ts;
5225 files_struct *fsp = NULL;
5226 struct file_id fileid;
5227 struct ea_list *ea_list = NULL;
5228 int lock_data_count = 0;
5229 char *lock_data = NULL;
5230 NTSTATUS status = NT_STATUS_OK;
5232 if (!params) {
5233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5234 return;
5237 ZERO_STRUCT(write_time_ts);
5239 if (tran_call == TRANSACT2_QFILEINFO) {
5240 if (total_params < 4) {
5241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5242 return;
5245 if (IS_IPC(conn)) {
5246 call_trans2qpipeinfo(conn, req, tran_call,
5247 pparams, total_params,
5248 ppdata, total_data,
5249 max_data_bytes);
5250 return;
5253 fsp = file_fsp(req, SVAL(params,0));
5254 info_level = SVAL(params,2);
5256 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5258 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5259 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5260 return;
5263 /* Initial check for valid fsp ptr. */
5264 if (!check_fsp_open(conn, req, fsp)) {
5265 return;
5268 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5269 if (smb_fname == NULL) {
5270 reply_nterror(req, NT_STATUS_NO_MEMORY);
5271 return;
5274 if(fsp->fake_file_handle) {
5276 * This is actually for the QUOTA_FAKE_FILE --metze
5279 /* We know this name is ok, it's already passed the checks. */
5281 } else if(fsp->fh->fd == -1) {
5283 * This is actually a QFILEINFO on a directory
5284 * handle (returned from an NT SMB). NT5.0 seems
5285 * to do this call. JRA.
5288 if (INFO_LEVEL_IS_UNIX(info_level)) {
5289 /* Always do lstat for UNIX calls. */
5290 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5291 DEBUG(3,("call_trans2qfilepathinfo: "
5292 "SMB_VFS_LSTAT of %s failed "
5293 "(%s)\n",
5294 smb_fname_str_dbg(smb_fname),
5295 strerror(errno)));
5296 reply_nterror(req,
5297 map_nt_error_from_unix(errno));
5298 return;
5300 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5301 DEBUG(3,("call_trans2qfilepathinfo: "
5302 "SMB_VFS_STAT of %s failed (%s)\n",
5303 smb_fname_str_dbg(smb_fname),
5304 strerror(errno)));
5305 reply_nterror(req,
5306 map_nt_error_from_unix(errno));
5307 return;
5310 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5311 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5312 } else {
5314 * Original code - this is an open file.
5316 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5317 DEBUG(3, ("fstat of %s failed (%s)\n",
5318 fsp_fnum_dbg(fsp), strerror(errno)));
5319 reply_nterror(req,
5320 map_nt_error_from_unix(errno));
5321 return;
5323 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5324 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5327 } else {
5328 uint32_t name_hash;
5329 char *fname = NULL;
5330 uint32_t ucf_flags = 0;
5332 /* qpathinfo */
5333 if (total_params < 7) {
5334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5335 return;
5338 info_level = SVAL(params,0);
5340 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5342 if (INFO_LEVEL_IS_UNIX(info_level)) {
5343 if (!lp_unix_extensions()) {
5344 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5345 return;
5347 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5348 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5349 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5350 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5354 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5355 total_params - 6,
5356 STR_TERMINATE, &status);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 reply_nterror(req, status);
5359 return;
5362 status = filename_convert(req,
5363 conn,
5364 req->flags2 & FLAGS2_DFS_PATHNAMES,
5365 fname,
5366 ucf_flags,
5367 NULL,
5368 &smb_fname);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5371 reply_botherror(req,
5372 NT_STATUS_PATH_NOT_COVERED,
5373 ERRSRV, ERRbadpath);
5374 return;
5376 reply_nterror(req, status);
5377 return;
5380 /* If this is a stream, check if there is a delete_pending. */
5381 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5382 && is_ntfs_stream_smb_fname(smb_fname)) {
5383 struct smb_filename *smb_fname_base;
5385 /* Create an smb_filename with stream_name == NULL. */
5386 smb_fname_base = synthetic_smb_fname(
5387 talloc_tos(), smb_fname->base_name,
5388 NULL, NULL);
5389 if (smb_fname_base == NULL) {
5390 reply_nterror(req, NT_STATUS_NO_MEMORY);
5391 return;
5394 if (INFO_LEVEL_IS_UNIX(info_level)) {
5395 /* Always do lstat for UNIX calls. */
5396 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5397 DEBUG(3,("call_trans2qfilepathinfo: "
5398 "SMB_VFS_LSTAT of %s failed "
5399 "(%s)\n",
5400 smb_fname_str_dbg(smb_fname_base),
5401 strerror(errno)));
5402 TALLOC_FREE(smb_fname_base);
5403 reply_nterror(req,
5404 map_nt_error_from_unix(errno));
5405 return;
5407 } else {
5408 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5409 DEBUG(3,("call_trans2qfilepathinfo: "
5410 "fileinfo 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;
5421 status = file_name_hash(conn,
5422 smb_fname_str_dbg(smb_fname_base),
5423 &name_hash);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 TALLOC_FREE(smb_fname_base);
5426 reply_nterror(req, status);
5427 return;
5430 fileid = vfs_file_id_from_sbuf(conn,
5431 &smb_fname_base->st);
5432 TALLOC_FREE(smb_fname_base);
5433 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5434 if (delete_pending) {
5435 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5436 return;
5440 if (INFO_LEVEL_IS_UNIX(info_level)) {
5441 /* Always do lstat for UNIX calls. */
5442 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5443 DEBUG(3,("call_trans2qfilepathinfo: "
5444 "SMB_VFS_LSTAT of %s failed (%s)\n",
5445 smb_fname_str_dbg(smb_fname),
5446 strerror(errno)));
5447 reply_nterror(req,
5448 map_nt_error_from_unix(errno));
5449 return;
5452 } else {
5453 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5454 DEBUG(3,("call_trans2qfilepathinfo: "
5455 "SMB_VFS_STAT of %s failed (%s)\n",
5456 smb_fname_str_dbg(smb_fname),
5457 strerror(errno)));
5458 reply_nterror(req,
5459 map_nt_error_from_unix(errno));
5460 return;
5464 status = file_name_hash(conn,
5465 smb_fname_str_dbg(smb_fname),
5466 &name_hash);
5467 if (!NT_STATUS_IS_OK(status)) {
5468 reply_nterror(req, status);
5469 return;
5472 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5473 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5474 if (delete_pending) {
5475 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5476 return;
5480 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5481 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5482 fsp_fnum_dbg(fsp),
5483 info_level,tran_call,total_data));
5485 /* Pull out any data sent here before we realloc. */
5486 switch (info_level) {
5487 case SMB_INFO_QUERY_EAS_FROM_LIST:
5489 /* Pull any EA list from the data portion. */
5490 uint32 ea_size;
5492 if (total_data < 4) {
5493 reply_nterror(
5494 req, NT_STATUS_INVALID_PARAMETER);
5495 return;
5497 ea_size = IVAL(pdata,0);
5499 if (total_data > 0 && ea_size != total_data) {
5500 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5501 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5502 reply_nterror(
5503 req, NT_STATUS_INVALID_PARAMETER);
5504 return;
5507 if (!lp_ea_support(SNUM(conn))) {
5508 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5509 return;
5512 /* Pull out the list of names. */
5513 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5514 if (!ea_list) {
5515 reply_nterror(
5516 req, NT_STATUS_INVALID_PARAMETER);
5517 return;
5519 break;
5522 case SMB_QUERY_POSIX_LOCK:
5524 if (fsp == NULL || fsp->fh->fd == -1) {
5525 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5526 return;
5529 if (total_data != POSIX_LOCK_DATA_SIZE) {
5530 reply_nterror(
5531 req, NT_STATUS_INVALID_PARAMETER);
5532 return;
5535 /* Copy the lock range data. */
5536 lock_data = (char *)talloc_memdup(
5537 req, pdata, total_data);
5538 if (!lock_data) {
5539 reply_nterror(req, NT_STATUS_NO_MEMORY);
5540 return;
5542 lock_data_count = total_data;
5544 default:
5545 break;
5548 *pparams = (char *)SMB_REALLOC(*pparams,2);
5549 if (*pparams == NULL) {
5550 reply_nterror(req, NT_STATUS_NO_MEMORY);
5551 return;
5553 params = *pparams;
5554 SSVAL(params,0,0);
5557 * draft-leach-cifs-v1-spec-02.txt
5558 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5559 * says:
5561 * The requested information is placed in the Data portion of the
5562 * transaction response. For the information levels greater than 0x100,
5563 * the transaction response has 1 parameter word which should be
5564 * ignored by the client.
5566 * However Windows only follows this rule for the IS_NAME_VALID call.
5568 switch (info_level) {
5569 case SMB_INFO_IS_NAME_VALID:
5570 param_size = 0;
5571 break;
5574 if ((info_level & 0xFF00) == 0xFF00) {
5576 * We use levels that start with 0xFF00
5577 * internally to represent SMB2 specific levels
5579 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5580 return;
5583 status = smbd_do_qfilepathinfo(conn, req, info_level,
5584 fsp, smb_fname,
5585 delete_pending, write_time_ts,
5586 ea_list,
5587 lock_data_count, lock_data,
5588 req->flags2, max_data_bytes,
5589 ppdata, &data_size);
5590 if (!NT_STATUS_IS_OK(status)) {
5591 reply_nterror(req, status);
5592 return;
5595 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5596 max_data_bytes);
5598 return;
5601 /****************************************************************************
5602 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5603 code.
5604 ****************************************************************************/
5606 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5607 connection_struct *conn,
5608 struct smb_request *req,
5609 bool overwrite_if_exists,
5610 const struct smb_filename *smb_fname_old,
5611 struct smb_filename *smb_fname_new)
5613 NTSTATUS status = NT_STATUS_OK;
5615 /* source must already exist. */
5616 if (!VALID_STAT(smb_fname_old->st)) {
5617 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5620 if (VALID_STAT(smb_fname_new->st)) {
5621 if (overwrite_if_exists) {
5622 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5623 return NT_STATUS_FILE_IS_A_DIRECTORY;
5625 status = unlink_internals(conn,
5626 req,
5627 FILE_ATTRIBUTE_NORMAL,
5628 smb_fname_new,
5629 false);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 return status;
5633 } else {
5634 /* Disallow if newname already exists. */
5635 return NT_STATUS_OBJECT_NAME_COLLISION;
5639 /* No links from a directory. */
5640 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5641 return NT_STATUS_FILE_IS_A_DIRECTORY;
5644 /* Setting a hardlink to/from a stream isn't currently supported. */
5645 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5646 is_ntfs_stream_smb_fname(smb_fname_new)) {
5647 return NT_STATUS_INVALID_PARAMETER;
5650 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5651 smb_fname_old->base_name, smb_fname_new->base_name));
5653 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5654 smb_fname_new->base_name) != 0) {
5655 status = map_nt_error_from_unix(errno);
5656 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5657 nt_errstr(status), smb_fname_old->base_name,
5658 smb_fname_new->base_name));
5660 return status;
5663 /****************************************************************************
5664 Deal with setting the time from any of the setfilepathinfo functions.
5665 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5666 calling this function.
5667 ****************************************************************************/
5669 NTSTATUS smb_set_file_time(connection_struct *conn,
5670 files_struct *fsp,
5671 const struct smb_filename *smb_fname,
5672 struct smb_file_time *ft,
5673 bool setting_write_time)
5675 struct smb_filename smb_fname_base;
5676 uint32 action =
5677 FILE_NOTIFY_CHANGE_LAST_ACCESS
5678 |FILE_NOTIFY_CHANGE_LAST_WRITE
5679 |FILE_NOTIFY_CHANGE_CREATION;
5681 if (!VALID_STAT(smb_fname->st)) {
5682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5685 /* get some defaults (no modifications) if any info is zero or -1. */
5686 if (null_timespec(ft->create_time)) {
5687 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5690 if (null_timespec(ft->atime)) {
5691 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5694 if (null_timespec(ft->mtime)) {
5695 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5698 if (!setting_write_time) {
5699 /* ft->mtime comes from change time, not write time. */
5700 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5703 /* Ensure the resolution is the correct for
5704 * what we can store on this filesystem. */
5706 round_timespec(conn->ts_res, &ft->create_time);
5707 round_timespec(conn->ts_res, &ft->ctime);
5708 round_timespec(conn->ts_res, &ft->atime);
5709 round_timespec(conn->ts_res, &ft->mtime);
5711 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5712 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5713 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5714 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5715 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5716 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5717 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5718 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5720 if (setting_write_time) {
5722 * This was a Windows setfileinfo on an open file.
5723 * NT does this a lot. We also need to
5724 * set the time here, as it can be read by
5725 * FindFirst/FindNext and with the patch for bug #2045
5726 * in smbd/fileio.c it ensures that this timestamp is
5727 * kept sticky even after a write. We save the request
5728 * away and will set it on file close and after a write. JRA.
5731 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5732 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5734 if (fsp != NULL) {
5735 if (fsp->base_fsp) {
5736 set_sticky_write_time_fsp(fsp->base_fsp,
5737 ft->mtime);
5738 } else {
5739 set_sticky_write_time_fsp(fsp, ft->mtime);
5741 } else {
5742 set_sticky_write_time_path(
5743 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5744 ft->mtime);
5748 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5750 /* Always call ntimes on the base, even if a stream was passed in. */
5751 smb_fname_base = *smb_fname;
5752 smb_fname_base.stream_name = NULL;
5754 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5755 return map_nt_error_from_unix(errno);
5758 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5759 smb_fname->base_name);
5760 return NT_STATUS_OK;
5763 /****************************************************************************
5764 Deal with setting the dosmode from any of the setfilepathinfo functions.
5765 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5766 done before calling this function.
5767 ****************************************************************************/
5769 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5770 const struct smb_filename *smb_fname,
5771 uint32 dosmode)
5773 struct smb_filename *smb_fname_base;
5774 NTSTATUS status;
5776 if (!VALID_STAT(smb_fname->st)) {
5777 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5780 /* Always operate on the base_name, even if a stream was passed in. */
5781 smb_fname_base = synthetic_smb_fname(
5782 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5783 if (smb_fname_base == NULL) {
5784 return NT_STATUS_NO_MEMORY;
5787 if (dosmode) {
5788 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5789 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5790 } else {
5791 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5795 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5797 /* check the mode isn't different, before changing it */
5798 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5799 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5800 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5801 (unsigned int)dosmode));
5803 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5804 false)) {
5805 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5806 "%s failed (%s)\n",
5807 smb_fname_str_dbg(smb_fname_base),
5808 strerror(errno)));
5809 status = map_nt_error_from_unix(errno);
5810 goto out;
5813 status = NT_STATUS_OK;
5814 out:
5815 TALLOC_FREE(smb_fname_base);
5816 return status;
5819 /****************************************************************************
5820 Deal with setting the size from any of the setfilepathinfo functions.
5821 ****************************************************************************/
5823 static NTSTATUS smb_set_file_size(connection_struct *conn,
5824 struct smb_request *req,
5825 files_struct *fsp,
5826 const struct smb_filename *smb_fname,
5827 const SMB_STRUCT_STAT *psbuf,
5828 off_t size,
5829 bool fail_after_createfile)
5831 NTSTATUS status = NT_STATUS_OK;
5832 struct smb_filename *smb_fname_tmp = NULL;
5833 files_struct *new_fsp = NULL;
5835 if (!VALID_STAT(*psbuf)) {
5836 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5839 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5841 if (size == get_file_size_stat(psbuf)) {
5842 return NT_STATUS_OK;
5845 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5846 smb_fname_str_dbg(smb_fname), (double)size));
5848 if (fsp && fsp->fh->fd != -1) {
5849 /* Handle based call. */
5850 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5851 return NT_STATUS_ACCESS_DENIED;
5854 if (vfs_set_filelen(fsp, size) == -1) {
5855 return map_nt_error_from_unix(errno);
5857 trigger_write_time_update_immediate(fsp);
5858 return NT_STATUS_OK;
5861 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5862 if (smb_fname_tmp == NULL) {
5863 return NT_STATUS_NO_MEMORY;
5866 smb_fname_tmp->st = *psbuf;
5868 status = SMB_VFS_CREATE_FILE(
5869 conn, /* conn */
5870 req, /* req */
5871 0, /* root_dir_fid */
5872 smb_fname_tmp, /* fname */
5873 FILE_WRITE_DATA, /* access_mask */
5874 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5875 FILE_SHARE_DELETE),
5876 FILE_OPEN, /* create_disposition*/
5877 0, /* create_options */
5878 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5879 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5880 0, /* allocation_size */
5881 0, /* private_flags */
5882 NULL, /* sd */
5883 NULL, /* ea_list */
5884 &new_fsp, /* result */
5885 NULL); /* pinfo */
5887 TALLOC_FREE(smb_fname_tmp);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 /* NB. We check for open_was_deferred in the caller. */
5891 return status;
5894 /* See RAW-SFILEINFO-END-OF-FILE */
5895 if (fail_after_createfile) {
5896 close_file(req, new_fsp,NORMAL_CLOSE);
5897 return NT_STATUS_INVALID_LEVEL;
5900 if (vfs_set_filelen(new_fsp, size) == -1) {
5901 status = map_nt_error_from_unix(errno);
5902 close_file(req, new_fsp,NORMAL_CLOSE);
5903 return status;
5906 trigger_write_time_update_immediate(new_fsp);
5907 close_file(req, new_fsp,NORMAL_CLOSE);
5908 return NT_STATUS_OK;
5911 /****************************************************************************
5912 Deal with SMB_INFO_SET_EA.
5913 ****************************************************************************/
5915 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5916 const char *pdata,
5917 int total_data,
5918 files_struct *fsp,
5919 const struct smb_filename *smb_fname)
5921 struct ea_list *ea_list = NULL;
5922 TALLOC_CTX *ctx = NULL;
5923 NTSTATUS status = NT_STATUS_OK;
5925 if (total_data < 10) {
5927 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5928 length. They seem to have no effect. Bug #3212. JRA */
5930 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5931 /* We're done. We only get EA info in this call. */
5932 return NT_STATUS_OK;
5935 return NT_STATUS_INVALID_PARAMETER;
5938 if (IVAL(pdata,0) > total_data) {
5939 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5940 IVAL(pdata,0), (unsigned int)total_data));
5941 return NT_STATUS_INVALID_PARAMETER;
5944 ctx = talloc_tos();
5945 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5946 if (!ea_list) {
5947 return NT_STATUS_INVALID_PARAMETER;
5950 status = set_ea(conn, fsp, smb_fname, ea_list);
5952 return status;
5955 /****************************************************************************
5956 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5957 ****************************************************************************/
5959 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5960 const char *pdata,
5961 int total_data,
5962 files_struct *fsp)
5964 struct ea_list *ea_list = NULL;
5965 NTSTATUS status;
5967 if (!fsp) {
5968 return NT_STATUS_INVALID_HANDLE;
5971 if (!lp_ea_support(SNUM(conn))) {
5972 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5973 "EA's not supported.\n",
5974 (unsigned int)total_data));
5975 return NT_STATUS_EAS_NOT_SUPPORTED;
5978 if (total_data < 10) {
5979 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5980 "too small.\n",
5981 (unsigned int)total_data));
5982 return NT_STATUS_INVALID_PARAMETER;
5985 ea_list = read_nttrans_ea_list(talloc_tos(),
5986 pdata,
5987 total_data);
5989 if (!ea_list) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5995 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5996 smb_fname_str_dbg(fsp->fsp_name),
5997 nt_errstr(status) ));
5999 return status;
6003 /****************************************************************************
6004 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6005 ****************************************************************************/
6007 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6008 const char *pdata,
6009 int total_data,
6010 files_struct *fsp,
6011 struct smb_filename *smb_fname)
6013 NTSTATUS status = NT_STATUS_OK;
6014 bool delete_on_close;
6015 uint32 dosmode = 0;
6017 if (total_data < 1) {
6018 return NT_STATUS_INVALID_PARAMETER;
6021 if (fsp == NULL) {
6022 return NT_STATUS_INVALID_HANDLE;
6025 delete_on_close = (CVAL(pdata,0) ? True : False);
6026 dosmode = dos_mode(conn, smb_fname);
6028 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6029 "delete_on_close = %u\n",
6030 smb_fname_str_dbg(smb_fname),
6031 (unsigned int)dosmode,
6032 (unsigned int)delete_on_close ));
6034 if (delete_on_close) {
6035 status = can_set_delete_on_close(fsp, dosmode);
6036 if (!NT_STATUS_IS_OK(status)) {
6037 return status;
6041 /* The set is across all open files on this dev/inode pair. */
6042 if (!set_delete_on_close(fsp, delete_on_close,
6043 conn->session_info->security_token,
6044 conn->session_info->unix_token)) {
6045 return NT_STATUS_ACCESS_DENIED;
6047 return NT_STATUS_OK;
6050 /****************************************************************************
6051 Deal with SMB_FILE_POSITION_INFORMATION.
6052 ****************************************************************************/
6054 static NTSTATUS smb_file_position_information(connection_struct *conn,
6055 const char *pdata,
6056 int total_data,
6057 files_struct *fsp)
6059 uint64_t position_information;
6061 if (total_data < 8) {
6062 return NT_STATUS_INVALID_PARAMETER;
6065 if (fsp == NULL) {
6066 /* Ignore on pathname based set. */
6067 return NT_STATUS_OK;
6070 position_information = (uint64_t)IVAL(pdata,0);
6071 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6073 DEBUG(10,("smb_file_position_information: Set file position "
6074 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6075 (double)position_information));
6076 fsp->fh->position_information = position_information;
6077 return NT_STATUS_OK;
6080 /****************************************************************************
6081 Deal with SMB_FILE_MODE_INFORMATION.
6082 ****************************************************************************/
6084 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6085 const char *pdata,
6086 int total_data)
6088 uint32 mode;
6090 if (total_data < 4) {
6091 return NT_STATUS_INVALID_PARAMETER;
6093 mode = IVAL(pdata,0);
6094 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6095 return NT_STATUS_INVALID_PARAMETER;
6097 return NT_STATUS_OK;
6100 /****************************************************************************
6101 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6102 ****************************************************************************/
6104 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6105 struct smb_request *req,
6106 const char *pdata,
6107 int total_data,
6108 const struct smb_filename *smb_fname)
6110 char *link_target = NULL;
6111 const char *newname = smb_fname->base_name;
6112 TALLOC_CTX *ctx = talloc_tos();
6114 /* Set a symbolic link. */
6115 /* Don't allow this if follow links is false. */
6117 if (total_data == 0) {
6118 return NT_STATUS_INVALID_PARAMETER;
6121 if (!lp_symlinks(SNUM(conn))) {
6122 return NT_STATUS_ACCESS_DENIED;
6125 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6126 total_data, STR_TERMINATE);
6128 if (!link_target) {
6129 return NT_STATUS_INVALID_PARAMETER;
6132 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6133 newname, link_target ));
6135 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6136 return map_nt_error_from_unix(errno);
6139 return NT_STATUS_OK;
6142 /****************************************************************************
6143 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6144 ****************************************************************************/
6146 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6147 struct smb_request *req,
6148 const char *pdata, int total_data,
6149 struct smb_filename *smb_fname_new)
6151 char *oldname = NULL;
6152 struct smb_filename *smb_fname_old = NULL;
6153 TALLOC_CTX *ctx = talloc_tos();
6154 NTSTATUS status = NT_STATUS_OK;
6156 /* Set a hard link. */
6157 if (total_data == 0) {
6158 return NT_STATUS_INVALID_PARAMETER;
6161 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6162 total_data, STR_TERMINATE, &status);
6163 if (!NT_STATUS_IS_OK(status)) {
6164 return status;
6167 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6168 smb_fname_str_dbg(smb_fname_new), oldname));
6170 status = filename_convert(ctx,
6171 conn,
6172 req->flags2 & FLAGS2_DFS_PATHNAMES,
6173 oldname,
6175 NULL,
6176 &smb_fname_old);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 return status;
6181 return hardlink_internals(ctx, conn, req, false,
6182 smb_fname_old, smb_fname_new);
6185 /****************************************************************************
6186 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6187 ****************************************************************************/
6189 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6190 struct smb_request *req,
6191 const char *pdata,
6192 int total_data,
6193 files_struct *fsp,
6194 struct smb_filename *smb_fname_src)
6196 bool overwrite;
6197 uint32_t len;
6198 char *newname = NULL;
6199 struct smb_filename *smb_fname_dst = NULL;
6200 NTSTATUS status = NT_STATUS_OK;
6201 TALLOC_CTX *ctx = talloc_tos();
6203 if (!fsp) {
6204 return NT_STATUS_INVALID_HANDLE;
6207 if (total_data < 20) {
6208 return NT_STATUS_INVALID_PARAMETER;
6211 overwrite = (CVAL(pdata,0) ? True : False);
6212 len = IVAL(pdata,16);
6214 if (len > (total_data - 20) || (len == 0)) {
6215 return NT_STATUS_INVALID_PARAMETER;
6218 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6219 &pdata[20], len, STR_TERMINATE,
6220 &status);
6221 if (!NT_STATUS_IS_OK(status)) {
6222 return status;
6225 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6226 newname));
6228 status = filename_convert(ctx,
6229 conn,
6230 req->flags2 & FLAGS2_DFS_PATHNAMES,
6231 newname,
6232 UCF_SAVE_LCOMP,
6233 NULL,
6234 &smb_fname_dst);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 return status;
6239 if (fsp->base_fsp) {
6240 /* newname must be a stream name. */
6241 if (newname[0] != ':') {
6242 return NT_STATUS_NOT_SUPPORTED;
6245 /* Create an smb_fname to call rename_internals_fsp() with. */
6246 smb_fname_dst = synthetic_smb_fname(
6247 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6248 newname, NULL);
6249 if (smb_fname_dst == NULL) {
6250 status = NT_STATUS_NO_MEMORY;
6251 goto out;
6255 * Set the original last component, since
6256 * rename_internals_fsp() requires it.
6258 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6259 newname);
6260 if (smb_fname_dst->original_lcomp == NULL) {
6261 status = NT_STATUS_NO_MEMORY;
6262 goto out;
6267 DEBUG(10,("smb2_file_rename_information: "
6268 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6269 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6270 smb_fname_str_dbg(smb_fname_dst)));
6271 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6272 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6273 overwrite);
6275 out:
6276 TALLOC_FREE(smb_fname_dst);
6277 return status;
6280 static NTSTATUS smb_file_link_information(connection_struct *conn,
6281 struct smb_request *req,
6282 const char *pdata,
6283 int total_data,
6284 files_struct *fsp,
6285 struct smb_filename *smb_fname_src)
6287 bool overwrite;
6288 uint32_t len;
6289 char *newname = NULL;
6290 struct smb_filename *smb_fname_dst = NULL;
6291 NTSTATUS status = NT_STATUS_OK;
6292 TALLOC_CTX *ctx = talloc_tos();
6294 if (!fsp) {
6295 return NT_STATUS_INVALID_HANDLE;
6298 if (total_data < 20) {
6299 return NT_STATUS_INVALID_PARAMETER;
6302 overwrite = (CVAL(pdata,0) ? true : false);
6303 len = IVAL(pdata,16);
6305 if (len > (total_data - 20) || (len == 0)) {
6306 return NT_STATUS_INVALID_PARAMETER;
6309 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6310 &pdata[20], len, STR_TERMINATE,
6311 &status);
6312 if (!NT_STATUS_IS_OK(status)) {
6313 return status;
6316 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6317 newname));
6319 status = filename_convert(ctx,
6320 conn,
6321 req->flags2 & FLAGS2_DFS_PATHNAMES,
6322 newname,
6323 UCF_SAVE_LCOMP,
6324 NULL,
6325 &smb_fname_dst);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 return status;
6330 if (fsp->base_fsp) {
6331 /* No stream names. */
6332 return NT_STATUS_NOT_SUPPORTED;
6335 DEBUG(10,("smb_file_link_information: "
6336 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6337 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6338 smb_fname_str_dbg(smb_fname_dst)));
6339 status = hardlink_internals(ctx,
6340 conn,
6341 req,
6342 overwrite,
6343 fsp->fsp_name,
6344 smb_fname_dst);
6346 TALLOC_FREE(smb_fname_dst);
6347 return status;
6350 /****************************************************************************
6351 Deal with SMB_FILE_RENAME_INFORMATION.
6352 ****************************************************************************/
6354 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6355 struct smb_request *req,
6356 const char *pdata,
6357 int total_data,
6358 files_struct *fsp,
6359 struct smb_filename *smb_fname_src)
6361 bool overwrite;
6362 uint32 root_fid;
6363 uint32 len;
6364 char *newname = NULL;
6365 struct smb_filename *smb_fname_dst = NULL;
6366 bool dest_has_wcard = False;
6367 NTSTATUS status = NT_STATUS_OK;
6368 char *p;
6369 TALLOC_CTX *ctx = talloc_tos();
6371 if (total_data < 13) {
6372 return NT_STATUS_INVALID_PARAMETER;
6375 overwrite = (CVAL(pdata,0) ? True : False);
6376 root_fid = IVAL(pdata,4);
6377 len = IVAL(pdata,8);
6379 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6380 return NT_STATUS_INVALID_PARAMETER;
6383 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6384 len, 0, &status,
6385 &dest_has_wcard);
6386 if (!NT_STATUS_IS_OK(status)) {
6387 return status;
6390 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6391 newname));
6393 status = resolve_dfspath_wcard(ctx, conn,
6394 req->flags2 & FLAGS2_DFS_PATHNAMES,
6395 newname,
6396 true,
6397 !conn->sconn->using_smb2,
6398 &newname,
6399 &dest_has_wcard);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 return status;
6404 /* Check the new name has no '/' characters. */
6405 if (strchr_m(newname, '/')) {
6406 return NT_STATUS_NOT_SUPPORTED;
6409 if (fsp && fsp->base_fsp) {
6410 /* newname must be a stream name. */
6411 if (newname[0] != ':') {
6412 return NT_STATUS_NOT_SUPPORTED;
6415 /* Create an smb_fname to call rename_internals_fsp() with. */
6416 smb_fname_dst = synthetic_smb_fname(
6417 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6418 newname, NULL);
6419 if (smb_fname_dst == NULL) {
6420 status = NT_STATUS_NO_MEMORY;
6421 goto out;
6425 * Set the original last component, since
6426 * rename_internals_fsp() requires it.
6428 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6429 newname);
6430 if (smb_fname_dst->original_lcomp == NULL) {
6431 status = NT_STATUS_NO_MEMORY;
6432 goto out;
6435 } else {
6437 * Build up an smb_fname_dst based on the filename passed in.
6438 * We basically just strip off the last component, and put on
6439 * the newname instead.
6441 char *base_name = NULL;
6443 /* newname must *not* be a stream name. */
6444 if (newname[0] == ':') {
6445 return NT_STATUS_NOT_SUPPORTED;
6449 * Strip off the last component (filename) of the path passed
6450 * in.
6452 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6453 if (!base_name) {
6454 return NT_STATUS_NO_MEMORY;
6456 p = strrchr_m(base_name, '/');
6457 if (p) {
6458 p[1] = '\0';
6459 } else {
6460 base_name = talloc_strdup(ctx, "");
6461 if (!base_name) {
6462 return NT_STATUS_NO_MEMORY;
6465 /* Append the new name. */
6466 base_name = talloc_asprintf_append(base_name,
6467 "%s",
6468 newname);
6469 if (!base_name) {
6470 return NT_STATUS_NO_MEMORY;
6473 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6474 (UCF_SAVE_LCOMP |
6475 (dest_has_wcard ?
6476 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6477 0)));
6479 /* If an error we expect this to be
6480 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6482 if (!NT_STATUS_IS_OK(status)) {
6483 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6484 status)) {
6485 goto out;
6487 /* Create an smb_fname to call rename_internals_fsp() */
6488 smb_fname_dst = synthetic_smb_fname(
6489 ctx, base_name, NULL, NULL);
6490 if (smb_fname_dst == NULL) {
6491 status = NT_STATUS_NO_MEMORY;
6492 goto out;
6497 if (fsp) {
6498 DEBUG(10,("smb_file_rename_information: "
6499 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6500 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6501 smb_fname_str_dbg(smb_fname_dst)));
6502 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6503 overwrite);
6504 } else {
6505 DEBUG(10,("smb_file_rename_information: "
6506 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6507 smb_fname_str_dbg(smb_fname_src),
6508 smb_fname_str_dbg(smb_fname_dst)));
6509 status = rename_internals(ctx, conn, req, smb_fname_src,
6510 smb_fname_dst, 0, overwrite, false,
6511 dest_has_wcard,
6512 FILE_WRITE_ATTRIBUTES);
6514 out:
6515 TALLOC_FREE(smb_fname_dst);
6516 return status;
6519 /****************************************************************************
6520 Deal with SMB_SET_POSIX_ACL.
6521 ****************************************************************************/
6523 #if defined(HAVE_POSIX_ACLS)
6524 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6525 const char *pdata,
6526 int total_data,
6527 files_struct *fsp,
6528 const struct smb_filename *smb_fname)
6530 uint16 posix_acl_version;
6531 uint16 num_file_acls;
6532 uint16 num_def_acls;
6533 bool valid_file_acls = True;
6534 bool valid_def_acls = True;
6536 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6537 return NT_STATUS_INVALID_PARAMETER;
6539 posix_acl_version = SVAL(pdata,0);
6540 num_file_acls = SVAL(pdata,2);
6541 num_def_acls = SVAL(pdata,4);
6543 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6544 valid_file_acls = False;
6545 num_file_acls = 0;
6548 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6549 valid_def_acls = False;
6550 num_def_acls = 0;
6553 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6558 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6559 return NT_STATUS_INVALID_PARAMETER;
6562 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6563 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6564 (unsigned int)num_file_acls,
6565 (unsigned int)num_def_acls));
6567 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6568 smb_fname->base_name, num_file_acls,
6569 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6570 return map_nt_error_from_unix(errno);
6573 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6574 smb_fname->base_name, &smb_fname->st, num_def_acls,
6575 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6576 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6577 return map_nt_error_from_unix(errno);
6579 return NT_STATUS_OK;
6581 #endif
6583 /****************************************************************************
6584 Deal with SMB_SET_POSIX_LOCK.
6585 ****************************************************************************/
6587 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6588 struct smb_request *req,
6589 const char *pdata,
6590 int total_data,
6591 files_struct *fsp)
6593 uint64_t count;
6594 uint64_t offset;
6595 uint64_t smblctx;
6596 bool blocking_lock = False;
6597 enum brl_type lock_type;
6599 NTSTATUS status = NT_STATUS_OK;
6601 if (fsp == NULL || fsp->fh->fd == -1) {
6602 return NT_STATUS_INVALID_HANDLE;
6605 if (total_data != POSIX_LOCK_DATA_SIZE) {
6606 return NT_STATUS_INVALID_PARAMETER;
6609 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6610 case POSIX_LOCK_TYPE_READ:
6611 lock_type = READ_LOCK;
6612 break;
6613 case POSIX_LOCK_TYPE_WRITE:
6614 /* Return the right POSIX-mappable error code for files opened read-only. */
6615 if (!fsp->can_write) {
6616 return NT_STATUS_INVALID_HANDLE;
6618 lock_type = WRITE_LOCK;
6619 break;
6620 case POSIX_LOCK_TYPE_UNLOCK:
6621 lock_type = UNLOCK_LOCK;
6622 break;
6623 default:
6624 return NT_STATUS_INVALID_PARAMETER;
6627 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6628 blocking_lock = False;
6629 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6630 blocking_lock = True;
6631 } else {
6632 return NT_STATUS_INVALID_PARAMETER;
6635 if (!lp_blocking_locks(SNUM(conn))) {
6636 blocking_lock = False;
6639 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6640 #if defined(HAVE_LONGLONG)
6641 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6642 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6643 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6644 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6645 #else /* HAVE_LONGLONG */
6646 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6647 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6648 #endif /* HAVE_LONGLONG */
6650 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6651 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6652 fsp_str_dbg(fsp),
6653 (unsigned int)lock_type,
6654 (unsigned long long)smblctx,
6655 (double)count,
6656 (double)offset ));
6658 if (lock_type == UNLOCK_LOCK) {
6659 status = do_unlock(req->sconn->msg_ctx,
6660 fsp,
6661 smblctx,
6662 count,
6663 offset,
6664 POSIX_LOCK);
6665 } else {
6666 uint64_t block_smblctx;
6668 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6669 fsp,
6670 smblctx,
6671 count,
6672 offset,
6673 lock_type,
6674 POSIX_LOCK,
6675 blocking_lock,
6676 &status,
6677 &block_smblctx,
6678 NULL);
6680 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6682 * A blocking lock was requested. Package up
6683 * this smb into a queued request and push it
6684 * onto the blocking lock queue.
6686 if(push_blocking_lock_request(br_lck,
6687 req,
6688 fsp,
6689 -1, /* infinite timeout. */
6691 smblctx,
6692 lock_type,
6693 POSIX_LOCK,
6694 offset,
6695 count,
6696 block_smblctx)) {
6697 TALLOC_FREE(br_lck);
6698 return status;
6701 TALLOC_FREE(br_lck);
6704 return status;
6707 /****************************************************************************
6708 Deal with SMB_SET_FILE_BASIC_INFO.
6709 ****************************************************************************/
6711 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6712 const char *pdata,
6713 int total_data,
6714 files_struct *fsp,
6715 const struct smb_filename *smb_fname)
6717 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6718 struct smb_file_time ft;
6719 uint32 dosmode = 0;
6720 NTSTATUS status = NT_STATUS_OK;
6722 ZERO_STRUCT(ft);
6724 if (total_data < 36) {
6725 return NT_STATUS_INVALID_PARAMETER;
6728 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 return status;
6733 /* Set the attributes */
6734 dosmode = IVAL(pdata,32);
6735 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6736 if (!NT_STATUS_IS_OK(status)) {
6737 return status;
6740 /* create time */
6741 ft.create_time = interpret_long_date(pdata);
6743 /* access time */
6744 ft.atime = interpret_long_date(pdata+8);
6746 /* write time. */
6747 ft.mtime = interpret_long_date(pdata+16);
6749 /* change time. */
6750 ft.ctime = interpret_long_date(pdata+24);
6752 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6753 smb_fname_str_dbg(smb_fname)));
6755 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6756 true);
6759 /****************************************************************************
6760 Deal with SMB_INFO_STANDARD.
6761 ****************************************************************************/
6763 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6764 const char *pdata,
6765 int total_data,
6766 files_struct *fsp,
6767 const struct smb_filename *smb_fname)
6769 NTSTATUS status;
6770 struct smb_file_time ft;
6772 ZERO_STRUCT(ft);
6774 if (total_data < 12) {
6775 return NT_STATUS_INVALID_PARAMETER;
6778 /* create time */
6779 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6780 /* access time */
6781 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6782 /* write time */
6783 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6785 DEBUG(10,("smb_set_info_standard: file %s\n",
6786 smb_fname_str_dbg(smb_fname)));
6788 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 return status;
6793 return smb_set_file_time(conn,
6794 fsp,
6795 smb_fname,
6796 &ft,
6797 true);
6800 /****************************************************************************
6801 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6802 ****************************************************************************/
6804 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6805 struct smb_request *req,
6806 const char *pdata,
6807 int total_data,
6808 files_struct *fsp,
6809 struct smb_filename *smb_fname)
6811 uint64_t allocation_size = 0;
6812 NTSTATUS status = NT_STATUS_OK;
6813 files_struct *new_fsp = NULL;
6815 if (!VALID_STAT(smb_fname->st)) {
6816 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6819 if (total_data < 8) {
6820 return NT_STATUS_INVALID_PARAMETER;
6823 allocation_size = (uint64_t)IVAL(pdata,0);
6824 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6825 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6826 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6827 (double)allocation_size));
6829 if (allocation_size) {
6830 allocation_size = smb_roundup(conn, allocation_size);
6833 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6834 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6835 (double)allocation_size));
6837 if (fsp && fsp->fh->fd != -1) {
6838 /* Open file handle. */
6839 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6840 return NT_STATUS_ACCESS_DENIED;
6843 /* Only change if needed. */
6844 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6845 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6846 return map_nt_error_from_unix(errno);
6849 /* But always update the time. */
6851 * This is equivalent to a write. Ensure it's seen immediately
6852 * if there are no pending writes.
6854 trigger_write_time_update_immediate(fsp);
6855 return NT_STATUS_OK;
6858 /* Pathname or stat or directory file. */
6859 status = SMB_VFS_CREATE_FILE(
6860 conn, /* conn */
6861 req, /* req */
6862 0, /* root_dir_fid */
6863 smb_fname, /* fname */
6864 FILE_WRITE_DATA, /* access_mask */
6865 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6866 FILE_SHARE_DELETE),
6867 FILE_OPEN, /* create_disposition*/
6868 0, /* create_options */
6869 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6870 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6871 0, /* allocation_size */
6872 0, /* private_flags */
6873 NULL, /* sd */
6874 NULL, /* ea_list */
6875 &new_fsp, /* result */
6876 NULL); /* pinfo */
6878 if (!NT_STATUS_IS_OK(status)) {
6879 /* NB. We check for open_was_deferred in the caller. */
6880 return status;
6883 /* Only change if needed. */
6884 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6885 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6886 status = map_nt_error_from_unix(errno);
6887 close_file(req, new_fsp, NORMAL_CLOSE);
6888 return status;
6892 /* Changing the allocation size should set the last mod time. */
6894 * This is equivalent to a write. Ensure it's seen immediately
6895 * if there are no pending writes.
6897 trigger_write_time_update_immediate(new_fsp);
6899 close_file(req, new_fsp, NORMAL_CLOSE);
6900 return NT_STATUS_OK;
6903 /****************************************************************************
6904 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6905 ****************************************************************************/
6907 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6908 struct smb_request *req,
6909 const char *pdata,
6910 int total_data,
6911 files_struct *fsp,
6912 const struct smb_filename *smb_fname,
6913 bool fail_after_createfile)
6915 off_t size;
6917 if (total_data < 8) {
6918 return NT_STATUS_INVALID_PARAMETER;
6921 size = IVAL(pdata,0);
6922 size |= (((off_t)IVAL(pdata,4)) << 32);
6923 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6924 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6925 (double)size));
6927 return smb_set_file_size(conn, req,
6928 fsp,
6929 smb_fname,
6930 &smb_fname->st,
6931 size,
6932 fail_after_createfile);
6935 /****************************************************************************
6936 Allow a UNIX info mknod.
6937 ****************************************************************************/
6939 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6940 const char *pdata,
6941 int total_data,
6942 const struct smb_filename *smb_fname)
6944 uint32 file_type = IVAL(pdata,56);
6945 #if defined(HAVE_MAKEDEV)
6946 uint32 dev_major = IVAL(pdata,60);
6947 uint32 dev_minor = IVAL(pdata,68);
6948 #endif
6949 SMB_DEV_T dev = (SMB_DEV_T)0;
6950 uint32 raw_unixmode = IVAL(pdata,84);
6951 NTSTATUS status;
6952 mode_t unixmode;
6954 if (total_data < 100) {
6955 return NT_STATUS_INVALID_PARAMETER;
6958 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6959 PERM_NEW_FILE, &unixmode);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 return status;
6964 #if defined(HAVE_MAKEDEV)
6965 dev = makedev(dev_major, dev_minor);
6966 #endif
6968 switch (file_type) {
6969 #if defined(S_IFIFO)
6970 case UNIX_TYPE_FIFO:
6971 unixmode |= S_IFIFO;
6972 break;
6973 #endif
6974 #if defined(S_IFSOCK)
6975 case UNIX_TYPE_SOCKET:
6976 unixmode |= S_IFSOCK;
6977 break;
6978 #endif
6979 #if defined(S_IFCHR)
6980 case UNIX_TYPE_CHARDEV:
6981 unixmode |= S_IFCHR;
6982 break;
6983 #endif
6984 #if defined(S_IFBLK)
6985 case UNIX_TYPE_BLKDEV:
6986 unixmode |= S_IFBLK;
6987 break;
6988 #endif
6989 default:
6990 return NT_STATUS_INVALID_PARAMETER;
6993 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6994 "%.0f mode 0%o for file %s\n", (double)dev,
6995 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6997 /* Ok - do the mknod. */
6998 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6999 return map_nt_error_from_unix(errno);
7002 /* If any of the other "set" calls fail we
7003 * don't want to end up with a half-constructed mknod.
7006 if (lp_inherit_perms(SNUM(conn))) {
7007 char *parent;
7008 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7009 &parent, NULL)) {
7010 return NT_STATUS_NO_MEMORY;
7012 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7013 unixmode);
7014 TALLOC_FREE(parent);
7017 return NT_STATUS_OK;
7020 /****************************************************************************
7021 Deal with SMB_SET_FILE_UNIX_BASIC.
7022 ****************************************************************************/
7024 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7025 struct smb_request *req,
7026 const char *pdata,
7027 int total_data,
7028 files_struct *fsp,
7029 const struct smb_filename *smb_fname)
7031 struct smb_file_time ft;
7032 uint32 raw_unixmode;
7033 mode_t unixmode;
7034 off_t size = 0;
7035 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7036 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7037 NTSTATUS status = NT_STATUS_OK;
7038 bool delete_on_fail = False;
7039 enum perm_type ptype;
7040 files_struct *all_fsps = NULL;
7041 bool modify_mtime = true;
7042 struct file_id id;
7043 struct smb_filename *smb_fname_tmp = NULL;
7044 SMB_STRUCT_STAT sbuf;
7046 ZERO_STRUCT(ft);
7048 if (total_data < 100) {
7049 return NT_STATUS_INVALID_PARAMETER;
7052 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7053 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7054 size=IVAL(pdata,0); /* first 8 Bytes are size */
7055 size |= (((off_t)IVAL(pdata,4)) << 32);
7058 ft.atime = interpret_long_date(pdata+24); /* access_time */
7059 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7060 set_owner = (uid_t)IVAL(pdata,40);
7061 set_grp = (gid_t)IVAL(pdata,48);
7062 raw_unixmode = IVAL(pdata,84);
7064 if (VALID_STAT(smb_fname->st)) {
7065 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7066 ptype = PERM_EXISTING_DIR;
7067 } else {
7068 ptype = PERM_EXISTING_FILE;
7070 } else {
7071 ptype = PERM_NEW_FILE;
7074 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7075 ptype, &unixmode);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 return status;
7080 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7081 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7082 smb_fname_str_dbg(smb_fname), (double)size,
7083 (unsigned int)set_owner, (unsigned int)set_grp,
7084 (int)raw_unixmode));
7086 sbuf = smb_fname->st;
7088 if (!VALID_STAT(sbuf)) {
7090 * The only valid use of this is to create character and block
7091 * devices, and named pipes. This is deprecated (IMHO) and
7092 * a new info level should be used for mknod. JRA.
7095 status = smb_unix_mknod(conn,
7096 pdata,
7097 total_data,
7098 smb_fname);
7099 if (!NT_STATUS_IS_OK(status)) {
7100 return status;
7103 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7104 if (smb_fname_tmp == NULL) {
7105 return NT_STATUS_NO_MEMORY;
7108 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7109 status = map_nt_error_from_unix(errno);
7110 TALLOC_FREE(smb_fname_tmp);
7111 SMB_VFS_UNLINK(conn, smb_fname);
7112 return status;
7115 sbuf = smb_fname_tmp->st;
7116 smb_fname = smb_fname_tmp;
7118 /* Ensure we don't try and change anything else. */
7119 raw_unixmode = SMB_MODE_NO_CHANGE;
7120 size = get_file_size_stat(&sbuf);
7121 ft.atime = sbuf.st_ex_atime;
7122 ft.mtime = sbuf.st_ex_mtime;
7124 * We continue here as we might want to change the
7125 * owner uid/gid.
7127 delete_on_fail = True;
7130 #if 1
7131 /* Horrible backwards compatibility hack as an old server bug
7132 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7133 * */
7135 if (!size) {
7136 size = get_file_size_stat(&sbuf);
7138 #endif
7141 * Deal with the UNIX specific mode set.
7144 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7145 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7146 "setting mode 0%o for file %s\n",
7147 (unsigned int)unixmode,
7148 smb_fname_str_dbg(smb_fname)));
7149 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7150 return map_nt_error_from_unix(errno);
7155 * Deal with the UNIX specific uid set.
7158 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7159 (sbuf.st_ex_uid != set_owner)) {
7160 int ret;
7162 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7163 "changing owner %u for path %s\n",
7164 (unsigned int)set_owner,
7165 smb_fname_str_dbg(smb_fname)));
7167 if (S_ISLNK(sbuf.st_ex_mode)) {
7168 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7169 set_owner, (gid_t)-1);
7170 } else {
7171 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7172 set_owner, (gid_t)-1);
7175 if (ret != 0) {
7176 status = map_nt_error_from_unix(errno);
7177 if (delete_on_fail) {
7178 SMB_VFS_UNLINK(conn, smb_fname);
7180 return status;
7185 * Deal with the UNIX specific gid set.
7188 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7189 (sbuf.st_ex_gid != set_grp)) {
7190 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7191 "changing group %u for file %s\n",
7192 (unsigned int)set_owner,
7193 smb_fname_str_dbg(smb_fname)));
7194 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7195 set_grp) != 0) {
7196 status = map_nt_error_from_unix(errno);
7197 if (delete_on_fail) {
7198 SMB_VFS_UNLINK(conn, smb_fname);
7200 return status;
7204 /* Deal with any size changes. */
7206 status = smb_set_file_size(conn, req,
7207 fsp,
7208 smb_fname,
7209 &sbuf,
7210 size,
7211 false);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 return status;
7216 /* Deal with any time changes. */
7217 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7218 /* No change, don't cancel anything. */
7219 return status;
7222 id = vfs_file_id_from_sbuf(conn, &sbuf);
7223 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7224 all_fsps = file_find_di_next(all_fsps)) {
7226 * We're setting the time explicitly for UNIX.
7227 * Cancel any pending changes over all handles.
7229 all_fsps->update_write_time_on_close = false;
7230 TALLOC_FREE(all_fsps->update_write_time_event);
7234 * Override the "setting_write_time"
7235 * parameter here as it almost does what
7236 * we need. Just remember if we modified
7237 * mtime and send the notify ourselves.
7239 if (null_timespec(ft.mtime)) {
7240 modify_mtime = false;
7243 status = smb_set_file_time(conn,
7244 fsp,
7245 smb_fname,
7246 &ft,
7247 false);
7248 if (modify_mtime) {
7249 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7250 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7252 return status;
7255 /****************************************************************************
7256 Deal with SMB_SET_FILE_UNIX_INFO2.
7257 ****************************************************************************/
7259 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7260 struct smb_request *req,
7261 const char *pdata,
7262 int total_data,
7263 files_struct *fsp,
7264 const struct smb_filename *smb_fname)
7266 NTSTATUS status;
7267 uint32 smb_fflags;
7268 uint32 smb_fmask;
7270 if (total_data < 116) {
7271 return NT_STATUS_INVALID_PARAMETER;
7274 /* Start by setting all the fields that are common between UNIX_BASIC
7275 * and UNIX_INFO2.
7277 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7278 fsp, smb_fname);
7279 if (!NT_STATUS_IS_OK(status)) {
7280 return status;
7283 smb_fflags = IVAL(pdata, 108);
7284 smb_fmask = IVAL(pdata, 112);
7286 /* NB: We should only attempt to alter the file flags if the client
7287 * sends a non-zero mask.
7289 if (smb_fmask != 0) {
7290 int stat_fflags = 0;
7292 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7293 smb_fmask, &stat_fflags)) {
7294 /* Client asked to alter a flag we don't understand. */
7295 return NT_STATUS_INVALID_PARAMETER;
7298 if (fsp && fsp->fh->fd != -1) {
7299 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7300 return NT_STATUS_NOT_SUPPORTED;
7301 } else {
7302 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7303 stat_fflags) != 0) {
7304 return map_nt_error_from_unix(errno);
7309 /* XXX: need to add support for changing the create_time here. You
7310 * can do this for paths on Darwin with setattrlist(2). The right way
7311 * to hook this up is probably by extending the VFS utimes interface.
7314 return NT_STATUS_OK;
7317 /****************************************************************************
7318 Create a directory with POSIX semantics.
7319 ****************************************************************************/
7321 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7322 struct smb_request *req,
7323 char **ppdata,
7324 int total_data,
7325 struct smb_filename *smb_fname,
7326 int *pdata_return_size)
7328 NTSTATUS status = NT_STATUS_OK;
7329 uint32 raw_unixmode = 0;
7330 uint32 mod_unixmode = 0;
7331 mode_t unixmode = (mode_t)0;
7332 files_struct *fsp = NULL;
7333 uint16 info_level_return = 0;
7334 int info;
7335 char *pdata = *ppdata;
7337 if (total_data < 18) {
7338 return NT_STATUS_INVALID_PARAMETER;
7341 raw_unixmode = IVAL(pdata,8);
7342 /* Next 4 bytes are not yet defined. */
7344 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7345 PERM_NEW_DIR, &unixmode);
7346 if (!NT_STATUS_IS_OK(status)) {
7347 return status;
7350 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7352 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7353 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7355 status = SMB_VFS_CREATE_FILE(
7356 conn, /* conn */
7357 req, /* req */
7358 0, /* root_dir_fid */
7359 smb_fname, /* fname */
7360 FILE_READ_ATTRIBUTES, /* access_mask */
7361 FILE_SHARE_NONE, /* share_access */
7362 FILE_CREATE, /* create_disposition*/
7363 FILE_DIRECTORY_FILE, /* create_options */
7364 mod_unixmode, /* file_attributes */
7365 0, /* oplock_request */
7366 0, /* allocation_size */
7367 0, /* private_flags */
7368 NULL, /* sd */
7369 NULL, /* ea_list */
7370 &fsp, /* result */
7371 &info); /* pinfo */
7373 if (NT_STATUS_IS_OK(status)) {
7374 close_file(req, fsp, NORMAL_CLOSE);
7377 info_level_return = SVAL(pdata,16);
7379 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7380 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7381 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7382 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7383 } else {
7384 *pdata_return_size = 12;
7387 /* Realloc the data size */
7388 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7389 if (*ppdata == NULL) {
7390 *pdata_return_size = 0;
7391 return NT_STATUS_NO_MEMORY;
7393 pdata = *ppdata;
7395 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7396 SSVAL(pdata,2,0); /* No fnum. */
7397 SIVAL(pdata,4,info); /* Was directory created. */
7399 switch (info_level_return) {
7400 case SMB_QUERY_FILE_UNIX_BASIC:
7401 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7402 SSVAL(pdata,10,0); /* Padding. */
7403 store_file_unix_basic(conn, pdata + 12, fsp,
7404 &smb_fname->st);
7405 break;
7406 case SMB_QUERY_FILE_UNIX_INFO2:
7407 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7408 SSVAL(pdata,10,0); /* Padding. */
7409 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7410 &smb_fname->st);
7411 break;
7412 default:
7413 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7414 SSVAL(pdata,10,0); /* Padding. */
7415 break;
7418 return status;
7421 /****************************************************************************
7422 Open/Create a file with POSIX semantics.
7423 ****************************************************************************/
7425 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7426 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7428 static NTSTATUS smb_posix_open(connection_struct *conn,
7429 struct smb_request *req,
7430 char **ppdata,
7431 int total_data,
7432 struct smb_filename *smb_fname,
7433 int *pdata_return_size)
7435 bool extended_oplock_granted = False;
7436 char *pdata = *ppdata;
7437 uint32 flags = 0;
7438 uint32 wire_open_mode = 0;
7439 uint32 raw_unixmode = 0;
7440 uint32 mod_unixmode = 0;
7441 uint32 create_disp = 0;
7442 uint32 access_mask = 0;
7443 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7444 NTSTATUS status = NT_STATUS_OK;
7445 mode_t unixmode = (mode_t)0;
7446 files_struct *fsp = NULL;
7447 int oplock_request = 0;
7448 int info = 0;
7449 uint16 info_level_return = 0;
7451 if (total_data < 18) {
7452 return NT_STATUS_INVALID_PARAMETER;
7455 flags = IVAL(pdata,0);
7456 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7457 if (oplock_request) {
7458 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7461 wire_open_mode = IVAL(pdata,4);
7463 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7464 return smb_posix_mkdir(conn, req,
7465 ppdata,
7466 total_data,
7467 smb_fname,
7468 pdata_return_size);
7471 switch (wire_open_mode & SMB_ACCMODE) {
7472 case SMB_O_RDONLY:
7473 access_mask = SMB_O_RDONLY_MAPPING;
7474 break;
7475 case SMB_O_WRONLY:
7476 access_mask = SMB_O_WRONLY_MAPPING;
7477 break;
7478 case SMB_O_RDWR:
7479 access_mask = (SMB_O_RDONLY_MAPPING|
7480 SMB_O_WRONLY_MAPPING);
7481 break;
7482 default:
7483 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7484 (unsigned int)wire_open_mode ));
7485 return NT_STATUS_INVALID_PARAMETER;
7488 wire_open_mode &= ~SMB_ACCMODE;
7490 /* First take care of O_CREAT|O_EXCL interactions. */
7491 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7492 case (SMB_O_CREAT | SMB_O_EXCL):
7493 /* File exists fail. File not exist create. */
7494 create_disp = FILE_CREATE;
7495 break;
7496 case SMB_O_CREAT:
7497 /* File exists open. File not exist create. */
7498 create_disp = FILE_OPEN_IF;
7499 break;
7500 case SMB_O_EXCL:
7501 /* O_EXCL on its own without O_CREAT is undefined.
7502 We deliberately ignore it as some versions of
7503 Linux CIFSFS can send a bare O_EXCL on the
7504 wire which other filesystems in the kernel
7505 ignore. See bug 9519 for details. */
7507 /* Fallthrough. */
7509 case 0:
7510 /* File exists open. File not exist fail. */
7511 create_disp = FILE_OPEN;
7512 break;
7513 default:
7514 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7515 (unsigned int)wire_open_mode ));
7516 return NT_STATUS_INVALID_PARAMETER;
7519 /* Next factor in the effects of O_TRUNC. */
7520 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7522 if (wire_open_mode & SMB_O_TRUNC) {
7523 switch (create_disp) {
7524 case FILE_CREATE:
7525 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7526 /* Leave create_disp alone as
7527 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7529 /* File exists fail. File not exist create. */
7530 break;
7531 case FILE_OPEN_IF:
7532 /* SMB_O_CREAT | SMB_O_TRUNC */
7533 /* File exists overwrite. File not exist create. */
7534 create_disp = FILE_OVERWRITE_IF;
7535 break;
7536 case FILE_OPEN:
7537 /* SMB_O_TRUNC */
7538 /* File exists overwrite. File not exist fail. */
7539 create_disp = FILE_OVERWRITE;
7540 break;
7541 default:
7542 /* Cannot get here. */
7543 smb_panic("smb_posix_open: logic error");
7544 return NT_STATUS_INVALID_PARAMETER;
7548 raw_unixmode = IVAL(pdata,8);
7549 /* Next 4 bytes are not yet defined. */
7551 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7552 (VALID_STAT(smb_fname->st) ?
7553 PERM_EXISTING_FILE : PERM_NEW_FILE),
7554 &unixmode);
7556 if (!NT_STATUS_IS_OK(status)) {
7557 return status;
7560 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7562 if (wire_open_mode & SMB_O_SYNC) {
7563 create_options |= FILE_WRITE_THROUGH;
7565 if (wire_open_mode & SMB_O_APPEND) {
7566 access_mask |= FILE_APPEND_DATA;
7568 if (wire_open_mode & SMB_O_DIRECT) {
7569 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7572 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7573 VALID_STAT_OF_DIR(smb_fname->st)) {
7574 if (access_mask != SMB_O_RDONLY_MAPPING) {
7575 return NT_STATUS_FILE_IS_A_DIRECTORY;
7577 create_options &= ~FILE_NON_DIRECTORY_FILE;
7578 create_options |= FILE_DIRECTORY_FILE;
7581 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7582 smb_fname_str_dbg(smb_fname),
7583 (unsigned int)wire_open_mode,
7584 (unsigned int)unixmode ));
7586 status = SMB_VFS_CREATE_FILE(
7587 conn, /* conn */
7588 req, /* req */
7589 0, /* root_dir_fid */
7590 smb_fname, /* fname */
7591 access_mask, /* access_mask */
7592 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7593 FILE_SHARE_DELETE),
7594 create_disp, /* create_disposition*/
7595 create_options, /* create_options */
7596 mod_unixmode, /* file_attributes */
7597 oplock_request, /* oplock_request */
7598 0, /* allocation_size */
7599 0, /* private_flags */
7600 NULL, /* sd */
7601 NULL, /* ea_list */
7602 &fsp, /* result */
7603 &info); /* pinfo */
7605 if (!NT_STATUS_IS_OK(status)) {
7606 return status;
7609 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7610 extended_oplock_granted = True;
7613 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7614 extended_oplock_granted = True;
7617 info_level_return = SVAL(pdata,16);
7619 /* Allocate the correct return size. */
7621 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7622 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7623 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7624 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7625 } else {
7626 *pdata_return_size = 12;
7629 /* Realloc the data size */
7630 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7631 if (*ppdata == NULL) {
7632 close_file(req, fsp, ERROR_CLOSE);
7633 *pdata_return_size = 0;
7634 return NT_STATUS_NO_MEMORY;
7636 pdata = *ppdata;
7638 if (extended_oplock_granted) {
7639 if (flags & REQUEST_BATCH_OPLOCK) {
7640 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7641 } else {
7642 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7644 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7645 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7646 } else {
7647 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7650 SSVAL(pdata,2,fsp->fnum);
7651 SIVAL(pdata,4,info); /* Was file created etc. */
7653 switch (info_level_return) {
7654 case SMB_QUERY_FILE_UNIX_BASIC:
7655 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7656 SSVAL(pdata,10,0); /* padding. */
7657 store_file_unix_basic(conn, pdata + 12, fsp,
7658 &smb_fname->st);
7659 break;
7660 case SMB_QUERY_FILE_UNIX_INFO2:
7661 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7662 SSVAL(pdata,10,0); /* padding. */
7663 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7664 &smb_fname->st);
7665 break;
7666 default:
7667 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7668 SSVAL(pdata,10,0); /* padding. */
7669 break;
7671 return NT_STATUS_OK;
7674 /****************************************************************************
7675 Delete a file with POSIX semantics.
7676 ****************************************************************************/
7678 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7679 struct smb_request *req,
7680 const char *pdata,
7681 int total_data,
7682 struct smb_filename *smb_fname)
7684 NTSTATUS status = NT_STATUS_OK;
7685 files_struct *fsp = NULL;
7686 uint16 flags = 0;
7687 char del = 1;
7688 int info = 0;
7689 int create_options = 0;
7690 int i;
7691 struct share_mode_lock *lck = NULL;
7693 if (total_data < 2) {
7694 return NT_STATUS_INVALID_PARAMETER;
7697 flags = SVAL(pdata,0);
7699 if (!VALID_STAT(smb_fname->st)) {
7700 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7703 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7704 !VALID_STAT_OF_DIR(smb_fname->st)) {
7705 return NT_STATUS_NOT_A_DIRECTORY;
7708 DEBUG(10,("smb_posix_unlink: %s %s\n",
7709 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7710 smb_fname_str_dbg(smb_fname)));
7712 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7713 create_options |= FILE_DIRECTORY_FILE;
7716 status = SMB_VFS_CREATE_FILE(
7717 conn, /* conn */
7718 req, /* req */
7719 0, /* root_dir_fid */
7720 smb_fname, /* fname */
7721 DELETE_ACCESS, /* access_mask */
7722 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7723 FILE_SHARE_DELETE),
7724 FILE_OPEN, /* create_disposition*/
7725 create_options, /* create_options */
7726 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7727 0, /* oplock_request */
7728 0, /* allocation_size */
7729 0, /* private_flags */
7730 NULL, /* sd */
7731 NULL, /* ea_list */
7732 &fsp, /* result */
7733 &info); /* pinfo */
7735 if (!NT_STATUS_IS_OK(status)) {
7736 return status;
7740 * Don't lie to client. If we can't really delete due to
7741 * non-POSIX opens return SHARING_VIOLATION.
7744 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7745 if (lck == NULL) {
7746 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7747 "lock for file %s\n", fsp_str_dbg(fsp)));
7748 close_file(req, fsp, NORMAL_CLOSE);
7749 return NT_STATUS_INVALID_PARAMETER;
7753 * See if others still have the file open. If this is the case, then
7754 * don't delete. If all opens are POSIX delete we can set the delete
7755 * on close disposition.
7757 for (i=0; i<lck->data->num_share_modes; i++) {
7758 struct share_mode_entry *e = &lck->data->share_modes[i];
7759 if (is_valid_share_mode_entry(e)) {
7760 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7761 continue;
7763 if (share_mode_stale_pid(lck->data, i)) {
7764 continue;
7766 /* Fail with sharing violation. */
7767 TALLOC_FREE(lck);
7768 close_file(req, fsp, NORMAL_CLOSE);
7769 return NT_STATUS_SHARING_VIOLATION;
7774 * Set the delete on close.
7776 status = smb_set_file_disposition_info(conn,
7777 &del,
7779 fsp,
7780 smb_fname);
7782 TALLOC_FREE(lck);
7784 if (!NT_STATUS_IS_OK(status)) {
7785 close_file(req, fsp, NORMAL_CLOSE);
7786 return status;
7788 return close_file(req, fsp, NORMAL_CLOSE);
7791 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7792 struct smb_request *req,
7793 TALLOC_CTX *mem_ctx,
7794 uint16_t info_level,
7795 files_struct *fsp,
7796 struct smb_filename *smb_fname,
7797 char **ppdata, int total_data,
7798 int *ret_data_size)
7800 char *pdata = *ppdata;
7801 NTSTATUS status = NT_STATUS_OK;
7802 int data_return_size = 0;
7804 *ret_data_size = 0;
7806 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7807 return NT_STATUS_INVALID_LEVEL;
7810 if (!CAN_WRITE(conn)) {
7811 /* Allow POSIX opens. The open path will deny
7812 * any non-readonly opens. */
7813 if (info_level != SMB_POSIX_PATH_OPEN) {
7814 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7818 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7819 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7820 fsp_fnum_dbg(fsp),
7821 info_level, total_data));
7823 switch (info_level) {
7825 case SMB_INFO_STANDARD:
7827 status = smb_set_info_standard(conn,
7828 pdata,
7829 total_data,
7830 fsp,
7831 smb_fname);
7832 break;
7835 case SMB_INFO_SET_EA:
7837 status = smb_info_set_ea(conn,
7838 pdata,
7839 total_data,
7840 fsp,
7841 smb_fname);
7842 break;
7845 case SMB_SET_FILE_BASIC_INFO:
7846 case SMB_FILE_BASIC_INFORMATION:
7848 status = smb_set_file_basic_info(conn,
7849 pdata,
7850 total_data,
7851 fsp,
7852 smb_fname);
7853 break;
7856 case SMB_FILE_ALLOCATION_INFORMATION:
7857 case SMB_SET_FILE_ALLOCATION_INFO:
7859 status = smb_set_file_allocation_info(conn, req,
7860 pdata,
7861 total_data,
7862 fsp,
7863 smb_fname);
7864 break;
7867 case SMB_FILE_END_OF_FILE_INFORMATION:
7868 case SMB_SET_FILE_END_OF_FILE_INFO:
7871 * XP/Win7 both fail after the createfile with
7872 * SMB_SET_FILE_END_OF_FILE_INFO but not
7873 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7874 * The level is known here, so pass it down
7875 * appropriately.
7877 bool should_fail =
7878 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7880 status = smb_set_file_end_of_file_info(conn, req,
7881 pdata,
7882 total_data,
7883 fsp,
7884 smb_fname,
7885 should_fail);
7886 break;
7889 case SMB_FILE_DISPOSITION_INFORMATION:
7890 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7892 #if 0
7893 /* JRA - We used to just ignore this on a path ?
7894 * Shouldn't this be invalid level on a pathname
7895 * based call ?
7897 if (tran_call != TRANSACT2_SETFILEINFO) {
7898 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7900 #endif
7901 status = smb_set_file_disposition_info(conn,
7902 pdata,
7903 total_data,
7904 fsp,
7905 smb_fname);
7906 break;
7909 case SMB_FILE_POSITION_INFORMATION:
7911 status = smb_file_position_information(conn,
7912 pdata,
7913 total_data,
7914 fsp);
7915 break;
7918 case SMB_FILE_FULL_EA_INFORMATION:
7920 status = smb_set_file_full_ea_info(conn,
7921 pdata,
7922 total_data,
7923 fsp);
7924 break;
7927 /* From tridge Samba4 :
7928 * MODE_INFORMATION in setfileinfo (I have no
7929 * idea what "mode information" on a file is - it takes a value of 0,
7930 * 2, 4 or 6. What could it be?).
7933 case SMB_FILE_MODE_INFORMATION:
7935 status = smb_file_mode_information(conn,
7936 pdata,
7937 total_data);
7938 break;
7942 * CIFS UNIX extensions.
7945 case SMB_SET_FILE_UNIX_BASIC:
7947 status = smb_set_file_unix_basic(conn, req,
7948 pdata,
7949 total_data,
7950 fsp,
7951 smb_fname);
7952 break;
7955 case SMB_SET_FILE_UNIX_INFO2:
7957 status = smb_set_file_unix_info2(conn, req,
7958 pdata,
7959 total_data,
7960 fsp,
7961 smb_fname);
7962 break;
7965 case SMB_SET_FILE_UNIX_LINK:
7967 if (fsp) {
7968 /* We must have a pathname for this. */
7969 return NT_STATUS_INVALID_LEVEL;
7971 status = smb_set_file_unix_link(conn, req, pdata,
7972 total_data, smb_fname);
7973 break;
7976 case SMB_SET_FILE_UNIX_HLINK:
7978 if (fsp) {
7979 /* We must have a pathname for this. */
7980 return NT_STATUS_INVALID_LEVEL;
7982 status = smb_set_file_unix_hlink(conn, req,
7983 pdata, total_data,
7984 smb_fname);
7985 break;
7988 case SMB_FILE_RENAME_INFORMATION:
7990 status = smb_file_rename_information(conn, req,
7991 pdata, total_data,
7992 fsp, smb_fname);
7993 break;
7996 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7998 /* SMB2 rename information. */
7999 status = smb2_file_rename_information(conn, req,
8000 pdata, total_data,
8001 fsp, smb_fname);
8002 break;
8005 case SMB_FILE_LINK_INFORMATION:
8007 status = smb_file_link_information(conn, req,
8008 pdata, total_data,
8009 fsp, smb_fname);
8010 break;
8013 #if defined(HAVE_POSIX_ACLS)
8014 case SMB_SET_POSIX_ACL:
8016 status = smb_set_posix_acl(conn,
8017 pdata,
8018 total_data,
8019 fsp,
8020 smb_fname);
8021 break;
8023 #endif
8025 case SMB_SET_POSIX_LOCK:
8027 if (!fsp) {
8028 return NT_STATUS_INVALID_LEVEL;
8030 status = smb_set_posix_lock(conn, req,
8031 pdata, total_data, fsp);
8032 break;
8035 case SMB_POSIX_PATH_OPEN:
8037 if (fsp) {
8038 /* We must have a pathname for this. */
8039 return NT_STATUS_INVALID_LEVEL;
8042 status = smb_posix_open(conn, req,
8043 ppdata,
8044 total_data,
8045 smb_fname,
8046 &data_return_size);
8047 break;
8050 case SMB_POSIX_PATH_UNLINK:
8052 if (fsp) {
8053 /* We must have a pathname for this. */
8054 return NT_STATUS_INVALID_LEVEL;
8057 status = smb_posix_unlink(conn, req,
8058 pdata,
8059 total_data,
8060 smb_fname);
8061 break;
8064 default:
8065 return NT_STATUS_INVALID_LEVEL;
8068 if (!NT_STATUS_IS_OK(status)) {
8069 return status;
8072 *ret_data_size = data_return_size;
8073 return NT_STATUS_OK;
8076 /****************************************************************************
8077 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8078 ****************************************************************************/
8080 static void call_trans2setfilepathinfo(connection_struct *conn,
8081 struct smb_request *req,
8082 unsigned int tran_call,
8083 char **pparams, int total_params,
8084 char **ppdata, int total_data,
8085 unsigned int max_data_bytes)
8087 char *params = *pparams;
8088 char *pdata = *ppdata;
8089 uint16 info_level;
8090 struct smb_filename *smb_fname = NULL;
8091 files_struct *fsp = NULL;
8092 NTSTATUS status = NT_STATUS_OK;
8093 int data_return_size = 0;
8095 if (!params) {
8096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8097 return;
8100 if (tran_call == TRANSACT2_SETFILEINFO) {
8101 if (total_params < 4) {
8102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8103 return;
8106 fsp = file_fsp(req, SVAL(params,0));
8107 /* Basic check for non-null fsp. */
8108 if (!check_fsp_open(conn, req, fsp)) {
8109 return;
8111 info_level = SVAL(params,2);
8113 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8114 if (smb_fname == NULL) {
8115 reply_nterror(req, NT_STATUS_NO_MEMORY);
8116 return;
8119 if(fsp->fh->fd == -1) {
8121 * This is actually a SETFILEINFO on a directory
8122 * handle (returned from an NT SMB). NT5.0 seems
8123 * to do this call. JRA.
8125 if (INFO_LEVEL_IS_UNIX(info_level)) {
8126 /* Always do lstat for UNIX calls. */
8127 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8128 DEBUG(3,("call_trans2setfilepathinfo: "
8129 "SMB_VFS_LSTAT of %s failed "
8130 "(%s)\n",
8131 smb_fname_str_dbg(smb_fname),
8132 strerror(errno)));
8133 reply_nterror(req, map_nt_error_from_unix(errno));
8134 return;
8136 } else {
8137 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8138 DEBUG(3,("call_trans2setfilepathinfo: "
8139 "fileinfo of %s failed (%s)\n",
8140 smb_fname_str_dbg(smb_fname),
8141 strerror(errno)));
8142 reply_nterror(req, map_nt_error_from_unix(errno));
8143 return;
8146 } else if (fsp->print_file) {
8148 * Doing a DELETE_ON_CLOSE should cancel a print job.
8150 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8151 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8153 DEBUG(3,("call_trans2setfilepathinfo: "
8154 "Cancelling print job (%s)\n",
8155 fsp_str_dbg(fsp)));
8157 SSVAL(params,0,0);
8158 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8159 *ppdata, 0,
8160 max_data_bytes);
8161 return;
8162 } else {
8163 reply_nterror(req,
8164 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8165 return;
8167 } else {
8169 * Original code - this is an open file.
8171 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8172 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8173 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8174 strerror(errno)));
8175 reply_nterror(req, map_nt_error_from_unix(errno));
8176 return;
8179 } else {
8180 char *fname = NULL;
8181 uint32_t ucf_flags = 0;
8183 /* set path info */
8184 if (total_params < 7) {
8185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8186 return;
8189 info_level = SVAL(params,0);
8190 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8191 total_params - 6, STR_TERMINATE,
8192 &status);
8193 if (!NT_STATUS_IS_OK(status)) {
8194 reply_nterror(req, status);
8195 return;
8198 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8199 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8200 info_level == SMB_FILE_RENAME_INFORMATION ||
8201 info_level == SMB_POSIX_PATH_UNLINK) {
8202 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8205 status = filename_convert(req, conn,
8206 req->flags2 & FLAGS2_DFS_PATHNAMES,
8207 fname,
8208 ucf_flags,
8209 NULL,
8210 &smb_fname);
8211 if (!NT_STATUS_IS_OK(status)) {
8212 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8213 reply_botherror(req,
8214 NT_STATUS_PATH_NOT_COVERED,
8215 ERRSRV, ERRbadpath);
8216 return;
8218 reply_nterror(req, status);
8219 return;
8222 if (INFO_LEVEL_IS_UNIX(info_level)) {
8224 * For CIFS UNIX extensions the target name may not exist.
8227 /* Always do lstat for UNIX calls. */
8228 SMB_VFS_LSTAT(conn, smb_fname);
8230 } else if (!VALID_STAT(smb_fname->st) &&
8231 SMB_VFS_STAT(conn, smb_fname)) {
8232 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8233 "%s failed (%s)\n",
8234 smb_fname_str_dbg(smb_fname),
8235 strerror(errno)));
8236 reply_nterror(req, map_nt_error_from_unix(errno));
8237 return;
8241 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8242 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8243 fsp_fnum_dbg(fsp),
8244 info_level,total_data));
8246 /* Realloc the parameter size */
8247 *pparams = (char *)SMB_REALLOC(*pparams,2);
8248 if (*pparams == NULL) {
8249 reply_nterror(req, NT_STATUS_NO_MEMORY);
8250 return;
8252 params = *pparams;
8254 SSVAL(params,0,0);
8256 status = smbd_do_setfilepathinfo(conn, req, req,
8257 info_level,
8258 fsp,
8259 smb_fname,
8260 ppdata, total_data,
8261 &data_return_size);
8262 if (!NT_STATUS_IS_OK(status)) {
8263 if (open_was_deferred(req->sconn, req->mid)) {
8264 /* We have re-scheduled this call. */
8265 return;
8267 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8268 /* We have re-scheduled this call. */
8269 return;
8271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8272 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8273 ERRSRV, ERRbadpath);
8274 return;
8276 if (info_level == SMB_POSIX_PATH_OPEN) {
8277 reply_openerror(req, status);
8278 return;
8282 * Invalid EA name needs to return 2 param bytes,
8283 * not a zero-length error packet.
8285 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8286 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8287 max_data_bytes);
8288 } else {
8289 reply_nterror(req, status);
8291 return;
8294 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8295 max_data_bytes);
8297 return;
8300 /****************************************************************************
8301 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8302 ****************************************************************************/
8304 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8305 char **pparams, int total_params,
8306 char **ppdata, int total_data,
8307 unsigned int max_data_bytes)
8309 struct smb_filename *smb_dname = NULL;
8310 char *params = *pparams;
8311 char *pdata = *ppdata;
8312 char *directory = NULL;
8313 NTSTATUS status = NT_STATUS_OK;
8314 struct ea_list *ea_list = NULL;
8315 TALLOC_CTX *ctx = talloc_tos();
8317 if (!CAN_WRITE(conn)) {
8318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8319 return;
8322 if (total_params < 5) {
8323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8324 return;
8327 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8328 total_params - 4, STR_TERMINATE,
8329 &status);
8330 if (!NT_STATUS_IS_OK(status)) {
8331 reply_nterror(req, status);
8332 return;
8335 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8337 status = filename_convert(ctx,
8338 conn,
8339 req->flags2 & FLAGS2_DFS_PATHNAMES,
8340 directory,
8342 NULL,
8343 &smb_dname);
8345 if (!NT_STATUS_IS_OK(status)) {
8346 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8347 reply_botherror(req,
8348 NT_STATUS_PATH_NOT_COVERED,
8349 ERRSRV, ERRbadpath);
8350 return;
8352 reply_nterror(req, status);
8353 return;
8357 * OS/2 workplace shell seems to send SET_EA requests of "null"
8358 * length (4 bytes containing IVAL 4).
8359 * They seem to have no effect. Bug #3212. JRA.
8362 if (total_data && (total_data != 4)) {
8363 /* Any data in this call is an EA list. */
8364 if (total_data < 10) {
8365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8366 goto out;
8369 if (IVAL(pdata,0) > total_data) {
8370 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8371 IVAL(pdata,0), (unsigned int)total_data));
8372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8373 goto out;
8376 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8377 total_data - 4);
8378 if (!ea_list) {
8379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8380 goto out;
8383 if (!lp_ea_support(SNUM(conn))) {
8384 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8385 goto out;
8388 /* If total_data == 4 Windows doesn't care what values
8389 * are placed in that field, it just ignores them.
8390 * The System i QNTC IBM SMB client puts bad values here,
8391 * so ignore them. */
8393 status = create_directory(conn, req, smb_dname);
8395 if (!NT_STATUS_IS_OK(status)) {
8396 reply_nterror(req, status);
8397 goto out;
8400 /* Try and set any given EA. */
8401 if (ea_list) {
8402 status = set_ea(conn, NULL, smb_dname, ea_list);
8403 if (!NT_STATUS_IS_OK(status)) {
8404 reply_nterror(req, status);
8405 goto out;
8409 /* Realloc the parameter and data sizes */
8410 *pparams = (char *)SMB_REALLOC(*pparams,2);
8411 if(*pparams == NULL) {
8412 reply_nterror(req, NT_STATUS_NO_MEMORY);
8413 goto out;
8415 params = *pparams;
8417 SSVAL(params,0,0);
8419 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8421 out:
8422 TALLOC_FREE(smb_dname);
8423 return;
8426 /****************************************************************************
8427 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8428 We don't actually do this - we just send a null response.
8429 ****************************************************************************/
8431 static void call_trans2findnotifyfirst(connection_struct *conn,
8432 struct smb_request *req,
8433 char **pparams, int total_params,
8434 char **ppdata, int total_data,
8435 unsigned int max_data_bytes)
8437 char *params = *pparams;
8438 uint16 info_level;
8440 if (total_params < 6) {
8441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8442 return;
8445 info_level = SVAL(params,4);
8446 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8448 switch (info_level) {
8449 case 1:
8450 case 2:
8451 break;
8452 default:
8453 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8454 return;
8457 /* Realloc the parameter and data sizes */
8458 *pparams = (char *)SMB_REALLOC(*pparams,6);
8459 if (*pparams == NULL) {
8460 reply_nterror(req, NT_STATUS_NO_MEMORY);
8461 return;
8463 params = *pparams;
8465 SSVAL(params,0,fnf_handle);
8466 SSVAL(params,2,0); /* No changes */
8467 SSVAL(params,4,0); /* No EA errors */
8469 fnf_handle++;
8471 if(fnf_handle == 0)
8472 fnf_handle = 257;
8474 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8476 return;
8479 /****************************************************************************
8480 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8481 changes). Currently this does nothing.
8482 ****************************************************************************/
8484 static void call_trans2findnotifynext(connection_struct *conn,
8485 struct smb_request *req,
8486 char **pparams, int total_params,
8487 char **ppdata, int total_data,
8488 unsigned int max_data_bytes)
8490 char *params = *pparams;
8492 DEBUG(3,("call_trans2findnotifynext\n"));
8494 /* Realloc the parameter and data sizes */
8495 *pparams = (char *)SMB_REALLOC(*pparams,4);
8496 if (*pparams == NULL) {
8497 reply_nterror(req, NT_STATUS_NO_MEMORY);
8498 return;
8500 params = *pparams;
8502 SSVAL(params,0,0); /* No changes */
8503 SSVAL(params,2,0); /* No EA errors */
8505 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8507 return;
8510 /****************************************************************************
8511 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8512 ****************************************************************************/
8514 static void call_trans2getdfsreferral(connection_struct *conn,
8515 struct smb_request *req,
8516 char **pparams, int total_params,
8517 char **ppdata, int total_data,
8518 unsigned int max_data_bytes)
8520 char *params = *pparams;
8521 char *pathname = NULL;
8522 int reply_size = 0;
8523 int max_referral_level;
8524 NTSTATUS status = NT_STATUS_OK;
8525 TALLOC_CTX *ctx = talloc_tos();
8527 DEBUG(10,("call_trans2getdfsreferral\n"));
8529 if (total_params < 3) {
8530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8531 return;
8534 max_referral_level = SVAL(params,0);
8536 if(!lp_host_msdfs()) {
8537 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8538 return;
8541 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8542 total_params - 2, STR_TERMINATE);
8543 if (!pathname) {
8544 reply_nterror(req, NT_STATUS_NOT_FOUND);
8545 return;
8547 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8548 ppdata,&status)) < 0) {
8549 reply_nterror(req, status);
8550 return;
8553 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8554 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8555 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8557 return;
8560 #define LMCAT_SPL 0x53
8561 #define LMFUNC_GETJOBID 0x60
8563 /****************************************************************************
8564 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8565 ****************************************************************************/
8567 static void call_trans2ioctl(connection_struct *conn,
8568 struct smb_request *req,
8569 char **pparams, int total_params,
8570 char **ppdata, int total_data,
8571 unsigned int max_data_bytes)
8573 char *pdata = *ppdata;
8574 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8576 /* check for an invalid fid before proceeding */
8578 if (!fsp) {
8579 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8580 return;
8583 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8584 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8585 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8586 if (*ppdata == NULL) {
8587 reply_nterror(req, NT_STATUS_NO_MEMORY);
8588 return;
8590 pdata = *ppdata;
8592 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8593 CAN ACCEPT THIS IN UNICODE. JRA. */
8595 /* Job number */
8596 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8598 srvstr_push(pdata, req->flags2, pdata + 2,
8599 lp_netbios_name(), 15,
8600 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8601 srvstr_push(pdata, req->flags2, pdata+18,
8602 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8603 STR_ASCII|STR_TERMINATE); /* Service name */
8604 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8605 max_data_bytes);
8606 return;
8609 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8610 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8613 /****************************************************************************
8614 Reply to a SMBfindclose (stop trans2 directory search).
8615 ****************************************************************************/
8617 void reply_findclose(struct smb_request *req)
8619 int dptr_num;
8620 struct smbd_server_connection *sconn = req->sconn;
8622 START_PROFILE(SMBfindclose);
8624 if (req->wct < 1) {
8625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8626 END_PROFILE(SMBfindclose);
8627 return;
8630 dptr_num = SVALS(req->vwv+0, 0);
8632 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8634 dptr_close(sconn, &dptr_num);
8636 reply_outbuf(req, 0, 0);
8638 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8640 END_PROFILE(SMBfindclose);
8641 return;
8644 /****************************************************************************
8645 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8646 ****************************************************************************/
8648 void reply_findnclose(struct smb_request *req)
8650 int dptr_num;
8652 START_PROFILE(SMBfindnclose);
8654 if (req->wct < 1) {
8655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8656 END_PROFILE(SMBfindnclose);
8657 return;
8660 dptr_num = SVAL(req->vwv+0, 0);
8662 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8664 /* We never give out valid handles for a
8665 findnotifyfirst - so any dptr_num is ok here.
8666 Just ignore it. */
8668 reply_outbuf(req, 0, 0);
8670 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8672 END_PROFILE(SMBfindnclose);
8673 return;
8676 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8677 struct trans_state *state)
8679 if (get_Protocol() >= PROTOCOL_NT1) {
8680 req->flags2 |= 0x40; /* IS_LONG_NAME */
8681 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8684 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8685 if (state->call != TRANSACT2_QFSINFO &&
8686 state->call != TRANSACT2_SETFSINFO) {
8687 DEBUG(0,("handle_trans2: encryption required "
8688 "with call 0x%x\n",
8689 (unsigned int)state->call));
8690 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8691 return;
8695 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8697 /* Now we must call the relevant TRANS2 function */
8698 switch(state->call) {
8699 case TRANSACT2_OPEN:
8701 START_PROFILE(Trans2_open);
8702 call_trans2open(conn, req,
8703 &state->param, state->total_param,
8704 &state->data, state->total_data,
8705 state->max_data_return);
8706 END_PROFILE(Trans2_open);
8707 break;
8710 case TRANSACT2_FINDFIRST:
8712 START_PROFILE(Trans2_findfirst);
8713 call_trans2findfirst(conn, req,
8714 &state->param, state->total_param,
8715 &state->data, state->total_data,
8716 state->max_data_return);
8717 END_PROFILE(Trans2_findfirst);
8718 break;
8721 case TRANSACT2_FINDNEXT:
8723 START_PROFILE(Trans2_findnext);
8724 call_trans2findnext(conn, req,
8725 &state->param, state->total_param,
8726 &state->data, state->total_data,
8727 state->max_data_return);
8728 END_PROFILE(Trans2_findnext);
8729 break;
8732 case TRANSACT2_QFSINFO:
8734 START_PROFILE(Trans2_qfsinfo);
8735 call_trans2qfsinfo(conn, req,
8736 &state->param, state->total_param,
8737 &state->data, state->total_data,
8738 state->max_data_return);
8739 END_PROFILE(Trans2_qfsinfo);
8740 break;
8743 case TRANSACT2_SETFSINFO:
8745 START_PROFILE(Trans2_setfsinfo);
8746 call_trans2setfsinfo(conn, req,
8747 &state->param, state->total_param,
8748 &state->data, state->total_data,
8749 state->max_data_return);
8750 END_PROFILE(Trans2_setfsinfo);
8751 break;
8754 case TRANSACT2_QPATHINFO:
8755 case TRANSACT2_QFILEINFO:
8757 START_PROFILE(Trans2_qpathinfo);
8758 call_trans2qfilepathinfo(conn, req, state->call,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_qpathinfo);
8763 break;
8766 case TRANSACT2_SETPATHINFO:
8767 case TRANSACT2_SETFILEINFO:
8769 START_PROFILE(Trans2_setpathinfo);
8770 call_trans2setfilepathinfo(conn, req, state->call,
8771 &state->param, state->total_param,
8772 &state->data, state->total_data,
8773 state->max_data_return);
8774 END_PROFILE(Trans2_setpathinfo);
8775 break;
8778 case TRANSACT2_FINDNOTIFYFIRST:
8780 START_PROFILE(Trans2_findnotifyfirst);
8781 call_trans2findnotifyfirst(conn, req,
8782 &state->param, state->total_param,
8783 &state->data, state->total_data,
8784 state->max_data_return);
8785 END_PROFILE(Trans2_findnotifyfirst);
8786 break;
8789 case TRANSACT2_FINDNOTIFYNEXT:
8791 START_PROFILE(Trans2_findnotifynext);
8792 call_trans2findnotifynext(conn, req,
8793 &state->param, state->total_param,
8794 &state->data, state->total_data,
8795 state->max_data_return);
8796 END_PROFILE(Trans2_findnotifynext);
8797 break;
8800 case TRANSACT2_MKDIR:
8802 START_PROFILE(Trans2_mkdir);
8803 call_trans2mkdir(conn, req,
8804 &state->param, state->total_param,
8805 &state->data, state->total_data,
8806 state->max_data_return);
8807 END_PROFILE(Trans2_mkdir);
8808 break;
8811 case TRANSACT2_GET_DFS_REFERRAL:
8813 START_PROFILE(Trans2_get_dfs_referral);
8814 call_trans2getdfsreferral(conn, req,
8815 &state->param, state->total_param,
8816 &state->data, state->total_data,
8817 state->max_data_return);
8818 END_PROFILE(Trans2_get_dfs_referral);
8819 break;
8822 case TRANSACT2_IOCTL:
8824 START_PROFILE(Trans2_ioctl);
8825 call_trans2ioctl(conn, req,
8826 &state->param, state->total_param,
8827 &state->data, state->total_data,
8828 state->max_data_return);
8829 END_PROFILE(Trans2_ioctl);
8830 break;
8833 default:
8834 /* Error in request */
8835 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8836 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8840 /****************************************************************************
8841 Reply to a SMBtrans2.
8842 ****************************************************************************/
8844 void reply_trans2(struct smb_request *req)
8846 connection_struct *conn = req->conn;
8847 unsigned int dsoff;
8848 unsigned int dscnt;
8849 unsigned int psoff;
8850 unsigned int pscnt;
8851 unsigned int tran_call;
8852 struct trans_state *state;
8853 NTSTATUS result;
8855 START_PROFILE(SMBtrans2);
8857 if (req->wct < 14) {
8858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8859 END_PROFILE(SMBtrans2);
8860 return;
8863 dsoff = SVAL(req->vwv+12, 0);
8864 dscnt = SVAL(req->vwv+11, 0);
8865 psoff = SVAL(req->vwv+10, 0);
8866 pscnt = SVAL(req->vwv+9, 0);
8867 tran_call = SVAL(req->vwv+14, 0);
8869 result = allow_new_trans(conn->pending_trans, req->mid);
8870 if (!NT_STATUS_IS_OK(result)) {
8871 DEBUG(2, ("Got invalid trans2 request: %s\n",
8872 nt_errstr(result)));
8873 reply_nterror(req, result);
8874 END_PROFILE(SMBtrans2);
8875 return;
8878 if (IS_IPC(conn)) {
8879 switch (tran_call) {
8880 /* List the allowed trans2 calls on IPC$ */
8881 case TRANSACT2_OPEN:
8882 case TRANSACT2_GET_DFS_REFERRAL:
8883 case TRANSACT2_QFILEINFO:
8884 case TRANSACT2_QFSINFO:
8885 case TRANSACT2_SETFSINFO:
8886 break;
8887 default:
8888 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8889 END_PROFILE(SMBtrans2);
8890 return;
8894 if ((state = talloc(conn, struct trans_state)) == NULL) {
8895 DEBUG(0, ("talloc failed\n"));
8896 reply_nterror(req, NT_STATUS_NO_MEMORY);
8897 END_PROFILE(SMBtrans2);
8898 return;
8901 state->cmd = SMBtrans2;
8903 state->mid = req->mid;
8904 state->vuid = req->vuid;
8905 state->setup_count = SVAL(req->vwv+13, 0);
8906 state->setup = NULL;
8907 state->total_param = SVAL(req->vwv+0, 0);
8908 state->param = NULL;
8909 state->total_data = SVAL(req->vwv+1, 0);
8910 state->data = NULL;
8911 state->max_param_return = SVAL(req->vwv+2, 0);
8912 state->max_data_return = SVAL(req->vwv+3, 0);
8913 state->max_setup_return = SVAL(req->vwv+4, 0);
8914 state->close_on_completion = BITSETW(req->vwv+5, 0);
8915 state->one_way = BITSETW(req->vwv+5, 1);
8917 state->call = tran_call;
8919 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8920 is so as a sanity check */
8921 if (state->setup_count != 1) {
8923 * Need to have rc=0 for ioctl to get job id for OS/2.
8924 * Network printing will fail if function is not successful.
8925 * Similar function in reply.c will be used if protocol
8926 * is LANMAN1.0 instead of LM1.2X002.
8927 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8928 * outbuf doesn't have to be set(only job id is used).
8930 if ( (state->setup_count == 4)
8931 && (tran_call == TRANSACT2_IOCTL)
8932 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8933 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8934 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8935 } else {
8936 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8937 DEBUG(2,("Transaction is %d\n",tran_call));
8938 TALLOC_FREE(state);
8939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8940 END_PROFILE(SMBtrans2);
8941 return;
8945 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8946 goto bad_param;
8948 if (state->total_data) {
8950 if (trans_oob(state->total_data, 0, dscnt)
8951 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8952 goto bad_param;
8955 /* Can't use talloc here, the core routines do realloc on the
8956 * params and data. */
8957 state->data = (char *)SMB_MALLOC(state->total_data);
8958 if (state->data == NULL) {
8959 DEBUG(0,("reply_trans2: data malloc fail for %u "
8960 "bytes !\n", (unsigned int)state->total_data));
8961 TALLOC_FREE(state);
8962 reply_nterror(req, NT_STATUS_NO_MEMORY);
8963 END_PROFILE(SMBtrans2);
8964 return;
8967 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8970 if (state->total_param) {
8972 if (trans_oob(state->total_param, 0, pscnt)
8973 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8974 goto bad_param;
8977 /* Can't use talloc here, the core routines do realloc on the
8978 * params and data. */
8979 state->param = (char *)SMB_MALLOC(state->total_param);
8980 if (state->param == NULL) {
8981 DEBUG(0,("reply_trans: param malloc fail for %u "
8982 "bytes !\n", (unsigned int)state->total_param));
8983 SAFE_FREE(state->data);
8984 TALLOC_FREE(state);
8985 reply_nterror(req, NT_STATUS_NO_MEMORY);
8986 END_PROFILE(SMBtrans2);
8987 return;
8990 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8993 state->received_data = dscnt;
8994 state->received_param = pscnt;
8996 if ((state->received_param == state->total_param) &&
8997 (state->received_data == state->total_data)) {
8999 handle_trans2(conn, req, state);
9001 SAFE_FREE(state->data);
9002 SAFE_FREE(state->param);
9003 TALLOC_FREE(state);
9004 END_PROFILE(SMBtrans2);
9005 return;
9008 DLIST_ADD(conn->pending_trans, state);
9010 /* We need to send an interim response then receive the rest
9011 of the parameter/data bytes */
9012 reply_outbuf(req, 0, 0);
9013 show_msg((char *)req->outbuf);
9014 END_PROFILE(SMBtrans2);
9015 return;
9017 bad_param:
9019 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9020 SAFE_FREE(state->data);
9021 SAFE_FREE(state->param);
9022 TALLOC_FREE(state);
9023 END_PROFILE(SMBtrans2);
9024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9028 /****************************************************************************
9029 Reply to a SMBtranss2
9030 ****************************************************************************/
9032 void reply_transs2(struct smb_request *req)
9034 connection_struct *conn = req->conn;
9035 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9036 struct trans_state *state;
9038 START_PROFILE(SMBtranss2);
9040 show_msg((const char *)req->inbuf);
9042 /* Windows clients expect all replies to
9043 a transact secondary (SMBtranss2 0x33)
9044 to have a command code of transact
9045 (SMBtrans2 0x32). See bug #8989
9046 and also [MS-CIFS] section 2.2.4.47.2
9047 for details.
9049 req->cmd = SMBtrans2;
9051 if (req->wct < 8) {
9052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9053 END_PROFILE(SMBtranss2);
9054 return;
9057 for (state = conn->pending_trans; state != NULL;
9058 state = state->next) {
9059 if (state->mid == req->mid) {
9060 break;
9064 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9066 END_PROFILE(SMBtranss2);
9067 return;
9070 /* Revise state->total_param and state->total_data in case they have
9071 changed downwards */
9073 if (SVAL(req->vwv+0, 0) < state->total_param)
9074 state->total_param = SVAL(req->vwv+0, 0);
9075 if (SVAL(req->vwv+1, 0) < state->total_data)
9076 state->total_data = SVAL(req->vwv+1, 0);
9078 pcnt = SVAL(req->vwv+2, 0);
9079 poff = SVAL(req->vwv+3, 0);
9080 pdisp = SVAL(req->vwv+4, 0);
9082 dcnt = SVAL(req->vwv+5, 0);
9083 doff = SVAL(req->vwv+6, 0);
9084 ddisp = SVAL(req->vwv+7, 0);
9086 state->received_param += pcnt;
9087 state->received_data += dcnt;
9089 if ((state->received_data > state->total_data) ||
9090 (state->received_param > state->total_param))
9091 goto bad_param;
9093 if (pcnt) {
9094 if (trans_oob(state->total_param, pdisp, pcnt)
9095 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9096 goto bad_param;
9098 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9101 if (dcnt) {
9102 if (trans_oob(state->total_data, ddisp, dcnt)
9103 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9104 goto bad_param;
9106 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9109 if ((state->received_param < state->total_param) ||
9110 (state->received_data < state->total_data)) {
9111 END_PROFILE(SMBtranss2);
9112 return;
9115 handle_trans2(conn, req, state);
9117 DLIST_REMOVE(conn->pending_trans, state);
9118 SAFE_FREE(state->data);
9119 SAFE_FREE(state->param);
9120 TALLOC_FREE(state);
9122 END_PROFILE(SMBtranss2);
9123 return;
9125 bad_param:
9127 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9128 DLIST_REMOVE(conn->pending_trans, state);
9129 SAFE_FREE(state->data);
9130 SAFE_FREE(state->param);
9131 TALLOC_FREE(state);
9132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9133 END_PROFILE(SMBtranss2);
9134 return;