s3:smbd: s/struct timed_event/struct tevent_timer
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobfae9e1ff9dcf4a698df869f32daecedbd8f03a72
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
327 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
328 &names, &num_names);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (num_names == 0) {
335 *ea_list = NULL;
336 return NT_STATUS_OK;
339 for (i=0; i<num_names; i++) {
340 struct ea_list *listp;
341 fstring dos_ea_name;
343 if (strnequal(names[i], "system.", 7)
344 || samba_private_attr_name(names[i]))
345 continue;
347 listp = talloc(mem_ctx, struct ea_list);
348 if (listp == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 status = get_ea_value(mem_ctx, conn, fsp,
353 fname, names[i],
354 &listp->ea);
356 if (!NT_STATUS_IS_OK(status)) {
357 return status;
360 push_ascii_fstring(dos_ea_name, listp->ea.name);
362 *pea_total_len +=
363 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
365 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
366 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
367 (unsigned int)listp->ea.value.length));
369 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
373 /* Add on 4 for total length. */
374 if (*pea_total_len) {
375 *pea_total_len += 4;
378 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
379 (unsigned int)*pea_total_len));
381 *ea_list = ea_list_head;
382 return NT_STATUS_OK;
385 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
386 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
388 *pea_total_len = 0;
389 *ea_list = NULL;
391 if (!lp_ea_support(SNUM(conn))) {
392 return NT_STATUS_OK;
395 if (is_ntfs_stream_smb_fname(smb_fname)) {
396 return NT_STATUS_INVALID_PARAMETER;
399 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
402 /****************************************************************************
403 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
404 that was filled.
405 ****************************************************************************/
407 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
408 connection_struct *conn, struct ea_list *ea_list)
410 unsigned int ret_data_size = 4;
411 char *p = pdata;
413 SMB_ASSERT(total_data_size >= 4);
415 if (!lp_ea_support(SNUM(conn))) {
416 SIVAL(pdata,4,0);
417 return 4;
420 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
421 size_t dos_namelen;
422 fstring dos_ea_name;
423 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
424 dos_namelen = strlen(dos_ea_name);
425 if (dos_namelen > 255 || dos_namelen == 0) {
426 break;
428 if (ea_list->ea.value.length > 65535) {
429 break;
431 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
432 break;
435 /* We know we have room. */
436 SCVAL(p,0,ea_list->ea.flags);
437 SCVAL(p,1,dos_namelen);
438 SSVAL(p,2,ea_list->ea.value.length);
439 strlcpy(p+4, dos_ea_name, dos_namelen+1);
440 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
442 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
443 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
446 ret_data_size = PTR_DIFF(p, pdata);
447 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
448 SIVAL(pdata,0,ret_data_size);
449 return ret_data_size;
452 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
453 char *pdata,
454 unsigned int total_data_size,
455 unsigned int *ret_data_size,
456 connection_struct *conn,
457 struct ea_list *ea_list)
459 uint8_t *p = (uint8_t *)pdata;
460 uint8_t *last_start = NULL;
462 *ret_data_size = 0;
464 if (!lp_ea_support(SNUM(conn))) {
465 return NT_STATUS_NO_EAS_ON_FILE;
468 for (; ea_list; ea_list = ea_list->next) {
469 size_t dos_namelen;
470 fstring dos_ea_name;
471 size_t this_size;
473 if (last_start) {
474 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
476 last_start = p;
478 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
479 dos_namelen = strlen(dos_ea_name);
480 if (dos_namelen > 255 || dos_namelen == 0) {
481 return NT_STATUS_INTERNAL_ERROR;
483 if (ea_list->ea.value.length > 65535) {
484 return NT_STATUS_INTERNAL_ERROR;
487 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
489 if (ea_list->next) {
490 size_t pad = 4 - (this_size % 4);
491 this_size += pad;
494 if (this_size > total_data_size) {
495 return NT_STATUS_INFO_LENGTH_MISMATCH;
498 /* We know we have room. */
499 SIVAL(p, 0x00, 0); /* next offset */
500 SCVAL(p, 0x04, ea_list->ea.flags);
501 SCVAL(p, 0x05, dos_namelen);
502 SSVAL(p, 0x06, ea_list->ea.value.length);
503 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
504 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
506 total_data_size -= this_size;
507 p += this_size;
510 *ret_data_size = PTR_DIFF(p, pdata);
511 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
512 return NT_STATUS_OK;
515 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
517 size_t total_ea_len = 0;
518 TALLOC_CTX *mem_ctx;
519 struct ea_list *ea_list;
521 if (!lp_ea_support(SNUM(conn))) {
522 return 0;
524 mem_ctx = talloc_stackframe();
526 /* If this is a stream fsp, then we need to instead find the
527 * estimated ea len from the main file, not the stream
528 * (streams cannot have EAs), but the estimate isn't just 0 in
529 * this case! */
530 if (is_ntfs_stream_smb_fname(smb_fname)) {
531 fsp = NULL;
533 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
534 TALLOC_FREE(mem_ctx);
535 return total_ea_len;
538 /****************************************************************************
539 Ensure the EA name is case insensitive by matching any existing EA name.
540 ****************************************************************************/
542 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
544 size_t total_ea_len;
545 TALLOC_CTX *mem_ctx = talloc_tos();
546 struct ea_list *ea_list;
547 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
548 if (!NT_STATUS_IS_OK(status)) {
549 return;
552 for (; ea_list; ea_list = ea_list->next) {
553 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
554 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
555 &unix_ea_name[5], ea_list->ea.name));
556 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
557 break;
562 /****************************************************************************
563 Set or delete an extended attribute.
564 ****************************************************************************/
566 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
567 const struct smb_filename *smb_fname, struct ea_list *ea_list)
569 NTSTATUS status;
570 char *fname = NULL;
572 if (!lp_ea_support(SNUM(conn))) {
573 return NT_STATUS_EAS_NOT_SUPPORTED;
576 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
577 if (!NT_STATUS_IS_OK(status)) {
578 return status;
581 /* Setting EAs on streams isn't supported. */
582 if (is_ntfs_stream_smb_fname(smb_fname)) {
583 return NT_STATUS_INVALID_PARAMETER;
586 fname = smb_fname->base_name;
588 for (;ea_list; ea_list = ea_list->next) {
589 int ret;
590 fstring unix_ea_name;
592 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
593 fstrcat(unix_ea_name, ea_list->ea.name);
595 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
597 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
599 if (samba_private_attr_name(unix_ea_name)) {
600 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
601 return NT_STATUS_ACCESS_DENIED;
604 if (ea_list->ea.value.length == 0) {
605 /* Remove the attribute. */
606 if (fsp && (fsp->fh->fd != -1)) {
607 DEBUG(10,("set_ea: deleting ea name %s on "
608 "file %s by file descriptor.\n",
609 unix_ea_name, fsp_str_dbg(fsp)));
610 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
611 } else {
612 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
613 unix_ea_name, fname));
614 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
616 #ifdef ENOATTR
617 /* Removing a non existent attribute always succeeds. */
618 if (ret == -1 && errno == ENOATTR) {
619 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
620 unix_ea_name));
621 ret = 0;
623 #endif
624 } else {
625 if (fsp && (fsp->fh->fd != -1)) {
626 DEBUG(10,("set_ea: setting ea name %s on file "
627 "%s by file descriptor.\n",
628 unix_ea_name, fsp_str_dbg(fsp)));
629 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
630 ea_list->ea.value.data, ea_list->ea.value.length, 0);
631 } else {
632 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
633 unix_ea_name, fname));
634 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
635 ea_list->ea.value.data, ea_list->ea.value.length, 0);
639 if (ret == -1) {
640 #ifdef ENOTSUP
641 if (errno == ENOTSUP) {
642 return NT_STATUS_EAS_NOT_SUPPORTED;
644 #endif
645 return map_nt_error_from_unix(errno);
649 return NT_STATUS_OK;
651 /****************************************************************************
652 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
653 ****************************************************************************/
655 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
657 struct ea_list *ea_list_head = NULL;
658 size_t converted_size, offset = 0;
660 while (offset + 2 < data_size) {
661 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
662 unsigned int namelen = CVAL(pdata,offset);
664 offset++; /* Go past the namelen byte. */
666 /* integer wrap paranioa. */
667 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
668 (offset > data_size) || (namelen > data_size) ||
669 (offset + namelen >= data_size)) {
670 break;
672 /* Ensure the name is null terminated. */
673 if (pdata[offset + namelen] != '\0') {
674 return NULL;
676 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
677 &converted_size)) {
678 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
679 "failed: %s", strerror(errno)));
681 if (!eal->ea.name) {
682 return NULL;
685 offset += (namelen + 1); /* Go past the name + terminating zero. */
686 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
687 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
690 return ea_list_head;
693 /****************************************************************************
694 Read one EA list entry from the buffer.
695 ****************************************************************************/
697 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
699 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
700 uint16 val_len;
701 unsigned int namelen;
702 size_t converted_size;
704 if (!eal) {
705 return NULL;
708 if (data_size < 6) {
709 return NULL;
712 eal->ea.flags = CVAL(pdata,0);
713 namelen = CVAL(pdata,1);
714 val_len = SVAL(pdata,2);
716 if (4 + namelen + 1 + val_len > data_size) {
717 return NULL;
720 /* Ensure the name is null terminated. */
721 if (pdata[namelen + 4] != '\0') {
722 return NULL;
724 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
725 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
726 strerror(errno)));
728 if (!eal->ea.name) {
729 return NULL;
732 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
733 if (!eal->ea.value.data) {
734 return NULL;
737 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
739 /* Ensure we're null terminated just in case we print the value. */
740 eal->ea.value.data[val_len] = '\0';
741 /* But don't count the null. */
742 eal->ea.value.length--;
744 if (pbytes_used) {
745 *pbytes_used = 4 + namelen + 1 + val_len;
748 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
749 dump_data(10, eal->ea.value.data, eal->ea.value.length);
751 return eal;
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
760 struct ea_list *ea_list_head = NULL;
761 size_t offset = 0;
762 size_t bytes_used = 0;
764 while (offset < data_size) {
765 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
767 if (!eal) {
768 return NULL;
771 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
772 offset += bytes_used;
775 return ea_list_head;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list *ealist)
784 fstring dos_ea_name;
785 struct ea_list *listp;
786 size_t ret = 0;
788 for (listp = ealist; listp; listp = listp->next) {
789 push_ascii_fstring(dos_ea_name, listp->ea.name);
790 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
792 /* Add on 4 for total length. */
793 if (ret) {
794 ret += 4;
797 return ret;
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
808 struct ea_list *nlistp, *flistp;
810 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
811 for (flistp = file_list; flistp; flistp = flistp->next) {
812 if (strequal(nlistp->ea.name, flistp->ea.name)) {
813 break;
817 if (flistp) {
818 /* Copy the data from this entry. */
819 nlistp->ea.flags = flistp->ea.flags;
820 nlistp->ea.value = flistp->ea.value;
821 } else {
822 /* Null entry. */
823 nlistp->ea.flags = 0;
824 ZERO_STRUCT(nlistp->ea.value);
828 *total_ea_len = ea_list_size(name_list);
829 return name_list;
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct *conn,
840 struct smb_request *req,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 show_msg((char *)req->outbuf);
882 if (!srv_send_smb(sconn,
883 (char *)req->outbuf,
884 true, req->seqnum+1,
885 IS_CONN_ENCRYPTED(conn),
886 &req->pcd)) {
887 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
889 TALLOC_FREE(req->outbuf);
890 return;
893 /* When sending params and data ensure that both are nicely aligned */
894 /* Only do this alignment when there is also data to send - else
895 can cause NT redirector problems. */
897 if (((params_to_send % 4) != 0) && (data_to_send != 0))
898 data_alignment_offset = 4 - (params_to_send % 4);
900 /* Space is bufsize minus Netbios over TCP header minus SMB header */
901 /* The alignment_offset is to align the param bytes on an even byte
902 boundary. NT 4.0 Beta needs this to work correctly. */
904 useable_space = max_send - (smb_size
905 + 2 * 10 /* wct */
906 + alignment_offset
907 + data_alignment_offset);
909 if (useable_space < 0) {
910 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
911 "= %d!!!", useable_space));
912 exit_server_cleanly("send_trans2_replies: Not enough space");
915 while (params_to_send || data_to_send) {
916 /* Calculate whether we will totally or partially fill this packet */
918 total_sent_thistime = params_to_send + data_to_send;
920 /* We can never send more than useable_space */
922 * Note that 'useable_space' does not include the alignment offsets,
923 * but we must include the alignment offsets in the calculation of
924 * the length of the data we send over the wire, as the alignment offsets
925 * are sent here. Fix from Marc_Jacobsen@hp.com.
928 total_sent_thistime = MIN(total_sent_thistime, useable_space);
930 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
931 + data_alignment_offset);
933 /* Set total params and data to be sent */
934 SSVAL(req->outbuf,smb_tprcnt,paramsize);
935 SSVAL(req->outbuf,smb_tdrcnt,datasize);
937 /* Calculate how many parameters and data we can fit into
938 * this packet. Parameters get precedence
941 params_sent_thistime = MIN(params_to_send,useable_space);
942 data_sent_thistime = useable_space - params_sent_thistime;
943 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
945 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
947 /* smb_proff is the offset from the start of the SMB header to the
948 parameter bytes, however the first 4 bytes of outbuf are
949 the Netbios over TCP header. Thus use smb_base() to subtract
950 them from the calculation */
952 SSVAL(req->outbuf,smb_proff,
953 ((smb_buf(req->outbuf)+alignment_offset)
954 - smb_base(req->outbuf)));
956 if(params_sent_thistime == 0)
957 SSVAL(req->outbuf,smb_prdisp,0);
958 else
959 /* Absolute displacement of param bytes sent in this packet */
960 SSVAL(req->outbuf,smb_prdisp,pp - params);
962 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
963 if(data_sent_thistime == 0) {
964 SSVAL(req->outbuf,smb_droff,0);
965 SSVAL(req->outbuf,smb_drdisp, 0);
966 } else {
967 /* The offset of the data bytes is the offset of the
968 parameter bytes plus the number of parameters being sent this time */
969 SSVAL(req->outbuf, smb_droff,
970 ((smb_buf(req->outbuf)+alignment_offset)
971 - smb_base(req->outbuf))
972 + params_sent_thistime + data_alignment_offset);
973 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
976 /* Initialize the padding for alignment */
978 if (alignment_offset != 0) {
979 memset(smb_buf(req->outbuf), 0, alignment_offset);
982 /* Copy the param bytes into the packet */
984 if(params_sent_thistime) {
985 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
986 params_sent_thistime);
989 /* Copy in the data bytes */
990 if(data_sent_thistime) {
991 if (data_alignment_offset != 0) {
992 memset((smb_buf(req->outbuf)+alignment_offset+
993 params_sent_thistime), 0,
994 data_alignment_offset);
996 memcpy(smb_buf(req->outbuf)+alignment_offset
997 +params_sent_thistime+data_alignment_offset,
998 pd,data_sent_thistime);
1001 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1002 params_sent_thistime, data_sent_thistime, useable_space));
1003 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1004 params_to_send, data_to_send, paramsize, datasize));
1006 if (overflow) {
1007 error_packet_set((char *)req->outbuf,
1008 ERRDOS,ERRbufferoverflow,
1009 STATUS_BUFFER_OVERFLOW,
1010 __LINE__,__FILE__);
1013 /* Send the packet */
1014 show_msg((char *)req->outbuf);
1015 if (!srv_send_smb(sconn,
1016 (char *)req->outbuf,
1017 true, req->seqnum+1,
1018 IS_CONN_ENCRYPTED(conn),
1019 &req->pcd))
1020 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1022 TALLOC_FREE(req->outbuf);
1024 pp += params_sent_thistime;
1025 pd += data_sent_thistime;
1027 params_to_send -= params_sent_thistime;
1028 data_to_send -= data_sent_thistime;
1030 /* Sanity check */
1031 if(params_to_send < 0 || data_to_send < 0) {
1032 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1033 params_to_send, data_to_send));
1034 return;
1038 return;
1041 /****************************************************************************
1042 Reply to a TRANSACT2_OPEN.
1043 ****************************************************************************/
1045 static void call_trans2open(connection_struct *conn,
1046 struct smb_request *req,
1047 char **pparams, int total_params,
1048 char **ppdata, int total_data,
1049 unsigned int max_data_bytes)
1051 struct smb_filename *smb_fname = NULL;
1052 char *params = *pparams;
1053 char *pdata = *ppdata;
1054 int deny_mode;
1055 int32 open_attr;
1056 bool oplock_request;
1057 #if 0
1058 bool return_additional_info;
1059 int16 open_sattr;
1060 time_t open_time;
1061 #endif
1062 int open_ofun;
1063 uint32 open_size;
1064 char *pname;
1065 char *fname = NULL;
1066 off_t size=0;
1067 int fattr=0,mtime=0;
1068 SMB_INO_T inode = 0;
1069 int smb_action = 0;
1070 files_struct *fsp;
1071 struct ea_list *ea_list = NULL;
1072 uint16 flags = 0;
1073 NTSTATUS status;
1074 uint32 access_mask;
1075 uint32 share_mode;
1076 uint32 create_disposition;
1077 uint32 create_options = 0;
1078 uint32_t private_flags = 0;
1079 TALLOC_CTX *ctx = talloc_tos();
1082 * Ensure we have enough parameters to perform the operation.
1085 if (total_params < 29) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1090 flags = SVAL(params, 0);
1091 deny_mode = SVAL(params, 2);
1092 open_attr = SVAL(params,6);
1093 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1094 if (oplock_request) {
1095 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1098 #if 0
1099 return_additional_info = BITSETW(params,0);
1100 open_sattr = SVAL(params, 4);
1101 open_time = make_unix_date3(params+8);
1102 #endif
1103 open_ofun = SVAL(params,12);
1104 open_size = IVAL(params,14);
1105 pname = &params[28];
1107 if (IS_IPC(conn)) {
1108 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1109 goto out;
1112 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1113 total_params - 28, STR_TERMINATE,
1114 &status);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 goto out;
1120 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1121 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1122 (unsigned int)open_ofun, open_size));
1124 status = filename_convert(ctx,
1125 conn,
1126 req->flags2 & FLAGS2_DFS_PATHNAMES,
1127 fname,
1129 NULL,
1130 &smb_fname);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1133 reply_botherror(req,
1134 NT_STATUS_PATH_NOT_COVERED,
1135 ERRSRV, ERRbadpath);
1136 goto out;
1138 reply_nterror(req, status);
1139 goto out;
1142 if (open_ofun == 0) {
1143 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1144 goto out;
1147 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1148 open_ofun,
1149 &access_mask, &share_mode,
1150 &create_disposition,
1151 &create_options,
1152 &private_flags)) {
1153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1154 goto out;
1157 /* Any data in this call is an EA list. */
1158 if (total_data && (total_data != 4)) {
1159 if (total_data < 10) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 goto out;
1164 if (IVAL(pdata,0) > total_data) {
1165 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1166 IVAL(pdata,0), (unsigned int)total_data));
1167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1168 goto out;
1171 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1172 total_data - 4);
1173 if (!ea_list) {
1174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 goto out;
1178 if (!lp_ea_support(SNUM(conn))) {
1179 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1180 goto out;
1184 status = SMB_VFS_CREATE_FILE(
1185 conn, /* conn */
1186 req, /* req */
1187 0, /* root_dir_fid */
1188 smb_fname, /* fname */
1189 access_mask, /* access_mask */
1190 share_mode, /* share_access */
1191 create_disposition, /* create_disposition*/
1192 create_options, /* create_options */
1193 open_attr, /* file_attributes */
1194 oplock_request, /* oplock_request */
1195 open_size, /* allocation_size */
1196 private_flags,
1197 NULL, /* sd */
1198 ea_list, /* ea_list */
1199 &fsp, /* result */
1200 &smb_action); /* psbuf */
1202 if (!NT_STATUS_IS_OK(status)) {
1203 if (open_was_deferred(req->sconn, req->mid)) {
1204 /* We have re-scheduled this call. */
1205 goto out;
1207 reply_openerror(req, status);
1208 goto out;
1211 size = get_file_size_stat(&smb_fname->st);
1212 fattr = dos_mode(conn, smb_fname);
1213 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1214 inode = smb_fname->st.st_ex_ino;
1215 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1216 close_file(req, fsp, ERROR_CLOSE);
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 goto out;
1221 /* Realloc the size of parameters and data we will return */
1222 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1223 if(*pparams == NULL ) {
1224 reply_nterror(req, NT_STATUS_NO_MEMORY);
1225 goto out;
1227 params = *pparams;
1229 SSVAL(params,0,fsp->fnum);
1230 SSVAL(params,2,fattr);
1231 srv_put_dos_date2(params,4, mtime);
1232 SIVAL(params,8, (uint32)size);
1233 SSVAL(params,12,deny_mode);
1234 SSVAL(params,14,0); /* open_type - file or directory. */
1235 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1237 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1238 smb_action |= EXTENDED_OPLOCK_GRANTED;
1241 SSVAL(params,18,smb_action);
1244 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1246 SIVAL(params,20,inode);
1247 SSVAL(params,24,0); /* Padding. */
1248 if (flags & 8) {
1249 uint32 ea_size = estimate_ea_size(conn, fsp,
1250 smb_fname);
1251 SIVAL(params, 26, ea_size);
1252 } else {
1253 SIVAL(params, 26, 0);
1256 /* Send the required number of replies */
1257 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1258 out:
1259 TALLOC_FREE(smb_fname);
1262 /*********************************************************
1263 Routine to check if a given string matches exactly.
1264 as a special case a mask of "." does NOT match. That
1265 is required for correct wildcard semantics
1266 Case can be significant or not.
1267 **********************************************************/
1269 static bool exact_match(bool has_wild,
1270 bool case_sensitive,
1271 const char *str,
1272 const char *mask)
1274 if (mask[0] == '.' && mask[1] == 0) {
1275 return false;
1278 if (has_wild) {
1279 return false;
1282 if (case_sensitive) {
1283 return strcmp(str,mask)==0;
1284 } else {
1285 return strcasecmp_m(str,mask) == 0;
1289 /****************************************************************************
1290 Return the filetype for UNIX extensions.
1291 ****************************************************************************/
1293 static uint32 unix_filetype(mode_t mode)
1295 if(S_ISREG(mode))
1296 return UNIX_TYPE_FILE;
1297 else if(S_ISDIR(mode))
1298 return UNIX_TYPE_DIR;
1299 #ifdef S_ISLNK
1300 else if(S_ISLNK(mode))
1301 return UNIX_TYPE_SYMLINK;
1302 #endif
1303 #ifdef S_ISCHR
1304 else if(S_ISCHR(mode))
1305 return UNIX_TYPE_CHARDEV;
1306 #endif
1307 #ifdef S_ISBLK
1308 else if(S_ISBLK(mode))
1309 return UNIX_TYPE_BLKDEV;
1310 #endif
1311 #ifdef S_ISFIFO
1312 else if(S_ISFIFO(mode))
1313 return UNIX_TYPE_FIFO;
1314 #endif
1315 #ifdef S_ISSOCK
1316 else if(S_ISSOCK(mode))
1317 return UNIX_TYPE_SOCKET;
1318 #endif
1320 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1321 return UNIX_TYPE_UNKNOWN;
1324 /****************************************************************************
1325 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1326 ****************************************************************************/
1328 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1330 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1331 const SMB_STRUCT_STAT *psbuf,
1332 uint32 perms,
1333 enum perm_type ptype,
1334 mode_t *ret_perms)
1336 mode_t ret = 0;
1338 if (perms == SMB_MODE_NO_CHANGE) {
1339 if (!VALID_STAT(*psbuf)) {
1340 return NT_STATUS_INVALID_PARAMETER;
1341 } else {
1342 *ret_perms = psbuf->st_ex_mode;
1343 return NT_STATUS_OK;
1347 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1348 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1349 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1350 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1351 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1352 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1353 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1354 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1355 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1356 #ifdef S_ISVTX
1357 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1358 #endif
1359 #ifdef S_ISGID
1360 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1361 #endif
1362 #ifdef S_ISUID
1363 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1364 #endif
1366 switch (ptype) {
1367 case PERM_NEW_FILE:
1368 case PERM_EXISTING_FILE:
1369 /* Apply mode mask */
1370 ret &= lp_create_mask(SNUM(conn));
1371 /* Add in force bits */
1372 ret |= lp_force_create_mode(SNUM(conn));
1373 break;
1374 case PERM_NEW_DIR:
1375 case PERM_EXISTING_DIR:
1376 ret &= lp_dir_mask(SNUM(conn));
1377 /* Add in force bits */
1378 ret |= lp_force_dir_mode(SNUM(conn));
1379 break;
1382 *ret_perms = ret;
1383 return NT_STATUS_OK;
1386 /****************************************************************************
1387 Needed to show the msdfs symlinks as directories. Modifies psbuf
1388 to be a directory if it's a msdfs link.
1389 ****************************************************************************/
1391 static bool check_msdfs_link(connection_struct *conn,
1392 const char *pathname,
1393 SMB_STRUCT_STAT *psbuf)
1395 int saved_errno = errno;
1396 if(lp_host_msdfs() &&
1397 lp_msdfs_root(SNUM(conn)) &&
1398 is_msdfs_link(conn, pathname, psbuf)) {
1400 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1401 "as a directory\n",
1402 pathname));
1403 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1404 errno = saved_errno;
1405 return true;
1407 errno = saved_errno;
1408 return false;
1412 /****************************************************************************
1413 Get a level dependent lanman2 dir entry.
1414 ****************************************************************************/
1416 struct smbd_dirptr_lanman2_state {
1417 connection_struct *conn;
1418 uint32_t info_level;
1419 bool check_mangled_names;
1420 bool has_wild;
1421 bool got_exact_match;
1424 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1425 void *private_data,
1426 const char *dname,
1427 const char *mask,
1428 char **_fname)
1430 struct smbd_dirptr_lanman2_state *state =
1431 (struct smbd_dirptr_lanman2_state *)private_data;
1432 bool ok;
1433 char mangled_name[13]; /* mangled 8.3 name. */
1434 bool got_match;
1435 const char *fname;
1437 /* Mangle fname if it's an illegal name. */
1438 if (mangle_must_mangle(dname, state->conn->params)) {
1439 ok = name_to_8_3(dname, mangled_name,
1440 true, state->conn->params);
1441 if (!ok) {
1442 return false;
1444 fname = mangled_name;
1445 } else {
1446 fname = dname;
1449 got_match = exact_match(state->has_wild,
1450 state->conn->case_sensitive,
1451 fname, mask);
1452 state->got_exact_match = got_match;
1453 if (!got_match) {
1454 got_match = mask_match(fname, mask,
1455 state->conn->case_sensitive);
1458 if(!got_match && state->check_mangled_names &&
1459 !mangle_is_8_3(fname, false, state->conn->params)) {
1461 * It turns out that NT matches wildcards against
1462 * both long *and* short names. This may explain some
1463 * of the wildcard wierdness from old DOS clients
1464 * that some people have been seeing.... JRA.
1466 /* Force the mangling into 8.3. */
1467 ok = name_to_8_3(fname, mangled_name,
1468 false, state->conn->params);
1469 if (!ok) {
1470 return false;
1473 got_match = exact_match(state->has_wild,
1474 state->conn->case_sensitive,
1475 mangled_name, mask);
1476 state->got_exact_match = got_match;
1477 if (!got_match) {
1478 got_match = mask_match(mangled_name, mask,
1479 state->conn->case_sensitive);
1483 if (!got_match) {
1484 return false;
1487 *_fname = talloc_strdup(ctx, fname);
1488 if (*_fname == NULL) {
1489 return false;
1492 return true;
1495 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1496 void *private_data,
1497 struct smb_filename *smb_fname,
1498 uint32_t *_mode)
1500 struct smbd_dirptr_lanman2_state *state =
1501 (struct smbd_dirptr_lanman2_state *)private_data;
1502 bool ms_dfs_link = false;
1503 uint32_t mode = 0;
1505 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1506 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1507 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1508 "Couldn't lstat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname),
1510 strerror(errno)));
1511 return false;
1513 } else if (!VALID_STAT(smb_fname->st) &&
1514 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1515 /* Needed to show the msdfs symlinks as
1516 * directories */
1518 ms_dfs_link = check_msdfs_link(state->conn,
1519 smb_fname->base_name,
1520 &smb_fname->st);
1521 if (!ms_dfs_link) {
1522 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1523 "Couldn't stat [%s] (%s)\n",
1524 smb_fname_str_dbg(smb_fname),
1525 strerror(errno)));
1526 return false;
1530 if (ms_dfs_link) {
1531 mode = dos_mode_msdfs(state->conn, smb_fname);
1532 } else {
1533 mode = dos_mode(state->conn, smb_fname);
1536 *_mode = mode;
1537 return true;
1540 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1541 connection_struct *conn,
1542 uint16_t flags2,
1543 uint32_t info_level,
1544 struct ea_list *name_list,
1545 bool check_mangled_names,
1546 bool requires_resume_key,
1547 uint32_t mode,
1548 const char *fname,
1549 const struct smb_filename *smb_fname,
1550 int space_remaining,
1551 uint8_t align,
1552 bool do_pad,
1553 char *base_data,
1554 char **ppdata,
1555 char *end_data,
1556 bool *out_of_space,
1557 uint64_t *last_entry_off)
1559 char *p, *q, *pdata = *ppdata;
1560 uint32_t reskey=0;
1561 uint64_t file_size = 0;
1562 uint64_t allocation_size = 0;
1563 uint64_t file_index = 0;
1564 uint32_t len;
1565 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1566 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1567 char *nameptr;
1568 char *last_entry_ptr;
1569 bool was_8_3;
1570 int off;
1571 int pad = 0;
1573 *out_of_space = false;
1575 ZERO_STRUCT(mdate_ts);
1576 ZERO_STRUCT(adate_ts);
1577 ZERO_STRUCT(create_date_ts);
1578 ZERO_STRUCT(cdate_ts);
1580 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1581 file_size = get_file_size_stat(&smb_fname->st);
1583 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1585 file_index = get_FileIndex(conn, &smb_fname->st);
1587 mdate_ts = smb_fname->st.st_ex_mtime;
1588 adate_ts = smb_fname->st.st_ex_atime;
1589 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1590 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1592 if (lp_dos_filetime_resolution(SNUM(conn))) {
1593 dos_filetime_timespec(&create_date_ts);
1594 dos_filetime_timespec(&mdate_ts);
1595 dos_filetime_timespec(&adate_ts);
1596 dos_filetime_timespec(&cdate_ts);
1599 create_date = convert_timespec_to_time_t(create_date_ts);
1600 mdate = convert_timespec_to_time_t(mdate_ts);
1601 adate = convert_timespec_to_time_t(adate_ts);
1603 /* align the record */
1604 SMB_ASSERT(align >= 1);
1606 off = (int)PTR_DIFF(pdata, base_data);
1607 pad = (off + (align-1)) & ~(align-1);
1608 pad -= off;
1610 if (pad && pad > space_remaining) {
1611 *out_of_space = true;
1612 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1613 "for padding (wanted %u, had %d)\n",
1614 (unsigned int)pad,
1615 space_remaining ));
1616 return false; /* Not finished - just out of space */
1619 off += pad;
1620 /* initialize padding to 0 */
1621 if (pad) {
1622 memset(pdata, 0, pad);
1624 space_remaining -= pad;
1626 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1627 space_remaining ));
1629 pdata += pad;
1630 p = pdata;
1631 last_entry_ptr = p;
1633 pad = 0;
1634 off = 0;
1636 switch (info_level) {
1637 case SMB_FIND_INFO_STANDARD:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1639 if(requires_resume_key) {
1640 SIVAL(p,0,reskey);
1641 p += 4;
1643 srv_put_dos_date2(p,0,create_date);
1644 srv_put_dos_date2(p,4,adate);
1645 srv_put_dos_date2(p,8,mdate);
1646 SIVAL(p,12,(uint32)file_size);
1647 SIVAL(p,16,(uint32)allocation_size);
1648 SSVAL(p,20,mode);
1649 p += 23;
1650 nameptr = p;
1651 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1652 p += ucs2_align(base_data, p, 0);
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE);
1657 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 if (len > 2) {
1659 SCVAL(nameptr, -1, len - 2);
1660 } else {
1661 SCVAL(nameptr, -1, 0);
1663 } else {
1664 if (len > 1) {
1665 SCVAL(nameptr, -1, len - 1);
1666 } else {
1667 SCVAL(nameptr, -1, 0);
1670 p += len;
1671 break;
1673 case SMB_FIND_EA_SIZE:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1675 if (requires_resume_key) {
1676 SIVAL(p,0,reskey);
1677 p += 4;
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1684 SSVAL(p,20,mode);
1686 unsigned int ea_size = estimate_ea_size(conn, NULL,
1687 smb_fname);
1688 SIVAL(p,22,ea_size); /* Extended attributes */
1690 p += 27;
1691 nameptr = p - 1;
1692 len = srvstr_push(base_data, flags2,
1693 p, fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE | STR_NOALIGN);
1695 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1696 if (len > 2) {
1697 len -= 2;
1698 } else {
1699 len = 0;
1701 } else {
1702 if (len > 1) {
1703 len -= 1;
1704 } else {
1705 len = 0;
1708 SCVAL(nameptr,0,len);
1709 p += len;
1710 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1711 break;
1713 case SMB_FIND_EA_LIST:
1715 struct ea_list *file_list = NULL;
1716 size_t ea_len = 0;
1717 NTSTATUS status;
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1720 if (!name_list) {
1721 return false;
1723 if (requires_resume_key) {
1724 SIVAL(p,0,reskey);
1725 p += 4;
1727 srv_put_dos_date2(p,0,create_date);
1728 srv_put_dos_date2(p,4,adate);
1729 srv_put_dos_date2(p,8,mdate);
1730 SIVAL(p,12,(uint32)file_size);
1731 SIVAL(p,16,(uint32)allocation_size);
1732 SSVAL(p,20,mode);
1733 p += 22; /* p now points to the EA area. */
1735 status = get_ea_list_from_file(ctx, conn, NULL,
1736 smb_fname,
1737 &ea_len, &file_list);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 file_list = NULL;
1741 name_list = ea_list_union(name_list, file_list, &ea_len);
1743 /* We need to determine if this entry will fit in the space available. */
1744 /* Max string size is 255 bytes. */
1745 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1746 *out_of_space = true;
1747 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1748 "(wanted %u, had %d)\n",
1749 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1750 space_remaining ));
1751 return False; /* Not finished - just out of space */
1754 /* Push the ea_data followed by the name. */
1755 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1756 nameptr = p;
1757 len = srvstr_push(base_data, flags2,
1758 p + 1, fname, PTR_DIFF(end_data, p+1),
1759 STR_TERMINATE | STR_NOALIGN);
1760 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1761 if (len > 2) {
1762 len -= 2;
1763 } else {
1764 len = 0;
1766 } else {
1767 if (len > 1) {
1768 len -= 1;
1769 } else {
1770 len = 0;
1773 SCVAL(nameptr,0,len);
1774 p += len + 1;
1775 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1776 break;
1779 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1781 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1782 p += 4;
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,mode); p += 4;
1791 q = p; p += 4; /* q is placeholder for name length. */
1793 unsigned int ea_size = estimate_ea_size(conn, NULL,
1794 smb_fname);
1795 SIVAL(p,0,ea_size); /* Extended attributes */
1796 p += 4;
1798 /* Clear the short name buffer. This is
1799 * IMPORTANT as not doing so will trigger
1800 * a Win2k client bug. JRA.
1802 if (!was_8_3 && check_mangled_names) {
1803 char mangled_name[13]; /* mangled 8.3 name. */
1804 if (!name_to_8_3(fname,mangled_name,True,
1805 conn->params)) {
1806 /* Error - mangle failed ! */
1807 memset(mangled_name,'\0',12);
1809 mangled_name[12] = 0;
1810 len = srvstr_push(base_data, flags2,
1811 p+2, mangled_name, 24,
1812 STR_UPPER|STR_UNICODE);
1813 if (len < 24) {
1814 memset(p + 2 + len,'\0',24 - len);
1816 SSVAL(p, 0, len);
1817 } else {
1818 memset(p,'\0',26);
1820 p += 2 + 24;
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE_ASCII);
1824 SIVAL(q,0,len);
1825 p += len;
1827 len = PTR_DIFF(p, pdata);
1828 pad = (len + (align-1)) & ~(align-1);
1830 * offset to the next entry, the caller
1831 * will overwrite it for the last entry
1832 * that's why we always include the padding
1834 SIVAL(pdata,0,pad);
1836 * set padding to zero
1838 if (do_pad) {
1839 memset(p, 0, pad - len);
1840 p = pdata + pad;
1841 } else {
1842 p = pdata + len;
1844 break;
1846 case SMB_FIND_FILE_DIRECTORY_INFO:
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1848 p += 4;
1849 SIVAL(p,0,reskey); p += 4;
1850 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1851 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1852 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1853 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1854 SOFF_T(p,0,file_size); p += 8;
1855 SOFF_T(p,0,allocation_size); p += 8;
1856 SIVAL(p,0,mode); p += 4;
1857 len = srvstr_push(base_data, flags2,
1858 p + 4, fname, PTR_DIFF(end_data, p+4),
1859 STR_TERMINATE_ASCII);
1860 SIVAL(p,0,len);
1861 p += 4 + len;
1863 len = PTR_DIFF(p, pdata);
1864 pad = (len + (align-1)) & ~(align-1);
1866 * offset to the next entry, the caller
1867 * will overwrite it for the last entry
1868 * that's why we always include the padding
1870 SIVAL(pdata,0,pad);
1872 * set padding to zero
1874 if (do_pad) {
1875 memset(p, 0, pad - len);
1876 p = pdata + pad;
1877 } else {
1878 p = pdata + len;
1880 break;
1882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1883 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1884 p += 4;
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1888 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1889 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,mode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length. */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL,
1896 smb_fname);
1897 SIVAL(p,0,ea_size); /* Extended attributes */
1898 p +=4;
1900 len = srvstr_push(base_data, flags2, p,
1901 fname, PTR_DIFF(end_data, p),
1902 STR_TERMINATE_ASCII);
1903 SIVAL(q, 0, len);
1904 p += len;
1906 len = PTR_DIFF(p, pdata);
1907 pad = (len + (align-1)) & ~(align-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1913 SIVAL(pdata,0,pad);
1915 * set padding to zero
1917 if (do_pad) {
1918 memset(p, 0, pad - len);
1919 p = pdata + pad;
1920 } else {
1921 p = pdata + len;
1923 break;
1925 case SMB_FIND_FILE_NAMES_INFO:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1927 p += 4;
1928 SIVAL(p,0,reskey); p += 4;
1929 p += 4;
1930 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1931 acl on a dir (tridge) */
1932 len = srvstr_push(base_data, flags2, p,
1933 fname, PTR_DIFF(end_data, p),
1934 STR_TERMINATE_ASCII);
1935 SIVAL(p, -4, len);
1936 p += len;
1938 len = PTR_DIFF(p, pdata);
1939 pad = (len + (align-1)) & ~(align-1);
1941 * offset to the next entry, the caller
1942 * will overwrite it for the last entry
1943 * that's why we always include the padding
1945 SIVAL(pdata,0,pad);
1947 * set padding to zero
1949 if (do_pad) {
1950 memset(p, 0, pad - len);
1951 p = pdata + pad;
1952 } else {
1953 p = pdata + len;
1955 break;
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1958 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1959 p += 4;
1960 SIVAL(p,0,reskey); p += 4;
1961 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1962 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1963 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1964 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1965 SOFF_T(p,0,file_size); p += 8;
1966 SOFF_T(p,0,allocation_size); p += 8;
1967 SIVAL(p,0,mode); p += 4;
1968 q = p; p += 4; /* q is placeholder for name length. */
1970 unsigned int ea_size = estimate_ea_size(conn, NULL,
1971 smb_fname);
1972 SIVAL(p,0,ea_size); /* Extended attributes */
1973 p +=4;
1975 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1976 SBVAL(p,0,file_index); p += 8;
1977 len = srvstr_push(base_data, flags2, p,
1978 fname, PTR_DIFF(end_data, p),
1979 STR_TERMINATE_ASCII);
1980 SIVAL(q, 0, len);
1981 p += len;
1983 len = PTR_DIFF(p, pdata);
1984 pad = (len + (align-1)) & ~(align-1);
1986 * offset to the next entry, the caller
1987 * will overwrite it for the last entry
1988 * that's why we always include the padding
1990 SIVAL(pdata,0,pad);
1992 * set padding to zero
1994 if (do_pad) {
1995 memset(p, 0, pad - len);
1996 p = pdata + pad;
1997 } else {
1998 p = pdata + len;
2000 break;
2002 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 p += 4;
2006 SIVAL(p,0,reskey); p += 4;
2007 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2010 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2011 SOFF_T(p,0,file_size); p += 8;
2012 SOFF_T(p,0,allocation_size); p += 8;
2013 SIVAL(p,0,mode); p += 4;
2014 q = p; p += 4; /* q is placeholder for name length */
2016 unsigned int ea_size = estimate_ea_size(conn, NULL,
2017 smb_fname);
2018 SIVAL(p,0,ea_size); /* Extended attributes */
2019 p +=4;
2021 /* Clear the short name buffer. This is
2022 * IMPORTANT as not doing so will trigger
2023 * a Win2k client bug. JRA.
2025 if (!was_8_3 && check_mangled_names) {
2026 char mangled_name[13]; /* mangled 8.3 name. */
2027 if (!name_to_8_3(fname,mangled_name,True,
2028 conn->params)) {
2029 /* Error - mangle failed ! */
2030 memset(mangled_name,'\0',12);
2032 mangled_name[12] = 0;
2033 len = srvstr_push(base_data, flags2,
2034 p+2, mangled_name, 24,
2035 STR_UPPER|STR_UNICODE);
2036 SSVAL(p, 0, len);
2037 if (len < 24) {
2038 memset(p + 2 + len,'\0',24 - len);
2040 SSVAL(p, 0, len);
2041 } else {
2042 memset(p,'\0',26);
2044 p += 26;
2045 SSVAL(p,0,0); p += 2; /* Reserved ? */
2046 SBVAL(p,0,file_index); p += 8;
2047 len = srvstr_push(base_data, flags2, p,
2048 fname, PTR_DIFF(end_data, p),
2049 STR_TERMINATE_ASCII);
2050 SIVAL(q,0,len);
2051 p += len;
2053 len = PTR_DIFF(p, pdata);
2054 pad = (len + (align-1)) & ~(align-1);
2056 * offset to the next entry, the caller
2057 * will overwrite it for the last entry
2058 * that's why we always include the padding
2060 SIVAL(pdata,0,pad);
2062 * set padding to zero
2064 if (do_pad) {
2065 memset(p, 0, pad - len);
2066 p = pdata + pad;
2067 } else {
2068 p = pdata + len;
2070 break;
2072 /* CIFS UNIX Extension. */
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 p+= 4;
2077 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2079 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2081 if (info_level == SMB_FIND_FILE_UNIX) {
2082 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2083 p = store_file_unix_basic(conn, p,
2084 NULL, &smb_fname->st);
2085 len = srvstr_push(base_data, flags2, p,
2086 fname, PTR_DIFF(end_data, p),
2087 STR_TERMINATE);
2088 } else {
2089 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2090 p = store_file_unix_basic_info2(conn, p,
2091 NULL, &smb_fname->st);
2092 nameptr = p;
2093 p += 4;
2094 len = srvstr_push(base_data, flags2, p, fname,
2095 PTR_DIFF(end_data, p), 0);
2096 SIVAL(nameptr, 0, len);
2099 p += len;
2101 len = PTR_DIFF(p, pdata);
2102 pad = (len + (align-1)) & ~(align-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2108 SIVAL(pdata,0,pad);
2110 * set padding to zero
2112 if (do_pad) {
2113 memset(p, 0, pad - len);
2114 p = pdata + pad;
2115 } else {
2116 p = pdata + len;
2118 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2120 break;
2122 default:
2123 return false;
2126 if (PTR_DIFF(p,pdata) > space_remaining) {
2127 *out_of_space = true;
2128 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2129 "(wanted %u, had %d)\n",
2130 (unsigned int)PTR_DIFF(p,pdata),
2131 space_remaining ));
2132 return false; /* Not finished - just out of space */
2135 /* Setup the last entry pointer, as an offset from base_data */
2136 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2137 /* Advance the data pointer to the next slot */
2138 *ppdata = p;
2140 return true;
2143 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2144 connection_struct *conn,
2145 struct dptr_struct *dirptr,
2146 uint16 flags2,
2147 const char *path_mask,
2148 uint32 dirtype,
2149 int info_level,
2150 int requires_resume_key,
2151 bool dont_descend,
2152 bool ask_sharemode,
2153 uint8_t align,
2154 bool do_pad,
2155 char **ppdata,
2156 char *base_data,
2157 char *end_data,
2158 int space_remaining,
2159 bool *out_of_space,
2160 bool *got_exact_match,
2161 int *_last_entry_off,
2162 struct ea_list *name_list)
2164 const char *p;
2165 const char *mask = NULL;
2166 long prev_dirpos = 0;
2167 uint32_t mode = 0;
2168 char *fname = NULL;
2169 struct smb_filename *smb_fname = NULL;
2170 struct smbd_dirptr_lanman2_state state;
2171 bool ok;
2172 uint64_t last_entry_off = 0;
2174 ZERO_STRUCT(state);
2175 state.conn = conn;
2176 state.info_level = info_level;
2177 state.check_mangled_names = lp_manglednames(conn->params);
2178 state.has_wild = dptr_has_wild(dirptr);
2179 state.got_exact_match = false;
2181 *out_of_space = false;
2182 *got_exact_match = false;
2184 p = strrchr_m(path_mask,'/');
2185 if(p != NULL) {
2186 if(p[1] == '\0') {
2187 mask = "*.*";
2188 } else {
2189 mask = p+1;
2191 } else {
2192 mask = path_mask;
2195 ok = smbd_dirptr_get_entry(ctx,
2196 dirptr,
2197 mask,
2198 dirtype,
2199 dont_descend,
2200 ask_sharemode,
2201 smbd_dirptr_lanman2_match_fn,
2202 smbd_dirptr_lanman2_mode_fn,
2203 &state,
2204 &fname,
2205 &smb_fname,
2206 &mode,
2207 &prev_dirpos);
2208 if (!ok) {
2209 return false;
2212 *got_exact_match = state.got_exact_match;
2214 ok = smbd_marshall_dir_entry(ctx,
2215 conn,
2216 flags2,
2217 info_level,
2218 name_list,
2219 state.check_mangled_names,
2220 requires_resume_key,
2221 mode,
2222 fname,
2223 smb_fname,
2224 space_remaining,
2225 align,
2226 do_pad,
2227 base_data,
2228 ppdata,
2229 end_data,
2230 out_of_space,
2231 &last_entry_off);
2232 TALLOC_FREE(fname);
2233 TALLOC_FREE(smb_fname);
2234 if (*out_of_space) {
2235 dptr_SeekDir(dirptr, prev_dirpos);
2236 return false;
2238 if (!ok) {
2239 return false;
2242 *_last_entry_off = last_entry_off;
2243 return true;
2246 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2247 connection_struct *conn,
2248 struct dptr_struct *dirptr,
2249 uint16 flags2,
2250 const char *path_mask,
2251 uint32 dirtype,
2252 int info_level,
2253 bool requires_resume_key,
2254 bool dont_descend,
2255 bool ask_sharemode,
2256 char **ppdata,
2257 char *base_data,
2258 char *end_data,
2259 int space_remaining,
2260 bool *out_of_space,
2261 bool *got_exact_match,
2262 int *last_entry_off,
2263 struct ea_list *name_list)
2265 uint8_t align = 4;
2266 const bool do_pad = true;
2268 if (info_level >= 1 && info_level <= 3) {
2269 /* No alignment on earlier info levels. */
2270 align = 1;
2273 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2274 path_mask, dirtype, info_level,
2275 requires_resume_key, dont_descend, ask_sharemode,
2276 align, do_pad,
2277 ppdata, base_data, end_data,
2278 space_remaining,
2279 out_of_space, got_exact_match,
2280 last_entry_off, name_list);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDFIRST.
2285 ****************************************************************************/
2287 static void call_trans2findfirst(connection_struct *conn,
2288 struct smb_request *req,
2289 char **pparams, int total_params,
2290 char **ppdata, int total_data,
2291 unsigned int max_data_bytes)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2297 requested. */
2298 struct smb_filename *smb_dname = NULL;
2299 char *params = *pparams;
2300 char *pdata = *ppdata;
2301 char *data_end;
2302 uint32 dirtype;
2303 int maxentries;
2304 uint16 findfirst_flags;
2305 bool close_after_first;
2306 bool close_if_end;
2307 bool requires_resume_key;
2308 int info_level;
2309 char *directory = NULL;
2310 char *mask = NULL;
2311 char *p;
2312 int last_entry_off=0;
2313 int dptr_num = -1;
2314 int numentries = 0;
2315 int i;
2316 bool finished = False;
2317 bool dont_descend = False;
2318 bool out_of_space = False;
2319 int space_remaining;
2320 bool mask_contains_wcard = False;
2321 struct ea_list *ea_list = NULL;
2322 NTSTATUS ntstatus = NT_STATUS_OK;
2323 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX *ctx = talloc_tos();
2325 struct dptr_struct *dirptr = NULL;
2326 struct smbd_server_connection *sconn = req->sconn;
2327 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2328 bool backup_priv = false;
2330 if (total_params < 13) {
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 goto out;
2335 dirtype = SVAL(params,0);
2336 maxentries = SVAL(params,2);
2337 findfirst_flags = SVAL(params,4);
2338 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2339 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2340 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2341 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2342 security_token_has_privilege(get_current_nttok(conn),
2343 SEC_PRIV_BACKUP));
2345 info_level = SVAL(params,6);
2347 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2348 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2349 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2350 (int)backup_priv,
2351 info_level, max_data_bytes));
2353 if (!maxentries) {
2354 /* W2K3 seems to treat zero as 1. */
2355 maxentries = 1;
2358 switch (info_level) {
2359 case SMB_FIND_INFO_STANDARD:
2360 case SMB_FIND_EA_SIZE:
2361 case SMB_FIND_EA_LIST:
2362 case SMB_FIND_FILE_DIRECTORY_INFO:
2363 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2364 case SMB_FIND_FILE_NAMES_INFO:
2365 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2366 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2367 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2368 break;
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2371 /* Always use filesystem for UNIX mtime query. */
2372 ask_sharemode = false;
2373 if (!lp_unix_extensions()) {
2374 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2375 goto out;
2377 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2378 break;
2379 default:
2380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2381 goto out;
2384 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2385 params+12, total_params - 12,
2386 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2387 if (!NT_STATUS_IS_OK(ntstatus)) {
2388 reply_nterror(req, ntstatus);
2389 goto out;
2392 if (backup_priv) {
2393 become_root();
2394 ntstatus = filename_convert_with_privilege(ctx,
2395 conn,
2396 req,
2397 directory,
2398 ucf_flags,
2399 &mask_contains_wcard,
2400 &smb_dname);
2401 } else {
2402 ntstatus = filename_convert(ctx, conn,
2403 req->flags2 & FLAGS2_DFS_PATHNAMES,
2404 directory,
2405 ucf_flags,
2406 &mask_contains_wcard,
2407 &smb_dname);
2410 if (!NT_STATUS_IS_OK(ntstatus)) {
2411 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2412 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2413 ERRSRV, ERRbadpath);
2414 goto out;
2416 reply_nterror(req, ntstatus);
2417 goto out;
2420 mask = smb_dname->original_lcomp;
2422 directory = smb_dname->base_name;
2424 p = strrchr_m(directory,'/');
2425 if(p == NULL) {
2426 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2427 if((directory[0] == '.') && (directory[1] == '\0')) {
2428 mask = talloc_strdup(ctx,"*");
2429 if (!mask) {
2430 reply_nterror(req, NT_STATUS_NO_MEMORY);
2431 goto out;
2433 mask_contains_wcard = True;
2435 } else {
2436 *p = 0;
2439 if (p == NULL || p == directory) {
2440 /* Ensure we don't have a directory name of "". */
2441 directory = talloc_strdup(talloc_tos(), ".");
2442 if (!directory) {
2443 reply_nterror(req, NT_STATUS_NO_MEMORY);
2444 goto out;
2448 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2450 if (info_level == SMB_FIND_EA_LIST) {
2451 uint32 ea_size;
2453 if (total_data < 4) {
2454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2455 goto out;
2458 ea_size = IVAL(pdata,0);
2459 if (ea_size != total_data) {
2460 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2461 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2463 goto out;
2466 if (!lp_ea_support(SNUM(conn))) {
2467 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2468 goto out;
2471 /* Pull out the list of names. */
2472 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2473 if (!ea_list) {
2474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2475 goto out;
2479 *ppdata = (char *)SMB_REALLOC(
2480 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2481 if(*ppdata == NULL ) {
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 goto out;
2485 pdata = *ppdata;
2486 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2488 /* Realloc the params space */
2489 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2490 if (*pparams == NULL) {
2491 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 goto out;
2494 params = *pparams;
2496 /* Save the wildcard match and attribs we are using on this directory -
2497 needed as lanman2 assumes these are being saved between calls */
2499 ntstatus = dptr_create(conn,
2500 req,
2501 NULL, /* fsp */
2502 directory,
2503 False,
2504 True,
2505 req->smbpid,
2506 mask,
2507 mask_contains_wcard,
2508 dirtype,
2509 &dirptr);
2511 if (!NT_STATUS_IS_OK(ntstatus)) {
2512 reply_nterror(req, ntstatus);
2513 goto out;
2516 if (backup_priv) {
2517 /* Remember this in case we have
2518 to do a findnext. */
2519 dptr_set_priv(dirptr);
2522 dptr_num = dptr_dnum(dirptr);
2523 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2525 /* Initialize per TRANS2_FIND_FIRST operation data */
2526 dptr_init_search_op(dirptr);
2528 /* We don't need to check for VOL here as this is returned by
2529 a different TRANS2 call. */
2531 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2532 directory,lp_dontdescend(ctx, SNUM(conn))));
2533 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2534 dont_descend = True;
2536 p = pdata;
2537 space_remaining = max_data_bytes;
2538 out_of_space = False;
2540 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2541 bool got_exact_match = False;
2543 /* this is a heuristic to avoid seeking the dirptr except when
2544 absolutely necessary. It allows for a filename of about 40 chars */
2545 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2546 out_of_space = True;
2547 finished = False;
2548 } else {
2549 finished = !get_lanman2_dir_entry(ctx,
2550 conn,
2551 dirptr,
2552 req->flags2,
2553 mask,dirtype,info_level,
2554 requires_resume_key,dont_descend,
2555 ask_sharemode,
2556 &p,pdata,data_end,
2557 space_remaining, &out_of_space,
2558 &got_exact_match,
2559 &last_entry_off, ea_list);
2562 if (finished && out_of_space)
2563 finished = False;
2565 if (!finished && !out_of_space)
2566 numentries++;
2569 * As an optimisation if we know we aren't looking
2570 * for a wildcard name (ie. the name matches the wildcard exactly)
2571 * then we can finish on any (first) match.
2572 * This speeds up large directory searches. JRA.
2575 if(got_exact_match)
2576 finished = True;
2578 /* Ensure space_remaining never goes -ve. */
2579 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2580 space_remaining = 0;
2581 out_of_space = true;
2582 } else {
2583 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2587 /* Check if we can close the dirptr */
2588 if(close_after_first || (finished && close_if_end)) {
2589 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2590 dptr_close(sconn, &dptr_num);
2594 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2595 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2596 * the protocol level is less than NT1. Tested with smbclient. JRA.
2597 * This should fix the OS/2 client bug #2335.
2600 if(numentries == 0) {
2601 dptr_close(sconn, &dptr_num);
2602 if (get_Protocol() < PROTOCOL_NT1) {
2603 reply_force_doserror(req, ERRDOS, ERRnofiles);
2604 goto out;
2605 } else {
2606 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2607 ERRDOS, ERRbadfile);
2608 goto out;
2612 /* At this point pdata points to numentries directory entries. */
2614 /* Set up the return parameter block */
2615 SSVAL(params,0,dptr_num);
2616 SSVAL(params,2,numentries);
2617 SSVAL(params,4,finished);
2618 SSVAL(params,6,0); /* Never an EA error */
2619 SSVAL(params,8,last_entry_off);
2621 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2622 max_data_bytes);
2624 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2625 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2626 if (!directory) {
2627 reply_nterror(req, NT_STATUS_NO_MEMORY);
2631 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2632 smb_fn_name(req->cmd),
2633 mask, directory, dirtype, numentries ) );
2636 * Force a name mangle here to ensure that the
2637 * mask as an 8.3 name is top of the mangled cache.
2638 * The reasons for this are subtle. Don't remove
2639 * this code unless you know what you are doing
2640 * (see PR#13758). JRA.
2643 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2644 char mangled_name[13];
2645 name_to_8_3(mask, mangled_name, True, conn->params);
2647 out:
2649 if (backup_priv) {
2650 unbecome_root();
2653 TALLOC_FREE(smb_dname);
2654 return;
2657 /****************************************************************************
2658 Reply to a TRANS2_FINDNEXT.
2659 ****************************************************************************/
2661 static void call_trans2findnext(connection_struct *conn,
2662 struct smb_request *req,
2663 char **pparams, int total_params,
2664 char **ppdata, int total_data,
2665 unsigned int max_data_bytes)
2667 /* We must be careful here that we don't return more than the
2668 allowed number of data bytes. If this means returning fewer than
2669 maxentries then so be it. We assume that the redirector has
2670 enough room for the fixed number of parameter bytes it has
2671 requested. */
2672 char *params = *pparams;
2673 char *pdata = *ppdata;
2674 char *data_end;
2675 int dptr_num;
2676 int maxentries;
2677 uint16 info_level;
2678 uint32 resume_key;
2679 uint16 findnext_flags;
2680 bool close_after_request;
2681 bool close_if_end;
2682 bool requires_resume_key;
2683 bool continue_bit;
2684 bool mask_contains_wcard = False;
2685 char *resume_name = NULL;
2686 const char *mask = NULL;
2687 const char *directory = NULL;
2688 char *p = NULL;
2689 uint16 dirtype;
2690 int numentries = 0;
2691 int i, last_entry_off=0;
2692 bool finished = False;
2693 bool dont_descend = False;
2694 bool out_of_space = False;
2695 int space_remaining;
2696 struct ea_list *ea_list = NULL;
2697 NTSTATUS ntstatus = NT_STATUS_OK;
2698 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2699 TALLOC_CTX *ctx = talloc_tos();
2700 struct dptr_struct *dirptr;
2701 struct smbd_server_connection *sconn = req->sconn;
2702 bool backup_priv = false;
2704 if (total_params < 13) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2709 dptr_num = SVAL(params,0);
2710 maxentries = SVAL(params,2);
2711 info_level = SVAL(params,4);
2712 resume_key = IVAL(params,6);
2713 findnext_flags = SVAL(params,10);
2714 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2715 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2716 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2717 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2719 if (!continue_bit) {
2720 /* We only need resume_name if continue_bit is zero. */
2721 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2722 params+12,
2723 total_params - 12, STR_TERMINATE, &ntstatus,
2724 &mask_contains_wcard);
2725 if (!NT_STATUS_IS_OK(ntstatus)) {
2726 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2727 complain (it thinks we're asking for the directory above the shared
2728 path or an invalid name). Catch this as the resume name is only compared, never used in
2729 a file access. JRA. */
2730 srvstr_pull_talloc(ctx, params, req->flags2,
2731 &resume_name, params+12,
2732 total_params - 12,
2733 STR_TERMINATE);
2735 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2736 reply_nterror(req, ntstatus);
2737 return;
2742 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2743 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2744 resume_key = %d resume name = %s continue=%d level = %d\n",
2745 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2746 requires_resume_key, resume_key,
2747 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2749 if (!maxentries) {
2750 /* W2K3 seems to treat zero as 1. */
2751 maxentries = 1;
2754 switch (info_level) {
2755 case SMB_FIND_INFO_STANDARD:
2756 case SMB_FIND_EA_SIZE:
2757 case SMB_FIND_EA_LIST:
2758 case SMB_FIND_FILE_DIRECTORY_INFO:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2760 case SMB_FIND_FILE_NAMES_INFO:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2764 break;
2765 case SMB_FIND_FILE_UNIX:
2766 case SMB_FIND_FILE_UNIX_INFO2:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode = false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2771 return;
2773 break;
2774 default:
2775 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2776 return;
2779 if (info_level == SMB_FIND_EA_LIST) {
2780 uint32 ea_size;
2782 if (total_data < 4) {
2783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2784 return;
2787 ea_size = IVAL(pdata,0);
2788 if (ea_size != total_data) {
2789 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2790 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2792 return;
2795 if (!lp_ea_support(SNUM(conn))) {
2796 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2797 return;
2800 /* Pull out the list of names. */
2801 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2802 if (!ea_list) {
2803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2804 return;
2808 *ppdata = (char *)SMB_REALLOC(
2809 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2810 if(*ppdata == NULL) {
2811 reply_nterror(req, NT_STATUS_NO_MEMORY);
2812 return;
2815 pdata = *ppdata;
2816 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2818 /* Realloc the params space */
2819 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2820 if(*pparams == NULL ) {
2821 reply_nterror(req, NT_STATUS_NO_MEMORY);
2822 return;
2825 params = *pparams;
2827 /* Check that the dptr is valid */
2828 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2829 reply_nterror(req, STATUS_NO_MORE_FILES);
2830 return;
2833 directory = dptr_path(sconn, dptr_num);
2835 /* Get the wildcard mask from the dptr */
2836 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2837 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2838 reply_nterror(req, STATUS_NO_MORE_FILES);
2839 return;
2842 /* Get the attr mask from the dptr */
2843 dirtype = dptr_attr(sconn, dptr_num);
2845 backup_priv = dptr_get_priv(dirptr);
2847 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2848 "backup_priv = %d\n",
2849 dptr_num, mask, dirtype,
2850 (long)dirptr,
2851 dptr_TellDir(dirptr),
2852 (int)backup_priv));
2854 /* Initialize per TRANS2_FIND_NEXT operation data */
2855 dptr_init_search_op(dirptr);
2857 /* We don't need to check for VOL here as this is returned by
2858 a different TRANS2 call. */
2860 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2861 directory,lp_dontdescend(ctx, SNUM(conn))));
2862 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2863 dont_descend = True;
2865 p = pdata;
2866 space_remaining = max_data_bytes;
2867 out_of_space = False;
2869 if (backup_priv) {
2870 become_root();
2874 * Seek to the correct position. We no longer use the resume key but
2875 * depend on the last file name instead.
2878 if(!continue_bit && resume_name && *resume_name) {
2879 SMB_STRUCT_STAT st;
2881 long current_pos = 0;
2883 * Remember, name_to_8_3 is called by
2884 * get_lanman2_dir_entry(), so the resume name
2885 * could be mangled. Ensure we check the unmangled name.
2888 if (mangle_is_mangled(resume_name, conn->params)) {
2889 char *new_resume_name = NULL;
2890 mangle_lookup_name_from_8_3(ctx,
2891 resume_name,
2892 &new_resume_name,
2893 conn->params);
2894 if (new_resume_name) {
2895 resume_name = new_resume_name;
2900 * Fix for NT redirector problem triggered by resume key indexes
2901 * changing between directory scans. We now return a resume key of 0
2902 * and instead look for the filename to continue from (also given
2903 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2904 * findfirst/findnext (as is usual) then the directory pointer
2905 * should already be at the correct place.
2908 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2909 } /* end if resume_name && !continue_bit */
2911 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2912 bool got_exact_match = False;
2914 /* this is a heuristic to avoid seeking the dirptr except when
2915 absolutely necessary. It allows for a filename of about 40 chars */
2916 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2917 out_of_space = True;
2918 finished = False;
2919 } else {
2920 finished = !get_lanman2_dir_entry(ctx,
2921 conn,
2922 dirptr,
2923 req->flags2,
2924 mask,dirtype,info_level,
2925 requires_resume_key,dont_descend,
2926 ask_sharemode,
2927 &p,pdata,data_end,
2928 space_remaining, &out_of_space,
2929 &got_exact_match,
2930 &last_entry_off, ea_list);
2933 if (finished && out_of_space)
2934 finished = False;
2936 if (!finished && !out_of_space)
2937 numentries++;
2940 * As an optimisation if we know we aren't looking
2941 * for a wildcard name (ie. the name matches the wildcard exactly)
2942 * then we can finish on any (first) match.
2943 * This speeds up large directory searches. JRA.
2946 if(got_exact_match)
2947 finished = True;
2949 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2952 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2953 smb_fn_name(req->cmd),
2954 mask, directory, dirtype, numentries ) );
2956 /* Check if we can close the dirptr */
2957 if(close_after_request || (finished && close_if_end)) {
2958 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2959 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2962 if (backup_priv) {
2963 unbecome_root();
2966 /* Set up the return parameter block */
2967 SSVAL(params,0,numentries);
2968 SSVAL(params,2,finished);
2969 SSVAL(params,4,0); /* Never an EA error */
2970 SSVAL(params,6,last_entry_off);
2972 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2973 max_data_bytes);
2975 return;
2978 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2980 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2981 return objid;
2984 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2986 SMB_ASSERT(extended_info != NULL);
2988 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2989 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2990 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2991 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2992 #ifdef SAMBA_VERSION_REVISION
2993 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2994 #endif
2995 extended_info->samba_subversion = 0;
2996 #ifdef SAMBA_VERSION_RC_RELEASE
2997 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2998 #else
2999 #ifdef SAMBA_VERSION_PRE_RELEASE
3000 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3001 #endif
3002 #endif
3003 #ifdef SAMBA_VERSION_VENDOR_PATCH
3004 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3005 #endif
3006 extended_info->samba_gitcommitdate = 0;
3007 #ifdef SAMBA_VERSION_COMMIT_TIME
3008 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3009 #endif
3011 memset(extended_info->samba_version_string, 0,
3012 sizeof(extended_info->samba_version_string));
3014 snprintf (extended_info->samba_version_string,
3015 sizeof(extended_info->samba_version_string),
3016 "%s", samba_version_string());
3019 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3020 TALLOC_CTX *mem_ctx,
3021 uint16_t info_level,
3022 uint16_t flags2,
3023 unsigned int max_data_bytes,
3024 struct smb_filename *fname,
3025 char **ppdata,
3026 int *ret_data_len)
3028 char *pdata, *end_data;
3029 int data_len = 0, len;
3030 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3031 int snum = SNUM(conn);
3032 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3033 char *filename = NULL;
3034 uint32 additional_flags = 0;
3035 struct smb_filename smb_fname;
3036 SMB_STRUCT_STAT st;
3038 if (fname == NULL || fname->base_name == NULL) {
3039 filename = ".";
3040 } else {
3041 filename = fname->base_name;
3044 if (IS_IPC(conn)) {
3045 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3046 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3047 "info level (0x%x) on IPC$.\n",
3048 (unsigned int)info_level));
3049 return NT_STATUS_ACCESS_DENIED;
3053 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3055 ZERO_STRUCT(smb_fname);
3056 smb_fname.base_name = discard_const_p(char, filename);
3058 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3059 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3060 return map_nt_error_from_unix(errno);
3063 st = smb_fname.st;
3065 *ppdata = (char *)SMB_REALLOC(
3066 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3067 if (*ppdata == NULL) {
3068 return NT_STATUS_NO_MEMORY;
3071 pdata = *ppdata;
3072 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3073 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3075 switch (info_level) {
3076 case SMB_INFO_ALLOCATION:
3078 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3079 data_len = 18;
3080 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3081 return map_nt_error_from_unix(errno);
3084 block_size = lp_block_size(snum);
3085 if (bsize < block_size) {
3086 uint64_t factor = block_size/bsize;
3087 bsize = block_size;
3088 dsize /= factor;
3089 dfree /= factor;
3091 if (bsize > block_size) {
3092 uint64_t factor = bsize/block_size;
3093 bsize = block_size;
3094 dsize *= factor;
3095 dfree *= factor;
3097 bytes_per_sector = 512;
3098 sectors_per_unit = bsize/bytes_per_sector;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3102 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3104 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3105 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3106 SIVAL(pdata,l1_cUnit,dsize);
3107 SIVAL(pdata,l1_cUnitAvail,dfree);
3108 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3109 break;
3112 case SMB_INFO_VOLUME:
3113 /* Return volume name */
3115 * Add volume serial number - hash of a combination of
3116 * the called hostname and the service name.
3118 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3120 * Win2k3 and previous mess this up by sending a name length
3121 * one byte short. I believe only older clients (OS/2 Win9x) use
3122 * this call so try fixing this by adding a terminating null to
3123 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3125 len = srvstr_push(
3126 pdata, flags2,
3127 pdata+l2_vol_szVolLabel, vname,
3128 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3129 STR_NOALIGN|STR_TERMINATE);
3130 SCVAL(pdata,l2_vol_cch,len);
3131 data_len = l2_vol_szVolLabel + len;
3132 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3133 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3134 len, vname));
3135 break;
3137 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3138 case SMB_FS_ATTRIBUTE_INFORMATION:
3140 additional_flags = 0;
3141 #if defined(HAVE_SYS_QUOTAS)
3142 additional_flags |= FILE_VOLUME_QUOTAS;
3143 #endif
3145 if(lp_nt_acl_support(SNUM(conn))) {
3146 additional_flags |= FILE_PERSISTENT_ACLS;
3149 /* Capabilities are filled in at connection time through STATVFS call */
3150 additional_flags |= conn->fs_capabilities;
3151 additional_flags |= lp_parm_int(conn->params->service,
3152 "share", "fake_fscaps",
3155 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3156 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3157 additional_flags); /* FS ATTRIBUTES */
3159 SIVAL(pdata,4,255); /* Max filename component length */
3160 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3161 and will think we can't do long filenames */
3162 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3163 PTR_DIFF(end_data, pdata+12),
3164 STR_UNICODE);
3165 SIVAL(pdata,8,len);
3166 data_len = 12 + len;
3167 break;
3169 case SMB_QUERY_FS_LABEL_INFO:
3170 case SMB_FS_LABEL_INFORMATION:
3171 len = srvstr_push(pdata, flags2, pdata+4, vname,
3172 PTR_DIFF(end_data, pdata+4), 0);
3173 data_len = 4 + len;
3174 SIVAL(pdata,0,len);
3175 break;
3177 case SMB_QUERY_FS_VOLUME_INFO:
3178 case SMB_FS_VOLUME_INFORMATION:
3181 * Add volume serial number - hash of a combination of
3182 * the called hostname and the service name.
3184 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3185 (str_checksum(get_local_machine_name())<<16));
3187 /* Max label len is 32 characters. */
3188 len = srvstr_push(pdata, flags2, pdata+18, vname,
3189 PTR_DIFF(end_data, pdata+18),
3190 STR_UNICODE);
3191 SIVAL(pdata,12,len);
3192 data_len = 18+len;
3194 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3195 (int)strlen(vname),vname,
3196 lp_servicename(talloc_tos(), snum)));
3197 break;
3199 case SMB_QUERY_FS_SIZE_INFO:
3200 case SMB_FS_SIZE_INFORMATION:
3202 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3203 data_len = 24;
3204 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3205 return map_nt_error_from_unix(errno);
3207 block_size = lp_block_size(snum);
3208 if (bsize < block_size) {
3209 uint64_t factor = block_size/bsize;
3210 bsize = block_size;
3211 dsize /= factor;
3212 dfree /= factor;
3214 if (bsize > block_size) {
3215 uint64_t factor = bsize/block_size;
3216 bsize = block_size;
3217 dsize *= factor;
3218 dfree *= factor;
3220 bytes_per_sector = 512;
3221 sectors_per_unit = bsize/bytes_per_sector;
3222 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3224 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3225 SBIG_UINT(pdata,0,dsize);
3226 SBIG_UINT(pdata,8,dfree);
3227 SIVAL(pdata,16,sectors_per_unit);
3228 SIVAL(pdata,20,bytes_per_sector);
3229 break;
3232 case SMB_FS_FULL_SIZE_INFORMATION:
3234 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3235 data_len = 32;
3236 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3237 return map_nt_error_from_unix(errno);
3239 block_size = lp_block_size(snum);
3240 if (bsize < block_size) {
3241 uint64_t factor = block_size/bsize;
3242 bsize = block_size;
3243 dsize /= factor;
3244 dfree /= factor;
3246 if (bsize > block_size) {
3247 uint64_t factor = bsize/block_size;
3248 bsize = block_size;
3249 dsize *= factor;
3250 dfree *= factor;
3252 bytes_per_sector = 512;
3253 sectors_per_unit = bsize/bytes_per_sector;
3254 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3255 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3256 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3257 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3258 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3259 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3260 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3261 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3262 break;
3265 case SMB_QUERY_FS_DEVICE_INFO:
3266 case SMB_FS_DEVICE_INFORMATION:
3268 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3270 if (!CAN_WRITE(conn)) {
3271 characteristics |= FILE_READ_ONLY_DEVICE;
3273 data_len = 8;
3274 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3275 SIVAL(pdata,4,characteristics);
3276 break;
3279 #ifdef HAVE_SYS_QUOTAS
3280 case SMB_FS_QUOTA_INFORMATION:
3282 * what we have to send --metze:
3284 * Unknown1: 24 NULL bytes
3285 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3286 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3287 * Quota Flags: 2 byte :
3288 * Unknown3: 6 NULL bytes
3290 * 48 bytes total
3292 * details for Quota Flags:
3294 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3295 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3296 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3297 * 0x0001 Enable Quotas: enable quota for this fs
3301 /* we need to fake up a fsp here,
3302 * because its not send in this call
3304 files_struct fsp;
3305 SMB_NTQUOTA_STRUCT quotas;
3307 ZERO_STRUCT(fsp);
3308 ZERO_STRUCT(quotas);
3310 fsp.conn = conn;
3311 fsp.fnum = FNUM_FIELD_INVALID;
3313 /* access check */
3314 if (get_current_uid(conn) != 0) {
3315 DEBUG(0,("set_user_quota: access_denied "
3316 "service [%s] user [%s]\n",
3317 lp_servicename(talloc_tos(), SNUM(conn)),
3318 conn->session_info->unix_info->unix_name));
3319 return NT_STATUS_ACCESS_DENIED;
3322 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3323 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3324 return map_nt_error_from_unix(errno);
3327 data_len = 48;
3329 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3330 lp_servicename(talloc_tos(), SNUM(conn))));
3332 /* Unknown1 24 NULL bytes*/
3333 SBIG_UINT(pdata,0,(uint64_t)0);
3334 SBIG_UINT(pdata,8,(uint64_t)0);
3335 SBIG_UINT(pdata,16,(uint64_t)0);
3337 /* Default Soft Quota 8 bytes */
3338 SBIG_UINT(pdata,24,quotas.softlim);
3340 /* Default Hard Quota 8 bytes */
3341 SBIG_UINT(pdata,32,quotas.hardlim);
3343 /* Quota flag 2 bytes */
3344 SSVAL(pdata,40,quotas.qflags);
3346 /* Unknown3 6 NULL bytes */
3347 SSVAL(pdata,42,0);
3348 SIVAL(pdata,44,0);
3350 break;
3352 #endif /* HAVE_SYS_QUOTAS */
3353 case SMB_FS_OBJECTID_INFORMATION:
3355 unsigned char objid[16];
3356 struct smb_extended_info extended_info;
3357 memcpy(pdata,create_volume_objectid(conn, objid),16);
3358 samba_extended_info_version (&extended_info);
3359 SIVAL(pdata,16,extended_info.samba_magic);
3360 SIVAL(pdata,20,extended_info.samba_version);
3361 SIVAL(pdata,24,extended_info.samba_subversion);
3362 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3363 memcpy(pdata+36,extended_info.samba_version_string,28);
3364 data_len = 64;
3365 break;
3369 * Query the version and capabilities of the CIFS UNIX extensions
3370 * in use.
3373 case SMB_QUERY_CIFS_UNIX_INFO:
3375 bool large_write = lp_min_receive_file_size() &&
3376 !srv_is_signing_active(conn->sconn);
3377 bool large_read = !srv_is_signing_active(conn->sconn);
3378 int encrypt_caps = 0;
3380 if (!lp_unix_extensions()) {
3381 return NT_STATUS_INVALID_LEVEL;
3384 switch (conn->encrypt_level) {
3385 case SMB_SIGNING_OFF:
3386 encrypt_caps = 0;
3387 break;
3388 case SMB_SIGNING_IF_REQUIRED:
3389 case SMB_SIGNING_DEFAULT:
3390 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3391 break;
3392 case SMB_SIGNING_REQUIRED:
3393 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3394 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3395 large_write = false;
3396 large_read = false;
3397 break;
3400 data_len = 12;
3401 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3402 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3404 /* We have POSIX ACLs, pathname, encryption,
3405 * large read/write, and locking capability. */
3407 SBIG_UINT(pdata,4,((uint64_t)(
3408 CIFS_UNIX_POSIX_ACLS_CAP|
3409 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3410 CIFS_UNIX_FCNTL_LOCKS_CAP|
3411 CIFS_UNIX_EXTATTR_CAP|
3412 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3413 encrypt_caps|
3414 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3415 (large_write ?
3416 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3417 break;
3420 case SMB_QUERY_POSIX_FS_INFO:
3422 int rc;
3423 vfs_statvfs_struct svfs;
3425 if (!lp_unix_extensions()) {
3426 return NT_STATUS_INVALID_LEVEL;
3429 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3431 if (!rc) {
3432 data_len = 56;
3433 SIVAL(pdata,0,svfs.OptimalTransferSize);
3434 SIVAL(pdata,4,svfs.BlockSize);
3435 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3436 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3437 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3438 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3439 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3440 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3441 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3442 #ifdef EOPNOTSUPP
3443 } else if (rc == EOPNOTSUPP) {
3444 return NT_STATUS_INVALID_LEVEL;
3445 #endif /* EOPNOTSUPP */
3446 } else {
3447 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3448 return NT_STATUS_DOS(ERRSRV, ERRerror);
3450 break;
3453 case SMB_QUERY_POSIX_WHOAMI:
3455 uint32_t flags = 0;
3456 uint32_t sid_bytes;
3457 int i;
3459 if (!lp_unix_extensions()) {
3460 return NT_STATUS_INVALID_LEVEL;
3463 if (max_data_bytes < 40) {
3464 return NT_STATUS_BUFFER_TOO_SMALL;
3467 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3468 flags |= SMB_WHOAMI_GUEST;
3471 /* NOTE: 8 bytes for UID/GID, irrespective of native
3472 * platform size. This matches
3473 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3475 data_len = 4 /* flags */
3476 + 4 /* flag mask */
3477 + 8 /* uid */
3478 + 8 /* gid */
3479 + 4 /* ngroups */
3480 + 4 /* num_sids */
3481 + 4 /* SID bytes */
3482 + 4 /* pad/reserved */
3483 + (conn->session_info->unix_token->ngroups * 8)
3484 /* groups list */
3485 + (conn->session_info->security_token->num_sids *
3486 SID_MAX_SIZE)
3487 /* SID list */;
3489 SIVAL(pdata, 0, flags);
3490 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3491 SBIG_UINT(pdata, 8,
3492 (uint64_t)conn->session_info->unix_token->uid);
3493 SBIG_UINT(pdata, 16,
3494 (uint64_t)conn->session_info->unix_token->gid);
3497 if (data_len >= max_data_bytes) {
3498 /* Potential overflow, skip the GIDs and SIDs. */
3500 SIVAL(pdata, 24, 0); /* num_groups */
3501 SIVAL(pdata, 28, 0); /* num_sids */
3502 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3503 SIVAL(pdata, 36, 0); /* reserved */
3505 data_len = 40;
3506 break;
3509 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3510 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3512 /* We walk the SID list twice, but this call is fairly
3513 * infrequent, and I don't expect that it's performance
3514 * sensitive -- jpeach
3516 for (i = 0, sid_bytes = 0;
3517 i < conn->session_info->security_token->num_sids; ++i) {
3518 sid_bytes += ndr_size_dom_sid(
3519 &conn->session_info->security_token->sids[i],
3523 /* SID list byte count */
3524 SIVAL(pdata, 32, sid_bytes);
3526 /* 4 bytes pad/reserved - must be zero */
3527 SIVAL(pdata, 36, 0);
3528 data_len = 40;
3530 /* GID list */
3531 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3532 SBIG_UINT(pdata, data_len,
3533 (uint64_t)conn->session_info->unix_token->groups[i]);
3534 data_len += 8;
3537 /* SID list */
3538 for (i = 0;