s3:smbd: allow status code in smbd_do_qfsinfo() to be set by information class handler
[Samba.git] / source3 / smbd / trans2.c
blob4dd40ad26c920e3134c08e8b2ba865ea64ea0fb6
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
882 uint8_t eclass;
883 uint32_t ecode;
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
887 __LINE__,__FILE__);
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
891 (char *)req->outbuf,
892 true, req->seqnum+1,
893 IS_CONN_ENCRYPTED(conn),
894 &req->pcd)) {
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
898 return;
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
913 + 2 * 10 /* wct */
914 + alignment_offset
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
966 else
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
974 } else {
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1014 if (overflow) {
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1018 __LINE__,__FILE__);
1019 } else if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1034 &req->pcd))
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1045 /* Sanity check */
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1049 return;
1053 return;
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1069 int deny_mode;
1070 int32 open_attr;
1071 bool oplock_request;
1072 #if 0
1073 bool return_additional_info;
1074 int16 open_sattr;
1075 time_t open_time;
1076 #endif
1077 int open_ofun;
1078 uint32 open_size;
1079 char *pname;
1080 char *fname = NULL;
1081 off_t size=0;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1084 int smb_action = 0;
1085 files_struct *fsp;
1086 struct ea_list *ea_list = NULL;
1087 uint16 flags = 0;
1088 NTSTATUS status;
1089 uint32 access_mask;
1090 uint32 share_mode;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 goto out;
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1113 #if 0
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1117 #endif
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = &params[28];
1122 if (IS_IPC(conn)) {
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1124 goto out;
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1129 &status);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1132 goto out;
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1159 goto out;
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1163 open_ofun,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1166 &create_options,
1167 &private_flags)) {
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1169 goto out;
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 goto out;
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 goto out;
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1187 total_data - 4);
1188 if (!ea_list) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1195 goto out;
1198 if (ea_list_has_invalid_name(ea_list)) {
1199 int param_len = 30;
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1203 goto out;
1205 params = *pparams;
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1209 goto out;
1213 status = SMB_VFS_CREATE_FILE(
1214 conn, /* conn */
1215 req, /* req */
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1225 private_flags,
1226 NULL, /* sd */
1227 ea_list, /* ea_list */
1228 &fsp, /* result */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1234 goto out;
1236 reply_openerror(req, status);
1237 goto out;
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 goto out;
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1254 goto out;
1256 params = *pparams;
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1277 if (flags & 8) {
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1279 smb_fname);
1280 SIVAL(params, 26, ea_size);
1281 } else {
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1287 out:
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1300 const char *str,
1301 const char *mask)
1303 if (mask[0] == '.' && mask[1] == 0) {
1304 return false;
1307 if (has_wild) {
1308 return false;
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1313 } else {
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1324 if(S_ISREG(mode))
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1328 #ifdef S_ISLNK
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1331 #endif
1332 #ifdef S_ISCHR
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1335 #endif
1336 #ifdef S_ISBLK
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1339 #endif
1340 #ifdef S_ISFIFO
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1343 #endif
1344 #ifdef S_ISSOCK
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1347 #endif
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1361 uint32 perms,
1362 enum perm_type ptype,
1363 mode_t *ret_perms)
1365 mode_t ret = 0;
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1370 } else {
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1385 #ifdef S_ISVTX
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1387 #endif
1388 #ifdef S_ISGID
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1390 #endif
1391 #ifdef S_ISUID
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1393 #endif
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1413 *ret_perms = ret;
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 "as a directory\n",
1433 pathname));
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1436 return true;
1438 errno = saved_errno;
1439 return false;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1451 bool has_wild;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1456 void *private_data,
1457 const char *dname,
1458 const char *mask,
1459 char **_fname)
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1463 bool ok;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1465 bool got_match;
1466 const char *fname;
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1472 if (!ok) {
1473 return false;
1475 fname = mangled_name;
1476 } else {
1477 fname = dname;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1482 fname, mask);
1483 state->got_exact_match = got_match;
1484 if (!got_match) {
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1500 if (!ok) {
1501 return false;
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1508 if (!got_match) {
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1514 if (!got_match) {
1515 return false;
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1520 return false;
1523 return true;
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1527 void *private_data,
1528 struct smb_filename *smb_fname,
1529 uint32_t *_mode)
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1534 uint32_t mode = 0;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1541 strerror(errno)));
1542 return false;
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1547 * directories */
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1551 &smb_fname->st);
1552 if (!ms_dfs_link) {
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1556 strerror(errno)));
1557 return false;
1561 if (ms_dfs_link) {
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1563 } else {
1564 mode = dos_mode(state->conn, smb_fname);
1567 *_mode = mode;
1568 return true;
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1573 uint16_t flags2,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1578 uint32_t mode,
1579 const char *fname,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1582 uint8_t align,
1583 bool do_pad,
1584 char *base_data,
1585 char **ppdata,
1586 char *end_data,
1587 bool *out_of_space,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1591 uint32_t reskey=0;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1595 uint32_t len;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1598 char *nameptr;
1599 char *last_entry_ptr;
1600 bool was_8_3;
1601 int off;
1602 int pad = 0;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1639 pad -= off;
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1645 (unsigned int)pad,
1646 space_remaining ));
1647 return false; /* Not finished - just out of space */
1650 off += pad;
1651 /* initialize padding to 0 */
1652 if (pad) {
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1658 space_remaining ));
1660 pdata += pad;
1661 p = pdata;
1662 last_entry_ptr = p;
1664 pad = 0;
1665 off = 0;
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 23;
1681 nameptr = p;
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE);
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1689 if (len > 2) {
1690 SCVAL(nameptr, -1, len - 2);
1691 } else {
1692 SCVAL(nameptr, -1, 0);
1694 } else {
1695 if (len > 1) {
1696 SCVAL(nameptr, -1, len - 1);
1697 } else {
1698 SCVAL(nameptr, -1, 0);
1701 p += len;
1702 break;
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key) {
1707 SIVAL(p,0,reskey);
1708 p += 4;
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1715 SSVAL(p,20,mode);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1718 smb_fname);
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1721 p += 27;
1722 nameptr = p - 1;
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1747 size_t ea_len = 0;
1748 NTSTATUS status;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1751 if (!name_list) {
1752 return false;
1754 if (requires_resume_key) {
1755 SIVAL(p,0,reskey);
1756 p += 4;
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1763 SSVAL(p,20,mode);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1767 smb_fname,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 file_list = NULL;
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1781 space_remaining ));
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1787 nameptr = p;
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1792 if (len > 2) {
1793 len -= 2;
1794 } else {
1795 len = 0;
1797 } else {
1798 if (len > 1) {
1799 len -= 1;
1800 } else {
1801 len = 0;
1804 SCVAL(nameptr,0,len);
1805 p += len + 1;
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1807 break;
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1813 p += 4;
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1825 } else {
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1830 p += 4;
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1838 conn->params)) {
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1846 if (len < 24) {
1847 memset(p + 2 + len,'\0',24 - len);
1849 SSVAL(p, 0, len);
1850 } else {
1851 memset(p,'\0',26);
1853 p += 2 + 24;
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1857 SIVAL(q,0,len);
1858 p += len;
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1867 SIVAL(pdata,0,pad);
1869 * set padding to zero
1871 if (do_pad) {
1872 memset(p, 0, pad - len);
1873 p = pdata + pad;
1874 } else {
1875 p = pdata + len;
1877 break;
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1881 p += 4;
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1893 SIVAL(p,0,len);
1894 p += 4 + len;
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1903 SIVAL(pdata,0,pad);
1905 * set padding to zero
1907 if (do_pad) {
1908 memset(p, 0, pad - len);
1909 p = pdata + pad;
1910 } else {
1911 p = pdata + len;
1913 break;
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1936 SIVAL(q, 0, len);
1937 p += len;
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1946 SIVAL(pdata,0,pad);
1948 * set padding to zero
1950 if (do_pad) {
1951 memset(p, 0, pad - len);
1952 p = pdata + pad;
1953 } else {
1954 p = pdata + len;
1956 break;
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1960 p += 4;
1961 SIVAL(p,0,reskey); p += 4;
1962 p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1968 SIVAL(p, -4, len);
1969 p += len;
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1978 SIVAL(pdata,0,pad);
1980 * set padding to zero
1982 if (do_pad) {
1983 memset(p, 0, pad - len);
1984 p = pdata + pad;
1985 } else {
1986 p = pdata + len;
1988 break;
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1992 p += 4;
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2004 } else {
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2006 smb_fname);
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2009 p += 4;
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2015 SIVAL(q, 0, len);
2016 p += len;
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2025 SIVAL(pdata,0,pad);
2027 * set padding to zero
2029 if (do_pad) {
2030 memset(p, 0, pad - len);
2031 p = pdata + pad;
2032 } else {
2033 p = pdata + len;
2035 break;
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2040 p += 4;
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2052 } else {
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2054 smb_fname);
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2057 p += 4;
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2065 conn->params)) {
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2073 SSVAL(p, 0, len);
2074 if (len < 24) {
2075 memset(p + 2 + len,'\0',24 - len);
2077 SSVAL(p, 0, len);
2078 } else {
2079 memset(p,'\0',26);
2081 p += 26;
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
2087 SIVAL(q,0,len);
2088 p += len;
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2097 SIVAL(pdata,0,pad);
2099 * set padding to zero
2101 if (do_pad) {
2102 memset(p, 0, pad - len);
2103 p = pdata + pad;
2104 } else {
2105 p = pdata + len;
2107 break;
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2113 p+= 4;
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2124 STR_TERMINATE);
2125 } else {
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2129 nameptr = p;
2130 p += 4;
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2136 p += len;
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2145 SIVAL(pdata,0,pad);
2147 * set padding to zero
2149 if (do_pad) {
2150 memset(p, 0, pad - len);
2151 p = pdata + pad;
2152 } else {
2153 p = pdata + len;
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2157 break;
2159 default:
2160 return false;
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2168 space_remaining ));
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2175 *ppdata = p;
2177 return true;
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 int requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 uint8_t align,
2191 bool do_pad,
2192 char **ppdata,
2193 char *base_data,
2194 char *end_data,
2195 int space_remaining,
2196 bool *out_of_space,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2201 const char *p;
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2204 uint32_t mode = 0;
2205 char *fname = NULL;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2208 bool ok;
2209 uint64_t last_entry_off = 0;
2211 ZERO_STRUCT(state);
2212 state.conn = conn;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2222 if(p != NULL) {
2223 if(p[1] == '\0') {
2224 mask = "*.*";
2225 } else {
2226 mask = p+1;
2228 } else {
2229 mask = path_mask;
2232 ok = smbd_dirptr_get_entry(ctx,
2233 dirptr,
2234 mask,
2235 dirtype,
2236 dont_descend,
2237 ask_sharemode,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2240 &state,
2241 &fname,
2242 &smb_fname,
2243 &mode,
2244 &prev_dirpos);
2245 if (!ok) {
2246 return false;
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2252 conn,
2253 flags2,
2254 info_level,
2255 name_list,
2256 state.check_mangled_names,
2257 requires_resume_key,
2258 mode,
2259 fname,
2260 smb_fname,
2261 space_remaining,
2262 align,
2263 do_pad,
2264 base_data,
2265 ppdata,
2266 end_data,
2267 out_of_space,
2268 &last_entry_off);
2269 TALLOC_FREE(fname);
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2273 return false;
2275 if (!ok) {
2276 return false;
2279 *_last_entry_off = last_entry_off;
2280 return true;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2286 uint16 flags2,
2287 const char *path_mask,
2288 uint32 dirtype,
2289 int info_level,
2290 bool requires_resume_key,
2291 bool dont_descend,
2292 bool ask_sharemode,
2293 char **ppdata,
2294 char *base_data,
2295 char *end_data,
2296 int space_remaining,
2297 bool *out_of_space,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2302 uint8_t align = 4;
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2307 align = 1;
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2313 align, do_pad,
2314 ppdata, base_data, end_data,
2315 space_remaining,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2334 requested. */
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2338 char *data_end;
2339 uint32 dirtype;
2340 int maxentries;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2343 bool close_if_end;
2344 bool requires_resume_key;
2345 int info_level;
2346 char *directory = NULL;
2347 char *mask = NULL;
2348 char *p;
2349 int last_entry_off=0;
2350 int dptr_num = -1;
2351 int numentries = 0;
2352 int i;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2367 if (total_params < 13) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2372 dirtype = SVAL(params,0);
2373 maxentries = SVAL(params,2);
2374 findfirst_flags = SVAL(params,4);
2375 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2376 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2377 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2378 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2379 security_token_has_privilege(get_current_nttok(conn),
2380 SEC_PRIV_BACKUP));
2382 info_level = SVAL(params,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2387 (int)backup_priv,
2388 info_level, max_data_bytes));
2390 if (!maxentries) {
2391 /* W2K3 seems to treat zero as 1. */
2392 maxentries = 1;
2395 switch (info_level) {
2396 case SMB_FIND_INFO_STANDARD:
2397 case SMB_FIND_EA_SIZE:
2398 case SMB_FIND_EA_LIST:
2399 case SMB_FIND_FILE_DIRECTORY_INFO:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_NAMES_INFO:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2405 break;
2406 case SMB_FIND_FILE_UNIX:
2407 case SMB_FIND_FILE_UNIX_INFO2:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode = false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 goto out;
2414 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 break;
2416 default:
2417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2418 goto out;
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2422 params+12, total_params - 12,
2423 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2424 if (!NT_STATUS_IS_OK(ntstatus)) {
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 if (backup_priv) {
2430 become_root();
2431 ntstatus = filename_convert_with_privilege(ctx,
2432 conn,
2433 req,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2438 } else {
2439 ntstatus = filename_convert(ctx, conn,
2440 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 directory,
2442 ucf_flags,
2443 &mask_contains_wcard,
2444 &smb_dname);
2447 if (!NT_STATUS_IS_OK(ntstatus)) {
2448 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2450 ERRSRV, ERRbadpath);
2451 goto out;
2453 reply_nterror(req, ntstatus);
2454 goto out;
2457 mask = smb_dname->original_lcomp;
2459 directory = smb_dname->base_name;
2461 p = strrchr_m(directory,'/');
2462 if(p == NULL) {
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory[0] == '.') && (directory[1] == '\0')) {
2465 mask = talloc_strdup(ctx,"*");
2466 if (!mask) {
2467 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 goto out;
2470 mask_contains_wcard = True;
2472 } else {
2473 *p = 0;
2476 if (p == NULL || p == directory) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory = talloc_strdup(talloc_tos(), ".");
2479 if (!directory) {
2480 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 goto out;
2485 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2487 if (info_level == SMB_FIND_EA_LIST) {
2488 uint32 ea_size;
2490 if (total_data < 4) {
2491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2492 goto out;
2495 ea_size = IVAL(pdata,0);
2496 if (ea_size != total_data) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 goto out;
2503 if (!lp_ea_support(SNUM(conn))) {
2504 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2505 goto out;
2508 /* Pull out the list of names. */
2509 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2510 if (!ea_list) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2516 *ppdata = (char *)SMB_REALLOC(
2517 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2518 if(*ppdata == NULL ) {
2519 reply_nterror(req, NT_STATUS_NO_MEMORY);
2520 goto out;
2522 pdata = *ppdata;
2523 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2525 /* Realloc the params space */
2526 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2527 if (*pparams == NULL) {
2528 reply_nterror(req, NT_STATUS_NO_MEMORY);
2529 goto out;
2531 params = *pparams;
2533 /* Save the wildcard match and attribs we are using on this directory -
2534 needed as lanman2 assumes these are being saved between calls */
2536 ntstatus = dptr_create(conn,
2537 req,
2538 NULL, /* fsp */
2539 directory,
2540 False,
2541 True,
2542 req->smbpid,
2543 mask,
2544 mask_contains_wcard,
2545 dirtype,
2546 &dirptr);
2548 if (!NT_STATUS_IS_OK(ntstatus)) {
2549 reply_nterror(req, ntstatus);
2550 goto out;
2553 if (backup_priv) {
2554 /* Remember this in case we have
2555 to do a findnext. */
2556 dptr_set_priv(dirptr);
2559 dptr_num = dptr_dnum(dirptr);
2560 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2562 /* Initialize per TRANS2_FIND_FIRST operation data */
2563 dptr_init_search_op(dirptr);
2565 /* We don't need to check for VOL here as this is returned by
2566 a different TRANS2 call. */
2568 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2569 directory,lp_dontdescend(ctx, SNUM(conn))));
2570 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2571 dont_descend = True;
2573 p = pdata;
2574 space_remaining = max_data_bytes;
2575 out_of_space = False;
2577 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2578 bool got_exact_match = False;
2580 /* this is a heuristic to avoid seeking the dirptr except when
2581 absolutely necessary. It allows for a filename of about 40 chars */
2582 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2583 out_of_space = True;
2584 finished = False;
2585 } else {
2586 finished = !get_lanman2_dir_entry(ctx,
2587 conn,
2588 dirptr,
2589 req->flags2,
2590 mask,dirtype,info_level,
2591 requires_resume_key,dont_descend,
2592 ask_sharemode,
2593 &p,pdata,data_end,
2594 space_remaining, &out_of_space,
2595 &got_exact_match,
2596 &last_entry_off, ea_list);
2599 if (finished && out_of_space)
2600 finished = False;
2602 if (!finished && !out_of_space)
2603 numentries++;
2606 * As an optimisation if we know we aren't looking
2607 * for a wildcard name (ie. the name matches the wildcard exactly)
2608 * then we can finish on any (first) match.
2609 * This speeds up large directory searches. JRA.
2612 if(got_exact_match)
2613 finished = True;
2615 /* Ensure space_remaining never goes -ve. */
2616 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2617 space_remaining = 0;
2618 out_of_space = true;
2619 } else {
2620 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2624 /* Check if we can close the dirptr */
2625 if(close_after_first || (finished && close_if_end)) {
2626 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2627 dptr_close(sconn, &dptr_num);
2631 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2632 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2633 * the protocol level is less than NT1. Tested with smbclient. JRA.
2634 * This should fix the OS/2 client bug #2335.
2637 if(numentries == 0) {
2638 dptr_close(sconn, &dptr_num);
2639 if (get_Protocol() < PROTOCOL_NT1) {
2640 reply_force_doserror(req, ERRDOS, ERRnofiles);
2641 goto out;
2642 } else {
2643 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2644 ERRDOS, ERRbadfile);
2645 goto out;
2649 /* At this point pdata points to numentries directory entries. */
2651 /* Set up the return parameter block */
2652 SSVAL(params,0,dptr_num);
2653 SSVAL(params,2,numentries);
2654 SSVAL(params,4,finished);
2655 SSVAL(params,6,0); /* Never an EA error */
2656 SSVAL(params,8,last_entry_off);
2658 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2659 max_data_bytes);
2661 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2662 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2663 if (!directory) {
2664 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2669 smb_fn_name(req->cmd),
2670 mask, directory, dirtype, numentries ) );
2673 * Force a name mangle here to ensure that the
2674 * mask as an 8.3 name is top of the mangled cache.
2675 * The reasons for this are subtle. Don't remove
2676 * this code unless you know what you are doing
2677 * (see PR#13758). JRA.
2680 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2681 char mangled_name[13];
2682 name_to_8_3(mask, mangled_name, True, conn->params);
2684 out:
2686 if (backup_priv) {
2687 unbecome_root();
2690 TALLOC_FREE(smb_dname);
2691 return;
2694 /****************************************************************************
2695 Reply to a TRANS2_FINDNEXT.
2696 ****************************************************************************/
2698 static void call_trans2findnext(connection_struct *conn,
2699 struct smb_request *req,
2700 char **pparams, int total_params,
2701 char **ppdata, int total_data,
2702 unsigned int max_data_bytes)
2704 /* We must be careful here that we don't return more than the
2705 allowed number of data bytes. If this means returning fewer than
2706 maxentries then so be it. We assume that the redirector has
2707 enough room for the fixed number of parameter bytes it has
2708 requested. */
2709 char *params = *pparams;
2710 char *pdata = *ppdata;
2711 char *data_end;
2712 int dptr_num;
2713 int maxentries;
2714 uint16 info_level;
2715 uint32 resume_key;
2716 uint16 findnext_flags;
2717 bool close_after_request;
2718 bool close_if_end;
2719 bool requires_resume_key;
2720 bool continue_bit;
2721 bool mask_contains_wcard = False;
2722 char *resume_name = NULL;
2723 const char *mask = NULL;
2724 const char *directory = NULL;
2725 char *p = NULL;
2726 uint16 dirtype;
2727 int numentries = 0;
2728 int i, last_entry_off=0;
2729 bool finished = False;
2730 bool dont_descend = False;
2731 bool out_of_space = False;
2732 int space_remaining;
2733 struct ea_list *ea_list = NULL;
2734 NTSTATUS ntstatus = NT_STATUS_OK;
2735 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2736 TALLOC_CTX *ctx = talloc_tos();
2737 struct dptr_struct *dirptr;
2738 struct smbd_server_connection *sconn = req->sconn;
2739 bool backup_priv = false;
2741 if (total_params < 13) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2743 return;
2746 dptr_num = SVAL(params,0);
2747 maxentries = SVAL(params,2);
2748 info_level = SVAL(params,4);
2749 resume_key = IVAL(params,6);
2750 findnext_flags = SVAL(params,10);
2751 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2752 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2753 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2754 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2756 if (!continue_bit) {
2757 /* We only need resume_name if continue_bit is zero. */
2758 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2759 params+12,
2760 total_params - 12, STR_TERMINATE, &ntstatus,
2761 &mask_contains_wcard);
2762 if (!NT_STATUS_IS_OK(ntstatus)) {
2763 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2764 complain (it thinks we're asking for the directory above the shared
2765 path or an invalid name). Catch this as the resume name is only compared, never used in
2766 a file access. JRA. */
2767 srvstr_pull_talloc(ctx, params, req->flags2,
2768 &resume_name, params+12,
2769 total_params - 12,
2770 STR_TERMINATE);
2772 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2773 reply_nterror(req, ntstatus);
2774 return;
2779 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2780 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2781 resume_key = %d resume name = %s continue=%d level = %d\n",
2782 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2783 requires_resume_key, resume_key,
2784 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2786 if (!maxentries) {
2787 /* W2K3 seems to treat zero as 1. */
2788 maxentries = 1;
2791 switch (info_level) {
2792 case SMB_FIND_INFO_STANDARD:
2793 case SMB_FIND_EA_SIZE:
2794 case SMB_FIND_EA_LIST:
2795 case SMB_FIND_FILE_DIRECTORY_INFO:
2796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2797 case SMB_FIND_FILE_NAMES_INFO:
2798 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2799 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2801 break;
2802 case SMB_FIND_FILE_UNIX:
2803 case SMB_FIND_FILE_UNIX_INFO2:
2804 /* Always use filesystem for UNIX mtime query. */
2805 ask_sharemode = false;
2806 if (!lp_unix_extensions()) {
2807 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2808 return;
2810 break;
2811 default:
2812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 return;
2816 if (info_level == SMB_FIND_EA_LIST) {
2817 uint32 ea_size;
2819 if (total_data < 4) {
2820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 return;
2824 ea_size = IVAL(pdata,0);
2825 if (ea_size != total_data) {
2826 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2827 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2829 return;
2832 if (!lp_ea_support(SNUM(conn))) {
2833 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2834 return;
2837 /* Pull out the list of names. */
2838 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2839 if (!ea_list) {
2840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2841 return;
2845 *ppdata = (char *)SMB_REALLOC(
2846 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2847 if(*ppdata == NULL) {
2848 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 return;
2852 pdata = *ppdata;
2853 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2855 /* Realloc the params space */
2856 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2857 if(*pparams == NULL ) {
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 return;
2862 params = *pparams;
2864 /* Check that the dptr is valid */
2865 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2866 reply_nterror(req, STATUS_NO_MORE_FILES);
2867 return;
2870 directory = dptr_path(sconn, dptr_num);
2872 /* Get the wildcard mask from the dptr */
2873 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2874 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2875 reply_nterror(req, STATUS_NO_MORE_FILES);
2876 return;
2879 /* Get the attr mask from the dptr */
2880 dirtype = dptr_attr(sconn, dptr_num);
2882 backup_priv = dptr_get_priv(dirptr);
2884 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2885 "backup_priv = %d\n",
2886 dptr_num, mask, dirtype,
2887 (long)dirptr,
2888 dptr_TellDir(dirptr),
2889 (int)backup_priv));
2891 /* Initialize per TRANS2_FIND_NEXT operation data */
2892 dptr_init_search_op(dirptr);
2894 /* We don't need to check for VOL here as this is returned by
2895 a different TRANS2 call. */
2897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2898 directory,lp_dontdescend(ctx, SNUM(conn))));
2899 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2900 dont_descend = True;
2902 p = pdata;
2903 space_remaining = max_data_bytes;
2904 out_of_space = False;
2906 if (backup_priv) {
2907 become_root();
2911 * Seek to the correct position. We no longer use the resume key but
2912 * depend on the last file name instead.
2915 if(!continue_bit && resume_name && *resume_name) {
2916 SMB_STRUCT_STAT st;
2918 long current_pos = 0;
2920 * Remember, name_to_8_3 is called by
2921 * get_lanman2_dir_entry(), so the resume name
2922 * could be mangled. Ensure we check the unmangled name.
2925 if (mangle_is_mangled(resume_name, conn->params)) {
2926 char *new_resume_name = NULL;
2927 mangle_lookup_name_from_8_3(ctx,
2928 resume_name,
2929 &new_resume_name,
2930 conn->params);
2931 if (new_resume_name) {
2932 resume_name = new_resume_name;
2937 * Fix for NT redirector problem triggered by resume key indexes
2938 * changing between directory scans. We now return a resume key of 0
2939 * and instead look for the filename to continue from (also given
2940 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2941 * findfirst/findnext (as is usual) then the directory pointer
2942 * should already be at the correct place.
2945 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2946 } /* end if resume_name && !continue_bit */
2948 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2949 bool got_exact_match = False;
2951 /* this is a heuristic to avoid seeking the dirptr except when
2952 absolutely necessary. It allows for a filename of about 40 chars */
2953 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2954 out_of_space = True;
2955 finished = False;
2956 } else {
2957 finished = !get_lanman2_dir_entry(ctx,
2958 conn,
2959 dirptr,
2960 req->flags2,
2961 mask,dirtype,info_level,
2962 requires_resume_key,dont_descend,
2963 ask_sharemode,
2964 &p,pdata,data_end,
2965 space_remaining, &out_of_space,
2966 &got_exact_match,
2967 &last_entry_off, ea_list);
2970 if (finished && out_of_space)
2971 finished = False;
2973 if (!finished && !out_of_space)
2974 numentries++;
2977 * As an optimisation if we know we aren't looking
2978 * for a wildcard name (ie. the name matches the wildcard exactly)
2979 * then we can finish on any (first) match.
2980 * This speeds up large directory searches. JRA.
2983 if(got_exact_match)
2984 finished = True;
2986 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2989 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req->cmd),
2991 mask, directory, dirtype, numentries ) );
2993 /* Check if we can close the dirptr */
2994 if(close_after_request || (finished && close_if_end)) {
2995 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2996 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2999 if (backup_priv) {
3000 unbecome_root();
3003 /* Set up the return parameter block */
3004 SSVAL(params,0,numentries);
3005 SSVAL(params,2,finished);
3006 SSVAL(params,4,0); /* Never an EA error */
3007 SSVAL(params,6,last_entry_off);
3009 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3010 max_data_bytes);
3012 return;
3015 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3017 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3018 return objid;
3021 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3023 SMB_ASSERT(extended_info != NULL);
3025 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3026 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3027 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3028 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3029 #ifdef SAMBA_VERSION_REVISION
3030 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3031 #endif
3032 extended_info->samba_subversion = 0;
3033 #ifdef SAMBA_VERSION_RC_RELEASE
3034 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3035 #else
3036 #ifdef SAMBA_VERSION_PRE_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3038 #endif
3039 #endif
3040 #ifdef SAMBA_VERSION_VENDOR_PATCH
3041 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3042 #endif
3043 extended_info->samba_gitcommitdate = 0;
3044 #ifdef SAMBA_VERSION_COMMIT_TIME
3045 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3046 #endif
3048 memset(extended_info->samba_version_string, 0,
3049 sizeof(extended_info->samba_version_string));
3051 snprintf (extended_info->samba_version_string,
3052 sizeof(extended_info->samba_version_string),
3053 "%s", samba_version_string());
3056 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3057 TALLOC_CTX *mem_ctx,
3058 uint16_t info_level,
3059 uint16_t flags2,
3060 unsigned int max_data_bytes,
3061 struct smb_filename *fname,
3062 char **ppdata,
3063 int *ret_data_len)
3065 char *pdata, *end_data;
3066 int data_len = 0, len;
3067 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3068 int snum = SNUM(conn);
3069 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3070 char *filename = NULL;
3071 uint32 additional_flags = 0;
3072 struct smb_filename smb_fname;
3073 SMB_STRUCT_STAT st;
3074 NTSTATUS status = NT_STATUS_OK;
3076 if (fname == NULL || fname->base_name == NULL) {
3077 filename = ".";
3078 } else {
3079 filename = fname->base_name;
3082 if (IS_IPC(conn)) {
3083 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3084 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3085 "info level (0x%x) on IPC$.\n",
3086 (unsigned int)info_level));
3087 return NT_STATUS_ACCESS_DENIED;
3091 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3093 ZERO_STRUCT(smb_fname);
3094 smb_fname.base_name = discard_const_p(char, filename);
3096 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3097 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3098 return map_nt_error_from_unix(errno);
3101 st = smb_fname.st;
3103 *ppdata = (char *)SMB_REALLOC(
3104 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3105 if (*ppdata == NULL) {
3106 return NT_STATUS_NO_MEMORY;
3109 pdata = *ppdata;
3110 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3111 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3113 switch (info_level) {
3114 case SMB_INFO_ALLOCATION:
3116 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3117 data_len = 18;
3118 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3119 return map_nt_error_from_unix(errno);
3122 block_size = lp_block_size(snum);
3123 if (bsize < block_size) {
3124 uint64_t factor = block_size/bsize;
3125 bsize = block_size;
3126 dsize /= factor;
3127 dfree /= factor;
3129 if (bsize > block_size) {
3130 uint64_t factor = bsize/block_size;
3131 bsize = block_size;
3132 dsize *= factor;
3133 dfree *= factor;
3135 bytes_per_sector = 512;
3136 sectors_per_unit = bsize/bytes_per_sector;
3138 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3139 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3140 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3142 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3143 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3144 SIVAL(pdata,l1_cUnit,dsize);
3145 SIVAL(pdata,l1_cUnitAvail,dfree);
3146 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3147 break;
3150 case SMB_INFO_VOLUME:
3151 /* Return volume name */
3153 * Add volume serial number - hash of a combination of
3154 * the called hostname and the service name.
3156 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3158 * Win2k3 and previous mess this up by sending a name length
3159 * one byte short. I believe only older clients (OS/2 Win9x) use
3160 * this call so try fixing this by adding a terminating null to
3161 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3163 len = srvstr_push(
3164 pdata, flags2,
3165 pdata+l2_vol_szVolLabel, vname,
3166 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3167 STR_NOALIGN|STR_TERMINATE);
3168 SCVAL(pdata,l2_vol_cch,len);
3169 data_len = l2_vol_szVolLabel + len;
3170 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3171 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3172 len, vname));
3173 break;
3175 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3176 case SMB_FS_ATTRIBUTE_INFORMATION:
3178 additional_flags = 0;
3179 #if defined(HAVE_SYS_QUOTAS)
3180 additional_flags |= FILE_VOLUME_QUOTAS;
3181 #endif
3183 if(lp_nt_acl_support(SNUM(conn))) {
3184 additional_flags |= FILE_PERSISTENT_ACLS;
3187 /* Capabilities are filled in at connection time through STATVFS call */
3188 additional_flags |= conn->fs_capabilities;
3189 additional_flags |= lp_parm_int(conn->params->service,
3190 "share", "fake_fscaps",
3193 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3194 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3195 additional_flags); /* FS ATTRIBUTES */
3197 SIVAL(pdata,4,255); /* Max filename component length */
3198 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3199 and will think we can't do long filenames */
3200 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3201 PTR_DIFF(end_data, pdata+12),
3202 STR_UNICODE);
3203 SIVAL(pdata,8,len);
3204 data_len = 12 + len;
3205 break;
3207 case SMB_QUERY_FS_LABEL_INFO:
3208 case SMB_FS_LABEL_INFORMATION:
3209 len = srvstr_push(pdata, flags2, pdata+4, vname,
3210 PTR_DIFF(end_data, pdata+4), 0);
3211 data_len = 4 + len;
3212 SIVAL(pdata,0,len);
3213 break;
3215 case SMB_QUERY_FS_VOLUME_INFO:
3216 case SMB_FS_VOLUME_INFORMATION:
3219 * Add volume serial number - hash of a combination of
3220 * the called hostname and the service name.
3222 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3223 (str_checksum(get_local_machine_name())<<16));
3225 /* Max label len is 32 characters. */
3226 len = srvstr_push(pdata, flags2, pdata+18, vname,
3227 PTR_DIFF(end_data, pdata+18),
3228 STR_UNICODE);
3229 SIVAL(pdata,12,len);
3230 data_len = 18+len;
3232 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3233 (int)strlen(vname),vname,
3234 lp_servicename(talloc_tos(), snum)));
3235 break;
3237 case SMB_QUERY_FS_SIZE_INFO:
3238 case SMB_FS_SIZE_INFORMATION:
3240 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3241 data_len = 24;
3242 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3243 return map_nt_error_from_unix(errno);
3245 block_size = lp_block_size(snum);
3246 if (bsize < block_size) {
3247 uint64_t factor = block_size/bsize;
3248 bsize = block_size;
3249 dsize /= factor;
3250 dfree /= factor;
3252 if (bsize > block_size) {
3253 uint64_t factor = bsize/block_size;
3254 bsize = block_size;
3255 dsize *= factor;
3256 dfree *= factor;
3258 bytes_per_sector = 512;
3259 sectors_per_unit = bsize/bytes_per_sector;
3260 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3261 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3262 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3263 SBIG_UINT(pdata,0,dsize);
3264 SBIG_UINT(pdata,8,dfree);
3265 SIVAL(pdata,16,sectors_per_unit);
3266 SIVAL(pdata,20,bytes_per_sector);
3267 break;
3270 case SMB_FS_FULL_SIZE_INFORMATION:
3272 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3273 data_len = 32;
3274 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3275 return map_nt_error_from_unix(errno);
3277 block_size = lp_block_size(snum);
3278 if (bsize < block_size) {
3279 uint64_t factor = block_size/bsize;
3280 bsize = block_size;
3281 dsize /= factor;
3282 dfree /= factor;
3284 if (bsize > block_size) {
3285 uint64_t factor = bsize/block_size;
3286 bsize = block_size;
3287 dsize *= factor;
3288 dfree *= factor;
3290 bytes_per_sector = 512;
3291 sectors_per_unit = bsize/bytes_per_sector;
3292 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3293 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3294 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3295 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3296 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3297 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3298 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3299 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3300 break;
3303 case SMB_QUERY_FS_DEVICE_INFO:
3304 case SMB_FS_DEVICE_INFORMATION:
3306 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3308 if (!CAN_WRITE(conn)) {
3309 characteristics |= FILE_READ_ONLY_DEVICE;
3311 data_len = 8;
3312 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3313 SIVAL(pdata,4,characteristics);
3314 break;
3317 #ifdef HAVE_SYS_QUOTAS
3318 case SMB_FS_QUOTA_INFORMATION:
3320 * what we have to send --metze:
3322 * Unknown1: 24 NULL bytes
3323 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3324 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3325 * Quota Flags: 2 byte :
3326 * Unknown3: 6 NULL bytes
3328 * 48 bytes total
3330 * details for Quota Flags:
3332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3335 * 0x0001 Enable Quotas: enable quota for this fs
3339 /* we need to fake up a fsp here,
3340 * because its not send in this call
3342 files_struct fsp;
3343 SMB_NTQUOTA_STRUCT quotas;
3345 ZERO_STRUCT(fsp);
3346 ZERO_STRUCT(quotas);
3348 fsp.conn = conn;
3349 fsp.fnum = FNUM_FIELD_INVALID;
3351 /* access check */
3352 if (get_current_uid(conn) != 0) {
3353 DEBUG(0,("set_user_quota: access_denied "
3354 "service [%s] user [%s]\n",
3355 lp_servicename(talloc_tos(), SNUM(conn)),
3356 conn->session_info->unix_info->unix_name));
3357 return NT_STATUS_ACCESS_DENIED;
3360 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3361 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3362 return map_nt_error_from_unix(errno);
3365 data_len = 48;
3367 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3368 lp_servicename(talloc_tos(), SNUM(conn))));
3370 /* Unknown1 24 NULL bytes*/
3371 SBIG_UINT(pdata,0,(uint64_t)0);
3372 SBIG_UINT(pdata,8,(uint64_t)0);
3373 SBIG_UINT(pdata,16,(uint64_t)0);
3375 /* Default Soft Quota 8 bytes */
3376 SBIG_UINT(pdata,24,quotas.softlim);
3378 /* Default Hard Quota 8 bytes */
3379 SBIG_UINT(pdata,32,quotas.hardlim);
3381 /* Quota flag 2 bytes */
3382 SSVAL(pdata,40,quotas.qflags);
3384 /* Unknown3 6 NULL bytes */
3385 SSVAL(pdata,42,0);
3386 SIVAL(pdata,44,0);
3388 break;
3390 #endif /* HAVE_SYS_QUOTAS */
3391 case SMB_FS_OBJECTID_INFORMATION:
3393 unsigned char objid[16];
3394 struct smb_extended_info extended_info;
3395 memcpy(pdata,create_volume_objectid(conn, objid),16);
3396 samba_extended_info_version (&extended_info);
3397 SIVAL(pdata,16,extended_info.samba_magic);
3398 SIVAL(pdata,20,extended_info.samba_version);
3399 SIVAL(pdata,24,extended_info.samba_subversion);
3400 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3401 memcpy(pdata+36,extended_info.samba_version_string,28);
3402 data_len = 64;
3403 break;
3407 * Query the version and capabilities of the CIFS UNIX extensions
3408 * in use.
3411 case SMB_QUERY_CIFS_UNIX_INFO:
3413 bool large_write = lp_min_receive_file_size() &&
3414 !srv_is_signing_active(conn->sconn);
3415 bool large_read = !srv_is_signing_active(conn->sconn);
3416 int encrypt_caps = 0;
3418 if (!lp_unix_extensions()) {
3419 return NT_STATUS_INVALID_LEVEL;
3422 switch (conn->encrypt_level) {
3423 case SMB_SIGNING_OFF:
3424 encrypt_caps = 0;
3425 break;
3426 case SMB_SIGNING_IF_REQUIRED:
3427 case SMB_SIGNING_DEFAULT:
3428 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3429 break;
3430 case SMB_SIGNING_REQUIRED:
3431 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3432 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3433 large_write = false;
3434 large_read = false;
3435 break;
3438 data_len = 12;
3439 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3440 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3442 /* We have POSIX ACLs, pathname, encryption,
3443 * large read/write, and locking capability. */
3445 SBIG_UINT(pdata,4,((uint64_t)(
3446 CIFS_UNIX_POSIX_ACLS_CAP|
3447 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3448 CIFS_UNIX_FCNTL_LOCKS_CAP|
3449 CIFS_UNIX_EXTATTR_CAP|
3450 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3451 encrypt_caps|
3452 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3453 (large_write ?
3454 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3455 break;
3458 case SMB_QUERY_POSIX_FS_INFO:
3460 int rc;
3461 vfs_statvfs_struct svfs;
3463 if (!lp_unix_extensions()) {
3464 return NT_STATUS_INVALID_LEVEL;
3467 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3469 if (!rc) {
3470 data_len = 56;
3471 SIVAL(pdata,0,svfs.OptimalTransferSize);
3472 SIVAL(pdata,4,svfs.BlockSize);
3473 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3474 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3475 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3476 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3477 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3478 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3479 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3480 #ifdef EOPNOTSUPP
3481 } else if (rc == EOPNOTSUPP) {
3482 return NT_STATUS_INVALID_LEVEL;
3483 #endif /* EOPNOTSUPP */
3484 } else {
3485 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3486 return NT_STATUS_DOS(ERRSRV, ERRerror);
3488 break;
3491 case SMB_QUERY_POSIX_WHOAMI:
3493 uint32_t flags = 0;
3494 uint32_t sid_bytes;
3495 int i;
3497 if (!lp_unix_extensions()) {
3498 return NT_STATUS_INVALID_LEVEL;
3501 if (max_data_bytes < 40) {
3502 return NT_STATUS_BUFFER_TOO_SMALL;
3505 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3506 flags |= SMB_WHOAMI_GUEST;
3509 /* NOTE: 8 bytes for UID/GID, irrespective of native
3510 * platform size. This matches
3511 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3513 data_len = 4 /* flags */
3514 + 4 /* flag mask */
3515 + 8 /* uid */
3516 + 8 /* gid */
3517 + 4 /* ngroups */
3518 + 4 /* num_sids */
3519 + 4 /* SID bytes */
3520 + 4 /* pad/reserved */
3521 + (conn->session_info->unix_token->ngroups * 8)
3522 /* groups list */
3523 + (conn->session_info->security_token->num_sids *
3524 SID_MAX_SIZE)
3525 /* SID list */;
3527 SIVAL(pdata, 0, flags);
3528 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3529 SBIG_UINT(pdata, 8,
3530 (uint64_t)conn->session_info->unix_token->uid);
3531 SBIG_UINT(pdata, 16,
3532 (uint64_t)conn->session_info->unix_token->gid);
3535 if (data_len >= max_data_bytes) {
3536 /* Potential overflow, skip the GIDs and SIDs. */
3538 SIVAL(pdata, 24, 0); /* num_groups */
3539 SIVAL(pdata, 28, 0); /* num_sids */
3540 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3541 SIVAL(pdata, 36, 0); /* reserved */
3543 data_len = 40;
3544 break;
3547 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3548 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3550 /* We walk the SID list twice, but this call is fairly
3551 * infrequent, and I don't expect that it's performance
3552 * sensitive -- jpeach
3554 for (i = 0, sid_bytes = 0;
3555 i < conn->session_info->security_token->num_sids; ++i) {
3556 sid_bytes += ndr_size_dom_sid(
3557 &conn->session_info->security_token->sids[i],
3561 /* SID list byte count */
3562 SIVAL(pdata, 32, sid_bytes);
3564 /* 4 bytes pad/reserved - must be zero */
3565 SIVAL(pdata, 36, 0);
3566 data_len = 40;
3568 /* GID list */
3569 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3570 SBIG_UINT(pdata, data_len,
3571 (uint64_t)conn->session_info->unix_token->groups[i]);
3572 data_len += 8;
3575 /* SID list */
3576 for (i = 0;
3577 i < conn->session_info->security_token->num_sids; ++i) {
3578 int sid_len = ndr_size_dom_sid(
3579 &conn->session_info->security_token->sids[i],
3582 sid_linearize(pdata + data_len, sid_len,
3583 &conn->session_info->security_token->sids[i]);
3584 data_len += sid_len;
3587 break;
3590 case SMB_MAC_QUERY_FS_INFO:
3592 * Thursby MAC extension... ONLY on NTFS filesystems
3593 * once we do streams then we don't need this
3595 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3596 data_len = 88;
3597 SIVAL(pdata,84,0x100); /* Don't support mac... */
3598 break;
3600 /* drop through */
3601 default:
3602 return NT_STATUS_INVALID_LEVEL;
3605 *ret_data_len = data_len;
3606 return status;
3609 /****************************************************************************
3610 Reply to a TRANS2_QFSINFO (query filesystem info).
3611 ****************************************************************************/
3613 static void call_trans2qfsinfo(connection_struct *conn,
3614 struct smb_request *req,
3615 char **pparams, int total_params,
3616 char **ppdata, int total_data,
3617 unsigned int max_data_bytes)
3619 char *params = *pparams;
3620 uint16_t info_level;
3621 int data_len = 0;
3622 NTSTATUS status;
3624 if (total_params < 2) {
3625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3626 return;
3629 info_level = SVAL(params,0);
3631 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3632 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3633 DEBUG(0,("call_trans2qfsinfo: encryption required "
3634 "and info level 0x%x sent.\n",
3635 (unsigned int)info_level));
3636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3637 return;
3641 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3643 status = smbd_do_qfsinfo(conn, req,
3644 info_level,
3645 req->flags2,
3646 max_data_bytes,
3647 NULL,
3648 ppdata, &data_len);
3649 if (!NT_STATUS_IS_OK(status)) {
3650 reply_nterror(req, status);
3651 return;
3654 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3655 max_data_bytes);
3657 DEBUG( 4, ( "%s info_level = %d\n",
3658 smb_fn_name(req->cmd), info_level) );
3660 return;
3663 /****************************************************************************
3664 Reply to a TRANS2_SETFSINFO (set filesystem info).
3665 ****************************************************************************/
3667 static void call_trans2setfsinfo(connection_struct *conn,
3668 struct smb_request *req,
3669 char **pparams, int total_params,
3670 char **ppdata, int total_data,
3671 unsigned int max_data_bytes)
3673 struct smbd_server_connection *sconn = req->sconn;
3674 char *pdata = *ppdata;
3675 char *params = *pparams;
3676 uint16 info_level;
3678 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3679 lp_servicename(talloc_tos(), SNUM(conn))));
3681 /* */
3682 if (total_params < 4) {
3683 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3684 total_params));
3685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3686 return;
3689 info_level = SVAL(params,2);
3691 if (IS_IPC(conn)) {
3692 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3693 info_level != SMB_SET_CIFS_UNIX_INFO) {
3694 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3695 "info level (0x%x) on IPC$.\n",
3696 (unsigned int)info_level));
3697 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3698 return;
3702 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3703 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3704 DEBUG(0,("call_trans2setfsinfo: encryption required "
3705 "and info level 0x%x sent.\n",
3706 (unsigned int)info_level));
3707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3708 return;
3712 switch(info_level) {
3713 case SMB_SET_CIFS_UNIX_INFO:
3714 if (!lp_unix_extensions()) {
3715 DEBUG(2,("call_trans2setfsinfo: "
3716 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3717 "unix extensions off\n"));
3718 reply_nterror(req,
3719 NT_STATUS_INVALID_LEVEL);
3720 return;
3723 /* There should be 12 bytes of capabilities set. */
3724 if (total_data < 12) {
3725 reply_nterror(
3726 req,
3727 NT_STATUS_INVALID_PARAMETER);
3728 return;
3730 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3731 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3732 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3733 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3734 /* Just print these values for now. */
3735 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3736 "major = %u, minor = %u cap_low = 0x%x, "
3737 "cap_high = 0x%xn",
3738 (unsigned int)sconn->
3739 smb1.unix_info.client_major,
3740 (unsigned int)sconn->
3741 smb1.unix_info.client_minor,
3742 (unsigned int)sconn->
3743 smb1.unix_info.client_cap_low,
3744 (unsigned int)sconn->
3745 smb1.unix_info.client_cap_high));
3747 /* Here is where we must switch to posix pathname processing... */
3748 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3749 lp_set_posix_pathnames();
3750 mangle_change_to_posix();
3753 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3754 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3755 /* Client that knows how to do posix locks,
3756 * but not posix open/mkdir operations. Set a
3757 * default type for read/write checks. */
3759 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3762 break;
3764 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3766 NTSTATUS status;
3767 size_t param_len = 0;
3768 size_t data_len = total_data;
3770 if (!lp_unix_extensions()) {
3771 reply_nterror(
3772 req,
3773 NT_STATUS_INVALID_LEVEL);
3774 return;
3777 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3778 reply_nterror(
3779 req,
3780 NT_STATUS_NOT_SUPPORTED);
3781 return;
3784 if (req->sconn->smb1.echo_handler.trusted_fde) {
3785 DEBUG( 2,("call_trans2setfsinfo: "
3786 "request transport encryption disabled"
3787 "with 'fork echo handler = yes'\n"));
3788 reply_nterror(
3789 req,
3790 NT_STATUS_NOT_SUPPORTED);
3791 return;
3794 DEBUG( 4,("call_trans2setfsinfo: "
3795 "request transport encryption.\n"));
3797 status = srv_request_encryption_setup(conn,
3798 (unsigned char **)ppdata,
3799 &data_len,
3800 (unsigned char **)pparams,
3801 &param_len);
3803 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3804 !NT_STATUS_IS_OK(status)) {
3805 reply_nterror(req, status);
3806 return;
3809 send_trans2_replies(conn, req,
3810 NT_STATUS_OK,
3811 *pparams,
3812 param_len,
3813 *ppdata,
3814 data_len,
3815 max_data_bytes);
3817 if (NT_STATUS_IS_OK(status)) {
3818 /* Server-side transport
3819 * encryption is now *on*. */
3820 status = srv_encryption_start(conn);
3821 if (!NT_STATUS_IS_OK(status)) {
3822 char *reason = talloc_asprintf(talloc_tos(),
3823 "Failure in setting "
3824 "up encrypted transport: %s",
3825 nt_errstr(status));
3826 exit_server_cleanly(reason);
3829 return;
3832 case SMB_FS_QUOTA_INFORMATION:
3834 files_struct *fsp = NULL;
3835 SMB_NTQUOTA_STRUCT quotas;
3837 ZERO_STRUCT(quotas);
3839 /* access check */
3840 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3841 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3842 lp_servicename(talloc_tos(), SNUM(conn)),
3843 conn->session_info->unix_info->unix_name));
3844 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3845 return;
3848 /* note: normaly there're 48 bytes,
3849 * but we didn't use the last 6 bytes for now
3850 * --metze
3852 fsp = file_fsp(req, SVAL(params,0));
3854 if (!check_fsp_ntquota_handle(conn, req,
3855 fsp)) {
3856 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3857 reply_nterror(
3858 req, NT_STATUS_INVALID_HANDLE);
3859 return;
3862 if (total_data < 42) {
3863 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3864 total_data));
3865 reply_nterror(
3866 req,
3867 NT_STATUS_INVALID_PARAMETER);
3868 return;
3871 /* unknown_1 24 NULL bytes in pdata*/
3873 /* the soft quotas 8 bytes (uint64_t)*/
3874 quotas.softlim = BVAL(pdata,24);
3876 /* the hard quotas 8 bytes (uint64_t)*/
3877 quotas.hardlim = BVAL(pdata,32);
3879 /* quota_flags 2 bytes **/
3880 quotas.qflags = SVAL(pdata,40);
3882 /* unknown_2 6 NULL bytes follow*/
3884 /* now set the quotas */
3885 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3886 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3887 reply_nterror(req, map_nt_error_from_unix(errno));
3888 return;
3891 break;
3893 default:
3894 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3895 info_level));
3896 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3897 return;
3898 break;
3902 * sending this reply works fine,
3903 * but I'm not sure it's the same
3904 * like windows do...
3905 * --metze
3907 reply_outbuf(req, 10, 0);
3910 #if defined(HAVE_POSIX_ACLS)
3911 /****************************************************************************
3912 Utility function to count the number of entries in a POSIX acl.
3913 ****************************************************************************/
3915 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3917 unsigned int ace_count = 0;
3918 int entry_id = SMB_ACL_FIRST_ENTRY;
3919 SMB_ACL_ENTRY_T entry;
3921 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3922 /* get_next... */
3923 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3924 entry_id = SMB_ACL_NEXT_ENTRY;
3926 ace_count++;
3928 return ace_count;
3931 /****************************************************************************
3932 Utility function to marshall a POSIX acl into wire format.
3933 ****************************************************************************/
3935 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3937 int entry_id = SMB_ACL_FIRST_ENTRY;
3938 SMB_ACL_ENTRY_T entry;
3940 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3941 SMB_ACL_TAG_T tagtype;
3942 SMB_ACL_PERMSET_T permset;
3943 unsigned char perms = 0;
3944 unsigned int own_grp;
3946 /* get_next... */
3947 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3948 entry_id = SMB_ACL_NEXT_ENTRY;
3951 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3952 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3953 return False;
3956 if (sys_acl_get_permset(entry, &permset) == -1) {
3957 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3958 return False;
3961 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3962 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3963 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3965 SCVAL(pdata,1,perms);
3967 switch (tagtype) {
3968 case SMB_ACL_USER_OBJ:
3969 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3970 own_grp = (unsigned int)pst->st_ex_uid;
3971 SIVAL(pdata,2,own_grp);
3972 SIVAL(pdata,6,0);
3973 break;
3974 case SMB_ACL_USER:
3976 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3977 if (!puid) {
3978 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3979 return False;
3981 own_grp = (unsigned int)*puid;
3982 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3983 SIVAL(pdata,2,own_grp);
3984 SIVAL(pdata,6,0);
3985 break;
3987 case SMB_ACL_GROUP_OBJ:
3988 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3989 own_grp = (unsigned int)pst->st_ex_gid;
3990 SIVAL(pdata,2,own_grp);
3991 SIVAL(pdata,6,0);
3992 break;
3993 case SMB_ACL_GROUP:
3995 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3996 if (!pgid) {
3997 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3998 return False;
4000 own_grp = (unsigned int)*pgid;
4001 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4002 SIVAL(pdata,2,own_grp);
4003 SIVAL(pdata,6,0);
4004 break;
4006 case SMB_ACL_MASK:
4007 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4008 SIVAL(pdata,2,0xFFFFFFFF);
4009 SIVAL(pdata,6,0xFFFFFFFF);
4010 break;
4011 case SMB_ACL_OTHER:
4012 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4013 SIVAL(pdata,2,0xFFFFFFFF);
4014 SIVAL(pdata,6,0xFFFFFFFF);
4015 break;
4016 default:
4017 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4018 return False;
4020 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4023 return True;
4025 #endif
4027 /****************************************************************************
4028 Store the FILE_UNIX_BASIC info.
4029 ****************************************************************************/
4031 static char *store_file_unix_basic(connection_struct *conn,
4032 char *pdata,
4033 files_struct *fsp,
4034 const SMB_STRUCT_STAT *psbuf)
4036 uint64_t file_index = get_FileIndex(conn, psbuf);
4037 dev_t devno;
4039 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4040 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4042 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4043 pdata += 8;
4045 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4046 pdata += 8;
4048 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4050 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4051 pdata += 24;
4053 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4054 SIVAL(pdata,4,0);
4055 pdata += 8;
4057 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4058 SIVAL(pdata,4,0);
4059 pdata += 8;
4061 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4062 pdata += 4;
4064 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4065 devno = psbuf->st_ex_rdev;
4066 } else {
4067 devno = psbuf->st_ex_dev;
4070 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4071 SIVAL(pdata,4,0);
4072 pdata += 8;
4074 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4075 SIVAL(pdata,4,0);
4076 pdata += 8;
4078 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4079 pdata += 8;
4081 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4082 SIVAL(pdata,4,0);
4083 pdata += 8;
4085 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4086 SIVAL(pdata,4,0);
4087 pdata += 8;
4089 return pdata;
4092 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4093 * the chflags(2) (or equivalent) flags.
4095 * XXX: this really should be behind the VFS interface. To do this, we would
4096 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4097 * Each VFS module could then implement its own mapping as appropriate for the
4098 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4100 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4101 info2_flags_map[] =
4103 #ifdef UF_NODUMP
4104 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4105 #endif
4107 #ifdef UF_IMMUTABLE
4108 { UF_IMMUTABLE, EXT_IMMUTABLE },
4109 #endif
4111 #ifdef UF_APPEND
4112 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4113 #endif
4115 #ifdef UF_HIDDEN
4116 { UF_HIDDEN, EXT_HIDDEN },
4117 #endif
4119 /* Do not remove. We need to guarantee that this array has at least one
4120 * entry to build on HP-UX.
4122 { 0, 0 }
4126 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4127 uint32 *smb_fflags, uint32 *smb_fmask)
4129 int i;
4131 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4132 *smb_fmask |= info2_flags_map[i].smb_fflag;
4133 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4134 *smb_fflags |= info2_flags_map[i].smb_fflag;
4139 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4140 const uint32 smb_fflags,
4141 const uint32 smb_fmask,
4142 int *stat_fflags)
4144 uint32 max_fmask = 0;
4145 int i;
4147 *stat_fflags = psbuf->st_ex_flags;
4149 /* For each flags requested in smb_fmask, check the state of the
4150 * corresponding flag in smb_fflags and set or clear the matching
4151 * stat flag.
4154 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4155 max_fmask |= info2_flags_map[i].smb_fflag;
4156 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4157 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4158 *stat_fflags |= info2_flags_map[i].stat_fflag;
4159 } else {
4160 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4165 /* If smb_fmask is asking to set any bits that are not supported by
4166 * our flag mappings, we should fail.
4168 if ((smb_fmask & max_fmask) != smb_fmask) {
4169 return False;
4172 return True;
4176 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4177 * of file flags and birth (create) time.
4179 static char *store_file_unix_basic_info2(connection_struct *conn,
4180 char *pdata,
4181 files_struct *fsp,
4182 const SMB_STRUCT_STAT *psbuf)
4184 uint32 file_flags = 0;
4185 uint32 flags_mask = 0;
4187 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4189 /* Create (birth) time 64 bit */
4190 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4191 pdata += 8;
4193 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4194 SIVAL(pdata, 0, file_flags); /* flags */
4195 SIVAL(pdata, 4, flags_mask); /* mask */
4196 pdata += 8;
4198 return pdata;
4201 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4202 const struct stream_struct *streams,
4203 char *data,
4204 unsigned int max_data_bytes,
4205 unsigned int *data_size)
4207 unsigned int i;
4208 unsigned int ofs = 0;
4210 for (i = 0; i < num_streams; i++) {
4211 unsigned int next_offset;
4212 size_t namelen;
4213 smb_ucs2_t *namebuf;
4215 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4216 streams[i].name, &namelen) ||
4217 namelen <= 2)
4219 return NT_STATUS_INVALID_PARAMETER;
4223 * name_buf is now null-terminated, we need to marshall as not
4224 * terminated
4227 namelen -= 2;
4230 * We cannot overflow ...
4232 if ((ofs + 24 + namelen) > max_data_bytes) {
4233 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4234 i));
4235 TALLOC_FREE(namebuf);
4236 return STATUS_BUFFER_OVERFLOW;
4239 SIVAL(data, ofs+4, namelen);
4240 SOFF_T(data, ofs+8, streams[i].size);
4241 SOFF_T(data, ofs+16, streams[i].alloc_size);
4242 memcpy(data+ofs+24, namebuf, namelen);
4243 TALLOC_FREE(namebuf);
4245 next_offset = ofs + 24 + namelen;
4247 if (i == num_streams-1) {
4248 SIVAL(data, ofs, 0);
4250 else {
4251 unsigned int align = ndr_align_size(next_offset, 8);
4253 if ((next_offset + align) > max_data_bytes) {
4254 DEBUG(10, ("refusing to overflow align "
4255 "reply at stream %u\n",
4256 i));
4257 TALLOC_FREE(namebuf);
4258 return STATUS_BUFFER_OVERFLOW;
4261 memset(data+next_offset, 0, align);
4262 next_offset += align;
4264 SIVAL(data, ofs, next_offset - ofs);
4265 ofs = next_offset;
4268 ofs = next_offset;
4271 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4273 *data_size = ofs;
4275 return NT_STATUS_OK;
4278 /****************************************************************************
4279 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4280 ****************************************************************************/
4282 static void call_trans2qpipeinfo(connection_struct *conn,
4283 struct smb_request *req,
4284 unsigned int tran_call,
4285 char **pparams, int total_params,
4286 char **ppdata, int total_data,
4287 unsigned int max_data_bytes)
4289 char *params = *pparams;
4290 char *pdata = *ppdata;
4291 unsigned int data_size = 0;
4292 unsigned int param_size = 2;
4293 uint16 info_level;
4294 files_struct *fsp;
4296 if (!params) {
4297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4298 return;
4301 if (total_params < 4) {
4302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4303 return;
4306 fsp = file_fsp(req, SVAL(params,0));
4307 if (!fsp_is_np(fsp)) {
4308 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4309 return;
4312 info_level = SVAL(params,2);
4314 *pparams = (char *)SMB_REALLOC(*pparams,2);
4315 if (*pparams == NULL) {
4316 reply_nterror(req, NT_STATUS_NO_MEMORY);
4317 return;
4319 params = *pparams;
4320 SSVAL(params,0,0);
4321 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4322 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4323 if (*ppdata == NULL ) {
4324 reply_nterror(req, NT_STATUS_NO_MEMORY);
4325 return;
4327 pdata = *ppdata;
4329 switch (info_level) {
4330 case SMB_FILE_STANDARD_INFORMATION:
4331 memset(pdata,0,24);
4332 SOFF_T(pdata,0,4096LL);
4333 SIVAL(pdata,16,1);
4334 SIVAL(pdata,20,1);
4335 data_size = 24;
4336 break;
4338 default:
4339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4340 return;
4343 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4344 max_data_bytes);
4346 return;
4349 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4350 TALLOC_CTX *mem_ctx,
4351 uint16_t info_level,
4352 files_struct *fsp,
4353 struct smb_filename *smb_fname,
4354 bool delete_pending,
4355 struct timespec write_time_ts,
4356 struct ea_list *ea_list,
4357 int lock_data_count,
4358 char *lock_data,
4359 uint16_t flags2,
4360 unsigned int max_data_bytes,
4361 char **ppdata,
4362 unsigned int *pdata_size)
4364 char *pdata = *ppdata;
4365 char *dstart, *dend;
4366 unsigned int data_size;
4367 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4368 time_t create_time, mtime, atime, c_time;
4369 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4370 char *p;
4371 char *base_name;
4372 char *dos_fname;
4373 int mode;
4374 int nlink;
4375 NTSTATUS status;
4376 uint64_t file_size = 0;
4377 uint64_t pos = 0;
4378 uint64_t allocation_size = 0;
4379 uint64_t file_index = 0;
4380 uint32_t access_mask = 0;
4382 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4383 return NT_STATUS_INVALID_LEVEL;
4386 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4387 smb_fname_str_dbg(smb_fname),
4388 fsp_fnum_dbg(fsp),
4389 info_level, max_data_bytes));
4391 mode = dos_mode(conn, smb_fname);
4392 nlink = psbuf->st_ex_nlink;
4394 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4395 nlink = 1;
4398 if ((nlink > 0) && delete_pending) {
4399 nlink -= 1;
4402 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4403 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4404 if (*ppdata == NULL) {
4405 return NT_STATUS_NO_MEMORY;
4407 pdata = *ppdata;
4408 dstart = pdata;
4409 dend = dstart + data_size - 1;
4411 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4412 update_stat_ex_mtime(psbuf, write_time_ts);
4415 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4416 mtime_ts = psbuf->st_ex_mtime;
4417 atime_ts = psbuf->st_ex_atime;
4418 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4420 if (lp_dos_filetime_resolution(SNUM(conn))) {
4421 dos_filetime_timespec(&create_time_ts);
4422 dos_filetime_timespec(&mtime_ts);
4423 dos_filetime_timespec(&atime_ts);
4424 dos_filetime_timespec(&ctime_ts);
4427 create_time = convert_timespec_to_time_t(create_time_ts);
4428 mtime = convert_timespec_to_time_t(mtime_ts);
4429 atime = convert_timespec_to_time_t(atime_ts);
4430 c_time = convert_timespec_to_time_t(ctime_ts);
4432 p = strrchr_m(smb_fname->base_name,'/');
4433 if (!p)
4434 base_name = smb_fname->base_name;
4435 else
4436 base_name = p+1;
4438 /* NT expects the name to be in an exact form of the *full*
4439 filename. See the trans2 torture test */
4440 if (ISDOT(base_name)) {
4441 dos_fname = talloc_strdup(mem_ctx, "\\");
4442 if (!dos_fname) {
4443 return NT_STATUS_NO_MEMORY;
4445 } else {
4446 dos_fname = talloc_asprintf(mem_ctx,
4447 "\\%s",
4448 smb_fname->base_name);
4449 if (!dos_fname) {
4450 return NT_STATUS_NO_MEMORY;
4452 if (is_ntfs_stream_smb_fname(smb_fname)) {
4453 dos_fname = talloc_asprintf(dos_fname, "%s",
4454 smb_fname->stream_name);
4455 if (!dos_fname) {
4456 return NT_STATUS_NO_MEMORY;
4460 string_replace(dos_fname, '/', '\\');
4463 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4465 if (!fsp) {
4466 /* Do we have this path open ? */
4467 files_struct *fsp1;
4468 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4469 fsp1 = file_find_di_first(conn->sconn, fileid);
4470 if (fsp1 && fsp1->initial_allocation_size) {
4471 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4475 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4476 file_size = get_file_size_stat(psbuf);
4479 if (fsp) {
4480 pos = fsp->fh->position_information;
4483 if (fsp) {
4484 access_mask = fsp->access_mask;
4485 } else {
4486 /* GENERIC_EXECUTE mapping from Windows */
4487 access_mask = 0x12019F;
4490 /* This should be an index number - looks like
4491 dev/ino to me :-)
4493 I think this causes us to fail the IFSKIT
4494 BasicFileInformationTest. -tpot */
4495 file_index = get_FileIndex(conn, psbuf);
4497 switch (info_level) {
4498 case SMB_INFO_STANDARD:
4499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4500 data_size = 22;
4501 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4502 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4503 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4504 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4505 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4506 SSVAL(pdata,l1_attrFile,mode);
4507 break;
4509 case SMB_INFO_QUERY_EA_SIZE:
4511 unsigned int ea_size =
4512 estimate_ea_size(conn, fsp,
4513 smb_fname);
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4515 data_size = 26;
4516 srv_put_dos_date2(pdata,0,create_time);
4517 srv_put_dos_date2(pdata,4,atime);
4518 srv_put_dos_date2(pdata,8,mtime); /* write time */
4519 SIVAL(pdata,12,(uint32)file_size);
4520 SIVAL(pdata,16,(uint32)allocation_size);
4521 SSVAL(pdata,20,mode);
4522 SIVAL(pdata,22,ea_size);
4523 break;
4526 case SMB_INFO_IS_NAME_VALID:
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4528 if (fsp) {
4529 /* os/2 needs this ? really ?*/
4530 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4532 /* This is only reached for qpathinfo */
4533 data_size = 0;
4534 break;
4536 case SMB_INFO_QUERY_EAS_FROM_LIST:
4538 size_t total_ea_len = 0;
4539 struct ea_list *ea_file_list = NULL;
4540 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4542 status =
4543 get_ea_list_from_file(mem_ctx, conn, fsp,
4544 smb_fname,
4545 &total_ea_len, &ea_file_list);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 return status;
4550 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4552 if (!ea_list || (total_ea_len > data_size)) {
4553 data_size = 4;
4554 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4555 break;
4558 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4559 break;
4562 case SMB_INFO_QUERY_ALL_EAS:
4564 /* We have data_size bytes to put EA's into. */
4565 size_t total_ea_len = 0;
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4568 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4569 smb_fname,
4570 &total_ea_len, &ea_list);
4571 if (!NT_STATUS_IS_OK(status)) {
4572 return status;
4575 if (!ea_list || (total_ea_len > data_size)) {
4576 data_size = 4;
4577 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4578 break;
4581 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4582 break;
4585 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4587 /* This is FileFullEaInformation - 0xF which maps to
4588 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4590 /* We have data_size bytes to put EA's into. */
4591 size_t total_ea_len = 0;
4592 struct ea_list *ea_file_list = NULL;
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4596 /*TODO: add filtering and index handling */
4598 status =
4599 get_ea_list_from_file(mem_ctx, conn, fsp,
4600 smb_fname,
4601 &total_ea_len, &ea_file_list);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 return status;
4605 if (!ea_file_list) {
4606 return NT_STATUS_NO_EAS_ON_FILE;
4609 status = fill_ea_chained_buffer(mem_ctx,
4610 pdata,
4611 data_size,
4612 &data_size,
4613 conn, ea_file_list);
4614 if (!NT_STATUS_IS_OK(status)) {
4615 return status;
4617 break;
4620 case SMB_FILE_BASIC_INFORMATION:
4621 case SMB_QUERY_FILE_BASIC_INFO:
4623 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4625 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4626 } else {
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4628 data_size = 40;
4629 SIVAL(pdata,36,0);
4631 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4632 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4633 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4634 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4635 SIVAL(pdata,32,mode);
4637 DEBUG(5,("SMB_QFBI - "));
4638 DEBUG(5,("create: %s ", ctime(&create_time)));
4639 DEBUG(5,("access: %s ", ctime(&atime)));
4640 DEBUG(5,("write: %s ", ctime(&mtime)));
4641 DEBUG(5,("change: %s ", ctime(&c_time)));
4642 DEBUG(5,("mode: %x\n", mode));
4643 break;
4645 case SMB_FILE_STANDARD_INFORMATION:
4646 case SMB_QUERY_FILE_STANDARD_INFO:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4649 data_size = 24;
4650 SOFF_T(pdata,0,allocation_size);
4651 SOFF_T(pdata,8,file_size);
4652 SIVAL(pdata,16,nlink);
4653 SCVAL(pdata,20,delete_pending?1:0);
4654 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4655 SSVAL(pdata,22,0); /* Padding. */
4656 break;
4658 case SMB_FILE_EA_INFORMATION:
4659 case SMB_QUERY_FILE_EA_INFO:
4661 unsigned int ea_size =
4662 estimate_ea_size(conn, fsp, smb_fname);
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4664 data_size = 4;
4665 SIVAL(pdata,0,ea_size);
4666 break;
4669 /* Get the 8.3 name - used if NT SMB was negotiated. */
4670 case SMB_QUERY_FILE_ALT_NAME_INFO:
4671 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4673 int len;
4674 char mangled_name[13];
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4676 if (!name_to_8_3(base_name,mangled_name,
4677 True,conn->params)) {
4678 return NT_STATUS_NO_MEMORY;
4680 len = srvstr_push(dstart, flags2,
4681 pdata+4, mangled_name,
4682 PTR_DIFF(dend, pdata+4),
4683 STR_UNICODE);
4684 data_size = 4 + len;
4685 SIVAL(pdata,0,len);
4686 break;
4689 case SMB_QUERY_FILE_NAME_INFO:
4691 int len;
4693 this must be *exactly* right for ACLs on mapped drives to work
4695 len = srvstr_push(dstart, flags2,
4696 pdata+4, dos_fname,
4697 PTR_DIFF(dend, pdata+4),
4698 STR_UNICODE);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4700 data_size = 4 + len;
4701 SIVAL(pdata,0,len);
4702 break;
4705 case SMB_FILE_ALLOCATION_INFORMATION:
4706 case SMB_QUERY_FILE_ALLOCATION_INFO:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4708 data_size = 8;
4709 SOFF_T(pdata,0,allocation_size);
4710 break;
4712 case SMB_FILE_END_OF_FILE_INFORMATION:
4713 case SMB_QUERY_FILE_END_OF_FILEINFO:
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4715 data_size = 8;
4716 SOFF_T(pdata,0,file_size);
4717 break;
4719 case SMB_QUERY_FILE_ALL_INFO:
4720 case SMB_FILE_ALL_INFORMATION:
4722 int len;
4723 unsigned int ea_size =
4724 estimate_ea_size(conn, fsp, smb_fname);
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4726 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4727 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4728 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4729 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4730 SIVAL(pdata,32,mode);
4731 SIVAL(pdata,36,0); /* padding. */
4732 pdata += 40;
4733 SOFF_T(pdata,0,allocation_size);
4734 SOFF_T(pdata,8,file_size);
4735 SIVAL(pdata,16,nlink);
4736 SCVAL(pdata,20,delete_pending);
4737 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4738 SSVAL(pdata,22,0);
4739 pdata += 24;
4740 SIVAL(pdata,0,ea_size);
4741 pdata += 4; /* EA info */
4742 len = srvstr_push(dstart, flags2,
4743 pdata+4, dos_fname,
4744 PTR_DIFF(dend, pdata+4),
4745 STR_UNICODE);
4746 SIVAL(pdata,0,len);
4747 pdata += 4 + len;
4748 data_size = PTR_DIFF(pdata,(*ppdata));
4749 break;
4752 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4754 int len;
4755 unsigned int ea_size =
4756 estimate_ea_size(conn, fsp, smb_fname);
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4758 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4759 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4760 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4761 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4762 SIVAL(pdata, 0x20, mode);
4763 SIVAL(pdata, 0x24, 0); /* padding. */
4764 SBVAL(pdata, 0x28, allocation_size);
4765 SBVAL(pdata, 0x30, file_size);
4766 SIVAL(pdata, 0x38, nlink);
4767 SCVAL(pdata, 0x3C, delete_pending);
4768 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4769 SSVAL(pdata, 0x3E, 0); /* padding */
4770 SBVAL(pdata, 0x40, file_index);
4771 SIVAL(pdata, 0x48, ea_size);
4772 SIVAL(pdata, 0x4C, access_mask);
4773 SBVAL(pdata, 0x50, pos);
4774 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4775 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4777 pdata += 0x60;
4779 len = srvstr_push(dstart, flags2,
4780 pdata+4, dos_fname,
4781 PTR_DIFF(dend, pdata+4),
4782 STR_UNICODE);
4783 SIVAL(pdata,0,len);
4784 pdata += 4 + len;
4785 data_size = PTR_DIFF(pdata,(*ppdata));
4786 break;
4788 case SMB_FILE_INTERNAL_INFORMATION:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4791 SBVAL(pdata, 0, file_index);
4792 data_size = 8;
4793 break;
4795 case SMB_FILE_ACCESS_INFORMATION:
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4797 SIVAL(pdata, 0, access_mask);
4798 data_size = 4;
4799 break;
4801 case SMB_FILE_NAME_INFORMATION:
4802 /* Pathname with leading '\'. */
4804 size_t byte_len;
4805 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4806 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4807 SIVAL(pdata,0,byte_len);
4808 data_size = 4 + byte_len;
4809 break;
4812 case SMB_FILE_DISPOSITION_INFORMATION:
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4814 data_size = 1;
4815 SCVAL(pdata,0,delete_pending);
4816 break;
4818 case SMB_FILE_POSITION_INFORMATION:
4819 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4820 data_size = 8;
4821 SOFF_T(pdata,0,pos);
4822 break;
4824 case SMB_FILE_MODE_INFORMATION:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4826 SIVAL(pdata,0,mode);
4827 data_size = 4;
4828 break;
4830 case SMB_FILE_ALIGNMENT_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4832 SIVAL(pdata,0,0); /* No alignment needed. */
4833 data_size = 4;
4834 break;
4837 * NT4 server just returns "invalid query" to this - if we try
4838 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4839 * want this. JRA.
4841 /* The first statement above is false - verified using Thursby
4842 * client against NT4 -- gcolley.
4844 case SMB_QUERY_FILE_STREAM_INFO:
4845 case SMB_FILE_STREAM_INFORMATION: {
4846 unsigned int num_streams = 0;
4847 struct stream_struct *streams = NULL;
4849 DEBUG(10,("smbd_do_qfilepathinfo: "
4850 "SMB_FILE_STREAM_INFORMATION\n"));
4852 if (is_ntfs_stream_smb_fname(smb_fname)) {
4853 return NT_STATUS_INVALID_PARAMETER;
4856 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4857 talloc_tos(), &num_streams, &streams);
4859 if (!NT_STATUS_IS_OK(status)) {
4860 DEBUG(10, ("could not get stream info: %s\n",
4861 nt_errstr(status)));
4862 return status;
4865 status = marshall_stream_info(num_streams, streams,
4866 pdata, max_data_bytes,
4867 &data_size);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 DEBUG(10, ("marshall_stream_info failed: %s\n",
4871 nt_errstr(status)));
4872 TALLOC_FREE(streams);
4873 return status;
4876 TALLOC_FREE(streams);
4878 break;
4880 case SMB_QUERY_COMPRESSION_INFO:
4881 case SMB_FILE_COMPRESSION_INFORMATION:
4882 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4883 SOFF_T(pdata,0,file_size);
4884 SIVAL(pdata,8,0); /* ??? */
4885 SIVAL(pdata,12,0); /* ??? */
4886 data_size = 16;
4887 break;
4889 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4891 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4892 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4893 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4894 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4895 SOFF_T(pdata,32,allocation_size);
4896 SOFF_T(pdata,40,file_size);
4897 SIVAL(pdata,48,mode);
4898 SIVAL(pdata,52,0); /* ??? */
4899 data_size = 56;
4900 break;
4902 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4903 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4904 SIVAL(pdata,0,mode);
4905 SIVAL(pdata,4,0);
4906 data_size = 8;
4907 break;
4910 * CIFS UNIX Extensions.
4913 case SMB_QUERY_FILE_UNIX_BASIC:
4915 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4916 data_size = PTR_DIFF(pdata,(*ppdata));
4918 DEBUG(4,("smbd_do_qfilepathinfo: "
4919 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4920 dump_data(4, (uint8_t *)(*ppdata), data_size);
4922 break;
4924 case SMB_QUERY_FILE_UNIX_INFO2:
4926 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4927 data_size = PTR_DIFF(pdata,(*ppdata));
4930 int i;
4931 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4933 for (i=0; i<100; i++)
4934 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4935 DEBUG(4,("\n"));
4938 break;
4940 case SMB_QUERY_FILE_UNIX_LINK:
4942 int len;
4943 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4945 if (!buffer) {
4946 return NT_STATUS_NO_MEMORY;
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4950 #ifdef S_ISLNK
4951 if(!S_ISLNK(psbuf->st_ex_mode)) {
4952 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4954 #else
4955 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4956 #endif
4957 len = SMB_VFS_READLINK(conn,
4958 smb_fname->base_name,
4959 buffer, PATH_MAX);
4960 if (len == -1) {
4961 return map_nt_error_from_unix(errno);
4963 buffer[len] = 0;
4964 len = srvstr_push(dstart, flags2,
4965 pdata, buffer,
4966 PTR_DIFF(dend, pdata),
4967 STR_TERMINATE);
4968 pdata += len;
4969 data_size = PTR_DIFF(pdata,(*ppdata));
4971 break;
4974 #if defined(HAVE_POSIX_ACLS)
4975 case SMB_QUERY_POSIX_ACL:
4977 SMB_ACL_T file_acl = NULL;
4978 SMB_ACL_T def_acl = NULL;
4979 uint16 num_file_acls = 0;
4980 uint16 num_def_acls = 0;
4982 if (fsp && fsp->fh->fd != -1) {
4983 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4984 talloc_tos());
4985 } else {
4986 file_acl =
4987 SMB_VFS_SYS_ACL_GET_FILE(conn,
4988 smb_fname->base_name,
4989 SMB_ACL_TYPE_ACCESS,
4990 talloc_tos());
4993 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4994 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4995 "not implemented on "
4996 "filesystem containing %s\n",
4997 smb_fname->base_name));
4998 return NT_STATUS_NOT_IMPLEMENTED;
5001 if (S_ISDIR(psbuf->st_ex_mode)) {
5002 if (fsp && fsp->is_directory) {
5003 def_acl =
5004 SMB_VFS_SYS_ACL_GET_FILE(
5005 conn,
5006 fsp->fsp_name->base_name,
5007 SMB_ACL_TYPE_DEFAULT,
5008 talloc_tos());
5009 } else {
5010 def_acl =
5011 SMB_VFS_SYS_ACL_GET_FILE(
5012 conn,
5013 smb_fname->base_name,
5014 SMB_ACL_TYPE_DEFAULT,
5015 talloc_tos());
5017 def_acl = free_empty_sys_acl(conn, def_acl);
5020 num_file_acls = count_acl_entries(conn, file_acl);
5021 num_def_acls = count_acl_entries(conn, def_acl);
5023 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5024 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5025 data_size,
5026 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5027 SMB_POSIX_ACL_HEADER_SIZE) ));
5028 if (file_acl) {
5029 TALLOC_FREE(file_acl);
5031 if (def_acl) {
5032 TALLOC_FREE(def_acl);
5034 return NT_STATUS_BUFFER_TOO_SMALL;
5037 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5038 SSVAL(pdata,2,num_file_acls);
5039 SSVAL(pdata,4,num_def_acls);
5040 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5041 if (file_acl) {
5042 TALLOC_FREE(file_acl);
5044 if (def_acl) {
5045 TALLOC_FREE(def_acl);
5047 return NT_STATUS_INTERNAL_ERROR;
5049 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5050 if (file_acl) {
5051 TALLOC_FREE(file_acl);
5053 if (def_acl) {
5054 TALLOC_FREE(def_acl);
5056 return NT_STATUS_INTERNAL_ERROR;
5059 if (file_acl) {
5060 TALLOC_FREE(file_acl);
5062 if (def_acl) {
5063 TALLOC_FREE(def_acl);
5065 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5066 break;
5068 #endif
5071 case SMB_QUERY_POSIX_LOCK:
5073 uint64_t count;
5074 uint64_t offset;
5075 uint64_t smblctx;
5076 enum brl_type lock_type;
5078 /* We need an open file with a real fd for this. */
5079 if (!fsp || fsp->fh->fd == -1) {
5080 return NT_STATUS_INVALID_LEVEL;
5083 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5084 return NT_STATUS_INVALID_PARAMETER;
5087 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5088 case POSIX_LOCK_TYPE_READ:
5089 lock_type = READ_LOCK;
5090 break;
5091 case POSIX_LOCK_TYPE_WRITE:
5092 lock_type = WRITE_LOCK;
5093 break;
5094 case POSIX_LOCK_TYPE_UNLOCK:
5095 default:
5096 /* There's no point in asking for an unlock... */
5097 return NT_STATUS_INVALID_PARAMETER;
5100 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5101 #if defined(HAVE_LONGLONG)
5102 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5103 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5104 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5105 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5106 #else /* HAVE_LONGLONG */
5107 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5108 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5109 #endif /* HAVE_LONGLONG */
5111 status = query_lock(fsp,
5112 &smblctx,
5113 &count,
5114 &offset,
5115 &lock_type,
5116 POSIX_LOCK);
5118 if (ERROR_WAS_LOCK_DENIED(status)) {
5119 /* Here we need to report who has it locked... */
5120 data_size = POSIX_LOCK_DATA_SIZE;
5122 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5123 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5124 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5125 #if defined(HAVE_LONGLONG)
5126 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5127 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5128 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5129 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5130 #else /* HAVE_LONGLONG */
5131 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5132 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5133 #endif /* HAVE_LONGLONG */
5135 } else if (NT_STATUS_IS_OK(status)) {
5136 /* For success we just return a copy of what we sent
5137 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5138 data_size = POSIX_LOCK_DATA_SIZE;
5139 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5140 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5141 } else {
5142 return status;
5144 break;
5147 default:
5148 return NT_STATUS_INVALID_LEVEL;
5151 *pdata_size = data_size;
5152 return NT_STATUS_OK;
5155 /****************************************************************************
5156 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5157 file name or file id).
5158 ****************************************************************************/
5160 static void call_trans2qfilepathinfo(connection_struct *conn,
5161 struct smb_request *req,
5162 unsigned int tran_call,
5163 char **pparams, int total_params,
5164 char **ppdata, int total_data,
5165 unsigned int max_data_bytes)
5167 char *params = *pparams;
5168 char *pdata = *ppdata;
5169 uint16 info_level;
5170 unsigned int data_size = 0;
5171 unsigned int param_size = 2;
5172 struct smb_filename *smb_fname = NULL;
5173 bool delete_pending = False;
5174 struct timespec write_time_ts;
5175 files_struct *fsp = NULL;
5176 struct file_id fileid;
5177 struct ea_list *ea_list = NULL;
5178 int lock_data_count = 0;
5179 char *lock_data = NULL;
5180 NTSTATUS status = NT_STATUS_OK;
5182 if (!params) {
5183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5184 return;
5187 ZERO_STRUCT(write_time_ts);
5189 if (tran_call == TRANSACT2_QFILEINFO) {
5190 if (total_params < 4) {
5191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5192 return;
5195 if (IS_IPC(conn)) {
5196 call_trans2qpipeinfo(conn, req, tran_call,
5197 pparams, total_params,
5198 ppdata, total_data,
5199 max_data_bytes);
5200 return;
5203 fsp = file_fsp(req, SVAL(params,0));
5204 info_level = SVAL(params,2);
5206 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5208 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5209 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5210 return;
5213 /* Initial check for valid fsp ptr. */
5214 if (!check_fsp_open(conn, req, fsp)) {
5215 return;
5218 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5219 if (smb_fname == NULL) {
5220 reply_nterror(req, NT_STATUS_NO_MEMORY);
5221 return;
5224 if(fsp->fake_file_handle) {
5226 * This is actually for the QUOTA_FAKE_FILE --metze
5229 /* We know this name is ok, it's already passed the checks. */
5231 } else if(fsp->fh->fd == -1) {
5233 * This is actually a QFILEINFO on a directory
5234 * handle (returned from an NT SMB). NT5.0 seems
5235 * to do this call. JRA.
5238 if (INFO_LEVEL_IS_UNIX(info_level)) {
5239 /* Always do lstat for UNIX calls. */
5240 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5241 DEBUG(3,("call_trans2qfilepathinfo: "
5242 "SMB_VFS_LSTAT of %s failed "
5243 "(%s)\n",
5244 smb_fname_str_dbg(smb_fname),
5245 strerror(errno)));
5246 reply_nterror(req,
5247 map_nt_error_from_unix(errno));
5248 return;
5250 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5251 DEBUG(3,("call_trans2qfilepathinfo: "
5252 "SMB_VFS_STAT of %s failed (%s)\n",
5253 smb_fname_str_dbg(smb_fname),
5254 strerror(errno)));
5255 reply_nterror(req,
5256 map_nt_error_from_unix(errno));
5257 return;
5260 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5261 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5262 } else {
5264 * Original code - this is an open file.
5266 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5267 DEBUG(3, ("fstat of %s failed (%s)\n",
5268 fsp_fnum_dbg(fsp), strerror(errno)));
5269 reply_nterror(req,
5270 map_nt_error_from_unix(errno));
5271 return;
5273 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5274 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5277 } else {
5278 uint32_t name_hash;
5279 char *fname = NULL;
5280 uint32_t ucf_flags = 0;
5282 /* qpathinfo */
5283 if (total_params < 7) {
5284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5285 return;
5288 info_level = SVAL(params,0);
5290 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5292 if (INFO_LEVEL_IS_UNIX(info_level)) {
5293 if (!lp_unix_extensions()) {
5294 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5295 return;
5297 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5298 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5299 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5300 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5304 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5305 total_params - 6,
5306 STR_TERMINATE, &status);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 reply_nterror(req, status);
5309 return;
5312 status = filename_convert(req,
5313 conn,
5314 req->flags2 & FLAGS2_DFS_PATHNAMES,
5315 fname,
5316 ucf_flags,
5317 NULL,
5318 &smb_fname);
5319 if (!NT_STATUS_IS_OK(status)) {
5320 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5321 reply_botherror(req,
5322 NT_STATUS_PATH_NOT_COVERED,
5323 ERRSRV, ERRbadpath);
5324 return;
5326 reply_nterror(req, status);
5327 return;
5330 /* If this is a stream, check if there is a delete_pending. */
5331 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5332 && is_ntfs_stream_smb_fname(smb_fname)) {
5333 struct smb_filename *smb_fname_base;
5335 /* Create an smb_filename with stream_name == NULL. */
5336 smb_fname_base = synthetic_smb_fname(
5337 talloc_tos(), smb_fname->base_name,
5338 NULL, NULL);
5339 if (smb_fname_base == NULL) {
5340 reply_nterror(req, NT_STATUS_NO_MEMORY);
5341 return;
5344 if (INFO_LEVEL_IS_UNIX(info_level)) {
5345 /* Always do lstat for UNIX calls. */
5346 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5347 DEBUG(3,("call_trans2qfilepathinfo: "
5348 "SMB_VFS_LSTAT of %s failed "
5349 "(%s)\n",
5350 smb_fname_str_dbg(smb_fname_base),
5351 strerror(errno)));
5352 TALLOC_FREE(smb_fname_base);
5353 reply_nterror(req,
5354 map_nt_error_from_unix(errno));
5355 return;
5357 } else {
5358 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5359 DEBUG(3,("call_trans2qfilepathinfo: "
5360 "fileinfo of %s failed "
5361 "(%s)\n",
5362 smb_fname_str_dbg(smb_fname_base),
5363 strerror(errno)));
5364 TALLOC_FREE(smb_fname_base);
5365 reply_nterror(req,
5366 map_nt_error_from_unix(errno));
5367 return;
5371 status = file_name_hash(conn,
5372 smb_fname_str_dbg(smb_fname_base),
5373 &name_hash);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 TALLOC_FREE(smb_fname_base);
5376 reply_nterror(req, status);
5377 return;
5380 fileid = vfs_file_id_from_sbuf(conn,
5381 &smb_fname_base->st);
5382 TALLOC_FREE(smb_fname_base);
5383 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5384 if (delete_pending) {
5385 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5386 return;
5390 if (INFO_LEVEL_IS_UNIX(info_level)) {
5391 /* Always do lstat for UNIX calls. */
5392 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5393 DEBUG(3,("call_trans2qfilepathinfo: "
5394 "SMB_VFS_LSTAT of %s failed (%s)\n",
5395 smb_fname_str_dbg(smb_fname),
5396 strerror(errno)));
5397 reply_nterror(req,
5398 map_nt_error_from_unix(errno));
5399 return;
5402 } else {
5403 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5404 DEBUG(3,("call_trans2qfilepathinfo: "
5405 "SMB_VFS_STAT of %s failed (%s)\n",
5406 smb_fname_str_dbg(smb_fname),
5407 strerror(errno)));
5408 reply_nterror(req,
5409 map_nt_error_from_unix(errno));
5410 return;
5414 status = file_name_hash(conn,
5415 smb_fname_str_dbg(smb_fname),
5416 &name_hash);
5417 if (!NT_STATUS_IS_OK(status)) {
5418 reply_nterror(req, status);
5419 return;
5422 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5423 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5424 if (delete_pending) {
5425 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5426 return;
5430 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5431 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5432 fsp_fnum_dbg(fsp),
5433 info_level,tran_call,total_data));
5435 /* Pull out any data sent here before we realloc. */
5436 switch (info_level) {
5437 case SMB_INFO_QUERY_EAS_FROM_LIST:
5439 /* Pull any EA list from the data portion. */
5440 uint32 ea_size;
5442 if (total_data < 4) {
5443 reply_nterror(
5444 req, NT_STATUS_INVALID_PARAMETER);
5445 return;
5447 ea_size = IVAL(pdata,0);
5449 if (total_data > 0 && ea_size != total_data) {
5450 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5451 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5452 reply_nterror(
5453 req, NT_STATUS_INVALID_PARAMETER);
5454 return;
5457 if (!lp_ea_support(SNUM(conn))) {
5458 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5459 return;
5462 /* Pull out the list of names. */
5463 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5464 if (!ea_list) {
5465 reply_nterror(
5466 req, NT_STATUS_INVALID_PARAMETER);
5467 return;
5469 break;
5472 case SMB_QUERY_POSIX_LOCK:
5474 if (fsp == NULL || fsp->fh->fd == -1) {
5475 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5476 return;
5479 if (total_data != POSIX_LOCK_DATA_SIZE) {
5480 reply_nterror(
5481 req, NT_STATUS_INVALID_PARAMETER);
5482 return;
5485 /* Copy the lock range data. */
5486 lock_data = (char *)talloc_memdup(
5487 req, pdata, total_data);
5488 if (!lock_data) {
5489 reply_nterror(req, NT_STATUS_NO_MEMORY);
5490 return;
5492 lock_data_count = total_data;
5494 default:
5495 break;
5498 *pparams = (char *)SMB_REALLOC(*pparams,2);
5499 if (*pparams == NULL) {
5500 reply_nterror(req, NT_STATUS_NO_MEMORY);
5501 return;
5503 params = *pparams;
5504 SSVAL(params,0,0);
5507 * draft-leach-cifs-v1-spec-02.txt
5508 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5509 * says:
5511 * The requested information is placed in the Data portion of the
5512 * transaction response. For the information levels greater than 0x100,
5513 * the transaction response has 1 parameter word which should be
5514 * ignored by the client.
5516 * However Windows only follows this rule for the IS_NAME_VALID call.
5518 switch (info_level) {
5519 case SMB_INFO_IS_NAME_VALID:
5520 param_size = 0;
5521 break;
5524 if ((info_level & 0xFF00) == 0xFF00) {
5526 * We use levels that start with 0xFF00
5527 * internally to represent SMB2 specific levels
5529 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5530 return;
5533 status = smbd_do_qfilepathinfo(conn, req, info_level,
5534 fsp, smb_fname,
5535 delete_pending, write_time_ts,
5536 ea_list,
5537 lock_data_count, lock_data,
5538 req->flags2, max_data_bytes,
5539 ppdata, &data_size);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 reply_nterror(req, status);
5542 return;
5545 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5546 max_data_bytes);
5548 return;
5551 /****************************************************************************
5552 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5553 code.
5554 ****************************************************************************/
5556 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5557 connection_struct *conn,
5558 struct smb_request *req,
5559 bool overwrite_if_exists,
5560 const struct smb_filename *smb_fname_old,
5561 struct smb_filename *smb_fname_new)
5563 NTSTATUS status = NT_STATUS_OK;
5565 /* source must already exist. */
5566 if (!VALID_STAT(smb_fname_old->st)) {
5567 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5570 if (VALID_STAT(smb_fname_new->st)) {
5571 if (overwrite_if_exists) {
5572 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5573 return NT_STATUS_FILE_IS_A_DIRECTORY;
5575 status = unlink_internals(conn,
5576 req,
5577 FILE_ATTRIBUTE_NORMAL,
5578 smb_fname_new,
5579 false);
5580 if (!NT_STATUS_IS_OK(status)) {
5581 return status;
5583 } else {
5584 /* Disallow if newname already exists. */
5585 return NT_STATUS_OBJECT_NAME_COLLISION;
5589 /* No links from a directory. */
5590 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5591 return NT_STATUS_FILE_IS_A_DIRECTORY;
5594 /* Setting a hardlink to/from a stream isn't currently supported. */
5595 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5596 is_ntfs_stream_smb_fname(smb_fname_new)) {
5597 return NT_STATUS_INVALID_PARAMETER;
5600 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5601 smb_fname_old->base_name, smb_fname_new->base_name));
5603 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5604 smb_fname_new->base_name) != 0) {
5605 status = map_nt_error_from_unix(errno);
5606 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5607 nt_errstr(status), smb_fname_old->base_name,
5608 smb_fname_new->base_name));
5610 return status;
5613 /****************************************************************************
5614 Deal with setting the time from any of the setfilepathinfo functions.
5615 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5616 calling this function.
5617 ****************************************************************************/
5619 NTSTATUS smb_set_file_time(connection_struct *conn,
5620 files_struct *fsp,
5621 const struct smb_filename *smb_fname,
5622 struct smb_file_time *ft,
5623 bool setting_write_time)
5625 struct smb_filename smb_fname_base;
5626 uint32 action =
5627 FILE_NOTIFY_CHANGE_LAST_ACCESS
5628 |FILE_NOTIFY_CHANGE_LAST_WRITE
5629 |FILE_NOTIFY_CHANGE_CREATION;
5631 if (!VALID_STAT(smb_fname->st)) {
5632 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5635 /* get some defaults (no modifications) if any info is zero or -1. */
5636 if (null_timespec(ft->create_time)) {
5637 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5640 if (null_timespec(ft->atime)) {
5641 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5644 if (null_timespec(ft->mtime)) {
5645 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5648 if (!setting_write_time) {
5649 /* ft->mtime comes from change time, not write time. */
5650 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5653 /* Ensure the resolution is the correct for
5654 * what we can store on this filesystem. */
5656 round_timespec(conn->ts_res, &ft->create_time);
5657 round_timespec(conn->ts_res, &ft->ctime);
5658 round_timespec(conn->ts_res, &ft->atime);
5659 round_timespec(conn->ts_res, &ft->mtime);
5661 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5662 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5663 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5664 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5665 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5666 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5667 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5668 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5670 if (setting_write_time) {
5672 * This was a Windows setfileinfo on an open file.
5673 * NT does this a lot. We also need to
5674 * set the time here, as it can be read by
5675 * FindFirst/FindNext and with the patch for bug #2045
5676 * in smbd/fileio.c it ensures that this timestamp is
5677 * kept sticky even after a write. We save the request
5678 * away and will set it on file close and after a write. JRA.
5681 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5682 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5684 if (fsp != NULL) {
5685 if (fsp->base_fsp) {
5686 set_sticky_write_time_fsp(fsp->base_fsp,
5687 ft->mtime);
5688 } else {
5689 set_sticky_write_time_fsp(fsp, ft->mtime);
5691 } else {
5692 set_sticky_write_time_path(
5693 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5694 ft->mtime);
5698 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5700 /* Always call ntimes on the base, even if a stream was passed in. */
5701 smb_fname_base = *smb_fname;
5702 smb_fname_base.stream_name = NULL;
5704 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5705 return map_nt_error_from_unix(errno);
5708 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5709 smb_fname->base_name);
5710 return NT_STATUS_OK;
5713 /****************************************************************************
5714 Deal with setting the dosmode from any of the setfilepathinfo functions.
5715 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5716 done before calling this function.
5717 ****************************************************************************/
5719 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5720 const struct smb_filename *smb_fname,
5721 uint32 dosmode)
5723 struct smb_filename *smb_fname_base;
5724 NTSTATUS status;
5726 if (!VALID_STAT(smb_fname->st)) {
5727 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5730 /* Always operate on the base_name, even if a stream was passed in. */
5731 smb_fname_base = synthetic_smb_fname(
5732 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5733 if (smb_fname_base == NULL) {
5734 return NT_STATUS_NO_MEMORY;
5737 if (dosmode) {
5738 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5739 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5740 } else {
5741 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5745 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5747 /* check the mode isn't different, before changing it */
5748 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5749 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5750 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5751 (unsigned int)dosmode));
5753 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5754 false)) {
5755 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5756 "%s failed (%s)\n",
5757 smb_fname_str_dbg(smb_fname_base),
5758 strerror(errno)));
5759 status = map_nt_error_from_unix(errno);
5760 goto out;
5763 status = NT_STATUS_OK;
5764 out:
5765 TALLOC_FREE(smb_fname_base);
5766 return status;
5769 /****************************************************************************
5770 Deal with setting the size from any of the setfilepathinfo functions.
5771 ****************************************************************************/
5773 static NTSTATUS smb_set_file_size(connection_struct *conn,
5774 struct smb_request *req,
5775 files_struct *fsp,
5776 const struct smb_filename *smb_fname,
5777 const SMB_STRUCT_STAT *psbuf,
5778 off_t size,
5779 bool fail_after_createfile)
5781 NTSTATUS status = NT_STATUS_OK;
5782 struct smb_filename *smb_fname_tmp = NULL;
5783 files_struct *new_fsp = NULL;
5785 if (!VALID_STAT(*psbuf)) {
5786 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5791 if (size == get_file_size_stat(psbuf)) {
5792 return NT_STATUS_OK;
5795 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5796 smb_fname_str_dbg(smb_fname), (double)size));
5798 if (fsp && fsp->fh->fd != -1) {
5799 /* Handle based call. */
5800 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5801 return NT_STATUS_ACCESS_DENIED;
5804 if (vfs_set_filelen(fsp, size) == -1) {
5805 return map_nt_error_from_unix(errno);
5807 trigger_write_time_update_immediate(fsp);
5808 return NT_STATUS_OK;
5811 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5812 if (smb_fname_tmp == NULL) {
5813 return NT_STATUS_NO_MEMORY;
5816 smb_fname_tmp->st = *psbuf;
5818 status = SMB_VFS_CREATE_FILE(
5819 conn, /* conn */
5820 req, /* req */
5821 0, /* root_dir_fid */
5822 smb_fname_tmp, /* fname */
5823 FILE_WRITE_DATA, /* access_mask */
5824 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5825 FILE_SHARE_DELETE),
5826 FILE_OPEN, /* create_disposition*/
5827 0, /* create_options */
5828 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5829 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5830 0, /* allocation_size */
5831 0, /* private_flags */
5832 NULL, /* sd */
5833 NULL, /* ea_list */
5834 &new_fsp, /* result */
5835 NULL); /* pinfo */
5837 TALLOC_FREE(smb_fname_tmp);
5839 if (!NT_STATUS_IS_OK(status)) {
5840 /* NB. We check for open_was_deferred in the caller. */
5841 return status;
5844 /* See RAW-SFILEINFO-END-OF-FILE */
5845 if (fail_after_createfile) {
5846 close_file(req, new_fsp,NORMAL_CLOSE);
5847 return NT_STATUS_INVALID_LEVEL;
5850 if (vfs_set_filelen(new_fsp, size) == -1) {
5851 status = map_nt_error_from_unix(errno);
5852 close_file(req, new_fsp,NORMAL_CLOSE);
5853 return status;
5856 trigger_write_time_update_immediate(new_fsp);
5857 close_file(req, new_fsp,NORMAL_CLOSE);
5858 return NT_STATUS_OK;
5861 /****************************************************************************
5862 Deal with SMB_INFO_SET_EA.
5863 ****************************************************************************/
5865 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5866 const char *pdata,
5867 int total_data,
5868 files_struct *fsp,
5869 const struct smb_filename *smb_fname)
5871 struct ea_list *ea_list = NULL;
5872 TALLOC_CTX *ctx = NULL;
5873 NTSTATUS status = NT_STATUS_OK;
5875 if (total_data < 10) {
5877 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5878 length. They seem to have no effect. Bug #3212. JRA */
5880 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5881 /* We're done. We only get EA info in this call. */
5882 return NT_STATUS_OK;
5885 return NT_STATUS_INVALID_PARAMETER;
5888 if (IVAL(pdata,0) > total_data) {
5889 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5890 IVAL(pdata,0), (unsigned int)total_data));
5891 return NT_STATUS_INVALID_PARAMETER;
5894 ctx = talloc_tos();
5895 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5896 if (!ea_list) {
5897 return NT_STATUS_INVALID_PARAMETER;
5900 status = set_ea(conn, fsp, smb_fname, ea_list);
5902 return status;
5905 /****************************************************************************
5906 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5907 ****************************************************************************/
5909 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5910 const char *pdata,
5911 int total_data,
5912 files_struct *fsp)
5914 struct ea_list *ea_list = NULL;
5915 NTSTATUS status;
5917 if (!fsp) {
5918 return NT_STATUS_INVALID_HANDLE;
5921 if (!lp_ea_support(SNUM(conn))) {
5922 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5923 "EA's not supported.\n",
5924 (unsigned int)total_data));
5925 return NT_STATUS_EAS_NOT_SUPPORTED;
5928 if (total_data < 10) {
5929 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5930 "too small.\n",
5931 (unsigned int)total_data));
5932 return NT_STATUS_INVALID_PARAMETER;
5935 ea_list = read_nttrans_ea_list(talloc_tos(),
5936 pdata,
5937 total_data);
5939 if (!ea_list) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5945 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5946 smb_fname_str_dbg(fsp->fsp_name),
5947 nt_errstr(status) ));
5949 return status;
5953 /****************************************************************************
5954 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5955 ****************************************************************************/
5957 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5958 const char *pdata,
5959 int total_data,
5960 files_struct *fsp,
5961 struct smb_filename *smb_fname)
5963 NTSTATUS status = NT_STATUS_OK;
5964 bool delete_on_close;
5965 uint32 dosmode = 0;
5967 if (total_data < 1) {
5968 return NT_STATUS_INVALID_PARAMETER;
5971 if (fsp == NULL) {
5972 return NT_STATUS_INVALID_HANDLE;
5975 delete_on_close = (CVAL(pdata,0) ? True : False);
5976 dosmode = dos_mode(conn, smb_fname);
5978 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5979 "delete_on_close = %u\n",
5980 smb_fname_str_dbg(smb_fname),
5981 (unsigned int)dosmode,
5982 (unsigned int)delete_on_close ));
5984 if (delete_on_close) {
5985 status = can_set_delete_on_close(fsp, dosmode);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 return status;
5991 /* The set is across all open files on this dev/inode pair. */
5992 if (!set_delete_on_close(fsp, delete_on_close,
5993 conn->session_info->security_token,
5994 conn->session_info->unix_token)) {
5995 return NT_STATUS_ACCESS_DENIED;
5997 return NT_STATUS_OK;
6000 /****************************************************************************
6001 Deal with SMB_FILE_POSITION_INFORMATION.
6002 ****************************************************************************/
6004 static NTSTATUS smb_file_position_information(connection_struct *conn,
6005 const char *pdata,
6006 int total_data,
6007 files_struct *fsp)
6009 uint64_t position_information;
6011 if (total_data < 8) {
6012 return NT_STATUS_INVALID_PARAMETER;
6015 if (fsp == NULL) {
6016 /* Ignore on pathname based set. */
6017 return NT_STATUS_OK;
6020 position_information = (uint64_t)IVAL(pdata,0);
6021 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6023 DEBUG(10,("smb_file_position_information: Set file position "
6024 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6025 (double)position_information));
6026 fsp->fh->position_information = position_information;
6027 return NT_STATUS_OK;
6030 /****************************************************************************
6031 Deal with SMB_FILE_MODE_INFORMATION.
6032 ****************************************************************************/
6034 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6035 const char *pdata,
6036 int total_data)
6038 uint32 mode;
6040 if (total_data < 4) {
6041 return NT_STATUS_INVALID_PARAMETER;
6043 mode = IVAL(pdata,0);
6044 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6045 return NT_STATUS_INVALID_PARAMETER;
6047 return NT_STATUS_OK;
6050 /****************************************************************************
6051 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6052 ****************************************************************************/
6054 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6055 struct smb_request *req,
6056 const char *pdata,
6057 int total_data,
6058 const struct smb_filename *smb_fname)
6060 char *link_target = NULL;
6061 const char *newname = smb_fname->base_name;
6062 TALLOC_CTX *ctx = talloc_tos();
6064 /* Set a symbolic link. */
6065 /* Don't allow this if follow links is false. */
6067 if (total_data == 0) {
6068 return NT_STATUS_INVALID_PARAMETER;
6071 if (!lp_symlinks(SNUM(conn))) {
6072 return NT_STATUS_ACCESS_DENIED;
6075 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6076 total_data, STR_TERMINATE);
6078 if (!link_target) {
6079 return NT_STATUS_INVALID_PARAMETER;
6082 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6083 newname, link_target ));
6085 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6086 return map_nt_error_from_unix(errno);
6089 return NT_STATUS_OK;
6092 /****************************************************************************
6093 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6094 ****************************************************************************/
6096 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6097 struct smb_request *req,
6098 const char *pdata, int total_data,
6099 struct smb_filename *smb_fname_new)
6101 char *oldname = NULL;
6102 struct smb_filename *smb_fname_old = NULL;
6103 TALLOC_CTX *ctx = talloc_tos();
6104 NTSTATUS status = NT_STATUS_OK;
6106 /* Set a hard link. */
6107 if (total_data == 0) {
6108 return NT_STATUS_INVALID_PARAMETER;
6111 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6112 total_data, STR_TERMINATE, &status);
6113 if (!NT_STATUS_IS_OK(status)) {
6114 return status;
6117 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6118 smb_fname_str_dbg(smb_fname_new), oldname));
6120 status = filename_convert(ctx,
6121 conn,
6122 req->flags2 & FLAGS2_DFS_PATHNAMES,
6123 oldname,
6125 NULL,
6126 &smb_fname_old);
6127 if (!NT_STATUS_IS_OK(status)) {
6128 return status;
6131 return hardlink_internals(ctx, conn, req, false,
6132 smb_fname_old, smb_fname_new);
6135 /****************************************************************************
6136 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6137 ****************************************************************************/
6139 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6140 struct smb_request *req,
6141 const char *pdata,
6142 int total_data,
6143 files_struct *fsp,
6144 struct smb_filename *smb_fname_src)
6146 bool overwrite;
6147 uint32_t len;
6148 char *newname = NULL;
6149 struct smb_filename *smb_fname_dst = NULL;
6150 NTSTATUS status = NT_STATUS_OK;
6151 TALLOC_CTX *ctx = talloc_tos();
6153 if (!fsp) {
6154 return NT_STATUS_INVALID_HANDLE;
6157 if (total_data < 20) {
6158 return NT_STATUS_INVALID_PARAMETER;
6161 overwrite = (CVAL(pdata,0) ? True : False);
6162 len = IVAL(pdata,16);
6164 if (len > (total_data - 20) || (len == 0)) {
6165 return NT_STATUS_INVALID_PARAMETER;
6168 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6169 &pdata[20], len, STR_TERMINATE,
6170 &status);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 return status;
6175 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6176 newname));
6178 status = filename_convert(ctx,
6179 conn,
6180 req->flags2 & FLAGS2_DFS_PATHNAMES,
6181 newname,
6182 UCF_SAVE_LCOMP,
6183 NULL,
6184 &smb_fname_dst);
6185 if (!NT_STATUS_IS_OK(status)) {
6186 return status;
6189 if (fsp->base_fsp) {
6190 /* newname must be a stream name. */
6191 if (newname[0] != ':') {
6192 return NT_STATUS_NOT_SUPPORTED;
6195 /* Create an smb_fname to call rename_internals_fsp() with. */
6196 smb_fname_dst = synthetic_smb_fname(
6197 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6198 newname, NULL);
6199 if (smb_fname_dst == NULL) {
6200 status = NT_STATUS_NO_MEMORY;
6201 goto out;
6205 * Set the original last component, since
6206 * rename_internals_fsp() requires it.
6208 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6209 newname);
6210 if (smb_fname_dst->original_lcomp == NULL) {
6211 status = NT_STATUS_NO_MEMORY;
6212 goto out;
6217 DEBUG(10,("smb2_file_rename_information: "
6218 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6219 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6220 smb_fname_str_dbg(smb_fname_dst)));
6221 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6222 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6223 overwrite);
6225 out:
6226 TALLOC_FREE(smb_fname_dst);
6227 return status;
6230 static NTSTATUS smb_file_link_information(connection_struct *conn,
6231 struct smb_request *req,
6232 const char *pdata,
6233 int total_data,
6234 files_struct *fsp,
6235 struct smb_filename *smb_fname_src)
6237 bool overwrite;
6238 uint32_t len;
6239 char *newname = NULL;
6240 struct smb_filename *smb_fname_dst = NULL;
6241 NTSTATUS status = NT_STATUS_OK;
6242 TALLOC_CTX *ctx = talloc_tos();
6244 if (!fsp) {
6245 return NT_STATUS_INVALID_HANDLE;
6248 if (total_data < 20) {
6249 return NT_STATUS_INVALID_PARAMETER;
6252 overwrite = (CVAL(pdata,0) ? true : false);
6253 len = IVAL(pdata,16);
6255 if (len > (total_data - 20) || (len == 0)) {
6256 return NT_STATUS_INVALID_PARAMETER;
6259 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6260 &pdata[20], len, STR_TERMINATE,
6261 &status);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 return status;
6266 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6267 newname));
6269 status = filename_convert(ctx,
6270 conn,
6271 req->flags2 & FLAGS2_DFS_PATHNAMES,
6272 newname,
6273 UCF_SAVE_LCOMP,
6274 NULL,
6275 &smb_fname_dst);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 return status;
6280 if (fsp->base_fsp) {
6281 /* No stream names. */
6282 return NT_STATUS_NOT_SUPPORTED;
6285 DEBUG(10,("smb_file_link_information: "
6286 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6287 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6288 smb_fname_str_dbg(smb_fname_dst)));
6289 status = hardlink_internals(ctx,
6290 conn,
6291 req,
6292 overwrite,
6293 fsp->fsp_name,
6294 smb_fname_dst);
6296 TALLOC_FREE(smb_fname_dst);
6297 return status;
6300 /****************************************************************************
6301 Deal with SMB_FILE_RENAME_INFORMATION.
6302 ****************************************************************************/
6304 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6305 struct smb_request *req,
6306 const char *pdata,
6307 int total_data,
6308 files_struct *fsp,
6309 struct smb_filename *smb_fname_src)
6311 bool overwrite;
6312 uint32 root_fid;
6313 uint32 len;
6314 char *newname = NULL;
6315 struct smb_filename *smb_fname_dst = NULL;
6316 bool dest_has_wcard = False;
6317 NTSTATUS status = NT_STATUS_OK;
6318 char *p;
6319 TALLOC_CTX *ctx = talloc_tos();
6321 if (total_data < 13) {
6322 return NT_STATUS_INVALID_PARAMETER;
6325 overwrite = (CVAL(pdata,0) ? True : False);
6326 root_fid = IVAL(pdata,4);
6327 len = IVAL(pdata,8);
6329 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6330 return NT_STATUS_INVALID_PARAMETER;
6333 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6334 len, 0, &status,
6335 &dest_has_wcard);
6336 if (!NT_STATUS_IS_OK(status)) {
6337 return status;
6340 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6341 newname));
6343 status = resolve_dfspath_wcard(ctx, conn,
6344 req->flags2 & FLAGS2_DFS_PATHNAMES,
6345 newname,
6346 true,
6347 !conn->sconn->using_smb2,
6348 &newname,
6349 &dest_has_wcard);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 return status;
6354 /* Check the new name has no '/' characters. */
6355 if (strchr_m(newname, '/')) {
6356 return NT_STATUS_NOT_SUPPORTED;
6359 if (fsp && fsp->base_fsp) {
6360 /* newname must be a stream name. */
6361 if (newname[0] != ':') {
6362 return NT_STATUS_NOT_SUPPORTED;
6365 /* Create an smb_fname to call rename_internals_fsp() with. */
6366 smb_fname_dst = synthetic_smb_fname(
6367 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6368 newname, NULL);
6369 if (smb_fname_dst == NULL) {
6370 status = NT_STATUS_NO_MEMORY;
6371 goto out;
6375 * Set the original last component, since
6376 * rename_internals_fsp() requires it.
6378 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6379 newname);
6380 if (smb_fname_dst->original_lcomp == NULL) {
6381 status = NT_STATUS_NO_MEMORY;
6382 goto out;
6385 } else {
6387 * Build up an smb_fname_dst based on the filename passed in.
6388 * We basically just strip off the last component, and put on
6389 * the newname instead.
6391 char *base_name = NULL;
6393 /* newname must *not* be a stream name. */
6394 if (newname[0] == ':') {
6395 return NT_STATUS_NOT_SUPPORTED;
6399 * Strip off the last component (filename) of the path passed
6400 * in.
6402 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6403 if (!base_name) {
6404 return NT_STATUS_NO_MEMORY;
6406 p = strrchr_m(base_name, '/');
6407 if (p) {
6408 p[1] = '\0';
6409 } else {
6410 base_name = talloc_strdup(ctx, "");
6411 if (!base_name) {
6412 return NT_STATUS_NO_MEMORY;
6415 /* Append the new name. */
6416 base_name = talloc_asprintf_append(base_name,
6417 "%s",
6418 newname);
6419 if (!base_name) {
6420 return NT_STATUS_NO_MEMORY;
6423 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6424 (UCF_SAVE_LCOMP |
6425 (dest_has_wcard ?
6426 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6427 0)));
6429 /* If an error we expect this to be
6430 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6432 if (!NT_STATUS_IS_OK(status)) {
6433 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6434 status)) {
6435 goto out;
6437 /* Create an smb_fname to call rename_internals_fsp() */
6438 smb_fname_dst = synthetic_smb_fname(
6439 ctx, base_name, NULL, NULL);
6440 if (smb_fname_dst == NULL) {
6441 status = NT_STATUS_NO_MEMORY;
6442 goto out;
6447 if (fsp) {
6448 DEBUG(10,("smb_file_rename_information: "
6449 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6450 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6451 smb_fname_str_dbg(smb_fname_dst)));
6452 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6453 overwrite);
6454 } else {
6455 DEBUG(10,("smb_file_rename_information: "
6456 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6457 smb_fname_str_dbg(smb_fname_src),
6458 smb_fname_str_dbg(smb_fname_dst)));
6459 status = rename_internals(ctx, conn, req, smb_fname_src,
6460 smb_fname_dst, 0, overwrite, false,
6461 dest_has_wcard,
6462 FILE_WRITE_ATTRIBUTES);
6464 out:
6465 TALLOC_FREE(smb_fname_dst);
6466 return status;
6469 /****************************************************************************
6470 Deal with SMB_SET_POSIX_ACL.
6471 ****************************************************************************/
6473 #if defined(HAVE_POSIX_ACLS)
6474 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6475 const char *pdata,
6476 int total_data,
6477 files_struct *fsp,
6478 const struct smb_filename *smb_fname)
6480 uint16 posix_acl_version;
6481 uint16 num_file_acls;
6482 uint16 num_def_acls;
6483 bool valid_file_acls = True;
6484 bool valid_def_acls = True;
6486 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6487 return NT_STATUS_INVALID_PARAMETER;
6489 posix_acl_version = SVAL(pdata,0);
6490 num_file_acls = SVAL(pdata,2);
6491 num_def_acls = SVAL(pdata,4);
6493 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6494 valid_file_acls = False;
6495 num_file_acls = 0;
6498 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6499 valid_def_acls = False;
6500 num_def_acls = 0;
6503 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6504 return NT_STATUS_INVALID_PARAMETER;
6507 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6508 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6509 return NT_STATUS_INVALID_PARAMETER;
6512 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6513 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6514 (unsigned int)num_file_acls,
6515 (unsigned int)num_def_acls));
6517 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6518 smb_fname->base_name, num_file_acls,
6519 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6520 return map_nt_error_from_unix(errno);
6523 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6524 smb_fname->base_name, &smb_fname->st, num_def_acls,
6525 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6526 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6527 return map_nt_error_from_unix(errno);
6529 return NT_STATUS_OK;
6531 #endif
6533 /****************************************************************************
6534 Deal with SMB_SET_POSIX_LOCK.
6535 ****************************************************************************/
6537 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6538 struct smb_request *req,
6539 const char *pdata,
6540 int total_data,
6541 files_struct *fsp)
6543 uint64_t count;
6544 uint64_t offset;
6545 uint64_t smblctx;
6546 bool blocking_lock = False;
6547 enum brl_type lock_type;
6549 NTSTATUS status = NT_STATUS_OK;
6551 if (fsp == NULL || fsp->fh->fd == -1) {
6552 return NT_STATUS_INVALID_HANDLE;
6555 if (total_data != POSIX_LOCK_DATA_SIZE) {
6556 return NT_STATUS_INVALID_PARAMETER;
6559 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6560 case POSIX_LOCK_TYPE_READ:
6561 lock_type = READ_LOCK;
6562 break;
6563 case POSIX_LOCK_TYPE_WRITE:
6564 /* Return the right POSIX-mappable error code for files opened read-only. */
6565 if (!fsp->can_write) {
6566 return NT_STATUS_INVALID_HANDLE;
6568 lock_type = WRITE_LOCK;
6569 break;
6570 case POSIX_LOCK_TYPE_UNLOCK:
6571 lock_type = UNLOCK_LOCK;
6572 break;
6573 default:
6574 return NT_STATUS_INVALID_PARAMETER;
6577 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6578 blocking_lock = False;
6579 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6580 blocking_lock = True;
6581 } else {
6582 return NT_STATUS_INVALID_PARAMETER;
6585 if (!lp_blocking_locks(SNUM(conn))) {
6586 blocking_lock = False;
6589 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6590 #if defined(HAVE_LONGLONG)
6591 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6592 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6593 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6594 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6595 #else /* HAVE_LONGLONG */
6596 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6597 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6598 #endif /* HAVE_LONGLONG */
6600 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6601 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6602 fsp_str_dbg(fsp),
6603 (unsigned int)lock_type,
6604 (unsigned long long)smblctx,
6605 (double)count,
6606 (double)offset ));
6608 if (lock_type == UNLOCK_LOCK) {
6609 status = do_unlock(req->sconn->msg_ctx,
6610 fsp,
6611 smblctx,
6612 count,
6613 offset,
6614 POSIX_LOCK);
6615 } else {
6616 uint64_t block_smblctx;
6618 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6619 fsp,
6620 smblctx,
6621 count,
6622 offset,
6623 lock_type,
6624 POSIX_LOCK,
6625 blocking_lock,
6626 &status,
6627 &block_smblctx,
6628 NULL);
6630 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6632 * A blocking lock was requested. Package up
6633 * this smb into a queued request and push it
6634 * onto the blocking lock queue.
6636 if(push_blocking_lock_request(br_lck,
6637 req,
6638 fsp,
6639 -1, /* infinite timeout. */
6641 smblctx,
6642 lock_type,
6643 POSIX_LOCK,
6644 offset,
6645 count,
6646 block_smblctx)) {
6647 TALLOC_FREE(br_lck);
6648 return status;
6651 TALLOC_FREE(br_lck);
6654 return status;
6657 /****************************************************************************
6658 Deal with SMB_SET_FILE_BASIC_INFO.
6659 ****************************************************************************/
6661 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6662 const char *pdata,
6663 int total_data,
6664 files_struct *fsp,
6665 const struct smb_filename *smb_fname)
6667 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6668 struct smb_file_time ft;
6669 uint32 dosmode = 0;
6670 NTSTATUS status = NT_STATUS_OK;
6672 ZERO_STRUCT(ft);
6674 if (total_data < 36) {
6675 return NT_STATUS_INVALID_PARAMETER;
6678 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 return status;
6683 /* Set the attributes */
6684 dosmode = IVAL(pdata,32);
6685 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6686 if (!NT_STATUS_IS_OK(status)) {
6687 return status;
6690 /* create time */
6691 ft.create_time = interpret_long_date(pdata);
6693 /* access time */
6694 ft.atime = interpret_long_date(pdata+8);
6696 /* write time. */
6697 ft.mtime = interpret_long_date(pdata+16);
6699 /* change time. */
6700 ft.ctime = interpret_long_date(pdata+24);
6702 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6703 smb_fname_str_dbg(smb_fname)));
6705 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6706 true);
6709 /****************************************************************************
6710 Deal with SMB_INFO_STANDARD.
6711 ****************************************************************************/
6713 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6714 const char *pdata,
6715 int total_data,
6716 files_struct *fsp,
6717 const struct smb_filename *smb_fname)
6719 NTSTATUS status;
6720 struct smb_file_time ft;
6722 ZERO_STRUCT(ft);
6724 if (total_data < 12) {
6725 return NT_STATUS_INVALID_PARAMETER;
6728 /* create time */
6729 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6730 /* access time */
6731 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6732 /* write time */
6733 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6735 DEBUG(10,("smb_set_info_standard: file %s\n",
6736 smb_fname_str_dbg(smb_fname)));
6738 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6739 if (!NT_STATUS_IS_OK(status)) {
6740 return status;
6743 return smb_set_file_time(conn,
6744 fsp,
6745 smb_fname,
6746 &ft,
6747 true);
6750 /****************************************************************************
6751 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6752 ****************************************************************************/
6754 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6755 struct smb_request *req,
6756 const char *pdata,
6757 int total_data,
6758 files_struct *fsp,
6759 struct smb_filename *smb_fname)
6761 uint64_t allocation_size = 0;
6762 NTSTATUS status = NT_STATUS_OK;
6763 files_struct *new_fsp = NULL;
6765 if (!VALID_STAT(smb_fname->st)) {
6766 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6769 if (total_data < 8) {
6770 return NT_STATUS_INVALID_PARAMETER;
6773 allocation_size = (uint64_t)IVAL(pdata,0);
6774 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6775 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6776 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6777 (double)allocation_size));
6779 if (allocation_size) {
6780 allocation_size = smb_roundup(conn, allocation_size);
6783 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6784 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6785 (double)allocation_size));
6787 if (fsp && fsp->fh->fd != -1) {
6788 /* Open file handle. */
6789 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6790 return NT_STATUS_ACCESS_DENIED;
6793 /* Only change if needed. */
6794 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6795 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6796 return map_nt_error_from_unix(errno);
6799 /* But always update the time. */
6801 * This is equivalent to a write. Ensure it's seen immediately
6802 * if there are no pending writes.
6804 trigger_write_time_update_immediate(fsp);
6805 return NT_STATUS_OK;
6808 /* Pathname or stat or directory file. */
6809 status = SMB_VFS_CREATE_FILE(
6810 conn, /* conn */
6811 req, /* req */
6812 0, /* root_dir_fid */
6813 smb_fname, /* fname */
6814 FILE_WRITE_DATA, /* access_mask */
6815 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6816 FILE_SHARE_DELETE),
6817 FILE_OPEN, /* create_disposition*/
6818 0, /* create_options */
6819 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6820 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6821 0, /* allocation_size */
6822 0, /* private_flags */
6823 NULL, /* sd */
6824 NULL, /* ea_list */
6825 &new_fsp, /* result */
6826 NULL); /* pinfo */
6828 if (!NT_STATUS_IS_OK(status)) {
6829 /* NB. We check for open_was_deferred in the caller. */
6830 return status;
6833 /* Only change if needed. */
6834 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6835 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6836 status = map_nt_error_from_unix(errno);
6837 close_file(req, new_fsp, NORMAL_CLOSE);
6838 return status;
6842 /* Changing the allocation size should set the last mod time. */
6844 * This is equivalent to a write. Ensure it's seen immediately
6845 * if there are no pending writes.
6847 trigger_write_time_update_immediate(new_fsp);
6849 close_file(req, new_fsp, NORMAL_CLOSE);
6850 return NT_STATUS_OK;
6853 /****************************************************************************
6854 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6855 ****************************************************************************/
6857 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6858 struct smb_request *req,
6859 const char *pdata,
6860 int total_data,
6861 files_struct *fsp,
6862 const struct smb_filename *smb_fname,
6863 bool fail_after_createfile)
6865 off_t size;
6867 if (total_data < 8) {
6868 return NT_STATUS_INVALID_PARAMETER;
6871 size = IVAL(pdata,0);
6872 size |= (((off_t)IVAL(pdata,4)) << 32);
6873 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6874 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6875 (double)size));
6877 return smb_set_file_size(conn, req,
6878 fsp,
6879 smb_fname,
6880 &smb_fname->st,
6881 size,
6882 fail_after_createfile);
6885 /****************************************************************************
6886 Allow a UNIX info mknod.
6887 ****************************************************************************/
6889 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6890 const char *pdata,
6891 int total_data,
6892 const struct smb_filename *smb_fname)
6894 uint32 file_type = IVAL(pdata,56);
6895 #if defined(HAVE_MAKEDEV)
6896 uint32 dev_major = IVAL(pdata,60);
6897 uint32 dev_minor = IVAL(pdata,68);
6898 #endif
6899 SMB_DEV_T dev = (SMB_DEV_T)0;
6900 uint32 raw_unixmode = IVAL(pdata,84);
6901 NTSTATUS status;
6902 mode_t unixmode;
6904 if (total_data < 100) {
6905 return NT_STATUS_INVALID_PARAMETER;
6908 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6909 PERM_NEW_FILE, &unixmode);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 return status;
6914 #if defined(HAVE_MAKEDEV)
6915 dev = makedev(dev_major, dev_minor);
6916 #endif
6918 switch (file_type) {
6919 #if defined(S_IFIFO)
6920 case UNIX_TYPE_FIFO:
6921 unixmode |= S_IFIFO;
6922 break;
6923 #endif
6924 #if defined(S_IFSOCK)
6925 case UNIX_TYPE_SOCKET:
6926 unixmode |= S_IFSOCK;
6927 break;
6928 #endif
6929 #if defined(S_IFCHR)
6930 case UNIX_TYPE_CHARDEV:
6931 unixmode |= S_IFCHR;
6932 break;
6933 #endif
6934 #if defined(S_IFBLK)
6935 case UNIX_TYPE_BLKDEV:
6936 unixmode |= S_IFBLK;
6937 break;
6938 #endif
6939 default:
6940 return NT_STATUS_INVALID_PARAMETER;
6943 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6944 "%.0f mode 0%o for file %s\n", (double)dev,
6945 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6947 /* Ok - do the mknod. */
6948 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6949 return map_nt_error_from_unix(errno);
6952 /* If any of the other "set" calls fail we
6953 * don't want to end up with a half-constructed mknod.
6956 if (lp_inherit_perms(SNUM(conn))) {
6957 char *parent;
6958 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6959 &parent, NULL)) {
6960 return NT_STATUS_NO_MEMORY;
6962 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6963 unixmode);
6964 TALLOC_FREE(parent);
6967 return NT_STATUS_OK;
6970 /****************************************************************************
6971 Deal with SMB_SET_FILE_UNIX_BASIC.
6972 ****************************************************************************/
6974 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6975 struct smb_request *req,
6976 const char *pdata,
6977 int total_data,
6978 files_struct *fsp,
6979 const struct smb_filename *smb_fname)
6981 struct smb_file_time ft;
6982 uint32 raw_unixmode;
6983 mode_t unixmode;
6984 off_t size = 0;
6985 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6986 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6987 NTSTATUS status = NT_STATUS_OK;
6988 bool delete_on_fail = False;
6989 enum perm_type ptype;
6990 files_struct *all_fsps = NULL;
6991 bool modify_mtime = true;
6992 struct file_id id;
6993 struct smb_filename *smb_fname_tmp = NULL;
6994 SMB_STRUCT_STAT sbuf;
6996 ZERO_STRUCT(ft);
6998 if (total_data < 100) {
6999 return NT_STATUS_INVALID_PARAMETER;
7002 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7003 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7004 size=IVAL(pdata,0); /* first 8 Bytes are size */
7005 size |= (((off_t)IVAL(pdata,4)) << 32);
7008 ft.atime = interpret_long_date(pdata+24); /* access_time */
7009 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7010 set_owner = (uid_t)IVAL(pdata,40);
7011 set_grp = (gid_t)IVAL(pdata,48);
7012 raw_unixmode = IVAL(pdata,84);
7014 if (VALID_STAT(smb_fname->st)) {
7015 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7016 ptype = PERM_EXISTING_DIR;
7017 } else {
7018 ptype = PERM_EXISTING_FILE;
7020 } else {
7021 ptype = PERM_NEW_FILE;
7024 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7025 ptype, &unixmode);
7026 if (!NT_STATUS_IS_OK(status)) {
7027 return status;
7030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7031 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7032 smb_fname_str_dbg(smb_fname), (double)size,
7033 (unsigned int)set_owner, (unsigned int)set_grp,
7034 (int)raw_unixmode));
7036 sbuf = smb_fname->st;
7038 if (!VALID_STAT(sbuf)) {
7040 * The only valid use of this is to create character and block
7041 * devices, and named pipes. This is deprecated (IMHO) and
7042 * a new info level should be used for mknod. JRA.
7045 status = smb_unix_mknod(conn,
7046 pdata,
7047 total_data,
7048 smb_fname);
7049 if (!NT_STATUS_IS_OK(status)) {
7050 return status;
7053 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7054 if (smb_fname_tmp == NULL) {
7055 return NT_STATUS_NO_MEMORY;
7058 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7059 status = map_nt_error_from_unix(errno);
7060 TALLOC_FREE(smb_fname_tmp);
7061 SMB_VFS_UNLINK(conn, smb_fname);
7062 return status;
7065 sbuf = smb_fname_tmp->st;
7066 smb_fname = smb_fname_tmp;
7068 /* Ensure we don't try and change anything else. */
7069 raw_unixmode = SMB_MODE_NO_CHANGE;
7070 size = get_file_size_stat(&sbuf);
7071 ft.atime = sbuf.st_ex_atime;
7072 ft.mtime = sbuf.st_ex_mtime;
7074 * We continue here as we might want to change the
7075 * owner uid/gid.
7077 delete_on_fail = True;
7080 #if 1
7081 /* Horrible backwards compatibility hack as an old server bug
7082 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7083 * */
7085 if (!size) {
7086 size = get_file_size_stat(&sbuf);
7088 #endif
7091 * Deal with the UNIX specific mode set.
7094 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7095 int ret;
7097 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7098 "setting mode 0%o for file %s\n",
7099 (unsigned int)unixmode,
7100 smb_fname_str_dbg(smb_fname)));
7101 if (fsp && fsp->fh->fd != -1) {
7102 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7103 } else {
7104 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7106 if (ret != 0) {
7107 return map_nt_error_from_unix(errno);
7112 * Deal with the UNIX specific uid set.
7115 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7116 (sbuf.st_ex_uid != set_owner)) {
7117 int ret;
7119 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7120 "changing owner %u for path %s\n",
7121 (unsigned int)set_owner,
7122 smb_fname_str_dbg(smb_fname)));
7124 if (fsp && fsp->fh->fd != -1) {
7125 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7126 } else {
7128 * UNIX extensions calls must always operate
7129 * on symlinks.
7131 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7132 set_owner, (gid_t)-1);
7135 if (ret != 0) {
7136 status = map_nt_error_from_unix(errno);
7137 if (delete_on_fail) {
7138 SMB_VFS_UNLINK(conn, smb_fname);
7140 return status;
7145 * Deal with the UNIX specific gid set.
7148 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7149 (sbuf.st_ex_gid != set_grp)) {
7150 int ret;
7152 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7153 "changing group %u for file %s\n",
7154 (unsigned int)set_owner,
7155 smb_fname_str_dbg(smb_fname)));
7156 if (fsp && fsp->fh->fd != -1) {
7157 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7158 } else {
7160 * UNIX extensions calls must always operate
7161 * on symlinks.
7163 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7164 set_grp);
7166 if (ret != 0) {
7167 status = map_nt_error_from_unix(errno);
7168 if (delete_on_fail) {
7169 SMB_VFS_UNLINK(conn, smb_fname);
7171 return status;
7175 /* Deal with any size changes. */
7177 status = smb_set_file_size(conn, req,
7178 fsp,
7179 smb_fname,
7180 &sbuf,
7181 size,
7182 false);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 return status;
7187 /* Deal with any time changes. */
7188 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7189 /* No change, don't cancel anything. */
7190 return status;
7193 id = vfs_file_id_from_sbuf(conn, &sbuf);
7194 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7195 all_fsps = file_find_di_next(all_fsps)) {
7197 * We're setting the time explicitly for UNIX.
7198 * Cancel any pending changes over all handles.
7200 all_fsps->update_write_time_on_close = false;
7201 TALLOC_FREE(all_fsps->update_write_time_event);
7205 * Override the "setting_write_time"
7206 * parameter here as it almost does what
7207 * we need. Just remember if we modified
7208 * mtime and send the notify ourselves.
7210 if (null_timespec(ft.mtime)) {
7211 modify_mtime = false;
7214 status = smb_set_file_time(conn,
7215 fsp,
7216 smb_fname,
7217 &ft,
7218 false);
7219 if (modify_mtime) {
7220 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7221 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7223 return status;
7226 /****************************************************************************
7227 Deal with SMB_SET_FILE_UNIX_INFO2.
7228 ****************************************************************************/
7230 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7231 struct smb_request *req,
7232 const char *pdata,
7233 int total_data,
7234 files_struct *fsp,
7235 const struct smb_filename *smb_fname)
7237 NTSTATUS status;
7238 uint32 smb_fflags;
7239 uint32 smb_fmask;
7241 if (total_data < 116) {
7242 return NT_STATUS_INVALID_PARAMETER;
7245 /* Start by setting all the fields that are common between UNIX_BASIC
7246 * and UNIX_INFO2.
7248 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7249 fsp, smb_fname);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 return status;
7254 smb_fflags = IVAL(pdata, 108);
7255 smb_fmask = IVAL(pdata, 112);
7257 /* NB: We should only attempt to alter the file flags if the client
7258 * sends a non-zero mask.
7260 if (smb_fmask != 0) {
7261 int stat_fflags = 0;
7263 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7264 smb_fmask, &stat_fflags)) {
7265 /* Client asked to alter a flag we don't understand. */
7266 return NT_STATUS_INVALID_PARAMETER;
7269 if (fsp && fsp->fh->fd != -1) {
7270 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7271 return NT_STATUS_NOT_SUPPORTED;
7272 } else {
7273 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7274 stat_fflags) != 0) {
7275 return map_nt_error_from_unix(errno);
7280 /* XXX: need to add support for changing the create_time here. You
7281 * can do this for paths on Darwin with setattrlist(2). The right way
7282 * to hook this up is probably by extending the VFS utimes interface.
7285 return NT_STATUS_OK;
7288 /****************************************************************************
7289 Create a directory with POSIX semantics.
7290 ****************************************************************************/
7292 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7293 struct smb_request *req,
7294 char **ppdata,
7295 int total_data,
7296 struct smb_filename *smb_fname,
7297 int *pdata_return_size)
7299 NTSTATUS status = NT_STATUS_OK;
7300 uint32 raw_unixmode = 0;
7301 uint32 mod_unixmode = 0;
7302 mode_t unixmode = (mode_t)0;
7303 files_struct *fsp = NULL;
7304 uint16 info_level_return = 0;
7305 int info;
7306 char *pdata = *ppdata;
7308 if (total_data < 18) {
7309 return NT_STATUS_INVALID_PARAMETER;
7312 raw_unixmode = IVAL(pdata,8);
7313 /* Next 4 bytes are not yet defined. */
7315 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7316 PERM_NEW_DIR, &unixmode);
7317 if (!NT_STATUS_IS_OK(status)) {
7318 return status;
7321 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7323 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7324 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7326 status = SMB_VFS_CREATE_FILE(
7327 conn, /* conn */
7328 req, /* req */
7329 0, /* root_dir_fid */
7330 smb_fname, /* fname */
7331 FILE_READ_ATTRIBUTES, /* access_mask */
7332 FILE_SHARE_NONE, /* share_access */
7333 FILE_CREATE, /* create_disposition*/
7334 FILE_DIRECTORY_FILE, /* create_options */
7335 mod_unixmode, /* file_attributes */
7336 0, /* oplock_request */
7337 0, /* allocation_size */
7338 0, /* private_flags */
7339 NULL, /* sd */
7340 NULL, /* ea_list */
7341 &fsp, /* result */
7342 &info); /* pinfo */
7344 if (NT_STATUS_IS_OK(status)) {
7345 close_file(req, fsp, NORMAL_CLOSE);
7348 info_level_return = SVAL(pdata,16);
7350 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7351 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7352 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7353 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7354 } else {
7355 *pdata_return_size = 12;
7358 /* Realloc the data size */
7359 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7360 if (*ppdata == NULL) {
7361 *pdata_return_size = 0;
7362 return NT_STATUS_NO_MEMORY;
7364 pdata = *ppdata;
7366 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7367 SSVAL(pdata,2,0); /* No fnum. */
7368 SIVAL(pdata,4,info); /* Was directory created. */
7370 switch (info_level_return) {
7371 case SMB_QUERY_FILE_UNIX_BASIC:
7372 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7373 SSVAL(pdata,10,0); /* Padding. */
7374 store_file_unix_basic(conn, pdata + 12, fsp,
7375 &smb_fname->st);
7376 break;
7377 case SMB_QUERY_FILE_UNIX_INFO2:
7378 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7379 SSVAL(pdata,10,0); /* Padding. */
7380 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7381 &smb_fname->st);
7382 break;
7383 default:
7384 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7385 SSVAL(pdata,10,0); /* Padding. */
7386 break;
7389 return status;
7392 /****************************************************************************
7393 Open/Create a file with POSIX semantics.
7394 ****************************************************************************/
7396 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7397 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7399 static NTSTATUS smb_posix_open(connection_struct *conn,
7400 struct smb_request *req,
7401 char **ppdata,
7402 int total_data,
7403 struct smb_filename *smb_fname,
7404 int *pdata_return_size)
7406 bool extended_oplock_granted = False;
7407 char *pdata = *ppdata;
7408 uint32 flags = 0;
7409 uint32 wire_open_mode = 0;
7410 uint32 raw_unixmode = 0;
7411 uint32 mod_unixmode = 0;
7412 uint32 create_disp = 0;
7413 uint32 access_mask = 0;
7414 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7415 NTSTATUS status = NT_STATUS_OK;
7416 mode_t unixmode = (mode_t)0;
7417 files_struct *fsp = NULL;
7418 int oplock_request = 0;
7419 int info = 0;
7420 uint16 info_level_return = 0;
7422 if (total_data < 18) {
7423 return NT_STATUS_INVALID_PARAMETER;
7426 flags = IVAL(pdata,0);
7427 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7428 if (oplock_request) {
7429 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7432 wire_open_mode = IVAL(pdata,4);
7434 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7435 return smb_posix_mkdir(conn, req,
7436 ppdata,
7437 total_data,
7438 smb_fname,
7439 pdata_return_size);
7442 switch (wire_open_mode & SMB_ACCMODE) {
7443 case SMB_O_RDONLY:
7444 access_mask = SMB_O_RDONLY_MAPPING;
7445 break;
7446 case SMB_O_WRONLY:
7447 access_mask = SMB_O_WRONLY_MAPPING;
7448 break;
7449 case SMB_O_RDWR:
7450 access_mask = (SMB_O_RDONLY_MAPPING|
7451 SMB_O_WRONLY_MAPPING);
7452 break;
7453 default:
7454 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7455 (unsigned int)wire_open_mode ));
7456 return NT_STATUS_INVALID_PARAMETER;
7459 wire_open_mode &= ~SMB_ACCMODE;
7461 /* First take care of O_CREAT|O_EXCL interactions. */
7462 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7463 case (SMB_O_CREAT | SMB_O_EXCL):
7464 /* File exists fail. File not exist create. */
7465 create_disp = FILE_CREATE;
7466 break;
7467 case SMB_O_CREAT:
7468 /* File exists open. File not exist create. */
7469 create_disp = FILE_OPEN_IF;
7470 break;
7471 case SMB_O_EXCL:
7472 /* O_EXCL on its own without O_CREAT is undefined.
7473 We deliberately ignore it as some versions of
7474 Linux CIFSFS can send a bare O_EXCL on the
7475 wire which other filesystems in the kernel
7476 ignore. See bug 9519 for details. */
7478 /* Fallthrough. */
7480 case 0:
7481 /* File exists open. File not exist fail. */
7482 create_disp = FILE_OPEN;
7483 break;
7484 default:
7485 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7486 (unsigned int)wire_open_mode ));
7487 return NT_STATUS_INVALID_PARAMETER;
7490 /* Next factor in the effects of O_TRUNC. */
7491 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7493 if (wire_open_mode & SMB_O_TRUNC) {
7494 switch (create_disp) {
7495 case FILE_CREATE:
7496 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7497 /* Leave create_disp alone as
7498 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7500 /* File exists fail. File not exist create. */
7501 break;
7502 case FILE_OPEN_IF:
7503 /* SMB_O_CREAT | SMB_O_TRUNC */
7504 /* File exists overwrite. File not exist create. */
7505 create_disp = FILE_OVERWRITE_IF;
7506 break;
7507 case FILE_OPEN:
7508 /* SMB_O_TRUNC */
7509 /* File exists overwrite. File not exist fail. */
7510 create_disp = FILE_OVERWRITE;
7511 break;
7512 default:
7513 /* Cannot get here. */
7514 smb_panic("smb_posix_open: logic error");
7515 return NT_STATUS_INVALID_PARAMETER;
7519 raw_unixmode = IVAL(pdata,8);
7520 /* Next 4 bytes are not yet defined. */
7522 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7523 (VALID_STAT(smb_fname->st) ?
7524 PERM_EXISTING_FILE : PERM_NEW_FILE),
7525 &unixmode);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 return status;
7531 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7533 if (wire_open_mode & SMB_O_SYNC) {
7534 create_options |= FILE_WRITE_THROUGH;
7536 if (wire_open_mode & SMB_O_APPEND) {
7537 access_mask |= FILE_APPEND_DATA;
7539 if (wire_open_mode & SMB_O_DIRECT) {
7540 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7543 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7544 VALID_STAT_OF_DIR(smb_fname->st)) {
7545 if (access_mask != SMB_O_RDONLY_MAPPING) {
7546 return NT_STATUS_FILE_IS_A_DIRECTORY;
7548 create_options &= ~FILE_NON_DIRECTORY_FILE;
7549 create_options |= FILE_DIRECTORY_FILE;
7552 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7553 smb_fname_str_dbg(smb_fname),
7554 (unsigned int)wire_open_mode,
7555 (unsigned int)unixmode ));
7557 status = SMB_VFS_CREATE_FILE(
7558 conn, /* conn */
7559 req, /* req */
7560 0, /* root_dir_fid */
7561 smb_fname, /* fname */
7562 access_mask, /* access_mask */
7563 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7564 FILE_SHARE_DELETE),
7565 create_disp, /* create_disposition*/
7566 create_options, /* create_options */
7567 mod_unixmode, /* file_attributes */
7568 oplock_request, /* oplock_request */
7569 0, /* allocation_size */
7570 0, /* private_flags */
7571 NULL, /* sd */
7572 NULL, /* ea_list */
7573 &fsp, /* result */
7574 &info); /* pinfo */
7576 if (!NT_STATUS_IS_OK(status)) {
7577 return status;
7580 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7581 extended_oplock_granted = True;
7584 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7585 extended_oplock_granted = True;
7588 info_level_return = SVAL(pdata,16);
7590 /* Allocate the correct return size. */
7592 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7593 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7594 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7595 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7596 } else {
7597 *pdata_return_size = 12;
7600 /* Realloc the data size */
7601 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7602 if (*ppdata == NULL) {
7603 close_file(req, fsp, ERROR_CLOSE);
7604 *pdata_return_size = 0;
7605 return NT_STATUS_NO_MEMORY;
7607 pdata = *ppdata;
7609 if (extended_oplock_granted) {
7610 if (flags & REQUEST_BATCH_OPLOCK) {
7611 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7612 } else {
7613 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7615 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7616 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7617 } else {
7618 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7621 SSVAL(pdata,2,fsp->fnum);
7622 SIVAL(pdata,4,info); /* Was file created etc. */
7624 switch (info_level_return) {
7625 case SMB_QUERY_FILE_UNIX_BASIC:
7626 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7627 SSVAL(pdata,10,0); /* padding. */
7628 store_file_unix_basic(conn, pdata + 12, fsp,
7629 &smb_fname->st);
7630 break;
7631 case SMB_QUERY_FILE_UNIX_INFO2:
7632 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7633 SSVAL(pdata,10,0); /* padding. */
7634 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7635 &smb_fname->st);
7636 break;
7637 default:
7638 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7639 SSVAL(pdata,10,0); /* padding. */
7640 break;
7642 return NT_STATUS_OK;
7645 /****************************************************************************
7646 Delete a file with POSIX semantics.
7647 ****************************************************************************/
7649 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7650 struct smb_request *req,
7651 const char *pdata,
7652 int total_data,
7653 struct smb_filename *smb_fname)
7655 NTSTATUS status = NT_STATUS_OK;
7656 files_struct *fsp = NULL;
7657 uint16 flags = 0;
7658 char del = 1;
7659 int info = 0;
7660 int create_options = 0;
7661 int i;
7662 struct share_mode_lock *lck = NULL;
7664 if (total_data < 2) {
7665 return NT_STATUS_INVALID_PARAMETER;
7668 flags = SVAL(pdata,0);
7670 if (!VALID_STAT(smb_fname->st)) {
7671 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7674 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7675 !VALID_STAT_OF_DIR(smb_fname->st)) {
7676 return NT_STATUS_NOT_A_DIRECTORY;
7679 DEBUG(10,("smb_posix_unlink: %s %s\n",
7680 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7681 smb_fname_str_dbg(smb_fname)));
7683 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7684 create_options |= FILE_DIRECTORY_FILE;
7687 status = SMB_VFS_CREATE_FILE(
7688 conn, /* conn */
7689 req, /* req */
7690 0, /* root_dir_fid */
7691 smb_fname, /* fname */
7692 DELETE_ACCESS, /* access_mask */
7693 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7694 FILE_SHARE_DELETE),
7695 FILE_OPEN, /* create_disposition*/
7696 create_options, /* create_options */
7697 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7698 0, /* oplock_request */
7699 0, /* allocation_size */
7700 0, /* private_flags */
7701 NULL, /* sd */
7702 NULL, /* ea_list */
7703 &fsp, /* result */
7704 &info); /* pinfo */
7706 if (!NT_STATUS_IS_OK(status)) {
7707 return status;
7711 * Don't lie to client. If we can't really delete due to
7712 * non-POSIX opens return SHARING_VIOLATION.
7715 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7716 if (lck == NULL) {
7717 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7718 "lock for file %s\n", fsp_str_dbg(fsp)));
7719 close_file(req, fsp, NORMAL_CLOSE);
7720 return NT_STATUS_INVALID_PARAMETER;
7724 * See if others still have the file open. If this is the case, then
7725 * don't delete. If all opens are POSIX delete we can set the delete
7726 * on close disposition.
7728 for (i=0; i<lck->data->num_share_modes; i++) {
7729 struct share_mode_entry *e = &lck->data->share_modes[i];
7730 if (is_valid_share_mode_entry(e)) {
7731 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7732 continue;
7734 if (share_mode_stale_pid(lck->data, i)) {
7735 continue;
7737 /* Fail with sharing violation. */
7738 TALLOC_FREE(lck);
7739 close_file(req, fsp, NORMAL_CLOSE);
7740 return NT_STATUS_SHARING_VIOLATION;
7745 * Set the delete on close.
7747 status = smb_set_file_disposition_info(conn,
7748 &del,
7750 fsp,
7751 smb_fname);
7753 TALLOC_FREE(lck);
7755 if (!NT_STATUS_IS_OK(status)) {
7756 close_file(req, fsp, NORMAL_CLOSE);
7757 return status;
7759 return close_file(req, fsp, NORMAL_CLOSE);
7762 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7763 struct smb_request *req,
7764 TALLOC_CTX *mem_ctx,
7765 uint16_t info_level,
7766 files_struct *fsp,
7767 struct smb_filename *smb_fname,
7768 char **ppdata, int total_data,
7769 int *ret_data_size)
7771 char *pdata = *ppdata;
7772 NTSTATUS status = NT_STATUS_OK;
7773 int data_return_size = 0;
7775 *ret_data_size = 0;
7777 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7778 return NT_STATUS_INVALID_LEVEL;
7781 if (!CAN_WRITE(conn)) {
7782 /* Allow POSIX opens. The open path will deny
7783 * any non-readonly opens. */
7784 if (info_level != SMB_POSIX_PATH_OPEN) {
7785 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7789 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7790 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7791 fsp_fnum_dbg(fsp),
7792 info_level, total_data));
7794 switch (info_level) {
7796 case SMB_INFO_STANDARD:
7798 status = smb_set_info_standard(conn,
7799 pdata,
7800 total_data,
7801 fsp,
7802 smb_fname);
7803 break;
7806 case SMB_INFO_SET_EA:
7808 status = smb_info_set_ea(conn,
7809 pdata,
7810 total_data,
7811 fsp,
7812 smb_fname);
7813 break;
7816 case SMB_SET_FILE_BASIC_INFO:
7817 case SMB_FILE_BASIC_INFORMATION:
7819 status = smb_set_file_basic_info(conn,
7820 pdata,
7821 total_data,
7822 fsp,
7823 smb_fname);
7824 break;
7827 case SMB_FILE_ALLOCATION_INFORMATION:
7828 case SMB_SET_FILE_ALLOCATION_INFO:
7830 status = smb_set_file_allocation_info(conn, req,
7831 pdata,
7832 total_data,
7833 fsp,
7834 smb_fname);
7835 break;
7838 case SMB_FILE_END_OF_FILE_INFORMATION:
7839 case SMB_SET_FILE_END_OF_FILE_INFO:
7842 * XP/Win7 both fail after the createfile with
7843 * SMB_SET_FILE_END_OF_FILE_INFO but not
7844 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7845 * The level is known here, so pass it down
7846 * appropriately.
7848 bool should_fail =
7849 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7851 status = smb_set_file_end_of_file_info(conn, req,
7852 pdata,
7853 total_data,
7854 fsp,
7855 smb_fname,
7856 should_fail);
7857 break;
7860 case SMB_FILE_DISPOSITION_INFORMATION:
7861 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7863 #if 0
7864 /* JRA - We used to just ignore this on a path ?
7865 * Shouldn't this be invalid level on a pathname
7866 * based call ?
7868 if (tran_call != TRANSACT2_SETFILEINFO) {
7869 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7871 #endif
7872 status = smb_set_file_disposition_info(conn,
7873 pdata,
7874 total_data,
7875 fsp,
7876 smb_fname);
7877 break;
7880 case SMB_FILE_POSITION_INFORMATION:
7882 status = smb_file_position_information(conn,
7883 pdata,
7884 total_data,
7885 fsp);
7886 break;
7889 case SMB_FILE_FULL_EA_INFORMATION:
7891 status = smb_set_file_full_ea_info(conn,
7892 pdata,
7893 total_data,
7894 fsp);
7895 break;
7898 /* From tridge Samba4 :
7899 * MODE_INFORMATION in setfileinfo (I have no
7900 * idea what "mode information" on a file is - it takes a value of 0,
7901 * 2, 4 or 6. What could it be?).
7904 case SMB_FILE_MODE_INFORMATION:
7906 status = smb_file_mode_information(conn,
7907 pdata,
7908 total_data);
7909 break;
7913 * CIFS UNIX extensions.
7916 case SMB_SET_FILE_UNIX_BASIC:
7918 status = smb_set_file_unix_basic(conn, req,
7919 pdata,
7920 total_data,
7921 fsp,
7922 smb_fname);
7923 break;
7926 case SMB_SET_FILE_UNIX_INFO2:
7928 status = smb_set_file_unix_info2(conn, req,
7929 pdata,
7930 total_data,
7931 fsp,
7932 smb_fname);
7933 break;
7936 case SMB_SET_FILE_UNIX_LINK:
7938 if (fsp) {
7939 /* We must have a pathname for this. */
7940 return NT_STATUS_INVALID_LEVEL;
7942 status = smb_set_file_unix_link(conn, req, pdata,
7943 total_data, smb_fname);
7944 break;
7947 case SMB_SET_FILE_UNIX_HLINK:
7949 if (fsp) {
7950 /* We must have a pathname for this. */
7951 return NT_STATUS_INVALID_LEVEL;
7953 status = smb_set_file_unix_hlink(conn, req,
7954 pdata, total_data,
7955 smb_fname);
7956 break;
7959 case SMB_FILE_RENAME_INFORMATION:
7961 status = smb_file_rename_information(conn, req,
7962 pdata, total_data,
7963 fsp, smb_fname);
7964 break;
7967 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7969 /* SMB2 rename information. */
7970 status = smb2_file_rename_information(conn, req,
7971 pdata, total_data,
7972 fsp, smb_fname);
7973 break;
7976 case SMB_FILE_LINK_INFORMATION:
7978 status = smb_file_link_information(conn, req,
7979 pdata, total_data,
7980 fsp, smb_fname);
7981 break;
7984 #if defined(HAVE_POSIX_ACLS)
7985 case SMB_SET_POSIX_ACL:
7987 status = smb_set_posix_acl(conn,
7988 pdata,
7989 total_data,
7990 fsp,
7991 smb_fname);
7992 break;
7994 #endif
7996 case SMB_SET_POSIX_LOCK:
7998 if (!fsp) {
7999 return NT_STATUS_INVALID_LEVEL;
8001 status = smb_set_posix_lock(conn, req,
8002 pdata, total_data, fsp);
8003 break;
8006 case SMB_POSIX_PATH_OPEN:
8008 if (fsp) {
8009 /* We must have a pathname for this. */
8010 return NT_STATUS_INVALID_LEVEL;
8013 status = smb_posix_open(conn, req,
8014 ppdata,
8015 total_data,
8016 smb_fname,
8017 &data_return_size);
8018 break;
8021 case SMB_POSIX_PATH_UNLINK:
8023 if (fsp) {
8024 /* We must have a pathname for this. */
8025 return NT_STATUS_INVALID_LEVEL;
8028 status = smb_posix_unlink(conn, req,
8029 pdata,
8030 total_data,
8031 smb_fname);
8032 break;
8035 default:
8036 return NT_STATUS_INVALID_LEVEL;
8039 if (!NT_STATUS_IS_OK(status)) {
8040 return status;
8043 *ret_data_size = data_return_size;
8044 return NT_STATUS_OK;
8047 /****************************************************************************
8048 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8049 ****************************************************************************/
8051 static void call_trans2setfilepathinfo(connection_struct *conn,
8052 struct smb_request *req,
8053 unsigned int tran_call,
8054 char **pparams, int total_params,
8055 char **ppdata, int total_data,
8056 unsigned int max_data_bytes)
8058 char *params = *pparams;
8059 char *pdata = *ppdata;
8060 uint16 info_level;
8061 struct smb_filename *smb_fname = NULL;
8062 files_struct *fsp = NULL;
8063 NTSTATUS status = NT_STATUS_OK;
8064 int data_return_size = 0;
8066 if (!params) {
8067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8068 return;
8071 if (tran_call == TRANSACT2_SETFILEINFO) {
8072 if (total_params < 4) {
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 return;
8077 fsp = file_fsp(req, SVAL(params,0));
8078 /* Basic check for non-null fsp. */
8079 if (!check_fsp_open(conn, req, fsp)) {
8080 return;
8082 info_level = SVAL(params,2);
8084 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8085 if (smb_fname == NULL) {
8086 reply_nterror(req, NT_STATUS_NO_MEMORY);
8087 return;
8090 if(fsp->fh->fd == -1) {
8092 * This is actually a SETFILEINFO on a directory
8093 * handle (returned from an NT SMB). NT5.0 seems
8094 * to do this call. JRA.
8096 if (INFO_LEVEL_IS_UNIX(info_level)) {
8097 /* Always do lstat for UNIX calls. */
8098 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8099 DEBUG(3,("call_trans2setfilepathinfo: "
8100 "SMB_VFS_LSTAT of %s failed "
8101 "(%s)\n",
8102 smb_fname_str_dbg(smb_fname),
8103 strerror(errno)));
8104 reply_nterror(req, map_nt_error_from_unix(errno));
8105 return;
8107 } else {
8108 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8109 DEBUG(3,("call_trans2setfilepathinfo: "
8110 "fileinfo of %s failed (%s)\n",
8111 smb_fname_str_dbg(smb_fname),
8112 strerror(errno)));
8113 reply_nterror(req, map_nt_error_from_unix(errno));
8114 return;
8117 } else if (fsp->print_file) {
8119 * Doing a DELETE_ON_CLOSE should cancel a print job.
8121 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8122 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8124 DEBUG(3,("call_trans2setfilepathinfo: "
8125 "Cancelling print job (%s)\n",
8126 fsp_str_dbg(fsp)));
8128 SSVAL(params,0,0);
8129 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8130 *ppdata, 0,
8131 max_data_bytes);
8132 return;
8133 } else {
8134 reply_nterror(req,
8135 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8136 return;
8138 } else {
8140 * Original code - this is an open file.
8142 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8143 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8144 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8145 strerror(errno)));
8146 reply_nterror(req, map_nt_error_from_unix(errno));
8147 return;
8150 } else {
8151 char *fname = NULL;
8152 uint32_t ucf_flags = 0;
8154 /* set path info */
8155 if (total_params < 7) {
8156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8157 return;
8160 info_level = SVAL(params,0);
8161 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8162 total_params - 6, STR_TERMINATE,
8163 &status);
8164 if (!NT_STATUS_IS_OK(status)) {
8165 reply_nterror(req, status);
8166 return;
8169 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8170 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8171 info_level == SMB_FILE_RENAME_INFORMATION ||
8172 info_level == SMB_POSIX_PATH_UNLINK) {
8173 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8176 status = filename_convert(req, conn,
8177 req->flags2 & FLAGS2_DFS_PATHNAMES,
8178 fname,
8179 ucf_flags,
8180 NULL,
8181 &smb_fname);
8182 if (!NT_STATUS_IS_OK(status)) {
8183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8184 reply_botherror(req,
8185 NT_STATUS_PATH_NOT_COVERED,
8186 ERRSRV, ERRbadpath);
8187 return;
8189 reply_nterror(req, status);
8190 return;
8193 if (INFO_LEVEL_IS_UNIX(info_level)) {
8195 * For CIFS UNIX extensions the target name may not exist.
8198 /* Always do lstat for UNIX calls. */
8199 SMB_VFS_LSTAT(conn, smb_fname);
8201 } else if (!VALID_STAT(smb_fname->st) &&
8202 SMB_VFS_STAT(conn, smb_fname)) {
8203 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8204 "%s failed (%s)\n",
8205 smb_fname_str_dbg(smb_fname),
8206 strerror(errno)));
8207 reply_nterror(req, map_nt_error_from_unix(errno));
8208 return;
8212 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8213 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8214 fsp_fnum_dbg(fsp),
8215 info_level,total_data));
8217 /* Realloc the parameter size */
8218 *pparams = (char *)SMB_REALLOC(*pparams,2);
8219 if (*pparams == NULL) {
8220 reply_nterror(req, NT_STATUS_NO_MEMORY);
8221 return;
8223 params = *pparams;
8225 SSVAL(params,0,0);
8227 status = smbd_do_setfilepathinfo(conn, req, req,
8228 info_level,
8229 fsp,
8230 smb_fname,
8231 ppdata, total_data,
8232 &data_return_size);
8233 if (!NT_STATUS_IS_OK(status)) {
8234 if (open_was_deferred(req->sconn, req->mid)) {
8235 /* We have re-scheduled this call. */
8236 return;
8238 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8239 /* We have re-scheduled this call. */
8240 return;
8242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8244 ERRSRV, ERRbadpath);
8245 return;
8247 if (info_level == SMB_POSIX_PATH_OPEN) {
8248 reply_openerror(req, status);
8249 return;
8253 * Invalid EA name needs to return 2 param bytes,
8254 * not a zero-length error packet.
8256 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8257 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8258 max_data_bytes);
8259 } else {
8260 reply_nterror(req, status);
8262 return;
8265 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8266 max_data_bytes);
8268 return;
8271 /****************************************************************************
8272 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8273 ****************************************************************************/
8275 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8276 char **pparams, int total_params,
8277 char **ppdata, int total_data,
8278 unsigned int max_data_bytes)
8280 struct smb_filename *smb_dname = NULL;
8281 char *params = *pparams;
8282 char *pdata = *ppdata;
8283 char *directory = NULL;
8284 NTSTATUS status = NT_STATUS_OK;
8285 struct ea_list *ea_list = NULL;
8286 TALLOC_CTX *ctx = talloc_tos();
8288 if (!CAN_WRITE(conn)) {
8289 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8290 return;
8293 if (total_params < 5) {
8294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8295 return;
8298 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8299 total_params - 4, STR_TERMINATE,
8300 &status);
8301 if (!NT_STATUS_IS_OK(status)) {
8302 reply_nterror(req, status);
8303 return;
8306 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8308 status = filename_convert(ctx,
8309 conn,
8310 req->flags2 & FLAGS2_DFS_PATHNAMES,
8311 directory,
8313 NULL,
8314 &smb_dname);
8316 if (!NT_STATUS_IS_OK(status)) {
8317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8318 reply_botherror(req,
8319 NT_STATUS_PATH_NOT_COVERED,
8320 ERRSRV, ERRbadpath);
8321 return;
8323 reply_nterror(req, status);
8324 return;
8328 * OS/2 workplace shell seems to send SET_EA requests of "null"
8329 * length (4 bytes containing IVAL 4).
8330 * They seem to have no effect. Bug #3212. JRA.
8333 if (total_data && (total_data != 4)) {
8334 /* Any data in this call is an EA list. */
8335 if (total_data < 10) {
8336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8337 goto out;
8340 if (IVAL(pdata,0) > total_data) {
8341 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8342 IVAL(pdata,0), (unsigned int)total_data));
8343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8344 goto out;
8347 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8348 total_data - 4);
8349 if (!ea_list) {
8350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8351 goto out;
8354 if (!lp_ea_support(SNUM(conn))) {
8355 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8356 goto out;
8359 /* If total_data == 4 Windows doesn't care what values
8360 * are placed in that field, it just ignores them.
8361 * The System i QNTC IBM SMB client puts bad values here,
8362 * so ignore them. */
8364 status = create_directory(conn, req, smb_dname);
8366 if (!NT_STATUS_IS_OK(status)) {
8367 reply_nterror(req, status);
8368 goto out;
8371 /* Try and set any given EA. */
8372 if (ea_list) {
8373 status = set_ea(conn, NULL, smb_dname, ea_list);
8374 if (!NT_STATUS_IS_OK(status)) {
8375 reply_nterror(req, status);
8376 goto out;
8380 /* Realloc the parameter and data sizes */
8381 *pparams = (char *)SMB_REALLOC(*pparams,2);
8382 if(*pparams == NULL) {
8383 reply_nterror(req, NT_STATUS_NO_MEMORY);
8384 goto out;
8386 params = *pparams;
8388 SSVAL(params,0,0);
8390 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8392 out:
8393 TALLOC_FREE(smb_dname);
8394 return;
8397 /****************************************************************************
8398 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8399 We don't actually do this - we just send a null response.
8400 ****************************************************************************/
8402 static void call_trans2findnotifyfirst(connection_struct *conn,
8403 struct smb_request *req,
8404 char **pparams, int total_params,
8405 char **ppdata, int total_data,
8406 unsigned int max_data_bytes)
8408 char *params = *pparams;
8409 uint16 info_level;
8411 if (total_params < 6) {
8412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8413 return;
8416 info_level = SVAL(params,4);
8417 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8419 switch (info_level) {
8420 case 1:
8421 case 2:
8422 break;
8423 default:
8424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8425 return;
8428 /* Realloc the parameter and data sizes */
8429 *pparams = (char *)SMB_REALLOC(*pparams,6);
8430 if (*pparams == NULL) {
8431 reply_nterror(req, NT_STATUS_NO_MEMORY);
8432 return;
8434 params = *pparams;
8436 SSVAL(params,0,fnf_handle);
8437 SSVAL(params,2,0); /* No changes */
8438 SSVAL(params,4,0); /* No EA errors */
8440 fnf_handle++;
8442 if(fnf_handle == 0)
8443 fnf_handle = 257;
8445 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8447 return;
8450 /****************************************************************************
8451 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8452 changes). Currently this does nothing.
8453 ****************************************************************************/
8455 static void call_trans2findnotifynext(connection_struct *conn,
8456 struct smb_request *req,
8457 char **pparams, int total_params,
8458 char **ppdata, int total_data,
8459 unsigned int max_data_bytes)
8461 char *params = *pparams;
8463 DEBUG(3,("call_trans2findnotifynext\n"));
8465 /* Realloc the parameter and data sizes */
8466 *pparams = (char *)SMB_REALLOC(*pparams,4);
8467 if (*pparams == NULL) {
8468 reply_nterror(req, NT_STATUS_NO_MEMORY);
8469 return;
8471 params = *pparams;
8473 SSVAL(params,0,0); /* No changes */
8474 SSVAL(params,2,0); /* No EA errors */
8476 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8478 return;
8481 /****************************************************************************
8482 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8483 ****************************************************************************/
8485 static void call_trans2getdfsreferral(connection_struct *conn,
8486 struct smb_request *req,
8487 char **pparams, int total_params,
8488 char **ppdata, int total_data,
8489 unsigned int max_data_bytes)
8491 char *params = *pparams;
8492 char *pathname = NULL;
8493 int reply_size = 0;
8494 int max_referral_level;
8495 NTSTATUS status = NT_STATUS_OK;
8496 TALLOC_CTX *ctx = talloc_tos();
8498 DEBUG(10,("call_trans2getdfsreferral\n"));
8500 if (total_params < 3) {
8501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8502 return;
8505 max_referral_level = SVAL(params,0);
8507 if(!lp_host_msdfs()) {
8508 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8509 return;
8512 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8513 total_params - 2, STR_TERMINATE);
8514 if (!pathname) {
8515 reply_nterror(req, NT_STATUS_NOT_FOUND);
8516 return;
8518 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8519 ppdata,&status)) < 0) {
8520 reply_nterror(req, status);
8521 return;
8524 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8525 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8526 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8528 return;
8531 #define LMCAT_SPL 0x53
8532 #define LMFUNC_GETJOBID 0x60
8534 /****************************************************************************
8535 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8536 ****************************************************************************/
8538 static void call_trans2ioctl(connection_struct *conn,
8539 struct smb_request *req,
8540 char **pparams, int total_params,
8541 char **ppdata, int total_data,
8542 unsigned int max_data_bytes)
8544 char *pdata = *ppdata;
8545 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8547 /* check for an invalid fid before proceeding */
8549 if (!fsp) {
8550 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8551 return;
8554 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8555 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8556 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8557 if (*ppdata == NULL) {
8558 reply_nterror(req, NT_STATUS_NO_MEMORY);
8559 return;
8561 pdata = *ppdata;
8563 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8564 CAN ACCEPT THIS IN UNICODE. JRA. */
8566 /* Job number */
8567 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8569 srvstr_push(pdata, req->flags2, pdata + 2,
8570 lp_netbios_name(), 15,
8571 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8572 srvstr_push(pdata, req->flags2, pdata+18,
8573 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8574 STR_ASCII|STR_TERMINATE); /* Service name */
8575 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8576 max_data_bytes);
8577 return;
8580 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8581 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8584 /****************************************************************************
8585 Reply to a SMBfindclose (stop trans2 directory search).
8586 ****************************************************************************/
8588 void reply_findclose(struct smb_request *req)
8590 int dptr_num;
8591 struct smbd_server_connection *sconn = req->sconn;
8593 START_PROFILE(SMBfindclose);
8595 if (req->wct < 1) {
8596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8597 END_PROFILE(SMBfindclose);
8598 return;
8601 dptr_num = SVALS(req->vwv+0, 0);
8603 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8605 dptr_close(sconn, &dptr_num);
8607 reply_outbuf(req, 0, 0);
8609 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8611 END_PROFILE(SMBfindclose);
8612 return;
8615 /****************************************************************************
8616 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8617 ****************************************************************************/
8619 void reply_findnclose(struct smb_request *req)
8621 int dptr_num;
8623 START_PROFILE(SMBfindnclose);
8625 if (req->wct < 1) {
8626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8627 END_PROFILE(SMBfindnclose);
8628 return;
8631 dptr_num = SVAL(req->vwv+0, 0);
8633 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8635 /* We never give out valid handles for a
8636 findnotifyfirst - so any dptr_num is ok here.
8637 Just ignore it. */
8639 reply_outbuf(req, 0, 0);
8641 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8643 END_PROFILE(SMBfindnclose);
8644 return;
8647 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8648 struct trans_state *state)
8650 if (get_Protocol() >= PROTOCOL_NT1) {
8651 req->flags2 |= 0x40; /* IS_LONG_NAME */
8652 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8655 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8656 if (state->call != TRANSACT2_QFSINFO &&
8657 state->call != TRANSACT2_SETFSINFO) {
8658 DEBUG(0,("handle_trans2: encryption required "
8659 "with call 0x%x\n",
8660 (unsigned int)state->call));
8661 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8662 return;
8666 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8668 /* Now we must call the relevant TRANS2 function */
8669 switch(state->call) {
8670 case TRANSACT2_OPEN:
8672 START_PROFILE(Trans2_open);
8673 call_trans2open(conn, req,
8674 &state->param, state->total_param,
8675 &state->data, state->total_data,
8676 state->max_data_return);
8677 END_PROFILE(Trans2_open);
8678 break;
8681 case TRANSACT2_FINDFIRST:
8683 START_PROFILE(Trans2_findfirst);
8684 call_trans2findfirst(conn, req,
8685 &state->param, state->total_param,
8686 &state->data, state->total_data,
8687 state->max_data_return);
8688 END_PROFILE(Trans2_findfirst);
8689 break;
8692 case TRANSACT2_FINDNEXT:
8694 START_PROFILE(Trans2_findnext);
8695 call_trans2findnext(conn, req,
8696 &state->param, state->total_param,
8697 &state->data, state->total_data,
8698 state->max_data_return);
8699 END_PROFILE(Trans2_findnext);
8700 break;
8703 case TRANSACT2_QFSINFO:
8705 START_PROFILE(Trans2_qfsinfo);
8706 call_trans2qfsinfo(conn, req,
8707 &state->param, state->total_param,
8708 &state->data, state->total_data,
8709 state->max_data_return);
8710 END_PROFILE(Trans2_qfsinfo);
8711 break;
8714 case TRANSACT2_SETFSINFO:
8716 START_PROFILE(Trans2_setfsinfo);
8717 call_trans2setfsinfo(conn, req,
8718 &state->param, state->total_param,
8719 &state->data, state->total_data,
8720 state->max_data_return);
8721 END_PROFILE(Trans2_setfsinfo);
8722 break;
8725 case TRANSACT2_QPATHINFO:
8726 case TRANSACT2_QFILEINFO:
8728 START_PROFILE(Trans2_qpathinfo);
8729 call_trans2qfilepathinfo(conn, req, state->call,
8730 &state->param, state->total_param,
8731 &state->data, state->total_data,
8732 state->max_data_return);
8733 END_PROFILE(Trans2_qpathinfo);
8734 break;
8737 case TRANSACT2_SETPATHINFO:
8738 case TRANSACT2_SETFILEINFO:
8740 START_PROFILE(Trans2_setpathinfo);
8741 call_trans2setfilepathinfo(conn, req, state->call,
8742 &state->param, state->total_param,
8743 &state->data, state->total_data,
8744 state->max_data_return);
8745 END_PROFILE(Trans2_setpathinfo);
8746 break;
8749 case TRANSACT2_FINDNOTIFYFIRST:
8751 START_PROFILE(Trans2_findnotifyfirst);
8752 call_trans2findnotifyfirst(conn, req,
8753 &state->param, state->total_param,
8754 &state->data, state->total_data,
8755 state->max_data_return);
8756 END_PROFILE(Trans2_findnotifyfirst);
8757 break;
8760 case TRANSACT2_FINDNOTIFYNEXT:
8762 START_PROFILE(Trans2_findnotifynext);
8763 call_trans2findnotifynext(conn, req,
8764 &state->param, state->total_param,
8765 &state->data, state->total_data,
8766 state->max_data_return);
8767 END_PROFILE(Trans2_findnotifynext);
8768 break;
8771 case TRANSACT2_MKDIR:
8773 START_PROFILE(Trans2_mkdir);
8774 call_trans2mkdir(conn, req,
8775 &state->param, state->total_param,
8776 &state->data, state->total_data,
8777 state->max_data_return);
8778 END_PROFILE(Trans2_mkdir);
8779 break;
8782 case TRANSACT2_GET_DFS_REFERRAL:
8784 START_PROFILE(Trans2_get_dfs_referral);
8785 call_trans2getdfsreferral(conn, req,
8786 &state->param, state->total_param,
8787 &state->data, state->total_data,
8788 state->max_data_return);
8789 END_PROFILE(Trans2_get_dfs_referral);
8790 break;
8793 case TRANSACT2_IOCTL:
8795 START_PROFILE(Trans2_ioctl);
8796 call_trans2ioctl(conn, req,
8797 &state->param, state->total_param,
8798 &state->data, state->total_data,
8799 state->max_data_return);
8800 END_PROFILE(Trans2_ioctl);
8801 break;
8804 default:
8805 /* Error in request */
8806 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8807 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8811 /****************************************************************************
8812 Reply to a SMBtrans2.
8813 ****************************************************************************/
8815 void reply_trans2(struct smb_request *req)
8817 connection_struct *conn = req->conn;
8818 unsigned int dsoff;
8819 unsigned int dscnt;
8820 unsigned int psoff;
8821 unsigned int pscnt;
8822 unsigned int tran_call;
8823 struct trans_state *state;
8824 NTSTATUS result;
8826 START_PROFILE(SMBtrans2);
8828 if (req->wct < 14) {
8829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8830 END_PROFILE(SMBtrans2);
8831 return;
8834 dsoff = SVAL(req->vwv+12, 0);
8835 dscnt = SVAL(req->vwv+11, 0);
8836 psoff = SVAL(req->vwv+10, 0);
8837 pscnt = SVAL(req->vwv+9, 0);
8838 tran_call = SVAL(req->vwv+14, 0);
8840 result = allow_new_trans(conn->pending_trans, req->mid);
8841 if (!NT_STATUS_IS_OK(result)) {
8842 DEBUG(2, ("Got invalid trans2 request: %s\n",
8843 nt_errstr(result)));
8844 reply_nterror(req, result);
8845 END_PROFILE(SMBtrans2);
8846 return;
8849 if (IS_IPC(conn)) {
8850 switch (tran_call) {
8851 /* List the allowed trans2 calls on IPC$ */
8852 case TRANSACT2_OPEN:
8853 case TRANSACT2_GET_DFS_REFERRAL:
8854 case TRANSACT2_QFILEINFO:
8855 case TRANSACT2_QFSINFO:
8856 case TRANSACT2_SETFSINFO:
8857 break;
8858 default:
8859 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8860 END_PROFILE(SMBtrans2);
8861 return;
8865 if ((state = talloc(conn, struct trans_state)) == NULL) {
8866 DEBUG(0, ("talloc failed\n"));
8867 reply_nterror(req, NT_STATUS_NO_MEMORY);
8868 END_PROFILE(SMBtrans2);
8869 return;
8872 state->cmd = SMBtrans2;
8874 state->mid = req->mid;
8875 state->vuid = req->vuid;
8876 state->setup_count = SVAL(req->vwv+13, 0);
8877 state->setup = NULL;
8878 state->total_param = SVAL(req->vwv+0, 0);
8879 state->param = NULL;
8880 state->total_data = SVAL(req->vwv+1, 0);
8881 state->data = NULL;
8882 state->max_param_return = SVAL(req->vwv+2, 0);
8883 state->max_data_return = SVAL(req->vwv+3, 0);
8884 state->max_setup_return = SVAL(req->vwv+4, 0);
8885 state->close_on_completion = BITSETW(req->vwv+5, 0);
8886 state->one_way = BITSETW(req->vwv+5, 1);
8888 state->call = tran_call;
8890 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8891 is so as a sanity check */
8892 if (state->setup_count != 1) {
8894 * Need to have rc=0 for ioctl to get job id for OS/2.
8895 * Network printing will fail if function is not successful.
8896 * Similar function in reply.c will be used if protocol
8897 * is LANMAN1.0 instead of LM1.2X002.
8898 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8899 * outbuf doesn't have to be set(only job id is used).
8901 if ( (state->setup_count == 4)
8902 && (tran_call == TRANSACT2_IOCTL)
8903 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8904 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8905 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8906 } else {
8907 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8908 DEBUG(2,("Transaction is %d\n",tran_call));
8909 TALLOC_FREE(state);
8910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8911 END_PROFILE(SMBtrans2);
8912 return;
8916 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8917 goto bad_param;
8919 if (state->total_data) {
8921 if (trans_oob(state->total_data, 0, dscnt)
8922 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8923 goto bad_param;
8926 /* Can't use talloc here, the core routines do realloc on the
8927 * params and data. */
8928 state->data = (char *)SMB_MALLOC(state->total_data);
8929 if (state->data == NULL) {
8930 DEBUG(0,("reply_trans2: data malloc fail for %u "
8931 "bytes !\n", (unsigned int)state->total_data));
8932 TALLOC_FREE(state);
8933 reply_nterror(req, NT_STATUS_NO_MEMORY);
8934 END_PROFILE(SMBtrans2);
8935 return;
8938 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8941 if (state->total_param) {
8943 if (trans_oob(state->total_param, 0, pscnt)
8944 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8945 goto bad_param;
8948 /* Can't use talloc here, the core routines do realloc on the
8949 * params and data. */
8950 state->param = (char *)SMB_MALLOC(state->total_param);
8951 if (state->param == NULL) {
8952 DEBUG(0,("reply_trans: param malloc fail for %u "
8953 "bytes !\n", (unsigned int)state->total_param));
8954 SAFE_FREE(state->data);
8955 TALLOC_FREE(state);
8956 reply_nterror(req, NT_STATUS_NO_MEMORY);
8957 END_PROFILE(SMBtrans2);
8958 return;
8961 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8964 state->received_data = dscnt;
8965 state->received_param = pscnt;
8967 if ((state->received_param == state->total_param) &&
8968 (state->received_data == state->total_data)) {
8970 handle_trans2(conn, req, state);
8972 SAFE_FREE(state->data);
8973 SAFE_FREE(state->param);
8974 TALLOC_FREE(state);
8975 END_PROFILE(SMBtrans2);
8976 return;
8979 DLIST_ADD(conn->pending_trans, state);
8981 /* We need to send an interim response then receive the rest
8982 of the parameter/data bytes */
8983 reply_outbuf(req, 0, 0);
8984 show_msg((char *)req->outbuf);
8985 END_PROFILE(SMBtrans2);
8986 return;
8988 bad_param:
8990 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8991 SAFE_FREE(state->data);
8992 SAFE_FREE(state->param);
8993 TALLOC_FREE(state);
8994 END_PROFILE(SMBtrans2);
8995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8999 /****************************************************************************
9000 Reply to a SMBtranss2
9001 ****************************************************************************/
9003 void reply_transs2(struct smb_request *req)
9005 connection_struct *conn = req->conn;
9006 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9007 struct trans_state *state;
9009 START_PROFILE(SMBtranss2);
9011 show_msg((const char *)req->inbuf);
9013 /* Windows clients expect all replies to
9014 a transact secondary (SMBtranss2 0x33)
9015 to have a command code of transact
9016 (SMBtrans2 0x32). See bug #8989
9017 and also [MS-CIFS] section 2.2.4.47.2
9018 for details.
9020 req->cmd = SMBtrans2;
9022 if (req->wct < 8) {
9023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9024 END_PROFILE(SMBtranss2);
9025 return;
9028 for (state = conn->pending_trans; state != NULL;
9029 state = state->next) {
9030 if (state->mid == req->mid) {
9031 break;
9035 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9037 END_PROFILE(SMBtranss2);
9038 return;
9041 /* Revise state->total_param and state->total_data in case they have
9042 changed downwards */
9044 if (SVAL(req->vwv+0, 0) < state->total_param)
9045 state->total_param = SVAL(req->vwv+0, 0);
9046 if (SVAL(req->vwv+1, 0) < state->total_data)
9047 state->total_data = SVAL(req->vwv+1, 0);
9049 pcnt = SVAL(req->vwv+2, 0);
9050 poff = SVAL(req->vwv+3, 0);
9051 pdisp = SVAL(req->vwv+4, 0);
9053 dcnt = SVAL(req->vwv+5, 0);
9054 doff = SVAL(req->vwv+6, 0);
9055 ddisp = SVAL(req->vwv+7, 0);
9057 state->received_param += pcnt;
9058 state->received_data += dcnt;
9060 if ((state->received_data > state->total_data) ||
9061 (state->received_param > state->total_param))
9062 goto bad_param;
9064 if (pcnt) {
9065 if (trans_oob(state->total_param, pdisp, pcnt)
9066 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9067 goto bad_param;
9069 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9072 if (dcnt) {
9073 if (trans_oob(state->total_data, ddisp, dcnt)
9074 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9075 goto bad_param;
9077 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9080 if ((state->received_param < state->total_param) ||
9081 (state->received_data < state->total_data)) {
9082 END_PROFILE(SMBtranss2);
9083 return;
9086 handle_trans2(conn, req, state);
9088 DLIST_REMOVE(conn->pending_trans, state);
9089 SAFE_FREE(state->data);
9090 SAFE_FREE(state->param);
9091 TALLOC_FREE(state);
9093 END_PROFILE(SMBtranss2);
9094 return;
9096 bad_param:
9098 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9099 DLIST_REMOVE(conn->pending_trans, state);
9100 SAFE_FREE(state->data);
9101 SAFE_FREE(state->param);
9102 TALLOC_FREE(state);
9103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9104 END_PROFILE(SMBtranss2);
9105 return;