s3:vfs: add SMB_VFS_READDIR_ATTR()
[Samba.git] / source3 / smbd / trans2.c
blob60128efdf3a794f5f6272b322ad00d2e019d7101
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 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, ("%s: ea_namelist size = %u\n",
262 __func__, (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 smbXsrv_connection *xconn = req->xconn;
863 int max_send = xconn->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(xconn,
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(xconn,
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 NULL, /* lease */
1225 open_size, /* allocation_size */
1226 private_flags,
1227 NULL, /* sd */
1228 ea_list, /* ea_list */
1229 &fsp, /* result */
1230 &smb_action); /* psbuf */
1232 if (!NT_STATUS_IS_OK(status)) {
1233 if (open_was_deferred(req->xconn, req->mid)) {
1234 /* We have re-scheduled this call. */
1235 goto out;
1237 reply_openerror(req, status);
1238 goto out;
1241 size = get_file_size_stat(&smb_fname->st);
1242 fattr = dos_mode(conn, smb_fname);
1243 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1244 inode = smb_fname->st.st_ex_ino;
1245 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1246 close_file(req, fsp, ERROR_CLOSE);
1247 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1248 goto out;
1251 /* Realloc the size of parameters and data we will return */
1252 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1253 if(*pparams == NULL ) {
1254 reply_nterror(req, NT_STATUS_NO_MEMORY);
1255 goto out;
1257 params = *pparams;
1259 SSVAL(params,0,fsp->fnum);
1260 SSVAL(params,2,fattr);
1261 srv_put_dos_date2(params,4, mtime);
1262 SIVAL(params,8, (uint32)size);
1263 SSVAL(params,12,deny_mode);
1264 SSVAL(params,14,0); /* open_type - file or directory. */
1265 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1267 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1268 smb_action |= EXTENDED_OPLOCK_GRANTED;
1271 SSVAL(params,18,smb_action);
1274 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1276 SIVAL(params,20,inode);
1277 SSVAL(params,24,0); /* Padding. */
1278 if (flags & 8) {
1279 uint32 ea_size = estimate_ea_size(conn, fsp,
1280 smb_fname);
1281 SIVAL(params, 26, ea_size);
1282 } else {
1283 SIVAL(params, 26, 0);
1286 /* Send the required number of replies */
1287 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1288 out:
1289 TALLOC_FREE(smb_fname);
1292 /*********************************************************
1293 Routine to check if a given string matches exactly.
1294 as a special case a mask of "." does NOT match. That
1295 is required for correct wildcard semantics
1296 Case can be significant or not.
1297 **********************************************************/
1299 static bool exact_match(bool has_wild,
1300 bool case_sensitive,
1301 const char *str,
1302 const char *mask)
1304 if (mask[0] == '.' && mask[1] == 0) {
1305 return false;
1308 if (has_wild) {
1309 return false;
1312 if (case_sensitive) {
1313 return strcmp(str,mask)==0;
1314 } else {
1315 return strcasecmp_m(str,mask) == 0;
1319 /****************************************************************************
1320 Return the filetype for UNIX extensions.
1321 ****************************************************************************/
1323 static uint32 unix_filetype(mode_t mode)
1325 if(S_ISREG(mode))
1326 return UNIX_TYPE_FILE;
1327 else if(S_ISDIR(mode))
1328 return UNIX_TYPE_DIR;
1329 #ifdef S_ISLNK
1330 else if(S_ISLNK(mode))
1331 return UNIX_TYPE_SYMLINK;
1332 #endif
1333 #ifdef S_ISCHR
1334 else if(S_ISCHR(mode))
1335 return UNIX_TYPE_CHARDEV;
1336 #endif
1337 #ifdef S_ISBLK
1338 else if(S_ISBLK(mode))
1339 return UNIX_TYPE_BLKDEV;
1340 #endif
1341 #ifdef S_ISFIFO
1342 else if(S_ISFIFO(mode))
1343 return UNIX_TYPE_FIFO;
1344 #endif
1345 #ifdef S_ISSOCK
1346 else if(S_ISSOCK(mode))
1347 return UNIX_TYPE_SOCKET;
1348 #endif
1350 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1351 return UNIX_TYPE_UNKNOWN;
1354 /****************************************************************************
1355 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1356 ****************************************************************************/
1358 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1360 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1361 const SMB_STRUCT_STAT *psbuf,
1362 uint32 perms,
1363 enum perm_type ptype,
1364 mode_t *ret_perms)
1366 mode_t ret = 0;
1368 if (perms == SMB_MODE_NO_CHANGE) {
1369 if (!VALID_STAT(*psbuf)) {
1370 return NT_STATUS_INVALID_PARAMETER;
1371 } else {
1372 *ret_perms = psbuf->st_ex_mode;
1373 return NT_STATUS_OK;
1377 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1378 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1379 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1380 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1381 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1382 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1383 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1384 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1385 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1386 #ifdef S_ISVTX
1387 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1388 #endif
1389 #ifdef S_ISGID
1390 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1391 #endif
1392 #ifdef S_ISUID
1393 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1394 #endif
1396 if (ptype == PERM_NEW_FILE) {
1398 * "create mask"/"force create mode" are
1399 * only applied to new files, not existing ones.
1401 ret &= lp_create_mask(SNUM(conn));
1402 /* Add in force bits */
1403 ret |= lp_force_create_mode(SNUM(conn));
1404 } else if (ptype == PERM_NEW_DIR) {
1406 * "directory mask"/"force directory mode" are
1407 * only applied to new directories, not existing ones.
1409 ret &= lp_directory_mask(SNUM(conn));
1410 /* Add in force bits */
1411 ret |= lp_force_directory_mode(SNUM(conn));
1414 *ret_perms = ret;
1415 return NT_STATUS_OK;
1418 /****************************************************************************
1419 Needed to show the msdfs symlinks as directories. Modifies psbuf
1420 to be a directory if it's a msdfs link.
1421 ****************************************************************************/
1423 static bool check_msdfs_link(connection_struct *conn,
1424 const char *pathname,
1425 SMB_STRUCT_STAT *psbuf)
1427 int saved_errno = errno;
1428 if(lp_host_msdfs() &&
1429 lp_msdfs_root(SNUM(conn)) &&
1430 is_msdfs_link(conn, pathname, psbuf)) {
1432 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1433 "as a directory\n",
1434 pathname));
1435 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1436 errno = saved_errno;
1437 return true;
1439 errno = saved_errno;
1440 return false;
1444 /****************************************************************************
1445 Get a level dependent lanman2 dir entry.
1446 ****************************************************************************/
1448 struct smbd_dirptr_lanman2_state {
1449 connection_struct *conn;
1450 uint32_t info_level;
1451 bool check_mangled_names;
1452 bool has_wild;
1453 bool got_exact_match;
1456 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1457 void *private_data,
1458 const char *dname,
1459 const char *mask,
1460 char **_fname)
1462 struct smbd_dirptr_lanman2_state *state =
1463 (struct smbd_dirptr_lanman2_state *)private_data;
1464 bool ok;
1465 char mangled_name[13]; /* mangled 8.3 name. */
1466 bool got_match;
1467 const char *fname;
1469 /* Mangle fname if it's an illegal name. */
1470 if (mangle_must_mangle(dname, state->conn->params)) {
1472 * Slow path - ensure we can push the original name as UCS2. If
1473 * not, then just don't return this name.
1475 NTSTATUS status;
1476 size_t ret_len = 0;
1477 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1478 uint8_t *tmp = talloc_array(talloc_tos(),
1479 uint8,
1480 len);
1482 status = srvstr_push(NULL,
1483 FLAGS2_UNICODE_STRINGS,
1484 tmp,
1485 dname,
1486 len,
1487 STR_TERMINATE,
1488 &ret_len);
1490 TALLOC_FREE(tmp);
1492 if (!NT_STATUS_IS_OK(status)) {
1493 return false;
1496 ok = name_to_8_3(dname, mangled_name,
1497 true, state->conn->params);
1498 if (!ok) {
1499 return false;
1501 fname = mangled_name;
1502 } else {
1503 fname = dname;
1506 got_match = exact_match(state->has_wild,
1507 state->conn->case_sensitive,
1508 fname, mask);
1509 state->got_exact_match = got_match;
1510 if (!got_match) {
1511 got_match = mask_match(fname, mask,
1512 state->conn->case_sensitive);
1515 if(!got_match && state->check_mangled_names &&
1516 !mangle_is_8_3(fname, false, state->conn->params)) {
1518 * It turns out that NT matches wildcards against
1519 * both long *and* short names. This may explain some
1520 * of the wildcard wierdness from old DOS clients
1521 * that some people have been seeing.... JRA.
1523 /* Force the mangling into 8.3. */
1524 ok = name_to_8_3(fname, mangled_name,
1525 false, state->conn->params);
1526 if (!ok) {
1527 return false;
1530 got_match = exact_match(state->has_wild,
1531 state->conn->case_sensitive,
1532 mangled_name, mask);
1533 state->got_exact_match = got_match;
1534 if (!got_match) {
1535 got_match = mask_match(mangled_name, mask,
1536 state->conn->case_sensitive);
1540 if (!got_match) {
1541 return false;
1544 *_fname = talloc_strdup(ctx, fname);
1545 if (*_fname == NULL) {
1546 return false;
1549 return true;
1552 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1553 void *private_data,
1554 struct smb_filename *smb_fname,
1555 uint32_t *_mode)
1557 struct smbd_dirptr_lanman2_state *state =
1558 (struct smbd_dirptr_lanman2_state *)private_data;
1559 bool ms_dfs_link = false;
1560 uint32_t mode = 0;
1562 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1563 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1564 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1565 "Couldn't lstat [%s] (%s)\n",
1566 smb_fname_str_dbg(smb_fname),
1567 strerror(errno)));
1568 return false;
1570 } else if (!VALID_STAT(smb_fname->st) &&
1571 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1572 /* Needed to show the msdfs symlinks as
1573 * directories */
1575 ms_dfs_link = check_msdfs_link(state->conn,
1576 smb_fname->base_name,
1577 &smb_fname->st);
1578 if (!ms_dfs_link) {
1579 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1580 "Couldn't stat [%s] (%s)\n",
1581 smb_fname_str_dbg(smb_fname),
1582 strerror(errno)));
1583 return false;
1587 if (ms_dfs_link) {
1588 mode = dos_mode_msdfs(state->conn, smb_fname);
1589 } else {
1590 mode = dos_mode(state->conn, smb_fname);
1593 *_mode = mode;
1594 return true;
1597 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1598 connection_struct *conn,
1599 uint16_t flags2,
1600 uint32_t info_level,
1601 struct ea_list *name_list,
1602 bool check_mangled_names,
1603 bool requires_resume_key,
1604 uint32_t mode,
1605 const char *fname,
1606 const struct smb_filename *smb_fname,
1607 int space_remaining,
1608 uint8_t align,
1609 bool do_pad,
1610 char *base_data,
1611 char **ppdata,
1612 char *end_data,
1613 uint64_t *last_entry_off)
1615 char *p, *q, *pdata = *ppdata;
1616 uint32_t reskey=0;
1617 uint64_t file_size = 0;
1618 uint64_t allocation_size = 0;
1619 uint64_t file_index = 0;
1620 size_t len = 0;
1621 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1622 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1623 char *nameptr;
1624 char *last_entry_ptr;
1625 bool was_8_3;
1626 int off;
1627 int pad = 0;
1628 NTSTATUS status;
1630 ZERO_STRUCT(mdate_ts);
1631 ZERO_STRUCT(adate_ts);
1632 ZERO_STRUCT(create_date_ts);
1633 ZERO_STRUCT(cdate_ts);
1635 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1636 file_size = get_file_size_stat(&smb_fname->st);
1638 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1640 file_index = get_FileIndex(conn, &smb_fname->st);
1642 mdate_ts = smb_fname->st.st_ex_mtime;
1643 adate_ts = smb_fname->st.st_ex_atime;
1644 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1645 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1647 if (lp_dos_filetime_resolution(SNUM(conn))) {
1648 dos_filetime_timespec(&create_date_ts);
1649 dos_filetime_timespec(&mdate_ts);
1650 dos_filetime_timespec(&adate_ts);
1651 dos_filetime_timespec(&cdate_ts);
1654 create_date = convert_timespec_to_time_t(create_date_ts);
1655 mdate = convert_timespec_to_time_t(mdate_ts);
1656 adate = convert_timespec_to_time_t(adate_ts);
1658 /* align the record */
1659 SMB_ASSERT(align >= 1);
1661 off = (int)PTR_DIFF(pdata, base_data);
1662 pad = (off + (align-1)) & ~(align-1);
1663 pad -= off;
1665 if (pad && pad > space_remaining) {
1666 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1667 "for padding (wanted %u, had %d)\n",
1668 (unsigned int)pad,
1669 space_remaining ));
1670 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1673 off += pad;
1674 /* initialize padding to 0 */
1675 if (pad) {
1676 memset(pdata, 0, pad);
1678 space_remaining -= pad;
1680 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1681 space_remaining ));
1683 pdata += pad;
1684 p = pdata;
1685 last_entry_ptr = p;
1687 pad = 0;
1688 off = 0;
1690 switch (info_level) {
1691 case SMB_FIND_INFO_STANDARD:
1692 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1693 if(requires_resume_key) {
1694 SIVAL(p,0,reskey);
1695 p += 4;
1697 srv_put_dos_date2(p,0,create_date);
1698 srv_put_dos_date2(p,4,adate);
1699 srv_put_dos_date2(p,8,mdate);
1700 SIVAL(p,12,(uint32)file_size);
1701 SIVAL(p,16,(uint32)allocation_size);
1702 SSVAL(p,20,mode);
1703 p += 23;
1704 nameptr = p;
1705 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1706 p += ucs2_align(base_data, p, 0);
1708 status = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE, &len);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return status;
1714 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1715 if (len > 2) {
1716 SCVAL(nameptr, -1, len - 2);
1717 } else {
1718 SCVAL(nameptr, -1, 0);
1720 } else {
1721 if (len > 1) {
1722 SCVAL(nameptr, -1, len - 1);
1723 } else {
1724 SCVAL(nameptr, -1, 0);
1727 p += len;
1728 break;
1730 case SMB_FIND_EA_SIZE:
1731 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1732 if (requires_resume_key) {
1733 SIVAL(p,0,reskey);
1734 p += 4;
1736 srv_put_dos_date2(p,0,create_date);
1737 srv_put_dos_date2(p,4,adate);
1738 srv_put_dos_date2(p,8,mdate);
1739 SIVAL(p,12,(uint32)file_size);
1740 SIVAL(p,16,(uint32)allocation_size);
1741 SSVAL(p,20,mode);
1743 unsigned int ea_size = estimate_ea_size(conn, NULL,
1744 smb_fname);
1745 SIVAL(p,22,ea_size); /* Extended attributes */
1747 p += 27;
1748 nameptr = p - 1;
1749 status = srvstr_push(base_data, flags2,
1750 p, fname, PTR_DIFF(end_data, p),
1751 STR_TERMINATE | STR_NOALIGN, &len);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 return status;
1755 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1756 if (len > 2) {
1757 len -= 2;
1758 } else {
1759 len = 0;
1761 } else {
1762 if (len > 1) {
1763 len -= 1;
1764 } else {
1765 len = 0;
1768 SCVAL(nameptr,0,len);
1769 p += len;
1770 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1771 break;
1773 case SMB_FIND_EA_LIST:
1775 struct ea_list *file_list = NULL;
1776 size_t ea_len = 0;
1778 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1779 if (!name_list) {
1780 return NT_STATUS_INVALID_PARAMETER;
1782 if (requires_resume_key) {
1783 SIVAL(p,0,reskey);
1784 p += 4;
1786 srv_put_dos_date2(p,0,create_date);
1787 srv_put_dos_date2(p,4,adate);
1788 srv_put_dos_date2(p,8,mdate);
1789 SIVAL(p,12,(uint32)file_size);
1790 SIVAL(p,16,(uint32)allocation_size);
1791 SSVAL(p,20,mode);
1792 p += 22; /* p now points to the EA area. */
1794 status = get_ea_list_from_file(ctx, conn, NULL,
1795 smb_fname,
1796 &ea_len, &file_list);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 file_list = NULL;
1800 name_list = ea_list_union(name_list, file_list, &ea_len);
1802 /* We need to determine if this entry will fit in the space available. */
1803 /* Max string size is 255 bytes. */
1804 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1805 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1806 "(wanted %u, had %d)\n",
1807 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1808 space_remaining ));
1809 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1812 /* Push the ea_data followed by the name. */
1813 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1814 nameptr = p;
1815 status = srvstr_push(base_data, flags2,
1816 p + 1, fname, PTR_DIFF(end_data, p+1),
1817 STR_TERMINATE | STR_NOALIGN, &len);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 return status;
1821 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1822 if (len > 2) {
1823 len -= 2;
1824 } else {
1825 len = 0;
1827 } else {
1828 if (len > 1) {
1829 len -= 1;
1830 } else {
1831 len = 0;
1834 SCVAL(nameptr,0,len);
1835 p += len + 1;
1836 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1837 break;
1840 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1841 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1842 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1843 p += 4;
1844 SIVAL(p,0,reskey); p += 4;
1845 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1846 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1847 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1848 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1849 SOFF_T(p,0,file_size); p += 8;
1850 SOFF_T(p,0,allocation_size); p += 8;
1851 SIVAL(p,0,mode); p += 4;
1852 q = p; p += 4; /* q is placeholder for name length. */
1853 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1854 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1855 } else {
1856 unsigned int ea_size = estimate_ea_size(conn, NULL,
1857 smb_fname);
1858 SIVAL(p,0,ea_size); /* Extended attributes */
1860 p += 4;
1861 /* Clear the short name buffer. This is
1862 * IMPORTANT as not doing so will trigger
1863 * a Win2k client bug. JRA.
1865 if (!was_8_3 && check_mangled_names) {
1866 char mangled_name[13]; /* mangled 8.3 name. */
1867 if (!name_to_8_3(fname,mangled_name,True,
1868 conn->params)) {
1869 /* Error - mangle failed ! */
1870 memset(mangled_name,'\0',12);
1872 mangled_name[12] = 0;
1873 status = srvstr_push(base_data, flags2,
1874 p+2, mangled_name, 24,
1875 STR_UPPER|STR_UNICODE, &len);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 return status;
1879 if (len < 24) {
1880 memset(p + 2 + len,'\0',24 - len);
1882 SSVAL(p, 0, len);
1883 } else {
1884 memset(p,'\0',26);
1886 p += 2 + 24;
1887 status = srvstr_push(base_data, flags2, p,
1888 fname, PTR_DIFF(end_data, p),
1889 STR_TERMINATE_ASCII, &len);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 return status;
1893 SIVAL(q,0,len);
1894 p += 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_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_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 status = srvstr_push(base_data, flags2,
1927 p + 4, fname, PTR_DIFF(end_data, p+4),
1928 STR_TERMINATE_ASCII, &len);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 return status;
1932 SIVAL(p,0,len);
1933 p += 4 + len;
1935 len = PTR_DIFF(p, pdata);
1936 pad = (len + (align-1)) & ~(align-1);
1938 * offset to the next entry, the caller
1939 * will overwrite it for the last entry
1940 * that's why we always include the padding
1942 SIVAL(pdata,0,pad);
1944 * set padding to zero
1946 if (do_pad) {
1947 memset(p, 0, pad - len);
1948 p = pdata + pad;
1949 } else {
1950 p = pdata + len;
1952 break;
1954 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1955 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1956 p += 4;
1957 SIVAL(p,0,reskey); p += 4;
1958 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1959 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1960 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1961 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1962 SOFF_T(p,0,file_size); p += 8;
1963 SOFF_T(p,0,allocation_size); p += 8;
1964 SIVAL(p,0,mode); p += 4;
1965 q = p; p += 4; /* q is placeholder for name length. */
1967 unsigned int ea_size = estimate_ea_size(conn, NULL,
1968 smb_fname);
1969 SIVAL(p,0,ea_size); /* Extended attributes */
1970 p +=4;
1972 status = srvstr_push(base_data, flags2, p,
1973 fname, PTR_DIFF(end_data, p),
1974 STR_TERMINATE_ASCII, &len);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 return status;
1978 SIVAL(q, 0, len);
1979 p += len;
1981 len = PTR_DIFF(p, pdata);
1982 pad = (len + (align-1)) & ~(align-1);
1984 * offset to the next entry, the caller
1985 * will overwrite it for the last entry
1986 * that's why we always include the padding
1988 SIVAL(pdata,0,pad);
1990 * set padding to zero
1992 if (do_pad) {
1993 memset(p, 0, pad - len);
1994 p = pdata + pad;
1995 } else {
1996 p = pdata + len;
1998 break;
2000 case SMB_FIND_FILE_NAMES_INFO:
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2002 p += 4;
2003 SIVAL(p,0,reskey); p += 4;
2004 p += 4;
2005 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2006 acl on a dir (tridge) */
2007 status = srvstr_push(base_data, flags2, p,
2008 fname, PTR_DIFF(end_data, p),
2009 STR_TERMINATE_ASCII, &len);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 return status;
2013 SIVAL(p, -4, len);
2014 p += len;
2016 len = PTR_DIFF(p, pdata);
2017 pad = (len + (align-1)) & ~(align-1);
2019 * offset to the next entry, the caller
2020 * will overwrite it for the last entry
2021 * that's why we always include the padding
2023 SIVAL(pdata,0,pad);
2025 * set padding to zero
2027 if (do_pad) {
2028 memset(p, 0, pad - len);
2029 p = pdata + pad;
2030 } else {
2031 p = pdata + len;
2033 break;
2035 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2036 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2037 p += 4;
2038 SIVAL(p,0,reskey); p += 4;
2039 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2040 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2041 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2042 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2043 SOFF_T(p,0,file_size); p += 8;
2044 SOFF_T(p,0,allocation_size); p += 8;
2045 SIVAL(p,0,mode); p += 4;
2046 q = p; p += 4; /* q is placeholder for name length. */
2047 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2048 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2049 } else {
2050 unsigned int ea_size = estimate_ea_size(conn, NULL,
2051 smb_fname);
2052 SIVAL(p,0,ea_size); /* Extended attributes */
2054 p += 4;
2055 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2056 SBVAL(p,0,file_index); p += 8;
2057 status = srvstr_push(base_data, flags2, p,
2058 fname, PTR_DIFF(end_data, p),
2059 STR_TERMINATE_ASCII, &len);
2060 if (!NT_STATUS_IS_OK(status)) {
2061 return status;
2063 SIVAL(q, 0, len);
2064 p += len;
2066 len = PTR_DIFF(p, pdata);
2067 pad = (len + (align-1)) & ~(align-1);
2069 * offset to the next entry, the caller
2070 * will overwrite it for the last entry
2071 * that's why we always include the padding
2073 SIVAL(pdata,0,pad);
2075 * set padding to zero
2077 if (do_pad) {
2078 memset(p, 0, pad - len);
2079 p = pdata + pad;
2080 } else {
2081 p = pdata + len;
2083 break;
2085 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2086 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2087 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2088 p += 4;
2089 SIVAL(p,0,reskey); p += 4;
2090 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2091 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2092 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2093 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2094 SOFF_T(p,0,file_size); p += 8;
2095 SOFF_T(p,0,allocation_size); p += 8;
2096 SIVAL(p,0,mode); p += 4;
2097 q = p; p += 4; /* q is placeholder for name length */
2098 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2099 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2100 } else {
2101 unsigned int ea_size = estimate_ea_size(conn, NULL,
2102 smb_fname);
2103 SIVAL(p,0,ea_size); /* Extended attributes */
2105 p += 4;
2106 /* Clear the short name buffer. This is
2107 * IMPORTANT as not doing so will trigger
2108 * a Win2k client bug. JRA.
2110 if (!was_8_3 && check_mangled_names) {
2111 char mangled_name[13]; /* mangled 8.3 name. */
2112 if (!name_to_8_3(fname,mangled_name,True,
2113 conn->params)) {
2114 /* Error - mangle failed ! */
2115 memset(mangled_name,'\0',12);
2117 mangled_name[12] = 0;
2118 status = srvstr_push(base_data, flags2,
2119 p+2, mangled_name, 24,
2120 STR_UPPER|STR_UNICODE, &len);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 return status;
2124 SSVAL(p, 0, len);
2125 if (len < 24) {
2126 memset(p + 2 + len,'\0',24 - len);
2128 SSVAL(p, 0, len);
2129 } else {
2130 memset(p,'\0',26);
2132 p += 26;
2133 SSVAL(p,0,0); p += 2; /* Reserved ? */
2134 SBVAL(p,0,file_index); p += 8;
2135 status = srvstr_push(base_data, flags2, p,
2136 fname, PTR_DIFF(end_data, p),
2137 STR_TERMINATE_ASCII, &len);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 return status;
2141 SIVAL(q,0,len);
2142 p += len;
2144 len = PTR_DIFF(p, pdata);
2145 pad = (len + (align-1)) & ~(align-1);
2147 * offset to the next entry, the caller
2148 * will overwrite it for the last entry
2149 * that's why we always include the padding
2151 SIVAL(pdata,0,pad);
2153 * set padding to zero
2155 if (do_pad) {
2156 memset(p, 0, pad - len);
2157 p = pdata + pad;
2158 } else {
2159 p = pdata + len;
2161 break;
2163 /* CIFS UNIX Extension. */
2165 case SMB_FIND_FILE_UNIX:
2166 case SMB_FIND_FILE_UNIX_INFO2:
2167 p+= 4;
2168 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2170 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2172 if (info_level == SMB_FIND_FILE_UNIX) {
2173 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2174 p = store_file_unix_basic(conn, p,
2175 NULL, &smb_fname->st);
2176 status = srvstr_push(base_data, flags2, p,
2177 fname, PTR_DIFF(end_data, p),
2178 STR_TERMINATE, &len);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 return status;
2182 } else {
2183 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2184 p = store_file_unix_basic_info2(conn, p,
2185 NULL, &smb_fname->st);
2186 nameptr = p;
2187 p += 4;
2188 status = srvstr_push(base_data, flags2, p, fname,
2189 PTR_DIFF(end_data, p), 0, &len);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 return status;
2193 SIVAL(nameptr, 0, len);
2196 p += len;
2198 len = PTR_DIFF(p, pdata);
2199 pad = (len + (align-1)) & ~(align-1);
2201 * offset to the next entry, the caller
2202 * will overwrite it for the last entry
2203 * that's why we always include the padding
2205 SIVAL(pdata,0,pad);
2207 * set padding to zero
2209 if (do_pad) {
2210 memset(p, 0, pad - len);
2211 p = pdata + pad;
2212 } else {
2213 p = pdata + len;
2215 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2217 break;
2219 default:
2220 return NT_STATUS_INVALID_LEVEL;
2223 if (PTR_DIFF(p,pdata) > space_remaining) {
2224 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2225 "(wanted %u, had %d)\n",
2226 (unsigned int)PTR_DIFF(p,pdata),
2227 space_remaining ));
2228 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2231 /* Setup the last entry pointer, as an offset from base_data */
2232 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2233 /* Advance the data pointer to the next slot */
2234 *ppdata = p;
2236 return NT_STATUS_OK;
2239 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2240 connection_struct *conn,
2241 struct dptr_struct *dirptr,
2242 uint16 flags2,
2243 const char *path_mask,
2244 uint32 dirtype,
2245 int info_level,
2246 int requires_resume_key,
2247 bool dont_descend,
2248 bool ask_sharemode,
2249 uint8_t align,
2250 bool do_pad,
2251 char **ppdata,
2252 char *base_data,
2253 char *end_data,
2254 int space_remaining,
2255 bool *got_exact_match,
2256 int *_last_entry_off,
2257 struct ea_list *name_list)
2259 const char *p;
2260 const char *mask = NULL;
2261 long prev_dirpos = 0;
2262 uint32_t mode = 0;
2263 char *fname = NULL;
2264 struct smb_filename *smb_fname = NULL;
2265 struct smbd_dirptr_lanman2_state state;
2266 bool ok;
2267 uint64_t last_entry_off = 0;
2268 NTSTATUS status;
2270 ZERO_STRUCT(state);
2271 state.conn = conn;
2272 state.info_level = info_level;
2273 state.check_mangled_names = lp_mangled_names(conn->params);
2274 state.has_wild = dptr_has_wild(dirptr);
2275 state.got_exact_match = false;
2277 *got_exact_match = false;
2279 p = strrchr_m(path_mask,'/');
2280 if(p != NULL) {
2281 if(p[1] == '\0') {
2282 mask = "*.*";
2283 } else {
2284 mask = p+1;
2286 } else {
2287 mask = path_mask;
2290 ok = smbd_dirptr_get_entry(ctx,
2291 dirptr,
2292 mask,
2293 dirtype,
2294 dont_descend,
2295 ask_sharemode,
2296 smbd_dirptr_lanman2_match_fn,
2297 smbd_dirptr_lanman2_mode_fn,
2298 &state,
2299 &fname,
2300 &smb_fname,
2301 &mode,
2302 &prev_dirpos);
2303 if (!ok) {
2304 return NT_STATUS_END_OF_FILE;
2307 *got_exact_match = state.got_exact_match;
2309 status = smbd_marshall_dir_entry(ctx,
2310 conn,
2311 flags2,
2312 info_level,
2313 name_list,
2314 state.check_mangled_names,
2315 requires_resume_key,
2316 mode,
2317 fname,
2318 smb_fname,
2319 space_remaining,
2320 align,
2321 do_pad,
2322 base_data,
2323 ppdata,
2324 end_data,
2325 &last_entry_off);
2326 TALLOC_FREE(fname);
2327 TALLOC_FREE(smb_fname);
2328 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2329 dptr_SeekDir(dirptr, prev_dirpos);
2330 return status;
2332 if (!NT_STATUS_IS_OK(status)) {
2333 return status;
2336 *_last_entry_off = last_entry_off;
2337 return NT_STATUS_OK;
2340 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2341 connection_struct *conn,
2342 struct dptr_struct *dirptr,
2343 uint16 flags2,
2344 const char *path_mask,
2345 uint32 dirtype,
2346 int info_level,
2347 bool requires_resume_key,
2348 bool dont_descend,
2349 bool ask_sharemode,
2350 char **ppdata,
2351 char *base_data,
2352 char *end_data,
2353 int space_remaining,
2354 bool *got_exact_match,
2355 int *last_entry_off,
2356 struct ea_list *name_list)
2358 uint8_t align = 4;
2359 const bool do_pad = true;
2361 if (info_level >= 1 && info_level <= 3) {
2362 /* No alignment on earlier info levels. */
2363 align = 1;
2366 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2367 path_mask, dirtype, info_level,
2368 requires_resume_key, dont_descend, ask_sharemode,
2369 align, do_pad,
2370 ppdata, base_data, end_data,
2371 space_remaining,
2372 got_exact_match,
2373 last_entry_off, name_list);
2376 /****************************************************************************
2377 Reply to a TRANS2_FINDFIRST.
2378 ****************************************************************************/
2380 static void call_trans2findfirst(connection_struct *conn,
2381 struct smb_request *req,
2382 char **pparams, int total_params,
2383 char **ppdata, int total_data,
2384 unsigned int max_data_bytes)
2386 /* We must be careful here that we don't return more than the
2387 allowed number of data bytes. If this means returning fewer than
2388 maxentries then so be it. We assume that the redirector has
2389 enough room for the fixed number of parameter bytes it has
2390 requested. */
2391 struct smb_filename *smb_dname = NULL;
2392 char *params = *pparams;
2393 char *pdata = *ppdata;
2394 char *data_end;
2395 uint32 dirtype;
2396 int maxentries;
2397 uint16 findfirst_flags;
2398 bool close_after_first;
2399 bool close_if_end;
2400 bool requires_resume_key;
2401 int info_level;
2402 char *directory = NULL;
2403 char *mask = NULL;
2404 char *p;
2405 int last_entry_off=0;
2406 int dptr_num = -1;
2407 int numentries = 0;
2408 int i;
2409 bool finished = False;
2410 bool dont_descend = False;
2411 bool out_of_space = False;
2412 int space_remaining;
2413 bool mask_contains_wcard = False;
2414 struct ea_list *ea_list = NULL;
2415 NTSTATUS ntstatus = NT_STATUS_OK;
2416 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2417 TALLOC_CTX *ctx = talloc_tos();
2418 struct dptr_struct *dirptr = NULL;
2419 struct smbd_server_connection *sconn = req->sconn;
2420 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2421 bool backup_priv = false;
2423 if (total_params < 13) {
2424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2425 goto out;
2428 dirtype = SVAL(params,0);
2429 maxentries = SVAL(params,2);
2430 findfirst_flags = SVAL(params,4);
2431 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2432 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2433 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2434 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2435 security_token_has_privilege(get_current_nttok(conn),
2436 SEC_PRIV_BACKUP));
2438 info_level = SVAL(params,6);
2440 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2441 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2442 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2443 (int)backup_priv,
2444 info_level, max_data_bytes));
2446 if (!maxentries) {
2447 /* W2K3 seems to treat zero as 1. */
2448 maxentries = 1;
2451 switch (info_level) {
2452 case SMB_FIND_INFO_STANDARD:
2453 case SMB_FIND_EA_SIZE:
2454 case SMB_FIND_EA_LIST:
2455 case SMB_FIND_FILE_DIRECTORY_INFO:
2456 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2457 case SMB_FIND_FILE_NAMES_INFO:
2458 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2459 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2460 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2461 break;
2462 case SMB_FIND_FILE_UNIX:
2463 case SMB_FIND_FILE_UNIX_INFO2:
2464 /* Always use filesystem for UNIX mtime query. */
2465 ask_sharemode = false;
2466 if (!lp_unix_extensions()) {
2467 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2468 goto out;
2470 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2471 break;
2472 default:
2473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2474 goto out;
2477 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2478 params+12, total_params - 12,
2479 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2480 if (!NT_STATUS_IS_OK(ntstatus)) {
2481 reply_nterror(req, ntstatus);
2482 goto out;
2485 if (backup_priv) {
2486 become_root();
2487 ntstatus = filename_convert_with_privilege(ctx,
2488 conn,
2489 req,
2490 directory,
2491 ucf_flags,
2492 &mask_contains_wcard,
2493 &smb_dname);
2494 } else {
2495 ntstatus = filename_convert(ctx, conn,
2496 req->flags2 & FLAGS2_DFS_PATHNAMES,
2497 directory,
2498 ucf_flags,
2499 &mask_contains_wcard,
2500 &smb_dname);
2503 if (!NT_STATUS_IS_OK(ntstatus)) {
2504 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2505 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2506 ERRSRV, ERRbadpath);
2507 goto out;
2509 reply_nterror(req, ntstatus);
2510 goto out;
2513 mask = smb_dname->original_lcomp;
2515 directory = smb_dname->base_name;
2517 p = strrchr_m(directory,'/');
2518 if(p == NULL) {
2519 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2520 if((directory[0] == '.') && (directory[1] == '\0')) {
2521 mask = talloc_strdup(ctx,"*");
2522 if (!mask) {
2523 reply_nterror(req, NT_STATUS_NO_MEMORY);
2524 goto out;
2526 mask_contains_wcard = True;
2528 } else {
2529 *p = 0;
2532 if (p == NULL || p == directory) {
2533 /* Ensure we don't have a directory name of "". */
2534 directory = talloc_strdup(talloc_tos(), ".");
2535 if (!directory) {
2536 reply_nterror(req, NT_STATUS_NO_MEMORY);
2537 goto out;
2541 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2543 if (info_level == SMB_FIND_EA_LIST) {
2544 uint32 ea_size;
2546 if (total_data < 4) {
2547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2548 goto out;
2551 ea_size = IVAL(pdata,0);
2552 if (ea_size != total_data) {
2553 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2554 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2556 goto out;
2559 if (!lp_ea_support(SNUM(conn))) {
2560 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2561 goto out;
2564 /* Pull out the list of names. */
2565 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2566 if (!ea_list) {
2567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2568 goto out;
2572 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2574 goto out;
2577 *ppdata = (char *)SMB_REALLOC(
2578 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2579 if(*ppdata == NULL ) {
2580 reply_nterror(req, NT_STATUS_NO_MEMORY);
2581 goto out;
2583 pdata = *ppdata;
2584 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2586 /* Realloc the params space */
2587 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2588 if (*pparams == NULL) {
2589 reply_nterror(req, NT_STATUS_NO_MEMORY);
2590 goto out;
2592 params = *pparams;
2594 /* Save the wildcard match and attribs we are using on this directory -
2595 needed as lanman2 assumes these are being saved between calls */
2597 ntstatus = dptr_create(conn,
2598 req,
2599 NULL, /* fsp */
2600 directory,
2601 False,
2602 True,
2603 req->smbpid,
2604 mask,
2605 mask_contains_wcard,
2606 dirtype,
2607 &dirptr);
2609 if (!NT_STATUS_IS_OK(ntstatus)) {
2610 reply_nterror(req, ntstatus);
2611 goto out;
2614 if (backup_priv) {
2615 /* Remember this in case we have
2616 to do a findnext. */
2617 dptr_set_priv(dirptr);
2620 dptr_num = dptr_dnum(dirptr);
2621 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2623 /* Initialize per TRANS2_FIND_FIRST operation data */
2624 dptr_init_search_op(dirptr);
2626 /* We don't need to check for VOL here as this is returned by
2627 a different TRANS2 call. */
2629 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2630 directory,lp_dont_descend(ctx, SNUM(conn))));
2631 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2632 dont_descend = True;
2634 p = pdata;
2635 space_remaining = max_data_bytes;
2636 out_of_space = False;
2638 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2639 bool got_exact_match = False;
2641 /* this is a heuristic to avoid seeking the dirptr except when
2642 absolutely necessary. It allows for a filename of about 40 chars */
2643 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2644 out_of_space = True;
2645 finished = False;
2646 } else {
2647 ntstatus = get_lanman2_dir_entry(ctx,
2648 conn,
2649 dirptr,
2650 req->flags2,
2651 mask,dirtype,info_level,
2652 requires_resume_key,dont_descend,
2653 ask_sharemode,
2654 &p,pdata,data_end,
2655 space_remaining,
2656 &got_exact_match,
2657 &last_entry_off, ea_list);
2658 if (NT_STATUS_EQUAL(ntstatus,
2659 NT_STATUS_ILLEGAL_CHARACTER)) {
2661 * Bad character conversion on name. Ignore this
2662 * entry.
2664 continue;
2666 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2667 out_of_space = true;
2668 } else {
2669 finished = !NT_STATUS_IS_OK(ntstatus);
2673 if (!finished && !out_of_space)
2674 numentries++;
2677 * As an optimisation if we know we aren't looking
2678 * for a wildcard name (ie. the name matches the wildcard exactly)
2679 * then we can finish on any (first) match.
2680 * This speeds up large directory searches. JRA.
2683 if(got_exact_match)
2684 finished = True;
2686 /* Ensure space_remaining never goes -ve. */
2687 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2688 space_remaining = 0;
2689 out_of_space = true;
2690 } else {
2691 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2695 /* Check if we can close the dirptr */
2696 if(close_after_first || (finished && close_if_end)) {
2697 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2698 dptr_close(sconn, &dptr_num);
2702 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2703 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2704 * the protocol level is less than NT1. Tested with smbclient. JRA.
2705 * This should fix the OS/2 client bug #2335.
2708 if(numentries == 0) {
2709 dptr_close(sconn, &dptr_num);
2710 if (get_Protocol() < PROTOCOL_NT1) {
2711 reply_force_doserror(req, ERRDOS, ERRnofiles);
2712 goto out;
2713 } else {
2714 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2715 ERRDOS, ERRbadfile);
2716 goto out;
2720 /* At this point pdata points to numentries directory entries. */
2722 /* Set up the return parameter block */
2723 SSVAL(params,0,dptr_num);
2724 SSVAL(params,2,numentries);
2725 SSVAL(params,4,finished);
2726 SSVAL(params,6,0); /* Never an EA error */
2727 SSVAL(params,8,last_entry_off);
2729 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2730 max_data_bytes);
2732 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2733 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2734 if (!directory) {
2735 reply_nterror(req, NT_STATUS_NO_MEMORY);
2739 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2740 smb_fn_name(req->cmd),
2741 mask, directory, dirtype, numentries ) );
2744 * Force a name mangle here to ensure that the
2745 * mask as an 8.3 name is top of the mangled cache.
2746 * The reasons for this are subtle. Don't remove
2747 * this code unless you know what you are doing
2748 * (see PR#13758). JRA.
2751 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2752 char mangled_name[13];
2753 name_to_8_3(mask, mangled_name, True, conn->params);
2755 out:
2757 if (backup_priv) {
2758 unbecome_root();
2761 TALLOC_FREE(smb_dname);
2762 return;
2765 /****************************************************************************
2766 Reply to a TRANS2_FINDNEXT.
2767 ****************************************************************************/
2769 static void call_trans2findnext(connection_struct *conn,
2770 struct smb_request *req,
2771 char **pparams, int total_params,
2772 char **ppdata, int total_data,
2773 unsigned int max_data_bytes)
2775 /* We must be careful here that we don't return more than the
2776 allowed number of data bytes. If this means returning fewer than
2777 maxentries then so be it. We assume that the redirector has
2778 enough room for the fixed number of parameter bytes it has
2779 requested. */
2780 char *params = *pparams;
2781 char *pdata = *ppdata;
2782 char *data_end;
2783 int dptr_num;
2784 int maxentries;
2785 uint16 info_level;
2786 uint32 resume_key;
2787 uint16 findnext_flags;
2788 bool close_after_request;
2789 bool close_if_end;
2790 bool requires_resume_key;
2791 bool continue_bit;
2792 bool mask_contains_wcard = False;
2793 char *resume_name = NULL;
2794 const char *mask = NULL;
2795 const char *directory = NULL;
2796 char *p = NULL;
2797 uint16 dirtype;
2798 int numentries = 0;
2799 int i, last_entry_off=0;
2800 bool finished = False;
2801 bool dont_descend = False;
2802 bool out_of_space = False;
2803 int space_remaining;
2804 struct ea_list *ea_list = NULL;
2805 NTSTATUS ntstatus = NT_STATUS_OK;
2806 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2807 TALLOC_CTX *ctx = talloc_tos();
2808 struct dptr_struct *dirptr;
2809 struct smbd_server_connection *sconn = req->sconn;
2810 bool backup_priv = false;
2812 if (total_params < 13) {
2813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2814 return;
2817 dptr_num = SVAL(params,0);
2818 maxentries = SVAL(params,2);
2819 info_level = SVAL(params,4);
2820 resume_key = IVAL(params,6);
2821 findnext_flags = SVAL(params,10);
2822 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2823 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2824 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2825 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2827 if (!continue_bit) {
2828 /* We only need resume_name if continue_bit is zero. */
2829 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2830 params+12,
2831 total_params - 12, STR_TERMINATE, &ntstatus,
2832 &mask_contains_wcard);
2833 if (!NT_STATUS_IS_OK(ntstatus)) {
2834 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2835 complain (it thinks we're asking for the directory above the shared
2836 path or an invalid name). Catch this as the resume name is only compared, never used in
2837 a file access. JRA. */
2838 srvstr_pull_talloc(ctx, params, req->flags2,
2839 &resume_name, params+12,
2840 total_params - 12,
2841 STR_TERMINATE);
2843 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2844 reply_nterror(req, ntstatus);
2845 return;
2850 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2851 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2852 resume_key = %d resume name = %s continue=%d level = %d\n",
2853 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2854 requires_resume_key, resume_key,
2855 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2857 if (!maxentries) {
2858 /* W2K3 seems to treat zero as 1. */
2859 maxentries = 1;
2862 switch (info_level) {
2863 case SMB_FIND_INFO_STANDARD:
2864 case SMB_FIND_EA_SIZE:
2865 case SMB_FIND_EA_LIST:
2866 case SMB_FIND_FILE_DIRECTORY_INFO:
2867 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2868 case SMB_FIND_FILE_NAMES_INFO:
2869 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2870 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2871 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2872 break;
2873 case SMB_FIND_FILE_UNIX:
2874 case SMB_FIND_FILE_UNIX_INFO2:
2875 /* Always use filesystem for UNIX mtime query. */
2876 ask_sharemode = false;
2877 if (!lp_unix_extensions()) {
2878 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2879 return;
2881 break;
2882 default:
2883 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2884 return;
2887 if (info_level == SMB_FIND_EA_LIST) {
2888 uint32 ea_size;
2890 if (total_data < 4) {
2891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2892 return;
2895 ea_size = IVAL(pdata,0);
2896 if (ea_size != total_data) {
2897 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2898 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2900 return;
2903 if (!lp_ea_support(SNUM(conn))) {
2904 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2905 return;
2908 /* Pull out the list of names. */
2909 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2910 if (!ea_list) {
2911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2912 return;
2916 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2918 return;
2921 *ppdata = (char *)SMB_REALLOC(
2922 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2923 if(*ppdata == NULL) {
2924 reply_nterror(req, NT_STATUS_NO_MEMORY);
2925 return;
2928 pdata = *ppdata;
2929 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2931 /* Realloc the params space */
2932 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2933 if(*pparams == NULL ) {
2934 reply_nterror(req, NT_STATUS_NO_MEMORY);
2935 return;
2938 params = *pparams;
2940 /* Check that the dptr is valid */
2941 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2942 reply_nterror(req, STATUS_NO_MORE_FILES);
2943 return;
2946 directory = dptr_path(sconn, dptr_num);
2948 /* Get the wildcard mask from the dptr */
2949 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2950 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2951 reply_nterror(req, STATUS_NO_MORE_FILES);
2952 return;
2955 /* Get the attr mask from the dptr */
2956 dirtype = dptr_attr(sconn, dptr_num);
2958 backup_priv = dptr_get_priv(dirptr);
2960 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2961 "backup_priv = %d\n",
2962 dptr_num, mask, dirtype,
2963 (long)dirptr,
2964 dptr_TellDir(dirptr),
2965 (int)backup_priv));
2967 /* Initialize per TRANS2_FIND_NEXT operation data */
2968 dptr_init_search_op(dirptr);
2970 /* We don't need to check for VOL here as this is returned by
2971 a different TRANS2 call. */
2973 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2974 directory,lp_dont_descend(ctx, SNUM(conn))));
2975 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2976 dont_descend = True;
2978 p = pdata;
2979 space_remaining = max_data_bytes;
2980 out_of_space = False;
2982 if (backup_priv) {
2983 become_root();
2987 * Seek to the correct position. We no longer use the resume key but
2988 * depend on the last file name instead.
2991 if(!continue_bit && resume_name && *resume_name) {
2992 SMB_STRUCT_STAT st;
2994 long current_pos = 0;
2996 * Remember, name_to_8_3 is called by
2997 * get_lanman2_dir_entry(), so the resume name
2998 * could be mangled. Ensure we check the unmangled name.
3001 if (mangle_is_mangled(resume_name, conn->params)) {
3002 char *new_resume_name = NULL;
3003 mangle_lookup_name_from_8_3(ctx,
3004 resume_name,
3005 &new_resume_name,
3006 conn->params);
3007 if (new_resume_name) {
3008 resume_name = new_resume_name;
3013 * Fix for NT redirector problem triggered by resume key indexes
3014 * changing between directory scans. We now return a resume key of 0
3015 * and instead look for the filename to continue from (also given
3016 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3017 * findfirst/findnext (as is usual) then the directory pointer
3018 * should already be at the correct place.
3021 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3022 } /* end if resume_name && !continue_bit */
3024 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3025 bool got_exact_match = False;
3027 /* this is a heuristic to avoid seeking the dirptr except when
3028 absolutely necessary. It allows for a filename of about 40 chars */
3029 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3030 out_of_space = True;
3031 finished = False;
3032 } else {
3033 ntstatus = get_lanman2_dir_entry(ctx,
3034 conn,
3035 dirptr,
3036 req->flags2,
3037 mask,dirtype,info_level,
3038 requires_resume_key,dont_descend,
3039 ask_sharemode,
3040 &p,pdata,data_end,
3041 space_remaining,
3042 &got_exact_match,
3043 &last_entry_off, ea_list);
3044 if (NT_STATUS_EQUAL(ntstatus,
3045 NT_STATUS_ILLEGAL_CHARACTER)) {
3047 * Bad character conversion on name. Ignore this
3048 * entry.
3050 continue;
3052 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3053 out_of_space = true;
3054 } else {
3055 finished = !NT_STATUS_IS_OK(ntstatus);
3059 if (!finished && !out_of_space)
3060 numentries++;
3063 * As an optimisation if we know we aren't looking
3064 * for a wildcard name (ie. the name matches the wildcard exactly)
3065 * then we can finish on any (first) match.
3066 * This speeds up large directory searches. JRA.
3069 if(got_exact_match)
3070 finished = True;
3072 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3075 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3076 smb_fn_name(req->cmd),
3077 mask, directory, dirtype, numentries ) );
3079 /* Check if we can close the dirptr */
3080 if(close_after_request || (finished && close_if_end)) {
3081 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3082 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3085 if (backup_priv) {
3086 unbecome_root();
3089 /* Set up the return parameter block */
3090 SSVAL(params,0,numentries);
3091 SSVAL(params,2,finished);
3092 SSVAL(params,4,0); /* Never an EA error */
3093 SSVAL(params,6,last_entry_off);
3095 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3096 max_data_bytes);
3098 return;
3101 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3103 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3104 return objid;
3107 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3109 SMB_ASSERT(extended_info != NULL);
3111 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3112 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3113 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3114 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3115 #ifdef SAMBA_VERSION_REVISION
3116 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3117 #endif
3118 extended_info->samba_subversion = 0;
3119 #ifdef SAMBA_VERSION_RC_RELEASE
3120 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3121 #else
3122 #ifdef SAMBA_VERSION_PRE_RELEASE
3123 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3124 #endif
3125 #endif
3126 #ifdef SAMBA_VERSION_VENDOR_PATCH
3127 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3128 #endif
3129 extended_info->samba_gitcommitdate = 0;
3130 #ifdef SAMBA_VERSION_COMMIT_TIME
3131 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3132 #endif
3134 memset(extended_info->samba_version_string, 0,
3135 sizeof(extended_info->samba_version_string));
3137 snprintf (extended_info->samba_version_string,
3138 sizeof(extended_info->samba_version_string),
3139 "%s", samba_version_string());
3142 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3143 connection_struct *conn,
3144 TALLOC_CTX *mem_ctx,
3145 uint16_t info_level,
3146 uint16_t flags2,
3147 unsigned int max_data_bytes,
3148 size_t *fixed_portion,
3149 struct smb_filename *fname,
3150 char **ppdata,
3151 int *ret_data_len)
3153 char *pdata, *end_data;
3154 int data_len = 0;
3155 size_t len = 0;
3156 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3157 int snum = SNUM(conn);
3158 const char *fstype = lp_fstype(SNUM(conn));
3159 const char *filename = NULL;
3160 uint32 additional_flags = 0;
3161 struct smb_filename smb_fname;
3162 SMB_STRUCT_STAT st;
3163 NTSTATUS status = NT_STATUS_OK;
3165 if (fname == NULL || fname->base_name == NULL) {
3166 filename = ".";
3167 } else {
3168 filename = fname->base_name;
3171 if (IS_IPC(conn)) {
3172 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3173 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3174 "info level (0x%x) on IPC$.\n",
3175 (unsigned int)info_level));
3176 return NT_STATUS_ACCESS_DENIED;
3180 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3182 ZERO_STRUCT(smb_fname);
3183 smb_fname.base_name = discard_const_p(char, filename);
3185 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3186 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3187 return map_nt_error_from_unix(errno);
3190 st = smb_fname.st;
3192 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3193 return NT_STATUS_INVALID_PARAMETER;
3196 *ppdata = (char *)SMB_REALLOC(
3197 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3198 if (*ppdata == NULL) {
3199 return NT_STATUS_NO_MEMORY;
3202 pdata = *ppdata;
3203 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3204 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3206 *fixed_portion = 0;
3208 switch (info_level) {
3209 case SMB_INFO_ALLOCATION:
3211 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3212 data_len = 18;
3213 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3214 return map_nt_error_from_unix(errno);
3217 block_size = lp_block_size(snum);
3218 if (bsize < block_size) {
3219 uint64_t factor = block_size/bsize;
3220 bsize = block_size;
3221 dsize /= factor;
3222 dfree /= factor;
3224 if (bsize > block_size) {
3225 uint64_t factor = bsize/block_size;
3226 bsize = block_size;
3227 dsize *= factor;
3228 dfree *= factor;
3230 bytes_per_sector = 512;
3231 sectors_per_unit = bsize/bytes_per_sector;
3233 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3234 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3235 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3237 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3238 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3239 SIVAL(pdata,l1_cUnit,dsize);
3240 SIVAL(pdata,l1_cUnitAvail,dfree);
3241 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3242 break;
3245 case SMB_INFO_VOLUME:
3246 /* Return volume name */
3248 * Add volume serial number - hash of a combination of
3249 * the called hostname and the service name.
3251 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3253 * Win2k3 and previous mess this up by sending a name length
3254 * one byte short. I believe only older clients (OS/2 Win9x) use
3255 * this call so try fixing this by adding a terminating null to
3256 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3258 status = srvstr_push(
3259 pdata, flags2,
3260 pdata+l2_vol_szVolLabel, vname,
3261 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3262 STR_NOALIGN|STR_TERMINATE, &len);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 return status;
3266 SCVAL(pdata,l2_vol_cch,len);
3267 data_len = l2_vol_szVolLabel + len;
3268 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3269 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3270 (unsigned)len, vname));
3271 break;
3273 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3274 case SMB_FS_ATTRIBUTE_INFORMATION:
3276 additional_flags = 0;
3277 #if defined(HAVE_SYS_QUOTAS)
3278 additional_flags |= FILE_VOLUME_QUOTAS;
3279 #endif
3281 if(lp_nt_acl_support(SNUM(conn))) {
3282 additional_flags |= FILE_PERSISTENT_ACLS;
3285 /* Capabilities are filled in at connection time through STATVFS call */
3286 additional_flags |= conn->fs_capabilities;
3287 additional_flags |= lp_parm_int(conn->params->service,
3288 "share", "fake_fscaps",
3291 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3292 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3293 additional_flags); /* FS ATTRIBUTES */
3295 SIVAL(pdata,4,255); /* Max filename component length */
3296 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3297 and will think we can't do long filenames */
3298 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3299 PTR_DIFF(end_data, pdata+12),
3300 STR_UNICODE, &len);
3301 if (!NT_STATUS_IS_OK(status)) {
3302 return status;
3304 SIVAL(pdata,8,len);
3305 data_len = 12 + len;
3306 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3307 /* the client only requested a portion of the
3308 file system name */
3309 data_len = max_data_bytes;
3310 status = STATUS_BUFFER_OVERFLOW;
3312 *fixed_portion = 16;
3313 break;
3315 case SMB_QUERY_FS_LABEL_INFO:
3316 case SMB_FS_LABEL_INFORMATION:
3317 status = srvstr_push(pdata, flags2, pdata+4, vname,
3318 PTR_DIFF(end_data, pdata+4), 0, &len);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 return status;
3322 data_len = 4 + len;
3323 SIVAL(pdata,0,len);
3324 break;
3326 case SMB_QUERY_FS_VOLUME_INFO:
3327 case SMB_FS_VOLUME_INFORMATION:
3330 * Add volume serial number - hash of a combination of
3331 * the called hostname and the service name.
3333 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3334 (str_checksum(get_local_machine_name())<<16));
3336 /* Max label len is 32 characters. */
3337 status = srvstr_push(pdata, flags2, pdata+18, vname,
3338 PTR_DIFF(end_data, pdata+18),
3339 STR_UNICODE, &len);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 return status;
3343 SIVAL(pdata,12,len);
3344 data_len = 18+len;
3346 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3347 (int)strlen(vname),vname,
3348 lp_servicename(talloc_tos(), snum)));
3349 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3350 /* the client only requested a portion of the
3351 volume label */
3352 data_len = max_data_bytes;
3353 status = STATUS_BUFFER_OVERFLOW;
3355 *fixed_portion = 24;
3356 break;
3358 case SMB_QUERY_FS_SIZE_INFO:
3359 case SMB_FS_SIZE_INFORMATION:
3361 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3362 data_len = 24;
3363 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3364 return map_nt_error_from_unix(errno);
3366 block_size = lp_block_size(snum);
3367 if (bsize < block_size) {
3368 uint64_t factor = block_size/bsize;
3369 bsize = block_size;
3370 dsize /= factor;
3371 dfree /= factor;
3373 if (bsize > block_size) {
3374 uint64_t factor = bsize/block_size;
3375 bsize = block_size;
3376 dsize *= factor;
3377 dfree *= factor;
3379 bytes_per_sector = 512;
3380 sectors_per_unit = bsize/bytes_per_sector;
3381 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3382 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3383 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3384 SBIG_UINT(pdata,0,dsize);
3385 SBIG_UINT(pdata,8,dfree);
3386 SIVAL(pdata,16,sectors_per_unit);
3387 SIVAL(pdata,20,bytes_per_sector);
3388 *fixed_portion = 24;
3389 break;
3392 case SMB_FS_FULL_SIZE_INFORMATION:
3394 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3395 data_len = 32;
3396 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3397 return map_nt_error_from_unix(errno);
3399 block_size = lp_block_size(snum);
3400 if (bsize < block_size) {
3401 uint64_t factor = block_size/bsize;
3402 bsize = block_size;
3403 dsize /= factor;
3404 dfree /= factor;
3406 if (bsize > block_size) {
3407 uint64_t factor = bsize/block_size;
3408 bsize = block_size;
3409 dsize *= factor;
3410 dfree *= factor;
3412 bytes_per_sector = 512;
3413 sectors_per_unit = bsize/bytes_per_sector;
3414 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3415 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3416 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3417 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3418 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3419 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3420 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3421 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3422 *fixed_portion = 32;
3423 break;
3426 case SMB_QUERY_FS_DEVICE_INFO:
3427 case SMB_FS_DEVICE_INFORMATION:
3429 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3431 if (!CAN_WRITE(conn)) {
3432 characteristics |= FILE_READ_ONLY_DEVICE;
3434 data_len = 8;
3435 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3436 SIVAL(pdata,4,characteristics);
3437 *fixed_portion = 8;
3438 break;
3441 #ifdef HAVE_SYS_QUOTAS
3442 case SMB_FS_QUOTA_INFORMATION:
3444 * what we have to send --metze:
3446 * Unknown1: 24 NULL bytes
3447 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3448 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3449 * Quota Flags: 2 byte :
3450 * Unknown3: 6 NULL bytes
3452 * 48 bytes total
3454 * details for Quota Flags:
3456 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3457 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3458 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3459 * 0x0001 Enable Quotas: enable quota for this fs
3463 /* we need to fake up a fsp here,
3464 * because its not send in this call
3466 files_struct fsp;
3467 SMB_NTQUOTA_STRUCT quotas;
3469 ZERO_STRUCT(fsp);
3470 ZERO_STRUCT(quotas);
3472 fsp.conn = conn;
3473 fsp.fnum = FNUM_FIELD_INVALID;
3475 /* access check */
3476 if (get_current_uid(conn) != 0) {
3477 DEBUG(0,("get_user_quota: access_denied "
3478 "service [%s] user [%s]\n",
3479 lp_servicename(talloc_tos(), SNUM(conn)),
3480 conn->session_info->unix_info->unix_name));
3481 return NT_STATUS_ACCESS_DENIED;
3484 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3485 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3486 return map_nt_error_from_unix(errno);
3489 data_len = 48;
3491 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3492 lp_servicename(talloc_tos(), SNUM(conn))));
3494 /* Unknown1 24 NULL bytes*/
3495 SBIG_UINT(pdata,0,(uint64_t)0);
3496 SBIG_UINT(pdata,8,(uint64_t)0);
3497 SBIG_UINT(pdata,16,(uint64_t)0);
3499 /* Default Soft Quota 8 bytes */
3500 SBIG_UINT(pdata,24,quotas.softlim);
3502 /* Default Hard Quota 8 bytes */
3503 SBIG_UINT(pdata,32,quotas.hardlim);
3505 /* Quota flag 2 bytes */
3506 SSVAL(pdata,40,quotas.qflags);
3508 /* Unknown3 6 NULL bytes */
3509 SSVAL(pdata,42,0);
3510 SIVAL(pdata,44,0);
3512 break;
3514 #endif /* HAVE_SYS_QUOTAS */
3515 case SMB_FS_OBJECTID_INFORMATION:
3517 unsigned char objid[16];
3518 struct smb_extended_info extended_info;
3519 memcpy(pdata,create_volume_objectid(conn, objid),16);
3520 samba_extended_info_version (&extended_info);
3521 SIVAL(pdata,16,extended_info.samba_magic);
3522 SIVAL(pdata,20,extended_info.samba_version);
3523 SIVAL(pdata,24,extended_info.samba_subversion);
3524 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3525 memcpy(pdata+36,extended_info.samba_version_string,28);
3526 data_len = 64;
3527 break;
3531 * Query the version and capabilities of the CIFS UNIX extensions
3532 * in use.
3535 case SMB_QUERY_CIFS_UNIX_INFO:
3537 bool large_write = lp_min_receive_file_size() &&
3538 !srv_is_signing_active(xconn);
3539 bool large_read = !srv_is_signing_active(xconn);
3540 int encrypt_caps = 0;
3542 if (!lp_unix_extensions()) {
3543 return NT_STATUS_INVALID_LEVEL;
3546 switch (conn->encrypt_level) {
3547 case SMB_SIGNING_OFF:
3548 encrypt_caps = 0;
3549 break;
3550 case SMB_SIGNING_IF_REQUIRED:
3551 case SMB_SIGNING_DEFAULT:
3552 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3553 break;
3554 case SMB_SIGNING_REQUIRED:
3555 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3556 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3557 large_write = false;
3558 large_read = false;
3559 break;
3562 data_len = 12;
3563 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3564 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3566 /* We have POSIX ACLs, pathname, encryption,
3567 * large read/write, and locking capability. */
3569 SBIG_UINT(pdata,4,((uint64_t)(
3570 CIFS_UNIX_POSIX_ACLS_CAP|
3571 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3572 CIFS_UNIX_FCNTL_LOCKS_CAP|
3573 CIFS_UNIX_EXTATTR_CAP|
3574 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3575 encrypt_caps|
3576 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3577 (large_write ?
3578 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3579 break;
3582 case SMB_QUERY_POSIX_FS_INFO:
3584 int rc;
3585 vfs_statvfs_struct svfs;
3587 if (!lp_unix_extensions()) {
3588 return NT_STATUS_INVALID_LEVEL;
3591 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3593 if (!rc) {
3594 data_len = 56;
3595 SIVAL(pdata,0,svfs.OptimalTransferSize);
3596 SIVAL(pdata,4,svfs.BlockSize);
3597 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3598 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3599 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3600 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3601 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3602 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3603 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3604 #ifdef EOPNOTSUPP
3605 } else if (rc == EOPNOTSUPP) {
3606 return NT_STATUS_INVALID_LEVEL;
3607 #endif /* EOPNOTSUPP */
3608 } else {
3609 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3610 return NT_STATUS_DOS(ERRSRV, ERRerror);
3612 break;
3615 case SMB_QUERY_POSIX_WHOAMI:
3617 uint32_t flags = 0;
3618 uint32_t sid_bytes;
3619 int i;
3621 if (!lp_unix_extensions()) {
3622 return NT_STATUS_INVALID_LEVEL;
3625 if (max_data_bytes < 40) {
3626 return NT_STATUS_BUFFER_TOO_SMALL;
3629 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3630 flags |= SMB_WHOAMI_GUEST;
3633 /* NOTE: 8 bytes for UID/GID, irrespective of native
3634 * platform size. This matches
3635 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3637 data_len = 4 /* flags */
3638 + 4 /* flag mask */
3639 + 8 /* uid */
3640 + 8 /* gid */
3641 + 4 /* ngroups */
3642 + 4 /* num_sids */
3643 + 4 /* SID bytes */
3644 + 4 /* pad/reserved */
3645 + (conn->session_info->unix_token->ngroups * 8)
3646 /* groups list */
3647 + (conn->session_info->security_token->num_sids *
3648 SID_MAX_SIZE)
3649 /* SID list */;
3651 SIVAL(pdata, 0, flags);
3652 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3653 SBIG_UINT(pdata, 8,
3654 (uint64_t)conn->session_info->unix_token->uid);
3655 SBIG_UINT(pdata, 16,
3656 (uint64_t)conn->session_info->unix_token->gid);
3659 if (data_len >= max_data_bytes) {
3660 /* Potential overflow, skip the GIDs and SIDs. */
3662 SIVAL(pdata, 24, 0); /* num_groups */
3663 SIVAL(pdata, 28, 0); /* num_sids */
3664 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3665 SIVAL(pdata, 36, 0); /* reserved */
3667 data_len = 40;
3668 break;
3671 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3672 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3674 /* We walk the SID list twice, but this call is fairly
3675 * infrequent, and I don't expect that it's performance
3676 * sensitive -- jpeach
3678 for (i = 0, sid_bytes = 0;
3679 i < conn->session_info->security_token->num_sids; ++i) {
3680 sid_bytes += ndr_size_dom_sid(
3681 &conn->session_info->security_token->sids[i],
3685 /* SID list byte count */
3686 SIVAL(pdata, 32, sid_bytes);
3688 /* 4 bytes pad/reserved - must be zero */
3689 SIVAL(pdata, 36, 0);
3690 data_len = 40;
3692 /* GID list */
3693 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3694 SBIG_UINT(pdata, data_len,
3695 (uint64_t)conn->session_info->unix_token->groups[i]);
3696 data_len += 8;
3699 /* SID list */
3700 for (i = 0;
3701 i < conn->session_info->security_token->num_sids; ++i) {
3702 int sid_len = ndr_size_dom_sid(
3703 &conn->session_info->security_token->sids[i],
3706 sid_linearize(pdata + data_len, sid_len,
3707 &conn->session_info->security_token->sids[i]);
3708 data_len += sid_len;
3711 break;
3714 case SMB_MAC_QUERY_FS_INFO:
3716 * Thursby MAC extension... ONLY on NTFS filesystems
3717 * once we do streams then we don't need this
3719 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3720 data_len = 88;
3721 SIVAL(pdata,84,0x100); /* Don't support mac... */
3722 break;
3724 /* drop through */
3725 default:
3726 return NT_STATUS_INVALID_LEVEL;
3729 *ret_data_len = data_len;
3730 return status;
3733 /****************************************************************************
3734 Reply to a TRANS2_QFSINFO (query filesystem info).
3735 ****************************************************************************/
3737 static void call_trans2qfsinfo(connection_struct *conn,
3738 struct smb_request *req,
3739 char **pparams, int total_params,
3740 char **ppdata, int total_data,
3741 unsigned int max_data_bytes)
3743 char *params = *pparams;
3744 uint16_t info_level;
3745 int data_len = 0;
3746 size_t fixed_portion;
3747 NTSTATUS status;
3749 if (total_params < 2) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3751 return;
3754 info_level = SVAL(params,0);
3756 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3757 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3758 DEBUG(0,("call_trans2qfsinfo: encryption required "
3759 "and info level 0x%x sent.\n",
3760 (unsigned int)info_level));
3761 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3762 return;
3766 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3768 status = smbd_do_qfsinfo(req->xconn, conn, req,
3769 info_level,
3770 req->flags2,
3771 max_data_bytes,
3772 &fixed_portion,
3773 NULL,
3774 ppdata, &data_len);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 reply_nterror(req, status);
3777 return;
3780 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3781 max_data_bytes);
3783 DEBUG( 4, ( "%s info_level = %d\n",
3784 smb_fn_name(req->cmd), info_level) );
3786 return;
3789 /****************************************************************************
3790 Reply to a TRANS2_SETFSINFO (set filesystem info).
3791 ****************************************************************************/
3793 static void call_trans2setfsinfo(connection_struct *conn,
3794 struct smb_request *req,
3795 char **pparams, int total_params,
3796 char **ppdata, int total_data,
3797 unsigned int max_data_bytes)
3799 struct smbXsrv_connection *xconn = req->xconn;
3800 char *pdata = *ppdata;
3801 char *params = *pparams;
3802 uint16 info_level;
3804 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3805 lp_servicename(talloc_tos(), SNUM(conn))));
3807 /* */
3808 if (total_params < 4) {
3809 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3810 total_params));
3811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3812 return;
3815 info_level = SVAL(params,2);
3817 if (IS_IPC(conn)) {
3818 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3819 info_level != SMB_SET_CIFS_UNIX_INFO) {
3820 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3821 "info level (0x%x) on IPC$.\n",
3822 (unsigned int)info_level));
3823 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3824 return;
3828 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3829 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3830 DEBUG(0,("call_trans2setfsinfo: encryption required "
3831 "and info level 0x%x sent.\n",
3832 (unsigned int)info_level));
3833 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3834 return;
3838 switch(info_level) {
3839 case SMB_SET_CIFS_UNIX_INFO:
3840 if (!lp_unix_extensions()) {
3841 DEBUG(2,("call_trans2setfsinfo: "
3842 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3843 "unix extensions off\n"));
3844 reply_nterror(req,
3845 NT_STATUS_INVALID_LEVEL);
3846 return;
3849 /* There should be 12 bytes of capabilities set. */
3850 if (total_data < 12) {
3851 reply_nterror(
3852 req,
3853 NT_STATUS_INVALID_PARAMETER);
3854 return;
3856 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3857 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3858 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3859 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3860 /* Just print these values for now. */
3861 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3862 "major = %u, minor = %u cap_low = 0x%x, "
3863 "cap_high = 0x%xn",
3864 (unsigned int)xconn->
3865 smb1.unix_info.client_major,
3866 (unsigned int)xconn->
3867 smb1.unix_info.client_minor,
3868 (unsigned int)xconn->
3869 smb1.unix_info.client_cap_low,
3870 (unsigned int)xconn->
3871 smb1.unix_info.client_cap_high));
3873 /* Here is where we must switch to posix pathname processing... */
3874 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3875 lp_set_posix_pathnames();
3876 mangle_change_to_posix();
3879 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3880 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3881 /* Client that knows how to do posix locks,
3882 * but not posix open/mkdir operations. Set a
3883 * default type for read/write checks. */
3885 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3888 break;
3890 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3892 NTSTATUS status;
3893 size_t param_len = 0;
3894 size_t data_len = total_data;
3896 if (!lp_unix_extensions()) {
3897 reply_nterror(
3898 req,
3899 NT_STATUS_INVALID_LEVEL);
3900 return;
3903 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3904 reply_nterror(
3905 req,
3906 NT_STATUS_NOT_SUPPORTED);
3907 return;
3910 if (xconn->smb1.echo_handler.trusted_fde) {
3911 DEBUG( 2,("call_trans2setfsinfo: "
3912 "request transport encryption disabled"
3913 "with 'fork echo handler = yes'\n"));
3914 reply_nterror(
3915 req,
3916 NT_STATUS_NOT_SUPPORTED);
3917 return;
3920 DEBUG( 4,("call_trans2setfsinfo: "
3921 "request transport encryption.\n"));
3923 status = srv_request_encryption_setup(conn,
3924 (unsigned char **)ppdata,
3925 &data_len,
3926 (unsigned char **)pparams,
3927 &param_len);
3929 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3930 !NT_STATUS_IS_OK(status)) {
3931 reply_nterror(req, status);
3932 return;
3935 send_trans2_replies(conn, req,
3936 NT_STATUS_OK,
3937 *pparams,
3938 param_len,
3939 *ppdata,
3940 data_len,
3941 max_data_bytes);
3943 if (NT_STATUS_IS_OK(status)) {
3944 /* Server-side transport
3945 * encryption is now *on*. */
3946 status = srv_encryption_start(conn);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 char *reason = talloc_asprintf(talloc_tos(),
3949 "Failure in setting "
3950 "up encrypted transport: %s",
3951 nt_errstr(status));
3952 exit_server_cleanly(reason);
3955 return;
3958 case SMB_FS_QUOTA_INFORMATION:
3960 files_struct *fsp = NULL;
3961 SMB_NTQUOTA_STRUCT quotas;
3963 ZERO_STRUCT(quotas);
3965 /* access check */
3966 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3967 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3968 lp_servicename(talloc_tos(), SNUM(conn)),
3969 conn->session_info->unix_info->unix_name));
3970 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3971 return;
3974 /* note: normaly there're 48 bytes,
3975 * but we didn't use the last 6 bytes for now
3976 * --metze
3978 fsp = file_fsp(req, SVAL(params,0));
3980 if (!check_fsp_ntquota_handle(conn, req,
3981 fsp)) {
3982 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3983 reply_nterror(
3984 req, NT_STATUS_INVALID_HANDLE);
3985 return;
3988 if (total_data < 42) {
3989 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3990 total_data));
3991 reply_nterror(
3992 req,
3993 NT_STATUS_INVALID_PARAMETER);
3994 return;
3997 /* unknown_1 24 NULL bytes in pdata*/
3999 /* the soft quotas 8 bytes (uint64_t)*/
4000 quotas.softlim = BVAL(pdata,24);
4002 /* the hard quotas 8 bytes (uint64_t)*/
4003 quotas.hardlim = BVAL(pdata,32);
4005 /* quota_flags 2 bytes **/
4006 quotas.qflags = SVAL(pdata,40);
4008 /* unknown_2 6 NULL bytes follow*/
4010 /* now set the quotas */
4011 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4012 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4013 reply_nterror(req, map_nt_error_from_unix(errno));
4014 return;
4017 break;
4019 default:
4020 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4021 info_level));
4022 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4023 return;
4024 break;
4028 * sending this reply works fine,
4029 * but I'm not sure it's the same
4030 * like windows do...
4031 * --metze
4033 reply_outbuf(req, 10, 0);
4036 #if defined(HAVE_POSIX_ACLS)
4037 /****************************************************************************
4038 Utility function to count the number of entries in a POSIX acl.
4039 ****************************************************************************/
4041 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4043 unsigned int ace_count = 0;
4044 int entry_id = SMB_ACL_FIRST_ENTRY;
4045 SMB_ACL_ENTRY_T entry;
4047 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4048 /* get_next... */
4049 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4050 entry_id = SMB_ACL_NEXT_ENTRY;
4052 ace_count++;
4054 return ace_count;
4057 /****************************************************************************
4058 Utility function to marshall a POSIX acl into wire format.
4059 ****************************************************************************/
4061 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4063 int entry_id = SMB_ACL_FIRST_ENTRY;
4064 SMB_ACL_ENTRY_T entry;
4066 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4067 SMB_ACL_TAG_T tagtype;
4068 SMB_ACL_PERMSET_T permset;
4069 unsigned char perms = 0;
4070 unsigned int own_grp;
4072 /* get_next... */
4073 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4074 entry_id = SMB_ACL_NEXT_ENTRY;
4077 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4078 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4079 return False;
4082 if (sys_acl_get_permset(entry, &permset) == -1) {
4083 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4084 return False;
4087 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4088 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4089 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4091 SCVAL(pdata,1,perms);
4093 switch (tagtype) {
4094 case SMB_ACL_USER_OBJ:
4095 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4096 own_grp = (unsigned int)pst->st_ex_uid;
4097 SIVAL(pdata,2,own_grp);
4098 SIVAL(pdata,6,0);
4099 break;
4100 case SMB_ACL_USER:
4102 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4103 if (!puid) {
4104 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4105 return False;
4107 own_grp = (unsigned int)*puid;
4108 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4109 SIVAL(pdata,2,own_grp);
4110 SIVAL(pdata,6,0);
4111 break;
4113 case SMB_ACL_GROUP_OBJ:
4114 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4115 own_grp = (unsigned int)pst->st_ex_gid;
4116 SIVAL(pdata,2,own_grp);
4117 SIVAL(pdata,6,0);
4118 break;
4119 case SMB_ACL_GROUP:
4121 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4122 if (!pgid) {
4123 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4124 return False;
4126 own_grp = (unsigned int)*pgid;
4127 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4128 SIVAL(pdata,2,own_grp);
4129 SIVAL(pdata,6,0);
4130 break;
4132 case SMB_ACL_MASK:
4133 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4134 SIVAL(pdata,2,0xFFFFFFFF);
4135 SIVAL(pdata,6,0xFFFFFFFF);
4136 break;
4137 case SMB_ACL_OTHER:
4138 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4139 SIVAL(pdata,2,0xFFFFFFFF);
4140 SIVAL(pdata,6,0xFFFFFFFF);
4141 break;
4142 default:
4143 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4144 return False;
4146 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4149 return True;
4151 #endif
4153 /****************************************************************************
4154 Store the FILE_UNIX_BASIC info.
4155 ****************************************************************************/
4157 static char *store_file_unix_basic(connection_struct *conn,
4158 char *pdata,
4159 files_struct *fsp,
4160 const SMB_STRUCT_STAT *psbuf)
4162 uint64_t file_index = get_FileIndex(conn, psbuf);
4163 dev_t devno;
4165 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4166 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4168 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4169 pdata += 8;
4171 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4172 pdata += 8;
4174 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4175 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4176 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4177 pdata += 24;
4179 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4180 SIVAL(pdata,4,0);
4181 pdata += 8;
4183 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4184 SIVAL(pdata,4,0);
4185 pdata += 8;
4187 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4188 pdata += 4;
4190 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4191 devno = psbuf->st_ex_rdev;
4192 } else {
4193 devno = psbuf->st_ex_dev;
4196 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4197 SIVAL(pdata,4,0);
4198 pdata += 8;
4200 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4201 SIVAL(pdata,4,0);
4202 pdata += 8;
4204 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4205 pdata += 8;
4207 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4208 SIVAL(pdata,4,0);
4209 pdata += 8;
4211 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4212 SIVAL(pdata,4,0);
4213 pdata += 8;
4215 return pdata;
4218 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4219 * the chflags(2) (or equivalent) flags.
4221 * XXX: this really should be behind the VFS interface. To do this, we would
4222 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4223 * Each VFS module could then implement its own mapping as appropriate for the
4224 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4226 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4227 info2_flags_map[] =
4229 #ifdef UF_NODUMP
4230 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4231 #endif
4233 #ifdef UF_IMMUTABLE
4234 { UF_IMMUTABLE, EXT_IMMUTABLE },
4235 #endif
4237 #ifdef UF_APPEND
4238 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4239 #endif
4241 #ifdef UF_HIDDEN
4242 { UF_HIDDEN, EXT_HIDDEN },
4243 #endif
4245 /* Do not remove. We need to guarantee that this array has at least one
4246 * entry to build on HP-UX.
4248 { 0, 0 }
4252 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4253 uint32 *smb_fflags, uint32 *smb_fmask)
4255 int i;
4257 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4258 *smb_fmask |= info2_flags_map[i].smb_fflag;
4259 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4260 *smb_fflags |= info2_flags_map[i].smb_fflag;
4265 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4266 const uint32 smb_fflags,
4267 const uint32 smb_fmask,
4268 int *stat_fflags)
4270 uint32 max_fmask = 0;
4271 int i;
4273 *stat_fflags = psbuf->st_ex_flags;
4275 /* For each flags requested in smb_fmask, check the state of the
4276 * corresponding flag in smb_fflags and set or clear the matching
4277 * stat flag.
4280 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4281 max_fmask |= info2_flags_map[i].smb_fflag;
4282 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4283 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4284 *stat_fflags |= info2_flags_map[i].stat_fflag;
4285 } else {
4286 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4291 /* If smb_fmask is asking to set any bits that are not supported by
4292 * our flag mappings, we should fail.
4294 if ((smb_fmask & max_fmask) != smb_fmask) {
4295 return False;
4298 return True;
4302 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4303 * of file flags and birth (create) time.
4305 static char *store_file_unix_basic_info2(connection_struct *conn,
4306 char *pdata,
4307 files_struct *fsp,
4308 const SMB_STRUCT_STAT *psbuf)
4310 uint32 file_flags = 0;
4311 uint32 flags_mask = 0;
4313 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4315 /* Create (birth) time 64 bit */
4316 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4317 pdata += 8;
4319 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4320 SIVAL(pdata, 0, file_flags); /* flags */
4321 SIVAL(pdata, 4, flags_mask); /* mask */
4322 pdata += 8;
4324 return pdata;
4327 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4328 const struct stream_struct *streams,
4329 char *data,
4330 unsigned int max_data_bytes,
4331 unsigned int *data_size)
4333 unsigned int i;
4334 unsigned int ofs = 0;
4336 if (max_data_bytes < 32) {
4337 return NT_STATUS_INFO_LENGTH_MISMATCH;
4340 for (i = 0; i < num_streams; i++) {
4341 unsigned int next_offset;
4342 size_t namelen;
4343 smb_ucs2_t *namebuf;
4345 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4346 streams[i].name, &namelen) ||
4347 namelen <= 2)
4349 return NT_STATUS_INVALID_PARAMETER;
4353 * name_buf is now null-terminated, we need to marshall as not
4354 * terminated
4357 namelen -= 2;
4360 * We cannot overflow ...
4362 if ((ofs + 24 + namelen) > max_data_bytes) {
4363 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4364 i));
4365 TALLOC_FREE(namebuf);
4366 return STATUS_BUFFER_OVERFLOW;
4369 SIVAL(data, ofs+4, namelen);
4370 SOFF_T(data, ofs+8, streams[i].size);
4371 SOFF_T(data, ofs+16, streams[i].alloc_size);
4372 memcpy(data+ofs+24, namebuf, namelen);
4373 TALLOC_FREE(namebuf);
4375 next_offset = ofs + 24 + namelen;
4377 if (i == num_streams-1) {
4378 SIVAL(data, ofs, 0);
4380 else {
4381 unsigned int align = ndr_align_size(next_offset, 8);
4383 if ((next_offset + align) > max_data_bytes) {
4384 DEBUG(10, ("refusing to overflow align "
4385 "reply at stream %u\n",
4386 i));
4387 TALLOC_FREE(namebuf);
4388 return STATUS_BUFFER_OVERFLOW;
4391 memset(data+next_offset, 0, align);
4392 next_offset += align;
4394 SIVAL(data, ofs, next_offset - ofs);
4395 ofs = next_offset;
4398 ofs = next_offset;
4401 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4403 *data_size = ofs;
4405 return NT_STATUS_OK;
4408 /****************************************************************************
4409 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4410 ****************************************************************************/
4412 static void call_trans2qpipeinfo(connection_struct *conn,
4413 struct smb_request *req,
4414 unsigned int tran_call,
4415 char **pparams, int total_params,
4416 char **ppdata, int total_data,
4417 unsigned int max_data_bytes)
4419 char *params = *pparams;
4420 char *pdata = *ppdata;
4421 unsigned int data_size = 0;
4422 unsigned int param_size = 2;
4423 uint16 info_level;
4424 files_struct *fsp;
4426 if (!params) {
4427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4428 return;
4431 if (total_params < 4) {
4432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4433 return;
4436 fsp = file_fsp(req, SVAL(params,0));
4437 if (!fsp_is_np(fsp)) {
4438 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4439 return;
4442 info_level = SVAL(params,2);
4444 *pparams = (char *)SMB_REALLOC(*pparams,2);
4445 if (*pparams == NULL) {
4446 reply_nterror(req, NT_STATUS_NO_MEMORY);
4447 return;
4449 params = *pparams;
4450 SSVAL(params,0,0);
4451 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4453 return;
4455 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4456 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4457 if (*ppdata == NULL ) {
4458 reply_nterror(req, NT_STATUS_NO_MEMORY);
4459 return;
4461 pdata = *ppdata;
4463 switch (info_level) {
4464 case SMB_FILE_STANDARD_INFORMATION:
4465 memset(pdata,0,24);
4466 SOFF_T(pdata,0,4096LL);
4467 SIVAL(pdata,16,1);
4468 SIVAL(pdata,20,1);
4469 data_size = 24;
4470 break;
4472 default:
4473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4474 return;
4477 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4478 max_data_bytes);
4480 return;
4483 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4484 TALLOC_CTX *mem_ctx,
4485 uint16_t info_level,
4486 files_struct *fsp,
4487 struct smb_filename *smb_fname,
4488 bool delete_pending,
4489 struct timespec write_time_ts,
4490 struct ea_list *ea_list,
4491 int lock_data_count,
4492 char *lock_data,
4493 uint16_t flags2,
4494 unsigned int max_data_bytes,
4495 size_t *fixed_portion,
4496 char **ppdata,
4497 unsigned int *pdata_size)
4499 char *pdata = *ppdata;
4500 char *dstart, *dend;
4501 unsigned int data_size;
4502 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4503 time_t create_time, mtime, atime, c_time;
4504 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4505 char *p;
4506 char *base_name;
4507 char *dos_fname;
4508 int mode;
4509 int nlink;
4510 NTSTATUS status;
4511 uint64_t file_size = 0;
4512 uint64_t pos = 0;
4513 uint64_t allocation_size = 0;
4514 uint64_t file_index = 0;
4515 uint32_t access_mask = 0;
4516 size_t len = 0;
4518 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4519 return NT_STATUS_INVALID_LEVEL;
4522 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4523 smb_fname_str_dbg(smb_fname),
4524 fsp_fnum_dbg(fsp),
4525 info_level, max_data_bytes));
4527 mode = dos_mode(conn, smb_fname);
4528 nlink = psbuf->st_ex_nlink;
4530 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4531 nlink = 1;
4534 if ((nlink > 0) && delete_pending) {
4535 nlink -= 1;
4538 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4539 return NT_STATUS_INVALID_PARAMETER;
4542 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4543 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4544 if (*ppdata == NULL) {
4545 return NT_STATUS_NO_MEMORY;
4547 pdata = *ppdata;
4548 dstart = pdata;
4549 dend = dstart + data_size - 1;
4551 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4552 update_stat_ex_mtime(psbuf, write_time_ts);
4555 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4556 mtime_ts = psbuf->st_ex_mtime;
4557 atime_ts = psbuf->st_ex_atime;
4558 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4560 if (lp_dos_filetime_resolution(SNUM(conn))) {
4561 dos_filetime_timespec(&create_time_ts);
4562 dos_filetime_timespec(&mtime_ts);
4563 dos_filetime_timespec(&atime_ts);
4564 dos_filetime_timespec(&ctime_ts);
4567 create_time = convert_timespec_to_time_t(create_time_ts);
4568 mtime = convert_timespec_to_time_t(mtime_ts);
4569 atime = convert_timespec_to_time_t(atime_ts);
4570 c_time = convert_timespec_to_time_t(ctime_ts);
4572 p = strrchr_m(smb_fname->base_name,'/');
4573 if (!p)
4574 base_name = smb_fname->base_name;
4575 else
4576 base_name = p+1;
4578 /* NT expects the name to be in an exact form of the *full*
4579 filename. See the trans2 torture test */
4580 if (ISDOT(base_name)) {
4581 dos_fname = talloc_strdup(mem_ctx, "\\");
4582 if (!dos_fname) {
4583 return NT_STATUS_NO_MEMORY;
4585 } else {
4586 dos_fname = talloc_asprintf(mem_ctx,
4587 "\\%s",
4588 smb_fname->base_name);
4589 if (!dos_fname) {
4590 return NT_STATUS_NO_MEMORY;
4592 if (is_ntfs_stream_smb_fname(smb_fname)) {
4593 dos_fname = talloc_asprintf(dos_fname, "%s",
4594 smb_fname->stream_name);
4595 if (!dos_fname) {
4596 return NT_STATUS_NO_MEMORY;
4600 string_replace(dos_fname, '/', '\\');
4603 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4605 if (!fsp) {
4606 /* Do we have this path open ? */
4607 files_struct *fsp1;
4608 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4609 fsp1 = file_find_di_first(conn->sconn, fileid);
4610 if (fsp1 && fsp1->initial_allocation_size) {
4611 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4615 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4616 file_size = get_file_size_stat(psbuf);
4619 if (fsp) {
4620 pos = fsp->fh->position_information;
4623 if (fsp) {
4624 access_mask = fsp->access_mask;
4625 } else {
4626 /* GENERIC_EXECUTE mapping from Windows */
4627 access_mask = 0x12019F;
4630 /* This should be an index number - looks like
4631 dev/ino to me :-)
4633 I think this causes us to fail the IFSKIT
4634 BasicFileInformationTest. -tpot */
4635 file_index = get_FileIndex(conn, psbuf);
4637 *fixed_portion = 0;
4639 switch (info_level) {
4640 case SMB_INFO_STANDARD:
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4642 data_size = 22;
4643 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4644 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4645 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4646 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4647 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4648 SSVAL(pdata,l1_attrFile,mode);
4649 break;
4651 case SMB_INFO_QUERY_EA_SIZE:
4653 unsigned int ea_size =
4654 estimate_ea_size(conn, fsp,
4655 smb_fname);
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4657 data_size = 26;
4658 srv_put_dos_date2(pdata,0,create_time);
4659 srv_put_dos_date2(pdata,4,atime);
4660 srv_put_dos_date2(pdata,8,mtime); /* write time */
4661 SIVAL(pdata,12,(uint32)file_size);
4662 SIVAL(pdata,16,(uint32)allocation_size);
4663 SSVAL(pdata,20,mode);
4664 SIVAL(pdata,22,ea_size);
4665 break;
4668 case SMB_INFO_IS_NAME_VALID:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4670 if (fsp) {
4671 /* os/2 needs this ? really ?*/
4672 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4674 /* This is only reached for qpathinfo */
4675 data_size = 0;
4676 break;
4678 case SMB_INFO_QUERY_EAS_FROM_LIST:
4680 size_t total_ea_len = 0;
4681 struct ea_list *ea_file_list = NULL;
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4684 status =
4685 get_ea_list_from_file(mem_ctx, conn, fsp,
4686 smb_fname,
4687 &total_ea_len, &ea_file_list);
4688 if (!NT_STATUS_IS_OK(status)) {
4689 return status;
4692 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4694 if (!ea_list || (total_ea_len > data_size)) {
4695 data_size = 4;
4696 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4697 break;
4700 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4701 break;
4704 case SMB_INFO_QUERY_ALL_EAS:
4706 /* We have data_size bytes to put EA's into. */
4707 size_t total_ea_len = 0;
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4710 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4711 smb_fname,
4712 &total_ea_len, &ea_list);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 return status;
4717 if (!ea_list || (total_ea_len > data_size)) {
4718 data_size = 4;
4719 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4720 break;
4723 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4724 break;
4727 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4729 /* This is FileFullEaInformation - 0xF which maps to
4730 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4732 /* We have data_size bytes to put EA's into. */
4733 size_t total_ea_len = 0;
4734 struct ea_list *ea_file_list = NULL;
4736 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4738 /*TODO: add filtering and index handling */
4740 status =
4741 get_ea_list_from_file(mem_ctx, conn, fsp,
4742 smb_fname,
4743 &total_ea_len, &ea_file_list);
4744 if (!NT_STATUS_IS_OK(status)) {
4745 return status;
4747 if (!ea_file_list) {
4748 return NT_STATUS_NO_EAS_ON_FILE;
4751 status = fill_ea_chained_buffer(mem_ctx,
4752 pdata,
4753 data_size,
4754 &data_size,
4755 conn, ea_file_list);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 return status;
4759 break;
4762 case SMB_FILE_BASIC_INFORMATION:
4763 case SMB_QUERY_FILE_BASIC_INFO:
4765 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4767 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4768 } else {
4769 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4770 data_size = 40;
4771 SIVAL(pdata,36,0);
4773 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4774 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4775 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4776 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4777 SIVAL(pdata,32,mode);
4779 DEBUG(5,("SMB_QFBI - "));
4780 DEBUG(5,("create: %s ", ctime(&create_time)));
4781 DEBUG(5,("access: %s ", ctime(&atime)));
4782 DEBUG(5,("write: %s ", ctime(&mtime)));
4783 DEBUG(5,("change: %s ", ctime(&c_time)));
4784 DEBUG(5,("mode: %x\n", mode));
4785 *fixed_portion = data_size;
4786 break;
4788 case SMB_FILE_STANDARD_INFORMATION:
4789 case SMB_QUERY_FILE_STANDARD_INFO:
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4792 data_size = 24;
4793 SOFF_T(pdata,0,allocation_size);
4794 SOFF_T(pdata,8,file_size);
4795 SIVAL(pdata,16,nlink);
4796 SCVAL(pdata,20,delete_pending?1:0);
4797 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4798 SSVAL(pdata,22,0); /* Padding. */
4799 *fixed_portion = 24;
4800 break;
4802 case SMB_FILE_EA_INFORMATION:
4803 case SMB_QUERY_FILE_EA_INFO:
4805 unsigned int ea_size =
4806 estimate_ea_size(conn, fsp, smb_fname);
4807 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4808 data_size = 4;
4809 *fixed_portion = 4;
4810 SIVAL(pdata,0,ea_size);
4811 break;
4814 /* Get the 8.3 name - used if NT SMB was negotiated. */
4815 case SMB_QUERY_FILE_ALT_NAME_INFO:
4816 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4818 char mangled_name[13];
4819 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4820 if (!name_to_8_3(base_name,mangled_name,
4821 True,conn->params)) {
4822 return NT_STATUS_NO_MEMORY;
4824 status = srvstr_push(dstart, flags2,
4825 pdata+4, mangled_name,
4826 PTR_DIFF(dend, pdata+4),
4827 STR_UNICODE, &len);
4828 if (!NT_STATUS_IS_OK(status)) {
4829 return status;
4831 data_size = 4 + len;
4832 SIVAL(pdata,0,len);
4833 *fixed_portion = 8;
4834 break;
4837 case SMB_QUERY_FILE_NAME_INFO:
4840 this must be *exactly* right for ACLs on mapped drives to work
4842 status = srvstr_push(dstart, flags2,
4843 pdata+4, dos_fname,
4844 PTR_DIFF(dend, pdata+4),
4845 STR_UNICODE, &len);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 return status;
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4850 data_size = 4 + len;
4851 SIVAL(pdata,0,len);
4852 break;
4855 case SMB_FILE_ALLOCATION_INFORMATION:
4856 case SMB_QUERY_FILE_ALLOCATION_INFO:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4858 data_size = 8;
4859 SOFF_T(pdata,0,allocation_size);
4860 break;
4862 case SMB_FILE_END_OF_FILE_INFORMATION:
4863 case SMB_QUERY_FILE_END_OF_FILEINFO:
4864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4865 data_size = 8;
4866 SOFF_T(pdata,0,file_size);
4867 break;
4869 case SMB_QUERY_FILE_ALL_INFO:
4870 case SMB_FILE_ALL_INFORMATION:
4872 unsigned int ea_size =
4873 estimate_ea_size(conn, fsp, smb_fname);
4874 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4875 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4876 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4877 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4878 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4879 SIVAL(pdata,32,mode);
4880 SIVAL(pdata,36,0); /* padding. */
4881 pdata += 40;
4882 SOFF_T(pdata,0,allocation_size);
4883 SOFF_T(pdata,8,file_size);
4884 SIVAL(pdata,16,nlink);
4885 SCVAL(pdata,20,delete_pending);
4886 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4887 SSVAL(pdata,22,0);
4888 pdata += 24;
4889 SIVAL(pdata,0,ea_size);
4890 pdata += 4; /* EA info */
4891 status = srvstr_push(dstart, flags2,
4892 pdata+4, dos_fname,
4893 PTR_DIFF(dend, pdata+4),
4894 STR_UNICODE, &len);
4895 if (!NT_STATUS_IS_OK(status)) {
4896 return status;
4898 SIVAL(pdata,0,len);
4899 pdata += 4 + len;
4900 data_size = PTR_DIFF(pdata,(*ppdata));
4901 *fixed_portion = 10;
4902 break;
4905 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4907 unsigned int ea_size =
4908 estimate_ea_size(conn, fsp, smb_fname);
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4910 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4911 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4912 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4913 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4914 SIVAL(pdata, 0x20, mode);
4915 SIVAL(pdata, 0x24, 0); /* padding. */
4916 SBVAL(pdata, 0x28, allocation_size);
4917 SBVAL(pdata, 0x30, file_size);
4918 SIVAL(pdata, 0x38, nlink);
4919 SCVAL(pdata, 0x3C, delete_pending);
4920 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4921 SSVAL(pdata, 0x3E, 0); /* padding */
4922 SBVAL(pdata, 0x40, file_index);
4923 SIVAL(pdata, 0x48, ea_size);
4924 SIVAL(pdata, 0x4C, access_mask);
4925 SBVAL(pdata, 0x50, pos);
4926 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4927 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4929 pdata += 0x60;
4931 status = srvstr_push(dstart, flags2,
4932 pdata+4, dos_fname,
4933 PTR_DIFF(dend, pdata+4),
4934 STR_UNICODE, &len);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 return status;
4938 SIVAL(pdata,0,len);
4939 pdata += 4 + len;
4940 data_size = PTR_DIFF(pdata,(*ppdata));
4941 *fixed_portion = 104;
4942 break;
4944 case SMB_FILE_INTERNAL_INFORMATION:
4946 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4947 SBVAL(pdata, 0, file_index);
4948 data_size = 8;
4949 *fixed_portion = 8;
4950 break;
4952 case SMB_FILE_ACCESS_INFORMATION:
4953 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4954 SIVAL(pdata, 0, access_mask);
4955 data_size = 4;
4956 *fixed_portion = 4;
4957 break;
4959 case SMB_FILE_NAME_INFORMATION:
4960 /* Pathname with leading '\'. */
4962 size_t byte_len;
4963 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4964 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4965 SIVAL(pdata,0,byte_len);
4966 data_size = 4 + byte_len;
4967 break;
4970 case SMB_FILE_DISPOSITION_INFORMATION:
4971 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4972 data_size = 1;
4973 SCVAL(pdata,0,delete_pending);
4974 *fixed_portion = 1;
4975 break;
4977 case SMB_FILE_POSITION_INFORMATION:
4978 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4979 data_size = 8;
4980 SOFF_T(pdata,0,pos);
4981 *fixed_portion = 8;
4982 break;
4984 case SMB_FILE_MODE_INFORMATION:
4985 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4986 SIVAL(pdata,0,mode);
4987 data_size = 4;
4988 *fixed_portion = 4;
4989 break;
4991 case SMB_FILE_ALIGNMENT_INFORMATION:
4992 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4993 SIVAL(pdata,0,0); /* No alignment needed. */
4994 data_size = 4;
4995 *fixed_portion = 4;
4996 break;
4999 * NT4 server just returns "invalid query" to this - if we try
5000 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5001 * want this. JRA.
5003 /* The first statement above is false - verified using Thursby
5004 * client against NT4 -- gcolley.
5006 case SMB_QUERY_FILE_STREAM_INFO:
5007 case SMB_FILE_STREAM_INFORMATION: {
5008 unsigned int num_streams = 0;
5009 struct stream_struct *streams = NULL;
5011 DEBUG(10,("smbd_do_qfilepathinfo: "
5012 "SMB_FILE_STREAM_INFORMATION\n"));
5014 if (is_ntfs_stream_smb_fname(smb_fname)) {
5015 return NT_STATUS_INVALID_PARAMETER;
5018 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5019 talloc_tos(), &num_streams, &streams);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 DEBUG(10, ("could not get stream info: %s\n",
5023 nt_errstr(status)));
5024 return status;
5027 status = marshall_stream_info(num_streams, streams,
5028 pdata, max_data_bytes,
5029 &data_size);
5031 if (!NT_STATUS_IS_OK(status)) {
5032 DEBUG(10, ("marshall_stream_info failed: %s\n",
5033 nt_errstr(status)));
5034 TALLOC_FREE(streams);
5035 return status;
5038 TALLOC_FREE(streams);
5040 *fixed_portion = 32;
5042 break;
5044 case SMB_QUERY_COMPRESSION_INFO:
5045 case SMB_FILE_COMPRESSION_INFORMATION:
5046 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5047 SOFF_T(pdata,0,file_size);
5048 SIVAL(pdata,8,0); /* ??? */
5049 SIVAL(pdata,12,0); /* ??? */
5050 data_size = 16;
5051 *fixed_portion = 16;
5052 break;
5054 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5055 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5056 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5057 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5058 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5059 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5060 SOFF_T(pdata,32,allocation_size);
5061 SOFF_T(pdata,40,file_size);
5062 SIVAL(pdata,48,mode);
5063 SIVAL(pdata,52,0); /* ??? */
5064 data_size = 56;
5065 *fixed_portion = 56;
5066 break;
5068 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5069 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5070 SIVAL(pdata,0,mode);
5071 SIVAL(pdata,4,0);
5072 data_size = 8;
5073 *fixed_portion = 8;
5074 break;
5077 * CIFS UNIX Extensions.
5080 case SMB_QUERY_FILE_UNIX_BASIC:
5082 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5083 data_size = PTR_DIFF(pdata,(*ppdata));
5085 DEBUG(4,("smbd_do_qfilepathinfo: "
5086 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5087 dump_data(4, (uint8_t *)(*ppdata), data_size);
5089 break;
5091 case SMB_QUERY_FILE_UNIX_INFO2:
5093 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5094 data_size = PTR_DIFF(pdata,(*ppdata));
5097 int i;
5098 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5100 for (i=0; i<100; i++)
5101 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5102 DEBUG(4,("\n"));
5105 break;
5107 case SMB_QUERY_FILE_UNIX_LINK:
5109 int link_len = 0;
5110 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5112 if (!buffer) {
5113 return NT_STATUS_NO_MEMORY;
5116 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5117 #ifdef S_ISLNK
5118 if(!S_ISLNK(psbuf->st_ex_mode)) {
5119 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5121 #else
5122 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5123 #endif
5124 link_len = SMB_VFS_READLINK(conn,
5125 smb_fname->base_name,
5126 buffer, PATH_MAX);
5127 if (link_len == -1) {
5128 return map_nt_error_from_unix(errno);
5130 buffer[link_len] = 0;
5131 status = srvstr_push(dstart, flags2,
5132 pdata, buffer,
5133 PTR_DIFF(dend, pdata),
5134 STR_TERMINATE, &len);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 return status;
5138 pdata += len;
5139 data_size = PTR_DIFF(pdata,(*ppdata));
5141 break;
5144 #if defined(HAVE_POSIX_ACLS)
5145 case SMB_QUERY_POSIX_ACL:
5147 SMB_ACL_T file_acl = NULL;
5148 SMB_ACL_T def_acl = NULL;
5149 uint16 num_file_acls = 0;
5150 uint16 num_def_acls = 0;
5152 if (fsp && fsp->fh->fd != -1) {
5153 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5154 talloc_tos());
5155 } else {
5156 file_acl =
5157 SMB_VFS_SYS_ACL_GET_FILE(conn,
5158 smb_fname->base_name,
5159 SMB_ACL_TYPE_ACCESS,
5160 talloc_tos());
5163 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5164 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5165 "not implemented on "
5166 "filesystem containing %s\n",
5167 smb_fname->base_name));
5168 return NT_STATUS_NOT_IMPLEMENTED;
5171 if (S_ISDIR(psbuf->st_ex_mode)) {
5172 if (fsp && fsp->is_directory) {
5173 def_acl =
5174 SMB_VFS_SYS_ACL_GET_FILE(
5175 conn,
5176 fsp->fsp_name->base_name,
5177 SMB_ACL_TYPE_DEFAULT,
5178 talloc_tos());
5179 } else {
5180 def_acl =
5181 SMB_VFS_SYS_ACL_GET_FILE(
5182 conn,
5183 smb_fname->base_name,
5184 SMB_ACL_TYPE_DEFAULT,
5185 talloc_tos());
5187 def_acl = free_empty_sys_acl(conn, def_acl);
5190 num_file_acls = count_acl_entries(conn, file_acl);
5191 num_def_acls = count_acl_entries(conn, def_acl);
5193 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5194 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5195 data_size,
5196 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5197 SMB_POSIX_ACL_HEADER_SIZE) ));
5198 if (file_acl) {
5199 TALLOC_FREE(file_acl);
5201 if (def_acl) {
5202 TALLOC_FREE(def_acl);
5204 return NT_STATUS_BUFFER_TOO_SMALL;
5207 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5208 SSVAL(pdata,2,num_file_acls);
5209 SSVAL(pdata,4,num_def_acls);
5210 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5211 if (file_acl) {
5212 TALLOC_FREE(file_acl);
5214 if (def_acl) {
5215 TALLOC_FREE(def_acl);
5217 return NT_STATUS_INTERNAL_ERROR;
5219 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5220 if (file_acl) {
5221 TALLOC_FREE(file_acl);
5223 if (def_acl) {
5224 TALLOC_FREE(def_acl);
5226 return NT_STATUS_INTERNAL_ERROR;
5229 if (file_acl) {
5230 TALLOC_FREE(file_acl);
5232 if (def_acl) {
5233 TALLOC_FREE(def_acl);
5235 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5236 break;
5238 #endif
5241 case SMB_QUERY_POSIX_LOCK:
5243 uint64_t count;
5244 uint64_t offset;
5245 uint64_t smblctx;
5246 enum brl_type lock_type;
5248 /* We need an open file with a real fd for this. */
5249 if (!fsp || fsp->fh->fd == -1) {
5250 return NT_STATUS_INVALID_LEVEL;
5253 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5254 return NT_STATUS_INVALID_PARAMETER;
5257 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5258 case POSIX_LOCK_TYPE_READ:
5259 lock_type = READ_LOCK;
5260 break;
5261 case POSIX_LOCK_TYPE_WRITE:
5262 lock_type = WRITE_LOCK;
5263 break;
5264 case POSIX_LOCK_TYPE_UNLOCK:
5265 default:
5266 /* There's no point in asking for an unlock... */
5267 return NT_STATUS_INVALID_PARAMETER;
5270 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5271 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5272 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5274 status = query_lock(fsp,
5275 &smblctx,
5276 &count,
5277 &offset,
5278 &lock_type,
5279 POSIX_LOCK);
5281 if (ERROR_WAS_LOCK_DENIED(status)) {
5282 /* Here we need to report who has it locked... */
5283 data_size = POSIX_LOCK_DATA_SIZE;
5285 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5286 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5287 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5288 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5289 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5291 } else if (NT_STATUS_IS_OK(status)) {
5292 /* For success we just return a copy of what we sent
5293 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5294 data_size = POSIX_LOCK_DATA_SIZE;
5295 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5296 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5297 } else {
5298 return status;
5300 break;
5303 default:
5304 return NT_STATUS_INVALID_LEVEL;
5307 *pdata_size = data_size;
5308 return NT_STATUS_OK;
5311 /****************************************************************************
5312 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5313 file name or file id).
5314 ****************************************************************************/
5316 static void call_trans2qfilepathinfo(connection_struct *conn,
5317 struct smb_request *req,
5318 unsigned int tran_call,
5319 char **pparams, int total_params,
5320 char **ppdata, int total_data,
5321 unsigned int max_data_bytes)
5323 char *params = *pparams;
5324 char *pdata = *ppdata;
5325 uint16 info_level;
5326 unsigned int data_size = 0;
5327 unsigned int param_size = 2;
5328 struct smb_filename *smb_fname = NULL;
5329 bool delete_pending = False;
5330 struct timespec write_time_ts;
5331 files_struct *fsp = NULL;
5332 struct file_id fileid;
5333 struct ea_list *ea_list = NULL;
5334 int lock_data_count = 0;
5335 char *lock_data = NULL;
5336 size_t fixed_portion;
5337 NTSTATUS status = NT_STATUS_OK;
5339 if (!params) {
5340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5341 return;
5344 ZERO_STRUCT(write_time_ts);
5346 if (tran_call == TRANSACT2_QFILEINFO) {
5347 if (total_params < 4) {
5348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5349 return;
5352 if (IS_IPC(conn)) {
5353 call_trans2qpipeinfo(conn, req, tran_call,
5354 pparams, total_params,
5355 ppdata, total_data,
5356 max_data_bytes);
5357 return;
5360 fsp = file_fsp(req, SVAL(params,0));
5361 info_level = SVAL(params,2);
5363 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5365 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5366 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5367 return;
5370 /* Initial check for valid fsp ptr. */
5371 if (!check_fsp_open(conn, req, fsp)) {
5372 return;
5375 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5376 if (smb_fname == NULL) {
5377 reply_nterror(req, NT_STATUS_NO_MEMORY);
5378 return;
5381 if(fsp->fake_file_handle) {
5383 * This is actually for the QUOTA_FAKE_FILE --metze
5386 /* We know this name is ok, it's already passed the checks. */
5388 } else if(fsp->fh->fd == -1) {
5390 * This is actually a QFILEINFO on a directory
5391 * handle (returned from an NT SMB). NT5.0 seems
5392 * to do this call. JRA.
5395 if (INFO_LEVEL_IS_UNIX(info_level)) {
5396 /* Always do lstat for UNIX calls. */
5397 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5398 DEBUG(3,("call_trans2qfilepathinfo: "
5399 "SMB_VFS_LSTAT of %s failed "
5400 "(%s)\n",
5401 smb_fname_str_dbg(smb_fname),
5402 strerror(errno)));
5403 reply_nterror(req,
5404 map_nt_error_from_unix(errno));
5405 return;
5407 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5408 DEBUG(3,("call_trans2qfilepathinfo: "
5409 "SMB_VFS_STAT of %s failed (%s)\n",
5410 smb_fname_str_dbg(smb_fname),
5411 strerror(errno)));
5412 reply_nterror(req,
5413 map_nt_error_from_unix(errno));
5414 return;
5417 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5418 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5419 } else {
5421 * Original code - this is an open file.
5423 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5424 DEBUG(3, ("fstat of %s failed (%s)\n",
5425 fsp_fnum_dbg(fsp), strerror(errno)));
5426 reply_nterror(req,
5427 map_nt_error_from_unix(errno));
5428 return;
5430 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5431 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5434 } else {
5435 uint32_t name_hash;
5436 char *fname = NULL;
5437 uint32_t ucf_flags = 0;
5439 /* qpathinfo */
5440 if (total_params < 7) {
5441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5442 return;
5445 info_level = SVAL(params,0);
5447 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5449 if (INFO_LEVEL_IS_UNIX(info_level)) {
5450 if (!lp_unix_extensions()) {
5451 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5452 return;
5454 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5455 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5456 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5457 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5461 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5462 total_params - 6,
5463 STR_TERMINATE, &status);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 reply_nterror(req, status);
5466 return;
5469 status = filename_convert(req,
5470 conn,
5471 req->flags2 & FLAGS2_DFS_PATHNAMES,
5472 fname,
5473 ucf_flags,
5474 NULL,
5475 &smb_fname);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5478 reply_botherror(req,
5479 NT_STATUS_PATH_NOT_COVERED,
5480 ERRSRV, ERRbadpath);
5481 return;
5483 reply_nterror(req, status);
5484 return;
5487 /* If this is a stream, check if there is a delete_pending. */
5488 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5489 && is_ntfs_stream_smb_fname(smb_fname)) {
5490 struct smb_filename *smb_fname_base;
5492 /* Create an smb_filename with stream_name == NULL. */
5493 smb_fname_base = synthetic_smb_fname(
5494 talloc_tos(), smb_fname->base_name,
5495 NULL, NULL);
5496 if (smb_fname_base == NULL) {
5497 reply_nterror(req, NT_STATUS_NO_MEMORY);
5498 return;
5501 if (INFO_LEVEL_IS_UNIX(info_level)) {
5502 /* Always do lstat for UNIX calls. */
5503 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5504 DEBUG(3,("call_trans2qfilepathinfo: "
5505 "SMB_VFS_LSTAT of %s failed "
5506 "(%s)\n",
5507 smb_fname_str_dbg(smb_fname_base),
5508 strerror(errno)));
5509 TALLOC_FREE(smb_fname_base);
5510 reply_nterror(req,
5511 map_nt_error_from_unix(errno));
5512 return;
5514 } else {
5515 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5516 DEBUG(3,("call_trans2qfilepathinfo: "
5517 "fileinfo of %s failed "
5518 "(%s)\n",
5519 smb_fname_str_dbg(smb_fname_base),
5520 strerror(errno)));
5521 TALLOC_FREE(smb_fname_base);
5522 reply_nterror(req,
5523 map_nt_error_from_unix(errno));
5524 return;
5528 status = file_name_hash(conn,
5529 smb_fname_str_dbg(smb_fname_base),
5530 &name_hash);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 TALLOC_FREE(smb_fname_base);
5533 reply_nterror(req, status);
5534 return;
5537 fileid = vfs_file_id_from_sbuf(conn,
5538 &smb_fname_base->st);
5539 TALLOC_FREE(smb_fname_base);
5540 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5541 if (delete_pending) {
5542 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5543 return;
5547 if (INFO_LEVEL_IS_UNIX(info_level)) {
5548 /* Always do lstat for UNIX calls. */
5549 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5550 DEBUG(3,("call_trans2qfilepathinfo: "
5551 "SMB_VFS_LSTAT of %s failed (%s)\n",
5552 smb_fname_str_dbg(smb_fname),
5553 strerror(errno)));
5554 reply_nterror(req,
5555 map_nt_error_from_unix(errno));
5556 return;
5559 } else {
5560 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5561 DEBUG(3,("call_trans2qfilepathinfo: "
5562 "SMB_VFS_STAT of %s failed (%s)\n",
5563 smb_fname_str_dbg(smb_fname),
5564 strerror(errno)));
5565 reply_nterror(req,
5566 map_nt_error_from_unix(errno));
5567 return;
5571 status = file_name_hash(conn,
5572 smb_fname_str_dbg(smb_fname),
5573 &name_hash);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 reply_nterror(req, status);
5576 return;
5579 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5580 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5581 if (delete_pending) {
5582 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5583 return;
5587 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5588 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5589 fsp_fnum_dbg(fsp),
5590 info_level,tran_call,total_data));
5592 /* Pull out any data sent here before we realloc. */
5593 switch (info_level) {
5594 case SMB_INFO_QUERY_EAS_FROM_LIST:
5596 /* Pull any EA list from the data portion. */
5597 uint32 ea_size;
5599 if (total_data < 4) {
5600 reply_nterror(
5601 req, NT_STATUS_INVALID_PARAMETER);
5602 return;
5604 ea_size = IVAL(pdata,0);
5606 if (total_data > 0 && ea_size != total_data) {
5607 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5608 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5609 reply_nterror(
5610 req, NT_STATUS_INVALID_PARAMETER);
5611 return;
5614 if (!lp_ea_support(SNUM(conn))) {
5615 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5616 return;
5619 /* Pull out the list of names. */
5620 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5621 if (!ea_list) {
5622 reply_nterror(
5623 req, NT_STATUS_INVALID_PARAMETER);
5624 return;
5626 break;
5629 case SMB_QUERY_POSIX_LOCK:
5631 if (fsp == NULL || fsp->fh->fd == -1) {
5632 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5633 return;
5636 if (total_data != POSIX_LOCK_DATA_SIZE) {
5637 reply_nterror(
5638 req, NT_STATUS_INVALID_PARAMETER);
5639 return;
5642 /* Copy the lock range data. */
5643 lock_data = (char *)talloc_memdup(
5644 req, pdata, total_data);
5645 if (!lock_data) {
5646 reply_nterror(req, NT_STATUS_NO_MEMORY);
5647 return;
5649 lock_data_count = total_data;
5651 default:
5652 break;
5655 *pparams = (char *)SMB_REALLOC(*pparams,2);
5656 if (*pparams == NULL) {
5657 reply_nterror(req, NT_STATUS_NO_MEMORY);
5658 return;
5660 params = *pparams;
5661 SSVAL(params,0,0);
5664 * draft-leach-cifs-v1-spec-02.txt
5665 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5666 * says:
5668 * The requested information is placed in the Data portion of the
5669 * transaction response. For the information levels greater than 0x100,
5670 * the transaction response has 1 parameter word which should be
5671 * ignored by the client.
5673 * However Windows only follows this rule for the IS_NAME_VALID call.
5675 switch (info_level) {
5676 case SMB_INFO_IS_NAME_VALID:
5677 param_size = 0;
5678 break;
5681 if ((info_level & 0xFF00) == 0xFF00) {
5683 * We use levels that start with 0xFF00
5684 * internally to represent SMB2 specific levels
5686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5687 return;
5690 status = smbd_do_qfilepathinfo(conn, req, info_level,
5691 fsp, smb_fname,
5692 delete_pending, write_time_ts,
5693 ea_list,
5694 lock_data_count, lock_data,
5695 req->flags2, max_data_bytes,
5696 &fixed_portion,
5697 ppdata, &data_size);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 reply_nterror(req, status);
5700 return;
5702 if (fixed_portion > max_data_bytes) {
5703 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5704 return;
5707 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5708 max_data_bytes);
5710 return;
5713 /****************************************************************************
5714 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5715 code.
5716 ****************************************************************************/
5718 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5719 connection_struct *conn,
5720 struct smb_request *req,
5721 bool overwrite_if_exists,
5722 const struct smb_filename *smb_fname_old,
5723 struct smb_filename *smb_fname_new)
5725 NTSTATUS status = NT_STATUS_OK;
5727 /* source must already exist. */
5728 if (!VALID_STAT(smb_fname_old->st)) {
5729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5732 if (VALID_STAT(smb_fname_new->st)) {
5733 if (overwrite_if_exists) {
5734 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5735 return NT_STATUS_FILE_IS_A_DIRECTORY;
5737 status = unlink_internals(conn,
5738 req,
5739 FILE_ATTRIBUTE_NORMAL,
5740 smb_fname_new,
5741 false);
5742 if (!NT_STATUS_IS_OK(status)) {
5743 return status;
5745 } else {
5746 /* Disallow if newname already exists. */
5747 return NT_STATUS_OBJECT_NAME_COLLISION;
5751 /* No links from a directory. */
5752 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5753 return NT_STATUS_FILE_IS_A_DIRECTORY;
5756 /* Setting a hardlink to/from a stream isn't currently supported. */
5757 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5758 is_ntfs_stream_smb_fname(smb_fname_new)) {
5759 return NT_STATUS_INVALID_PARAMETER;
5762 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5763 smb_fname_old->base_name, smb_fname_new->base_name));
5765 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5766 smb_fname_new->base_name) != 0) {
5767 status = map_nt_error_from_unix(errno);
5768 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5769 nt_errstr(status), smb_fname_old->base_name,
5770 smb_fname_new->base_name));
5772 return status;
5775 /****************************************************************************
5776 Deal with setting the time from any of the setfilepathinfo functions.
5777 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5778 calling this function.
5779 ****************************************************************************/
5781 NTSTATUS smb_set_file_time(connection_struct *conn,
5782 files_struct *fsp,
5783 const struct smb_filename *smb_fname,
5784 struct smb_file_time *ft,
5785 bool setting_write_time)
5787 struct smb_filename smb_fname_base;
5788 uint32 action =
5789 FILE_NOTIFY_CHANGE_LAST_ACCESS
5790 |FILE_NOTIFY_CHANGE_LAST_WRITE
5791 |FILE_NOTIFY_CHANGE_CREATION;
5793 if (!VALID_STAT(smb_fname->st)) {
5794 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5797 /* get some defaults (no modifications) if any info is zero or -1. */
5798 if (null_timespec(ft->create_time)) {
5799 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5802 if (null_timespec(ft->atime)) {
5803 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5806 if (null_timespec(ft->mtime)) {
5807 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5810 if (!setting_write_time) {
5811 /* ft->mtime comes from change time, not write time. */
5812 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5815 /* Ensure the resolution is the correct for
5816 * what we can store on this filesystem. */
5818 round_timespec(conn->ts_res, &ft->create_time);
5819 round_timespec(conn->ts_res, &ft->ctime);
5820 round_timespec(conn->ts_res, &ft->atime);
5821 round_timespec(conn->ts_res, &ft->mtime);
5823 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5824 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5825 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5826 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5827 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5828 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5829 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5830 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5832 if (setting_write_time) {
5834 * This was a Windows setfileinfo on an open file.
5835 * NT does this a lot. We also need to
5836 * set the time here, as it can be read by
5837 * FindFirst/FindNext and with the patch for bug #2045
5838 * in smbd/fileio.c it ensures that this timestamp is
5839 * kept sticky even after a write. We save the request
5840 * away and will set it on file close and after a write. JRA.
5843 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5844 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5846 if (fsp != NULL) {
5847 if (fsp->base_fsp) {
5848 set_sticky_write_time_fsp(fsp->base_fsp,
5849 ft->mtime);
5850 } else {
5851 set_sticky_write_time_fsp(fsp, ft->mtime);
5853 } else {
5854 set_sticky_write_time_path(
5855 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5856 ft->mtime);
5860 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5862 /* Always call ntimes on the base, even if a stream was passed in. */
5863 smb_fname_base = *smb_fname;
5864 smb_fname_base.stream_name = NULL;
5866 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5867 return map_nt_error_from_unix(errno);
5870 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5871 smb_fname->base_name);
5872 return NT_STATUS_OK;
5875 /****************************************************************************
5876 Deal with setting the dosmode from any of the setfilepathinfo functions.
5877 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5878 done before calling this function.
5879 ****************************************************************************/
5881 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5882 const struct smb_filename *smb_fname,
5883 uint32 dosmode)
5885 struct smb_filename *smb_fname_base;
5886 NTSTATUS status;
5888 if (!VALID_STAT(smb_fname->st)) {
5889 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5892 /* Always operate on the base_name, even if a stream was passed in. */
5893 smb_fname_base = synthetic_smb_fname(
5894 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5895 if (smb_fname_base == NULL) {
5896 return NT_STATUS_NO_MEMORY;
5899 if (dosmode) {
5900 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5901 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5902 } else {
5903 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5907 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5909 /* check the mode isn't different, before changing it */
5910 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5911 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5912 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5913 (unsigned int)dosmode));
5915 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5916 false)) {
5917 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5918 "%s failed (%s)\n",
5919 smb_fname_str_dbg(smb_fname_base),
5920 strerror(errno)));
5921 status = map_nt_error_from_unix(errno);
5922 goto out;
5925 status = NT_STATUS_OK;
5926 out:
5927 TALLOC_FREE(smb_fname_base);
5928 return status;
5931 /****************************************************************************
5932 Deal with setting the size from any of the setfilepathinfo functions.
5933 ****************************************************************************/
5935 static NTSTATUS smb_set_file_size(connection_struct *conn,
5936 struct smb_request *req,
5937 files_struct *fsp,
5938 const struct smb_filename *smb_fname,
5939 const SMB_STRUCT_STAT *psbuf,
5940 off_t size,
5941 bool fail_after_createfile)
5943 NTSTATUS status = NT_STATUS_OK;
5944 struct smb_filename *smb_fname_tmp = NULL;
5945 files_struct *new_fsp = NULL;
5947 if (!VALID_STAT(*psbuf)) {
5948 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5951 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5953 if (size == get_file_size_stat(psbuf)) {
5954 return NT_STATUS_OK;
5957 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5958 smb_fname_str_dbg(smb_fname), (double)size));
5960 if (fsp && fsp->fh->fd != -1) {
5961 /* Handle based call. */
5962 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5963 return NT_STATUS_ACCESS_DENIED;
5966 if (vfs_set_filelen(fsp, size) == -1) {
5967 return map_nt_error_from_unix(errno);
5969 trigger_write_time_update_immediate(fsp);
5970 return NT_STATUS_OK;
5973 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5974 if (smb_fname_tmp == NULL) {
5975 return NT_STATUS_NO_MEMORY;
5978 smb_fname_tmp->st = *psbuf;
5980 status = SMB_VFS_CREATE_FILE(
5981 conn, /* conn */
5982 req, /* req */
5983 0, /* root_dir_fid */
5984 smb_fname_tmp, /* fname */
5985 FILE_WRITE_DATA, /* access_mask */
5986 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5987 FILE_SHARE_DELETE),
5988 FILE_OPEN, /* create_disposition*/
5989 0, /* create_options */
5990 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5991 0, /* oplock_request */
5992 NULL, /* lease */
5993 0, /* allocation_size */
5994 0, /* private_flags */
5995 NULL, /* sd */
5996 NULL, /* ea_list */
5997 &new_fsp, /* result */
5998 NULL); /* pinfo */
6000 TALLOC_FREE(smb_fname_tmp);
6002 if (!NT_STATUS_IS_OK(status)) {
6003 /* NB. We check for open_was_deferred in the caller. */
6004 return status;
6007 /* See RAW-SFILEINFO-END-OF-FILE */
6008 if (fail_after_createfile) {
6009 close_file(req, new_fsp,NORMAL_CLOSE);
6010 return NT_STATUS_INVALID_LEVEL;
6013 if (vfs_set_filelen(new_fsp, size) == -1) {
6014 status = map_nt_error_from_unix(errno);
6015 close_file(req, new_fsp,NORMAL_CLOSE);
6016 return status;
6019 trigger_write_time_update_immediate(new_fsp);
6020 close_file(req, new_fsp,NORMAL_CLOSE);
6021 return NT_STATUS_OK;
6024 /****************************************************************************
6025 Deal with SMB_INFO_SET_EA.
6026 ****************************************************************************/
6028 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6029 const char *pdata,
6030 int total_data,
6031 files_struct *fsp,
6032 const struct smb_filename *smb_fname)
6034 struct ea_list *ea_list = NULL;
6035 TALLOC_CTX *ctx = NULL;
6036 NTSTATUS status = NT_STATUS_OK;
6038 if (total_data < 10) {
6040 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6041 length. They seem to have no effect. Bug #3212. JRA */
6043 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6044 /* We're done. We only get EA info in this call. */
6045 return NT_STATUS_OK;
6048 return NT_STATUS_INVALID_PARAMETER;
6051 if (IVAL(pdata,0) > total_data) {
6052 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6053 IVAL(pdata,0), (unsigned int)total_data));
6054 return NT_STATUS_INVALID_PARAMETER;
6057 ctx = talloc_tos();
6058 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6059 if (!ea_list) {
6060 return NT_STATUS_INVALID_PARAMETER;
6063 status = set_ea(conn, fsp, smb_fname, ea_list);
6065 return status;
6068 /****************************************************************************
6069 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6070 ****************************************************************************/
6072 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6073 const char *pdata,
6074 int total_data,
6075 files_struct *fsp)
6077 struct ea_list *ea_list = NULL;
6078 NTSTATUS status;
6080 if (!fsp) {
6081 return NT_STATUS_INVALID_HANDLE;
6084 if (!lp_ea_support(SNUM(conn))) {
6085 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6086 "EA's not supported.\n",
6087 (unsigned int)total_data));
6088 return NT_STATUS_EAS_NOT_SUPPORTED;
6091 if (total_data < 10) {
6092 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6093 "too small.\n",
6094 (unsigned int)total_data));
6095 return NT_STATUS_INVALID_PARAMETER;
6098 ea_list = read_nttrans_ea_list(talloc_tos(),
6099 pdata,
6100 total_data);
6102 if (!ea_list) {
6103 return NT_STATUS_INVALID_PARAMETER;
6106 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6108 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6109 smb_fname_str_dbg(fsp->fsp_name),
6110 nt_errstr(status) ));
6112 return status;
6116 /****************************************************************************
6117 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6118 ****************************************************************************/
6120 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6121 const char *pdata,
6122 int total_data,
6123 files_struct *fsp,
6124 struct smb_filename *smb_fname)
6126 NTSTATUS status = NT_STATUS_OK;
6127 bool delete_on_close;
6128 uint32 dosmode = 0;
6130 if (total_data < 1) {
6131 return NT_STATUS_INVALID_PARAMETER;
6134 if (fsp == NULL) {
6135 return NT_STATUS_INVALID_HANDLE;
6138 delete_on_close = (CVAL(pdata,0) ? True : False);
6139 dosmode = dos_mode(conn, smb_fname);
6141 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6142 "delete_on_close = %u\n",
6143 smb_fname_str_dbg(smb_fname),
6144 (unsigned int)dosmode,
6145 (unsigned int)delete_on_close ));
6147 if (delete_on_close) {
6148 status = can_set_delete_on_close(fsp, dosmode);
6149 if (!NT_STATUS_IS_OK(status)) {
6150 return status;
6154 /* The set is across all open files on this dev/inode pair. */
6155 if (!set_delete_on_close(fsp, delete_on_close,
6156 conn->session_info->security_token,
6157 conn->session_info->unix_token)) {
6158 return NT_STATUS_ACCESS_DENIED;
6160 return NT_STATUS_OK;
6163 /****************************************************************************
6164 Deal with SMB_FILE_POSITION_INFORMATION.
6165 ****************************************************************************/
6167 static NTSTATUS smb_file_position_information(connection_struct *conn,
6168 const char *pdata,
6169 int total_data,
6170 files_struct *fsp)
6172 uint64_t position_information;
6174 if (total_data < 8) {
6175 return NT_STATUS_INVALID_PARAMETER;
6178 if (fsp == NULL) {
6179 /* Ignore on pathname based set. */
6180 return NT_STATUS_OK;
6183 position_information = (uint64_t)IVAL(pdata,0);
6184 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6186 DEBUG(10,("smb_file_position_information: Set file position "
6187 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6188 (double)position_information));
6189 fsp->fh->position_information = position_information;
6190 return NT_STATUS_OK;
6193 /****************************************************************************
6194 Deal with SMB_FILE_MODE_INFORMATION.
6195 ****************************************************************************/
6197 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6198 const char *pdata,
6199 int total_data)
6201 uint32 mode;
6203 if (total_data < 4) {
6204 return NT_STATUS_INVALID_PARAMETER;
6206 mode = IVAL(pdata,0);
6207 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6208 return NT_STATUS_INVALID_PARAMETER;
6210 return NT_STATUS_OK;
6213 /****************************************************************************
6214 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6215 ****************************************************************************/
6217 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6218 struct smb_request *req,
6219 const char *pdata,
6220 int total_data,
6221 const struct smb_filename *smb_fname)
6223 char *link_target = NULL;
6224 const char *newname = smb_fname->base_name;
6225 TALLOC_CTX *ctx = talloc_tos();
6227 /* Set a symbolic link. */
6228 /* Don't allow this if follow links is false. */
6230 if (total_data == 0) {
6231 return NT_STATUS_INVALID_PARAMETER;
6234 if (!lp_follow_symlinks(SNUM(conn))) {
6235 return NT_STATUS_ACCESS_DENIED;
6238 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6239 total_data, STR_TERMINATE);
6241 if (!link_target) {
6242 return NT_STATUS_INVALID_PARAMETER;
6245 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6246 newname, link_target ));
6248 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6249 return map_nt_error_from_unix(errno);
6252 return NT_STATUS_OK;
6255 /****************************************************************************
6256 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6257 ****************************************************************************/
6259 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6260 struct smb_request *req,
6261 const char *pdata, int total_data,
6262 struct smb_filename *smb_fname_new)
6264 char *oldname = NULL;
6265 struct smb_filename *smb_fname_old = NULL;
6266 TALLOC_CTX *ctx = talloc_tos();
6267 NTSTATUS status = NT_STATUS_OK;
6269 /* Set a hard link. */
6270 if (total_data == 0) {
6271 return NT_STATUS_INVALID_PARAMETER;
6274 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6275 total_data, STR_TERMINATE, &status);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 return status;
6280 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6281 smb_fname_str_dbg(smb_fname_new), oldname));
6283 status = filename_convert(ctx,
6284 conn,
6285 req->flags2 & FLAGS2_DFS_PATHNAMES,
6286 oldname,
6288 NULL,
6289 &smb_fname_old);
6290 if (!NT_STATUS_IS_OK(status)) {
6291 return status;
6294 return hardlink_internals(ctx, conn, req, false,
6295 smb_fname_old, smb_fname_new);
6298 /****************************************************************************
6299 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6300 ****************************************************************************/
6302 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6303 struct smb_request *req,
6304 const char *pdata,
6305 int total_data,
6306 files_struct *fsp,
6307 struct smb_filename *smb_fname_src)
6309 bool overwrite;
6310 uint32_t len;
6311 char *newname = NULL;
6312 struct smb_filename *smb_fname_dst = NULL;
6313 NTSTATUS status = NT_STATUS_OK;
6314 TALLOC_CTX *ctx = talloc_tos();
6316 if (!fsp) {
6317 return NT_STATUS_INVALID_HANDLE;
6320 if (total_data < 20) {
6321 return NT_STATUS_INVALID_PARAMETER;
6324 overwrite = (CVAL(pdata,0) ? True : False);
6325 len = IVAL(pdata,16);
6327 if (len > (total_data - 20) || (len == 0)) {
6328 return NT_STATUS_INVALID_PARAMETER;
6331 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6332 &pdata[20], len, STR_TERMINATE,
6333 &status);
6334 if (!NT_STATUS_IS_OK(status)) {
6335 return status;
6338 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6339 newname));
6341 status = filename_convert(ctx,
6342 conn,
6343 req->flags2 & FLAGS2_DFS_PATHNAMES,
6344 newname,
6345 UCF_SAVE_LCOMP,
6346 NULL,
6347 &smb_fname_dst);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 return status;
6352 if (fsp->base_fsp) {
6353 /* newname must be a stream name. */
6354 if (newname[0] != ':') {
6355 return NT_STATUS_NOT_SUPPORTED;
6358 /* Create an smb_fname to call rename_internals_fsp() with. */
6359 smb_fname_dst = synthetic_smb_fname(
6360 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6361 newname, NULL);
6362 if (smb_fname_dst == NULL) {
6363 status = NT_STATUS_NO_MEMORY;
6364 goto out;
6368 * Set the original last component, since
6369 * rename_internals_fsp() requires it.
6371 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6372 newname);
6373 if (smb_fname_dst->original_lcomp == NULL) {
6374 status = NT_STATUS_NO_MEMORY;
6375 goto out;
6380 DEBUG(10,("smb2_file_rename_information: "
6381 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6382 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6383 smb_fname_str_dbg(smb_fname_dst)));
6384 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6385 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6386 overwrite);
6388 out:
6389 TALLOC_FREE(smb_fname_dst);
6390 return status;
6393 static NTSTATUS smb_file_link_information(connection_struct *conn,
6394 struct smb_request *req,
6395 const char *pdata,
6396 int total_data,
6397 files_struct *fsp,
6398 struct smb_filename *smb_fname_src)
6400 bool overwrite;
6401 uint32_t len;
6402 char *newname = NULL;
6403 struct smb_filename *smb_fname_dst = NULL;
6404 NTSTATUS status = NT_STATUS_OK;
6405 TALLOC_CTX *ctx = talloc_tos();
6407 if (!fsp) {
6408 return NT_STATUS_INVALID_HANDLE;
6411 if (total_data < 20) {
6412 return NT_STATUS_INVALID_PARAMETER;
6415 overwrite = (CVAL(pdata,0) ? true : false);
6416 len = IVAL(pdata,16);
6418 if (len > (total_data - 20) || (len == 0)) {
6419 return NT_STATUS_INVALID_PARAMETER;
6422 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6423 &pdata[20], len, STR_TERMINATE,
6424 &status);
6425 if (!NT_STATUS_IS_OK(status)) {
6426 return status;
6429 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6430 newname));
6432 status = filename_convert(ctx,
6433 conn,
6434 req->flags2 & FLAGS2_DFS_PATHNAMES,
6435 newname,
6436 UCF_SAVE_LCOMP,
6437 NULL,
6438 &smb_fname_dst);
6439 if (!NT_STATUS_IS_OK(status)) {
6440 return status;
6443 if (fsp->base_fsp) {
6444 /* No stream names. */
6445 return NT_STATUS_NOT_SUPPORTED;
6448 DEBUG(10,("smb_file_link_information: "
6449 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6450 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6451 smb_fname_str_dbg(smb_fname_dst)));
6452 status = hardlink_internals(ctx,
6453 conn,
6454 req,
6455 overwrite,
6456 fsp->fsp_name,
6457 smb_fname_dst);
6459 TALLOC_FREE(smb_fname_dst);
6460 return status;
6463 /****************************************************************************
6464 Deal with SMB_FILE_RENAME_INFORMATION.
6465 ****************************************************************************/
6467 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6468 struct smb_request *req,
6469 const char *pdata,
6470 int total_data,
6471 files_struct *fsp,
6472 struct smb_filename *smb_fname_src)
6474 bool overwrite;
6475 uint32 root_fid;
6476 uint32 len;
6477 char *newname = NULL;
6478 struct smb_filename *smb_fname_dst = NULL;
6479 bool dest_has_wcard = False;
6480 NTSTATUS status = NT_STATUS_OK;
6481 char *p;
6482 TALLOC_CTX *ctx = talloc_tos();
6484 if (total_data < 13) {
6485 return NT_STATUS_INVALID_PARAMETER;
6488 overwrite = (CVAL(pdata,0) ? True : False);
6489 root_fid = IVAL(pdata,4);
6490 len = IVAL(pdata,8);
6492 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6493 return NT_STATUS_INVALID_PARAMETER;
6496 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6497 len, 0, &status,
6498 &dest_has_wcard);
6499 if (!NT_STATUS_IS_OK(status)) {
6500 return status;
6503 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6504 newname));
6506 status = resolve_dfspath_wcard(ctx, conn,
6507 req->flags2 & FLAGS2_DFS_PATHNAMES,
6508 newname,
6509 true,
6510 !conn->sconn->using_smb2,
6511 &newname,
6512 &dest_has_wcard);
6513 if (!NT_STATUS_IS_OK(status)) {
6514 return status;
6517 /* Check the new name has no '/' characters. */
6518 if (strchr_m(newname, '/')) {
6519 return NT_STATUS_NOT_SUPPORTED;
6522 if (fsp && fsp->base_fsp) {
6523 /* newname must be a stream name. */
6524 if (newname[0] != ':') {
6525 return NT_STATUS_NOT_SUPPORTED;
6528 /* Create an smb_fname to call rename_internals_fsp() with. */
6529 smb_fname_dst = synthetic_smb_fname(
6530 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6531 newname, NULL);
6532 if (smb_fname_dst == NULL) {
6533 status = NT_STATUS_NO_MEMORY;
6534 goto out;
6538 * Set the original last component, since
6539 * rename_internals_fsp() requires it.
6541 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6542 newname);
6543 if (smb_fname_dst->original_lcomp == NULL) {
6544 status = NT_STATUS_NO_MEMORY;
6545 goto out;
6548 } else {
6550 * Build up an smb_fname_dst based on the filename passed in.
6551 * We basically just strip off the last component, and put on
6552 * the newname instead.
6554 char *base_name = NULL;
6556 /* newname must *not* be a stream name. */
6557 if (newname[0] == ':') {
6558 return NT_STATUS_NOT_SUPPORTED;
6562 * Strip off the last component (filename) of the path passed
6563 * in.
6565 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6566 if (!base_name) {
6567 return NT_STATUS_NO_MEMORY;
6569 p = strrchr_m(base_name, '/');
6570 if (p) {
6571 p[1] = '\0';
6572 } else {
6573 base_name = talloc_strdup(ctx, "");
6574 if (!base_name) {
6575 return NT_STATUS_NO_MEMORY;
6578 /* Append the new name. */
6579 base_name = talloc_asprintf_append(base_name,
6580 "%s",
6581 newname);
6582 if (!base_name) {
6583 return NT_STATUS_NO_MEMORY;
6586 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6587 (UCF_SAVE_LCOMP |
6588 (dest_has_wcard ?
6589 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6590 0)));
6592 /* If an error we expect this to be
6593 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6595 if (!NT_STATUS_IS_OK(status)) {
6596 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6597 status)) {
6598 goto out;
6600 /* Create an smb_fname to call rename_internals_fsp() */
6601 smb_fname_dst = synthetic_smb_fname(
6602 ctx, base_name, NULL, NULL);
6603 if (smb_fname_dst == NULL) {
6604 status = NT_STATUS_NO_MEMORY;
6605 goto out;
6610 if (fsp) {
6611 DEBUG(10,("smb_file_rename_information: "
6612 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6613 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6614 smb_fname_str_dbg(smb_fname_dst)));
6615 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6616 overwrite);
6617 } else {
6618 DEBUG(10,("smb_file_rename_information: "
6619 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6620 smb_fname_str_dbg(smb_fname_src),
6621 smb_fname_str_dbg(smb_fname_dst)));
6622 status = rename_internals(ctx, conn, req, smb_fname_src,
6623 smb_fname_dst, 0, overwrite, false,
6624 dest_has_wcard,
6625 FILE_WRITE_ATTRIBUTES);
6627 out:
6628 TALLOC_FREE(smb_fname_dst);
6629 return status;
6632 /****************************************************************************
6633 Deal with SMB_SET_POSIX_ACL.
6634 ****************************************************************************/
6636 #if defined(HAVE_POSIX_ACLS)
6637 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6638 const char *pdata,
6639 int total_data,
6640 files_struct *fsp,
6641 const struct smb_filename *smb_fname)
6643 uint16 posix_acl_version;
6644 uint16 num_file_acls;
6645 uint16 num_def_acls;
6646 bool valid_file_acls = True;
6647 bool valid_def_acls = True;
6649 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6650 return NT_STATUS_INVALID_PARAMETER;
6652 posix_acl_version = SVAL(pdata,0);
6653 num_file_acls = SVAL(pdata,2);
6654 num_def_acls = SVAL(pdata,4);
6656 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6657 valid_file_acls = False;
6658 num_file_acls = 0;
6661 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6662 valid_def_acls = False;
6663 num_def_acls = 0;
6666 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6667 return NT_STATUS_INVALID_PARAMETER;
6670 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6671 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6672 return NT_STATUS_INVALID_PARAMETER;
6675 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6676 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6677 (unsigned int)num_file_acls,
6678 (unsigned int)num_def_acls));
6680 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6681 smb_fname->base_name, num_file_acls,
6682 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6683 return map_nt_error_from_unix(errno);
6686 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6687 smb_fname->base_name, &smb_fname->st, num_def_acls,
6688 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6689 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6690 return map_nt_error_from_unix(errno);
6692 return NT_STATUS_OK;
6694 #endif
6696 /****************************************************************************
6697 Deal with SMB_SET_POSIX_LOCK.
6698 ****************************************************************************/
6700 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6701 struct smb_request *req,
6702 const char *pdata,
6703 int total_data,
6704 files_struct *fsp)
6706 uint64_t count;
6707 uint64_t offset;
6708 uint64_t smblctx;
6709 bool blocking_lock = False;
6710 enum brl_type lock_type;
6712 NTSTATUS status = NT_STATUS_OK;
6714 if (fsp == NULL || fsp->fh->fd == -1) {
6715 return NT_STATUS_INVALID_HANDLE;
6718 if (total_data != POSIX_LOCK_DATA_SIZE) {
6719 return NT_STATUS_INVALID_PARAMETER;
6722 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6723 case POSIX_LOCK_TYPE_READ:
6724 lock_type = READ_LOCK;
6725 break;
6726 case POSIX_LOCK_TYPE_WRITE:
6727 /* Return the right POSIX-mappable error code for files opened read-only. */
6728 if (!fsp->can_write) {
6729 return NT_STATUS_INVALID_HANDLE;
6731 lock_type = WRITE_LOCK;
6732 break;
6733 case POSIX_LOCK_TYPE_UNLOCK:
6734 lock_type = UNLOCK_LOCK;
6735 break;
6736 default:
6737 return NT_STATUS_INVALID_PARAMETER;
6740 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6741 blocking_lock = False;
6742 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6743 blocking_lock = True;
6744 } else {
6745 return NT_STATUS_INVALID_PARAMETER;
6748 if (!lp_blocking_locks(SNUM(conn))) {
6749 blocking_lock = False;
6752 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6753 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6754 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6755 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6756 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6758 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6759 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6760 fsp_str_dbg(fsp),
6761 (unsigned int)lock_type,
6762 (unsigned long long)smblctx,
6763 (double)count,
6764 (double)offset ));
6766 if (lock_type == UNLOCK_LOCK) {
6767 status = do_unlock(req->sconn->msg_ctx,
6768 fsp,
6769 smblctx,
6770 count,
6771 offset,
6772 POSIX_LOCK);
6773 } else {
6774 uint64_t block_smblctx;
6776 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6777 fsp,
6778 smblctx,
6779 count,
6780 offset,
6781 lock_type,
6782 POSIX_LOCK,
6783 blocking_lock,
6784 &status,
6785 &block_smblctx);
6787 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6789 * A blocking lock was requested. Package up
6790 * this smb into a queued request and push it
6791 * onto the blocking lock queue.
6793 if(push_blocking_lock_request(br_lck,
6794 req,
6795 fsp,
6796 -1, /* infinite timeout. */
6798 smblctx,
6799 lock_type,
6800 POSIX_LOCK,
6801 offset,
6802 count,
6803 block_smblctx)) {
6804 TALLOC_FREE(br_lck);
6805 return status;
6808 TALLOC_FREE(br_lck);
6811 return status;
6814 /****************************************************************************
6815 Deal with SMB_SET_FILE_BASIC_INFO.
6816 ****************************************************************************/
6818 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6819 const char *pdata,
6820 int total_data,
6821 files_struct *fsp,
6822 const struct smb_filename *smb_fname)
6824 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6825 struct smb_file_time ft;
6826 uint32 dosmode = 0;
6827 NTSTATUS status = NT_STATUS_OK;
6829 ZERO_STRUCT(ft);
6831 if (total_data < 36) {
6832 return NT_STATUS_INVALID_PARAMETER;
6835 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 return status;
6840 /* Set the attributes */
6841 dosmode = IVAL(pdata,32);
6842 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6843 if (!NT_STATUS_IS_OK(status)) {
6844 return status;
6847 /* create time */
6848 ft.create_time = interpret_long_date(pdata);
6850 /* access time */
6851 ft.atime = interpret_long_date(pdata+8);
6853 /* write time. */
6854 ft.mtime = interpret_long_date(pdata+16);
6856 /* change time. */
6857 ft.ctime = interpret_long_date(pdata+24);
6859 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6860 smb_fname_str_dbg(smb_fname)));
6862 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6863 true);
6866 /****************************************************************************
6867 Deal with SMB_INFO_STANDARD.
6868 ****************************************************************************/
6870 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6871 const char *pdata,
6872 int total_data,
6873 files_struct *fsp,
6874 const struct smb_filename *smb_fname)
6876 NTSTATUS status;
6877 struct smb_file_time ft;
6879 ZERO_STRUCT(ft);
6881 if (total_data < 12) {
6882 return NT_STATUS_INVALID_PARAMETER;
6885 /* create time */
6886 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6887 /* access time */
6888 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6889 /* write time */
6890 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6892 DEBUG(10,("smb_set_info_standard: file %s\n",
6893 smb_fname_str_dbg(smb_fname)));
6895 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6896 if (!NT_STATUS_IS_OK(status)) {
6897 return status;
6900 return smb_set_file_time(conn,
6901 fsp,
6902 smb_fname,
6903 &ft,
6904 true);
6907 /****************************************************************************
6908 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6909 ****************************************************************************/
6911 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6912 struct smb_request *req,
6913 const char *pdata,
6914 int total_data,
6915 files_struct *fsp,
6916 struct smb_filename *smb_fname)
6918 uint64_t allocation_size = 0;
6919 NTSTATUS status = NT_STATUS_OK;
6920 files_struct *new_fsp = NULL;
6922 if (!VALID_STAT(smb_fname->st)) {
6923 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6926 if (total_data < 8) {
6927 return NT_STATUS_INVALID_PARAMETER;
6930 allocation_size = (uint64_t)IVAL(pdata,0);
6931 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6932 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6933 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6934 (double)allocation_size));
6936 if (allocation_size) {
6937 allocation_size = smb_roundup(conn, allocation_size);
6940 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6941 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6942 (double)allocation_size));
6944 if (fsp && fsp->fh->fd != -1) {
6945 /* Open file handle. */
6946 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6947 return NT_STATUS_ACCESS_DENIED;
6950 /* Only change if needed. */
6951 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6952 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6953 return map_nt_error_from_unix(errno);
6956 /* But always update the time. */
6958 * This is equivalent to a write. Ensure it's seen immediately
6959 * if there are no pending writes.
6961 trigger_write_time_update_immediate(fsp);
6962 return NT_STATUS_OK;
6965 /* Pathname or stat or directory file. */
6966 status = SMB_VFS_CREATE_FILE(
6967 conn, /* conn */
6968 req, /* req */
6969 0, /* root_dir_fid */
6970 smb_fname, /* fname */
6971 FILE_WRITE_DATA, /* access_mask */
6972 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6973 FILE_SHARE_DELETE),
6974 FILE_OPEN, /* create_disposition*/
6975 0, /* create_options */
6976 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6977 0, /* oplock_request */
6978 NULL, /* lease */
6979 0, /* allocation_size */
6980 0, /* private_flags */
6981 NULL, /* sd */
6982 NULL, /* ea_list */
6983 &new_fsp, /* result */
6984 NULL); /* pinfo */
6986 if (!NT_STATUS_IS_OK(status)) {
6987 /* NB. We check for open_was_deferred in the caller. */
6988 return status;
6991 /* Only change if needed. */
6992 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6993 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6994 status = map_nt_error_from_unix(errno);
6995 close_file(req, new_fsp, NORMAL_CLOSE);
6996 return status;
7000 /* Changing the allocation size should set the last mod time. */
7002 * This is equivalent to a write. Ensure it's seen immediately
7003 * if there are no pending writes.
7005 trigger_write_time_update_immediate(new_fsp);
7006 close_file(req, new_fsp, NORMAL_CLOSE);
7007 return NT_STATUS_OK;
7010 /****************************************************************************
7011 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7012 ****************************************************************************/
7014 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7015 struct smb_request *req,
7016 const char *pdata,
7017 int total_data,
7018 files_struct *fsp,
7019 const struct smb_filename *smb_fname,
7020 bool fail_after_createfile)
7022 off_t size;
7024 if (total_data < 8) {
7025 return NT_STATUS_INVALID_PARAMETER;
7028 size = IVAL(pdata,0);
7029 size |= (((off_t)IVAL(pdata,4)) << 32);
7030 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7031 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7032 (double)size));
7034 return smb_set_file_size(conn, req,
7035 fsp,
7036 smb_fname,
7037 &smb_fname->st,
7038 size,
7039 fail_after_createfile);
7042 /****************************************************************************
7043 Allow a UNIX info mknod.
7044 ****************************************************************************/
7046 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7047 const char *pdata,
7048 int total_data,
7049 const struct smb_filename *smb_fname)
7051 uint32 file_type = IVAL(pdata,56);
7052 #if defined(HAVE_MAKEDEV)
7053 uint32 dev_major = IVAL(pdata,60);
7054 uint32 dev_minor = IVAL(pdata,68);
7055 #endif
7056 SMB_DEV_T dev = (SMB_DEV_T)0;
7057 uint32 raw_unixmode = IVAL(pdata,84);
7058 NTSTATUS status;
7059 mode_t unixmode;
7061 if (total_data < 100) {
7062 return NT_STATUS_INVALID_PARAMETER;
7065 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7066 PERM_NEW_FILE, &unixmode);
7067 if (!NT_STATUS_IS_OK(status)) {
7068 return status;
7071 #if defined(HAVE_MAKEDEV)
7072 dev = makedev(dev_major, dev_minor);
7073 #endif
7075 switch (file_type) {
7076 #if defined(S_IFIFO)
7077 case UNIX_TYPE_FIFO:
7078 unixmode |= S_IFIFO;
7079 break;
7080 #endif
7081 #if defined(S_IFSOCK)
7082 case UNIX_TYPE_SOCKET:
7083 unixmode |= S_IFSOCK;
7084 break;
7085 #endif
7086 #if defined(S_IFCHR)
7087 case UNIX_TYPE_CHARDEV:
7088 unixmode |= S_IFCHR;
7089 break;
7090 #endif
7091 #if defined(S_IFBLK)
7092 case UNIX_TYPE_BLKDEV:
7093 unixmode |= S_IFBLK;
7094 break;
7095 #endif
7096 default:
7097 return NT_STATUS_INVALID_PARAMETER;
7100 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7101 "%.0f mode 0%o for file %s\n", (double)dev,
7102 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7104 /* Ok - do the mknod. */
7105 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7106 return map_nt_error_from_unix(errno);
7109 /* If any of the other "set" calls fail we
7110 * don't want to end up with a half-constructed mknod.
7113 if (lp_inherit_permissions(SNUM(conn))) {
7114 char *parent;
7115 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7116 &parent, NULL)) {
7117 return NT_STATUS_NO_MEMORY;
7119 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7120 unixmode);
7121 TALLOC_FREE(parent);
7124 return NT_STATUS_OK;
7127 /****************************************************************************
7128 Deal with SMB_SET_FILE_UNIX_BASIC.
7129 ****************************************************************************/
7131 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7132 struct smb_request *req,
7133 const char *pdata,
7134 int total_data,
7135 files_struct *fsp,
7136 const struct smb_filename *smb_fname)
7138 struct smb_file_time ft;
7139 uint32 raw_unixmode;
7140 mode_t unixmode;
7141 off_t size = 0;
7142 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7143 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7144 NTSTATUS status = NT_STATUS_OK;
7145 bool delete_on_fail = False;
7146 enum perm_type ptype;
7147 files_struct *all_fsps = NULL;
7148 bool modify_mtime = true;
7149 struct file_id id;
7150 struct smb_filename *smb_fname_tmp = NULL;
7151 SMB_STRUCT_STAT sbuf;
7153 ZERO_STRUCT(ft);
7155 if (total_data < 100) {
7156 return NT_STATUS_INVALID_PARAMETER;
7159 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7160 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7161 size=IVAL(pdata,0); /* first 8 Bytes are size */
7162 size |= (((off_t)IVAL(pdata,4)) << 32);
7165 ft.atime = interpret_long_date(pdata+24); /* access_time */
7166 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7167 set_owner = (uid_t)IVAL(pdata,40);
7168 set_grp = (gid_t)IVAL(pdata,48);
7169 raw_unixmode = IVAL(pdata,84);
7171 if (VALID_STAT(smb_fname->st)) {
7172 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7173 ptype = PERM_EXISTING_DIR;
7174 } else {
7175 ptype = PERM_EXISTING_FILE;
7177 } else {
7178 ptype = PERM_NEW_FILE;
7181 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7182 ptype, &unixmode);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 return status;
7187 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7188 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7189 smb_fname_str_dbg(smb_fname), (double)size,
7190 (unsigned int)set_owner, (unsigned int)set_grp,
7191 (int)raw_unixmode));
7193 sbuf = smb_fname->st;
7195 if (!VALID_STAT(sbuf)) {
7197 * The only valid use of this is to create character and block
7198 * devices, and named pipes. This is deprecated (IMHO) and
7199 * a new info level should be used for mknod. JRA.
7202 status = smb_unix_mknod(conn,
7203 pdata,
7204 total_data,
7205 smb_fname);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 return status;
7210 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7211 if (smb_fname_tmp == NULL) {
7212 return NT_STATUS_NO_MEMORY;
7215 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7216 status = map_nt_error_from_unix(errno);
7217 TALLOC_FREE(smb_fname_tmp);
7218 SMB_VFS_UNLINK(conn, smb_fname);
7219 return status;
7222 sbuf = smb_fname_tmp->st;
7223 smb_fname = smb_fname_tmp;
7225 /* Ensure we don't try and change anything else. */
7226 raw_unixmode = SMB_MODE_NO_CHANGE;
7227 size = get_file_size_stat(&sbuf);
7228 ft.atime = sbuf.st_ex_atime;
7229 ft.mtime = sbuf.st_ex_mtime;
7231 * We continue here as we might want to change the
7232 * owner uid/gid.
7234 delete_on_fail = True;
7237 #if 1
7238 /* Horrible backwards compatibility hack as an old server bug
7239 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7240 * */
7242 if (!size) {
7243 size = get_file_size_stat(&sbuf);
7245 #endif
7248 * Deal with the UNIX specific mode set.
7251 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7252 int ret;
7254 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7255 "setting mode 0%o for file %s\n",
7256 (unsigned int)unixmode,
7257 smb_fname_str_dbg(smb_fname)));
7258 if (fsp && fsp->fh->fd != -1) {
7259 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7260 } else {
7261 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7263 if (ret != 0) {
7264 return map_nt_error_from_unix(errno);
7269 * Deal with the UNIX specific uid set.
7272 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7273 (sbuf.st_ex_uid != set_owner)) {
7274 int ret;
7276 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7277 "changing owner %u for path %s\n",
7278 (unsigned int)set_owner,
7279 smb_fname_str_dbg(smb_fname)));
7281 if (fsp && fsp->fh->fd != -1) {
7282 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7283 } else {
7285 * UNIX extensions calls must always operate
7286 * on symlinks.
7288 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7289 set_owner, (gid_t)-1);
7292 if (ret != 0) {
7293 status = map_nt_error_from_unix(errno);
7294 if (delete_on_fail) {
7295 SMB_VFS_UNLINK(conn, smb_fname);
7297 return status;
7302 * Deal with the UNIX specific gid set.
7305 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7306 (sbuf.st_ex_gid != set_grp)) {
7307 int ret;
7309 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7310 "changing group %u for file %s\n",
7311 (unsigned int)set_owner,
7312 smb_fname_str_dbg(smb_fname)));
7313 if (fsp && fsp->fh->fd != -1) {
7314 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7315 } else {
7317 * UNIX extensions calls must always operate
7318 * on symlinks.
7320 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7321 set_grp);
7323 if (ret != 0) {
7324 status = map_nt_error_from_unix(errno);
7325 if (delete_on_fail) {
7326 SMB_VFS_UNLINK(conn, smb_fname);
7328 return status;
7332 /* Deal with any size changes. */
7334 status = smb_set_file_size(conn, req,
7335 fsp,
7336 smb_fname,
7337 &sbuf,
7338 size,
7339 false);
7340 if (!NT_STATUS_IS_OK(status)) {
7341 return status;
7344 /* Deal with any time changes. */
7345 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7346 /* No change, don't cancel anything. */
7347 return status;
7350 id = vfs_file_id_from_sbuf(conn, &sbuf);
7351 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7352 all_fsps = file_find_di_next(all_fsps)) {
7354 * We're setting the time explicitly for UNIX.
7355 * Cancel any pending changes over all handles.
7357 all_fsps->update_write_time_on_close = false;
7358 TALLOC_FREE(all_fsps->update_write_time_event);
7362 * Override the "setting_write_time"
7363 * parameter here as it almost does what
7364 * we need. Just remember if we modified
7365 * mtime and send the notify ourselves.
7367 if (null_timespec(ft.mtime)) {
7368 modify_mtime = false;
7371 status = smb_set_file_time(conn,
7372 fsp,
7373 smb_fname,
7374 &ft,
7375 false);
7376 if (modify_mtime) {
7377 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7378 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7380 return status;
7383 /****************************************************************************
7384 Deal with SMB_SET_FILE_UNIX_INFO2.
7385 ****************************************************************************/
7387 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7388 struct smb_request *req,
7389 const char *pdata,
7390 int total_data,
7391 files_struct *fsp,
7392 const struct smb_filename *smb_fname)
7394 NTSTATUS status;
7395 uint32 smb_fflags;
7396 uint32 smb_fmask;
7398 if (total_data < 116) {
7399 return NT_STATUS_INVALID_PARAMETER;
7402 /* Start by setting all the fields that are common between UNIX_BASIC
7403 * and UNIX_INFO2.
7405 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7406 fsp, smb_fname);
7407 if (!NT_STATUS_IS_OK(status)) {
7408 return status;
7411 smb_fflags = IVAL(pdata, 108);
7412 smb_fmask = IVAL(pdata, 112);
7414 /* NB: We should only attempt to alter the file flags if the client
7415 * sends a non-zero mask.
7417 if (smb_fmask != 0) {
7418 int stat_fflags = 0;
7420 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7421 smb_fmask, &stat_fflags)) {
7422 /* Client asked to alter a flag we don't understand. */
7423 return NT_STATUS_INVALID_PARAMETER;
7426 if (fsp && fsp->fh->fd != -1) {
7427 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7428 return NT_STATUS_NOT_SUPPORTED;
7429 } else {
7430 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7431 stat_fflags) != 0) {
7432 return map_nt_error_from_unix(errno);
7437 /* XXX: need to add support for changing the create_time here. You
7438 * can do this for paths on Darwin with setattrlist(2). The right way
7439 * to hook this up is probably by extending the VFS utimes interface.
7442 return NT_STATUS_OK;
7445 /****************************************************************************
7446 Create a directory with POSIX semantics.
7447 ****************************************************************************/
7449 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7450 struct smb_request *req,
7451 char **ppdata,
7452 int total_data,
7453 struct smb_filename *smb_fname,
7454 int *pdata_return_size)
7456 NTSTATUS status = NT_STATUS_OK;
7457 uint32 raw_unixmode = 0;
7458 uint32 mod_unixmode = 0;
7459 mode_t unixmode = (mode_t)0;
7460 files_struct *fsp = NULL;
7461 uint16 info_level_return = 0;
7462 int info;
7463 char *pdata = *ppdata;
7465 if (total_data < 18) {
7466 return NT_STATUS_INVALID_PARAMETER;
7469 raw_unixmode = IVAL(pdata,8);
7470 /* Next 4 bytes are not yet defined. */
7472 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7473 PERM_NEW_DIR, &unixmode);
7474 if (!NT_STATUS_IS_OK(status)) {
7475 return status;
7478 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7480 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7481 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7483 status = SMB_VFS_CREATE_FILE(
7484 conn, /* conn */
7485 req, /* req */
7486 0, /* root_dir_fid */
7487 smb_fname, /* fname */
7488 FILE_READ_ATTRIBUTES, /* access_mask */
7489 FILE_SHARE_NONE, /* share_access */
7490 FILE_CREATE, /* create_disposition*/
7491 FILE_DIRECTORY_FILE, /* create_options */
7492 mod_unixmode, /* file_attributes */
7493 0, /* oplock_request */
7494 NULL, /* lease */
7495 0, /* allocation_size */
7496 0, /* private_flags */
7497 NULL, /* sd */
7498 NULL, /* ea_list */
7499 &fsp, /* result */
7500 &info); /* pinfo */
7502 if (NT_STATUS_IS_OK(status)) {
7503 close_file(req, fsp, NORMAL_CLOSE);
7506 info_level_return = SVAL(pdata,16);
7508 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7509 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7510 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7511 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7512 } else {
7513 *pdata_return_size = 12;
7516 /* Realloc the data size */
7517 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7518 if (*ppdata == NULL) {
7519 *pdata_return_size = 0;
7520 return NT_STATUS_NO_MEMORY;
7522 pdata = *ppdata;
7524 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7525 SSVAL(pdata,2,0); /* No fnum. */
7526 SIVAL(pdata,4,info); /* Was directory created. */
7528 switch (info_level_return) {
7529 case SMB_QUERY_FILE_UNIX_BASIC:
7530 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7531 SSVAL(pdata,10,0); /* Padding. */
7532 store_file_unix_basic(conn, pdata + 12, fsp,
7533 &smb_fname->st);
7534 break;
7535 case SMB_QUERY_FILE_UNIX_INFO2:
7536 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7537 SSVAL(pdata,10,0); /* Padding. */
7538 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7539 &smb_fname->st);
7540 break;
7541 default:
7542 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7543 SSVAL(pdata,10,0); /* Padding. */
7544 break;
7547 return status;
7550 /****************************************************************************
7551 Open/Create a file with POSIX semantics.
7552 ****************************************************************************/
7554 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7555 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7557 static NTSTATUS smb_posix_open(connection_struct *conn,
7558 struct smb_request *req,
7559 char **ppdata,
7560 int total_data,
7561 struct smb_filename *smb_fname,
7562 int *pdata_return_size)
7564 bool extended_oplock_granted = False;
7565 char *pdata = *ppdata;
7566 uint32 flags = 0;
7567 uint32 wire_open_mode = 0;
7568 uint32 raw_unixmode = 0;
7569 uint32 mod_unixmode = 0;
7570 uint32 create_disp = 0;
7571 uint32 access_mask = 0;
7572 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7573 NTSTATUS status = NT_STATUS_OK;
7574 mode_t unixmode = (mode_t)0;
7575 files_struct *fsp = NULL;
7576 int oplock_request = 0;
7577 int info = 0;
7578 uint16 info_level_return = 0;
7580 if (total_data < 18) {
7581 return NT_STATUS_INVALID_PARAMETER;
7584 flags = IVAL(pdata,0);
7585 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7586 if (oplock_request) {
7587 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7590 wire_open_mode = IVAL(pdata,4);
7592 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7593 return smb_posix_mkdir(conn, req,
7594 ppdata,
7595 total_data,
7596 smb_fname,
7597 pdata_return_size);
7600 switch (wire_open_mode & SMB_ACCMODE) {
7601 case SMB_O_RDONLY:
7602 access_mask = SMB_O_RDONLY_MAPPING;
7603 break;
7604 case SMB_O_WRONLY:
7605 access_mask = SMB_O_WRONLY_MAPPING;
7606 break;
7607 case SMB_O_RDWR:
7608 access_mask = (SMB_O_RDONLY_MAPPING|
7609 SMB_O_WRONLY_MAPPING);
7610 break;
7611 default:
7612 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7613 (unsigned int)wire_open_mode ));
7614 return NT_STATUS_INVALID_PARAMETER;
7617 wire_open_mode &= ~SMB_ACCMODE;
7619 /* First take care of O_CREAT|O_EXCL interactions. */
7620 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7621 case (SMB_O_CREAT | SMB_O_EXCL):
7622 /* File exists fail. File not exist create. */
7623 create_disp = FILE_CREATE;
7624 break;
7625 case SMB_O_CREAT:
7626 /* File exists open. File not exist create. */
7627 create_disp = FILE_OPEN_IF;
7628 break;
7629 case SMB_O_EXCL:
7630 /* O_EXCL on its own without O_CREAT is undefined.
7631 We deliberately ignore it as some versions of
7632 Linux CIFSFS can send a bare O_EXCL on the
7633 wire which other filesystems in the kernel
7634 ignore. See bug 9519 for details. */
7636 /* Fallthrough. */
7638 case 0:
7639 /* File exists open. File not exist fail. */
7640 create_disp = FILE_OPEN;
7641 break;
7642 default:
7643 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7644 (unsigned int)wire_open_mode ));
7645 return NT_STATUS_INVALID_PARAMETER;
7648 /* Next factor in the effects of O_TRUNC. */
7649 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7651 if (wire_open_mode & SMB_O_TRUNC) {
7652 switch (create_disp) {
7653 case FILE_CREATE:
7654 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7655 /* Leave create_disp alone as
7656 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7658 /* File exists fail. File not exist create. */
7659 break;
7660 case FILE_OPEN_IF:
7661 /* SMB_O_CREAT | SMB_O_TRUNC */
7662 /* File exists overwrite. File not exist create. */
7663 create_disp = FILE_OVERWRITE_IF;
7664 break;
7665 case FILE_OPEN:
7666 /* SMB_O_TRUNC */
7667 /* File exists overwrite. File not exist fail. */
7668 create_disp = FILE_OVERWRITE;
7669 break;
7670 default:
7671 /* Cannot get here. */
7672 smb_panic("smb_posix_open: logic error");
7673 return NT_STATUS_INVALID_PARAMETER;
7677 raw_unixmode = IVAL(pdata,8);
7678 /* Next 4 bytes are not yet defined. */
7680 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7681 (VALID_STAT(smb_fname->st) ?
7682 PERM_EXISTING_FILE : PERM_NEW_FILE),
7683 &unixmode);
7685 if (!NT_STATUS_IS_OK(status)) {
7686 return status;
7689 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7691 if (wire_open_mode & SMB_O_SYNC) {
7692 create_options |= FILE_WRITE_THROUGH;
7694 if (wire_open_mode & SMB_O_APPEND) {
7695 access_mask |= FILE_APPEND_DATA;
7697 if (wire_open_mode & SMB_O_DIRECT) {
7698 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7701 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7702 VALID_STAT_OF_DIR(smb_fname->st)) {
7703 if (access_mask != SMB_O_RDONLY_MAPPING) {
7704 return NT_STATUS_FILE_IS_A_DIRECTORY;
7706 create_options &= ~FILE_NON_DIRECTORY_FILE;
7707 create_options |= FILE_DIRECTORY_FILE;
7710 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7711 smb_fname_str_dbg(smb_fname),
7712 (unsigned int)wire_open_mode,
7713 (unsigned int)unixmode ));
7715 status = SMB_VFS_CREATE_FILE(
7716 conn, /* conn */
7717 req, /* req */
7718 0, /* root_dir_fid */
7719 smb_fname, /* fname */
7720 access_mask, /* access_mask */
7721 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7722 FILE_SHARE_DELETE),
7723 create_disp, /* create_disposition*/
7724 create_options, /* create_options */
7725 mod_unixmode, /* file_attributes */
7726 oplock_request, /* oplock_request */
7727 NULL, /* lease */
7728 0, /* allocation_size */
7729 0, /* private_flags */
7730 NULL, /* sd */
7731 NULL, /* ea_list */
7732 &fsp, /* result */
7733 &info); /* pinfo */
7735 if (!NT_STATUS_IS_OK(status)) {
7736 return status;
7739 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7740 extended_oplock_granted = True;
7743 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7744 extended_oplock_granted = True;
7747 info_level_return = SVAL(pdata,16);
7749 /* Allocate the correct return size. */
7751 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7752 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7753 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7754 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7755 } else {
7756 *pdata_return_size = 12;
7759 /* Realloc the data size */
7760 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7761 if (*ppdata == NULL) {
7762 close_file(req, fsp, ERROR_CLOSE);
7763 *pdata_return_size = 0;
7764 return NT_STATUS_NO_MEMORY;
7766 pdata = *ppdata;
7768 if (extended_oplock_granted) {
7769 if (flags & REQUEST_BATCH_OPLOCK) {
7770 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7771 } else {
7772 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7774 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7775 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7776 } else {
7777 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7780 SSVAL(pdata,2,fsp->fnum);
7781 SIVAL(pdata,4,info); /* Was file created etc. */
7783 switch (info_level_return) {
7784 case SMB_QUERY_FILE_UNIX_BASIC:
7785 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7786 SSVAL(pdata,10,0); /* padding. */
7787 store_file_unix_basic(conn, pdata + 12, fsp,
7788 &smb_fname->st);
7789 break;
7790 case SMB_QUERY_FILE_UNIX_INFO2:
7791 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7792 SSVAL(pdata,10,0); /* padding. */
7793 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7794 &smb_fname->st);
7795 break;
7796 default:
7797 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7798 SSVAL(pdata,10,0); /* padding. */
7799 break;
7801 return NT_STATUS_OK;
7804 /****************************************************************************
7805 Delete a file with POSIX semantics.
7806 ****************************************************************************/
7808 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7809 struct smb_request *req,
7810 const char *pdata,
7811 int total_data,
7812 struct smb_filename *smb_fname)
7814 NTSTATUS status = NT_STATUS_OK;
7815 files_struct *fsp = NULL;
7816 uint16 flags = 0;
7817 char del = 1;
7818 int info = 0;
7819 int create_options = 0;
7820 int i;
7821 struct share_mode_lock *lck = NULL;
7823 if (total_data < 2) {
7824 return NT_STATUS_INVALID_PARAMETER;
7827 flags = SVAL(pdata,0);
7829 if (!VALID_STAT(smb_fname->st)) {
7830 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7833 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7834 !VALID_STAT_OF_DIR(smb_fname->st)) {
7835 return NT_STATUS_NOT_A_DIRECTORY;
7838 DEBUG(10,("smb_posix_unlink: %s %s\n",
7839 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7840 smb_fname_str_dbg(smb_fname)));
7842 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7843 create_options |= FILE_DIRECTORY_FILE;
7846 status = SMB_VFS_CREATE_FILE(
7847 conn, /* conn */
7848 req, /* req */
7849 0, /* root_dir_fid */
7850 smb_fname, /* fname */
7851 DELETE_ACCESS, /* access_mask */
7852 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7853 FILE_SHARE_DELETE),
7854 FILE_OPEN, /* create_disposition*/
7855 create_options, /* create_options */
7856 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7857 0, /* oplock_request */
7858 NULL, /* lease */
7859 0, /* allocation_size */
7860 0, /* private_flags */
7861 NULL, /* sd */
7862 NULL, /* ea_list */
7863 &fsp, /* result */
7864 &info); /* pinfo */
7866 if (!NT_STATUS_IS_OK(status)) {
7867 return status;
7871 * Don't lie to client. If we can't really delete due to
7872 * non-POSIX opens return SHARING_VIOLATION.
7875 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7876 if (lck == NULL) {
7877 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7878 "lock for file %s\n", fsp_str_dbg(fsp)));
7879 close_file(req, fsp, NORMAL_CLOSE);
7880 return NT_STATUS_INVALID_PARAMETER;
7884 * See if others still have the file open. If this is the case, then
7885 * don't delete. If all opens are POSIX delete we can set the delete
7886 * on close disposition.
7888 for (i=0; i<lck->data->num_share_modes; i++) {
7889 struct share_mode_entry *e = &lck->data->share_modes[i];
7890 if (is_valid_share_mode_entry(e)) {
7891 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7892 continue;
7894 if (share_mode_stale_pid(lck->data, i)) {
7895 continue;
7897 /* Fail with sharing violation. */
7898 TALLOC_FREE(lck);
7899 close_file(req, fsp, NORMAL_CLOSE);
7900 return NT_STATUS_SHARING_VIOLATION;
7905 * Set the delete on close.
7907 status = smb_set_file_disposition_info(conn,
7908 &del,
7910 fsp,
7911 smb_fname);
7913 TALLOC_FREE(lck);
7915 if (!NT_STATUS_IS_OK(status)) {
7916 close_file(req, fsp, NORMAL_CLOSE);
7917 return status;
7919 return close_file(req, fsp, NORMAL_CLOSE);
7922 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7923 struct smb_request *req,
7924 TALLOC_CTX *mem_ctx,
7925 uint16_t info_level,
7926 files_struct *fsp,
7927 struct smb_filename *smb_fname,
7928 char **ppdata, int total_data,
7929 int *ret_data_size)
7931 char *pdata = *ppdata;
7932 NTSTATUS status = NT_STATUS_OK;
7933 int data_return_size = 0;
7935 *ret_data_size = 0;
7937 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7938 return NT_STATUS_INVALID_LEVEL;
7941 if (!CAN_WRITE(conn)) {
7942 /* Allow POSIX opens. The open path will deny
7943 * any non-readonly opens. */
7944 if (info_level != SMB_POSIX_PATH_OPEN) {
7945 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7949 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7950 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7951 fsp_fnum_dbg(fsp),
7952 info_level, total_data));
7954 switch (info_level) {
7956 case SMB_INFO_STANDARD:
7958 status = smb_set_info_standard(conn,
7959 pdata,
7960 total_data,
7961 fsp,
7962 smb_fname);
7963 break;
7966 case SMB_INFO_SET_EA:
7968 status = smb_info_set_ea(conn,
7969 pdata,
7970 total_data,
7971 fsp,
7972 smb_fname);
7973 break;
7976 case SMB_SET_FILE_BASIC_INFO:
7977 case SMB_FILE_BASIC_INFORMATION:
7979 status = smb_set_file_basic_info(conn,
7980 pdata,
7981 total_data,
7982 fsp,
7983 smb_fname);
7984 break;
7987 case SMB_FILE_ALLOCATION_INFORMATION:
7988 case SMB_SET_FILE_ALLOCATION_INFO:
7990 status = smb_set_file_allocation_info(conn, req,
7991 pdata,
7992 total_data,
7993 fsp,
7994 smb_fname);
7995 break;
7998 case SMB_FILE_END_OF_FILE_INFORMATION:
7999 case SMB_SET_FILE_END_OF_FILE_INFO:
8002 * XP/Win7 both fail after the createfile with
8003 * SMB_SET_FILE_END_OF_FILE_INFO but not
8004 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8005 * The level is known here, so pass it down
8006 * appropriately.
8008 bool should_fail =
8009 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8011 status = smb_set_file_end_of_file_info(conn, req,
8012 pdata,
8013 total_data,
8014 fsp,
8015 smb_fname,
8016 should_fail);
8017 break;
8020 case SMB_FILE_DISPOSITION_INFORMATION:
8021 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8023 #if 0
8024 /* JRA - We used to just ignore this on a path ?
8025 * Shouldn't this be invalid level on a pathname
8026 * based call ?
8028 if (tran_call != TRANSACT2_SETFILEINFO) {
8029 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8031 #endif
8032 status = smb_set_file_disposition_info(conn,
8033 pdata,
8034 total_data,
8035 fsp,
8036 smb_fname);
8037 break;
8040 case SMB_FILE_POSITION_INFORMATION:
8042 status = smb_file_position_information(conn,
8043 pdata,
8044 total_data,
8045 fsp);
8046 break;
8049 case SMB_FILE_FULL_EA_INFORMATION:
8051 status = smb_set_file_full_ea_info(conn,
8052 pdata,
8053 total_data,
8054 fsp);
8055 break;
8058 /* From tridge Samba4 :
8059 * MODE_INFORMATION in setfileinfo (I have no
8060 * idea what "mode information" on a file is - it takes a value of 0,
8061 * 2, 4 or 6. What could it be?).
8064 case SMB_FILE_MODE_INFORMATION:
8066 status = smb_file_mode_information(conn,
8067 pdata,
8068 total_data);
8069 break;
8073 * CIFS UNIX extensions.
8076 case SMB_SET_FILE_UNIX_BASIC:
8078 status = smb_set_file_unix_basic(conn, req,
8079 pdata,
8080 total_data,
8081 fsp,
8082 smb_fname);
8083 break;
8086 case SMB_SET_FILE_UNIX_INFO2:
8088 status = smb_set_file_unix_info2(conn, req,
8089 pdata,
8090 total_data,
8091 fsp,
8092 smb_fname);
8093 break;
8096 case SMB_SET_FILE_UNIX_LINK:
8098 if (fsp) {
8099 /* We must have a pathname for this. */
8100 return NT_STATUS_INVALID_LEVEL;
8102 status = smb_set_file_unix_link(conn, req, pdata,
8103 total_data, smb_fname);
8104 break;
8107 case SMB_SET_FILE_UNIX_HLINK:
8109 if (fsp) {
8110 /* We must have a pathname for this. */
8111 return NT_STATUS_INVALID_LEVEL;
8113 status = smb_set_file_unix_hlink(conn, req,
8114 pdata, total_data,
8115 smb_fname);
8116 break;
8119 case SMB_FILE_RENAME_INFORMATION:
8121 status = smb_file_rename_information(conn, req,
8122 pdata, total_data,
8123 fsp, smb_fname);
8124 break;
8127 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8129 /* SMB2 rename information. */
8130 status = smb2_file_rename_information(conn, req,
8131 pdata, total_data,
8132 fsp, smb_fname);
8133 break;
8136 case SMB_FILE_LINK_INFORMATION:
8138 status = smb_file_link_information(conn, req,
8139 pdata, total_data,
8140 fsp, smb_fname);
8141 break;
8144 #if defined(HAVE_POSIX_ACLS)
8145 case SMB_SET_POSIX_ACL:
8147 status = smb_set_posix_acl(conn,
8148 pdata,
8149 total_data,
8150 fsp,
8151 smb_fname);
8152 break;
8154 #endif
8156 case SMB_SET_POSIX_LOCK:
8158 if (!fsp) {
8159 return NT_STATUS_INVALID_LEVEL;
8161 status = smb_set_posix_lock(conn, req,
8162 pdata, total_data, fsp);
8163 break;
8166 case SMB_POSIX_PATH_OPEN:
8168 if (fsp) {
8169 /* We must have a pathname for this. */
8170 return NT_STATUS_INVALID_LEVEL;
8173 status = smb_posix_open(conn, req,
8174 ppdata,
8175 total_data,
8176 smb_fname,
8177 &data_return_size);
8178 break;
8181 case SMB_POSIX_PATH_UNLINK:
8183 if (fsp) {
8184 /* We must have a pathname for this. */
8185 return NT_STATUS_INVALID_LEVEL;
8188 status = smb_posix_unlink(conn, req,
8189 pdata,
8190 total_data,
8191 smb_fname);
8192 break;
8195 default:
8196 return NT_STATUS_INVALID_LEVEL;
8199 if (!NT_STATUS_IS_OK(status)) {
8200 return status;
8203 *ret_data_size = data_return_size;
8204 return NT_STATUS_OK;
8207 /****************************************************************************
8208 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8209 ****************************************************************************/
8211 static void call_trans2setfilepathinfo(connection_struct *conn,
8212 struct smb_request *req,
8213 unsigned int tran_call,
8214 char **pparams, int total_params,
8215 char **ppdata, int total_data,
8216 unsigned int max_data_bytes)
8218 char *params = *pparams;
8219 char *pdata = *ppdata;
8220 uint16 info_level;
8221 struct smb_filename *smb_fname = NULL;
8222 files_struct *fsp = NULL;
8223 NTSTATUS status = NT_STATUS_OK;
8224 int data_return_size = 0;
8226 if (!params) {
8227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8228 return;
8231 if (tran_call == TRANSACT2_SETFILEINFO) {
8232 if (total_params < 4) {
8233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8234 return;
8237 fsp = file_fsp(req, SVAL(params,0));
8238 /* Basic check for non-null fsp. */
8239 if (!check_fsp_open(conn, req, fsp)) {
8240 return;
8242 info_level = SVAL(params,2);
8244 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8245 if (smb_fname == NULL) {
8246 reply_nterror(req, NT_STATUS_NO_MEMORY);
8247 return;
8250 if(fsp->fh->fd == -1) {
8252 * This is actually a SETFILEINFO on a directory
8253 * handle (returned from an NT SMB). NT5.0 seems
8254 * to do this call. JRA.
8256 if (INFO_LEVEL_IS_UNIX(info_level)) {
8257 /* Always do lstat for UNIX calls. */
8258 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8259 DEBUG(3,("call_trans2setfilepathinfo: "
8260 "SMB_VFS_LSTAT of %s failed "
8261 "(%s)\n",
8262 smb_fname_str_dbg(smb_fname),
8263 strerror(errno)));
8264 reply_nterror(req, map_nt_error_from_unix(errno));
8265 return;
8267 } else {
8268 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8269 DEBUG(3,("call_trans2setfilepathinfo: "
8270 "fileinfo of %s failed (%s)\n",
8271 smb_fname_str_dbg(smb_fname),
8272 strerror(errno)));
8273 reply_nterror(req, map_nt_error_from_unix(errno));
8274 return;
8277 } else if (fsp->print_file) {
8279 * Doing a DELETE_ON_CLOSE should cancel a print job.
8281 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8282 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8284 DEBUG(3,("call_trans2setfilepathinfo: "
8285 "Cancelling print job (%s)\n",
8286 fsp_str_dbg(fsp)));
8288 SSVAL(params,0,0);
8289 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8290 *ppdata, 0,
8291 max_data_bytes);
8292 return;
8293 } else {
8294 reply_nterror(req,
8295 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8296 return;
8298 } else {
8300 * Original code - this is an open file.
8302 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8303 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8304 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8305 strerror(errno)));
8306 reply_nterror(req, map_nt_error_from_unix(errno));
8307 return;
8310 } else {
8311 char *fname = NULL;
8312 uint32_t ucf_flags = 0;
8314 /* set path info */
8315 if (total_params < 7) {
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 return;
8320 info_level = SVAL(params,0);
8321 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8322 total_params - 6, STR_TERMINATE,
8323 &status);
8324 if (!NT_STATUS_IS_OK(status)) {
8325 reply_nterror(req, status);
8326 return;
8329 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8330 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8331 info_level == SMB_FILE_RENAME_INFORMATION ||
8332 info_level == SMB_POSIX_PATH_UNLINK) {
8333 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8336 status = filename_convert(req, conn,
8337 req->flags2 & FLAGS2_DFS_PATHNAMES,
8338 fname,
8339 ucf_flags,
8340 NULL,
8341 &smb_fname);
8342 if (!NT_STATUS_IS_OK(status)) {
8343 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8344 reply_botherror(req,
8345 NT_STATUS_PATH_NOT_COVERED,
8346 ERRSRV, ERRbadpath);
8347 return;
8349 reply_nterror(req, status);
8350 return;
8353 if (INFO_LEVEL_IS_UNIX(info_level)) {
8355 * For CIFS UNIX extensions the target name may not exist.
8358 /* Always do lstat for UNIX calls. */
8359 SMB_VFS_LSTAT(conn, smb_fname);
8361 } else if (!VALID_STAT(smb_fname->st) &&
8362 SMB_VFS_STAT(conn, smb_fname)) {
8363 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8364 "%s failed (%s)\n",
8365 smb_fname_str_dbg(smb_fname),
8366 strerror(errno)));
8367 reply_nterror(req, map_nt_error_from_unix(errno));
8368 return;
8372 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8373 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8374 fsp_fnum_dbg(fsp),
8375 info_level,total_data));
8377 /* Realloc the parameter size */
8378 *pparams = (char *)SMB_REALLOC(*pparams,2);
8379 if (*pparams == NULL) {
8380 reply_nterror(req, NT_STATUS_NO_MEMORY);
8381 return;
8383 params = *pparams;
8385 SSVAL(params,0,0);
8387 status = smbd_do_setfilepathinfo(conn, req, req,
8388 info_level,
8389 fsp,
8390 smb_fname,
8391 ppdata, total_data,
8392 &data_return_size);
8393 if (!NT_STATUS_IS_OK(status)) {
8394 if (open_was_deferred(req->xconn, req->mid)) {
8395 /* We have re-scheduled this call. */
8396 return;
8398 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8399 /* We have re-scheduled this call. */
8400 return;
8402 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8403 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8404 ERRSRV, ERRbadpath);
8405 return;
8407 if (info_level == SMB_POSIX_PATH_OPEN) {
8408 reply_openerror(req, status);
8409 return;
8413 * Invalid EA name needs to return 2 param bytes,
8414 * not a zero-length error packet.
8416 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8417 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8418 max_data_bytes);
8419 } else {
8420 reply_nterror(req, status);
8422 return;
8425 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8426 max_data_bytes);
8428 return;
8431 /****************************************************************************
8432 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8433 ****************************************************************************/
8435 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8436 char **pparams, int total_params,
8437 char **ppdata, int total_data,
8438 unsigned int max_data_bytes)
8440 struct smb_filename *smb_dname = NULL;
8441 char *params = *pparams;
8442 char *pdata = *ppdata;
8443 char *directory = NULL;
8444 NTSTATUS status = NT_STATUS_OK;
8445 struct ea_list *ea_list = NULL;
8446 TALLOC_CTX *ctx = talloc_tos();
8448 if (!CAN_WRITE(conn)) {
8449 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8450 return;
8453 if (total_params < 5) {
8454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8455 return;
8458 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8459 total_params - 4, STR_TERMINATE,
8460 &status);
8461 if (!NT_STATUS_IS_OK(status)) {
8462 reply_nterror(req, status);
8463 return;
8466 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8468 status = filename_convert(ctx,
8469 conn,
8470 req->flags2 & FLAGS2_DFS_PATHNAMES,
8471 directory,
8473 NULL,
8474 &smb_dname);
8476 if (!NT_STATUS_IS_OK(status)) {
8477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8478 reply_botherror(req,
8479 NT_STATUS_PATH_NOT_COVERED,
8480 ERRSRV, ERRbadpath);
8481 return;
8483 reply_nterror(req, status);
8484 return;
8488 * OS/2 workplace shell seems to send SET_EA requests of "null"
8489 * length (4 bytes containing IVAL 4).
8490 * They seem to have no effect. Bug #3212. JRA.
8493 if (total_data && (total_data != 4)) {
8494 /* Any data in this call is an EA list. */
8495 if (total_data < 10) {
8496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8497 goto out;
8500 if (IVAL(pdata,0) > total_data) {
8501 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8502 IVAL(pdata,0), (unsigned int)total_data));
8503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8504 goto out;
8507 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8508 total_data - 4);
8509 if (!ea_list) {
8510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8511 goto out;
8514 if (!lp_ea_support(SNUM(conn))) {
8515 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8516 goto out;
8519 /* If total_data == 4 Windows doesn't care what values
8520 * are placed in that field, it just ignores them.
8521 * The System i QNTC IBM SMB client puts bad values here,
8522 * so ignore them. */
8524 status = create_directory(conn, req, smb_dname);
8526 if (!NT_STATUS_IS_OK(status)) {
8527 reply_nterror(req, status);
8528 goto out;
8531 /* Try and set any given EA. */
8532 if (ea_list) {
8533 status = set_ea(conn, NULL, smb_dname, ea_list);
8534 if (!NT_STATUS_IS_OK(status)) {
8535 reply_nterror(req, status);
8536 goto out;
8540 /* Realloc the parameter and data sizes */
8541 *pparams = (char *)SMB_REALLOC(*pparams,2);
8542 if(*pparams == NULL) {
8543 reply_nterror(req, NT_STATUS_NO_MEMORY);
8544 goto out;
8546 params = *pparams;
8548 SSVAL(params,0,0);
8550 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8552 out:
8553 TALLOC_FREE(smb_dname);
8554 return;
8557 /****************************************************************************
8558 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8559 We don't actually do this - we just send a null response.
8560 ****************************************************************************/
8562 static void call_trans2findnotifyfirst(connection_struct *conn,
8563 struct smb_request *req,
8564 char **pparams, int total_params,
8565 char **ppdata, int total_data,
8566 unsigned int max_data_bytes)
8568 char *params = *pparams;
8569 uint16 info_level;
8571 if (total_params < 6) {
8572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8573 return;
8576 info_level = SVAL(params,4);
8577 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8579 switch (info_level) {
8580 case 1:
8581 case 2:
8582 break;
8583 default:
8584 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8585 return;
8588 /* Realloc the parameter and data sizes */
8589 *pparams = (char *)SMB_REALLOC(*pparams,6);
8590 if (*pparams == NULL) {
8591 reply_nterror(req, NT_STATUS_NO_MEMORY);
8592 return;
8594 params = *pparams;
8596 SSVAL(params,0,fnf_handle);
8597 SSVAL(params,2,0); /* No changes */
8598 SSVAL(params,4,0); /* No EA errors */
8600 fnf_handle++;
8602 if(fnf_handle == 0)
8603 fnf_handle = 257;
8605 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8607 return;
8610 /****************************************************************************
8611 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8612 changes). Currently this does nothing.
8613 ****************************************************************************/
8615 static void call_trans2findnotifynext(connection_struct *conn,
8616 struct smb_request *req,
8617 char **pparams, int total_params,
8618 char **ppdata, int total_data,
8619 unsigned int max_data_bytes)
8621 char *params = *pparams;
8623 DEBUG(3,("call_trans2findnotifynext\n"));
8625 /* Realloc the parameter and data sizes */
8626 *pparams = (char *)SMB_REALLOC(*pparams,4);
8627 if (*pparams == NULL) {
8628 reply_nterror(req, NT_STATUS_NO_MEMORY);
8629 return;
8631 params = *pparams;
8633 SSVAL(params,0,0); /* No changes */
8634 SSVAL(params,2,0); /* No EA errors */
8636 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8638 return;
8641 /****************************************************************************
8642 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8643 ****************************************************************************/
8645 static void call_trans2getdfsreferral(connection_struct *conn,
8646 struct smb_request *req,
8647 char **pparams, int total_params,
8648 char **ppdata, int total_data,
8649 unsigned int max_data_bytes)
8651 char *params = *pparams;
8652 char *pathname = NULL;
8653 int reply_size = 0;
8654 int max_referral_level;
8655 NTSTATUS status = NT_STATUS_OK;
8656 TALLOC_CTX *ctx = talloc_tos();
8658 DEBUG(10,("call_trans2getdfsreferral\n"));
8660 if (total_params < 3) {
8661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8662 return;
8665 max_referral_level = SVAL(params,0);
8667 if(!lp_host_msdfs()) {
8668 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8669 return;
8672 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8673 total_params - 2, STR_TERMINATE);
8674 if (!pathname) {
8675 reply_nterror(req, NT_STATUS_NOT_FOUND);
8676 return;
8678 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8679 ppdata,&status)) < 0) {
8680 reply_nterror(req, status);
8681 return;
8684 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8685 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8686 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8688 return;
8691 #define LMCAT_SPL 0x53
8692 #define LMFUNC_GETJOBID 0x60
8694 /****************************************************************************
8695 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8696 ****************************************************************************/
8698 static void call_trans2ioctl(connection_struct *conn,
8699 struct smb_request *req,
8700 char **pparams, int total_params,
8701 char **ppdata, int total_data,
8702 unsigned int max_data_bytes)
8704 char *pdata = *ppdata;
8705 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8706 NTSTATUS status;
8707 size_t len = 0;
8709 /* check for an invalid fid before proceeding */
8711 if (!fsp) {
8712 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8713 return;
8716 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8717 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8718 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8719 if (*ppdata == NULL) {
8720 reply_nterror(req, NT_STATUS_NO_MEMORY);
8721 return;
8723 pdata = *ppdata;
8725 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8726 CAN ACCEPT THIS IN UNICODE. JRA. */
8728 /* Job number */
8729 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8731 status = srvstr_push(pdata, req->flags2, pdata + 2,
8732 lp_netbios_name(), 15,
8733 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8734 if (!NT_STATUS_IS_OK(status)) {
8735 reply_nterror(req, status);
8736 return;
8738 status = srvstr_push(pdata, req->flags2, pdata+18,
8739 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8740 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8741 if (!NT_STATUS_IS_OK(status)) {
8742 reply_nterror(req, status);
8743 return;
8745 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8746 max_data_bytes);
8747 return;
8750 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8751 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8754 /****************************************************************************
8755 Reply to a SMBfindclose (stop trans2 directory search).
8756 ****************************************************************************/
8758 void reply_findclose(struct smb_request *req)
8760 int dptr_num;
8761 struct smbd_server_connection *sconn = req->sconn;
8763 START_PROFILE(SMBfindclose);
8765 if (req->wct < 1) {
8766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8767 END_PROFILE(SMBfindclose);
8768 return;
8771 dptr_num = SVALS(req->vwv+0, 0);
8773 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8775 dptr_close(sconn, &dptr_num);
8777 reply_outbuf(req, 0, 0);
8779 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8781 END_PROFILE(SMBfindclose);
8782 return;
8785 /****************************************************************************
8786 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8787 ****************************************************************************/
8789 void reply_findnclose(struct smb_request *req)
8791 int dptr_num;
8793 START_PROFILE(SMBfindnclose);
8795 if (req->wct < 1) {
8796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8797 END_PROFILE(SMBfindnclose);
8798 return;
8801 dptr_num = SVAL(req->vwv+0, 0);
8803 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8805 /* We never give out valid handles for a
8806 findnotifyfirst - so any dptr_num is ok here.
8807 Just ignore it. */
8809 reply_outbuf(req, 0, 0);
8811 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8813 END_PROFILE(SMBfindnclose);
8814 return;
8817 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8818 struct trans_state *state)
8820 if (get_Protocol() >= PROTOCOL_NT1) {
8821 req->flags2 |= 0x40; /* IS_LONG_NAME */
8822 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8825 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8826 if (state->call != TRANSACT2_QFSINFO &&
8827 state->call != TRANSACT2_SETFSINFO) {
8828 DEBUG(0,("handle_trans2: encryption required "
8829 "with call 0x%x\n",
8830 (unsigned int)state->call));
8831 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8832 return;
8836 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8838 /* Now we must call the relevant TRANS2 function */
8839 switch(state->call) {
8840 case TRANSACT2_OPEN:
8842 START_PROFILE(Trans2_open);
8843 call_trans2open(conn, req,
8844 &state->param, state->total_param,
8845 &state->data, state->total_data,
8846 state->max_data_return);
8847 END_PROFILE(Trans2_open);
8848 break;
8851 case TRANSACT2_FINDFIRST:
8853 START_PROFILE(Trans2_findfirst);
8854 call_trans2findfirst(conn, req,
8855 &state->param, state->total_param,
8856 &state->data, state->total_data,
8857 state->max_data_return);
8858 END_PROFILE(Trans2_findfirst);
8859 break;
8862 case TRANSACT2_FINDNEXT:
8864 START_PROFILE(Trans2_findnext);
8865 call_trans2findnext(conn, req,
8866 &state->param, state->total_param,
8867 &state->data, state->total_data,
8868 state->max_data_return);
8869 END_PROFILE(Trans2_findnext);
8870 break;
8873 case TRANSACT2_QFSINFO:
8875 START_PROFILE(Trans2_qfsinfo);
8876 call_trans2qfsinfo(conn, req,
8877 &state->param, state->total_param,
8878 &state->data, state->total_data,
8879 state->max_data_return);
8880 END_PROFILE(Trans2_qfsinfo);
8881 break;
8884 case TRANSACT2_SETFSINFO:
8886 START_PROFILE(Trans2_setfsinfo);
8887 call_trans2setfsinfo(conn, req,
8888 &state->param, state->total_param,
8889 &state->data, state->total_data,
8890 state->max_data_return);
8891 END_PROFILE(Trans2_setfsinfo);
8892 break;
8895 case TRANSACT2_QPATHINFO:
8896 case TRANSACT2_QFILEINFO:
8898 START_PROFILE(Trans2_qpathinfo);
8899 call_trans2qfilepathinfo(conn, req, state->call,
8900 &state->param, state->total_param,
8901 &state->data, state->total_data,
8902 state->max_data_return);
8903 END_PROFILE(Trans2_qpathinfo);
8904 break;
8907 case TRANSACT2_SETPATHINFO:
8908 case TRANSACT2_SETFILEINFO:
8910 START_PROFILE(Trans2_setpathinfo);
8911 call_trans2setfilepathinfo(conn, req, state->call,
8912 &state->param, state->total_param,
8913 &state->data, state->total_data,
8914 state->max_data_return);
8915 END_PROFILE(Trans2_setpathinfo);
8916 break;
8919 case TRANSACT2_FINDNOTIFYFIRST:
8921 START_PROFILE(Trans2_findnotifyfirst);
8922 call_trans2findnotifyfirst(conn, req,
8923 &state->param, state->total_param,
8924 &state->data, state->total_data,
8925 state->max_data_return);
8926 END_PROFILE(Trans2_findnotifyfirst);
8927 break;
8930 case TRANSACT2_FINDNOTIFYNEXT:
8932 START_PROFILE(Trans2_findnotifynext);
8933 call_trans2findnotifynext(conn, req,
8934 &state->param, state->total_param,
8935 &state->data, state->total_data,
8936 state->max_data_return);
8937 END_PROFILE(Trans2_findnotifynext);
8938 break;
8941 case TRANSACT2_MKDIR:
8943 START_PROFILE(Trans2_mkdir);
8944 call_trans2mkdir(conn, req,
8945 &state->param, state->total_param,
8946 &state->data, state->total_data,
8947 state->max_data_return);
8948 END_PROFILE(Trans2_mkdir);
8949 break;
8952 case TRANSACT2_GET_DFS_REFERRAL:
8954 START_PROFILE(Trans2_get_dfs_referral);
8955 call_trans2getdfsreferral(conn, req,
8956 &state->param, state->total_param,
8957 &state->data, state->total_data,
8958 state->max_data_return);
8959 END_PROFILE(Trans2_get_dfs_referral);
8960 break;
8963 case TRANSACT2_IOCTL:
8965 START_PROFILE(Trans2_ioctl);
8966 call_trans2ioctl(conn, req,
8967 &state->param, state->total_param,
8968 &state->data, state->total_data,
8969 state->max_data_return);
8970 END_PROFILE(Trans2_ioctl);
8971 break;
8974 default:
8975 /* Error in request */
8976 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8977 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8981 /****************************************************************************
8982 Reply to a SMBtrans2.
8983 ****************************************************************************/
8985 void reply_trans2(struct smb_request *req)
8987 connection_struct *conn = req->conn;
8988 unsigned int dsoff;
8989 unsigned int dscnt;
8990 unsigned int psoff;
8991 unsigned int pscnt;
8992 unsigned int tran_call;
8993 struct trans_state *state;
8994 NTSTATUS result;
8996 START_PROFILE(SMBtrans2);
8998 if (req->wct < 14) {
8999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9000 END_PROFILE(SMBtrans2);
9001 return;
9004 dsoff = SVAL(req->vwv+12, 0);
9005 dscnt = SVAL(req->vwv+11, 0);
9006 psoff = SVAL(req->vwv+10, 0);
9007 pscnt = SVAL(req->vwv+9, 0);
9008 tran_call = SVAL(req->vwv+14, 0);
9010 result = allow_new_trans(conn->pending_trans, req->mid);
9011 if (!NT_STATUS_IS_OK(result)) {
9012 DEBUG(2, ("Got invalid trans2 request: %s\n",
9013 nt_errstr(result)));
9014 reply_nterror(req, result);
9015 END_PROFILE(SMBtrans2);
9016 return;
9019 if (IS_IPC(conn)) {
9020 switch (tran_call) {
9021 /* List the allowed trans2 calls on IPC$ */
9022 case TRANSACT2_OPEN:
9023 case TRANSACT2_GET_DFS_REFERRAL:
9024 case TRANSACT2_QFILEINFO:
9025 case TRANSACT2_QFSINFO:
9026 case TRANSACT2_SETFSINFO:
9027 break;
9028 default:
9029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9030 END_PROFILE(SMBtrans2);
9031 return;
9035 if ((state = talloc(conn, struct trans_state)) == NULL) {
9036 DEBUG(0, ("talloc failed\n"));
9037 reply_nterror(req, NT_STATUS_NO_MEMORY);
9038 END_PROFILE(SMBtrans2);
9039 return;
9042 state->cmd = SMBtrans2;
9044 state->mid = req->mid;
9045 state->vuid = req->vuid;
9046 state->setup_count = SVAL(req->vwv+13, 0);
9047 state->setup = NULL;
9048 state->total_param = SVAL(req->vwv+0, 0);
9049 state->param = NULL;
9050 state->total_data = SVAL(req->vwv+1, 0);
9051 state->data = NULL;
9052 state->max_param_return = SVAL(req->vwv+2, 0);
9053 state->max_data_return = SVAL(req->vwv+3, 0);
9054 state->max_setup_return = SVAL(req->vwv+4, 0);
9055 state->close_on_completion = BITSETW(req->vwv+5, 0);
9056 state->one_way = BITSETW(req->vwv+5, 1);
9058 state->call = tran_call;
9060 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9061 is so as a sanity check */
9062 if (state->setup_count != 1) {
9064 * Need to have rc=0 for ioctl to get job id for OS/2.
9065 * Network printing will fail if function is not successful.
9066 * Similar function in reply.c will be used if protocol
9067 * is LANMAN1.0 instead of LM1.2X002.
9068 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9069 * outbuf doesn't have to be set(only job id is used).
9071 if ( (state->setup_count == 4)
9072 && (tran_call == TRANSACT2_IOCTL)
9073 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9074 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9075 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9076 } else {
9077 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9078 DEBUG(2,("Transaction is %d\n",tran_call));
9079 TALLOC_FREE(state);
9080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9081 END_PROFILE(SMBtrans2);
9082 return;
9086 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9087 goto bad_param;
9089 if (state->total_data) {
9091 if (trans_oob(state->total_data, 0, dscnt)
9092 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9093 goto bad_param;
9096 /* Can't use talloc here, the core routines do realloc on the
9097 * params and data. */
9098 state->data = (char *)SMB_MALLOC(state->total_data);
9099 if (state->data == NULL) {
9100 DEBUG(0,("reply_trans2: data malloc fail for %u "
9101 "bytes !\n", (unsigned int)state->total_data));
9102 TALLOC_FREE(state);
9103 reply_nterror(req, NT_STATUS_NO_MEMORY);
9104 END_PROFILE(SMBtrans2);
9105 return;
9108 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9111 if (state->total_param) {
9113 if (trans_oob(state->total_param, 0, pscnt)
9114 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9115 goto bad_param;
9118 /* Can't use talloc here, the core routines do realloc on the
9119 * params and data. */
9120 state->param = (char *)SMB_MALLOC(state->total_param);
9121 if (state->param == NULL) {
9122 DEBUG(0,("reply_trans: param malloc fail for %u "
9123 "bytes !\n", (unsigned int)state->total_param));
9124 SAFE_FREE(state->data);
9125 TALLOC_FREE(state);
9126 reply_nterror(req, NT_STATUS_NO_MEMORY);
9127 END_PROFILE(SMBtrans2);
9128 return;
9131 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9134 state->received_data = dscnt;
9135 state->received_param = pscnt;
9137 if ((state->received_param == state->total_param) &&
9138 (state->received_data == state->total_data)) {
9140 handle_trans2(conn, req, state);
9142 SAFE_FREE(state->data);
9143 SAFE_FREE(state->param);
9144 TALLOC_FREE(state);
9145 END_PROFILE(SMBtrans2);
9146 return;
9149 DLIST_ADD(conn->pending_trans, state);
9151 /* We need to send an interim response then receive the rest
9152 of the parameter/data bytes */
9153 reply_outbuf(req, 0, 0);
9154 show_msg((char *)req->outbuf);
9155 END_PROFILE(SMBtrans2);
9156 return;
9158 bad_param:
9160 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9161 SAFE_FREE(state->data);
9162 SAFE_FREE(state->param);
9163 TALLOC_FREE(state);
9164 END_PROFILE(SMBtrans2);
9165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9169 /****************************************************************************
9170 Reply to a SMBtranss2
9171 ****************************************************************************/
9173 void reply_transs2(struct smb_request *req)
9175 connection_struct *conn = req->conn;
9176 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9177 struct trans_state *state;
9179 START_PROFILE(SMBtranss2);
9181 show_msg((const char *)req->inbuf);
9183 /* Windows clients expect all replies to
9184 a transact secondary (SMBtranss2 0x33)
9185 to have a command code of transact
9186 (SMBtrans2 0x32). See bug #8989
9187 and also [MS-CIFS] section 2.2.4.47.2
9188 for details.
9190 req->cmd = SMBtrans2;
9192 if (req->wct < 8) {
9193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9194 END_PROFILE(SMBtranss2);
9195 return;
9198 for (state = conn->pending_trans; state != NULL;
9199 state = state->next) {
9200 if (state->mid == req->mid) {
9201 break;
9205 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9207 END_PROFILE(SMBtranss2);
9208 return;
9211 /* Revise state->total_param and state->total_data in case they have
9212 changed downwards */
9214 if (SVAL(req->vwv+0, 0) < state->total_param)
9215 state->total_param = SVAL(req->vwv+0, 0);
9216 if (SVAL(req->vwv+1, 0) < state->total_data)
9217 state->total_data = SVAL(req->vwv+1, 0);
9219 pcnt = SVAL(req->vwv+2, 0);
9220 poff = SVAL(req->vwv+3, 0);
9221 pdisp = SVAL(req->vwv+4, 0);
9223 dcnt = SVAL(req->vwv+5, 0);
9224 doff = SVAL(req->vwv+6, 0);
9225 ddisp = SVAL(req->vwv+7, 0);
9227 state->received_param += pcnt;
9228 state->received_data += dcnt;
9230 if ((state->received_data > state->total_data) ||
9231 (state->received_param > state->total_param))
9232 goto bad_param;
9234 if (pcnt) {
9235 if (trans_oob(state->total_param, pdisp, pcnt)
9236 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9237 goto bad_param;
9239 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9242 if (dcnt) {
9243 if (trans_oob(state->total_data, ddisp, dcnt)
9244 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9245 goto bad_param;
9247 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9250 if ((state->received_param < state->total_param) ||
9251 (state->received_data < state->total_data)) {
9252 END_PROFILE(SMBtranss2);
9253 return;
9256 handle_trans2(conn, req, state);
9258 DLIST_REMOVE(conn->pending_trans, state);
9259 SAFE_FREE(state->data);
9260 SAFE_FREE(state->param);
9261 TALLOC_FREE(state);
9263 END_PROFILE(SMBtranss2);
9264 return;
9266 bad_param:
9268 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9269 DLIST_REMOVE(conn->pending_trans, state);
9270 SAFE_FREE(state->data);
9271 SAFE_FREE(state->param);
9272 TALLOC_FREE(state);
9273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9274 END_PROFILE(SMBtranss2);
9275 return;